include of instPoint.h is new
[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 #include "dyninstAPI/src/inst-sparc.h"
43 #include "dyninstAPI/src/instPoint.h"
44
45 // Another constructor for the class instPoint. This one is called
46 // for the define the instPoints for regular functions which means
47 // multiple instructions is going to be moved to based trampoline.
48 // Since we will use the instruction CALL to branch to the base
49 // tramp(so it doesn't have any code size restriction), things are
50 // a little more complicated because instruction CALL changes the 
51 // value in the link register.
52 instPoint::instPoint(pd_Function *f, const instruction &instr, 
53                      const image *owner, Address &adr,
54                      bool delayOK, bool isLeaf, instPointType pointType)
55 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
56   callIndirect(false), callAggregate(false), callee(NULL), func(f),
57   leaf(isLeaf), ipType(pointType), image_ptr(owner), firstIsConditional(false),
58   relocated_(false), isLongJump(false)
59 {
60
61   isBranchOut = false;
62   size = 0;
63
64   // When the function is not a leaf function 
65   if (!leaf) {
66
67       // we will treat the first instruction after the SAVE instruction
68       // in the nonleaf procedure as the function entry.  
69       if (ipType == functionEntry) {
70
71           assert(isInsnType(instr, SAVEmask, SAVEmatch));
72           saveInsn.raw = owner->get_instruction(addr);
73           addr += 4;
74           originalInstruction.raw = owner->get_instruction(addr);
75           delaySlotInsn.raw = owner->get_instruction(addr+4);
76           size += 2*sizeof(instruction);
77
78           // If the second instruction is DCTI, we need to move the
79           // the instruction in the delayed slot.
80           if (IS_DELAYED_INST(delaySlotInsn)) {
81               isDelayed = true; 
82               isDelayedInsn.raw = owner->get_instruction(addr+8);
83               size += 1*sizeof(instruction);
84
85               // Life is hard. If the second instruction is actually
86               // an CALL instruction, we need to move the instruction
87               // after the instruction in the delayed slot if the 
88               // return value of this function is a aggregate value.
89               aggregateInsn.raw = owner->get_instruction(addr+12);
90               if (isCallInsn(delaySlotInsn)) {
91                   if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
92                       callAggregate = true;
93                       size += 1*sizeof(instruction);
94                   }
95               }
96           }
97
98       // The following are easier.        
99       } else if (ipType == callSite) {
100           delaySlotInsn.raw = owner->get_instruction(addr+4);
101           size += 2*sizeof(instruction);
102
103           aggregateInsn.raw = owner->get_instruction(addr+8);
104           if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
105               callAggregate = true;
106               size += 1*sizeof(instruction);
107           }
108       } else {
109           delaySlotInsn.raw = owner->get_instruction(addr+4);
110           size += 2*sizeof(instruction);
111       }
112   }
113
114   // When the function is a leaf function
115   else {
116
117       // For the leaf procedure, there are no function calls in
118       // this procdure. So we don't need to consider the 
119       // aggregate instuction.
120       if (ipType == functionEntry) {
121
122           otherInstruction.raw = owner->get_instruction(addr+4);
123           delaySlotInsn.raw = owner->get_instruction(addr+8);
124           size += 2*sizeof(instruction);
125
126           if (IS_DELAYED_INST(delaySlotInsn)) {
127               isDelayed = true;
128               isDelayedInsn.raw = owner->get_instruction(addr+12);
129               size += 2*sizeof(instruction);
130           }
131
132       } else if (ipType == functionExit) {
133           
134           addr -= 4;
135
136           if (owner->isValidAddress(addr-4)) {
137               instruction iplus1;
138               iplus1.raw = owner->get_instruction(addr-4);
139               if (IS_DELAYED_INST(iplus1) && !delayOK) {
140                   addr -= 4;
141                   inDelaySlot = true;
142                   size += 1*sizeof(instruction);
143                   if(isCondBranch(iplus1)){
144                       instruction previous_inst; 
145                       previous_inst.raw = owner->get_instruction(addr-4);
146                       firstIsConditional = true;
147                       addr -= sizeof(instruction);
148                       size += 1*sizeof(instruction);
149                   }
150               }
151           }
152
153           originalInstruction.raw = owner->get_instruction(addr);
154           otherInstruction.raw = owner->get_instruction(addr+4);
155           delaySlotInsn.raw = owner->get_instruction(addr+8);
156           size += 3*sizeof(instruction);
157
158           if (inDelaySlot) {
159               inDelaySlotInsn.raw = owner->get_instruction(addr+12);
160               if(firstIsConditional) {
161                   extraInsn.raw = owner->get_instruction(addr+16);
162               }
163           }
164
165       } else {
166           // Of course, the leaf function could not have call sites. 
167           logLine("Internal Error: in inst-sparc.C.");
168           abort();
169       }
170   }
171
172   // return the address in the code segment after this instruction
173   // sequence. (there's a -1 here because one will be added up later in
174   // the function findInstPoints)  
175   adr = addr + (size - 1*sizeof(instruction));
176 }
177
178
179 void AstNode::sysFlag(instPoint *location)
180 {
181     // astFlag = location->func->isTrapFunc();
182     if (location -> ipType == functionEntry) {
183         astFlag = (location -> isLongJump)? false:true; 
184     } else if (location -> ipType == functionExit) {
185         astFlag = location -> leaf;
186     } else
187         astFlag = false;
188
189     if (loperand)
190         loperand->sysFlag(location);
191     if (roperand)
192         roperand->sysFlag(location); 
193
194     for (unsigned u = 0; u < operands.size(); u++) {
195         operands[u]->sysFlag(location);
196     }
197 }
198
199 // Determine if the called function is a "library" function or a "user" function
200 // This cannot be done until all of the functions have been seen, verified, and
201 // classified
202 //
203 void pd_Function::checkCallPoints() {
204   instPoint *p;
205   Address loc_addr;
206
207   vector<instPoint*> non_lib;
208
209   for (unsigned i=0; i<calls.size(); ++i) {
210     /* check to see where we are calling */
211     p = calls[i];
212     assert(p);
213
214     if (isInsnType(p->originalInstruction, CALLmask, CALLmatch)) {
215       // Direct call
216       loc_addr = p->addr + (p->originalInstruction.call.disp30 << 2);
217       pd_Function *pdf = (file_->exec())->findFunction(loc_addr);
218       if (pdf && !pdf->isLibTag()) {
219         p->callee = pdf;
220         non_lib += p;
221       } else if(!pdf){
222            // if this is a call outside the fuction, keep it
223            if((loc_addr < getAddress(0))||(loc_addr > (getAddress(0)+size()))){
224                 p->callIndirect = true;
225                 p->callee = NULL;
226                 non_lib += p;
227            }
228            else {
229                delete p;
230            }
231       } else {
232           delete p;
233       }
234     } else {
235       // Indirect call -- be conservative, assume it is a call to 
236       // an unnamed user function
237       assert(!p->callee); assert(p->callIndirect);
238       p->callee = NULL;
239       non_lib += p;
240     }
241   }
242   calls = non_lib;
243 }
244
245 // TODO we cannot find the called function by address at this point in time
246 // because the called function may not have been seen.
247 // reloc_info is 0 if the function is not currently being relocated
248 Address pd_Function::newCallPoint(Address &adr, const instruction instr,
249                                  const image *owner, bool &err, 
250                                  int &callId, Address &oldAddr,
251                                  relocatedFuncInfo *reloc_info,
252                                  const instPoint *&location)
253 {
254     Address ret=adr;
255     instPoint *point;
256
257     err = true;
258     if (isTrap) {
259         point = new instPoint(this, instr, owner, adr, false, callSite, oldAddr);
260     } else {
261         point = new instPoint(this, instr, owner, adr, false, false, callSite);
262     }
263
264     if (!isInsnType(instr, CALLmask, CALLmatch)) {
265       point->callIndirect = true;
266       point->callee = NULL;
267     } else{
268       point->callIndirect = false;
269     }
270
271     if (isTrap) {
272         if (!reloc_info) {
273             calls += point;
274             calls[callId] -> instId = callId++;
275         } else {
276             // calls to a location within the function are not
277             // kept in the calls vector
278             assert(callId >= 0);
279             assert(((u_int)callId) < calls.size());
280             point->relocated_ = true;
281             // if the location was this call site, then change its value
282             if(location && (calls[callId] == location)) { 
283                 assert(calls[callId]->instId  == location->instId);
284                 location = point; 
285             } 
286             point->instId = callId++;
287             reloc_info->addFuncCall(point);
288         }
289     } else {
290         if (!reloc_info) {
291             calls += point;
292         }
293         else {
294             point->relocated_ = true;
295             reloc_info->addFuncCall(point);
296         }
297     }
298     err = false;
299     return ret;
300 }
301
302 /*
303  * Given and instruction, relocate it to a new address, patching up
304  *   any relative addressing that is present.
305  *
306  */
307 void relocateInstruction(instruction *insn, u_int origAddr, u_int targetAddr,
308                          process *proc)
309 {
310     int newOffset;
311
312     // If the instruction is a CALL instruction, calculate the new
313     // offset
314     if (isInsnType(*insn, CALLmask, CALLmatch)) {
315         newOffset = origAddr  - targetAddr + (insn->call.disp30 << 2);
316         insn->call.disp30 = newOffset >> 2;
317     } else if (isInsnType(*insn, BRNCHmask, BRNCHmatch)||
318                isInsnType(*insn, FBRNCHmask, FBRNCHmatch)) {
319
320         // If the instruction is a Branch instruction, calculate the 
321         // new offset. If the new offset is out of reach after the 
322         // instruction is moved to the base Trampoline, we would do
323         // the following:
324         //    b  address  ......    address: save
325         //                                   call new_offset             
326         //                                   restore 
327         newOffset = origAddr - targetAddr + (insn->branch.disp22 << 2);
328
329         // if the branch is too far, then allocate more space in inferior
330         // heap for a call instruction to branch target.  The base tramp 
331         // will branch to this new inferior heap code, which will call the
332         // target of the branch
333         if (!offsetWithinRangeOfBranchInsn(newOffset)) {
334 //      if (ABS(newOffset) > getMaxBranch1Insn()) {
335             int ret = inferiorMalloc(proc,3*sizeof(instruction), textHeap);
336             u_int old_offset = insn->branch.disp22 << 2;
337             insn->branch.disp22  = (ret - targetAddr)>>2;
338             instruction insnPlus[3];
339             genImmInsn(insnPlus, SAVEop3, REG_SP, -112, REG_SP);
340             generateCallInsn(insnPlus+1, ret+sizeof(instruction), 
341                              origAddr+old_offset);
342             genSimpleInsn(insnPlus+2, RESTOREop3, 0, 0, 0); 
343             proc->writeDataSpace((caddr_t)ret, sizeof(insnPlus), 
344                          (caddr_t) insnPlus);
345         } else {
346             insn->branch.disp22 = newOffset >> 2;
347         }
348     } else if (isInsnType(*insn, TRAPmask, TRAPmatch)) {
349         // There should be no probelm for moving trap instruction
350         // logLine("attempt to relocate trap\n");
351     } 
352     /* The rest of the instructions should be fine as is */
353 }
354
355 /*
356  * Install a base tramp -- fill calls with nop's for now.
357  *
358  * This one install the base tramp for the regular functions.
359  *
360  */
361 trampTemplate *installBaseTramp(instPoint *&location, process *proc)
362 {
363     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
364
365     instruction *code = new instruction[baseTemplate.size];
366     assert(code);
367
368     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
369
370     instruction *temp;
371     unsigned currAddr;
372     for (temp = code, currAddr = baseAddr; 
373         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
374         temp++, currAddr += sizeof(instruction)) {
375
376         if (temp->raw == EMULATE_INSN) {
377
378             // Load the value of link register from stack 
379             // If it is a leaf function, genereate a RESTORE instruction
380             // since there's an instruction SAVE generated and put in the
381             // code segment.
382             if (location -> leaf) {
383
384                 Address baseAddress = 0;
385                 proc->getBaseAddress(location->image_ptr,baseAddress);
386                 baseAddress += location -> addr;
387
388                 if (in1BranchInsnRange(baseAddress, baseAddr) == false) {
389                     //cerr << "This happen very rarely, I suppose "<< endl;
390                     //cerr << "Let's see if this is going to be executed..." << endl;
391                     location -> isLongJump = true;
392                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
393                 } else {
394                     generateNOOP(temp);
395                 }
396                 temp++;
397                 currAddr += sizeof(instruction);
398             } 
399             // Same for the leaf and nonleaf functions.
400             // First, relocate the "FIRST instruction" in the sequence;  
401             Address fromAddr = location->addr;
402
403             if (!location -> leaf)
404                 if (location -> ipType == functionEntry) {
405                     *temp = location -> saveInsn;
406                     temp++;
407                     currAddr += sizeof(instruction);
408                 }
409
410             *temp = location->originalInstruction;
411
412             // compute the real from address if this instrumentation
413             // point is from a shared object image
414             Address baseAddress = 0;
415             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
416                 fromAddr += baseAddress;                
417             }
418             // If the instruction is a call instruction to a location somewhere 
419             // within the function, then the 07 regester must be saved and 
420             // resored around the relocated call from the base tramp...the call
421             // instruction changes the value of 07 to be the PC value, and if
422             // we move the call instruction to the base tramp, its value will
423             // be incorrect when we use it in the function.  We generate the
424             // following base tramp code:
425             //          original delay slot instruction 
426             //          save
427             //          original call instruction
428             //          restore
429             // This case should only occur for function entry points in
430             // functions from shared objects, and there should be no append
431             // trampolene code because the relocated call instruction will
432             // not return to the base tramp
433             if (isInsnType(*temp, CALLmask, CALLmatch)) {
434                 Address offset = fromAddr + (temp->call.disp30 << 2);
435                 if ((offset > (location->func->getAddress(0)+ baseAddress)) && 
436                     (offset < ((location->func->getAddress(0)+ baseAddress)+
437                                  location->func->size()))) {
438                     // offset > adr; "=" means recursive function which is allowed
439                     // offset < adr + size; "=" does not apply to this case
440
441                     // TODO: this assumes that the delay slot instruction is not
442                     // a call instruction....is this okay?
443                     
444                     // assume this situation only happens at function entry point 
445                     // for the shared library routine. And it is definately nees
446                     // long jump support
447                     assert(location -> ipType == functionEntry); 
448                     location -> isLongJump = true;
449                     
450                     // In this situcation, save instruction is discarded
451                     // Rollback!! 
452                     assert(location->leaf == false);
453                     temp--;
454                     currAddr -= sizeof(instruction);
455                     
456                     *temp = location->delaySlotInsn;  
457                     temp++; 
458                     currAddr += sizeof(instruction);
459                     genImmInsn(temp, SAVEop3, REG_SP, -112, REG_SP); 
460                     temp++; 
461                     currAddr += sizeof(instruction);  
462                     *temp = location->originalInstruction;
463                     relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
464                     temp++; 
465                     fromAddr += sizeof(instruction); 
466                     currAddr += sizeof(instruction);
467                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
468                     continue;
469                 }
470             }   
471
472             relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
473
474             // Again, for leaf function, one more is needed to move for one
475             // more spot;
476             if (location->leaf) {
477                 fromAddr += sizeof(instruction);
478                 currAddr += sizeof(instruction);
479                 *++temp = location->otherInstruction;
480                 relocateInstruction(temp, fromAddr, currAddr, 
481                                     (process *)proc);
482             }     
483             
484             // Second, relocate the "NEXT instruction";
485             fromAddr += sizeof(instruction);
486             currAddr += sizeof(instruction);
487             *++temp = location->delaySlotInsn;
488  
489             // if the NEXT instruction is a call instruction to a location
490             // within the function, then the 07 regester must be saved and 
491             // resored around the relocated call from the base tramp...the call
492             // instruction changes the value of 07 to be the PC value, and if
493             // we move the call instruction to the base tramp, its value will
494             // be incorrect when we use it in the function.  We generate:
495             //
496             //  orignial            relocated to base tramp
497             //  --------            -----------------------
498             //  save                nop  // SAVE added above, replace w/nop 
499             //  original insn       original instruction // already relocated
500             //  delaySlotInsn       isDelayedInsn
501             //  isDelayedInsn       save
502             //                      delaySlotInsn  (call with offset - 4)
503             //                      restore
504             //  In the function, the call to the base tramp will have an
505             //  additional add instruction to adjust the 07 register
506             //  orignial            relocated to base tramp
507             //  --------            -----------------------
508             //  save                 save       
509             //  mov                  call
510             //  call                 nop
511             //  sethi                add $o7 4   
512             //
513             if (isInsnType(*temp, CALLmask, CALLmatch)) {
514                 Address offset = fromAddr + (temp->call.disp30 << 2);
515                 if ((offset > (location->func->getAddress(0)+ baseAddress)) && 
516                     (offset < ((location->func->getAddress(0)+ baseAddress)+
517                                  location->func->size()))) {
518                     
519                     temp--;
520                     temp--;
521                     generateNOOP(temp);  
522                     temp++;
523                     temp++;
524                     location->isLongJump = true;
525                     // assert(location->leaf == false);
526                     // assume that this is not a delayed instr.
527                     *temp = location->isDelayedInsn;  
528                     temp++; 
529                     currAddr += sizeof(instruction);
530                     genImmInsn(temp, SAVEop3, REG_SP, -112, REG_SP); 
531                     temp++; 
532                     currAddr += sizeof(instruction);  
533                     *temp = location->delaySlotInsn;
534                     Address new_call_addr = fromAddr - sizeof(instruction);
535                     relocateInstruction(temp,new_call_addr,currAddr,proc);
536                     temp++; 
537                     fromAddr += sizeof(instruction); 
538                     currAddr += sizeof(instruction);
539                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
540                     continue;
541                 }
542             }   
543
544             // otherwise relocate the NEXT instruction
545             relocateInstruction(temp, fromAddr, currAddr,
546                                 (process *)proc);
547             
548             // Third, if the "NEXT instruction" is a DCTI, 
549             if (location->isDelayed) {
550                 fromAddr += sizeof(instruction);
551                 currAddr += sizeof(instruction);
552                 *++temp = location->isDelayedInsn;
553                 relocateInstruction(temp, fromAddr, currAddr,
554                                     (process *)proc);
555                 
556                 // Then, possibly, there's an callAggregate instruction
557                 // after this. 
558                 if (location->callAggregate) {
559                     currAddr += sizeof(instruction);
560                     *++temp = location->aggregateInsn;
561                     continue;
562                 }       
563             }
564             
565             // If the "FIRST instruction" is a DCTI, then our so called 
566             // "NEXT instruction" is in the delayed Slot and this might
567             // happen. (actullay, it happened)
568             if (location->callAggregate) {
569                 currAddr += sizeof(instruction);
570                 *++temp = location->aggregateInsn;
571                 continue;
572             }   
573             
574             // For the leaf function, if there's an inDelaySlot instruction,
575             // move this one to the base Tramp.(i.e. at the function exit,
576             // if the first instruction is in the delayed slot the previous
577             // instruction, we have to move that one too, so we count from 
578             // that one and the last one is this sequence is called inDelaySlot
579             // instruction.)
580             // Well, after all these, another SAVE instruction is generated
581             // so we are prepared to handle the returning to our application's
582             // code segment. 
583             if (location->leaf) {
584                 if (location->inDelaySlot) {
585                     fromAddr += sizeof(instruction);
586                     currAddr += sizeof(instruction);
587                     *++temp = location->inDelaySlotInsn;
588                     relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
589                     if(location->firstIsConditional){
590                         fromAddr += sizeof(instruction);
591                         currAddr += sizeof(instruction);
592                         *++temp = location->extraInsn;
593                         relocateInstruction(temp, fromAddr, currAddr, proc);
594                     }
595                 } 
596                 
597                 genImmInsn(temp+1, SAVEop3, REG_SP, -112, REG_SP);
598             }
599             
600         } else if (temp->raw == RETURN_INSN) {
601             // compute the real from address if this instrumentation
602             // point is from a shared object image
603             Address baseAddress = 0;
604             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
605             }
606             // Back to the code segement of the application.
607             // If the location is in the leaf procedure, generate an RESTORE
608             // instruction right after the CALL instruction to restore all
609             // the values in the registers.
610             if (location -> leaf) {
611                 generateCallInsn(temp, currAddr, 
612                                 (baseAddress + location->addr)+location->size);
613                 genImmInsn(temp+1, RESTOREop3, 0, 0, 0);
614             } else {
615                 generateCallInsn(temp, currAddr, 
616                                 (baseAddress + location->addr)+location->size);
617             }
618         } else if (temp->raw == SKIP_PRE_INSN) {
619             unsigned offset;
620             offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
621             generateBranchInsn(temp,offset);
622
623         } else if (temp->raw == SKIP_POST_INSN) {
624             unsigned offset;
625             offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
626             generateBranchInsn(temp,offset);
627
628         } else if (temp->raw == UPDATE_COST_INSN) {
629             
630             baseTemplate.costAddr = currAddr;
631             generateNOOP(temp);
632         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
633                    (temp->raw == GLOBAL_PRE_BRANCH) ||
634                    (temp->raw == LOCAL_POST_BRANCH) ||
635                    (temp->raw == GLOBAL_POST_BRANCH)) {
636 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
637             if ((temp->raw == LOCAL_PRE_BRANCH) ||
638                 (temp->raw == LOCAL_POST_BRANCH)) {
639                 temp -= NUM_INSN_MT_PREAMBLE;
640                 unsigned numIns=0;
641                 generateMTpreamble((char *)temp, numIns, proc);
642                 temp += NUM_INSN_MT_PREAMBLE;
643             }
644 #endif
645             /* fill with no-op */
646             generateNOOP(temp);
647         }
648     }
649     // TODO cast
650     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
651
652     delete [] code;
653
654     trampTemplate *baseInst = new trampTemplate;
655     *baseInst = baseTemplate;
656     baseInst->baseAddr = baseAddr;
657     return baseInst;
658 }
659
660 /*
661  * Install the base Tramp for the function relocated.
662  * (it means the base tramp that don't need to bother with long jump and
663  *  is the one we used before for all the functions(since there's no
664  *  long jumps)
665  *  for system calls
666  */ 
667 trampTemplate *installBaseTrampSpecial(const instPoint *&location,
668                                        process *proc,
669                                        vector<instruction> &extra_instrs) 
670 {
671     unsigned currAddr;
672     instruction *code;
673     instruction *temp;
674
675     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
676
677     if(!(location->func->isInstalled(proc))) {
678         location->func->relocateFunction(proc,location,extra_instrs);
679     }
680     else if(!location->relocated_){
681         // need to find new instPoint for location...it has the pre-relocated
682         // address of the instPoint
683         location->func->modifyInstPoint(location,proc);      
684     }
685
686     code = new instruction[baseTemplate.size];
687     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
688
689     for (temp = code, currAddr = baseAddr; 
690         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
691         temp++, currAddr += sizeof(instruction)) {
692
693         if (temp->raw == EMULATE_INSN) {
694             if (location->isBranchOut) {
695                 // the original instruction is a branch that goes out of a 
696                 // function.  We don't relocate the original instruction. We 
697                 // only get to the tramp is the branch is taken, so we generate
698                 // a unconditional branch to the target of the original 
699                 // instruction here 
700                 assert(location->branchTarget);
701                 int disp = location->branchTarget - currAddr;
702
703                 generateBranchInsn(temp, disp);
704                 disp = temp->branch.disp22;
705                 continue;
706             }
707             else {
708                 *temp = location->originalInstruction;
709                 Address fromAddress = location->addr;
710                 relocateInstruction(temp, fromAddress, currAddr, proc);
711                 if (location->isDelayed) {
712                     /* copy delay slot instruction into tramp instance */
713                     currAddr += sizeof(instruction);  
714                     *++temp = location->delaySlotInsn;
715                 }
716                 if (location->callAggregate) {
717                     /* copy invalid insn with aggregate size in it */
718                     currAddr += sizeof(instruction);  
719                     *++temp = location->aggregateInsn;
720                 }
721             }
722         } else if (temp->raw == RETURN_INSN) {
723             generateBranchInsn(temp, 
724                 (location->addr+ sizeof(instruction) - currAddr));
725             if (location->isDelayed) {
726                 /* skip the delay slot instruction */
727                 temp->branch.disp22 += 1;
728             }
729             if (location->callAggregate) {
730                 /* skip the aggregate size slot */
731                 temp->branch.disp22 += 1;
732             }
733         } else if (temp->raw == SKIP_PRE_INSN) {
734           unsigned offset;
735           offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
736           generateBranchInsn(temp,offset);
737         } else if (temp->raw == SKIP_POST_INSN) {
738           unsigned offset;
739           offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
740           generateBranchInsn(temp,offset);
741         } else if (temp->raw == UPDATE_COST_INSN) {
742             
743             baseTemplate.costAddr = currAddr;
744             generateNOOP(temp);
745         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
746                    (temp->raw == GLOBAL_PRE_BRANCH) ||
747                    (temp->raw == LOCAL_POST_BRANCH) ||
748                    (temp->raw == GLOBAL_POST_BRANCH)) {
749 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
750             if ((temp->raw == LOCAL_PRE_BRANCH) ||
751                 (temp->raw == LOCAL_POST_BRANCH)) {
752                 temp -= NUM_INSN_MT_PREAMBLE;
753                 unsigned numIns=0;
754                 generateMTpreamble((char *)temp, numIns, proc);
755                 temp += NUM_INSN_MT_PREAMBLE;
756             }
757 #endif
758             /* fill with no-op */
759             generateNOOP(temp);
760         }
761     }
762     // TODO cast
763     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
764
765     delete [] code;
766
767     trampTemplate *baseInst = new trampTemplate;
768     *baseInst = baseTemplate;
769     baseInst->baseAddr = baseAddr;
770     return baseInst;
771 }
772
773 /*
774  * Allocate the space for the base Trampoline, and generate the instruction
775  * we need for modifying the code segment.
776  *
777  * 'retInstance' tells you how to modify the code to jump to the base tramp
778  *
779  */
780 trampTemplate *findAndInstallBaseTramp(process *proc, 
781                                  instPoint *&location,
782                                  returnInstance *&retInstance,
783                                  bool)
784 {
785     Address adr = location->addr;
786     retInstance = NULL;
787
788     
789     trampTemplate *ret;
790     if (proc->baseMap.find((const instPoint *)location, ret)) // writes to ret if found
791        // This base tramp already exists; nothing to do.
792        return ret;
793
794     if (location->func->isTrapFunc()) {
795        // get the base Address of this function if it is a 
796        // shared object
797        Address baseAddress = 0;
798        if(!proc->getBaseAddress(location->image_ptr,baseAddress)){
799           // TODO: what should be done here?    
800           logLine("Error:findAndInstallBaseTramp call getBaseAddress\n"); 
801        }
802        // Install Base Tramp for the functions which are 
803        // relocated to the heap.
804        vector<instruction> extra_instrs;
805
806        ret = installBaseTrampSpecial(location, proc,extra_instrs);
807
808        // add a branch from relocated function to the base tramp
809        // if function was just relocated then location has old address
810        // otherwise location will have address in already relocated func
811        if (!location->func->isInstalled(proc)){
812           if (location->isBranchOut){
813              changeBranch(proc, location->addr, 
814                           (int) ret->baseAddr, location->originalInstruction);
815            } else {
816              generateBranch(proc, location->addr, (int)ret->baseAddr);
817            }
818        }
819        else {  // location's address is correct...it is in the heap
820           if (location->isBranchOut){
821              changeBranch(proc, location->addr, 
822                           (int) ret->baseAddr, location->originalInstruction);
823           } else {
824              generateBranch(proc, location->addr, (int)ret->baseAddr);
825           }
826        }
827
828        // If for this process, a call to the relocated function has not
829        // yet be installed in its original location, then genterate the
830        // following instructions at the begining of the function:
831        //   SAVE;             CALL;         RESTORE.
832        // so that it would jump the start of the relocated function
833        // which is in heap.
834        if (!location->func->isInstalled(proc)){
835           location->func->setInstalled(proc);
836           u_int e_size = extra_instrs.size();
837           instruction *insn = new instruction[3 + e_size];
838           Address adr = location-> func -> getAddress(0);
839           genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
840           generateCallInsn(insn+1, adr+baseAddress+4, 
841                            location->func->getAddress(proc));
842           genSimpleInsn(insn+2, RESTOREop3, 0, 0, 0); 
843           for(u_int i=0; i < e_size; i++){
844              insn[3+i] = extra_instrs[i];
845           }
846           retInstance = new returnInstance((instructUnion *)insn, 
847                                            (3+e_size)*sizeof(instruction), 
848                                            adr+baseAddress, 
849                                            location->func->size());
850           assert(retInstance);
851
852           //cerr << "created a new return instance (relocated fn)!" << endl;
853        }
854     } else {
855        // It's not a trap-function; it's a "normal" function
856        // compute the real from address if this instrumentation
857        // point is from a shared object image
858        Address baseAddress = 0;
859        if (proc->getBaseAddress(location->image_ptr,baseAddress)){
860           adr += baseAddress;           
861        }
862
863        ret = installBaseTramp(location, proc);
864        // check to see if this is an entry point and if the delay 
865        // slot instruction is a call insn, if so, then if the 
866        // call is to a location within the function, then we need to 
867        // add an extra instruction after the restore to correctly
868        // set the o7 register
869        bool need_to_add = false;
870        if (location->ipType==functionEntry &&
871            isInsnType(location->delaySlotInsn,CALLmask,CALLmatch)) {
872           Address call_offset = location->addr + 8 + 
873                                 (location->delaySlotInsn.call.disp30<<2);
874           Address fun_addr = location->func->getAddress(0);
875           u_int fun_size = location->func->size();
876           if (call_offset>fun_addr && call_offset<(fun_addr+fun_size)) {
877              assert(location->isLongJump);
878              need_to_add = true;
879           }
880        }        
881
882        if (location->leaf) {
883           // if it is the leaf function, we need to generate
884           // the following instruction sequence:
885           //     SAVE;      CALL;      NOP.
886
887           if (location -> isLongJump == false) {
888              instruction *insn = new instruction;
889              generateBranchInsn(insn, (int)(ret->baseAddr-location->addr));
890              retInstance = new returnInstance((instructUnion *)insn,
891                                               sizeof(instruction), adr, 
892                                               sizeof(instruction));
893           } else if (need_to_add) {
894              // generate  original; call; add $o7 imm4 
895              instruction *insn = new instruction[2];
896              generateCallInsn(insn, adr+4, (int) ret->baseAddr);
897              genImmInsn(insn+1,ADDop3,REG_O7,4,REG_O7);
898              retInstance = new returnInstance((instructUnion *)insn,
899                                  2*sizeof(instruction), adr+4,
900                                  2*sizeof(instruction));
901
902           } else {
903              instruction *insn = new instruction[3];
904              genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
905              generateCallInsn(insn+1, adr+4, (int) ret->baseAddr);
906              generateNOOP(insn+2);
907              retInstance = new returnInstance((instructUnion *)insn, 
908                                                      3*sizeof(instruction), adr, 
909                                                      3*sizeof(instruction));
910                     
911           }
912                 
913           assert(retInstance);
914        } else {
915           // It's not a leaf.
916           // Generate branch instruction from the application to the
917           // base trampoline and no SAVE instruction is needed
918                 
919           if (in1BranchInsnRange(adr, ret->baseAddr)) {
920              // make sure that the isLongJump won't be true
921              // which only is possible for shlib entry point 
922              assert(location->isLongJump == false);
923              instruction *insn = new instruction;
924              if (location -> ipType == functionEntry) {
925                 generateBranchInsn(insn, (int)(ret->baseAddr -
926                                                location->addr+sizeof(instruction))); 
927                 retInstance = new returnInstance((instructUnion *)insn,
928                                                  sizeof(instruction), 
929                                                  adr - sizeof(instruction), 
930                                                  sizeof(instruction));
931              } else {
932                 generateBranchInsn(insn, (int)(ret->baseAddr-location->addr));
933                 retInstance = new returnInstance((instructUnion *)insn,
934                                                  sizeof(instruction), 
935                                                  adr, 
936                                                  sizeof(instruction));
937              }
938           } else if(need_to_add) {
939              // the delay slot instruction is is a call to a location
940              // within the same function, then need to generate 3 instrs
941              //    call
942              //    nop          // delay slot (originally call insn)
943              //    add o7 imm4  // sets o7 register to correct value
944              instruction *insn = new instruction[3];    
945              generateCallInsn(insn, adr, (int) ret->baseAddr);
946              generateNOOP(insn+1);
947              genImmInsn(insn+2,ADDop3,REG_O7,4,REG_O7);
948              retInstance = new returnInstance((instructUnion *)insn, 
949                                               3*sizeof(instruction), adr, 
950                                               3*sizeof(instruction));
951           } else {
952              instruction *insn = new instruction[2];    
953              generateCallInsn(insn, adr, (int) ret->baseAddr);
954              if (location -> ipType == functionEntry) {
955                 if (location -> isLongJump)
956                    generateNOOP(insn+1);
957                 else
958                    genSimpleInsn(insn+1, RESTOREop3, 0, 0, 0);
959              } else
960                 generateNOOP(insn+1);
961
962              retInstance = new returnInstance((instructUnion *)insn, 
963                                               2*sizeof(instruction), adr, 
964                                               2*sizeof(instruction));
965              assert(retInstance);
966           }
967        }
968     }
969
970     proc->baseMap[(const instPoint *)location] = ret;
971         
972     return(ret);
973        // remember, ret was the result of either installBaseTramp() or
974        // installBaseTrampSpecial()
975 }
976
977 /*
978  * Install a single tramp.
979  *
980  */
981 void installTramp(instInstance *inst, char *code, int codeSize) 
982 {
983     totalMiniTramps++;
984     insnGenerated += codeSize/sizeof(int);
985     
986     // TODO cast
987     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
988
989     unsigned atAddr;
990     if (inst->when == callPreInsn) {
991         if (inst->baseInstance->prevInstru == false) {
992             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPreInsOffset;
993             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
994             inst->baseInstance->prevInstru = true;
995             generateNoOp(inst->proc, atAddr);
996         }
997     } else {
998         if (inst->baseInstance->postInstru == false) {
999             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPostInsOffset; 
1000             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
1001             inst->baseInstance->postInstru = true;
1002             generateNoOp(inst->proc, atAddr);
1003         }
1004     }
1005 }
1006
1007
1008 unsigned emitFuncCall(opCode op, 
1009                       registerSpace *rs,
1010                       char *i, unsigned &base, 
1011                       const vector<AstNode *> &operands, 
1012                       const string &callee, process *proc,
1013                       bool noCost)
1014 {
1015         assert(op == callOp);
1016         unsigned addr;
1017         bool err;
1018         vector <reg> srcs;
1019         void cleanUpAndExit(int status);
1020
1021         addr = proc->findInternalAddress(callee, false, err);
1022
1023         if (err) {
1024             function_base *func = proc->findOneFunction(callee);
1025             if (!func) {
1026                 ostrstream os(errorLine, 1024, ios::out);
1027                 os << "Internal error: unable to find addr of " << callee << endl;
1028                 logLine(errorLine);
1029                 showErrorCallback(80, (const char *) errorLine);
1030                 P_abort();
1031             }
1032             // TODO: is this correct or should we get relocated address?
1033             addr = func->getAddress(0);
1034         }
1035         
1036         for (unsigned u = 0; u < operands.size(); u++)
1037             srcs += operands[u]->generateCode(proc, rs, i, base, noCost);
1038
1039         // TODO cast
1040         instruction *insn = (instruction *) ((void*)&i[base]);
1041
1042         for (unsigned u=0; u<srcs.size(); u++){
1043             if (u >= 5) {
1044                  string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
1045                  fprintf(stderr, msg.string_of());
1046                  showErrorCallback(94,msg);
1047                  cleanUpAndExit(-1);
1048             }
1049             genSimpleInsn(insn, ORop3, 0, srcs[u], u+8); insn++;
1050             base += sizeof(instruction);
1051             rs->freeRegister(srcs[u]);
1052         }
1053
1054         // As Ling pointed out to me, the following is rather inefficient.  It does:
1055         //   sethi %hi(addr), %o5
1056         //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
1057         //   nop
1058         // We can do better:
1059         //   call <addr>    (but note that the call true-instr is pc-relative jump)
1060         //   nop
1061         generateSetHi(insn, addr, 13); insn++;
1062         genImmInsn(insn, JMPLop3, 13, LOW10(addr), 15); insn++;
1063         generateNOOP(insn);
1064
1065         base += 3 * sizeof(instruction);
1066
1067         // return value is the register with the return value from the
1068         //   function.
1069         // This needs to be %o0 since it is back in the callers scope.
1070         return(8);
1071 }
1072  
1073 unsigned emit(opCode op, reg src1, reg src2, reg dest, char *i, unsigned &base,
1074               bool noCost)
1075 {
1076     // TODO cast
1077     instruction *insn = (instruction *) ((void*)&i[base]);
1078
1079     if (op == loadConstOp) {
1080       // dest = src1:imm    TODO
1081       if (src1 > MAX_IMM13 || src1 < MIN_IMM13) {
1082             // src1 is out of range of imm13, so we need an extra instruction
1083             generateSetHi(insn, src1, dest);
1084             base += sizeof(instruction);
1085             insn++;
1086
1087             // or regd,imm,regd
1088
1089             // Chance for optimization: we should check for LOW10(src1)==0, and
1090             // if so, don't generate the following bitwise-or instruction, since
1091             // in that case nothing would be done.
1092
1093             genImmInsn(insn, ORop3, dest, LOW10(src1), dest);
1094             base += sizeof(instruction);
1095         } else {
1096             // really or %g0,imm,regd
1097             genImmInsn(insn, ORop3, 0, src1, dest);
1098
1099             base += sizeof(instruction);
1100         }
1101     } else if (op ==  loadOp) {
1102         // dest = [src1]   TODO
1103         generateSetHi(insn, src1, dest);
1104         insn++;
1105
1106         generateLoad(insn, dest, LOW10(src1), dest);
1107
1108         base += sizeof(instruction)*2;
1109     } else if (op ==  loadIndirOp) {
1110         generateLoad(insn, src1, 0, dest);
1111         base += sizeof(instruction);
1112     } else if (op ==  storeOp) {
1113         insn->sethi.op = FMT2op;
1114         insn->sethi.rd = src2;
1115         insn->sethi.op2 = SETHIop2;
1116         insn->sethi.imm22 = HIGH22(dest);
1117         insn++;
1118
1119         generateStore(insn, src1, src2, LOW10(dest));
1120
1121         base += sizeof(instruction)*2;
1122     } else if (op ==  storeIndirOp) {
1123         generateStore(insn, src1, dest, 0);
1124         base += sizeof(instruction);
1125     } else if (op ==  ifOp) {
1126         // cmp src1,0
1127         genSimpleInsn(insn, SUBop3cc, src1, 0, 0); insn++;
1128
1129         insn->branch.op = 0;
1130         insn->branch.cond = BEcond;
1131         insn->branch.op2 = BICCop2;
1132         insn->branch.anneal = false;
1133         insn->branch.disp22 = dest/4;
1134         insn++;
1135
1136         generateNOOP(insn);
1137         base += sizeof(instruction)*3;
1138         return(base - 2*sizeof(instruction));
1139     } else if (op ==  updateCostOp) {
1140         // generate code to update the observed cost.
1141         if (!noCost) {
1142            // sethi %hi(dest), %l0
1143            generateSetHi(insn, dest, REG_L0);
1144            base += sizeof(instruction);
1145            insn++;
1146   
1147            // ld [%l0+ lo(dest)], %l1
1148            generateLoad(insn, REG_L0, LOW10(dest), REG_L1);
1149            base += sizeof(instruction);
1150            insn++;
1151   
1152            // update value (src1 holds the cost, in cycles; e.g. 19)
1153            if (src1 <= MAX_IMM13) {
1154               genImmInsn(insn, ADDop3, REG_L1, src1, REG_L1);
1155               base += sizeof(instruction);
1156               insn++;
1157
1158               generateNOOP(insn);
1159               base += sizeof(instruction);
1160               insn++;
1161
1162               generateNOOP(insn);
1163               base += sizeof(instruction);
1164               insn++;
1165            } else {
1166               // load in two parts
1167               generateSetHi(insn, src1, REG_L2);
1168               base += sizeof(instruction);
1169               insn++;
1170
1171               // or regd,imm,regd
1172               genImmInsn(insn, ORop3, REG_L2, LOW10(src1), REG_L2);
1173               base += sizeof(instruction);
1174               insn++;
1175
1176               // now add it
1177               genSimpleInsn(insn, ADDop3, REG_L1, REG_L2, REG_L1);
1178               base += sizeof(instruction);
1179               insn++;
1180            }
1181   
1182            // store result st %l1, [%l0+ lo(dest)];
1183            generateStore(insn, REG_L1, REG_L0, LOW10(dest));
1184            base += sizeof(instruction);
1185            insn++;
1186         } // if (!noCost)
1187     } else if (op ==  trampPreamble) {
1188 #ifdef ndef
1189         // save and restore are done inthe base tramp now
1190         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1191         base += sizeof(instruction);
1192         insn++;
1193
1194         // generate code to save global registers
1195         for (unsigned u = 0; u < 4; u++) {
1196           genStoreD(insn, 2*u, REG_FP, - (8 + 8*u));
1197           base += sizeof(instruction);
1198           insn++;
1199         }
1200 #endif
1201     } else if (op ==  trampTrailer) {
1202 #ifdef ndef
1203         // save and restore are done inthe base tramp now
1204         // generate code to restore global registers
1205         for (unsigned u = 0; u < 4; u++) {
1206           genLoadD(insn, REG_FP, - (8 + 8*u), 2*u);
1207           base += sizeof(instruction);
1208           insn++;
1209         }
1210
1211         // sequence: restore; nop; b,a back to base tramp; nop
1212         // we can do better.  How about putting the restore in
1213         // the delay slot of the branch instruction, as in:
1214         // b <back to base tramp>; restore
1215         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); 
1216         base += sizeof(instruction);
1217         insn++;
1218
1219         generateNOOP(insn);
1220         base += sizeof(instruction);
1221         insn++;
1222 #endif
1223         // dest is in words of offset and generateBranchInsn is bytes offset
1224         generateBranchInsn(insn, dest << 2);
1225         base += sizeof(instruction);
1226         insn++;
1227
1228         // add no-op, SS-5 sometimes seems to try to decode this insn - jkh 2/14
1229         generateNOOP(insn);
1230         insn++;
1231         base += sizeof(instruction);
1232
1233         return(base -  2 * sizeof(instruction));
1234     } else if (op == noOp) {
1235         generateNOOP(insn);
1236         base += sizeof(instruction);
1237     } else if (op == getParamOp) {
1238 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1239         // saving CT/vector address on the stack
1240         generateStore(insn, REG_MT, REG_FP, -40);
1241         insn++;
1242 #endif
1243         // first 8 parameters are in register 24 ....
1244         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1245         insn++;
1246
1247         generateStore(insn, 24+src1, REG_SP, 68+4*src1); 
1248         insn++;
1249               
1250         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1251         insn++;
1252
1253         generateLoad(insn, REG_SP, 112+68+4*src1, 24+src1); 
1254         insn++;
1255
1256 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1257         // restoring CT/vector address back in REG_MT
1258         generateLoad(insn, REG_FP, -40, REG_MT);
1259         insn++;
1260         base += 6*sizeof(instruction);
1261 #else
1262         base += 4*sizeof(instruction);
1263 #endif
1264         
1265         if (src1 <= 8) {
1266             return(24+src1);
1267         }
1268         
1269         abort();
1270     } else if (op == getSysParamOp) {
1271         
1272         if (src1 <= 8) {
1273             return(24+src1);
1274         }       
1275     } else if (op == getRetValOp) {
1276         // return value is in register 24
1277         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1278         insn++;
1279
1280         generateStore(insn, 24, REG_SP, 68); 
1281         insn++;
1282               
1283         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1284         insn++;
1285
1286         generateLoad(insn, REG_SP, 112+68, 24); 
1287         insn++;
1288
1289         base += 4*sizeof(instruction);
1290
1291         return(24);
1292
1293     } else if (op == getSysRetValOp) {
1294
1295         return(24);
1296     } else if (op == saveRegOp) {
1297         // should never be called for this platform.
1298         abort();
1299     } else {
1300       int op3=-1;
1301         switch (op) {
1302             // integer ops
1303             case plusOp:
1304                 op3 = ADDop3;
1305                 break;
1306
1307             case minusOp:
1308                 op3 = SUBop3;
1309                 break;
1310
1311             case timesOp:
1312                 op3 = SMULop3;
1313                 break;
1314
1315             case divOp:
1316                 op3 = SDIVop3;
1317                 //need to set the Y register to Zero, Zhichen
1318                 genImmInsn(insn, WRYop3, REG_G0, 0, 0);
1319                 base += sizeof(instruction);
1320                 insn = (instruction *) ((void*)&i[base]);
1321                 break;
1322
1323             // Bool ops
1324             case orOp:
1325                 op3 = ORop3;
1326                 break;
1327
1328             case andOp:
1329                 op3 = ANDop3;
1330                 break;
1331
1332             // rel ops
1333             // For a particular condition (e.g. <=) we need to use the
1334             // the opposite in order to get the right value (e.g. for >=
1335             // we need BLTcond) - naim
1336             case eqOp:
1337                 genRelOp(insn, BNEcond, src1, src2, dest, base);
1338                 return(0);
1339                 break;
1340
1341             case neOp:
1342                 genRelOp(insn, BEcond, src1, src2, dest, base);
1343                 return(0);
1344                 break;
1345
1346             case lessOp:
1347                 genRelOp(insn, BGEcond, src1, src2, dest, base);
1348                 return(0);
1349                 break;
1350
1351             case leOp:
1352                 genRelOp(insn, BGTcond, src1, src2, dest, base);
1353                 return(0);
1354                 break;
1355
1356             case greaterOp:
1357                 genRelOp(insn, BLEcond, src1, src2, dest, base);
1358                 return(0);
1359                 break;
1360
1361             case geOp:
1362                 genRelOp(insn, BLTcond, src1, src2, dest, base);
1363                 return(0);
1364                 break;
1365
1366             default:
1367                 abort();
1368                 break;
1369         }
1370         genSimpleInsn(insn, op3, src1, src2, dest);
1371
1372         base += sizeof(instruction);
1373       }
1374     return(0);
1375 }
1376
1377 /*
1378  * Find the instPoints of this function.
1379  */
1380 bool pd_Function::findInstPoints(const image *owner) {
1381
1382    if (size() == 0) {
1383      return false;
1384    }
1385
1386    leaf = true;
1387    Address adr;
1388    Address adr1 = getAddress(0);
1389    instruction instr;
1390    instr.raw = owner->get_instruction(adr1);
1391    if (!IS_VALID_INSN(instr))
1392      return false;
1393
1394    // If it contains an instruction, I assume it would be s system call
1395    // which will be treat differently. 
1396    isTrap = false;
1397    bool func_entry_found = false;
1398
1399    for ( ; adr1 < getAddress(0) + size(); adr1 += 4) {
1400        instr.raw = owner->get_instruction(adr1);
1401
1402        // If there's an TRAP instruction in the function, we 
1403        // assume that it is an system call and will relocate it 
1404        // to the heap
1405        if (isInsnType(instr, TRAPmask, TRAPmatch)) {
1406            isTrap = true;
1407            return findInstPoints(owner, getAddress(0), 0);
1408        } 
1409
1410        // TODO: This is a hacking for the solaris(solaris2.5 actually)
1411        // We will relocate that function if the function has been 
1412        // tail-call optimazed.
1413        // (Actully, the reason of this is that the system calls like 
1414        //  read, write, etc have the tail-call optimazation to call
1415        //  the _read, _write etc. which contain the TRAP instruction 
1416        //  This is only done if libc is statically linked...if the
1417        //  libTag is set, otherwise we instrument read and _read
1418        //  both for the dynamically linked case
1419        if (isLibTag()) {
1420            if (isCallInsn(instr)) {
1421                instruction nexti; 
1422                nexti.raw = owner->get_instruction(adr1+4);
1423                
1424                if (nexti.rest.op == 2 
1425                    && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1426                        || nexti.rest.op3 == RESTOREop3)) {
1427                    isTrap = true;
1428                    return findInstPoints(owner, getAddress(0), 0);
1429                }
1430            }   
1431        }
1432
1433        // The function Entry is defined as the first SAVE instruction plus
1434        // the instructions after this.
1435        // ( The first instruction for the nonleaf function is not 
1436        //   necessarily a SAVE instruction. ) 
1437        if (isInsnType(instr, SAVEmask, SAVEmatch) && !func_entry_found) {
1438
1439            leaf = false;
1440            func_entry_found = true;
1441            funcEntry_ = new instPoint(this, instr, owner, adr1, true, leaf, 
1442                                       functionEntry);
1443            adr = adr1;
1444            assert(funcEntry_);
1445        }
1446    }
1447
1448    // If there's no SAVE instruction found, this is a leaf function and
1449    // and function Entry will be defined from the first instruction
1450    if (leaf) {
1451        adr = getAddress(0);
1452        instr.raw = owner->get_instruction(adr);
1453        funcEntry_ = new instPoint(this, instr, owner, adr, true, leaf, functionEntry);
1454        assert(funcEntry_);
1455    }
1456
1457    for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1458
1459      instr.raw = owner->get_instruction(adr);
1460
1461      bool done;
1462
1463      // check for return insn and as a side affect decide if we are at the
1464      //   end of the function.
1465      if (isReturnInsn(owner, adr, done)) {
1466        // define the return point
1467        funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
1468                                     functionExit);
1469
1470      } else if (instr.branch.op == 0 
1471                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6) 
1472                 && (instr.branch.cond == 0 ||instr.branch.cond == 8)) {
1473        // find if this branch is going out of the function
1474        int disp = instr.branch.disp22;
1475        Address target = adr +  (disp << 2);
1476        if ((target < (getAddress(0)))  
1477            || (target >= (getAddress(0) + size()))) {
1478          instPoint *point = new instPoint(this, instr, owner, adr, false, leaf, 
1479                                           functionExit);
1480          funcReturns += point;
1481        }
1482
1483      } else if (isCallInsn(instr)) {
1484
1485        // if the call target is the address of the call instruction
1486        // then this is not something that we can instrument...
1487        // this occurs in functions with code that is modifined when 
1488        // they are loaded by the run-time linker, or when the .init
1489        // section is executed.  In this case the instructions in the
1490        // parsed image file are different from the ones in the executable
1491        // process.
1492        if(instr.call.op == CALLop) { 
1493            Address call_target = adr + (instr.call.disp30 << 2);
1494            if(call_target == adr){ 
1495                 return false;
1496        }}
1497        // first, check for tail-call optimization: a call where the instruction 
1498        // in the delay slot write to register %o7(15), usually just moving
1499        // the caller's return address, or doing a restore
1500        // Tail calls are instrumented as return points, not call points.
1501
1502
1503        instruction nexti; 
1504        nexti.raw = owner->get_instruction(adr+4);
1505
1506        if (nexti.rest.op == 2 
1507            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1508               || nexti.rest.op3 == RESTOREop3)) {
1509          //fprintf(stderr, "#### Tail-call optimization in function %s, addr %x\n",
1510          //     prettyName().string_of(), adr);
1511          funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
1512                                       functionExit);
1513
1514        } else {
1515          // define a call point
1516          // this may update address - sparc - aggregate return value
1517          // want to skip instructions
1518          bool err;
1519          int dummyId;
1520          instPoint *blah = 0;
1521          adr = newCallPoint(adr, instr, owner, err, dummyId, adr,0,blah);
1522        }
1523      }
1524
1525      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1526        /* A register indirect jump. Some jumps may exit the function 
1527           (e.g. read/write on SunOS). In general, the only way to 
1528           know if a jump is exiting the function is to instrument
1529           the jump to test if the target is outside the current 
1530           function. Instead of doing this, we just check the 
1531           previous two instructions, to see if they are loading
1532           an address that is out of the current function.
1533           This should catch the most common cases (e.g. read/write).
1534           For other cases, we would miss a return point.
1535
1536           This is the case considered:
1537
1538              sethi addr_hi, r
1539              or addr_lo, r, r
1540              jump r
1541         */
1542
1543        reg jumpreg = instr.rest.rs1;
1544        instruction prev1;
1545        instruction prev2;
1546
1547        prev1.raw = owner->get_instruction(adr-4);
1548        prev2.raw = owner->get_instruction(adr-8);
1549
1550        unsigned targetAddr;
1551
1552        if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1553            && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1554            && prev2.sethi.rd == (unsigned)jumpreg
1555            && prev1.rest.op == RESTop 
1556            && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1557            && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg) {
1558
1559          targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1560          targetAddr |= prev1.resti.simm13;
1561          if ((targetAddr<getAddress(0))||(targetAddr>=(getAddress(0)+size()))){
1562            instPoint *point = new instPoint(this, instr, owner, adr, false, 
1563                                             leaf, functionExit);
1564            funcReturns += point;
1565          }
1566        }
1567
1568      }
1569  }
1570
1571  return (checkInstPoints(owner)); 
1572 }
1573
1574 /*
1575  * Check all the instPoints within this function to see if there's 
1576  * any conficts happen.
1577  */
1578 bool pd_Function::checkInstPoints(const image *owner) {
1579
1580     // Our own library function, skip the test.
1581     if (prettyName().prefixed_by("DYNINST")) 
1582         return true;
1583
1584 #ifndef BPATCH_LIBRARY /* XXX Users of libdyninstAPI might not agree. */
1585     // The function is too small to be worthing instrumenting.
1586     if (size() <= 12){
1587         return false;
1588     }
1589 #endif
1590
1591     // No function return! return false;
1592     if (sizeof(funcReturns) == 0) {
1593         return false;
1594     }
1595
1596     instruction instr;
1597     Address adr = getAddress(0);
1598
1599     bool retl_inst = false;
1600     // Check if there's any branch instruction jump to the middle
1601     // of the instruction sequence in the function entry point
1602     // and function exit point.
1603     for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1604
1605         instr.raw = owner->get_instruction(adr);
1606         if(isInsnType(instr, RETLmask, RETLmatch)) retl_inst = true;
1607
1608         if (isInsnType(instr, BRNCHmask, BRNCHmatch)||
1609             isInsnType(instr, FBRNCHmask, FBRNCHmatch)) {
1610
1611             int disp = instr.branch.disp22;
1612             Address target = adr + (disp << 2);
1613
1614             if ((target > funcEntry_->addr)&&
1615                 (target < (funcEntry_->addr + funcEntry_->size))) {
1616                 if (adr > (funcEntry_->addr+funcEntry_->size)){
1617                     //cout << "Function " << prettyName().string_of() <<" entry" << endl;
1618                     return false;
1619             } }
1620
1621             for (u_int i = 0; i < funcReturns.size(); i++) {
1622                 if ((target > funcReturns[i]->addr)&&
1623                     (target < (funcReturns[i]->addr + funcReturns[i]->size))) {
1624                     if ((adr < funcReturns[i]->addr)||
1625                         (adr > (funcReturns[i]->addr + funcReturns[i]->size))){
1626                         return false;
1627                 } }
1628             }
1629         }
1630     }
1631
1632     // if there is a retl instruction and we don't think this is a leaf
1633     // function then this is a way messed up function...well, at least we
1634     // we can't deal with this...the only example I can find is _cerror
1635     // and _cerror64 in libc.so.1
1636     if(retl_inst && !leaf){
1637          return false;
1638     }
1639
1640     // check that no instrumentation points could overlap
1641     Address func_entry = funcEntry_->addr + funcEntry_->size; 
1642     for (u_int i = 0; i < funcReturns.size(); i++) {
1643         if(func_entry >= funcReturns[i]->addr){
1644            return false;
1645         }
1646         if(i >= 1){ // check if return points overlap
1647             Address prev_exit = funcReturns[i-1]->addr+funcReturns[i-1]->size;  
1648             if(funcReturns[i]->addr < prev_exit) {
1649                 return false;
1650             } 
1651         }
1652     }
1653
1654     return true;        
1655 }
1656
1657
1658 /* The maximum length of relocatable function is 1k instructions */  
1659 // This function is to find the inst Points for a function
1660 // that will be relocated if it is instrumented. 
1661 bool pd_Function::findInstPoints(const image *owner, Address newAdr, process*){
1662
1663    int i;
1664    if (size() == 0) {
1665      return false;
1666    }
1667    relocatable_ = true;
1668
1669    Address adr = getAddress(0);
1670    instruction instr;
1671    instr.raw = owner->get_instruction(adr);
1672    if (!IS_VALID_INSN(instr))
1673      return false;
1674    
1675    if (size() <= 3*sizeof(instruction)) 
1676        return false;
1677
1678    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1679                                     functionEntry, adr);
1680
1681    funcEntry_ = point;
1682
1683    // if the second instruction in a relocated function is a call instruction
1684    // or a branch instruction, then we can't deal with this 
1685    if(size() > sizeof(instruction)){
1686        Address second_adr = adr + sizeof(instruction);
1687        instruction second_instr;
1688        second_instr.raw =  owner->get_instruction(second_adr); 
1689        if ((isCallInsn(second_instr)) || 
1690                       (second_instr.branch.op == 0 && 
1691                       (second_instr.branch.op2 == 2 || 
1692                       second_instr.branch.op2 == 6))) {
1693            return false;
1694        }
1695    }
1696    
1697    assert(funcEntry_);
1698    int retId = 0;
1699    int callsId = 0; 
1700
1701    for (i = 0; adr < getAddress(0) + size(); adr += sizeof(instruction),  
1702         newAdr += sizeof(instruction), i++) {
1703
1704      instr.raw = owner->get_instruction(adr);
1705      newInstr[i] = instr;
1706      bool done;
1707
1708      // check for return insn and as a side affect decide if we are at the
1709      //   end of the function.
1710      if (isReturnInsn(owner, adr, done)) {
1711        // define the return point
1712        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1713                                         functionExit, adr);
1714        funcReturns += point;
1715        funcReturns[retId] -> instId = retId++;
1716      } else if (instr.branch.op == 0 
1717                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1718        // find if this branch is going out of the function
1719        int disp = instr.branch.disp22;
1720        Address target = adr + (disp << 2);
1721        if (target < getAddress(0) || target >= getAddress(0) + size()) {
1722            instPoint *point = new instPoint(this, newInstr[i], owner, 
1723                                             newAdr, false, 
1724                                             functionExit, adr);
1725            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1726                point->isBranchOut = true;
1727                point->branchTarget = target;
1728            }
1729            funcReturns += point;
1730            funcReturns[retId] -> instId = retId++;
1731        }
1732
1733      } else if (isCallInsn(instr)) {
1734
1735        // first, check for tail-call optimization: a call where the instruction 
1736        // in the delay slot write to register %o7(15), usually just moving
1737        // the caller's return address, or doing a restore
1738        // Tail calls are instrumented as return points, not call points.
1739        instruction nexti; 
1740        nexti.raw = owner->get_instruction(adr+4);
1741
1742        if (nexti.rest.op == 2 
1743            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1744               || nexti.rest.op3 == RESTOREop3)) {
1745
1746            instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1747                                       functionExit, adr);
1748            funcReturns += point;
1749            funcReturns[retId] -> instId = retId++;
1750
1751        } else {
1752          // if this is a call instr to a location within the function, and if 
1753          // the offest is not 8 then do not define this function 
1754          if(instr.call.op == CALLop){ 
1755            Address call_target = adr + (instr.call.disp30 << 2);
1756            if((call_target >= getAddress(0)) 
1757               && (call_target <= (getAddress(0)+size()))){ 
1758               if((instr.call.disp30 << 2) != 2*sizeof(instruction)) {
1759                 return false;
1760               }
1761            }
1762          }
1763          // define a call point
1764          // this may update address - sparc - aggregate return value
1765          // want to skip instructions
1766          bool err;
1767          instPoint *blah = 0;
1768          adr = newCallPoint(newAdr, instr, owner, err, callsId, adr,0,blah);
1769          if (err)
1770            return false;
1771        }
1772      }
1773
1774      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1775        /* A register indirect jump. Some jumps may exit the function 
1776           (e.g. read/write on SunOS). In general, the only way to 
1777           know if a jump is exiting the function is to instrument
1778           the jump to test if the target is outside the current 
1779           function. Instead of doing this, we just check the 
1780           previous two instructions, to see if they are loading
1781           an address that is out of the current function.
1782           This should catch the most common cases (e.g. read/write).
1783           For other cases, we would miss a return point.
1784
1785           This is the case considered:
1786
1787              sethi addr_hi, r
1788              or addr_lo, r, r
1789              jump r
1790         */
1791
1792          reg jumpreg = instr.rest.rs1;
1793          instruction prev1;
1794          instruction prev2;
1795          
1796          prev1.raw = owner->get_instruction(adr-4);
1797          prev2.raw = owner->get_instruction(adr-8);
1798
1799          unsigned targetAddr;
1800
1801          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1802              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1803              && prev2.sethi.rd == (unsigned)jumpreg
1804              && prev1.rest.op == RESTop 
1805              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1806              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
1807              
1808              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1809              targetAddr |= prev1.resti.simm13;
1810              if ((targetAddr < getAddress(0)) 
1811                  || (targetAddr >= (getAddress(0)+size()))) {
1812                  instPoint *point = new instPoint(this, instr, owner, 
1813                                                   newAdr, false,
1814                                                   functionExit, adr);
1815                  funcReturns += point;
1816                  funcReturns[retId] -> instId = retId++;
1817              }
1818          }
1819      }
1820  }
1821  return true;
1822 }
1823
1824 // This function assigns new address to instrumentation points of  
1825 // a function that has been relocated
1826 bool pd_Function::findNewInstPoints(const image *owner, 
1827                                 const instPoint *&location,
1828                                 Address newAdr,
1829                                 process *proc,
1830                                 vector<instruction> &callInstrs,
1831                                 relocatedFuncInfo *reloc_info) {
1832
1833    int i;
1834    if (size() == 0) {
1835      return false;
1836    }
1837    assert(reloc_info);
1838
1839    Address adr = getAddress(0);
1840    instruction instr;
1841    instr.raw = owner->get_instruction(adr);
1842    if (!IS_VALID_INSN(instr))
1843      return false;
1844
1845    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1846                                     functionEntry, adr);
1847    point->relocated_ = true;
1848    // if location was the entry point then change location's value to new pt
1849    if(location == funcEntry_) { 
1850         location = point;
1851    }
1852
1853    reloc_info->addFuncEntry(point);
1854    assert(reloc_info->funcEntry());
1855    int retId = 0;
1856    int callsId = 0; 
1857
1858    // get baseAddress if this is a shared object
1859    Address baseAddress = 0;
1860    if(!(proc->getBaseAddress(owner,baseAddress))){
1861         baseAddress =0;
1862    }
1863
1864    // if we have call instructions that need to be added after the instrs
1865    // to call the relocated instruction, the first address we can use is
1866    // the address of the 4th instruction in the function
1867    Address call_start_addr = getAddress(0)+baseAddress + 3*sizeof(instruction);
1868
1869    for (i = 0; adr < getAddress(0) + size(); adr += 4,  newAdr += 4, i++) {
1870     
1871      instr.raw = owner->get_instruction(adr);
1872      newInstr[i] = instr;
1873
1874      bool done;
1875
1876      // check for return insn and as a side affect decide if we are at the
1877      //   end of the function.
1878      if (isReturnInsn(owner, adr, done)) {
1879        // define the return point
1880        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1881                                         functionExit, adr);
1882        point->relocated_ = true;
1883        // if location was this point, change it to new point
1884        if(location == funcReturns[retId]) { 
1885            location = point;
1886        }
1887        retId++;
1888        reloc_info->addFuncReturn(point);
1889      } else if (instr.branch.op == 0 
1890                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1891        // find if this branch is going out of the function
1892        int disp = instr.branch.disp22;
1893        Address target = adr + baseAddress + (disp << 2);
1894
1895        // getAddress(0) gives the addr of the fn before it's relocated
1896        if ((target < (getAddress(0) + baseAddress)) 
1897            || (target >= (getAddress(0) + baseAddress + size()))) {
1898            // the original branch went out of the function...
1899
1900            relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
1901            instPoint *point = new instPoint(this, newInstr[i], owner, 
1902                                             newAdr, false, 
1903                                             functionExit, adr);
1904            point->relocated_ = true;
1905            disp = newInstr[i].branch.disp22;
1906            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1907                point->isBranchOut = true;
1908                point->branchTarget = adr + (disp<<2);
1909            }
1910            // if location was this point, change it to new point
1911            if(location == funcReturns[retId]) { 
1912                location = point;
1913            }
1914            retId++;
1915            reloc_info->addFuncReturn(point);
1916        }
1917
1918      } else if (isCallInsn(instr)) {
1919
1920        // first, check for tail-call optimization: a call where the instruction 
1921        // in the delay slot write to register %o7(15), usually just moving
1922        // the caller's return address, or doing a restore
1923        // Tail calls are instrumented as return points, not call points.
1924        instruction nexti; 
1925        nexti.raw = owner->get_instruction(adr+4);
1926
1927        if (nexti.rest.op == 2 
1928            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1929               || nexti.rest.op3 == RESTOREop3)) {
1930
1931             // Undoing the tail-call optimazation when the function
1932             // is relocated. Here is an example:
1933             //   before:          --->             after
1934             // ---------------------------------------------------
1935             //   call  %g1                        restore    
1936             //   restore                          st  %i0, [ %fp + 0x44 ]
1937             //                                    mov %o7 %i0
1938             //                                    call %g1 
1939             //                                    nop
1940             //                                    mov %i0,%o7
1941             //                                    st  [ %fp + 0x44 ], %i0
1942             //                              retl
1943             //                                    nop
1944             // Q: Here the assumption that register i1 is available 
1945             //    might be an question, is it?
1946             // A: I think it is appropriate because:
1947             //      (in situation A calls B and B calls C)
1948             //      The procedure C called via tail call is a leaf 
1949             //      procedure, the value arguments and return value between
1950             //      A and C are passed by register (o1...o5, o7)
1951             //      So even If B mess up the value of i0, it won't affect the
1952             //      commnucation between A and C. Also, we saved the value of
1953             //      i0 on stack and when we return from B, the value of i0
1954             //      won't be affected.
1955             //      If C is not a leaf procedure, it should be fine
1956             //      as it is.
1957             //    ( If you could give an counter-example, please
1958             //      let me know.                         --ling )
1959
1960             genSimpleInsn(&newInstr[i++], RESTOREop3, 0, 0, 0);
1961             generateStore(&newInstr[i++], 24, REG_FP, 0x44); 
1962             genImmInsn(&newInstr[i++], ORop3, 15, 0, 24); 
1963             newInstr[i++].raw = owner->get_instruction(adr);
1964             generateNOOP(&newInstr[i++]);
1965             genImmInsn(&newInstr[i++], ORop3, 24, 0, 15);
1966             generateLoad(&newInstr[i++], REG_FP, 0x44, 24);         
1967             generateJmplInsn(&newInstr[i++], 15, 8 ,0);
1968             newAdr += 28;
1969             generateNOOP(&newInstr[i]);
1970             instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1971                                       functionExit, adr);
1972             point-> originalInstruction = newInstr[i-1];
1973             point-> delaySlotInsn = newInstr[i];
1974             point-> isDelayed = true;
1975             point->relocated_ = true;
1976             // if location was this point, change it to new point
1977             if(location == funcReturns[retId]) { 
1978                 location = point;
1979             }
1980             retId++;
1981             reloc_info->addFuncReturn(point);
1982        } else {
1983          // if the second instruction in the function is a call instruction
1984          // then this cannot go in the delay slot of the branch to the
1985          // base tramp, so add a noop between first and second instructions
1986          // in the relocated function (check out write in libc.so.1 for
1987          // and example of this):
1988          //
1989          //     save  %sp, -96, %sp             brach to base tramp
1990          //     call  0x73b70                   nop
1991          //                                     call 0x73b70
1992          if(adr == (getAddress(0)+4)){
1993              newInstr[i+1] = instr;
1994              generateNOOP(&newInstr[i]);
1995              i++;
1996              newAdr += 4;
1997          }
1998
1999          // if this is a call to an address within the same function, then
2000          // we need to set the 07 register to have the same value as it
2001          // would before the function was relocated
2002          // to do this we generate a call instruction back to the original
2003          // function location, and then at this location we generate a call 
2004          // instruction back to the relocated instruction.  In the delay 
2005          // slot of the second instruction the value of 07 is changed by 
2006          // the difference between the origninal call instruction, and 
2007          // the location of the call instruction back to the relocated
2008          // function.  This way the 07 register will contain the address
2009          // of the original call instruction
2010          Address call_target = adr + (instr.call.disp30 << 2);
2011          if((call_target >= getAddress(0)) 
2012                 && (call_target <= (getAddress(0) + size()))){ 
2013             assert((newInstr[i].call.disp30 << 2) == 8);
2014
2015             // generating call instruction to orginal function address
2016             // after the SAVE call RESTORE instr.s that call the relocated
2017             // function 
2018             newInstr[i].call.disp30 = ((call_start_addr -newAdr) >> 2); 
2019
2020             // generate call to relocated function from original function 
2021             // (this will get almost correct value for register 07)
2022             instruction new_inst;
2023             generateCallInsn(&new_inst,call_start_addr,
2024                              newAdr+sizeof(instruction));
2025             callInstrs += new_inst;
2026            
2027             // generate add isntruction to get correct value for 07 register 
2028             // this will go in delay slot of previous call instr.
2029             genImmInsn(&new_inst,ADDop3,REG_O7,
2030                        (adr+baseAddress-call_start_addr),REG_O7);
2031             callInstrs += new_inst;
2032             call_start_addr += 2*sizeof(instruction);
2033          }
2034          else {
2035             // otherwise, this is a call instruction to a location
2036             // outside the function
2037             bool err;
2038             relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
2039             (void)newCallPoint(newAdr, newInstr[i], owner, err, 
2040                                callsId, adr,reloc_info,location);
2041             if (err) return false;
2042          }
2043        }
2044      }
2045
2046      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
2047        /* A register indirect jump. Some jumps may exit the function 
2048           (e.g. read/write on SunOS). In general, the only way to 
2049           know if a jump is exiting the function is to instrument
2050           the jump to test if the target is outside the current 
2051           function. Instead of doing this, we just check the 
2052           previous two instructions, to see if they are loading
2053           an address that is out of the current function.
2054           This should catch the most common cases (e.g. read/write).
2055           For other cases, we would miss a return point.
2056
2057           This is the case considered:
2058
2059              sethi addr_hi, r
2060              or addr_lo, r, r
2061              jump r
2062         */
2063
2064          reg jumpreg = instr.rest.rs1;
2065          instruction prev1;
2066          instruction prev2;
2067          
2068          prev1.raw = owner->get_instruction(adr-4);
2069          prev2.raw = owner->get_instruction(adr-8);
2070
2071          unsigned targetAddr;
2072
2073          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
2074              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
2075              && prev2.sethi.rd == (unsigned)jumpreg
2076              && prev1.rest.op == RESTop 
2077              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
2078              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
2079              
2080              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
2081              targetAddr |= prev1.resti.simm13;
2082              if ((targetAddr < getAddress(0)) 
2083                  || (targetAddr >= (getAddress(0)+size()))) {
2084                  instPoint *point = new instPoint(this, instr, owner, 
2085                                                   newAdr, false,
2086                                                   functionExit, adr);
2087                  point->relocated_ = true;
2088                  // if location was this point, change it to new point
2089                  if(location == funcReturns[retId]) { 
2090                      location = point;
2091                  }
2092                  retId++;
2093                  reloc_info->addFuncReturn(point);
2094              }
2095          }
2096      }
2097  }
2098    
2099    return true;
2100 }