isLeaf() --> hasNoStackFrame() for instPoint and pd_Function
[dyninst.git] / dyninstAPI / src / inst-sparc-sunos.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 #include "util/h/debugOstream.h"
45
46 // Another constructor for the class instPoint. This one is called
47 // for the define the instPoints for regular functions which means
48 // multiple instructions is going to be moved to based trampoline.
49 // Since we will use the instruction CALL to branch to the base
50 // tramp(so it doesn't have any code size restriction), things are
51 // a little more complicated because instruction CALL changes the 
52 // value in the link register.
53 instPoint::instPoint(pd_Function *f, const instruction &instr, 
54                      const image *owner, Address &adr,
55                      bool delayOK, instPointType pointType)
56 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
57   callIndirect(false), callAggregate(false), callee(NULL), func(f),
58   ipType(pointType), image_ptr(owner), firstIsConditional(false),
59   relocated_(false), isLongJump(true)
60 {
61
62   isBranchOut = false;
63   size = 0;
64
65   // When the function has a stack frame
66   if (!hasNoStackFrame()) {
67
68       // we will treat the first instruction after the SAVE instruction
69       // in the nonleaf procedure as the function entry.  
70       if (ipType == functionEntry) {
71
72           assert(isInsnType(instr, SAVEmask, SAVEmatch));
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 += 1*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               }
144           }
145
146           originalInstruction.raw = owner->get_instruction(addr);
147           otherInstruction.raw = owner->get_instruction(addr+4);
148           delaySlotInsn.raw = owner->get_instruction(addr+8);
149           size += 3*sizeof(instruction);
150
151           if (inDelaySlot) {
152               inDelaySlotInsn.raw = owner->get_instruction(addr+12);
153           }
154
155       } else {
156           assert(ipType == callSite);
157           // Usually, a function without a stack frame won't have any call sites
158           extern debug_ostream metric_cerr;
159           metric_cerr << "inst-sparc-solaris.C WARNING: found a leaf fn (no stack frame)" << endl;
160           metric_cerr << "which makes a function call" << endl;
161           metric_cerr << "This fn is " << func->prettyName() << endl;
162
163           //abort();
164       }
165   }
166
167   // return the address in the code segment after this instruction
168   // sequence. (there's a -1 here because one will be added up later in
169   // the function findInstPoints)  
170   adr = addr + (size - 1*sizeof(instruction));
171 }
172
173
174 void AstNode::sysFlag(instPoint *location)
175 {
176     // astFlag = location->func->isTrapFunc();
177     if (astFlag == false)
178         astFlag = (location -> isLongJump)? false:true; 
179     if (loperand)
180         loperand->sysFlag(location);
181     if (roperand)
182         roperand->sysFlag(location); 
183
184     for (unsigned u = 0; u < operands.size(); u++) {
185         operands[u]->sysFlag(location);
186     }
187 }
188
189 // Determine if the called function is a "library" function or a "user" function
190 // This cannot be done until all of the functions have been seen, verified, and
191 // classified
192 //
193 void pd_Function::checkCallPoints() {
194   instPoint *p;
195   Address loc_addr;
196
197   vector<instPoint*> non_lib;
198
199   for (unsigned i=0; i<calls.size(); ++i) {
200     /* check to see where we are calling */
201     p = calls[i];
202     assert(p);
203
204     if (isInsnType(p->originalInstruction, CALLmask, CALLmatch)) {
205       // Direct call
206       loc_addr = p->addr + (p->originalInstruction.call.disp30 << 2);
207       pd_Function *pdf = (file_->exec())->findFunction(loc_addr);
208       if (pdf && !pdf->isLibTag()) {
209         p->callee = pdf;
210         non_lib += p;
211       } else {
212           delete p;
213       }
214     } else {
215       // Indirect call -- be conservative, assume it is a call to 
216       // an unnamed user function
217       assert(!p->callee); assert(p->callIndirect);
218       p->callee = NULL;
219       non_lib += p;
220     }
221   }
222   calls = non_lib;
223 }
224
225 // TODO we cannot find the called function by address at this point in time
226 // because the called function may not have been seen.
227 // reloc_info is 0 if the function is not currently being relocated
228 Address pd_Function::newCallPoint(Address &adr, const instruction instr,
229                                  const image *owner, bool &err, 
230                                  int &callId, Address &oldAddr,
231                                  relocatedFuncInfo *reloc_info,
232                                  const instPoint *&location)
233 {
234     Address ret=adr;
235     instPoint *point;
236
237     err = true;
238     if (isTrap) {
239         point = new instPoint(this, instr, owner, adr, false, callSite, oldAddr);
240     } else {
241         point = new instPoint(this, instr, owner, adr, false, callSite);
242     }
243
244     if (!isInsnType(instr, CALLmask, CALLmatch)) {
245       point->callIndirect = true;
246       point->callee = NULL;
247     } else{
248       point->callIndirect = false;
249     }
250
251     if (isTrap) {
252         if (!reloc_info) {
253             calls += point;
254             calls[callId] -> instId = callId++;
255         } else {
256             // calls to a location within the function are not
257             // kept in the calls vector
258             assert(callId >= 0);
259             assert(((u_int)callId) < calls.size());
260             point->relocated_ = true;
261             // if the location was this call site, then change its value
262             if(location && (calls[callId] == location)) { 
263                 assert(calls[callId]->instId  == location->instId);
264                 location = point; 
265             } 
266             point->instId = callId++;
267             reloc_info->addFuncCall(point);
268         }
269     } else {
270         if (!reloc_info) {
271             calls += point;
272         }
273         else {
274             point->relocated_ = true;
275             reloc_info->addFuncCall(point);
276         }
277     }
278     err = false;
279     return ret;
280 }
281
282 /*
283  * Given and instruction, relocate it to a new address, patching up
284  *   any relative addressing that is present.
285  *
286  */
287 void relocateInstruction(instruction *insn, u_int origAddr, u_int targetAddr,
288                          process *proc)
289 {
290     u_int newOffset;
291
292     // If the instruction is a CALL instruction, calculate the new
293     // offset
294     if (isInsnType(*insn, CALLmask, CALLmatch)) {
295         newOffset = origAddr  - targetAddr + (insn->call.disp30 << 2);
296         insn->call.disp30 = newOffset >> 2;
297     } else if (isInsnType(*insn, BRNCHmask, BRNCHmatch)||
298                isInsnType(*insn, FBRNCHmask, FBRNCHmatch)) {
299
300         // If the instruction is a Branch instruction, calculate the 
301         // new offset. If the new offset is out of reach after the 
302         // instruction is moved to the base Trampoline, we would do
303         // the following:
304         //    b  address  ......    address: save
305         //                                   call new_offset             
306         //                                   restore 
307         newOffset = origAddr - targetAddr + (insn->branch.disp22 << 2);
308         // if the branch is too far, then allocate more space in inferior
309         // heap for a call instruction to branch target.  The base tramp 
310         // will branch to this new inferior heap code, which will call the
311         // target of the branch
312         if (!offsetWithinRangeOfBranchInsn(newOffset)) {
313 //      if (ABS(newOffset) > getMaxBranch1Insn()) {
314             int ret = inferiorMalloc(proc,3*sizeof(instruction), textHeap);
315             u_int old_offset = insn->branch.disp22 << 2;
316             // TODO: this is the wrong branch offset
317             insn->branch.disp22  = (ret - targetAddr)>>2;
318             instruction insnPlus[3];
319             genImmInsn(insnPlus, SAVEop3, REG_SP, -112, REG_SP);
320             generateCallInsn(insnPlus+1, ret+sizeof(instruction), 
321                              origAddr+old_offset);
322             genSimpleInsn(insnPlus+2, RESTOREop3, 0, 0, 0); 
323             proc->writeDataSpace((caddr_t)ret, sizeof(insnPlus), 
324                          (caddr_t) insnPlus);
325         } else {
326             insn->branch.disp22 = newOffset >> 2;
327         }
328     } else if (isInsnType(*insn, TRAPmask, TRAPmatch)) {
329         // There should be no probelm for moving trap instruction
330         // logLine("attempt to relocate trap\n");
331     } 
332     /* The rest of the instructions should be fine as is */
333 }
334
335 /*
336  * Install a base tramp -- fill calls with nop's for now.
337  *
338  * This one install the base tramp for the regular functions.
339  *
340  */
341 trampTemplate *installBaseTramp(const instPoint *&location, process *proc)
342 {
343     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
344
345     instruction *code = new instruction[baseTemplate.size];
346     assert(code);
347
348     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
349
350     instruction *temp;
351     unsigned currAddr;
352     for (temp = code, currAddr = baseAddr; 
353         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
354         temp++, currAddr += sizeof(instruction)) {
355
356         if (temp->raw == EMULATE_INSN) {
357
358             // Load the value of link register from stack 
359             // If no stack frame, genereate a RESTORE instruction
360             // since there's an instruction SAVE generated and put in the
361             // code segment.
362             if (location -> hasNoStackFrame()) {
363                 genImmInsn(temp, RESTOREop3, 0, 0, 0);
364                 temp++;
365                 currAddr += sizeof(instruction);
366             } 
367
368             // Same for the leaf and nonleaf functions.
369             // First, relocate the "FIRST instruction" in the sequence;  
370             *temp = location->originalInstruction;
371             Address fromAddr = location->addr;
372             relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
373
374             // Again, for leaf function, one more is needed to move for one
375             // more spot;
376             if (location->hasNoStackFrame()) {
377                 fromAddr += sizeof(instruction);
378                 currAddr += sizeof(instruction);
379                 *++temp = location->otherInstruction;
380                 relocateInstruction(temp, fromAddr, currAddr, 
381                                     (process *)proc);
382             }     
383             
384             // Second, relocate the "NEXT instruction";
385             fromAddr += sizeof(instruction);
386             currAddr += sizeof(instruction);
387             *++temp = location->delaySlotInsn;
388             relocateInstruction(temp, fromAddr, currAddr,
389                                 (process *)proc);
390             
391             // Third, if the "NEXT instruction" is a DCTI, 
392             if (location->isDelayed) {
393                 fromAddr += sizeof(instruction);
394                 currAddr += sizeof(instruction);
395                 *++temp = location->isDelayedInsn;
396                 relocateInstruction(temp, fromAddr, currAddr,
397                                     (process *)proc);
398                 
399                 // Then, possibly, there's an callAggregate instruction
400                 // after this. 
401                 if (location->callAggregate) {
402                     currAddr += sizeof(instruction);
403                     *++temp = location->aggregateInsn;
404                     continue;
405                 }       
406             }
407             
408             // If the "FIRST instruction" is a DCTI, then our so called 
409             // "NEXT instruction" is in the delayed Slot and this might
410             // happen. (actullay, it happened)
411             if (location->callAggregate) {
412                 currAddr += sizeof(instruction);
413                 *++temp = location->aggregateInsn;
414                 continue;
415             }   
416             
417             // For the leaf function, if there's an inDelaySlot instruction,
418             // move this one to the base Tramp.(i.e. at the function exit,
419             // if the first instruction is in the delayed slot the previous
420             // instruction, we have to move that one too, so we count from 
421             // that one and the last one is this sequence is called inDelaySlot
422             // instruction.)
423             // Well, after all these, another SAVE instruction is generated
424             // so we are prepared to handle the returning to our application's
425             // code segment. 
426             if (location->hasNoStackFrame()) {
427                 if (location->inDelaySlot) {
428                     fromAddr += sizeof(instruction);
429                     currAddr += sizeof(instruction);
430                     *++temp = location->inDelaySlotInsn;
431                     relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
432                 } 
433                 
434                 genImmInsn(temp+1, SAVEop3, REG_SP, -112, REG_SP);
435             }
436             
437         } else if (temp->raw == RETURN_INSN) {
438             // Back to the code segement of the application.
439             // If the location is in the leaf procedure, generate an RESTORE
440             // instruction right after the CALL instruction to restore all
441             // the values in the registers.
442             if (location -> hasNoStackFrame()) {
443                 generateCallInsn(temp, currAddr, location->addr+location->size);
444                 genImmInsn(temp+1, RESTOREop3, 0, 0, 0);
445             } else {
446                 generateCallInsn(temp, currAddr, location->addr+location->size);
447             }
448         } else if (temp->raw == SKIP_PRE_INSN) {
449             unsigned offset;
450             offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
451             generateAnnulledBranchInsn(temp,offset);
452
453         } else if (temp->raw == SKIP_POST_INSN) {
454             unsigned offset;
455             offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
456             generateAnnulledBranchInsn(temp,offset);
457
458         } else if (temp->raw == UPDATE_COST_INSN) {
459             
460             baseTemplate.costAddr = currAddr;
461             generateNOOP(temp);
462         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
463                    (temp->raw == GLOBAL_PRE_BRANCH) ||
464                    (temp->raw == LOCAL_POST_BRANCH) ||
465                    (temp->raw == GLOBAL_POST_BRANCH)) {
466 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
467             if ((temp->raw == LOCAL_PRE_BRANCH) ||
468                 (temp->raw == LOCAL_POST_BRANCH)) {
469                 temp -= NUM_INSN_MT_PREAMBLE;
470                 unsigned numIns=0;
471                 generateMTpreamble((char *)temp, numIns, proc);
472                 temp += NUM_INSN_MT_PREAMBLE;
473             }
474 #endif
475             /* fill with no-op */
476             generateNOOP(temp);
477         }
478     }
479     // TODO cast
480     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
481
482     delete [] code;
483
484     trampTemplate *baseInst = new trampTemplate;
485     *baseInst = baseTemplate;
486     baseInst->baseAddr = baseAddr;
487     return baseInst;
488 }
489
490 /*
491  * Install the base Tramp for the function relocated.
492  * (it means the base tramp that don't need to bother with long jump and
493  *  is the one we used before for all the functions(since there's no
494  *  long jumps)
495  *  for system calls
496  */ 
497 trampTemplate *installBaseTrampSpecial(const instPoint *&location,
498                              process *proc,
499                              vector<instruction> &extra_instrs) 
500 {
501     unsigned currAddr;
502     instruction *code;
503     instruction *temp;
504
505     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
506
507     if(!(location->func->isInstalled(proc))) {
508         location->func->relocateFunction(proc,location,extra_instrs);
509     }
510     else if(!location->relocated_){
511         // need to find new instPoint for location...it has the pre-relocated
512         // address of the instPoint
513         location->func->modifyInstPoint(location,proc);      
514     }
515
516     code = new instruction[baseTemplate.size];
517     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
518
519     for (temp = code, currAddr = baseAddr; 
520         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
521         temp++, currAddr += sizeof(instruction)) {
522
523         if (temp->raw == EMULATE_INSN) {
524             if (location->isBranchOut) {
525                 // the original instruction is a branch that goes out of a 
526                 // function.  We don't relocate the original instruction. We 
527                 // only get to the tramp is the branch is taken, so we generate
528                 // a unconditional branch to the target of the original 
529                 // instruction here 
530                 assert(location->branchTarget);
531                 int disp = location->branchTarget - currAddr;
532                 generateAnnulledBranchInsn(temp, disp);
533                 disp = temp->branch.disp22;
534                 continue;
535             }
536             else {
537                 *temp = location->originalInstruction;
538                 Address fromAddress = location->addr;
539                 relocateInstruction(temp, fromAddress, currAddr, proc);
540                 if (location->isDelayed) {
541                     /* copy delay slot instruction into tramp instance */
542                     currAddr += sizeof(instruction);  
543                     *++temp = location->delaySlotInsn;
544                 }
545                 if (location->callAggregate) {
546                     /* copy invalid insn with aggregate size in it */
547                     currAddr += sizeof(instruction);  
548                     *++temp = location->aggregateInsn;
549                 }
550             }
551         } else if (temp->raw == RETURN_INSN) {
552             generateAnnulledBranchInsn(temp, 
553                 (location->addr+ sizeof(instruction) - currAddr));
554             if (location->isDelayed) {
555                 /* skip the delay slot instruction */
556                 temp->branch.disp22 += 1;
557             }
558             if (location->callAggregate) {
559                 /* skip the aggregate size slot */
560                 temp->branch.disp22 += 1;
561             }
562         } else if (temp->raw == SKIP_PRE_INSN) {
563           unsigned offset;
564           offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
565           generateAnnulledBranchInsn(temp,offset);
566         } else if (temp->raw == SKIP_POST_INSN) {
567           unsigned offset;
568           offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
569           generateAnnulledBranchInsn(temp,offset);
570         } else if (temp->raw == UPDATE_COST_INSN) {
571             baseTemplate.costAddr = currAddr;
572             generateNOOP(temp);
573         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
574                    (temp->raw == GLOBAL_PRE_BRANCH) ||
575                    (temp->raw == LOCAL_POST_BRANCH) ||
576                    (temp->raw == GLOBAL_POST_BRANCH)) {
577 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
578             if ((temp->raw == LOCAL_PRE_BRANCH) ||
579                 (temp->raw == LOCAL_POST_BRANCH)) {
580                 temp -= NUM_INSN_MT_PREAMBLE;
581                 unsigned numIns=0;
582                 generateMTpreamble((char *)temp, numIns, proc);
583                 temp += NUM_INSN_MT_PREAMBLE;
584             }
585 #endif
586             /* fill with no-op */
587             generateNOOP(temp);
588         }
589     }
590     // TODO cast
591     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
592
593     delete [] code;
594
595     trampTemplate *baseInst = new trampTemplate;
596     *baseInst = baseTemplate;
597     baseInst->baseAddr = baseAddr;
598     return baseInst;
599 }
600
601 /*
602  * Allocate the space for the base Trampoline, and generate the instruction
603  * we need for modifying the code segment
604  *
605  */
606 trampTemplate *findAndInstallBaseTramp(process *proc, 
607                                  instPoint *&location,
608                                  returnInstance *&retInstance,
609                                  bool )
610 {
611     Address adr = location->addr;
612     trampTemplate *ret;
613     retInstance = NULL;
614     if (!proc->baseMap.defines((const instPoint *)location)) {
615         if (location->func->isTrapFunc()) {
616             // Install Base Tramp for the functions which are 
617             // relocated to the heap.
618             vector<instruction> extra_instrs;
619             ret = installBaseTrampSpecial(location,proc,extra_instrs);
620             if (location->isBranchOut){
621                 changeBranch(proc, location->addr, (int) ret->baseAddr, 
622                              location->originalInstruction);
623             } else {
624                 generateBranch(proc, location->addr, (int)ret->baseAddr);
625             }
626
627             // If for this process, a call to the relocated function has not
628             // yet be installed in its original location, then genterate the
629             // following instructions at the begining of the function:
630             //   SAVE;             CALL;         RESTORE.
631             // so that it would jump the start of the relocated function
632             // which is in heap.
633             if(!(location->func->isInstalled(proc))){
634                 location->func->setInstalled(proc);
635                 u_int e_size = extra_instrs.size();
636                 instruction *insn = new instruction[3 + e_size];
637                 Address adr = location-> func -> getAddress(0);
638                 genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
639                 generateCallInsn(insn+1, adr+4, 
640                                  location->func->getAddress(proc));
641                 genSimpleInsn(insn+2, RESTOREop3, 0, 0, 0); 
642                 for(u_int i=0; i < e_size; i++){
643                     insn[3+i] = extra_instrs[i];
644                 }
645                 retInstance = new returnInstance((instructUnion *)insn, 
646                                          (3+e_size)*sizeof(instruction), 
647                                          adr, location->func->size());
648                 assert(retInstance);
649
650                 //cerr << "created a new return instance (relocated fn)!" << endl;
651             }
652
653         } else {
654             // Install base tramp for all the other regular functions. 
655             ret = installBaseTramp(location, proc);
656             if (location->hasNoStackFrame()) {
657                 // if it is the leaf function, we need to generate
658                 // the following instruction sequence:
659                 //     SAVE;      CALL;      NOP.
660                 instruction *insn = new instruction[3];
661                 genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
662                 generateCallInsn(insn+1, adr+4, (int) ret->baseAddr);
663                 generateNOOP(insn+2);
664                 retInstance = new returnInstance((instructUnion *)insn, 
665                                                  3*sizeof(instruction), adr, 
666                                                  3*sizeof(instruction));
667                 assert(retInstance);
668             } else {
669                 // Otherwise,
670                 // Generate branch instruction from the application to the
671                 // base trampoline and no SAVE instruction is needed
672                 instruction *insn = new instruction[2]; 
673                 assert(insn);
674
675                 generateCallInsn(insn, adr, (int) ret->baseAddr);
676                 generateNOOP(insn+1);
677
678                 retInstance = new returnInstance((instructUnion *)insn, 
679                                                  2*sizeof(instruction), adr, 
680                                                  2*sizeof(instruction));
681                 assert(retInstance);
682             }
683         }
684
685         proc->baseMap[(const instPoint *)location] = ret;
686
687     } else {
688         ret = proc->baseMap[(const instPoint *)location];
689     }
690       
691     return(ret);
692 }
693
694 /*
695  * Install a single tramp.
696  *
697  */
698 void installTramp(instInstance *inst, char *code, int codeSize)
699 {
700     totalMiniTramps++;
701     insnGenerated += codeSize/sizeof(int);
702
703     // TODO cast
704    (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
705
706     unsigned atAddr;
707     if (inst->when == callPreInsn) {
708         if (inst->baseInstance->prevInstru == false) {
709             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPreInsOffset;
710             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
711             inst->baseInstance->prevInstru = true;
712             generateNoOp(inst->proc, atAddr);
713         }
714     } else {
715         if (inst->baseInstance->postInstru == false) {
716             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPostInsOffset
717             ;
718             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
719             inst->baseInstance->postInstru = true;
720             generateNoOp(inst->proc, atAddr);
721         }
722     }
723     // What does this next statement do? atAddr could be not initialized here!
724     //  jkh 3/12/97
725     //generateNoOp(inst->proc, atAddr);
726 }
727
728
729 unsigned emitFuncCall(opCode op, 
730                       registerSpace *rs,
731                       char *i, unsigned &base, 
732                       const vector<AstNode *> &operands, 
733                       const string &callee, process *proc,
734                       bool noCost)
735 {
736         assert(op == callOp);
737         unsigned addr;
738         bool err;
739         vector <reg> srcs;
740         void cleanUpAndExit(int status);
741
742         addr = proc->findInternalAddress(callee, false, err);
743
744         if (err) {
745             function_base *func = proc->findOneFunction(callee);
746             if (!func) {
747                 ostrstream os(errorLine, 1024, ios::out);
748                 os << "Internal error: unable to find addr of " << callee << endl;
749                 logLine(errorLine);
750                 showErrorCallback(80, (const char *) errorLine);
751                 P_abort();
752             }
753             // TODO: is this correct or should we get relocated address?
754             addr = func->getAddress(0);
755         }
756         
757         for (unsigned u = 0; u < operands.size(); u++)
758             srcs += operands[u]->generateCode(proc, rs, i, base, noCost);
759
760         // TODO cast
761         instruction *insn = (instruction *) ((void*)&i[base]);
762
763         for (unsigned u=0; u<srcs.size(); u++){
764             if (u >= 5) {
765                  string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
766                  fprintf(stderr, msg.string_of());
767                  showErrorCallback(94,msg);
768                  cleanUpAndExit(-1);
769             }
770             genSimpleInsn(insn, ORop3, 0, srcs[u], u+8); insn++;
771             base += sizeof(instruction);
772             rs->freeRegister(srcs[u]);
773         }
774
775         // As Ling pointed out to me, the following is rather inefficient.  It does:
776         //   sethi %hi(addr), %o5
777         //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
778         //   nop
779         // We can do better:
780         //   call <addr>    (but note that the call true-instr is pc-relative jump)
781         //   nop
782         generateSetHi(insn, addr, 13); insn++;
783         genImmInsn(insn, JMPLop3, 13, LOW10(addr), 15); insn++;
784         generateNOOP(insn);
785
786         base += 3 * sizeof(instruction);
787
788         // return value is the register with the return value from the
789         //   function.
790         // This needs to be %o0 since it is back in the callers scope.
791         return(8);
792 }
793  
794 unsigned emit(opCode op, reg src1, reg src2, reg dest, char *i, unsigned &base,
795               bool noCost)
796 {
797     // TODO cast
798     instruction *insn = (instruction *) ((void*)&i[base]);
799
800     if (op == loadConstOp) {
801       // dest = src1:imm    TODO
802       if (src1 > MAX_IMM13 || src1 < MIN_IMM13) {
803             // src1 is out of range of imm13, so we need an extra instruction
804             generateSetHi(insn, src1, dest);
805             base += sizeof(instruction);
806             insn++;
807
808             // or regd,imm,regd
809
810             // Chance for optimization: we should check for LOW10(src1)==0, and
811             // if so, don't generate the following bitwise-or instruction, since
812             // in that case nothing would be done.
813
814             genImmInsn(insn, ORop3, dest, LOW10(src1), dest);
815             base += sizeof(instruction);
816         } else {
817             // really or %g0,imm,regd
818             genImmInsn(insn, ORop3, 0, src1, dest);
819
820             base += sizeof(instruction);
821         }
822     } else if (op ==  loadOp) {
823         // dest = [src1]   TODO
824         generateSetHi(insn, src1, dest);
825         insn++;
826
827         generateLoad(insn, dest, LOW10(src1), dest);
828
829         base += sizeof(instruction)*2;
830     } else if (op ==  loadIndirOp) {
831         generateLoad(insn, src1, 0, dest);
832         base += sizeof(instruction);
833     } else if (op ==  storeOp) {
834         generateSetHi(insn, dest, src2);
835         insn++;
836
837         generateStore(insn, src1, src2, LOW10(dest));
838
839         base += sizeof(instruction)*2;
840     } else if (op ==  storeIndirOp) {
841         generateStore(insn, src1, dest, 0);
842         base += sizeof(instruction);
843     } else if (op ==  ifOp) {
844         // cmp src1,0
845         genSimpleInsn(insn, SUBop3cc, src1, 0, 0); insn++;
846         genBranch(insn, dest, BEcond, false); insn++;
847
848         generateNOOP(insn);
849         base += sizeof(instruction)*3;
850         return(base - 2*sizeof(instruction));
851     } else if (op == branchOp) {
852         // Unconditional branch
853         generateBranchInsn(insn, dest); insn++;
854
855         generateNOOP(insn);
856         base += sizeof(instruction)*2;
857         return(base - 2*sizeof(instruction));
858     } else if (op ==  updateCostOp) {
859         // generate code to update the observed cost.
860         if (!noCost) {
861            // sethi %hi(dest), %l0
862            generateSetHi(insn, dest, REG_L0);
863            base += sizeof(instruction);
864            insn++;
865   
866            // ld [%l0+ lo(dest)], %l1
867            generateLoad(insn, REG_L0, LOW10(dest), REG_L1);
868            base += sizeof(instruction);
869            insn++;
870   
871            // update value (src1 holds the cost, in cycles; e.g. 19)
872            if (src1 <= MAX_IMM13) {
873               genImmInsn(insn, ADDop3, REG_L1, src1, REG_L1);
874               base += sizeof(instruction);
875               insn++;
876
877               generateNOOP(insn);
878               base += sizeof(instruction);
879               insn++;
880
881               generateNOOP(insn);
882               base += sizeof(instruction);
883               insn++;
884            } else {
885               // load in two parts
886               generateSetHi(insn, src1, REG_L2);
887               base += sizeof(instruction);
888               insn++;
889
890               // or regd,imm,regd
891               genImmInsn(insn, ORop3, REG_L2, LOW10(src1), REG_L2);
892               base += sizeof(instruction);
893               insn++;
894
895               // now add it
896               genSimpleInsn(insn, ADDop3, REG_L1, REG_L2, REG_L1);
897               base += sizeof(instruction);
898               insn++;
899            }
900   
901            // store result st %l1, [%l0+ lo(dest)];
902            generateStore(insn, REG_L1, REG_L0, LOW10(dest));
903            base += sizeof(instruction);
904            insn++;
905         } // if (!noCost)
906     } else if (op ==  trampPreamble) {
907     } else if (op ==  trampTrailer) {
908         // dest is in words of offset and generateBranchInsn is bytes offset
909         generateAnnulledBranchInsn(insn, dest << 2);
910         base += sizeof(instruction);
911         insn++;
912
913         // add no-op, SS-5 sometimes seems to try to decode this insn - jkh 2/14
914         generateNOOP(insn);
915         insn++;
916         base += sizeof(instruction);
917
918         return(base -  2 * sizeof(instruction));
919     } else if (op == noOp) {
920         generateNOOP(insn);
921         base += sizeof(instruction);
922     } else if (op == getParamOp) {
923 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
924         // saving CT/vector address on the stack
925         generateStore(insn, REG_MT, REG_FP, -40);
926         insn++;
927 #endif
928         // first 8 parameters are in register 24 ....
929         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
930         insn++;
931
932         generateStore(insn, 24+src1, REG_SP, 68+4*src1); 
933         insn++;
934               
935         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
936         insn++;
937
938         generateLoad(insn, REG_SP, 112+68+4*src1, 24+src1); 
939         insn++;
940
941 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
942         // restoring CT/vector address back in REG_MT
943         generateLoad(insn, REG_FP, -40, REG_MT);
944         insn++;
945         base += 6*sizeof(instruction);
946 #else
947         base += 4*sizeof(instruction);
948 #endif
949         
950         if (src1 <= 8) {
951             return(24+src1);
952         }
953         
954         abort();
955     } else if (op == getSysParamOp) {
956         
957         if (src1 <= 8) {
958             return(24+src1);
959         }       
960     } else if (op == getRetValOp) {
961         // return value is in register 24
962         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
963         insn++;
964
965         generateStore(insn, 24, REG_SP, 68); 
966         insn++;
967               
968         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
969         insn++;
970
971         generateLoad(insn, REG_SP, 112+68, 24); 
972         insn++;
973
974         base += 4*sizeof(instruction);
975
976         return(24);
977
978     } else if (op == getSysRetValOp) {
979         return(24);
980     } else if (op == saveRegOp) {
981         // should never be called for this platform.
982         abort();
983     } else {
984       int op3=-1;
985         switch (op) {
986             // integer ops
987             case plusOp:
988                 op3 = ADDop3;
989                 break;
990
991             case minusOp:
992                 op3 = SUBop3;
993                 break;
994
995             case timesOp:
996                 op3 = SMULop3;
997                 break;
998
999             case divOp:
1000                 op3 = SDIVop3;
1001                 //need to set the Y register to Zero, Zhichen
1002                 genImmInsn(insn, WRYop3, REG_G0, 0, 0);
1003                 base += sizeof(instruction);
1004                 insn = (instruction *) ((void*)&i[base]);
1005                 break;
1006
1007             // Bool ops
1008             case orOp:
1009                 op3 = ORop3;
1010                 break;
1011
1012             case andOp:
1013                 op3 = ANDop3;
1014                 break;
1015
1016             // rel ops
1017             // For a particular condition (e.g. <=) we need to use the
1018             // the opposite in order to get the right value (e.g. for >=
1019             // we need BLTcond) - naim
1020             case eqOp:
1021                 genRelOp(insn, BNEcond, src1, src2, dest, base);
1022                 return(0);
1023                 break;
1024
1025             case neOp:
1026                 genRelOp(insn, BEcond, src1, src2, dest, base);
1027                 return(0);
1028                 break;
1029
1030             case lessOp:
1031                 genRelOp(insn, BGEcond, src1, src2, dest, base);
1032                 return(0);
1033                 break;
1034
1035             case leOp:
1036                 genRelOp(insn, BGTcond, src1, src2, dest, base);
1037                 return(0);
1038                 break;
1039
1040             case greaterOp:
1041                 genRelOp(insn, BLEcond, src1, src2, dest, base);
1042                 return(0);
1043                 break;
1044
1045             case geOp:
1046                 genRelOp(insn, BLTcond, src1, src2, dest, base);
1047                 return(0);
1048                 break;
1049
1050             default:
1051                 abort();
1052                 break;
1053         }
1054         genSimpleInsn(insn, op3, src1, src2, dest);
1055
1056         base += sizeof(instruction);
1057       }
1058     return(0);
1059 }
1060
1061 /*
1062  * Find the instPoints of this function.
1063  */
1064 bool pd_Function::findInstPoints(const image *owner) {
1065
1066    if (size() == 0) {
1067      return false;
1068    }
1069
1070    noStackFrame = true;
1071
1072    Address adr;
1073    Address adr1 = getAddress(0);
1074    instruction instr;
1075    instr.raw = owner->get_instruction(adr1);
1076    if (!IS_VALID_INSN(instr))
1077      return false;
1078
1079    // If it contains an instruction, I assume it would be s system call
1080    // which will be treat differently. 
1081    isTrap = false;
1082    bool func_entry_found = false;
1083
1084    for ( ; adr1 < getAddress(0) + size(); adr1 += 4) {
1085        instr.raw = owner->get_instruction(adr1);
1086
1087        // If there's an TRAP instruction in the function, we 
1088        // assume that it is an system call and will relocate it 
1089        // to the heap
1090        if (isInsnType(instr, TRAPmask, TRAPmatch)) {
1091            isTrap = true;
1092            return findInstPoints(owner, getAddress(0), 0);
1093        } 
1094
1095        // The function Entry is defined as the first SAVE instruction plus
1096        // the instructions after this.
1097        // ( The first instruction for the nonleaf function is not 
1098        //   necessarily a SAVE instruction. ) 
1099        if (isInsnType(instr, SAVEmask, SAVEmatch) && !func_entry_found) {
1100
1101            noStackFrame = false;
1102
1103            func_entry_found = true;
1104            funcEntry_ = new instPoint(this, instr, owner, adr1, true,
1105                                       functionEntry);
1106            adr = adr1;
1107            assert(funcEntry_);
1108        }
1109    }
1110
1111    // If there's no SAVE instruction found, this is a leaf function and
1112    // and function Entry will be defined from the first instruction
1113    if (noStackFrame) {
1114        adr = getAddress(0);
1115        instr.raw = owner->get_instruction(adr);
1116        funcEntry_ = new instPoint(this, instr, owner, adr, true,
1117                                   functionEntry);
1118        assert(funcEntry_);
1119    }
1120
1121    for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1122
1123      instr.raw = owner->get_instruction(adr);
1124
1125      bool done;
1126
1127      // check for return insn and as a side affect decide if we are at the
1128      //   end of the function.
1129      if (isReturnInsn(owner, adr, done)) {
1130        // define the return point
1131        funcReturns += new instPoint(this, instr, owner, adr, false,
1132                                     functionExit);
1133
1134      } else if (instr.branch.op == 0 
1135                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6) 
1136                 && (instr.branch.cond == 0 ||instr.branch.cond == 8)) {
1137        // find if this branch is going out of the function
1138        int disp = instr.branch.disp22;
1139        Address target = adr +  (disp << 2);
1140        if ((target < (getAddress(0)))  
1141            || (target >= (getAddress(0) + size()))) {
1142          instPoint *point = new instPoint(this, instr, owner, adr, false,
1143                                           functionExit);
1144          funcReturns += point;
1145        }
1146
1147      } else if (isCallInsn(instr)) {
1148
1149        // if the call target is the address of the call instruction
1150        // then this is not something that we can instrument...
1151        // this occurs in functions with code that is modifined when 
1152        // they are loaded by the run-time linker, or when the .init
1153        // section is executed.  In this case the instructions in the
1154        // parsed image file are different from the ones in the executable
1155        // process.
1156        if(instr.call.op == CALLop) { 
1157            Address call_target = adr + (instr.call.disp30 << 2);
1158            if(call_target == adr){ 
1159                 return false;
1160        }}
1161        // first, check for tail-call optimization: a call where the instruction 
1162        // in the delay slot write to register %o7(15), usually just moving
1163        // the caller's return address, or doing a restore
1164        // Tail calls are instrumented as return points, not call points.
1165
1166
1167        instruction nexti; 
1168        nexti.raw = owner->get_instruction(adr+4);
1169
1170        if (nexti.rest.op == 2 
1171            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1172               || nexti.rest.op3 == RESTOREop3)) {
1173          funcReturns += new instPoint(this, instr, owner, adr, false,
1174                                       functionExit);
1175
1176        } else {
1177          // define a call point
1178          // this may update address - sparc - aggregate return value
1179          // want to skip instructions
1180          bool err;
1181          int dummyId;
1182          instPoint *blah = 0;
1183          adr = newCallPoint(adr, instr, owner, err, dummyId, adr,0,blah);
1184        }
1185      }
1186
1187      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1188        /* A register indirect jump. Some jumps may exit the function 
1189           (e.g. read/write on SunOS). In general, the only way to 
1190           know if a jump is exiting the function is to instrument
1191           the jump to test if the target is outside the current 
1192           function. Instead of doing this, we just check the 
1193           previous two instructions, to see if they are loading
1194           an address that is out of the current function.
1195           This should catch the most common cases (e.g. read/write).
1196           For other cases, we would miss a return point.
1197
1198           This is the case considered:
1199
1200              sethi addr_hi, r
1201              or addr_lo, r, r
1202              jump r
1203         */
1204
1205        reg jumpreg = instr.rest.rs1;
1206        instruction prev1;
1207        instruction prev2;
1208
1209        prev1.raw = owner->get_instruction(adr-4);
1210        prev2.raw = owner->get_instruction(adr-8);
1211
1212        unsigned targetAddr;
1213
1214        if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1215            && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1216            && prev2.sethi.rd == (unsigned)jumpreg
1217            && prev1.rest.op == RESTop 
1218            && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1219            && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg) {
1220
1221          targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1222          targetAddr |= prev1.resti.simm13;
1223          if ((targetAddr<getAddress(0))||(targetAddr>=(getAddress(0)+size()))){
1224            instPoint *point = new instPoint(this, instr, owner, adr, false, 
1225                                             functionExit);
1226            funcReturns += point;
1227          }
1228        }
1229
1230      }
1231  }
1232
1233  return (checkInstPoints(owner)); 
1234 }
1235
1236 /*
1237  * Check all the instPoints within this function to see if there's 
1238  * any conficts happen.
1239  */
1240 bool pd_Function::checkInstPoints(const image *owner) {
1241
1242     // Our own library function, skip the test.
1243     if (prettyName().prefixed_by("DYNINST")) 
1244         return true;
1245
1246 #ifndef BPATCH_LIBRARY
1247     // The function is too small to be worthing instrumenting.
1248     if (size() <= 12)
1249         return false;
1250 #endif
1251
1252     // No function return! return false;
1253     if (sizeof(funcReturns) == 0)
1254         return false;
1255
1256     instruction instr;
1257     Address adr = getAddress(0);
1258
1259     // Check if there's any branch instruction jump to the middle
1260     // of the instruction sequence in the function entry point
1261     // and function exit point.
1262     for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1263
1264         instr.raw = owner->get_instruction(adr);
1265
1266         if (isInsnType(instr, BRNCHmask, BRNCHmatch)||
1267             isInsnType(instr, FBRNCHmask, FBRNCHmatch)) {
1268
1269             int disp = instr.branch.disp22;
1270             Address target = adr + (disp << 2);
1271
1272             if ((target > funcEntry_->addr)&&
1273                 (target < (funcEntry_->addr + funcEntry_->size))) {
1274                 if (adr > (funcEntry_->addr+funcEntry_->size))
1275                     return false;
1276             }
1277
1278             for (u_int i = 0; i < funcReturns.size(); i++) {
1279                 if ((target > funcReturns[i]->addr)&&
1280                     (target < (funcReturns[i]->addr + funcReturns[i]->size))) {
1281                     if ((adr < funcReturns[i]->addr)||
1282                         (adr > (funcReturns[i]->addr + funcReturns[i]->size)))
1283                         return false;
1284                 }
1285             }
1286         }
1287     }
1288
1289     return true;        
1290 }
1291
1292 // This function is to find the inst Points for a function
1293 // that will be relocated if it is instrumented. 
1294 bool pd_Function::findInstPoints(const image *owner, Address newAdr, 
1295                                 process *proc){
1296
1297    int i;
1298    if (size() == 0) {
1299      return false;
1300    }
1301    relocatable_ = true;
1302
1303    Address adr = getAddress(0);
1304    instruction instr;
1305    instr.raw = owner->get_instruction(adr);
1306    if (!IS_VALID_INSN(instr))
1307      return false;
1308    
1309    if (size() <= 3*sizeof(instruction)) 
1310        return false;
1311
1312    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1313                                     functionEntry, adr);
1314
1315    funcEntry_ = point;
1316
1317    // if the second instruction in a relocated function is a call instruction
1318    // or a branch instruction, then we can't deal with this 
1319    if(size() > sizeof(instruction)){
1320        Address second_adr = adr + sizeof(instruction);
1321        instruction second_instr;
1322        second_instr.raw =  owner->get_instruction(second_adr); 
1323        if ((isCallInsn(second_instr)) || 
1324                       (second_instr.branch.op == 0 && 
1325                       (second_instr.branch.op2 == 2 || 
1326                       second_instr.branch.op2 == 6))) {
1327            return false;
1328        }
1329    }
1330    
1331    assert(funcEntry_);
1332    int retId = 0;
1333    int callsId = 0; 
1334
1335    for (i = 0; adr < getAddress(0) + size(); adr += sizeof(instruction),  
1336         newAdr += sizeof(instruction), i++) {
1337
1338      instr.raw = owner->get_instruction(adr);
1339      newInstr[i] = instr;
1340      bool done;
1341
1342      // check for return insn and as a side affect decide if we are at the
1343      //   end of the function.
1344      if (isReturnInsn(owner, adr, done)) {
1345        // define the return point
1346        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1347                                         functionExit, adr);
1348        funcReturns += point;
1349        funcReturns[retId] -> instId = retId++;
1350      } else if (instr.branch.op == 0 
1351                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1352        // find if this branch is going out of the function
1353        int disp = instr.branch.disp22;
1354        Address target = adr + (disp << 2);
1355        if (target < getAddress(0) || target >= getAddress(0) + size()) {
1356            relocateInstruction(&newInstr[i], adr, newAdr, proc);
1357            instPoint *point = new instPoint(this, newInstr[i], owner, 
1358                                             newAdr, false, 
1359                                             functionExit, adr);
1360            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1361                point->isBranchOut = true;
1362                point->branchTarget = target;
1363            }
1364            funcReturns += point;
1365            funcReturns[retId] -> instId = retId++;
1366        }
1367
1368      } else if (isCallInsn(instr)) {
1369
1370        // first, check for tail-call optimization: a call where the instruction 
1371        // in the delay slot write to register %o7(15), usually just moving
1372        // the caller's return address, or doing a restore
1373        // Tail calls are instrumented as return points, not call points.
1374        instruction nexti; 
1375        nexti.raw = owner->get_instruction(adr+4);
1376
1377        if (nexti.rest.op == 2 
1378            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1379               || nexti.rest.op3 == RESTOREop3)) {
1380
1381            instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1382                                       functionExit, adr);
1383            funcReturns += point;
1384            funcReturns[retId] -> instId = retId++;
1385
1386        } else {
1387
1388          // define a call point
1389          // this may update address - sparc - aggregate return value
1390          // want to skip instructions
1391          bool err;
1392          instPoint *blah = 0;
1393          adr = newCallPoint(newAdr, instr, owner, err, callsId, adr,0,blah);
1394          if (err)
1395            return false;
1396        }
1397      }
1398
1399      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1400        /* A register indirect jump. Some jumps may exit the function 
1401           (e.g. read/write on SunOS). In general, the only way to 
1402           know if a jump is exiting the function is to instrument
1403           the jump to test if the target is outside the current 
1404           function. Instead of doing this, we just check the 
1405           previous two instructions, to see if they are loading
1406           an address that is out of the current function.
1407           This should catch the most common cases (e.g. read/write).
1408           For other cases, we would miss a return point.
1409
1410           This is the case considered:
1411
1412              sethi addr_hi, r
1413              or addr_lo, r, r
1414              jump r
1415         */
1416
1417          reg jumpreg = instr.rest.rs1;
1418          instruction prev1;
1419          instruction prev2;
1420          
1421          prev1.raw = owner->get_instruction(adr-4);
1422          prev2.raw = owner->get_instruction(adr-8);
1423
1424          unsigned targetAddr;
1425
1426          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1427              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1428              && prev2.sethi.rd == (unsigned)jumpreg
1429              && prev1.rest.op == RESTop 
1430              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1431              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
1432              
1433              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1434              targetAddr |= prev1.resti.simm13;
1435              if ((targetAddr < getAddress(0)) 
1436                  || (targetAddr >= (getAddress(0)+size()))) {
1437                  instPoint *point = new instPoint(this, instr, owner, 
1438                                                   newAdr, false,
1439                                                   functionExit, adr);
1440                  funcReturns += point;
1441                  funcReturns[retId] -> instId = retId++;
1442              }
1443          }
1444      }
1445  }
1446  return true;
1447 }
1448
1449 // This function assigns new address to instrumentation points of  
1450 // a function that has been relocated
1451 bool pd_Function::findNewInstPoints(const image *owner, 
1452                                 const instPoint *&location,
1453                                 Address newAdr,
1454                                 process *proc,
1455                                 vector<instruction> &,
1456                                 relocatedFuncInfo *reloc_info) {
1457
1458    int i;
1459    if (size() == 0) {
1460      return false;
1461    }
1462    assert(reloc_info);
1463
1464    Address adr = getAddress(0);
1465    instruction instr;
1466    instr.raw = owner->get_instruction(adr);
1467    if (!IS_VALID_INSN(instr))
1468      return false;
1469
1470    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1471                                     functionEntry, adr);
1472    point->relocated_ = true;
1473    // if location was the entry point then change location's value to new pt
1474    if(location == funcEntry_) { 
1475         location = point; 
1476    }
1477
1478    reloc_info->addFuncEntry(point);
1479    assert(reloc_info->funcEntry());
1480    int retId = 0;
1481    int callsId = 0; 
1482
1483    // get baseAddress if this is a shared object
1484    Address baseAddress = 0;
1485    if(!(proc->getBaseAddress(owner,baseAddress))){
1486        baseAddress =0;
1487    }
1488
1489    for (i = 0; adr < getAddress(0) + size(); adr += 4,  newAdr += 4, i++) {
1490     
1491      instr.raw = owner->get_instruction(adr);
1492      newInstr[i] = instr;
1493
1494      bool done;
1495
1496      // check for return insn and as a side affect decide if we are at the
1497      //   end of the function.
1498      if (isReturnInsn(owner, adr, done)) {
1499        // define the return point
1500        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1501                                         functionExit, adr);
1502        point->relocated_ = true;
1503        // if location was this point, change it to new point
1504        if(location == funcReturns[retId]) { 
1505            location = point; 
1506        }
1507        retId++;
1508        reloc_info->addFuncReturn(point);
1509      } else if (instr.branch.op == 0 
1510                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1511        // find if this branch is going out of the function
1512        int disp = instr.branch.disp22;
1513        Address target = adr + (disp << 2);
1514        if ((target < (getAddress(0))) 
1515            || (target >= (getAddress(0) + size()))) {
1516            relocateInstruction(&newInstr[i],adr,newAdr,proc);
1517            instPoint *point = new instPoint(this, newInstr[i], owner, 
1518                                             newAdr, false, 
1519                                             functionExit, adr);
1520            point->relocated_ = true;
1521            // TODO is this the correct displacement???
1522            disp = newInstr[i].branch.disp22;
1523            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1524                point->isBranchOut = true;
1525                // TODO is this the correct target???
1526                point->branchTarget = target;
1527            }
1528            // if location was this point, change it to new point
1529            if(location == funcReturns[retId]) { 
1530                location = point;
1531            }
1532            retId++;
1533            reloc_info->addFuncReturn(point);
1534        }
1535
1536      } else if (isCallInsn(instr)) {
1537
1538        // first, check for tail-call optimization: a call where the instruction 
1539        // in the delay slot write to register %o7(15), usually just moving
1540        // the caller's return address, or doing a restore
1541        // Tail calls are instrumented as return points, not call points.
1542        instruction nexti; 
1543        nexti.raw = owner->get_instruction(adr+4);
1544
1545        if (nexti.rest.op == 2 
1546            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1547               || nexti.rest.op3 == RESTOREop3)) {
1548
1549             // Undoing the tail-call optimazation when the function
1550             // is relocated. Here is an example:
1551             //   before:          --->             after
1552             // ---------------------------------------------------
1553             //   call  %g1                        restore    
1554             //   restore                          st  %i0, [ %fp + 0x44 ]
1555             //                                    mov %o7 %i0
1556             //                                    call %g1 
1557             //                                    nop
1558             //                                    mov %i0,%o7
1559             //                                    st  [ %fp + 0x44 ], %i0
1560             //                              retl
1561             //                                    nop
1562             // Q: Here the assumption that register i1 is available 
1563             //    might be an question, is it?
1564             // A: I think it is appropriate because:
1565             //      (in situation A calls B and B calls C)
1566             //      The procedure C called via tail call is a leaf 
1567             //      procedure, the value arguments and return value between
1568             //      A and C are passed by register (o1...o5, o7)
1569             //      So even If B mess up the value of i0, it won't affect the
1570             //      commnucation between A and C. Also, we saved the value of
1571             //      i0 on stack and when we return from B, the value of i0
1572             //      won't be affected.
1573             //      If C is not a leaf procedure, it should be fine
1574             //      as it is.
1575             //    ( If you could give an counter-example, please
1576             //      let me know.                         --ling )
1577
1578             genSimpleInsn(&newInstr[i++], RESTOREop3, 0, 0, 0);
1579             generateStore(&newInstr[i++], 24, REG_FP, 0x44); 
1580             genImmInsn(&newInstr[i++], ORop3, 15, 0, 24); 
1581             newInstr[i++].raw = owner->get_instruction(adr);
1582             generateNOOP(&newInstr[i++]);
1583             genImmInsn(&newInstr[i++], ORop3, 24, 0, 15);
1584             generateLoad(&newInstr[i++], REG_FP, 0x44, 24);         
1585             generateJmplInsn(&newInstr[i++], 15, 8 ,0);
1586             newAdr += 28;
1587             generateNOOP(&newInstr[i]);
1588             instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1589                                       functionExit, adr);
1590             point-> originalInstruction = newInstr[i-1];
1591             point-> delaySlotInsn = newInstr[i];
1592             point-> isDelayed = true;
1593             point->relocated_ = true;
1594             // if location was this point, change it to new point
1595             if(location == funcReturns[retId]) { 
1596                 location = point;
1597             }
1598             retId++;
1599             reloc_info->addFuncReturn(point);
1600        } else {
1601
1602            // otherwise, this is a call instruction to a location
1603            // outside the function
1604            bool err;
1605            // relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
1606            adr = newCallPoint(newAdr, newInstr[i], owner, err,
1607                                    callsId, adr,reloc_info,location);
1608            if (err) return false;
1609        }
1610      }
1611
1612      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1613        /* A register indirect jump. Some jumps may exit the function 
1614           (e.g. read/write on SunOS). In general, the only way to 
1615           know if a jump is exiting the function is to instrument
1616           the jump to test if the target is outside the current 
1617           function. Instead of doing this, we just check the 
1618           previous two instructions, to see if they are loading
1619           an address that is out of the current function.
1620           This should catch the most common cases (e.g. read/write).
1621           For other cases, we would miss a return point.
1622
1623           This is the case considered:
1624
1625              sethi addr_hi, r
1626              or addr_lo, r, r
1627              jump r
1628         */
1629
1630          reg jumpreg = instr.rest.rs1;
1631          instruction prev1;
1632          instruction prev2;
1633          
1634          prev1.raw = owner->get_instruction(adr-4);
1635          prev2.raw = owner->get_instruction(adr-8);
1636
1637          unsigned targetAddr;
1638
1639          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1640              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1641              && prev2.sethi.rd == (unsigned)jumpreg
1642              && prev1.rest.op == RESTop 
1643              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1644              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
1645              
1646              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1647              targetAddr |= prev1.resti.simm13;
1648              if ((targetAddr < getAddress(0)) 
1649                  || (targetAddr >= (getAddress(0)+size()))) {
1650                  instPoint *point = new instPoint(this, instr, owner, 
1651                                                   newAdr, false,
1652                                                   functionExit, adr);
1653                  point->relocated_ = true;
1654                  // if location was this point, change it to new point
1655                  if(location == funcReturns[retId]) { 
1656                      location = point;
1657                  }
1658                  retId++;
1659                  reloc_info->addFuncReturn(point);
1660              }
1661          }
1662      }
1663  }
1664    
1665    return true;
1666 }
1667
1668 // hasBeenBound: returns false
1669 // dynamic linking not implemented on this platform
1670 bool process::hasBeenBound(const relocationEntry ,pd_Function *&, Address ) {
1671     return false;
1672 }
1673
1674 // findCallee: returns false unless callee is already set in instPoint
1675 // dynamic linking not implemented on this platform
1676 bool process::findCallee(instPoint &instr, function_base *&target){
1677
1678     if((target = (function_base *)instr.iPgetCallee())) {
1679        return true;
1680     }
1681     return false;
1682 }