This commit enables arbitrary instrumentation points at the last instruction
[dyninst.git] / dyninstAPI / src / inst-sparc-solaris.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: inst-sparc-solaris.C,v 1.124 2003/03/13 17:00:14 jodom Exp $
43
44 #include "dyninstAPI/src/inst-sparc.h"
45 #include "dyninstAPI/src/instPoint.h"
46 #include "common/h/debugOstream.h"
47
48 // Needed for function relocation
49 #include "dyninstAPI/src/func-reloc.h"
50
51 #include <sys/utsname.h>
52 #include <stdlib.h>
53 #include <strstream.h>
54
55 extern bool relocateFunction(process *proc, instPoint *&location);
56 extern bool branchInsideRange(instruction insn, Address branchAddress, 
57                               Address firstAddress, Address lastAddress); 
58 extern instPoint* find_overlap(pdvector<instPoint*> v, Address targetAddress);
59 extern void sorted_ips_vector(pdvector<instPoint*>&fill_in);
60
61 /****************************************************************************/
62 /****************************************************************************/
63 /****************************************************************************/
64
65
66 void AstNode::sysFlag(instPoint *location)
67 {
68     if (location -> ipType == functionEntry) {
69         astFlag = true;
70     } else if (location->ipType == functionExit) {
71         astFlag = location->hasNoStackFrame();
72     } else {
73         astFlag = false;
74     }
75
76     if (loperand)
77         loperand->sysFlag(location);
78     if (roperand)
79         roperand->sysFlag(location); 
80
81     for (unsigned u = 0; u < operands.size(); u++) {
82         operands[u]->sysFlag(location);
83     }
84 }
85
86 /****************************************************************************/
87 /****************************************************************************/
88 /****************************************************************************/
89
90 // Determine if the called function is a "library" function or a "user" 
91 // function. This cannot be done until all of the functions have been 
92 // seen, verified, and classified.
93 void pd_Function::checkCallPoints() {
94   instPoint *p;
95   Address loc_addr;
96
97   //cerr << "pd_Function:: checkCallPoints called, *this = " << *this;
98
99   pdvector<instPoint*> non_lib;
100
101   for (unsigned i=0; i<calls.size(); ++i) {
102     /* check to see where we are calling */
103     p = calls[i];
104     assert(p);
105
106     if (isInsnType(p->firstInstruction, CALLmask, CALLmatch)) {
107
108       loc_addr = p->addr + (p->firstInstruction.call.disp30 << 2);
109       pd_Function *pdf = (file_->exec())->findFuncByAddr(loc_addr);
110
111       if (pdf) {
112         p->callee = pdf;
113         non_lib.push_back(p);
114
115       } else if(!pdf){
116
117            if((loc_addr < getAddress(0))||(loc_addr > (getAddress(0)+size()))){
118
119                 p->callIndirect = true;
120                 p->callee = NULL; 
121                 non_lib.push_back(p);
122            }
123            else {
124
125                delete p;
126            }
127       } 
128     } else {
129
130       // Indirect call -- be conservative, assume it is a call to 
131       // an unnamed user function
132       assert(!p->callee); assert(p->callIndirect);
133       p->callee = NULL;
134       non_lib.push_back(p);
135     }
136   }
137   calls = non_lib;
138 }
139
140 /****************************************************************************/
141 /****************************************************************************/
142 /****************************************************************************/
143
144 // Add the instPoint 'point' to the array of call instPoints
145
146 // TODO we cannot find the called function by address at this point in time
147 // because the called function may not have been seen.
148 // reloc_info is 0 if the function is not currently being relocated
149 // Note that this may be called even when instr is NOT a CAlL inst, e.g.
150 //  in the case of a jmp instruction where paradynd/dyninstAPI knows
151 //  (really guesses) that control flow will return to the point following
152 //  the jmp, or wants
153 //  to mark the jmp as a call to preserve its logical structure of 
154 //  synchronous call + return (which is violated by tail-call optimization -
155 //  including a function (w/o stack frame) which ends w/ jmp, nop....
156 void pd_Function::addCallPoint(const instruction instr, 
157                                   unsigned &callId,
158                                   relocatedFuncInfo *reloc_info,
159                                   instPoint *&point,
160                                   const instPoint *&location)
161 {
162  
163 #ifdef DEBUG_CALL_POINTS
164     cerr << "pd_Function::addCallPoint called " << endl;
165     cerr << " this " << *this << endl;
166     cerr << " adr = " << adr << endl;
167     cerr << " relocatable_ = " << relocatable_ << endl;
168     cerr << " reloc_info = " << reloc_info << endl;
169 #endif
170
171     if (!isInsnType(instr, CALLmask, CALLmatch)) {
172       point->callIndirect = true;
173       point->callee = NULL;
174     } else{
175       point->callIndirect = false;
176     }
177
178     if (relocatable_) {
179
180         if (!reloc_info) {
181             calls.push_back(point);
182             calls[callId] -> instId = callId; 
183             callId++;
184
185         } else {
186
187 #ifdef DEBUG_CALL_POINTS
188             cerr << " *this = " << *this;
189             cerr << " callId = " << callId;
190             cerr << " (u_int)callId = " << (u_int)callId;
191             cerr << " calls.size() = " << calls.size() << endl;
192             cerr << " calls = " << endl;
193             for(unsigned un=0;un<calls.size();un++) {
194                 cerr << calls[un] << " , ";
195             }
196             cerr << endl;
197 #endif
198
199             assert((callId) < calls.size());
200           
201             if(location && (calls[callId] == location)) { 
202                 assert(calls[callId]->instId  == location->instId);
203                 location = point; 
204             } 
205            
206             point->instId = callId++;
207             reloc_info->addFuncCall(point);
208         }
209
210     } else {
211
212         if (!reloc_info) {
213             calls.push_back(point);
214         } else {
215             reloc_info->addFuncCall(point);
216         }
217     }
218 }
219
220 /****************************************************************************/
221 /****************************************************************************/
222 /****************************************************************************/
223
224 /*
225  * Given an instruction, relocate it to a new address, patching up
226  *   any relative addressing that is present.
227  * 
228  */
229 void relocateInstruction(instruction*& insn, Address origAddr, 
230                          Address& targetAddr, process *proc)
231 {
232     long long newLongOffset = 0;
233
234     // If the instruction is a CALL instruction, calculate the new
235     // offset
236     if (isInsnType(*insn, CALLmask, CALLmatch)) {
237     
238       newLongOffset = origAddr;
239       newLongOffset -= targetAddr;
240       newLongOffset += (insn->call.disp30 << 2);
241
242       insn->call.disp30 = (int)(newLongOffset >> 2);
243     
244     } else if (isInsnType(*insn, BRNCHmask, BRNCHmatch)||
245                isInsnType(*insn, FBRNCHmask, FBRNCHmatch)) {
246
247         // If the instruction is a Branch instruction, calculate the 
248         // new offset. If the new offset is out of reach after the 
249         // instruction is moved to the base Trampoline, we would do
250         // the following:
251         //    b  address  ......    address: save
252         //                                   call new_offset             
253         //                                   restore 
254         newLongOffset = origAddr;
255         newLongOffset -= targetAddr;
256         newLongOffset +=  (insn->branch.disp22 << 2);
257
258         // if the branch is too far, then allocate more space in inferior
259         // heap for a call instruction to branch target.  The base tramp 
260         // will branch to this new inferior heap code, which will call the
261         // target of the branch
262
263         if ((newLongOffset < (long long)(-0x7fffffff-1)) ||
264             (newLongOffset > (long long)0x7fffffff) ||
265             !offsetWithinRangeOfBranchInsn((int)newLongOffset)){
266
267             /** we need to check whether the new allocated space is **/
268             /** in the range of 1 branch instruction from reloacted inst **/
269
270             unsigned ret = proc->inferiorMalloc(3*sizeof(instruction), textHeap,
271                                            targetAddr);
272             assert(ret);
273
274             int old_offset = insn->branch.disp22 << 2;
275
276             long long assertCheck = ret;
277             assertCheck -= targetAddr;
278             assertCheck = assertCheck >> 2;
279
280             /** will it really fit to branch offset **/
281             if ((assertCheck < (long long)(-0x1FFFFF-1)) ||
282                 (assertCheck > (long long)0x1FFFFF))
283                         assert( 0 && "We could not create nearby space");
284
285
286             insn->branch.disp22  = (int)(assertCheck);
287
288             instruction insnPlus[3];
289             genImmInsn(insnPlus, SAVEop3, REG_SPTR, -112, REG_SPTR);
290             generateCallInsn(insnPlus+1, ret+sizeof(instruction), 
291                              origAddr+old_offset);
292             genSimpleInsn(insnPlus+2, RESTOREop3, 0, 0, 0); 
293             proc->writeDataSpace((caddr_t)ret, sizeof(insnPlus), 
294                          (caddr_t) insnPlus);
295         } else {
296             insn->branch.disp22 = (int)(newLongOffset >> 2);
297         }
298     } else if (isInsnType(*insn, TRAPmask, TRAPmatch)) {
299         // There should be no probelm for moving trap instruction
300         // logLine("attempt to relocate trap\n");
301     } 
302     /* The rest of the instructions should be fine as is */
303 }
304
305 /****************************************************************************/
306 /****************************************************************************/
307 /****************************************************************************/
308
309 void generate_base_tramp_recursive_guard_code( process & p,
310                                                instruction * code,
311                                                Address base_addr,
312                                                NonRecursiveTrampTemplate & templ )
313 {
314   /* prepare guard flag memory, if needed */
315   Address guard_flag_address = p.trampGuardAddr();
316   
317   instruction * curr_instr;
318   Address curr_addr;
319
320   /* Assignments: L0 holds the tramp guard addr, L1 holds the loaded value
321      and L2 holds the compare/set to value. Oh, and L3 has the shifted POS
322      for MT calcs
323   */
324
325   /* fill the 'guard on' pre-instruction instrumentation */
326   curr_instr = code + templ.guardOnPre_beginOffset / sizeof( instruction );
327   curr_addr = base_addr + templ.guardOnPre_beginOffset;
328   generateSetHi( curr_instr, guard_flag_address, REG_L(0) );
329   curr_instr++; curr_addr += sizeof( instruction );
330   if (p.multithread_capable()) {
331     int shift_val;
332     isPowerOf2(sizeof(unsigned), shift_val);
333     generateLShift(curr_instr, REG_MT_POS, (Register)shift_val, REG_L(3));
334     curr_instr++; curr_addr += sizeof(instruction);
335     genSimpleInsn(curr_instr, ADDop3, REG_L(3), REG_L(0), REG_L(0));
336     curr_instr++; curr_addr += sizeof(instruction);
337   }    
338   genSimpleInsn( curr_instr, ADDop3, REG_G(0), REG_G(0), REG_L(1) );
339   curr_instr++; curr_addr += sizeof( instruction );
340   generateLoad( curr_instr, REG_L(0), LOW10( guard_flag_address ), REG_L(2) );
341   curr_instr++; curr_addr += sizeof( instruction );
342   generateStore( curr_instr, REG_L(1), REG_L(0), LOW10( guard_flag_address ) );
343   curr_instr++; curr_addr += sizeof( instruction );
344   genSimpleInsn( curr_instr, SUBop3cc, REG_L(2), REG_G(0), REG_G(0) );
345   curr_instr++; curr_addr += sizeof( instruction );
346   int branch_offset_in_bytes =
347     ( base_addr + templ.guardOffPre_endOffset )
348     -
349     curr_addr
350     ;
351   genBranch( curr_instr,
352              branch_offset_in_bytes,
353              BEcond,
354              false );
355   curr_instr++; curr_addr += sizeof( instruction );
356   generateNOOP ( curr_instr );
357
358   /* fill the 'guard off' pre-instruction instrumentation */
359   curr_instr = code + templ.guardOffPre_beginOffset / sizeof( instruction );
360   curr_addr = base_addr + templ.guardOffPre_beginOffset;
361   generateSetHi( curr_instr, guard_flag_address, REG_L(0) );
362   curr_instr++; curr_addr += sizeof( instruction );
363   // We should store this value... but where?
364   if (p.multithread_capable()) {
365     int shift_val;
366     isPowerOf2(sizeof(unsigned), shift_val);
367     generateLShift(curr_instr, REG_MT_POS, (Register)shift_val, REG_L(3));
368     curr_instr++; curr_addr += sizeof(instruction);
369     genSimpleInsn(curr_instr, ADDop3, REG_L(3), REG_L(0), REG_L(0));
370     curr_instr++; curr_addr += sizeof(instruction);
371   }    
372
373   genImmInsn( curr_instr, ADDop3, REG_G(0), 1, REG_L(1) );
374   curr_instr++; curr_addr += sizeof( instruction );
375   generateStore( curr_instr, REG_L(1), REG_L(0), LOW10( guard_flag_address ) );
376
377   /* fill the 'guard on' post-instruction instrumentation */
378   curr_instr = code + templ.guardOnPost_beginOffset / sizeof( instruction );
379   curr_addr = base_addr + templ.guardOnPost_beginOffset;
380   generateSetHi( curr_instr, guard_flag_address, REG_L(0) );
381   curr_instr++; curr_addr += sizeof( instruction );
382
383   if (p.multithread_capable()) {
384     int shift_val;
385     isPowerOf2(sizeof(unsigned), shift_val);
386     generateLShift(curr_instr, REG_MT_POS, (Register)shift_val, REG_L(3));
387     curr_instr++; curr_addr += sizeof(instruction);
388     genSimpleInsn(curr_instr, ADDop3, REG_L(3), REG_L(0), REG_L(0));
389     curr_instr++; curr_addr += sizeof(instruction);
390   }    
391
392   genSimpleInsn( curr_instr, ADDop3, REG_G(0), REG_G(0), REG_L(1) );
393   curr_instr++; curr_addr += sizeof( instruction );
394   generateLoad( curr_instr, REG_L(0), LOW10( guard_flag_address ), REG_L(2) );
395   curr_instr++; curr_addr += sizeof( instruction );
396   generateStore( curr_instr, REG_L(1), REG_L(0), LOW10( guard_flag_address ) );
397   curr_instr++; curr_addr += sizeof( instruction );
398   genSimpleInsn( curr_instr, SUBop3cc, REG_L(2), REG_G(0), REG_G(0) );
399   curr_instr++; curr_addr += sizeof( instruction );
400   branch_offset_in_bytes =
401     ( base_addr + templ.guardOffPost_endOffset )
402     -
403     curr_addr
404     ;
405   genBranch( curr_instr,
406              branch_offset_in_bytes,
407              BEcond,
408              false );
409   curr_instr++; curr_addr += sizeof( instruction );
410   generateNOOP ( curr_instr );
411
412   /* fill the 'guard off' post-instruction instrumentation */
413   curr_instr = code + templ.guardOffPost_beginOffset / sizeof( instruction );
414   curr_addr = base_addr + templ.guardOffPost_beginOffset;
415   generateSetHi( curr_instr, guard_flag_address, REG_L(0) );
416   curr_instr++; curr_addr += sizeof( instruction );
417
418   if (p.multithread_capable()) {
419     int shift_val;
420     isPowerOf2(sizeof(unsigned), shift_val);
421     generateLShift(curr_instr, REG_MT_POS, (Register)shift_val, REG_L(3));
422     curr_instr++; curr_addr += sizeof(instruction);
423     genSimpleInsn(curr_instr, ADDop3, REG_L(3), REG_L(0), REG_L(0));
424     curr_instr++; curr_addr += sizeof(instruction);
425   }    
426
427   genImmInsn( curr_instr, ADDop3, REG_G(0), 1, REG_L(1) );
428   curr_instr++; curr_addr += sizeof( instruction );
429   generateStore( curr_instr, REG_L(1), REG_L(0), LOW10( guard_flag_address ) );
430 }
431
432 //
433 // For multithreaded applications and shared memory sampling, this routine 
434 // will compute the address where the corresponding counter/timer vector for
435 // level 0 is (by default). In the mini-tramp, if the counter/timer is at a
436 // different level, we will add the corresponding offset - naim 4/18/97
437 //
438 // NUM_INSN_MT_PREAMBLE
439 void generateMTpreamble(char *insn, Address &base, process *proc)
440 {
441   AstNode *threadPOS;
442   Address returnVal;
443   pdvector<AstNode *> dummy;
444   bool err;
445   Register src = Null_Register;
446
447   // registers cleanup
448   regSpace->resetSpace();
449
450   /* Get the hashed value of the thread */
451   if (!proc->multithread_ready()) {
452     // Uh oh... we're not ready to build a tramp yet!
453     cerr << "WARNING: tramp constructed without RT multithread support!" << endl;
454     threadPOS = new AstNode("DYNINSTreturnZero", dummy);
455   }
456   else 
457     threadPOS = new AstNode("DYNINSTthreadPos", dummy);
458   src = threadPOS->generateCode(proc, regSpace, (char *)insn,
459                                 base, 
460                                 false, // noCost 
461                                 true); // root node
462   if ((src) != REG_MT_POS) {
463     // This is always going to happen... we reserve REG_MT_POS, so the
464     // code generator will never use it as a destination
465     emitV(orOp, src, 0, REG_MT_POS, insn, base, false);
466   }
467 }
468
469
470 /****************************************************************************/
471 /****************************************************************************/
472 /****************************************************************************/
473
474 /*
475  * Install a base tramp -- fill calls with nop's for now.
476  *
477  * This one install the base tramp for the regular functions.
478  *
479  */
480 trampTemplate * installBaseTramp( instPoint * & location,
481                                   process * proc,
482                                   trampTemplate *&current_template,
483                                   Address baseTrampAddress,
484                                   bool trampRecursiveDesired = false )
485 {
486     Address ipAddr = 0;
487     Address baseAddress = 0;
488     Address currAddr;
489     instruction *temp;
490     // Records the number of instructions copied over to the base trampoline
491     int numInsnsCopied = 0;
492
493     // Get the base address of the so 
494     proc->getBaseAddress( location->image_ptr, baseAddress );
495
496     // Determine the address of the instPoint
497     ipAddr = location->iPgetAddress() + baseAddress;
498
499     // Determine if the base trampoline is within the range of a branch
500     // instruction from the instrumentation point. This is used to determine
501     // How we transfer between the function and instrumentation, as well
502     // as how many instructions get copied to the base trampoline 
503     if ( !offsetWithinRangeOfBranchInsn(baseTrampAddress - ipAddr) ) {
504       location->needsLongJump = true;
505     }
506
507 //     if(location->dontUseCall)
508 //       fprintf(stderr, "dontUseCall@%p\n", ipAddr);
509
510     // VG(4/25/2002): refuse installation if call is needed, but not safe
511     if(location->needsLongJump && location->dontUseCall)
512       return NULL;
513
514     // very conservative installation as o7 can be live 
515     // at this arbitrary inst point
516     if( (location->ipType == otherPoint) &&
517          location->func && location->func->is_o7_live() &&
518          location->needsLongJump)
519     {
520         // Free up the space allocated for the base tramp
521         proc->inferiorFree(baseTrampAddress);
522         location->needsLongJump = false;
523
524         // Creation of base tramp failed
525         return NULL;
526     }
527
528     // Generate a buffer for writing the base tramp to
529     instruction * code = new instruction[ current_template->size ];
530     assert( code );
531
532     // Set up the template of the base trampoline in the buffer
533     memcpy( (char *)code,
534             (char *)current_template->trampTemp,
535             current_template->size );
536
537
538
539     // Iterate over the trampoline template buffer, filling in the details
540     for (temp = code, currAddr = baseTrampAddress; 
541         (currAddr - baseTrampAddress) < (unsigned) current_template->size;
542         temp++, currAddr += sizeof(instruction)) {
543
544       unsigned offset;
545       Address numIns;
546       Address retAddress;
547
548       switch (temp->raw) {
549       case EMULATE_INSN:
550         // Branch instruction (i.e.  ba, a) will do for transfering 
551         // between function and base trampoline, thus only one 
552         // instruction needs to be copied to the base tramp. (unless
553         // of course that instruction is a DCTI).
554         if ( !location->needsLongJump ) {
555           
556           // Need to copy the first instruction to the base trampoline
557           *temp = location->firstInstruction;
558           relocateInstruction(temp, ipAddr, currAddr, proc);
559           numInsnsCopied = 1;
560           
561           // If the instruction that was copied over to the 
562           // base tramp was a DCTI, then we need to copy over the
563           // instruction in its delay slot, and perhaps also an
564           // aggregate instruction. (An aggregate instruction is a
565           // byte that follows the delay slot of a call, where the 
566           // called function returns a structure, and the aggregate
567           // instruction records the size of the structure returned).
568           
569           if ( location->firstIsDCTI ) {
570             
571             // copy delay slot instruction to trampoline
572             currAddr += sizeof(instruction);  
573             *++temp = location->secondInstruction;
574             numInsnsCopied = 2;
575           }
576           
577           if ( location->thirdIsAggregate ) {
578             
579             // copy invalid insn with aggregate size in it to
580             // base trampoline
581             currAddr += sizeof(instruction);  
582             *++temp = location->thirdInstruction;
583             numInsnsCopied = 3;
584           }
585           
586           // call sequence is needed to transfer to base trampoline
587         } else {
588           
589           // For arbitrary instPoints. call; nop; used to transfer 
590           if (location->ipType == otherPoint) {
591             
592             // relocate the FIRST instruction
593             *temp = location->firstInstruction;
594             relocateInstruction(temp, ipAddr, currAddr, proc);
595             numInsnsCopied = 1;
596             
597             
598             // relocate the SECOND instruction
599             temp++;
600             currAddr += sizeof(instruction);
601             *temp = location->secondInstruction;
602             relocateInstruction(temp,
603                                 ipAddr + 1*sizeof(instruction), 
604                                 currAddr, proc);
605             numInsnsCopied = 2;
606             
607             // if the SECOND instruction is a DCTI, then the 
608             // third instruction needs to be copied, and the fourth 
609             // instruction may be an aggregate 
610             if (location->secondIsDCTI) {
611               
612               // relocate the third instruction
613               temp++;
614               currAddr += sizeof(instruction);
615               *temp = location->thirdInstruction;
616               relocateInstruction(temp, 
617                                   ipAddr + 2*sizeof(instruction),
618                                   currAddr, proc);
619               numInsnsCopied = 3;
620               
621               if (location->fourthIsAggregate) {
622                 
623                 // relocate the FOURTH instruction
624                 temp++;
625                 currAddr += sizeof(instruction);
626                 *temp = location->fourthInstruction;
627                 relocateInstruction(temp, 
628                                     ipAddr + 3*sizeof(instruction),
629                                     currAddr, proc);
630                 numInsnsCopied = 4;
631               }
632             }
633             
634           } else {
635             
636             // the instructions prior to the instPoint don't need to 
637             // be used
638             if ( !location->usesPriorInstructions ) {
639               
640               
641               // For leaf functions
642               if (location->hasNoStackFrame()) {
643                 
644                 // relocate the FIRST instruction
645                 *temp = location->firstInstruction;
646                 relocateInstruction(temp,
647                                     ipAddr, 
648                                     currAddr, proc);
649                 numInsnsCopied = 1;
650                 
651                 
652                 // relocate the SECOND instruction
653                 temp++;
654                 currAddr += sizeof(instruction);
655                 *temp = location->secondInstruction;
656                 relocateInstruction(temp,
657                                     ipAddr + 1*sizeof(instruction), 
658                                     currAddr, proc);
659                 numInsnsCopied = 2;
660                 
661                 
662                 // relocate the THIRD instruction
663                 temp++;
664                 currAddr += sizeof(instruction);
665                 *temp = location->thirdInstruction;
666                 relocateInstruction(temp, 
667                                     ipAddr + 2*sizeof(instruction),
668                                     currAddr, proc);
669                 numInsnsCopied = 3;
670                 
671                 
672                 // if the THIRD instruction is a DCTI, then the fourth
673                 // instruction must be copied to the base tramp as well 
674                 if (location->thirdIsDCTI) {
675                   
676                   // Copy the instruction in the delay slot to the 
677                   // base trampoline
678                   temp++;
679                   currAddr += sizeof(instruction);
680                   *temp = location->fourthInstruction;
681                   relocateInstruction(temp,
682                                       ipAddr + 3*sizeof(instruction),
683                                       currAddr, proc);
684                   temp++;
685                   numInsnsCopied = 4;
686                 }
687                 
688                 // Function has a stack frame
689               } else {
690                 
691                 // No need for a save instruction, only need to copy
692                 // the original instruction and the delay slot insn
693                 if ( location->ipType == callSite || 
694                      location->ipType == functionExit ) {
695                   
696                   // relocate the FIRST instruction
697                   *temp = location->firstInstruction;
698                   relocateInstruction(temp,
699                                       ipAddr, 
700                                       currAddr, proc);
701                   temp++;
702                   currAddr += sizeof(instruction);
703                   numInsnsCopied = 1;
704                   
705                   // relocate the SECOND instruction
706                   *temp = location->secondInstruction;
707                   relocateInstruction(temp,
708                                       ipAddr + 1*sizeof(instruction), 
709                                       currAddr, proc);
710                   numInsnsCopied = 2;
711                   
712                   
713                   // since the FIRST instruction is a DCTI, the 
714                   // third instruction may be an aggregate
715                   assert (location->firstIsDCTI);
716                   
717                   if (location->thirdIsAggregate) {
718                     
719                     // relocate the THIRD instruction
720                     temp++;
721                     currAddr += sizeof(instruction);
722                     *temp = location->thirdInstruction;
723                     relocateInstruction(temp, 
724                                         ipAddr + 2*sizeof(instruction),
725                                         currAddr, proc);
726                     numInsnsCopied = 3;
727                   }
728                   
729                 } else {
730                   
731                   assert (location->ipType == functionEntry);
732                   
733                   // relocate the FIRST instruction
734                   *temp = location->firstInstruction;
735                   relocateInstruction(temp, ipAddr, currAddr, proc);
736                   temp++;
737                   currAddr += sizeof(instruction);
738                   numInsnsCopied = 1;
739                   
740                   // relocate the SECOND instruction
741                   *temp = location->secondInstruction;
742                   relocateInstruction(temp,
743                                       ipAddr + 1*sizeof(instruction),
744                                       currAddr, proc);
745                   numInsnsCopied = 2;
746                   
747                   
748                   // relocate the THIRD instruction
749                   temp++;
750                   currAddr += sizeof(instruction);
751                   *temp = location->thirdInstruction;
752                   relocateInstruction(temp, 
753                                       ipAddr + 2*sizeof(instruction),
754                                       currAddr, proc);
755                   numInsnsCopied = 3;
756                   
757                   
758                   // if the SECOND instruction is a DCTI, then the 
759                   // fourth instruction may be an aggregate 
760                   if (location->secondIsDCTI) {
761                     
762                     if (location->fourthIsAggregate) {
763                       
764                                 // relocate the FOURTH instruction
765                       temp++;
766                       currAddr += sizeof(instruction);
767                       *temp = location->fourthInstruction;
768                       relocateInstruction(temp, 
769                                           ipAddr + 3*sizeof(instruction),
770                                           currAddr, proc);
771                       numInsnsCopied = 4;
772                     }
773                   }
774                   
775                   // if the THIRD instruction is a DCTI, then the 
776                   // fourth instruction is in the delay slot and the
777                   // fifth instruction may be an aggregate (for 
778                   // entry and other points only). 
779                   if (location->thirdIsDCTI) {
780                     
781                     // relocate the FOURTH instruction
782                     temp++;
783                     currAddr += sizeof(instruction);
784                     *temp = location->fourthInstruction;
785                     relocateInstruction(temp, 
786                                         ipAddr + 3*sizeof(instruction),
787                                         currAddr, proc);
788                     numInsnsCopied = 4;
789                     
790                     // Then, possibly, there's a callAggregate
791                     // instruction after this. 
792                     if (location->fifthIsAggregate) {
793                       
794                                 // relocate the FIFTH instruction
795                       temp++;
796                       currAddr += sizeof(instruction);
797                       *temp = location->fifthInstruction;
798                       relocateInstruction(temp, 
799                                           ipAddr + 4*sizeof(instruction),
800                                           currAddr, proc);
801                       
802                       numInsnsCopied = 5;
803                     }
804                   }
805                 }
806               }
807               
808               // the instructions prior to the instPoint need to be used
809             } else {
810               
811               // At the exit of leaf function, we need to over-write
812               // three instructions for a save; call; restore; sequence
813               // but we only have two instructions. So we claim the
814               // the instructions preceding the exit point
815               assert(location->hasNoStackFrame());
816               assert(location->ipType == functionExit);
817               
818               numInsnsCopied = 2;
819               
820               // 'firstPriorInstruction' is the aggregate after a call,
821               // so copy the two instructions that precede it.
822               if (location->numPriorInstructions == 3) {
823                 
824                 currAddr += sizeof(instruction);
825                 *++temp = location->thirdPriorInstruction;
826                 relocateInstruction(temp, ipAddr, currAddr, proc);
827                 
828                 currAddr += sizeof(instruction);
829                 *++temp = location->secondPriorInstruction;
830                 
831               }
832               
833               // 'firstPriorInstruction' is the delay slot of a call,
834               // so copy the instruction that precedes it.
835               if (location->numPriorInstructions == 2) {
836                 
837                 currAddr += sizeof(instruction);
838                 *++temp = location->secondPriorInstruction;
839                 relocateInstruction(temp, ipAddr, currAddr, proc);
840                 
841               }
842               
843               currAddr += sizeof(instruction);
844               *++temp = location->firstPriorInstruction;
845               
846               currAddr += sizeof(instruction);
847               *++temp = location->firstInstruction;
848               
849               currAddr += sizeof(instruction);
850               *++temp = location->secondInstruction;
851               
852               // Well, after all these, another SAVE instruction is 
853               // generated so we are prepared to handle the returning 
854               // to our application's code segment.
855               genImmInsn(temp+1, SAVEop3, REG_SPTR, -120, REG_SPTR);
856             }
857           }
858           
859         }
860         break;
861       case RETURN_INSN:
862         
863         if ( offsetWithinRangeOfBranchInsn((ipAddr + 
864                                             numInsnsCopied*sizeof(instruction)) - 
865                                            currAddr) ) {
866           
867           generateBranchInsn(temp, ipAddr + 
868                              numInsnsCopied*sizeof(instruction) - 
869                              currAddr);
870           
871         } else {
872           
873           retAddress =  baseAddress + 
874             location->iPgetAddress() + 
875             numInsnsCopied*sizeof(instruction);
876           
877           if (location->func->hasNoStackFrame() ||
878               ((location->ipType == otherPoint) &&
879                location->func->is_o7_live())){
880                 
881               /* to save value of live o7 register we save and call*/
882               genImmInsn(temp, SAVEop3, REG_SPTR, -120, REG_SPTR);
883               generateCallInsn(temp + 1, 
884                                currAddr + sizeof(instruction), 
885                                retAddress);
886               genImmInsn(temp+2, RESTOREop3, 0, 0, 0);
887               
888           } else {
889               generateCallInsn(temp, currAddr, retAddress);
890           }
891         }
892         break;
893       case SKIP_PRE_INSN:
894         offset = baseTrampAddress+current_template->updateCostOffset-currAddr;
895         generateBranchInsn(temp,offset);
896         break;
897       case SKIP_POST_INSN:
898         offset = baseTrampAddress+current_template->returnInsOffset-currAddr;
899         generateBranchInsn(temp,offset);
900         break;
901       case UPDATE_COST_INSN:
902         current_template->costAddr = currAddr;
903         generateNOOP(temp);
904         break;
905       case LOCAL_PRE_BRANCH:
906       case LOCAL_POST_BRANCH:
907         generateNOOP(temp);
908         break;
909       case MT_POS_CALC:
910         if (proc->multithread_capable()) {
911           numIns = 0;
912           generateMTpreamble((char *)temp, numIns, proc);
913           //temp += (numIns/sizeof(instruction));
914         }
915         else
916           generateNOOP(temp); /* Not yet ready for MT tramp */
917         break;
918       case RECURSIVE_GUARD_ON_PRE_INSN:
919       case RECURSIVE_GUARD_OFF_PRE_INSN:
920       case RECURSIVE_GUARD_ON_POST_INSN:
921       case RECURSIVE_GUARD_OFF_POST_INSN:
922         generateNOOP( temp );
923         break;
924       default: /* May catch an unknown instruction (or a noop) */
925         break;
926       }
927     }
928     
929     if( ! trampRecursiveDesired ) {
930       generate_base_tramp_recursive_guard_code( *proc, code, baseTrampAddress,
931                                                 (NonRecursiveTrampTemplate &) *current_template);
932     }
933     /*
934     fprintf(stderr, "------------\n");
935     for (int i = 0; i < (current_template->size/4); i++)
936       fprintf(stderr, "0x%x,\n", code[i].raw);
937     fprintf(stderr, "------------\n");
938     fprintf(stderr, "\n\n\n");
939     */
940
941     // TODO cast
942     proc->writeDataSpace( ( caddr_t )baseTrampAddress,
943                           current_template->size,
944                           ( caddr_t )code );
945     delete [] code;
946
947     trampTemplate * baseInst;
948     if( trampRecursiveDesired )
949       {
950         baseInst = new trampTemplate;
951       }
952     else
953       {
954         baseInst = new NonRecursiveTrampTemplate;
955       }
956     * baseInst = *current_template;
957     baseInst->baseAddr = baseTrampAddress;
958
959     return baseInst;
960 }
961
962
963 /****************************************************************************/
964 /****************************************************************************/
965 /****************************************************************************/
966
967 /*
968  * Allocate the space for the base Trampoline, and generate the instruction
969  * we need for modifying the code segment.
970  *
971  * 'retInstance' tells you how to modify the code to jump to the base tramp
972  *
973  */
974 trampTemplate *findAndInstallBaseTramp(process *proc, 
975                                        instPoint *&location,
976                                        returnInstance *&retInstance,
977                                        bool trampRecursionDesired,
978                                        bool, 
979                                        bool &deferred)
980 {
981     Address baseAddress;
982     Address ipAddr;
983     Address baseTrampAddress = 0;
984
985     retInstance = NULL;
986
987     const instPoint *&cLocation = const_cast<const instPoint *&>(location);
988  
989     trampTemplate *ret;
990
991     if (proc->baseMap.find(cLocation, ret)) {
992
993        // This base tramp already exists; nothing to do.
994        return ret;
995     }
996
997
998     // Generate the template for the trampoline
999     trampTemplate *current_template = &nonRecursiveBaseTemplate;
1000
1001     if(location->ipType == otherPoint) {
1002       current_template = &nonRecursiveConservativeBaseTemplate;
1003     }
1004
1005     if( trampRecursionDesired ) {
1006       current_template = &baseTemplate;
1007
1008       if(location->ipType == otherPoint) {
1009         current_template = &conservativeBaseTemplate;
1010       }
1011     }
1012
1013
1014     // Get the base address of the shared object 
1015     proc->getBaseAddress( location->image_ptr, baseAddress );
1016
1017     // Determine the address of the instPoint
1018     ipAddr = location->iPgetAddress() + baseAddress;
1019
1020
1021     // For functions that MAY need relocation, check to see if the 
1022     // base tramp is within the range of a branch of the instPoint.
1023     // If the base tramp is too far away, force relocation, and rewrite
1024     // the function so that a save; call; restore; sequence can be used
1025     // to transfer to the base trampoline.
1026     if ( location->func->mayNeedRelocation() ) { 
1027
1028       // Allocate space for the base trampoline
1029       baseTrampAddress = proc->inferiorMalloc(current_template->size, 
1030                                               textHeap, ipAddr);
1031       assert( baseTrampAddress );
1032
1033       // Determine if the base trampoline is within the range of a branch
1034       // instruction from the instrumentation point. This is used to determine
1035       // How we transfer between the function and instrumentation, as well
1036       // as how many instructions get copied to the base trampoline
1037       if ( !offsetWithinRangeOfBranchInsn(baseTrampAddress - ipAddr) ) {
1038
1039         // The function needs to be relocated to be instrumentable
1040         location->func->setRelocatable(true);
1041
1042         // Free up the space allocated for the base tramp
1043         // (Since we are relocating the function, we want to allocate
1044         // the base tramp near the NEW instPoint location).
1045         proc->inferiorFree(baseTrampAddress);
1046         baseTrampAddress = 0;
1047
1048       }
1049     }
1050
1051
1052     // Relocate the function if needed 
1053     if (location->func->needsRelocation()) {
1054
1055 #ifdef BPATCH_LIBRARY
1056       const BPatch_point *old_bppoint = location->getBPatch_point();
1057 #endif
1058       if(!(location->func->isInstalled(proc))) {
1059
1060         // Relocate the function
1061         bool relocated = location->func->relocateFunction(proc, location, 
1062                                                                 deferred);
1063
1064         // Unable to relocate function
1065         if (relocated == false) {
1066           return NULL;
1067         }
1068 #ifdef BPATCH_LIBRARY
1069         location->setBPatch_point(old_bppoint);
1070 #endif
1071
1072       } else {
1073
1074           if(!location->relocated_){
1075
1076             // need to find new instPoint for location...
1077             // it has the pre-relocated address of the instPoint
1078             location->func->modifyInstPoint(cLocation,proc);
1079 #ifdef BPATCH_LIBRARY
1080             location->setBPatch_point(old_bppoint);
1081 #endif
1082           }
1083       }
1084     }
1085
1086
1087     // Grab the address of the instPoint (this may have changed if the
1088     // function was relocated).
1089     ipAddr = location->iPgetAddress() + baseAddress;
1090
1091
1092     // Allocate space for the base tramp if it has not been allocated yet
1093     if (baseTrampAddress == 0) {
1094
1095       // Allocate space for the base trampoline
1096       baseTrampAddress = proc->inferiorMalloc(current_template->size, 
1097                                               textHeap, ipAddr);
1098       assert( baseTrampAddress );
1099     }
1100
1101
1102     // Set up the base tramp.
1103     ret = installBaseTramp(location, proc, 
1104                            current_template, 
1105                            baseTrampAddress, 
1106                            trampRecursionDesired);
1107     if(!ret) return NULL;
1108
1109
1110     // If the base trampoline is within the range of a branch instruction
1111     // from the function, use a branch to transfer control from the 
1112     // function to the base tramp
1113     if ( !location->needsLongJump ) {
1114
1115       // Place branch at the exact location of the instruction to be 
1116       // instrumented (insnAddress()), rather than at the
1117       // first Address of the instPoint's footprint, iPgetAddress(),
1118       // (these may differ).
1119       // The latter address is used when we use a call instruction 
1120       // instead of a branch to get to the base tramp.
1121       Address branchAddress = location->insnAddress() + baseAddress;
1122
1123       instruction *insn = new instruction;
1124       generateBranchInsn(insn, ret->baseAddr - branchAddress);
1125       retInstance = new returnInstance(1, (instructUnion *)insn,
1126                                        1 * sizeof(instruction), branchAddress, 
1127                                        1 * sizeof(instruction));
1128     } else {
1129
1130
1131         if ( location->ipType == otherPoint ) {
1132
1133           // Generate call; nop; sequence
1134           // (no need to generate a save since instrumentation will only go
1135           // in if the o7 register is not live
1136           instruction *insn = new instruction[2];
1137
1138           // Generate the call instruction over the ret
1139           generateCallInsn(insn, ipAddr, ret->baseAddr);
1140
1141           // Generate the nop over the restore
1142           generateNOOP(insn+1);
1143
1144           retInstance = new returnInstance(2, (instructUnion *)insn, 
1145                                            2*sizeof(instruction), 
1146                                            ipAddr, 
1147                                            2*sizeof(instruction));
1148         } else {
1149
1150           // For functions that have no stack frame
1151           if (location->hasNoStackFrame()) {
1152
1153             // Generate a save; call; nop sequence
1154             instruction *insn = new instruction[3];
1155
1156             // The address the save will be written to
1157             Address saveAddr = ipAddr;
1158
1159             // If prior instructions need to be claimed, determine the
1160             // address of the first instruction that will be moved to the
1161             // base tramp (and thus replaced by the save).
1162             if (location->usesPriorInstructions) {
1163
1164               saveAddr = 
1165                 ipAddr - location->numPriorInstructions * sizeof(instruction);
1166             }
1167
1168             // Generate the save
1169             genImmInsn(insn, SAVEop3, REG_SPTR, -120, REG_SPTR);
1170
1171             // Generate the call
1172             generateCallInsn(insn + 1, 
1173                              saveAddr + sizeof(instruction), 
1174                              ret->baseAddr);
1175
1176             // Generate the restore
1177             genImmInsn(insn + 2, RESTOREop3, 0, 0, 0);
1178
1179             retInstance = new returnInstance(3, (instructUnion *)insn, 
1180                                              3 * sizeof(instruction), 
1181                                              saveAddr, 
1182                                              3 * sizeof(instruction));
1183
1184           // Not a leaf function
1185           } else {
1186
1187             if ( location->ipType == callSite || 
1188                  location->ipType == functionExit ) {
1189
1190                 // Generate call; nop; sequence
1191                 // (no need to generate a save since the o7 register is 
1192                 // going to be clobbered by the ret; restore).
1193                 instruction *insn = new instruction[2];
1194
1195                 // Generate the call instruction over the ret
1196                 generateCallInsn(insn, ipAddr, ret->baseAddr);
1197
1198                 // Generate the nop over the restore
1199                 generateNOOP(insn+1);
1200
1201                 retInstance = new returnInstance(2, (instructUnion *)insn, 
1202                                                  2*sizeof(instruction), 
1203                                                  ipAddr, 
1204                                                  2*sizeof(instruction));
1205
1206             } else if ( location->ipType == functionEntry ) {
1207
1208                 // Generate save; call; restore; sequence
1209                 instruction *insn = new instruction[3];
1210
1211                 // Generate the save
1212                 genImmInsn(insn, SAVEop3, REG_SPTR, -120, REG_SPTR);
1213
1214                 // Generate the call
1215                 generateCallInsn(insn + 1, 
1216                                  ipAddr + sizeof(instruction), 
1217                                  ret->baseAddr);
1218
1219                 // Generate the restore
1220                 genImmInsn(insn + 2, RESTOREop3, 0, 0, 0);
1221
1222                 retInstance = new returnInstance(3, (instructUnion *)insn, 
1223                                                  3 * sizeof(instruction), 
1224                                                  ipAddr, 
1225                                                  3 * sizeof(instruction));
1226             }
1227           }
1228         }
1229     }
1230
1231     assert(retInstance);
1232     proc->baseMap[(const instPoint *)location] = ret;
1233         
1234     return(ret);
1235 }
1236
1237 /****************************************************************************/
1238 /****************************************************************************/
1239 /****************************************************************************/
1240
1241 /*
1242  * Install a single tramp.
1243  *
1244  */
1245 void installTramp(instInstance *inst, process *proc, char *code, int codeSize,
1246                   instPoint *location, callWhen when) 
1247 {
1248     //the default base trampoline template is the regular base trampoline.
1249     //However if the location iptype is  randomPoint then we have to use
1250     //the conservatibve base trampoline which saves the condition codes
1251
1252     trampTemplate* current_template = &baseTemplate;
1253
1254     if(location->ipType == otherPoint)
1255         current_template = &conservativeBaseTemplate;
1256
1257     totalMiniTramps++;
1258     insnGenerated += codeSize/sizeof(int);
1259     
1260     // TODO cast
1261     proc->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
1262
1263     Address atAddr;
1264     if(when == callPreInsn) {
1265         if (inst->baseInstance->prevInstru == false) {
1266             atAddr = inst->baseInstance->baseAddr+current_template->skipPreInsOffset;
1267             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
1268             inst->baseInstance->prevInstru = true;
1269             generateNoOp(proc, atAddr);
1270         }
1271     } else {
1272         if (inst->baseInstance->postInstru == false) {
1273             atAddr = inst->baseInstance->baseAddr+current_template->skipPostInsOffset; 
1274             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
1275             inst->baseInstance->postInstru = true;
1276             generateNoOp(proc, atAddr);
1277         }
1278     }
1279 }
1280
1281 /****************************************************************************/
1282 /****************************************************************************/
1283 /****************************************************************************/
1284
1285 //This function returns true if the processor on which the daemon is running
1286 //is an ultra SPARC, otherwise returns false.
1287 bool isUltraSparc(){
1288   struct utsname u;
1289   if(uname(&u) < 0){
1290     cerr <<"Trouble in uname(), inst-sparc-solaris.C\n";
1291     return false;
1292   }
1293   if(!strcmp(u.machine, "sun4u")){
1294     return 1;
1295   }
1296   return false;
1297 }
1298
1299 /****************************************************************************/
1300 /****************************************************************************/
1301 /****************************************************************************/
1302
1303 void emitLoadPreviousStackFrameRegister(Address register_num,
1304                                         Register dest,
1305                                         char *insn,
1306                                         Address &base,
1307                                         int size,
1308                                         bool noCost){
1309   if(register_num > 31)
1310     assert(0);
1311   else if(register_num > 15){
1312     /*Need to find it on the stack*/
1313     unsigned frame_offset = (register_num-16) * 4;
1314     /*generate a FLUSHW instruction, in order to make sure that
1315       the registers from the caller are on the caller's stack
1316       frame*/
1317     instruction *in = (instruction *) ((void*)&insn[base]);
1318     if(isUltraSparc())
1319       generateFlushw(in);
1320     else 
1321       generateTrapRegisterSpill(in);
1322     base+=sizeof(instruction);
1323     
1324     if(frame_offset == 0){
1325       emitV(loadIndirOp, 30, 0, dest, insn, base, noCost, size);
1326     }       
1327     else {
1328       emitImm(plusOp,(Register) 30,(RegValue)frame_offset, 
1329               dest, insn, base, noCost);
1330       emitV(loadIndirOp, dest, 0, dest, insn, base, noCost, size);
1331     }
1332   }       
1333   else if(register_num > 7) { 
1334     //out registers become in registers, so we add 16 to the register
1335     //number to find it's value this stack frame. We move it's value
1336     //into the destination register
1337     emitV(orOp, (Register) register_num + 16, 0,  dest, insn, base, false);
1338   }
1339   else /* if(register_num >= 0) */ {
1340     int frame_offset;
1341     if(register_num % 2 == 0) 
1342       frame_offset = (register_num * -4) - 8;
1343     else 
1344       frame_offset = (register_num * -4);
1345     //read globals from the stack, they were saved in tramp-sparc.S
1346     emitImm(plusOp,(Register) 30,(RegValue)frame_offset, 
1347             dest, insn, base, noCost);
1348     emitV(loadIndirOp, dest, 0, dest, insn, base, noCost, size);
1349   }
1350   /* else assert(0); */
1351   
1352 }
1353
1354 /****************************************************************************/
1355 /****************************************************************************/
1356 /****************************************************************************/
1357
1358 Register emitFuncCall(opCode op, 
1359                       registerSpace *rs,
1360                       char *i, Address &base, 
1361                       const pdvector<AstNode *> &operands, 
1362                       const string &callee, process *proc,
1363                       bool noCost, const function_base *calleefunc,
1364                       const pdvector<AstNode *> &ifForks,
1365                       const instPoint *location)
1366 {
1367    assert(op == callOp);
1368    Address addr;
1369    bool err;
1370    pdvector <Register> srcs;
1371    void cleanUpAndExit(int status);
1372    
1373    if (calleefunc) {
1374       addr = calleefunc->getEffectiveAddress(proc);
1375    }
1376    else {      
1377       addr = proc->findInternalAddress(callee, false, err);
1378       
1379       if (err) {
1380          function_base *func = proc->findOneFunction(callee);
1381          if (!func) {
1382             ostrstream os(errorLine, 1024, ios::out);
1383             os << "Internal error: unable to find addr of " << callee << endl;
1384             showErrorCallback(80, (const char *) errorLine);
1385             P_abort();
1386          }
1387          // TODO: is this correct or should we get relocated address?
1388          //addr = func->getAddress(0);
1389          addr = func->getEffectiveAddress(proc);
1390       }
1391    }
1392    for (unsigned u = 0; u < operands.size(); u++)
1393       srcs.push_back(operands[u]->generateCode_phase2(proc, rs, i, base,
1394                                                       noCost, ifForks,
1395                                                       location));
1396    
1397    // TODO cast
1398    instruction *insn = (instruction *) ((void*)&i[base]);
1399    
1400    for (unsigned u=0; u<srcs.size(); u++){
1401       if (u >= 5) {
1402          string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
1403          fprintf(stderr, msg.c_str());
1404          showErrorCallback(94,msg);
1405          cleanUpAndExit(-1);
1406       }
1407       genSimpleInsn(insn, ORop3, 0, srcs[u], u+8); insn++;
1408       base += sizeof(instruction);
1409       rs->freeRegister(srcs[u]);
1410    }
1411    
1412    // As Ling pointed out to me, the following is rather inefficient.  It does:
1413    //   sethi %hi(addr), %o5
1414    //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
1415    //   nop
1416    // We can do better:
1417    //   call <addr>    (but note that the call true-instr is pc-relative jump)
1418    //   nop
1419    generateSetHi(insn, addr, 13); insn++;
1420    genImmInsn(insn, JMPLop3, 13, LOW10(addr), 15); insn++;
1421    generateNOOP(insn);
1422         
1423    base += 3 * sizeof(instruction);
1424    
1425    // return value is the register with the return value from the function.
1426    // This needs to be %o0 since it is back in the caller's scope.
1427    return(REG_O(0));
1428 }
1429  
1430 /****************************************************************************/
1431 /****************************************************************************/
1432 /****************************************************************************/
1433
1434 Address emitA(opCode op, Register src1, Register /*src2*/, Register dest, 
1435               char *i, Address &base, bool /*noCost*/)
1436 {
1437     //fprintf(stderr,"emitA(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
1438
1439     instruction *insn = (instruction *) ((void*)&i[base]);
1440
1441     switch (op) {
1442       case ifOp: {
1443         // cmp src1,0
1444         genImmInsn(insn, SUBop3cc, src1, 0, 0); insn++;
1445         //genSimpleInsn(insn, SUBop3cc, src1, 0, 0); insn++;
1446
1447         insn->branch.op = 0;
1448         insn->branch.cond = BEcond;
1449         insn->branch.op2 = BICCop2;
1450         insn->branch.anneal = false;
1451         insn->branch.disp22 = dest/4;
1452         insn++;
1453
1454         generateNOOP(insn);
1455         base += sizeof(instruction)*3;
1456         return(base - 2*sizeof(instruction));
1457         }
1458       case branchOp: {
1459         // Unconditional branch
1460         generateBranchInsn(insn, dest); insn++;
1461
1462         generateNOOP(insn);
1463         base += sizeof(instruction)*2;
1464         return(base - 2*sizeof(instruction));
1465         }
1466       case trampPreamble: {
1467 #ifdef ndef
1468         // save and restore are done in the base tramp now
1469         genImmInsn(insn, SAVEop3, REG_SPTR, -112, REG_SPTR);
1470         base += sizeof(instruction);
1471         insn++;
1472
1473         // generate code to save global registers
1474         for (unsigned u = 0; u < 4; u++) {
1475           genStoreD(insn, 2*u, REG_FPTR, - (8 + 8*u));
1476           base += sizeof(instruction);
1477           insn++;
1478         }
1479 #endif
1480         return(0);      // let's hope this is expected!
1481         }
1482       case trampTrailer: {
1483 #ifdef ndef
1484         // save and restore are done in the base tramp now
1485         // generate code to restore global registers
1486         for (unsigned u = 0; u < 4; u++) {
1487           genLoadD(insn, REG_FPTR, - (8 + 8*u), 2*u);
1488           base += sizeof(instruction);
1489           insn++;
1490         }
1491
1492         // sequence: restore; nop; b,a back to base tramp; nop
1493         // we can do better.  How about putting the restore in
1494         // the delay slot of the branch instruction, as in:
1495         // b <back to base tramp>; restore
1496         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); 
1497         base += sizeof(instruction);
1498         insn++;
1499
1500         generateNOOP(insn);
1501         base += sizeof(instruction);
1502         insn++;
1503 #endif
1504         // dest is in words of offset and generateBranchInsn is bytes offset
1505         generateBranchInsn(insn, dest << 2);
1506         base += sizeof(instruction);
1507         insn++;
1508
1509         // add no-op, SS-5 sometimes seems to try to decode this insn - jkh 2/14
1510         generateNOOP(insn);
1511         insn++;
1512         base += sizeof(instruction);
1513
1514         return(base -  2 * sizeof(instruction));
1515         }
1516       default:
1517         abort();        // unexpected op for this emit!
1518     }
1519 }
1520
1521 /****************************************************************************/
1522 /****************************************************************************/
1523 /****************************************************************************/
1524
1525 Register emitR(opCode op, Register src1, Register /*src2*/, Register dest, 
1526                char *i, Address &base, bool /*noCost*/,
1527                const instPoint * /* location */ )
1528 {
1529     //fprintf(stderr,"emitR(op=%d,src1=%d,src2=XX,dest=XX)\n",op,src1);
1530
1531     instruction *insn = (instruction *) ((void*)&i[base]);
1532
1533     switch(op) {
1534       case getParamOp: {
1535 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1536         // saving CT/vector address on the stack
1537         generateStore(insn, REG_MT_POS, REG_FPTR, -40);
1538         insn++; base += sizeof(instruction);
1539 #endif
1540         // We have managed to emit two saves since the entry point of
1541         // the function, so the first 6 parameters are in the previous
1542         // frame's I registers, and we need to pick them off the stack
1543
1544         // generate the FLUSHW instruction to make sure that previous
1545         // windows are written to the register save area on the stack
1546         if (isUltraSparc()) {
1547             generateFlushw(insn);
1548         }
1549         else {
1550             generateTrapRegisterSpill(insn);
1551         }
1552         insn++; base += sizeof(instruction);
1553         
1554         if (src1 < 6) {
1555             // The arg is in a previous frame's I register. Get it from
1556             // the register save area
1557             generateLoad(insn, REG_FPTR, 4*8 + 4*src1, dest);
1558             insn++; base += sizeof(instruction);
1559         }
1560         else {
1561             // The arg is on the stack, two frames above us. Get the previous
1562             // FP (i6) from the register save area
1563             generateLoad(insn, REG_FPTR, 4*8 + 4*6, dest);
1564             // old fp is in dest now
1565             insn++; base += sizeof(instruction);
1566
1567             // Finally, load the arg from the stack
1568             generateLoad(insn, dest, 92 + 4 * (src1 - 6), dest);
1569             insn++; base += sizeof(instruction);
1570         }
1571
1572 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1573         // restoring CT/vector address back in REG_MT_POS
1574         generateLoad(insn, REG_FPTR, -40, REG_MT_POS);
1575         insn++; base += sizeof(instruction);
1576 #endif
1577         
1578         return dest;
1579       }
1580     case getSysParamOp: {
1581         // We have emitted one save since the entry point of
1582         // the function, so the first 6 parameters are in this
1583         // frame's I registers
1584         if (src1 < 6) {
1585             // Param is in an I register
1586             return(REG_I(src1));
1587         }       
1588         else {
1589             // Param is on the stack
1590             generateLoad(insn, REG_FPTR, 92 + 4 * (src1 - 6), dest);
1591             insn++; base += sizeof(instruction);
1592             return dest;
1593         }
1594     }
1595     case getRetValOp: {
1596         // We have emitted one save since the exit point of
1597         // the function, so the return value is in the previous frame's
1598         // I0, and we need to pick it from the stack
1599
1600         // generate the FLUSHW instruction to make sure that previous
1601         // windows are written to the register save area on the stack
1602         if (isUltraSparc()) {
1603             generateFlushw(insn);
1604         }
1605         else {
1606             generateTrapRegisterSpill(insn);
1607         }
1608         insn++; base += sizeof(instruction);
1609
1610         generateLoad(insn, REG_FPTR, 4*8, dest); 
1611         insn++; base += sizeof(instruction);
1612
1613         return dest;
1614     }
1615     case getSysRetValOp:
1616         return(REG_I(0));
1617     default:
1618         abort();        // unexpected op for this emit!
1619     }
1620 }
1621
1622 #ifdef BPATCH_LIBRARY
1623 void emitJmpMC(int condition, int offset, char* baseInsn, Address &base)
1624 {
1625   // Not needed for memory instrumentation, otherwise TBD
1626 }
1627
1628 // VG(12/02/01): Emit code to add the original value of a register to
1629 // another. The original value may need to be restored somehow...
1630 static inline void emitAddOriginal(Register src, Register acc, 
1631                             char* baseInsn, Address &base, bool noCost)
1632 {
1633 // Plan:
1634 // ignore g0 (r0), since we would be adding 0.
1635 // get    g1-g4 (r1-r4) from stack (where the base tramp saved them)
1636 // get    g5-g7 (r5-r7) also from stack, but issue an warning because
1637 // the SPARC psABI cleary states that G5-G7 SHOULD NOT BE EVER WRITTEN
1638 // in userland, as they may be changed arbitrarily by signal handlers!
1639 // So AFAICT it doesn't make much sense to read them...
1640 // get o0-o7 (r8-r15) by "shifting" the window back (i.e. get r24-r31)
1641 // get l0-l7 (r16-23) by flushing the register window to stack
1642 //                    and geeting them from there
1643 // get i0-i7 (r24-31) by --"--
1644 // Note: The last two may seem slow, but they're async. trap safe this way
1645
1646 // All this is coded as a binary search.
1647
1648   bool mustFree = false;
1649   instruction *insn = (instruction *) ((void*)&baseInsn[base]);
1650   Register temp;
1651
1652   if (src >= 16) {
1653     // VG(12/06/01): Currently saving registers on demand is NOT
1654     // implemented on SPARC (dumps assert), so we can safely ignore it
1655     temp = regSpace->allocateRegister(baseInsn, base, noCost);
1656     mustFree = true;
1657
1658     // Cause repeated spills, till all windows but current are clear
1659     generateFlushw(insn); // only ultraSPARC supported here
1660     insn++;
1661     base += sizeof(instruction);
1662
1663     // the spill trap puts these at offset from the previous %sp now %fp (r30)
1664     unsigned offset = (src-16) * sizeof(long); // FIXME for 64bit mutator/32bit mutatee
1665     generateLoad(insn, 30, offset, temp);
1666     insn++;
1667     base += sizeof(instruction);
1668   }
1669   else if (src >= 8)
1670     temp = src + 16;
1671   else if (src >= 1) {
1672     // VG(12/06/01): Currently saving registers on demand is NOT
1673     // implemented on SPARC (dumps assert), so we can safely ignore it
1674     temp = regSpace->allocateRegister(baseInsn, base, noCost);
1675     mustFree = true;
1676
1677     // the base tramp puts these at offset from %fp (r30)
1678     unsigned offset = ((src%2) ? src : (src+2)) * -sizeof(long); // FIXME too
1679     generateLoad(insn, 30, offset, temp);
1680     insn++;
1681     base += sizeof(instruction);
1682
1683     if (src >= 5)
1684       logLine("SPARC WARNING: Restoring original value of g5-g7 is unreliable!");
1685   }
1686   else // src == 0
1687     return;
1688
1689   // add temp to dest;
1690   // writes at baseInsn+base and updates base, we must update insn...
1691   emitV(plusOp, temp, acc, acc, baseInsn, base, noCost, 0);
1692   insn = (instruction *) ((void*)&baseInsn[base]);
1693
1694   if(mustFree)
1695     regSpace->freeRegister(temp);
1696 }
1697
1698 // VG(11/30/01): Load in destination the effective address given
1699 // by the address descriptor. Used for memory access stuff.
1700 void emitASload(BPatch_addrSpec_NP as, Register dest, char* baseInsn,
1701                 Address &base, bool noCost)
1702 {
1703   //instruction *insn = (instruction *) ((void*)&baseInsn[base]);
1704   int imm = as.getImm();
1705   int ra  = as.getReg(0);
1706   int rb  = as.getReg(1);
1707   
1708   // TODO: optimize this to generate the minimum number of
1709   // instructions; think about schedule
1710
1711   // emit code to load the immediate (constant offset) into dest; this
1712   // writes at baseInsn+base and updates base, we must update insn...
1713   emitVload(loadConstOp, (Address)imm, dest, dest, baseInsn, base, noCost);
1714   //insn = (instruction *) ((void*)&baseInsn[base]);
1715   
1716   // If ra is used in the address spec, allocate a temp register and
1717   // get the value of ra from stack into it
1718   if(ra > -1)
1719     emitAddOriginal(ra, dest, baseInsn, base, noCost);
1720
1721   // If rb is used in the address spec, allocate a temp register and
1722   // get the value of ra from stack into it
1723   if(rb > -1)
1724     emitAddOriginal(rb, dest, baseInsn, base, noCost);
1725 }
1726
1727 void emitCSload(BPatch_addrSpec_NP as, Register dest, char* baseInsn,
1728                 Address &base, bool noCost)
1729 {
1730   emitASload(as, dest, baseInsn, base, noCost);
1731 }
1732 #endif
1733
1734 /****************************************************************************/
1735 /****************************************************************************/
1736 /****************************************************************************/
1737
1738 //
1739 // load the original FP (before the dyninst saves) into register dest
1740 //
1741 int getFP(instruction *insn, Register dest)
1742 {
1743     genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1744     insn++;
1745
1746     generateStore(insn, REG_FPTR, REG_SPTR, 68); 
1747     insn++;
1748           
1749     genImmInsn(insn, SAVEop3, REG_SPTR, -112, REG_SPTR);
1750     insn++;
1751
1752     generateLoad(insn, REG_SPTR, 112+68, dest); 
1753     insn++;
1754
1755     return(4*sizeof(instruction));
1756 }
1757
1758 /****************************************************************************/
1759 /****************************************************************************/
1760 /****************************************************************************/
1761
1762 void emitVload(opCode op, Address src1, Register src2, Register dest, 
1763               char *i, Address &base, bool /*noCost*/, int /* size */)
1764 {
1765     instruction *insn = (instruction *) ((void*)&i[base]);
1766
1767     if (op == loadConstOp) {
1768       // dest = src1:imm    TODO
1769
1770       if ((src1) > ( unsigned )MAX_IMM13 || (src1) < ( unsigned )MIN_IMM13) {
1771             // src1 is out of range of imm13, so we need an extra instruction
1772             generateSetHi(insn, src1, dest);
1773             base += sizeof(instruction);
1774             insn++;
1775
1776             // or regd,imm,regd
1777
1778             // Chance for optimization: we should check for LOW10(src1)==0,
1779             // and if so, don't generate the following bitwise-or instruction,
1780             // since in that case nothing would be done.
1781
1782             genImmInsn(insn, ORop3, dest, LOW10(src1), dest);
1783             base += sizeof(instruction);
1784         } else {
1785             // really or %g0,imm,regd
1786             genImmInsn(insn, ORop3, 0, src1, dest);
1787
1788             base += sizeof(instruction);
1789         }
1790     } else if (op ==  loadOp) {
1791         // dest = [src1]   TODO
1792         generateSetHi(insn, src1, dest);
1793         insn++;
1794
1795         generateLoad(insn, dest, LOW10(src1), dest);
1796
1797         base += sizeof(instruction)*2;
1798     } else if (op ==  loadFrameRelativeOp) {
1799         // return the value that is FP offset from the original fp
1800         //   need to restore old fp and save it on the stack to get at it.
1801
1802         base += getFP(insn, dest);
1803         insn = (instruction *) ((void*)&i[base]);
1804         if (((int) src1 < MIN_IMM13) || ((int) src1 > MAX_IMM13)) {
1805             // offsets are signed!
1806             int offset = (int) src1;
1807
1808             // emit sethi src2, offset
1809             generateSetHi(insn, offset, src2);
1810             base += sizeof(instruction);
1811             insn++;
1812
1813             // or src2, offset, src2
1814             genImmInsn(insn, ORop3, src2, LOW10(offset), src2);
1815             base += sizeof(instruction);
1816             insn++;
1817
1818             // add dest, src2, dest
1819             genSimpleInsn(insn, ADDop3, dest, src2, src2);
1820             base += sizeof(instruction);
1821             insn++;
1822
1823             generateLoad(insn, src2, 0, dest);
1824             insn++;
1825             base += sizeof(instruction);
1826         }  else {
1827             generateLoad(insn, dest, src1, dest);
1828             insn++;
1829             base += sizeof(instruction);
1830         }
1831     } else if (op == loadFrameAddr) {
1832         // offsets are signed!
1833         int offset = (int) src1;
1834
1835         base += getFP(insn, dest);
1836         insn = (instruction *) ((void*)&i[base]);
1837
1838         if (((int) offset < MIN_IMM13) || ((int) offset > MAX_IMM13)) {
1839             // emit sethi src2, offset
1840             generateSetHi(insn, offset, src2);
1841             base += sizeof(instruction);
1842             insn++;
1843
1844             // or src2, offset, src2
1845             genImmInsn(insn, ORop3, src2, LOW10(offset), src2);
1846             base += sizeof(instruction);
1847             insn++;
1848
1849             // add dest, src2, dest
1850             genSimpleInsn(insn, ADDop3, dest, src2, dest);
1851             base += sizeof(instruction);
1852             insn++;
1853         }  else {
1854             // fp is in dest, just add the offset
1855             genImmInsn(insn, ADDop3, dest, offset, dest);
1856             insn++;
1857             base += sizeof(instruction);
1858         }
1859     } else {
1860         abort();       // unexpected op for this emit!
1861     }
1862 }
1863
1864 /****************************************************************************/
1865 /****************************************************************************/
1866 /****************************************************************************/
1867
1868 void emitVstore(opCode op, Register src1, Register src2, Address dest, 
1869               char *i, Address &base, bool /*noCost*/, int /* size */)
1870 {
1871     instruction *insn = (instruction *) ((void*)&i[base]);
1872
1873     if (op == storeOp) {
1874         insn->sethi.op = FMT2op;
1875         insn->sethi.rd = src2;
1876         insn->sethi.op2 = SETHIop2;
1877         insn->sethi.imm22 = HIGH22(dest);
1878         insn++;
1879
1880         generateStore(insn, src1, src2, LOW10(dest));
1881
1882         base += sizeof(instruction)*2;
1883     } else if (op == storeFrameRelativeOp) {
1884         // offsets are signed!
1885         int offset = (int) dest;
1886
1887         base += getFP(insn, src2);
1888         insn = (instruction *) ((void*)&i[base]);
1889
1890         if ((offset < MIN_IMM13) || (offset > MAX_IMM13)) {
1891             // We are really one regsiter short here, so we put the
1892             //   value to store onto the stack for part of the sequence
1893             generateStore(insn, src1, REG_SPTR, 112+68);
1894             base += sizeof(instruction);
1895             insn++;
1896
1897             generateSetHi(insn, offset, src1);
1898             base += sizeof(instruction);
1899             insn++;
1900
1901             genImmInsn(insn, ORop3, src1, LOW10(offset), src1);
1902             base += sizeof(instruction);
1903             insn++;
1904
1905             genSimpleInsn(insn, ADDop3, src1, src2, src2);
1906             base += sizeof(instruction);
1907             insn++;
1908
1909             generateLoad(insn, REG_SPTR, 112+68, src1); 
1910             base += sizeof(instruction);
1911             insn++;
1912
1913             generateStore(insn, src1, src2, 0);
1914             base += sizeof(instruction);
1915             insn++;
1916         } else {
1917             generateStore(insn, src1, src2, offset);
1918             insn++;
1919             base += sizeof(instruction);
1920         }
1921     } else {
1922         abort();       // unexpected op for this emit!
1923     }
1924 }
1925
1926 /****************************************************************************/
1927 /****************************************************************************/
1928 /****************************************************************************/
1929
1930 void emitVupdate(opCode op, RegValue src1, Register /*src2*/, Address dest, 
1931               char *i, Address &base, bool noCost)
1932 {
1933     instruction *insn = (instruction *) ((void*)&i[base]);
1934
1935     if (op == updateCostOp) {
1936         // generate code to update the observed cost.
1937         if (!noCost) {
1938            // sethi %hi(dest), %l0
1939            generateSetHi(insn, dest, REG_L(0));
1940            base += sizeof(instruction);
1941            insn++;
1942   
1943            // ld [%l0+ lo(dest)], %l1
1944            generateLoad(insn, REG_L(0), LOW10(dest), REG_L(1));
1945            base += sizeof(instruction);
1946            insn++;
1947   
1948            // update value (src1 holds the cost, in cycles; e.g. 19)
1949            if (src1 <= MAX_IMM13) {
1950               genImmInsn(insn, ADDop3, REG_L(1), src1, REG_L(1));
1951               base += sizeof(instruction);
1952               insn++;
1953
1954               generateNOOP(insn);
1955               base += sizeof(instruction);
1956               insn++;
1957
1958               generateNOOP(insn);
1959               base += sizeof(instruction);
1960               insn++;
1961            } else {
1962               // load in two parts
1963               generateSetHi(insn, src1, REG_L(2));
1964               base += sizeof(instruction);
1965               insn++;
1966
1967               // or regd,imm,regd
1968               genImmInsn(insn, ORop3, REG_L(2), LOW10(src1), REG_L(2));
1969               base += sizeof(instruction);
1970               insn++;
1971
1972               // now add it
1973               genSimpleInsn(insn, ADDop3, REG_L(1), REG_L(2), REG_L(1));
1974               base += sizeof(instruction);
1975               insn++;
1976            }
1977   
1978            // store result st %l1, [%l0+ lo(dest)];
1979            generateStore(insn, REG_L(1), REG_L(0), LOW10(dest));
1980            base += sizeof(instruction);
1981            insn++;
1982         }
1983     } else {
1984         abort();       // unexpected op for this emit!
1985     }
1986 }
1987
1988 /****************************************************************************/
1989 /****************************************************************************/
1990 /****************************************************************************/
1991
1992 void emitV(opCode op, Register src1, Register src2, Register dest, 
1993               char *i, Address &base, bool /*noCost*/, int /* size */,
1994               const instPoint * /* location */, process * /* proc */,
1995               registerSpace * /* rs */ )
1996 {
1997     //fprintf(stderr,"emitV(op=%d,src1=%d,src2=%d,dest=%d)\n",op,src1,src2,dest);
1998
1999     assert ((op!=branchOp) && (op!=ifOp) && 
2000             (op!=trampTrailer) && (op!=trampPreamble));         // !emitA
2001     assert ((op!=getRetValOp) && (op!=getSysRetValOp) &&
2002             (op!=getParamOp) && (op!=getSysParamOp));           // !emitR
2003     assert ((op!=loadOp) && (op!=loadConstOp));                 // !emitVload
2004     assert ((op!=storeOp));                                     // !emitVstore
2005     assert ((op!=updateCostOp));                                // !emitVupdate
2006
2007     instruction *insn = (instruction *) ((void*)&i[base]);
2008
2009     if (op == loadIndirOp) {
2010         generateLoad(insn, src1, 0, dest);
2011         base += sizeof(instruction);
2012     } else if (op == storeIndirOp) {
2013         generateStore(insn, src1, dest, 0);
2014         base += sizeof(instruction);
2015     } else if (op == noOp) {
2016         generateNOOP(insn);
2017         base += sizeof(instruction);
2018     } else if (op == saveRegOp) {
2019         // should never be called for this platform.
2020         // VG(12/02/01): Unfortunately allocateRegister *may* call this
2021         abort();
2022     } else {
2023       int op3=-1;
2024         switch (op) {
2025             // integer ops
2026             case plusOp:
2027                 op3 = ADDop3;
2028                 break;
2029
2030             case minusOp:
2031                 op3 = SUBop3;
2032                 break;
2033
2034             case timesOp:
2035                 op3 = SMULop3;
2036                 break;
2037
2038             case divOp:
2039                 op3 = SDIVop3;
2040                 //need to set the Y register to Zero, Zhichen
2041                 genImmInsn(insn, WRYop3, REG_G(0), 0, 0);
2042                 base += sizeof(instruction);
2043                 insn = (instruction *) ((void*)&i[base]);
2044                 break;
2045
2046             // Bool ops
2047             case orOp:
2048                 op3 = ORop3;
2049                 break;
2050
2051             case andOp:
2052                 op3 = ANDop3;
2053                 break;
2054
2055             // rel ops
2056             // For a particular condition (e.g. <=) we need to use the
2057             // the opposite in order to get the right value (e.g. for >=
2058             // we need BLTcond) - naim
2059             case eqOp:
2060                 genRelOp(insn, BNEcond, src1, src2, dest, base);
2061                 return;
2062                 break;
2063
2064             case neOp:
2065                 genRelOp(insn, BEcond, src1, src2, dest, base);
2066                 return;
2067                 break;
2068
2069             case lessOp:
2070                 genRelOp(insn, BGEcond, src1, src2, dest, base);
2071                 return;
2072                 break;
2073
2074             case leOp:
2075                 genRelOp(insn, BGTcond, src1, src2, dest, base);
2076                 return;
2077                 break;
2078
2079             case greaterOp:
2080                 genRelOp(insn, BLEcond, src1, src2, dest, base);
2081                 return;
2082                 break;
2083
2084             case geOp:
2085                 genRelOp(insn, BLTcond, src1, src2, dest, base);
2086                 return;
2087                 break;
2088
2089             default:
2090                 abort();
2091                 break;
2092         }
2093         genSimpleInsn(insn, op3, src1, src2, dest);
2094
2095         base += sizeof(instruction);
2096       }
2097    return;
2098 }
2099
2100 /****************************************************************************/
2101 /****************************************************************************/
2102
2103 static inline bool isRestoreInsn(instruction i) {
2104     return (i.rest.op == 2 \
2105                && ((i.rest.op3 == ORop3 && i.rest.rd == 15)
2106                        || i.rest.op3 == RESTOREop3));
2107 }
2108
2109 /****************************************************************************/
2110 /****************************************************************************/
2111
2112 static inline bool CallRestoreTC(instruction instr, instruction nexti) {
2113     return (isCallInsn(instr) && isRestoreInsn(nexti));
2114 }
2115
2116 /****************************************************************************/
2117 /****************************************************************************/
2118
2119
2120 /*
2121     Return bool value indicating whether instruction sequence
2122      found signals tail-call jmp; nop; sequence.  Note that this should 
2123      NOT include jmpl; nop;, ret; nop;, retl; nop;....
2124
2125     Current heuristic to detect such sequences :
2126      look for jmp %reg, nop in function w/ no stack frame, if jmp, nop
2127      are last 2 instructions, return true (definate TC), at any other point,
2128      return false (not TC).  Otherwise, return false (no TC).
2129      w/ no stack frame....
2130     instr is instruction being examioned.
2131     nexti is instruction after
2132     addr is address of <instr>
2133     func is pointer to function class object describing function
2134      instructions come from....
2135  */
2136 static inline bool JmpNopTC(instruction instr, instruction nexti,
2137                             Address addr, pd_Function *func) {
2138
2139     if (!isInsnType(instr, JMPLmask, JMPLmatch)) {
2140         return 0;
2141     }
2142
2143     assert(instr.resti.op3 == 0x38);
2144
2145     // only looking for jump instructions which don't overwrite a register
2146     //  with the PC which the jump comes from (g0 is hardwired to 0, so a write
2147     //  there has no effect?)....  
2148     //  instr should have gdb disass syntax : 
2149     //      jmp  %reg, 
2150     //  NOT jmpl %reg1, %reg2
2151     if (instr.resti.rd != REG_G(0)) {
2152         return 0;
2153     }
2154
2155     // only looking for jump instructions in which the destination is
2156     //  NOT %i7 + 8/12/16 or %o7 + 8/12/16 (ret and retl synthetic 
2157     //  instructions, respectively)
2158     if (instr.resti.i == 1) {
2159         if (instr.resti.rs1 == REG_I(7) || instr.resti.rs1 == REG_O(7)) {
2160             // NOTE : some return and retl instructions jump to {io}7 + 12,
2161             //  or (io)7 + 16, not + 8, to have some extra space to store the size of a 
2162             //  return structure....
2163             if (instr.resti.simm13 == 0x8 || instr.resti.simm13 == 12 ||
2164                     instr.resti.simm13 == 16) {
2165                 return 0;
2166             }
2167         }
2168     }  
2169
2170     // jmp, foloowed by NOP....
2171     if (!isNopInsn(nexti)) {
2172         return 0;
2173     }
2174
2175     // in function w/o stack frame....
2176     if (!func->hasNoStackFrame()) {
2177         return 0;
2178     }
2179
2180     // if sequence is detected, but not at end of fn 
2181     //  (last 2 instructions....), return value indicating possible TC.
2182     //  This should (eventually) mark the fn as uninstrumenatble....
2183     if (addr != (func->getAddress(0) + func->size() - 8)) {
2184         return 0;
2185     }
2186
2187     return 1;
2188 }
2189
2190 /****************************************************************************/
2191 /****************************************************************************/
2192 /****************************************************************************/
2193
2194 /*
2195   Is the specified call instruction one whose goal is to set the 07 register
2196   (the sequence of execution is as if the call instruction did not change the
2197   control flow, and the O7 register is set)?
2198
2199   here, we define a call whose goal is to set the 07 regsiter
2200     as one where the target is the call address + 8, AND where that
2201     target is INSIDE the same function (need to make sure to check for that
2202     last case also, c.f. function DOW, which ends with):
2203      0xef601374 <DOW+56>:    call  0xef60137c <adddays>
2204      0xef601378 <DOW+60>:    restore 
2205
2206   instr - raw instruction....
2207   functionSize - size of function (in bytes, NOT # instructions)....
2208   instructionOffset - BYTE offset in function at which instr occurs....
2209  */        
2210 static inline bool is_set_O7_call(instruction instr, unsigned functionSize, 
2211                               unsigned instructionOffset) {
2212     // if the instruction is call %register, assume that it is NOT a 
2213     //  call designed purely to set %O7....
2214     if(instr.call.op != CALLop) {
2215         return false;
2216     }
2217     if (((instr.call.disp30 << 2) == 8) && 
2218              (instructionOffset < (functionSize - 2 * sizeof(instruction)))) {
2219         return true; 
2220     }
2221     return false; 
2222 }  
2223
2224 /****************************************************************************/
2225 /****************************************************************************/
2226 /****************************************************************************/
2227
2228 /*
2229     Does the specified call instruction call to target inside function
2230     or outside - may be indeterminate if insn is call %reg instead of 
2231     call <address> (really call PC + offset)
2232     Note: (recursive) calls back to the beginning of the function are OK
2233     since we really want to consider these as instrumentable call sites!
2234  */
2235 enum fuzzyBoolean {eFalse = 0, eTrue = 1, eDontKnow = 2}; 
2236
2237 static enum fuzzyBoolean is_call_outside_function(const instruction instr,
2238                 const Address functionStarts, const Address instructionAddress, 
2239                 const unsigned int functionSize) 
2240 {
2241     // call %register - don't know if target inside function....
2242     if(instr.call.op != CALLop) {
2243         return eDontKnow;
2244     }
2245     const Address call_target = instructionAddress + (instr.call.disp30 << 2);
2246     if ((call_target > functionStarts) && 
2247         (call_target < (functionStarts + functionSize))) {
2248         return eFalse;
2249     }
2250     return eTrue;
2251 }
2252
2253
2254 /****************************************************************************/
2255 /****************************************************************************/
2256 /****************************************************************************/
2257
2258 /*
2259  * Find the instPoints of this function.
2260  */
2261 bool pd_Function::findInstPoints(const image *owner) {
2262
2263   Address firstAddress = getAddress(0);
2264   Address lastAddress = getAddress(0) + size();
2265   Address adr;
2266   Address target;
2267   Address entry;
2268   Address disp;
2269
2270   instruction instr; 
2271   instruction nexti;
2272
2273   instPoint *point = 0;
2274
2275   // For determining if function needs relocation to be instrumented
2276   relocatable_ = false;
2277   mayNeedRelocation_ = false;
2278   canBeRelocated_ = true;
2279
2280   // Initially assume function has no stack frame 
2281   noStackFrame = true;
2282
2283   // variables for function parameters
2284   const instPoint *blah = 0;
2285   
2286   bool dummyParam;
2287
2288   // Ids for instPoints
2289   unsigned retId = 0;
2290   unsigned callsId = 0; 
2291
2292   if (size() == 0) {
2293     return false;
2294   } 
2295
2296   instr.raw = owner->get_instruction(firstAddress);
2297   if (!IS_VALID_INSN(instr)) {
2298     return false;
2299   }
2300
2301   // Determine if function needs to be relocated when instrumented
2302   for ( adr = firstAddress; adr < lastAddress; adr += 4) { 
2303     instr.raw = owner->get_instruction(adr);
2304     nexti.raw = owner->get_instruction(adr+4);
2305
2306     // If there's an TRAP instruction in the function, we assume
2307     // that it is an system call and will relocate it to the heap
2308     if (isInsnType(instr, TRAPmask, TRAPmatch)) {
2309       relocatable_ = true;
2310     } 
2311
2312     // TODO: This is a hacking for the solaris(solaris2.5 actually)
2313     // We will relocate that function if the function has been 
2314     // tail-call optimazed.
2315     // (Actully, the reason of this is that the system calls like 
2316     //  read, write, etc have the tail-call optimazation to call
2317     //  the _read, _write etc. which contain the TRAP instruction 
2318     //  This is only done if libc is statically linked...if the
2319     //  libTag is set, otherwise we instrument read and _read
2320     //  both for the dynamically linked case
2321     // New for Solaris 2.6 support - new form of tail-call opt-
2322     //  imization found:
2323     //   jmp %register
2324     //   nop
2325     //  as last 2 instructions in function which does not have
2326     //  own register frame.
2327     if (CallRestoreTC(instr, nexti) || JmpNopTC(instr, nexti, adr, this)) {
2328       relocatable_ = true;
2329     }
2330
2331     // if call is directly to a retl, this is not a real call, but
2332     // is instead used to set the o7 register. Set the function to be
2333     // relocated when instrumented.
2334     if (isCallInsn(instr)) {
2335
2336       // find target address of call
2337       disp = instr.call.disp30 << 2;
2338       target = adr + disp;
2339
2340       // get target instruction of the call   
2341       instruction tmpInsn;
2342       tmpInsn.raw = owner->get_instruction( target );
2343
2344       if((tmpInsn.raw & 0xfffff000) == 0x81c3e000) {
2345         mayNeedRelocation_ = true;
2346       }
2347
2348       // if this is a call instr to a location within the function, 
2349       // and if the offest is 8 then this is used to set the o7 register
2350       // with the pc and we may need to relocate the function 
2351       if ( is_set_O7_call(instr, size(), adr - firstAddress)) {
2352         mayNeedRelocation_ = true;
2353       }
2354     }
2355   }
2356
2357
2358   /* FIND FUNCTION ENTRY */
2359
2360
2361   entry = firstAddress;
2362   for (adr = firstAddress; adr < lastAddress; adr += 4) { 
2363
2364     // The function Entry is defined as the first SAVE instruction plus
2365     // the instructions after this.
2366     // ( The first instruction for the nonleaf function is not 
2367     //   necessarily a SAVE instruction. ) 
2368     instr.raw = owner->get_instruction(adr);
2369
2370     if (isInsnType(instr, SAVEmask, SAVEmatch)) {
2371       entry = adr;
2372       noStackFrame = false;
2373       continue;
2374     }
2375   }
2376
2377
2378   // If there's no SAVE instruction found, this is a leaf function
2379   // and function Entry will be defined from the first instruction
2380   if (noStackFrame) {
2381
2382     // noStackFrame, apparently leaf function
2383     adr = firstAddress;
2384     entry = adr;
2385   }
2386
2387
2388   /* CHECK IF FUNCTION SHOULD NOT BE RELOCATED WHEN INSTRUMENTED */
2389
2390   // FUNCTION TOO SMALL
2391   if (size() <= 3*sizeof(instruction)) {
2392     canBeRelocated_ = false;
2393   }
2394
2395
2396   // Can't handle function
2397   if (canBeRelocated_ == false && relocatable_ == true) {
2398     return false;
2399   }
2400
2401
2402 #ifdef BPATCH_LIBRARY
2403   if (BPatch::bpatch->hasForcedRelocation_NP()) {
2404     if (canBeRelocated_ == true) {
2405       relocatable_ = true;
2406     }
2407   }
2408 #endif
2409
2410   o7_live = false;
2411
2412   /* CREATE ENTRY INSTPOINT */
2413   instr.raw = owner->get_instruction(entry);
2414
2415   funcEntry_ = new instPoint(this, owner, entry, true, functionEntry);
2416   assert(funcEntry_);
2417
2418   // ITERATE OVER INSTRUCTIONS, locating instPoints
2419   adr = firstAddress;
2420
2421   instructions = new instruction[size()/sizeof(instruction)];
2422  
2423   for (int i=0; adr < lastAddress; adr += sizeof(instruction), i++) {
2424
2425     instr.raw = owner->get_instruction(adr);
2426     instructions[i] = instr;
2427     nexti.raw = owner->get_instruction(adr+4);
2428
2429     if(!o7_live){
2430       InsnRegister rd,rs1,rs2;
2431       get_register_operands(instr,&rd,&rs1,&rs2);
2432
2433       if(rs1.is_o7() || rs2.is_o7())// ||
2434         // (rd.is_o7() && 
2435         //  ((instr.raw & 0xc1f80000) != 0x81c00000))) /*indirect call*/
2436               o7_live = true;
2437     }
2438
2439     // check for return insn and as a side, decide if we are at the
2440     // end of the function.
2441     if (isReturnInsn(owner, adr, dummyParam, prettyName())) {
2442       // define the return point
2443
2444       instPoint *point;
2445       point = new instPoint(this, owner, adr, false, functionExit);
2446       funcReturns.push_back(point);
2447       funcReturns[retId] -> instId = retId; retId++;
2448     } 
2449     
2450     else if (instr.branch.op == 0      
2451               &&  (instr.branch.op2 == 2 || instr.branch.op2 == 6) 
2452               && (instr.branch.cond == 0 || instr.branch.cond == 8)) {
2453
2454       // find if this branch is going out of the function
2455       disp = instr.branch.disp22;
2456       Address target = adr +  (disp << 2);
2457          
2458       if (target < firstAddress || target >= lastAddress) {
2459
2460         instPoint *point;
2461         point = new instPoint(this, owner, adr, false, functionExit);
2462
2463         if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
2464
2465           point->isBranchOut = true;
2466           point->branchTarget = target;
2467         }
2468
2469         funcReturns.push_back(point);
2470         funcReturns[retId] -> instId = retId; retId++;
2471
2472       }
2473     } 
2474     
2475     else if (isCallInsn(instr)) {
2476
2477       // if the call target is the address of the call instruction
2478       // then this is not something that we can instrument...
2479       // this occurs in functions with code that is modifined when 
2480       // they are loaded by the run-time linker, or when the .init
2481       // section is executed.  In this case the instructions in the
2482       // parsed image file are different from the ones in the executable
2483       // process.
2484       Address call_target = adr + (instr.call.disp30 << 2);
2485       if(instr.call.op == CALLop) { 
2486         if(call_target == adr){ 
2487           cerr << "WARN : function " << prettyName().c_str()
2488                << " has call to same location as call, NOT instrumenting"
2489                << endl;
2490           return false;
2491         }
2492       }
2493
2494       // first, check for tail-call optimization: a call where the 
2495       // instruction in the delay slot write to register %o7(15), usually 
2496       // just moving the caller's return address, or doing a restore
2497       // Tail calls are instrumented as return points, not call points.
2498
2499       if (CallRestoreTC(instr, nexti)) {
2500
2501         // generate a call instPoint for the call instruction
2502         point = new instPoint(this, owner, adr, false, callSite);
2503
2504         // record the call instPoint in pdFunction's calls vector 
2505         addCallPoint(instr, callsId, 0, point, blah);
2506   
2507         // generate a functionExit instPoint for the tail-call sequence  
2508         // (mark the instruction in the delay slot of the call as the exit)
2509         point = new instPoint(this, owner, adr, false, functionExit);
2510         funcReturns.push_back(point);
2511         funcReturns[retId] -> instId = retId; retId++;
2512
2513       } else {
2514
2515           // check if the call is to inside the function - if definately
2516           // inside function (meaning that thew destination can be determined
2517           // statically because its a call to an address, not to a register 
2518           // or register + offset) then don't instrument as call site, 
2519           // otherwise (meaning that the call destination is known statically 
2520           // to be outside the function, or is not known statically), then 
2521           // instrument as a call site....
2522           enum fuzzyBoolean is_inst_point;
2523           is_inst_point = is_call_outside_function(instr, firstAddress, 
2524                                                            adr, size());
2525           if (is_inst_point == eFalse) {
2526
2527             // if this is a call instr to a location within the function, 
2528             // and if the offest is not 8 then do not define this function 
2529             if (!is_set_O7_call(instr, size(), adr - firstAddress)) {
2530               return false;
2531             }
2532
2533             // generate a call instPoint for the call instruction
2534             point = new instPoint(this, owner, adr, false, callSite);
2535
2536             // record the call instPoint in pdFunction's calls vector 
2537             addCallPoint(instr, callsId, 0, point, blah);
2538
2539           } else {
2540  
2541               // get call target instruction   
2542               Address call_target = adr + (instr.call.disp30 << 2);
2543               instruction tmpInsn;
2544               tmpInsn.raw = owner->get_instruction( call_target );
2545
2546               // check that call is not directly to a retl instruction,
2547               // and thus a real call
2548               if((tmpInsn.raw & 0xfffff000) != 0x81c3e000) {
2549
2550                 // generate a call instPoint for the call instruction
2551                 point = new instPoint(this,  owner, adr, false, callSite);
2552
2553                 // record the call instPoint in pdFunction's calls vector 
2554                 addCallPoint(instr, callsId, 0, point, blah);
2555
2556               } 
2557           }         
2558       }
2559     }
2560
2561     else if (JmpNopTC(instr, nexti, adr, this)) {
2562
2563       // generate a call instPoint for the jump instruction
2564       point = new instPoint(this, owner, adr, false, callSite);
2565
2566       // record the call instPoint in pdFunction's calls vector 
2567       addCallPoint(instr, callsId, 0, point, blah);
2568
2569       // generate a functionExit instPoint for the tail-call sequence  
2570       // (mark the instruction in the delay slot of the jump as the exit)
2571       point = new instPoint(this,  owner, adr, false, functionExit);
2572       funcReturns.push_back(point);
2573       funcReturns[retId] -> instId = retId; retId++;
2574     }
2575
2576     else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
2577        /* A register indirect jump. Some jumps may exit the function 
2578           (e.g. read/write on SunOS). In general, the only way to 
2579           know if a jump is exiting the function is to instrument
2580           the jump to test if the target is outside the current 
2581           function. Instead of doing this, we just check the 
2582           previous two instructions, to see if they are loading
2583           an address that is out of the current function.
2584           This should catch the most common cases (e.g. read/write).
2585           For other cases, we would miss a return point.
2586
2587           This is the case considered:
2588
2589              sethi addr_hi, r
2590              or addr_lo, r, r
2591              jump r
2592         */
2593
2594       Register jumpreg = instr.rest.rs1;
2595       instruction prev1;
2596       instruction prev2;
2597
2598       prev1.raw = owner->get_instruction(adr-4);
2599       prev2.raw = owner->get_instruction(adr-8);
2600
2601       Address targetAddr;
2602
2603       if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
2604           && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
2605           && prev2.sethi.rd == (unsigned)jumpreg
2606           && prev1.rest.op == RESTop 
2607           && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
2608           && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg) {
2609
2610         targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
2611         targetAddr |= prev1.resti.simm13;
2612
2613         if ( (targetAddr < firstAddress) || (targetAddr >= lastAddress) ){
2614
2615           instPoint *point;
2616           point = new instPoint(this, owner, adr, false, functionExit);
2617
2618           funcReturns.push_back(point);
2619           funcReturns[retId] -> instId = retId; retId++;
2620         }
2621       }
2622     }
2623   }
2624
2625
2626   // For leaf functions, beware of exit points with a DCTI just prior.
2627   // If we can't use a branch instruction (i.e. ba,a) at the exit, we 
2628   // will need to relocate the function.  
2629   if ( hasNoStackFrame() ) {
2630
2631     // Check each return point
2632     for (unsigned j=0; j < funcReturns.size(); j++) {
2633
2634       // Leaf exits always require prior instructions to instrument with
2635       // a save; call; restore; sequence
2636       assert(funcReturns[j]->usesPriorInstructions);
2637
2638       // Check if the first prior instruction is in the delay slot of a
2639       // DCTI, or is an aggregate for a DCTI
2640       if ( (funcReturns[j]->secondPriorIsDCTI) ||
2641            (funcReturns[j]->thirdPriorIsDCTI && 
2642             funcReturns[j]->firstPriorIsAggregate) ) {
2643
2644         mayNeedRelocation_ = true;
2645         continue;
2646       }
2647     }
2648
2649
2650     // Check for branches to the exit point. If there is such a branch,
2651     // we will need to relocate the function and add nops after exit point
2652     // instead of claiming prior instructions
2653     Address insnAddr    = firstAddress;
2654     int num_instructions = size() / sizeof(instruction);
2655  
2656     // Iterate over all instructions
2657     for (int j=0; j < num_instructions; j++) {
2658
2659       // Grab the instruction
2660       instr = instructions[j];
2661
2662       // Check if the instruction is a branch
2663       if ( instr.branch.op == 0 ) {
2664
2665         // find if this branch is going to an exit point
2666         int displacement = instr.branch.disp22;
2667         Address target   = insnAddr + (displacement << 2);
2668
2669         // Check each return point address
2670         for (unsigned k=0; k < funcReturns.size(); k++) {
2671
2672           // Check if the branch target matches the exit point address
2673           if (target == funcReturns[k]->iPgetAddress()) {
2674             mayNeedRelocation_ = true;
2675             continue;
2676           }
2677         }
2678       }
2679
2680       insnAddr += sizeof(instruction);
2681     }
2682   }
2683
2684   bool checkPoints = checkInstPoints(owner);
2685
2686   if ( (checkPoints == false) || (!canBeRelocated_ && relocatable_) ){
2687     return false;
2688   }
2689
2690   return true;
2691 }
2692
2693 /****************************************************************************/
2694 /****************************************************************************/
2695 /****************************************************************************/
2696
2697 /*
2698  * Check all the instPoints within this function to see if there's 
2699  * any conficts happen.
2700  */
2701 bool pd_Function::checkInstPoints(const image *owner) {
2702
2703     // Our own library function, skip the test.
2704     if (prettyName().prefixed_by("DYNINST")) 
2705         return true;
2706
2707 #ifndef BPATCH_LIBRARY /* XXX Users of libdyninstAPI might not agree. */
2708     // The function is too small to be worth instrumenting.
2709     if (size() <= 12){
2710         return false;
2711     }
2712 #endif
2713
2714     // No function return! return false;
2715     if (sizeof(funcReturns) == 0) {
2716         return false;
2717     }
2718
2719     instruction instr;
2720     Address adr = getAddress(0);
2721
2722     bool retl_inst = false;
2723     bool restore_inst = false;
2724     // Check if there's any branch instruction jump to the middle
2725     // of the instruction sequence in the function entry point
2726     // and function exit point.
2727     for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
2728
2729         instr.raw = owner->get_instruction(adr);
2730         if(isInsnType(instr, RETLmask, RETLmatch)) retl_inst = true;
2731         if(isInsnType(instr, RESTOREmask, RESTOREmatch)) restore_inst = true;
2732         if (isInsnType(instr, BRNCHmask, BRNCHmatch)||
2733             isInsnType(instr, FBRNCHmask, FBRNCHmatch)) {
2734
2735             int disp = instr.branch.disp22;
2736             Address target = adr + (disp << 2);
2737
2738             if ((target > funcEntry_->addr)&&
2739                 (target < (funcEntry_->addr + funcEntry_->size))) {
2740                 if (adr > (funcEntry_->addr+funcEntry_->size)){
2741
2742                   // function can be instrumented if we relocate it
2743                   relocatable_ = true;
2744                 }
2745             }
2746
2747             for (u_int i = 0; i < funcReturns.size(); i++) {
2748                 if ((target > funcReturns[i]->addr)&&
2749                     (target < (funcReturns[i]->addr + funcReturns[i]->size))) {
2750                     if ((adr < funcReturns[i]->addr)||
2751                         (adr > (funcReturns[i]->addr + funcReturns[i]->size))){
2752
2753                       // function can be instrumented if we relocate it
2754                       relocatable_ = true; 
2755                     }
2756                 }
2757             }
2758         }
2759     }
2760
2761     // if there is a retl instruction and we don't think this is a leaf
2762     // function then this is a way messed up function...well, at least we
2763     // we can't deal with this...the only example I can find is _cerror
2764     // and _cerror64 in libc.so.1
2765     if(retl_inst && !noStackFrame && !restore_inst){ 
2766         //cerr << "WARN : function " << prettyName().c_str()
2767         //     << " retl instruction in non-leaf function, can't instrument"
2768         //      << endl;
2769         return false;
2770     }
2771
2772     // check that no instrumentation points could overlap
2773     Address func_entry = funcEntry_->addr + funcEntry_->size; 
2774     for (u_int i = 0; i < funcReturns.size(); i++) {
2775         if(func_entry >= funcReturns[i]->addr){
2776
2777           // function can be instrumented if we relocate it 
2778           relocatable_ = true; 
2779         }
2780         if(i >= 1){ // check if return points overlap
2781             Address prev_exit = funcReturns[i-1]->addr+funcReturns[i-1]->size;  
2782             if(funcReturns[i]->addr < prev_exit) {
2783
2784               // function can be instrumented if we relocate it 
2785               relocatable_ = true;
2786             } 
2787         }
2788     }
2789
2790     return true;        
2791 }
2792
2793 /****************************************************************************/
2794 /****************************************************************************/
2795 /****************************************************************************/
2796
2797 // used for sorting inst points - typecast void *s to instPoint **s, then
2798 //  do {-1, 0, 1} comparison by address....
2799 int sort_inst_points_by_address(const void *arg1, const void *arg2) {
2800     instPoint * const *a = static_cast<instPoint* const *>(arg1);
2801     instPoint * const *b = static_cast<instPoint* const *>(arg2);
2802     if ((*a)->iPgetAddress() > (*b)->iPgetAddress()) {
2803         return 1;
2804     } else if ((*a)->iPgetAddress() < (*b)->iPgetAddress()) {
2805         return -1;
2806     }
2807     return 0;
2808 }
2809
2810 /****************************************************************************/
2811 /****************************************************************************/
2812 /****************************************************************************/
2813
2814 /*
2815   First pass, handle cases where general-purpose re-writing needs to be
2816   done to preserve paradynd/dyninstAPI's assumptions about function
2817   structure.  
2818     In current sparc-solaris version, this is ONLY the following cases:
2819       If a call site and return point overlap and are located directly
2820        next to eachother, and the return point is located on a 
2821        restore operation, then a TailCallPA is applied whose footprint
2822        covers the call and the restore.
2823        The TailCallPA should rewrite the call; restore, and update the 
2824        locations of both inst points as necessary.
2825       If the 2nd instruction in a function is a CALL, then a single nop
2826        is inserted before the call - to clear out the delay slot of the
2827        branch which is inserted at the first instruction (for entry point
2828        instrumentation).
2829        If the dyninstAPI is seperated from paradyn, or when converting this 
2830        code to support instrumentation at arbitrary points (instead of assuming
2831        entry, exit, and call site instrumentation), then the check should be 
2832        changed from:
2833          look at 2nd insn, see if its a call
2834         TO
2835          look at all inst points, see if any of them have a call in what
2836          corresponds to the delay slot of the instruction which is going to
2837          get stomped by a branch/call to tramp....
2838       If the code has any calls to address (of call) + 8, replace the call with
2839         a sequence which sets the 07 register to the (original) address....
2840   Function:
2841     Attaches LocalAlterations related to general rewrites of function
2842      (by adding them to LocalAlterationSet p).
2843     returns boolean value indicating whether it was able to figure out
2844     sequence of LocalAlterations to apply to perform specified rewrites....
2845  */
2846 bool pd_Function::PA_attachGeneralRewrites( const image *owner,
2847                                             LocalAlterationSet *p, 
2848                                             Address baseAddress, 
2849                                             Address firstAddress, 
2850                                             instruction loadedCode[], 
2851                                             unsigned /* numInstructions */,
2852                                             int codeSize ) {
2853
2854 #ifdef DEBUG_PA_INST
2855     cerr << "pd_Function::PA_attachGeneralRewrites called" <<endl;
2856     cerr << " prettyName = " << prettyName() << endl;
2857 #endif
2858
2859     assert((codeSize % sizeof(instruction)) == 0);
2860
2861     // Iterate over function instruction by instruction, looking for calls
2862     // made to set the pc
2863     for(unsigned i=0; i < codeSize / sizeof(instruction); i++) {
2864
2865         //  want CALL %address, NOT CALL %register
2866         if (isTrueCallInsn(loadedCode[i])) {
2867
2868             // figure out destination of call....
2869             if (is_set_O7_call(loadedCode[i], codeSize, 
2870                                i * sizeof(instruction))) {
2871
2872                 SetO7 *seto7 = new SetO7(this, i * sizeof(instruction));
2873                 p->AddAlteration(seto7);
2874
2875 #ifdef DEBUG_PA_INST
2876                 cerr << " detected call designed to set 07 register at offset "
2877                      <<  i * sizeof(instruction) << endl;
2878 #endif
2879
2880             } else {
2881
2882                 // Check for a call to a location outside of the function, 
2883                 // where the target of the call is a retl instruction. This 
2884                 // sequence is used to set the o7 register with the PC.
2885
2886                 // Get target of call instruction
2887                 Address callAddress = firstAddress + i*sizeof(instruction);
2888                 Address callTarget  = callAddress + 
2889                                       (loadedCode[i].call.disp30 << 2);
2890
2891                 // If call is to location outside of function              
2892                 if ( (callTarget < firstAddress) || 
2893                      (callTarget > firstAddress + size()) ) { 
2894
2895                   // get target instruction
2896                   instruction tmpInsn;
2897                   tmpInsn.raw = owner->get_instruction(callTarget - baseAddress);
2898                   // If call target instruction is a retl instruction
2899                   if((tmpInsn.raw & 0xfffff000) == 0x81c3e000) {
2900
2901                     // Retrieve the instruction in the delay slot of the retl,
2902                     // so that it can be copied into the relocated function
2903                     tmpInsn.raw = 
2904                     owner->get_instruction( (callTarget - baseAddress) + sizeof(instruction) );
2905
2906                     RetlSetO7 *retlSetO7 = 
2907                         new RetlSetO7(this, i * sizeof(instruction), tmpInsn);
2908                     p->AddAlteration(retlSetO7);
2909
2910 #ifdef DEBUG_PA_INST
2911                     cerr << " detected call to retl instruction"
2912                          << " designed to set 07 register at offset " 
2913                          <<  i * sizeof(instruction) << endl;
2914 #endif
2915                   }
2916                 }
2917             }
2918         }
2919     }
2920
2921
2922     // Special cases for leaf functions
2923     if (hasNoStackFrame()) {
2924
2925       // Since we are already relocating the function, add a nop after the
2926       // return point so that we don't have to use prior instructions to
2927       // instrument the exit.
2928       for(unsigned i=0; i < funcReturns.size(); i++) {
2929
2930         instPoint *point = funcReturns[i];
2931
2932         if (!JmpNopTC(point->firstInstruction, point->secondInstruction,
2933                       point->iPgetAddress() - sizeof(instruction), this) &&
2934             !CallRestoreTC(point->firstInstruction, point->secondInstruction)){
2935
2936             // Offset to insert nop after
2937             int offset;
2938  
2939             offset = ( point->iPgetAddress() + baseAddress + 
2940                        sizeof(instruction) ) - firstAddress;
2941
2942             // Insert a single nop after the exit to the function
2943             InsertNops *exitNops = 
2944                 new InsertNops(this, offset, sizeof(instruction));
2945
2946             p->AddAlteration(exitNops);
2947
2948 #ifdef DEBUG_PA_INST
2949             cerr << "Function: " << prettyName() << " added a single nop "
2950                  << " after exit at offset " << offset << "." << endl;
2951 #endif
2952
2953         }
2954       }
2955     }
2956
2957     return true;
2958 }
2959
2960
2961 bool pd_Function::PA_attachTailCalls(LocalAlterationSet *p) {
2962     instruction instr, nexti;
2963     TailCallOptimization *tail_call;
2964
2965     // previously referred to calls[i] directly, but gdb seems to be having
2966     //  trouble with templated types with the new compiler - making debugging
2967     //  difficult - so, directly assign calls[i] to the_call so can use gdb
2968     //  to get at info about it....
2969     instPoint *the_call;
2970
2971 #ifdef DEBUG_PA_INST
2972     cerr << "pd_Function::PA_tailCallOptimizations called" <<endl;
2973     cerr << " prettyName = " << prettyName() << endl;
2974 #endif
2975
2976
2977     // Look for an instPoint in funcCalls where the instruction is 
2978     //  a call instruction and the next instruction is a restore op
2979     //  or where the instruction is a jmp (out of function?), and the next 
2980     //  instruction is a nop....
2981     for(unsigned i=0; i < calls.size(); i++) {
2982
2983         // this should return the offset at which the FIRST instruction which
2984         //  is ACTUALLY OVEWRITTEN BY INST POINT is located....
2985         the_call = calls[i];
2986         int offset = (the_call->iPgetAddress() - getAddress(0));
2987         instr = the_call->insnAtPoint();
2988         nexti = the_call->insnAfterPoint();
2989         if (CallRestoreTC(instr, nexti)) {
2990             tail_call = new CallRestoreTailCallOptimization(this, offset, 
2991                                    offset + 2 * sizeof(instruction), instr);
2992             p->AddAlteration(tail_call);
2993
2994 #ifdef DEBUG_PA_INST
2995             cerr << " detected call-restore tail-call optimization at offset "
2996                  << offset << endl;
2997 #endif
2998
2999         }
3000         if (JmpNopTC(instr, nexti, the_call->iPgetAddress(), this)) {
3001             tail_call = new JmpNopTailCallOptimization(this, offset, 
3002                                    offset + 2 * sizeof(instruction));
3003             p->AddAlteration(tail_call);
3004
3005 #ifdef DEBUG_PA_INST
3006             cerr << " detected jmp-nop tail-call optimization at offset " 
3007                  << offset << endl;
3008 #endif
3009
3010         }
3011     }
3012
3013     return true;
3014 }
3015
3016 /****************************************************************************/
3017 /****************************************************************************/
3018 /****************************************************************************/
3019
3020 /* 
3021   Second pass, handle cases where inst points overlap eachother (and
3022   thus prevent the normal instrumentation technique from being used).
3023     In current sparc-solaris version, the following algorithm is used:
3024      Check all inst points.  If any overlap, figure out the instruction
3025      that each is trying to get and insert nops so that they no longer
3026      overlap.  
3027 */
3028 bool pd_Function::PA_attachOverlappingInstPoints(
3029                         LocalAlterationSet *p, Address /* baseAddress */, 
3030                         Address /* firstAddress */,
3031                         instruction loadedCode[], int /* codeSize */) {
3032
3033     instruction instr, nexti;
3034
3035 #ifdef DEBUG_PA_INST
3036     cerr << "pd_Function::PA_attachOverlappingInstPoints called" <<endl;
3037     cerr << " prettyName = " << prettyName() << endl;
3038 #endif
3039
3040     // Make a list of all inst-points attached to function, and sort
3041     //  by address.  Then check for overlaps....
3042     pdvector<instPoint*> foo;    
3043     sorted_ips_vector(foo);
3044
3045     // should hopefully have inst points for fn sorted by address....
3046     // check for overlaps....
3047     for (unsigned i=0;i<foo.size()-1;i++) {
3048         instPoint *this_inst_point = foo[i];
3049         instPoint *next_inst_point = foo[i+1];
3050         
3051         if ((this_inst_point->ipType == callSite) && 
3052                   (next_inst_point->ipType == functionExit)) {
3053           instr = this_inst_point->insnAtPoint();
3054           nexti = this_inst_point->insnAfterPoint();
3055           if (CallRestoreTC(instr, nexti) || 
3056             JmpNopTC(instr, nexti, this_inst_point->iPgetAddress(), this)) {
3057
3058              // This tail call optimization will be rewritten, eliminating the
3059              // overlap, so we don't have to worry here about rewriting this
3060              // as overlapping instPoints.
3061              continue;
3062           }
3063         }
3064
3065         // check if inst point overlaps with next inst point....
3066         int overlap = ((this_inst_point->iPgetAddress() + 
3067           this_inst_point->Size()) - next_inst_point->iPgetAddress());
3068         if (overlap > 0) {
3069
3070             // Inst point overlaps with next one.  Insert 
3071             //  InsertNops into PA Set AFTER instruction pointed to
3072             //  by inst point (Making sure that this does NOT break up 
3073             //  an insn and its delay slot).....
3074             // ALRT ALRT : This is NOT designed to handle the case where
3075             //  2 inst points are located at exactly the same place or 
3076             //  1 is located in the delay slot of the other - it will NOT
3077             //  break up the 2 inst points in that case....
3078
3079             int offset = (this_inst_point->insnAddress() - getAddress(0));
3080             
3081             if (isDCTI(loadedCode[offset/sizeof(instruction)])) {
3082               offset += sizeof(instruction);
3083             } 
3084             InsertNops *nops = new InsertNops(this, offset, overlap);
3085             p->AddAlteration(nops);
3086
3087 #ifdef DEBUG_PA_INST
3088             cerr << " detected overlapping inst points : offset " << offset <<
3089               " overlap " << overlap << endl;
3090 #endif
3091         }
3092     }
3093     return true;
3094 }
3095
3096 /****************************************************************************/
3097 /****************************************************************************/
3098 /****************************************************************************/
3099
3100 /*
3101   Third pass, handle cases where inst points overlap branch/jump targets.
3102     In current sparc-solaris version, the following algorithm is used:
3103      Check all branch/jump operations.  If they go into footprint of 
3104      any inst points, then try to insert nops so that the branch targets
3105      move outside of the the footprint....
3106   Note that the algorithm given below should be attached AFTER alterations
3107    which unwind tail-call optimizations and seperate overlapping inst points
3108    have been BOTH attached and applied....
3109  */
3110 bool pd_Function::PA_attachBranchOverlaps(
3111                              LocalAlterationSet *p, Address /* baseAddress */, 
3112                              Address firstAddress, instruction loadedCode[],
3113                              unsigned /* numberOfInstructions */, 
3114                              int codeSize)  {
3115
3116 #ifdef DEBUG_PA_INST
3117     cerr << "pd_Function::PA_attachBranchOverlaps called" <<endl;
3118     cerr << " prettyName = " << prettyName() << endl;
3119 #endif
3120
3121     // Make a list of all inst-points attached to function, and sort
3122     //  by address.  Then check for overlaps....
3123     pdvector<instPoint*> foo;
3124     foo.push_back(funcEntry_);
3125     VECTOR_APPEND(foo,funcReturns);
3126     VECTOR_APPEND(foo,calls);
3127
3128     // Sort inst points list by address....
3129     VECTOR_SORT(foo, sort_inst_points_by_address);
3130
3131     // Iterate over function instruction by instruction....
3132     assert((codeSize % sizeof(instruction)) == 0);
3133     for(unsigned i=0;i<(codeSize/sizeof(instruction));i++) {
3134         // looking for branch instructions inside function....
3135         if (!branchInsideRange(loadedCode[i], 
3136                                firstAddress + (i * sizeof(instruction)),
3137                                firstAddress, 
3138                                firstAddress + size())) {
3139             continue;
3140         }
3141                                                               
3142         int disp = loadedCode[i].branch.disp22;
3143         Address target = firstAddress + (i * sizeof(instruction))
3144                                                             + (disp << 2);
3145
3146         // branch insn inside function.  Check target versus known inst points....
3147         instPoint *overlap = find_overlap(foo, target);
3148         if (overlap == NULL) continue;
3149
3150         if (target <= overlap->iPgetAddress()) {
3151             InsertNops *nops = new InsertNops(this, 
3152                                (target - firstAddress) - sizeof(instruction), 
3153                                target - overlap->firstAddress());
3154             p->AddAlteration(nops);
3155
3156 #ifdef DEBUG_PA_INST
3157           cerr << " detected overlap between branch target and inst point:"
3158                << " offset "  << target - firstAddress 
3159                << " # bytes " << target - overlap->firstAddress() << endl;
3160 #endif
3161
3162         } else {
3163             InsertNops *nops = new InsertNops(this, 
3164                                  (target - firstAddress) - sizeof(instruction),
3165                                  overlap->followingAddress() - target);
3166             p->AddAlteration(nops);
3167
3168 #ifdef DEBUG_PA_INST
3169           cerr << " detected overlap between branch target and inst point:"
3170                << " offset " << (target - firstAddress) - sizeof(instruction)
3171                << " # bytes " << overlap->firstAddress() - target << endl;
3172 #endif
3173
3174         }
3175     }
3176
3177     return true;
3178 }
3179
3180 /****************************************************************************/
3181 /****************************************************************************/
3182 /****************************************************************************/
3183
3184 bool pd_Function::PA_attachBasicBlockEndRewrites(LocalAlterationSet *p,
3185                                                  Address baseAddress,
3186                                                  Address firstAddress,
3187                                                  process *proc) {
3188 #ifdef BPATCH_LIBRARY
3189
3190   BPatch_function *bpfunc = proc->findOrCreateBPFunc(this);
3191
3192   BPatch_flowGraph *cfg = bpfunc->getCFG();
3193   BPatch_Set<BPatch_basicBlock*> allBlocks;
3194   cfg->getAllBasicBlocks(allBlocks);
3195
3196   BPatch_basicBlock** belements =
3197     new BPatch_basicBlock*[allBlocks.size()];
3198   allBlocks.elements(belements);
3199
3200   BPatch_Set<Address> blockEnds;
3201   for (int i = 0; i < allBlocks.size(); i++) {
3202     void *bbsa, *bbea;
3203     belements[i]->getAddressRange(bbsa, bbea);
3204     blockEnds.insert((Address) bbea);
3205   }
3206   delete[] belements;
3207
3208   pdvector<instPoint*> ips;
3209   sorted_ips_vector(ips);
3210
3211   for (unsigned i = 0; i < ips.size(); i++) {
3212     if (blockEnds.contains(ips[i]->iPgetAddress())) {
3213
3214       InsertNops *blockNop = 
3215         new InsertNops(this, ips[i]->iPgetAddress() + baseAddress +
3216                        sizeof(instruction) - firstAddress, 
3217                        sizeof(instruction));
3218       p->AddAlteration(blockNop);
3219
3220     }
3221   }
3222
3223 #endif BPATCH_LIBRARY
3224   return true;
3225 }
3226
3227
3228
3229 /****************************************************************************/
3230 /****************************************************************************/
3231 /****************************************************************************/
3232
3233 // Return the offset (in bytes) of the next instruction at or after
3234 //  offset (again bytes) which is NOT in the delay slot of another
3235 //  instruction....
3236 int pd_Function::moveOutOfDelaySlot(int offset, instruction loadedCode[],
3237           int codeSize) {
3238     assert(offset >= 0 && offset < codeSize);
3239     if (isDCTI(loadedCode[offset/sizeof(instruction)-1])) {
3240         return offset + sizeof(instruction);
3241     }
3242     return offset;
3243 }
3244
3245 /****************************************************************************/
3246 /****************************************************************************/
3247 /****************************************************************************/
3248
3249 #ifdef NOT_DEFINED
3250 #define UPDATE_ADDR(point) \
3251     if (point != NULL) { \
3252         offset = point->Addr() - oldAdr; \
3253         shift = p->GetInstPointShift();  \
3254         if (shift != 0) {                \
3255             p->SetAddr(p->Addr() = shift); \
3256         } \
3257     }
3258 bool pd_Function::applyAlterationsToInstPoints(LocalAlterationSet *p, 
3259         relocatedFuncInfo *info, Address oldAdr) {
3260     instPoint *point;
3261     int offset, shift, i;    
3262
3263     // try to handle entry point....
3264     point = info->funcEntry();
3265     UPDATE_ADDR(point);
3266
3267     // ditto for calls....
3268     for(i=0;i<funcCalls().size();i++) {
3269         point = funcCalls[i];
3270         UPDATE_ADDR(point);
3271     }
3272
3273     // and for exit points....
3274     for(i=0;i<funcReturns().size();i++) {
3275         point = funcReturns[i];
3276         UPDATE_ADDR(point);
3277     }
3278 }
3279 #endif
3280
3281 /****************************************************************************/
3282 /****************************************************************************/
3283 /****************************************************************************/
3284
3285 // Fill in relocatedFuncInfo <func> with inst points from function.
3286 //  Notes:
3287 //    Assumes that function inst points are : 1 entry, multiple call site, and
3288 //     multiple exit points, and that all should be translated into inst
3289 //     points in relocated function (in reloc_info).  This probably shld get 
3290 //     changed if Trash-A-Dyn/Dyninst moves to a model of instrumenting arbitrary
3291 //     points in function....
3292 //    When this function finishes, inst points in reloc info should have their
3293 //     NEW (relocated) address, including changes made by alterations applied
3294 //     to function.
3295 //    3 LocalAlterationSet s are used because that is the number which a relatively
3296 //     straight-forward coding of the logic to find alterations used - other
3297 //     platforms which have different logic for attaching alterations will 
3298 //     probably have more or less than 3 alteration sets....
3299 //    This function preserves the (probably memory leaking) semantics of Tia's original
3300 //     code for filling in reloc_info in findNewInstPoints - it does NOT delete 
3301 //     created inst points on error....
3302 #define CALC_OFFSETS(ip) \
3303     originalOffset = ((ip->insnAddress() + imageBaseAddr) - mutatee); \
3304     newOffset = alteration_set.getInstPointShift(originalOffset + 1); \
3305     assert(((originalOffset + newOffset) % sizeof(instruction)) == 0); \
3306     arrayOffset = (originalOffset + newOffset) / sizeof(instruction); \
3307     tmp = (newAdr + originalOffset + newOffset) - imageBaseAddr; \
3308     tmp2 = ip->iPgetAddress();
3309
3310 /****************************************************************************/
3311 /****************************************************************************/
3312 /****************************************************************************/
3313
3314 void pd_Function::addArbitraryPoint(instPoint* location,
3315                                     process* proc,
3316                                     relocatedFuncInfo* reloc_info)
3317 {
3318
3319     if(!isInstalled(proc))
3320         return;
3321
3322     instPoint *point;
3323     int originalOffset, newOffset, arrayOffset;
3324     Address tmp, tmp2,mutatee,newAdr,mutator;
3325     LocalAlterationSet alteration_set(this);
3326
3327     instruction *oldInstructions = NULL, *newCode = NULL;
3328
3329
3330     const image* owner = location->iPgetOwner();
3331
3332     findAlterations(owner,proc,oldInstructions,alteration_set,
3333                                     mutator, mutatee);
3334     Address imageBaseAddr;
3335     if (!proc->getBaseAddress(owner,imageBaseAddr))
3336         abort();
3337
3338     newAdr = reloc_info->address();
3339     CALC_OFFSETS(location);
3340
3341     newCode  = reinterpret_cast<instruction *> (relocatedCode);
3342     point = new instPoint(this, newCode, arrayOffset, owner,
3343                                      tmp, true, otherPoint);
3344
3345     reloc_info->addArbitraryPoint(point);
3346
3347     delete[] oldInstructions;
3348 }
3349
3350
3351 bool pd_Function::fillInRelocInstPoints(
3352                             const image *owner, process *proc, 
3353