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