Optimization for code generation (use of immediate operations whenever
[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 /*
43  * inst-sparc.C - Identify instrumentation points for a SPARC processors.
44  *
45  * $Log: inst-sparc-solaris.C,v $
46  * Revision 1.5  1996/10/04 16:12:40  naim
47  * Optimization for code generation (use of immediate operations whenever
48  * possible). This first commit is only for the sparc platform. Other platforms
49  * should follow soon - naim
50  *
51  * Revision 1.4  1996/10/04 04:19:52  newhall
52  * bug fix to pdFunction::checkCallPoints
53  *
54  * Revision 1.3  1996/10/03 22:12:12  mjrg
55  * Removed multiple stop/continues when inserting instrumentation
56  * Fixed bug on process termination
57  * Removed machine dependent code from metric.C and process.C
58  *
59  * Revision 1.2  1996/10/01 18:25:30  newhall
60  * bug fix to instPoint::instPoint when relocating a function
61  *
62  * Revision 1.1  1996/09/26 18:58:36  newhall
63  * added support for instrumenting dynamic executables on sparc-solaris
64  * platform
65  *
66  * Revision 1.47  1996/09/13 21:41:51  mjrg
67  * Implemented opcode ReturnVal for ast's to get the return value of functions.
68  * Added missing calls to free registers in Ast.generateCode and emitFuncCall.
69  * Removed architecture dependencies from inst.C.
70  * Changed code to allow base tramps of variable size.
71  *
72  * Revision 1.46  1996/09/12 18:25:14  naim
73  * Another minor fix to my previous commit! - naim
74  *
75  * Revision 1.44  1996/09/12 15:08:21  naim
76  * This commit move all saves and restores from the mini-tramps to the base
77  * tramp. It also add jumps to skip instrumentation in the base-tramp when
78  * it isn't required - naim
79  *
80  * Revision 1.43  1996/09/05 16:40:07  lzheng
81  * Moved the architecture dependent definations to the architecture
82  * dependent files; Added some comments
83  *
84  * Revision 1.42  1996/08/23 16:59:23  lzheng
85  * Another minor change related to the undoing of tail-call optimaztion
86  *
87  * Revision 1.41  1996/08/23 03:44:57  lzheng
88  * Changes made for the previous commit and also minor bug fix for the
89  * undoing of tail-call optimaztion
90  *
91  * Revision 1.40  1996/08/20 19:21:57  lzheng
92  * Implementation of moving multiple instructions sequence and
93  * splitting the instrumentation into two phases
94  * (For solaris2.5, ndo the tail-call optimaztion for the system call
95  * so we could get the correct value for calculating the time of system call.)
96  *
97  * Revision 1.39  1996/08/16 21:18:59  tamches
98  * updated copyright for release 1.1
99  *
100  * Revision 1.38  1996/07/18 19:37:46  naim
101  * Changing the "frequency" value from 250 to 100 - naim
102  *
103  * Revision 1.37  1996/05/08  23:51:41  mjrg
104  * included instructions to save registers in cost
105  *
106  * Revision 1.36  1996/04/29 22:18:46  mjrg
107  * Added size to functions (get size from symbol table)
108  * Use size to define function boundary
109  * Find multiple return points for sparc
110  * Instrument branches and jumps out of a function as return points (sparc)
111  * Recognize tail-call optimizations and instrument them as return points (sparc)
112  * Move instPoint to machine dependent files
113  *
114  * Revision 1.35  1996/04/26 20:43:07  lzheng
115  * Changes to the procedure emitFuncCall. (move all the code dealing with
116  * function Call in the miniTrampoline here)
117  *
118  * Revision 1.34  1996/03/25 22:58:05  hollings
119  * Support functions that have multiple exit points.
120  *
121  * Revision 1.33  1996/03/20  17:02:46  mjrg
122  * Added multiple arguments to calls.
123  * Instrument pvm_send instead of pvm_recv to get tags.
124  *
125  */
126
127 #include "util/h/headers.h"
128
129 #include "rtinst/h/rtinst.h"
130 #include "symtab.h"
131 #include "process.h"
132 #include "inst.h"
133 #include "instP.h"
134 #include "inst-sparc.h"
135 #include "arch-sparc.h"
136 #include "ast.h"
137 #include "util.h"
138 #include "internalMetrics.h"
139 #include "stats.h"
140 #include "os.h"
141 #include "showerror.h"
142
143 #define perror(a) P_abort();
144
145 extern bool isPowerOf2(int value, int &result);
146
147 class instPoint {
148 public:
149   instPoint(pdFunction *f, const instruction &instr, const image *owner,
150             Address &adr, const bool delayOK, bool isLeaf,
151             instPointType ipt);
152   instPoint(pdFunction *f, const instruction &instr, const image *owner,
153             Address &adr, const bool delayOK, instPointType ipt,   
154             Address &oldAddr);
155   ~instPoint() {  /* TODO */ }
156
157   // can't set this in the constructor because call points can't be classified until
158   // all functions have been seen -- this might be cleaned up
159   void set_callee(pdFunction *to) { callee = to; }
160
161
162   Address addr;                       /* address of inst point */
163   instruction originalInstruction;    /* original instruction */
164   instruction delaySlotInsn;          /* original instruction */
165   instruction aggregateInsn;          /* aggregate insn */
166   instruction otherInstruction;       
167   instruction isDelayedInsn;  
168   instruction inDelaySlotInsn;
169   instruction extraInsn;   /* if 1st instr is conditional branch this is
170                               previous instruction */
171
172   bool inDelaySlot;            /* Is the instruction in a delay slot */
173   bool isDelayed;               /* is the instruction a delayed instruction */
174   bool callIndirect;            /* is it a call whose target is rt computed ? */
175   bool callAggregate;           /* calling a func that returns an aggregate
176                                    we need to reolcate three insns in this case
177                                    */
178   pdFunction *callee;           /* what function is called */
179   pdFunction *func;             /* what function we are inst */
180
181   bool isBranchOut;                /* true if this point is a conditional branch, 
182                                    that may branch out of the function */
183   int branchTarget;                /* the original target of the branch */
184   bool leaf;                       /* true if the procedure is a leaf     */
185   instPointType ipType;
186   int instId;                      /* id of inst in this function */
187   int size;                        /* size of multiple instruction sequences */
188   const image *image_ptr;       // for finding correct image in process
189   bool firstIsConditional;     /* 1st instruction is conditional branch */
190 };
191
192
193
194 #define ABS(x)          ((x) > 0 ? x : -x)
195 #define MAX_BRANCH      0x1<<23
196 //#define MAX_IMM               0x1<<12         /* 11 plus shign == 12 bits */
197 #define MAX_IMM13       (4095)
198 #define MIN_IMM13       (-4096)
199
200 unsigned getMaxBranch() {
201   return MAX_BRANCH;
202 }
203
204 #define REG_G5          5
205 #define REG_G6          6
206 #define REG_G7          7
207
208 #define REG_O7          15
209
210 #define REG_L0          16
211 #define REG_L1          17
212 #define REG_L2          18
213
214 #define REG_SP          14
215 #define REG_FP          30
216
217 const char *registerNames[] = { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
218                                 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
219                                 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
220                                 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7" };
221
222 dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
223
224 string getStrOp(int op)
225 {
226     switch (op) {
227         case SetCC:     return("set");
228         case ADDop3:    return("add");
229         case ANDop3:    return("and");
230         case ORop3:     return("or");
231         case SUBop3:    return("sub");
232         case SUBop3cc:  return("subcc");
233         case SMULop3:   return("smul");
234         case SDIVop3:   return("sdiv");
235         case XNORop3:   return("xnor");
236         case SAVEop3:   return("save");
237         case RESTOREop3:        return("restore");
238         case JMPLop3:   return("jmpl");
239         default:        return("???");
240     }
241 }
242
243 inline void generateNOOP(instruction *insn)
244 {
245     insn->raw = 0;
246     insn->branch.op = 0;
247     insn->branch.op2 = NOOPop2;
248
249     // logLine("nop\n");
250 }
251
252 inline void generateBranchInsn(instruction *insn, int offset)
253 {
254     if (ABS(offset) > MAX_BRANCH) {
255         logLine("a Ranch too far\n");
256         //showErrorCallback(52, "");
257         //abort();
258         return;
259     }
260
261     insn->raw = 0;
262     insn->branch.op = 0;
263     insn->branch.cond = BAcond;
264     insn->branch.op2 = BICCop2;
265     insn->branch.anneal = true;
266     insn->branch.disp22 = offset >> 2;
267
268     // logLine("ba,a %x\n", offset);
269 }
270
271 inline void generateCallInsn(instruction *insn, int fromAddr, int toAddr)
272 {
273     int offset = toAddr - fromAddr;
274     insn->call.op = 01;
275     insn->call.disp30 = offset >> 2;
276 }
277
278 inline void generateJmplInsn(instruction *insn, int rs1, int offset, int rd)
279 {
280     insn->resti.op = 10;
281     insn->resti.rd = rd;
282     insn->resti.op3 = JMPLop3;
283     insn->resti.rs1 = rs1;
284     insn->resti.i = 1;
285     insn->resti.simm13 = LOW(offset);
286 }    
287
288 inline void genBranch(instruction *insn, int offset, unsigned condition, bool annul)
289 {
290     if (ABS(offset) > MAX_BRANCH) {
291         logLine("a branch too far\n");
292         showErrorCallback(52, "");
293         abort();
294     }
295
296     insn->raw = 0;
297     insn->branch.op = 0;
298     insn->branch.cond = condition;
299     insn->branch.op2 = BICCop2;
300     insn->branch.anneal = annul;
301     insn->branch.disp22 = offset >> 2;
302 }
303
304 inline void genSimpleInsn(instruction *insn, int op, reg rs1, reg rs2, reg rd)
305 {
306     insn->raw = 0;
307     insn->rest.op = RESTop;
308     insn->rest.rd = rd;
309     insn->rest.op3 = op;
310     insn->rest.rs1 = rs1;
311     insn->rest.rs2 = rs2;
312
313     // logLine("%s %%%s,%%%s,%%%s\n", getStrOp(op), registerNames[rs1], 
314     //  registerNames[rs2], registerNames[rd]);
315 }
316
317 inline void genImmInsn(instruction *insn, int op, reg rs1, int immd, reg rd)
318 {
319     insn->raw = 0;
320     insn->resti.op = RESTop;
321     insn->resti.rd = rd;
322     insn->resti.op3 = op;
323     insn->resti.rs1 = rs1;
324     insn->resti.i = 1;
325     insn->resti.simm13 = immd;
326
327     // logLine("%s %%%s,%d,%%%s\n", getStrOp(op), registerNames[rs1], immd,
328     //  registerNames[rd]);
329 }
330
331 inline void genImmRelOp(instruction *insn, int cond, reg rs1,
332                         int immd, reg rd, unsigned &base)
333 {
334     // cmp rs1, rs2
335     genImmInsn(insn, SUBop3cc, rs1, immd, 0); insn++;
336     // mov 1, rd
337     genImmInsn(insn, ORop3, 0, 1, rd); insn++;
338
339     // b??,a +2
340     insn->branch.op = 0;
341     insn->branch.cond = cond;
342     insn->branch.op2 = BICCop2;
343     insn->branch.anneal = true;
344     insn->branch.disp22 = 2;
345     insn++;
346
347     // clr rd
348     genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
349     base += 4 * sizeof(instruction);
350 }
351
352 inline void genRelOp(instruction *insn, int cond, reg rs1,
353                      reg rs2, reg rd, unsigned &base)
354 {
355     // cmp rs1, rs2
356     genSimpleInsn(insn, SUBop3cc, rs1, rs2, 0); insn++;
357     // mov 1, rd
358     genImmInsn(insn, ORop3, 0, 1, rd); insn++;
359
360     // b??,a +2
361     insn->branch.op = 0;
362     insn->branch.cond = cond;
363     insn->branch.op2 = BICCop2;
364     insn->branch.anneal = true;
365     insn->branch.disp22 = 2;
366     insn++;
367
368     // clr rd
369     genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
370     base += 4 * sizeof(instruction);
371 }
372
373 inline void generateSetHi(instruction *insn, int src1, int dest)
374 {
375     insn->raw = 0;
376     insn->sethi.op = FMT2op;
377     insn->sethi.rd = dest;
378     insn->sethi.op2 = SETHIop2;
379     insn->sethi.imm22 = HIGH(src1);
380
381     // logLine("sethi  %%hi(0x%x), %%%s\n", HIGH(src1)*1024, 
382     //  registerNames[dest]);
383 }
384
385 // st rd, [rs1 + offset]
386 inline void generateStore(instruction *insn, int rd, int rs1, int offset)
387 {
388     insn->resti.op = STop;
389     insn->resti.rd = rd;
390     insn->resti.op3 = STop3;
391     insn->resti.rs1 = rs1;
392     insn->resti.i = 1;
393     insn->resti.simm13 = LOW(offset);
394 }
395
396 // sll rs1,rs2,rd
397 inline void generateLShift(instruction *insn, int rs1, int offset, int rd)
398 {
399     insn->restix.op = SLLop;
400     insn->restix.op3 = SLLop3;
401     insn->restix.rd = rd;
402     insn->restix.rs1 = rs1;
403     insn->restix.i = 1;
404     insn->restix.x = 0;
405     insn->restix.rs2 = offset;
406 }
407
408 // sll rs1,rs2,rd
409 inline void generateRShift(instruction *insn, int rs1, int offset, int rd)
410 {
411     insn->restix.op = SRLop;
412     insn->restix.op3 = SRLop3;
413     insn->restix.rd = rd;
414     insn->restix.rs1 = rs1;
415     insn->restix.i = 1;
416     insn->restix.x = 0;
417     insn->restix.rs2 = offset;
418 }
419
420 // load [rs1 + offset], rd
421 inline void generateLoad(instruction *insn, int rs1, int offset, int rd)
422 {
423     insn->resti.op = LOADop;
424     insn->resti.op3 = LDop3;
425     insn->resti.rd = rd;
426     insn->resti.rs1 = rs1;
427     insn->resti.i = 1;
428     insn->resti.simm13 = LOW(offset);
429 }
430
431 // swap [rs1 + offset], rd
432 inline void generateSwap(instruction *insn, int rs1, int offset, int rd)
433 {
434     insn->resti.op = SWAPop;
435     insn->resti.rd = rd;
436     insn->resti.op3 = SWAPop3;
437     insn->resti.rs1 = rs1;
438     insn->resti.i = 0;
439     insn->resti.simm13 = LOW(offset);
440 }    
441
442 // std rd, [rs1 + offset]
443 inline void genStoreD(instruction *insn, int rd, int rs1, int offset)
444 {
445     insn->resti.op = STop;
446     insn->resti.rd = rd;
447     insn->resti.op3 = STDop3;
448     insn->resti.rs1 = rs1;
449     insn->resti.i = 1;
450     insn->resti.simm13 = LOW(offset);
451 }
452
453 // ldd [rs1 + offset], rd
454 inline void genLoadD(instruction *insn, int rs1, int offset, int rd)
455 {
456     insn->resti.op = LOADop;
457     insn->resti.op3 = LDDop3;
458     insn->resti.rd = rd;
459     insn->resti.rs1 = rs1;
460     insn->resti.i = 1;
461     insn->resti.simm13 = LOW(offset);
462 }
463
464
465 // Constructor for the class instPoint. This one defines the 
466 // instPoints for the relocated function. Since the function reloated
467 // to the heap don't need to worry about that jump could be out of
468 // reach, the instructions to be moved are the one instruction at that
469 // point plus others if necessary(i.e. instruction in the delayed
470 // slot and maybe the aggregate instuction ).    
471 instPoint::instPoint(pdFunction *f, const instruction &instr, 
472                      const image *owner, Address &adr, bool delayOK, 
473                      instPointType pointType, Address &oldAddr)
474 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
475   callIndirect(false), callAggregate(false), callee(NULL), func(f), ipType(pointType), image_ptr(owner), firstIsConditional(false)
476 {
477   assert(f->isTrap == true);  
478
479   isBranchOut = false;
480   delaySlotInsn.raw = owner->get_instruction(oldAddr+4);
481   aggregateInsn.raw = owner->get_instruction(oldAddr+8);
482
483   // If the instruction is a DCTI, the instruction in the delayed 
484   // slot is to be moved.
485   if (IS_DELAYED_INST(instr))
486     isDelayed = true;
487
488   // If this function call another function which return an aggregate
489   // value, move the aggregate instruction, too. 
490   if (ipType == callSite) {
491       if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
492           callAggregate = true;
493           adr += 8;
494           oldAddr += 8;
495       }
496   }
497
498   if (owner->isValidAddress(oldAddr-4)) {
499     instruction iplus1;
500     iplus1.raw = owner->get_instruction(oldAddr-4);
501     if (IS_DELAYED_INST(iplus1) && !delayOK) {
502       // ostrstream os(errorLine, 1024, ios::out);
503       // os << "** inst point " << func->file->fullName << "/"
504       //  << func->prettyName() << " at addr " << addr <<
505       //        " in a delay slot\n";
506       // logLine(errorLine);
507       inDelaySlot = true;
508     }
509   }
510 }
511
512 // Another constructor for the class instPoint. This one is called
513 // for the define the instPoints for regular functions which means
514 // multiple instructions is going to be moved to based trampoline.
515 // Since we will use the instruction CALL to branch to the base
516 // tramp(so it doesn't have any code size restriction), things are
517 // a little more complicated because instruction CALL changes the 
518 // value in the link register.
519 instPoint::instPoint(pdFunction *f, const instruction &instr, 
520                      const image *owner, Address &adr,
521                      bool delayOK, bool isLeaf, instPointType pointType)
522 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
523   callIndirect(false), callAggregate(false), callee(NULL), func(f),
524   leaf(isLeaf), ipType(pointType), image_ptr(owner), firstIsConditional(false)
525 {
526
527   isBranchOut = false;
528   size = 0;
529
530   // When the function is not a leaf function 
531   if (!leaf) {
532
533       // we will treat the first instruction after the SAVE instruction
534       // in the nonleaf procedure as the function entry.  
535       if (ipType == functionEntry) {
536
537           assert(isInsnType(instr, SAVEmask, SAVEmatch));
538           addr += 4;
539           originalInstruction.raw = owner->get_instruction(addr);
540           delaySlotInsn.raw = owner->get_instruction(addr+4);
541           size += 2*sizeof(instruction);
542
543           // If the second instruction is DCTI, we need to move the
544           // the instruction in the delayed slot.
545           if (IS_DELAYED_INST(delaySlotInsn)) {
546               isDelayed = true; 
547               isDelayedInsn.raw = owner->get_instruction(addr+8);
548               size += 1*sizeof(instruction);
549
550               // Life is hard. If the second instruction is actually
551               // an CALL instruction, we need to move the instruction
552               // after the instruction in the delayed slot if the 
553               // return value of this function is a aggregate value.
554               aggregateInsn.raw = owner->get_instruction(addr+12);
555               if (isCallInsn(delaySlotInsn)) {
556                   if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
557                       callAggregate = true;
558                       size += 1*sizeof(instruction);
559                   }
560               }
561           }
562
563       // The following are easier.        
564       } else if (ipType == callSite) {
565           delaySlotInsn.raw = owner->get_instruction(addr+4);
566           size += 2*sizeof(instruction);
567
568           aggregateInsn.raw = owner->get_instruction(addr+8);
569           if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
570               callAggregate = true;
571               size += 1*sizeof(instruction);
572           }
573       } else {
574           delaySlotInsn.raw = owner->get_instruction(addr+4);
575           size += 2*sizeof(instruction);
576       }
577
578       //if (owner->isValidAddress(addr-4)) {
579       //          instruction iplus1;
580       //          iplus1.raw = owner->get_instruction(addr-4);
581       //          if (IS_DELAYED_INST(iplus1) && !delayOK) {
582               // ostrstream os(errorLine, 1024, ios::out);
583               // os << "** inst point " << func->file->fullName << "/"
584               //  << func->prettyName() << " at addr " << addr <<
585               //        " in a delay slot\n";
586               // logLine(errorLine);
587       //              inDelaySlot = true;
588       //          }
589       //}
590   }
591
592   // When the function is a leaf function
593   else {
594
595       // For the leaf procedure, there are no function calls in
596       // this procdure. So we don't need to consider the 
597       // aggregate instuction.
598       if (ipType == functionEntry) {
599
600           otherInstruction.raw = owner->get_instruction(addr+4);
601           delaySlotInsn.raw = owner->get_instruction(addr+8);
602           size += 2*sizeof(instruction);
603
604           if (IS_DELAYED_INST(delaySlotInsn)) {
605               isDelayed = true;
606               isDelayedInsn.raw = owner->get_instruction(addr+12);
607               size += 2*sizeof(instruction);
608           }
609
610       } else if (ipType == functionExit) {
611           
612           addr -= 4;
613
614           if (owner->isValidAddress(addr-4)) {
615               instruction iplus1;
616               iplus1.raw = owner->get_instruction(addr-4);
617               if (IS_DELAYED_INST(iplus1) && !delayOK) {
618                   addr -= 4;
619                   inDelaySlot = true;
620                   size += 1*sizeof(instruction);
621                   if(isCondBranch(iplus1)){
622                       instruction previous_inst; 
623                       previous_inst.raw = owner->get_instruction(addr-4);
624                       firstIsConditional = true;
625                       addr -= sizeof(instruction);
626                       size += 1*sizeof(instruction);
627                   }
628               }
629           }
630
631           originalInstruction.raw = owner->get_instruction(addr);
632           otherInstruction.raw = owner->get_instruction(addr+4);
633           delaySlotInsn.raw = owner->get_instruction(addr+8);
634           size += 3*sizeof(instruction);
635
636           if (inDelaySlot) {
637               inDelaySlotInsn.raw = owner->get_instruction(addr+12);
638               if(firstIsConditional) {
639                   extraInsn.raw = owner->get_instruction(addr+16);
640               }
641           }
642
643       } else {
644           // Of course, the leaf function could not have call sites. 
645           logLine("Internal Error: in inst-sparc.C.");
646           abort();
647       }
648   }
649
650   // return the address in the code segment after this instruction
651   // sequence. (there's a -1 here because one will be added up later in
652   // the function findInstPoints)  
653   adr = addr + (size - 1*sizeof(instruction));
654 }
655
656 // Determine if the called function is a "library" function or a "user" function
657 // This cannot be done until all of the functions have been seen, verified, and
658 // classified
659 //
660 void pdFunction::checkCallPoints() {
661   instPoint *p;
662   Address loc_addr;
663
664   vector<instPoint*> non_lib;
665
666   for (unsigned i=0; i<calls.size(); ++i) {
667     /* check to see where we are calling */
668     p = calls[i];
669     assert(p);
670
671     if (isInsnType(p->originalInstruction, CALLmask, CALLmatch)) {
672       // Direct call
673       loc_addr = p->addr + (p->originalInstruction.call.disp30 << 2);
674       pdFunction *pdf = (file_->exec())->findFunction(loc_addr);
675       if (pdf && !pdf->isLibTag()) {
676         p->callee = pdf;
677         non_lib += p;
678       } else if(!pdf){
679            // if this is a call outside the fuction, keep it
680            if((loc_addr < addr()) || (loc_addr > (addr() + size()))){
681                 p->callIndirect = true;
682                 p->callee = NULL;
683                 non_lib += p;
684            }
685            else {
686                delete p;
687            }
688       } else {
689           delete p;
690       }
691     } else {
692       // Indirect call -- be conservative, assume it is a call to 
693       // an unnamed user function
694       assert(!p->callee); assert(p->callIndirect);
695       p->callee = NULL;
696       non_lib += p;
697     }
698   }
699   calls = non_lib;
700 }
701
702 // TODO we cannot find the called function by address at this point in time
703 // because the called function may not have been seen.
704 //
705 Address pdFunction::newCallPoint(Address &adr, const instruction instr,
706                                  const image *owner, bool &err, 
707                                  int &callId, Address &oldAddr)
708 {
709     Address ret=adr;
710     instPoint *point;
711
712     err = true;
713     if (isTrap) {
714         point = new instPoint(this, instr, owner, adr, false, callSite, oldAddr);
715     } else {
716         point = new instPoint(this, instr, owner, adr, false, false, callSite);
717     }
718
719     if (!isInsnType(instr, CALLmask, CALLmatch)) {
720       point->callIndirect = true;
721       point->callee = NULL;
722     } else{
723       point->callIndirect = false;
724     }
725
726     if (isTrap) {
727         if (not_relocating) {
728             calls += point;
729             calls[callId] -> instId = callId++;
730         } else {
731             // calls to a location within the function are not
732             // kept in the calls vector
733             assert(callId >= 0);
734             assert(((u_int)callId) < calls.size());
735             *(calls[callId++]) = *point;
736         }
737     } else {
738         calls += point;
739     }
740     err = false;
741     return ret;
742 }
743
744 //
745 // initDefaultPointFrequencyTable - define the expected call frequency of
746 //    procedures.  Currently we just define several one shots with a
747 //    frequency of one, and provide a hook to read a file with more accurate
748 //    information.
749 //
750 void initDefaultPointFrequencyTable()
751 {
752     FILE *fp;
753     float value;
754     char name[512];
755
756     funcFrequencyTable["main"] = 1;
757     funcFrequencyTable["DYNINSTsampleValues"] = 1;
758     funcFrequencyTable[EXIT_NAME] = 1;
759
760     // try to read file.
761     fp = fopen("freq.input", "r");
762     if (!fp) {
763         return;
764     } else {
765         printf("found freq.input file\n");
766     }
767     while (!feof(fp)) {
768         fscanf(fp, "%s %f\n", name, &value);
769         funcFrequencyTable[name] = (int) value;
770         printf("adding %s %f\n", name, value);
771     }
772     fclose(fp);
773 }
774
775 /*
776  * Get an etimate of the frequency for the passed instPoint.  
777  *    This is not (always) the same as the function that contains the point.
778  * 
779  *  The function is selected as follows:
780  *
781  *  If the point is an entry or an exit return the function name.
782  *  If the point is a call and the callee can be determined, return the called
783  *     function.
784  *  else return the funcation containing the point.
785  *
786  *  WARNING: This code contins arbitray values for func frequency (both user 
787  *     and system).  This should be refined over time.
788  *
789  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
790  *      -- jkh 6/24/94
791  *
792  */
793 float getPointFrequency(instPoint *point)
794 {
795
796     pdFunction *func;
797
798     if (point->callee)
799         func = point->callee;
800     else
801         func = point->func;
802
803     if (!funcFrequencyTable.defines(func->prettyName())) {
804       if (func->isLibTag()) {
805         return(100);
806       } else {
807         // Changing this value from 250 to 100 because predictedCost was
808         // too high - naim 07/18/96
809         return(100); 
810       }
811     } else {
812       return (funcFrequencyTable[func->prettyName()]);
813     }
814 }
815
816 //
817 // return cost in cycles of executing at this point.  This is the cost
818 //   of the base tramp if it is the first at this point or 0 otherwise.
819 //
820 int getPointCost(process *proc, instPoint *point)
821 {
822     if (proc->baseMap.defines(point)) {
823         return(0);
824     } else {
825         // 70 cycles for base tramp (worst case)
826         return(70);
827     }
828 }
829
830 /*
831  * Given and instruction, relocate it to a new address, patching up
832  *   any relative addressing that is present.
833  *
834  */
835 void relocateInstruction(instruction *insn, u_int origAddr, u_int targetAddr,
836                          process *proc)
837 {
838     int newOffset;
839
840     // If the instruction is a CALL instruction, calculate the new
841     // offset
842     if (isInsnType(*insn, CALLmask, CALLmatch)) {
843         newOffset = origAddr  - targetAddr + (insn->call.disp30 << 2);
844         insn->call.disp30 = newOffset >> 2;
845     } else if (isInsnType(*insn, BRNCHmask, BRNCHmatch)||
846                isInsnType(*insn, FBRNCHmask, FBRNCHmatch)) {
847
848         // If the instruction is a Branch instruction, calculate the 
849         // new offset. If the new offset is out of reach after the 
850         // instruction is moved to the base Trampoline, we would do
851         // the following:
852         //    b  address  ......    address: save
853         //                                   call new_offset             
854         //                                   restore 
855         newOffset = origAddr - targetAddr + (insn->branch.disp22 << 2);
856
857         // if the branch is too far, then allocate more space in inferior
858         // heap for a call instruction to branch target.  The base tramp 
859         // will branch to this new inferior heap code, which will call the
860         // target of the branch
861         if (ABS(newOffset) > MAX_BRANCH) {
862             int ret = inferiorMalloc(proc, 3*sizeof(instruction), textHeap);
863             u_int old_offset = insn->branch.disp22 << 2;
864             insn->branch.disp22  = (ret - targetAddr)>>2;
865 // printf("ret = %d origAddr = %d targetAddr = %d disp22 = %d oldoff = %d\n",
866 //          ret ,origAddr, targetAddr,insn->branch.disp22,old_offset);
867
868             instruction insnPlus[3];
869             genImmInsn(insnPlus, SAVEop3, REG_SP, -112, REG_SP);
870             generateCallInsn(insnPlus+1, ret+sizeof(instruction), 
871                              origAddr+old_offset);
872             genSimpleInsn(insnPlus+2, RESTOREop3, 0, 0, 0); 
873             proc->writeDataSpace((caddr_t)ret, sizeof(insnPlus), 
874                          (caddr_t) insnPlus);
875         } else {
876             insn->branch.disp22 = newOffset >> 2;
877         }
878     } else if (isInsnType(*insn, TRAPmask, TRAPmatch)) {
879         // There should be no probelm for moving trap instruction
880         // logLine("attempt to relocate trap\n");
881     } 
882     /* The rest of the instructions should be fine as is */
883 }
884
885 trampTemplate baseTemplate;
886
887 extern "C" void baseTramp();
888
889 void initATramp(trampTemplate *thisTemp, instruction *tramp)
890 {
891     instruction *temp;
892
893     // TODO - are these offset always positive?
894     thisTemp->trampTemp = (void *) tramp;
895     for (temp = tramp; temp->raw != END_TRAMP; temp++) {
896         switch (temp->raw) {
897             case LOCAL_PRE_BRANCH:
898                 thisTemp->localPreOffset = ((void*)temp - (void*)tramp);
899                 thisTemp->localPreReturnOffset = thisTemp->localPreOffset 
900                                                  + sizeof(temp->raw);
901                 break;
902             case GLOBAL_PRE_BRANCH:
903                 thisTemp->globalPreOffset = ((void*)temp - (void*)tramp);
904                 break;
905             case LOCAL_POST_BRANCH:
906                 thisTemp->localPostOffset = ((void*)temp - (void*)tramp);
907                 thisTemp->localPostReturnOffset = thisTemp->localPostOffset
908                                                   + sizeof(temp->raw);
909                 break;
910             case GLOBAL_POST_BRANCH:
911                 thisTemp->globalPostOffset = ((void*)temp - (void*)tramp);
912                 break;
913             case SKIP_PRE_INSN:
914                 thisTemp->skipPreInsOffset = ((void*)temp - (void*)tramp);
915                 break;
916             case SKIP_POST_INSN:
917                 thisTemp->skipPostInsOffset = ((void*)temp - (void*)tramp);
918                 break;
919             case RETURN_INSN:
920                 thisTemp->returnInsOffset = ((void*)temp - (void*)tramp);
921                 break;
922             case EMULATE_INSN:
923                 thisTemp->emulateInsOffset = ((void*)temp - (void*)tramp);
924                 break;
925         }       
926     }
927     thisTemp->size = (int) temp - (int) tramp;
928 }
929
930 registerSpace *regSpace;
931
932 int deadList[] = {16, 17, 18, 19, 20, 21, 22, 23 };
933
934 void initTramps()
935 {
936     static bool inited=false;
937
938     if (inited) return;
939     inited = true;
940
941     initATramp(&baseTemplate, (instruction *) baseTramp);
942
943     regSpace = new registerSpace(sizeof(deadList)/sizeof(int), deadList,                                         0, NULL);
944 }
945
946 /*
947  * Install a base tramp -- fill calls with nop's for now.
948  *
949  * This one install the base tramp for the regular functions.
950  *
951  */
952 trampTemplate *installBaseTramp(instPoint *location, process *proc) 
953 {
954     unsigned currAddr;
955     instruction *code;
956     instruction *temp;
957
958     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
959     code = new instruction[baseTemplate.size];
960     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
961
962     for (temp = code, currAddr = baseAddr; 
963         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
964         temp++, currAddr += sizeof(instruction)) {
965
966         if (temp->raw == EMULATE_INSN) {
967
968             // Load the value of link register from stack 
969             // If it is a leaf function, genereate a RESTORE instruction
970             // since there's an instruction SAVE generated and put in the
971             // code segment.
972             if (location -> leaf) {
973                 genImmInsn(temp, RESTOREop3, 0, 0, 0);
974                 temp++;
975                 currAddr += sizeof(instruction);
976             } 
977
978             // Same for the leaf and nonleaf functions.
979             // First, relocate the "FIRST instruction" in the sequence;  
980             *temp = location->originalInstruction;
981             Address fromAddr = location->addr;
982
983             // compute the real from address if this instrumentation
984             // point is from a shared object image
985             Address baseAddress = 0;
986             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
987 // printf("in installBaseTramp: currAddr = %x fromAddr = %x baseAddr = %x"
988 //      ,currAddr, fromAddr,baseAddress); 
989                 fromAddr += baseAddress;                
990 //              printf(" newAddr = %x\n",fromAddr); 
991             }
992
993             // If the instruction is a call instruction to a location somewhere 
994             // within the function, then the 07 regester must be saved and 
995             // resored around the relocated call from the base tramp...the call
996             // instruction changes the value of 07 to be the PC value, and if
997             // we move the call instruction to the base tramp, its value will
998             // be incorrect when we use it in the function.  We generate the
999             // following base tramp code:
1000             //          original delay slot instruction 
1001             //          save
1002             //          original call instruction
1003             //          restore
1004             // This case should only occur for function entry points in
1005             // functions from shared objects, and there should be no append
1006             // trampolene code because the relocated call instruction will
1007             // not return to the base tramp
1008             if (isInsnType(*temp, CALLmask, CALLmatch)) {
1009                 Address offset = fromAddr + (temp->call.disp30 << 2);
1010                 if ((offset >= (location->func->addr()+ baseAddress)) && 
1011                     (offset <= ((location->func->addr()+ baseAddress)+
1012                                  location->func->size()))) {
1013                     // TODO: this assumes that the delay slot instruction is not
1014                     // a call instruction....is this okay?
1015                     *temp = location->delaySlotInsn;  
1016                     temp++; 
1017                     currAddr += sizeof(instruction);
1018                     genImmInsn(temp, SAVEop3, REG_SP, -112, REG_SP); 
1019                     temp++; 
1020                     currAddr += sizeof(instruction);  
1021                     *temp = location->originalInstruction;
1022                     relocateInstruction(temp, fromAddr, currAddr, proc);
1023                     temp++; 
1024                     fromAddr += sizeof(instruction); 
1025                     currAddr += sizeof(instruction);
1026                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
1027                     continue;
1028                 }
1029             }   
1030
1031             relocateInstruction(temp, fromAddr, currAddr, proc);
1032
1033             // Again, for leaf function, one more is needed to move for one
1034             // more spot;
1035             if (location->leaf) {
1036                 fromAddr += sizeof(instruction);
1037                 currAddr += sizeof(instruction);
1038                 *++temp = location->otherInstruction;
1039                 relocateInstruction(temp, fromAddr, currAddr, 
1040                                     proc);
1041             }     
1042             
1043             // Second, relocate the "NEXT instruction";
1044             fromAddr += sizeof(instruction);
1045             currAddr += sizeof(instruction);
1046             *++temp = location->delaySlotInsn;
1047             relocateInstruction(temp, fromAddr, currAddr,
1048                                 proc);
1049             
1050             // Third, if the "NEXT instruction" is a DCTI, 
1051             if (location->isDelayed) {
1052                 fromAddr += sizeof(instruction);
1053                 currAddr += sizeof(instruction);
1054                 *++temp = location->isDelayedInsn;
1055                 relocateInstruction(temp, fromAddr, currAddr,
1056                                     proc);
1057                 
1058                 // Then, possibly, there's an callAggregate instruction
1059                 // after this. 
1060                 if (location->callAggregate) {
1061                     currAddr += sizeof(instruction);
1062                     *++temp = location->aggregateInsn;
1063                     continue;
1064                 }       
1065             }
1066             
1067             // If the "FIRST instruction" is a DCTI, then our so called 
1068             // "NEXT instruction" is in the delayed Slot and this might
1069             // happen. (actullay, it happened)
1070             if (location->callAggregate) {
1071                 currAddr += sizeof(instruction);
1072                 *++temp = location->aggregateInsn;
1073                 continue;
1074             }   
1075             
1076             // For the leaf function, if there's an inDelaySlot instruction,
1077             // move this one to the base Tramp.(i.e. at the function exit,
1078             // if the first instruction is in the delayed slot the previous
1079             // instruction, we have to move that one too, so we count from 
1080             // that one and the last one is this sequence is called inDelaySlot
1081             // instruction.)
1082             // Well, after all these, another SAVE instruction is generated
1083             // so we are prepared to handle the returning to our application's
1084             // code segment. 
1085             if (location->leaf) {
1086                 if (location->inDelaySlot) {
1087                     fromAddr += sizeof(instruction);
1088                     currAddr += sizeof(instruction);
1089                     *++temp = location->inDelaySlotInsn;
1090                     relocateInstruction(temp, fromAddr, currAddr, proc);
1091                     if(location->firstIsConditional){
1092                         fromAddr += sizeof(instruction);
1093                         currAddr += sizeof(instruction);
1094                         *++temp = location->extraInsn;
1095                         relocateInstruction(temp, fromAddr, currAddr, proc);
1096                     }
1097                 } 
1098                 
1099                 genImmInsn(temp+1, SAVEop3, REG_SP, -112, REG_SP);
1100             }
1101             
1102         } else if (temp->raw == RETURN_INSN) {
1103             // compute the real from address if this instrumentation
1104             // point is from a shared object image
1105             Address baseAddress = 0;
1106             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
1107 // printf("in installBaseTramp: RETURN_INSN: baseAddr = %x currAddr = %x size = %x\n",baseAddress,currAddr,location->size); 
1108             }
1109             // Back to the code segement of the application.
1110             // If the location is in the leaf procedure, generate an RESTORE
1111             // instruction right after the CALL instruction to restore all
1112             // the values in the registers.
1113             if (location -> leaf) {
1114                 generateCallInsn(temp, currAddr, 
1115                                 (baseAddress + location->addr)+location->size);
1116                 genImmInsn(temp+1, RESTOREop3, 0, 0, 0);
1117             } else {
1118                 generateCallInsn(temp, currAddr, 
1119                                 (baseAddress + location->addr)+location->size);
1120             }
1121         } else if (temp->raw == SKIP_PRE_INSN) {
1122           unsigned offset;
1123           offset = baseAddr+baseTemplate.emulateInsOffset-currAddr;
1124           generateBranchInsn(temp,offset);
1125         } else if (temp->raw == SKIP_POST_INSN) {
1126           unsigned offset;
1127           offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
1128           generateBranchInsn(temp,offset);
1129         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
1130                    (temp->raw == GLOBAL_PRE_BRANCH) ||
1131                    (temp->raw == LOCAL_POST_BRANCH) ||
1132                    (temp->raw == GLOBAL_POST_BRANCH)) {
1133             /* fill with no-op */
1134             generateNOOP(temp);
1135         }
1136     }
1137     // TODO cast
1138     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
1139     free(code);
1140
1141     trampTemplate *baseInst = new trampTemplate;
1142     *baseInst = baseTemplate;
1143     baseInst->baseAddr = baseAddr;
1144     return baseInst;
1145 }
1146
1147 /*
1148  * Install the base Tramp for the function relocated.
1149  * (it means the base tramp that don't need to bother with long jump and
1150  *  is the one we used before for all the functions(since there's no
1151  *  long jumps)
1152  *  for system calls
1153  */ 
1154 trampTemplate *installBaseTrampSpecial(instPoint *location,
1155                              process *proc,
1156                              vector<instruction> &extra_instrs) 
1157 {
1158     unsigned currAddr;
1159     instruction *code;
1160     instruction *temp;
1161
1162     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
1163     if (location->func->not_relocating) {
1164         location->func->not_relocating = false;
1165         location->func->relocateFunction(proc,location,extra_instrs);
1166     }
1167
1168     code = new instruction[baseTemplate.size];
1169     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
1170
1171     for (temp = code, currAddr = baseAddr; 
1172         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
1173         temp++, currAddr += sizeof(instruction)) {
1174
1175         // get the base address if this is a shared object
1176         Address baseAddress = 0;
1177         if(!(proc->getBaseAddress(location->image_ptr,baseAddress))){
1178            baseAddress = 0;
1179         }
1180         if (temp->raw == EMULATE_INSN) {
1181
1182             if (location->isBranchOut) {
1183                 // the original instruction is a branch that goes out of a 
1184                 // function.  We don't relocate the original instruction. We 
1185                 // only get to the tramp is the branch is taken, so we generate
1186                 // a unconditional branch to the target of the original 
1187                 // instruction here 
1188                 assert(location->branchTarget);
1189                 // int disp = location->branchTarget + baseAddress - currAddr;
1190                 int disp = location->branchTarget - currAddr;
1191                 //printf("A disp = %x\n",disp);
1192                 generateBranchInsn(temp, disp);
1193                 disp = temp->branch.disp22;
1194                 continue;
1195             }
1196             else {
1197                 *temp = location->originalInstruction;
1198                 // compute the real from address if this instrumentation
1199                 // point is from a shared object image
1200                 Address fromAddress = location->addr;
1201                 //if(proc->getBaseAddress(location->image_ptr,baseAddress)){
1202                 //   fromAddress += baseAddress;
1203                 // }    
1204                 relocateInstruction(temp, fromAddress, currAddr, proc);
1205                 if (location->isDelayed) {
1206                     /* copy delay slot instruction into tramp instance */
1207                     currAddr += sizeof(instruction);  
1208                     *++temp = location->delaySlotInsn;
1209                 }
1210                 if (location->callAggregate) {
1211                     /* copy invalid insn with aggregate size in it */
1212                     currAddr += sizeof(instruction);  
1213                     *++temp = location->aggregateInsn;
1214                 }
1215             }
1216         } else if (temp->raw == RETURN_INSN) {
1217             generateBranchInsn(temp, 
1218                 (location->addr+ sizeof(instruction) - currAddr));
1219             if (location->isDelayed) {
1220                 /* skip the delay slot instruction */
1221                 temp->branch.disp22 += 1;
1222             }
1223             if (location->callAggregate) {
1224                 /* skip the aggregate size slot */
1225                 temp->branch.disp22 += 1;
1226             }
1227         } else if (temp->raw == SKIP_PRE_INSN) {
1228           unsigned offset;
1229           offset = baseAddr+baseTemplate.emulateInsOffset-currAddr;
1230           generateBranchInsn(temp,offset);
1231         } else if (temp->raw == SKIP_POST_INSN) {
1232           unsigned offset;
1233           offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
1234           generateBranchInsn(temp,offset);
1235         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
1236                    (temp->raw == GLOBAL_PRE_BRANCH) ||
1237                    (temp->raw == LOCAL_POST_BRANCH) ||
1238                    (temp->raw == GLOBAL_POST_BRANCH)) {
1239             /* fill with no-op */
1240             generateNOOP(temp);
1241         }
1242     }
1243     // TODO cast
1244     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
1245     free(code);
1246     trampTemplate *baseInst = new trampTemplate;
1247     *baseInst = baseTemplate;
1248     baseInst->baseAddr = baseAddr;
1249     return baseInst;
1250 }
1251
1252 void generateNoOp(process *proc, int addr)
1253 {
1254     instruction insn;
1255
1256     /* fill with no-op */
1257     insn.raw = 0;
1258     insn.branch.op = 0;
1259     insn.branch.op2 = NOOPop2;
1260
1261     // TODO cast
1262     proc->writeTextWord((caddr_t)addr, insn.raw);
1263     // (void) PCptrace(PTRACE_POKETEXT, proc, (char*)addr, insn.raw, NULL);
1264 }
1265
1266 void changeBranch(process *proc, unsigned fromAddr, unsigned newAddr, 
1267                   instruction originalBranch);
1268
1269 void generateCall(process *proc, unsigned fromAddr, unsigned newAddr);
1270 void genImm(process *proc, unsigned fromAddr, int op, reg rs1, int immd,reg rd);
1271
1272
1273 void AstNode::sysFlag(instPoint *location)
1274 {
1275     astFlag = location->func->isTrap;
1276     if (loperand)
1277         loperand->sysFlag(location);
1278     if (roperand)
1279         roperand->sysFlag(location); 
1280
1281     for (unsigned u = 0; u < operands.size(); u++)
1282         operands[u].sysFlag(location);
1283 }
1284
1285
1286 /*
1287  * Allocate the space for the base Trampoline, and generate the instruction
1288  * we need for modifying the code segment
1289  *
1290  */
1291 trampTemplate *findAndInstallBaseTramp(process *proc, 
1292                                  instPoint *location,
1293                                  returnInstance *&retInstance)
1294 {
1295     Address adr = location->addr;
1296     trampTemplate *ret;
1297     process *globalProc;
1298
1299     if (nodePseudoProcess && (proc->symbols == nodePseudoProcess->symbols)){
1300         globalProc = nodePseudoProcess;
1301     } else {
1302         globalProc = proc;
1303     }
1304
1305     retInstance = NULL;
1306     if (!globalProc->baseMap.defines(location)) {
1307         if (location->func->isTrap) {
1308             // get the base Address of this function if it is a 
1309             // shared object
1310             Address baseAddress = 0;
1311             if(!(proc->getBaseAddress(location->image_ptr,baseAddress))){
1312                 // TODO: what should be done here?      
1313                 logLine("Error:findAndInstallBaseTramp call getBaseAddress\n"); 
1314             }
1315             // Install Base Tramp for the functions which are 
1316             // relocated to the heap.
1317             vector<instruction> extra_instrs;
1318             ret = installBaseTrampSpecial(location, globalProc,extra_instrs);
1319             if (location->isBranchOut){
1320                 changeBranch(globalProc, location->addr, 
1321                   (int) ret->baseAddr, location->originalInstruction);
1322             } else {
1323                 generateBranch(globalProc, location->addr, 
1324                               (int)ret->baseAddr);
1325             }
1326
1327             // If the function has not been installed to the base Tramp yet,
1328             // generate the following instruction sequece at the right
1329             // beginning of this function:
1330             //   SAVE;             CALL;         RESTORE.
1331             // so that it would jump the start of the relocated function
1332             // which is in heap.
1333             if (location->func->notInstalled) {
1334                 location->func->notInstalled = false;
1335                 u_int e_size = extra_instrs.size();
1336                 instruction *insn = new instruction[3 + e_size];
1337                 Address adr = location-> func -> addr();
1338                 genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1339                 generateCallInsn(insn+1, adr+baseAddress+4, 
1340                                  location->func->newAddr);
1341                 genSimpleInsn(insn+2, RESTOREop3, 0, 0, 0); 
1342                 for(u_int i=0; i < e_size; i++){
1343                     insn[3+i] = extra_instrs[i];
1344                 }
1345                 retInstance = new returnInstance((instructUnion *)insn, 
1346                                          (3+e_size)*sizeof(instruction), 
1347                                          adr+baseAddress, 
1348                                          location->func->size());
1349             }
1350
1351         } else {
1352             // Install base tramp for all the other regular functions. 
1353             ret = installBaseTramp(location, globalProc);
1354             // compute the real from address if this instrumentation
1355             // point is from a shared object image
1356             Address baseAddress = 0;
1357             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
1358                 adr += baseAddress;             
1359             }
1360             if (location->leaf) {
1361                 // if it is the leaf function, we need to generate
1362                 // the following instruction sequence:
1363                 //     SAVE;      CALL;      NOP.
1364                 instruction *insn = new instruction[3];
1365                 genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1366                 generateCallInsn(insn+1, adr+4, (int) ret->baseAddr);
1367                 generateNOOP(insn+2);
1368                 retInstance = new returnInstance((instructUnion *)insn, 
1369                                                  3*sizeof(instruction), adr, 
1370                                                  3*sizeof(instruction));
1371             } else {
1372                 // Otherwise,
1373                 // Generate branch instruction from the application to the
1374                 // base trampoline and no SAVE instruction is needed
1375                 instruction *insn = new instruction[2]; 
1376                 generateCallInsn(insn, adr, (int) ret->baseAddr);
1377                 generateNOOP(insn+1);
1378                 retInstance = new returnInstance((instructUnion *)insn, 
1379                                                  2*sizeof(instruction), adr, 
1380                                                  2*sizeof(instruction));
1381             }
1382         }
1383
1384         globalProc->baseMap[location] = ret;
1385
1386     } else {
1387         ret = globalProc->baseMap[location];
1388     }
1389       
1390     return(ret);
1391 }
1392
1393 /*
1394  * Install a single tramp.
1395  *
1396  */
1397 void installTramp(instInstance *inst, char *code, int codeSize) 
1398 {
1399     totalMiniTramps++;
1400     insnGenerated += codeSize/sizeof(int);
1401     
1402     // TODO cast
1403     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
1404
1405     unsigned atAddr;
1406     if (inst->when == callPreInsn) {
1407       atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPreInsOffset;
1408     }
1409     else {
1410       atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPostInsOffset; 
1411     }
1412     generateNoOp(inst->proc, atAddr);
1413 }
1414
1415 /*
1416  * change the insn at addr to be a branch to newAddr.
1417  *   Used to add multiple tramps to a point.
1418  */
1419 void generateBranch(process *proc, unsigned fromAddr, unsigned newAddr)
1420 {
1421     int disp;
1422     instruction insn;
1423
1424     disp = newAddr-fromAddr;
1425     generateBranchInsn(&insn, disp);
1426
1427     // TODO cast
1428     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1429     // (void) PCptrace(PTRACE_POKETEXT, proc, (char*)fromAddr, insn.raw, NULL);
1430 }
1431
1432 void generateCall(process *proc, unsigned fromAddr,unsigned newAddr)
1433 {
1434     instruction insn; 
1435     generateCallInsn(&insn, fromAddr, newAddr);
1436
1437     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1438
1439 }
1440
1441 void genImm(process *proc, Address fromAddr,int op, reg rs1, int immd, reg rd)
1442 {
1443     instruction insn;
1444     genImmInsn(&insn, op, rs1, immd, rd);
1445
1446     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1447 }
1448
1449 /*
1450  *  change the target of the branch at fromAddr, to be newAddr.
1451  */
1452 void changeBranch(process *proc, unsigned fromAddr, unsigned newAddr, 
1453                   instruction originalBranch) {
1454     int disp = newAddr-fromAddr;
1455     instruction insn;
1456     insn.raw = originalBranch.raw;
1457     insn.branch.disp22 = disp >> 2;
1458     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1459 }
1460
1461 int callsTrackedFuncP(instPoint *point)
1462 {
1463     if (point->callIndirect) {
1464 #ifdef notdef
1465         // TODO this won't compile now
1466         // it's rare to call a library function as a parameter.
1467         sprintf(errorLine, "*** Warning call indirect\n from %s %s (addr %d)\n",
1468             point->func->file->fullName, point->func->prettyName, point->addr);
1469         logLine(errorLine);
1470 #endif
1471         return(true);
1472     } else {
1473         if (point->callee && !(point->callee->isLibTag())) {
1474             return(true);
1475         } else {
1476             return(false);
1477         }
1478     }
1479 }
1480
1481 /*
1482  * return the function asociated with a point.
1483  *
1484  *     If the point is a funcation call, and we know the function being called,
1485  *          then we use that.  Otherwise it is the function that contains the
1486  *          point.
1487  *  
1488  *   This is done to return a better idea of which function we are using.
1489  */
1490 pdFunction *getFunction(instPoint *point)
1491 {
1492     return(point->callee ? point->callee : point->func);
1493 }
1494
1495 unsigned emitFuncCall(opCode op, 
1496                       registerSpace *rs,
1497                       char *i, unsigned &base, 
1498                       vector<AstNode> operands, 
1499                       string callee, process *proc)
1500 {
1501         assert(op == callOp);
1502         unsigned addr;
1503         bool err;
1504         vector <reg> srcs;
1505
1506         addr = (proc->symbols)->findInternalAddress(callee, false, err);
1507         if (err) {
1508             pdFunction *func = (proc->symbols)->findOneFunction(callee);
1509             if (!func) {
1510                 ostrstream os(errorLine, 1024, ios::out);
1511                 os << "Internal error: unable to find addr of " << callee << endl;
1512                 logLine(errorLine);
1513                 showErrorCallback(80, (const char *) errorLine);
1514                 P_abort();
1515             }
1516             addr = func->addr();
1517         }
1518         
1519         for (unsigned u = 0; u < operands.size(); u++)
1520             srcs += operands[u].generateCode(proc, rs, i, base);
1521         
1522         // TODO cast
1523         instruction *insn = (instruction *) ((void*)&i[base]);
1524
1525         for (unsigned u=0; u<srcs.size(); u++){
1526             if (u >= 5) {
1527                  string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
1528                  fprintf(stderr, msg.string_of());
1529                  showErrorCallback(94,msg);
1530                  cleanUpAndExit(-1);
1531             }
1532             genSimpleInsn(insn, ORop3, 0, srcs[u], u+8); insn++;
1533             base += sizeof(instruction);
1534             rs->freeRegister(srcs[u]);
1535         }
1536
1537         generateSetHi(insn, addr, 13); insn++;
1538         genImmInsn(insn, JMPLop3, 13, LOW(addr), 15); insn++;
1539         generateNOOP(insn);
1540
1541         base += 3 * sizeof(instruction);
1542
1543         // return value is the register with the return value from the
1544         //   function.
1545         // This needs to be %o0 since it is back in the callers scope.
1546         return(8);
1547 }
1548  
1549 unsigned emitImm(opCode op, reg src1, reg src2, reg dest, char *i, 
1550                  unsigned &base)
1551 {
1552         instruction *insn = (instruction *) ((void*)&i[base]);
1553         int op3=-1;
1554         int result;
1555         switch (op) {
1556             // integer ops
1557             case plusOp:
1558                 op3 = ADDop3;
1559                 genImmInsn(insn, op3, src1, src2, dest);
1560                 break;
1561
1562             case minusOp:
1563                 op3 = SUBop3;
1564                 genImmInsn(insn, op3, src1, src2, dest);
1565                 break;
1566
1567             case timesOp:
1568                 op3 = SMULop3;
1569                 if (isPowerOf2(src2,result))
1570                   generateLShift(insn, src1, (reg)result, dest);           
1571                 else 
1572                   genImmInsn(insn, op3, src1, src2, dest);
1573                 break;
1574
1575             case shiftOp:
1576                 op3 = SLLop3;
1577                 generateLShift(insn, src1, src2, dest);           
1578                 break;
1579
1580             case divOp:
1581                 op3 = SDIVop3;
1582                 if (isPowerOf2(src2,result))
1583                   generateRShift(insn, src1, (reg)result, dest);           
1584                 else 
1585                   genImmInsn(insn, op3, src1, src2, dest);
1586                 break;
1587
1588             // Bool ops
1589             case orOp:
1590                 op3 = ORop3;
1591                 genImmInsn(insn, op3, src1, src2, dest);
1592                 break;
1593
1594             case andOp:
1595                 op3 = ANDop3;
1596                 genImmInsn(insn, op3, src1, src2, dest);
1597                 break;
1598
1599             // rel ops
1600             // For a particular condition (e.g. <=) we need to use the
1601             // the opposite in order to get the right value (e.g. for >=
1602             // we need BLTcond) - naim
1603             case eqOp:
1604                 genImmRelOp(insn, BNEcond, src1, src2, dest, base);
1605                 return(0);
1606                 break;
1607
1608             case neOp:
1609                 genImmRelOp(insn, BEcond, src1, src2, dest, base);
1610                 return(0);
1611                 break;
1612
1613             case lessOp:
1614                 genImmRelOp(insn, BGEcond, src1, src2, dest, base);
1615                 return(0);
1616                 break;
1617
1618             case leOp:
1619                 genImmRelOp(insn, BGTcond, src1, src2, dest, base);
1620                 return(0);
1621                 break;
1622
1623             case greaterOp:
1624                 genImmRelOp(insn, BLEcond, src1, src2, dest, base);
1625                 return(0);
1626                 break;
1627
1628             case geOp:
1629                 genImmRelOp(insn, BLTcond, src1, src2, dest, base);
1630                 return(0);
1631                 break;
1632
1633             default:
1634                 abort();
1635                 break;
1636         }
1637         base += sizeof(instruction);
1638         return(0);
1639 }
1640
1641 unsigned emit(opCode op, reg src1, reg src2, reg dest, char *i, unsigned &base)
1642 {
1643     // TODO cast
1644     instruction *insn = (instruction *) ((void*)&i[base]);
1645
1646     if (op == loadConstOp) {
1647       // dest = src1:imm    TODO
1648       if (src1 > MAX_IMM13 || src1 < MIN_IMM13) {
1649             generateSetHi(insn, src1, dest);
1650             base += sizeof(instruction);
1651             insn++;
1652
1653             // or regd,imm,regd
1654             genImmInsn(insn, ORop3, dest, LOW(src1), dest);
1655             base += sizeof(instruction);
1656         } else {
1657             // really or %g0,imm,regd
1658             genImmInsn(insn, ORop3, 0, src1, dest);
1659
1660             base += sizeof(instruction);
1661         }
1662     } else if (op ==  loadOp) {
1663         // dest = [src1]   TODO
1664         generateSetHi(insn, src1, dest);
1665         insn++;
1666
1667         generateLoad(insn, dest, src1, dest);
1668
1669         base += sizeof(instruction)*2;
1670     } else if (op ==  shiftOp) {
1671         generateLShift(insn, src1, src2, dest);
1672         base += sizeof(instruction);
1673     } else if (op ==  storeOp) {
1674         insn->sethi.op = FMT2op;
1675         insn->sethi.rd = src2;
1676         insn->sethi.op2 = SETHIop2;
1677         insn->sethi.imm22 = HIGH(dest);
1678         insn++;
1679
1680         generateStore(insn, src1, src2, dest);
1681
1682         base += sizeof(instruction)*2;
1683     } else if (op ==  ifOp) {
1684         // cmp src1,0
1685         genSimpleInsn(insn, SUBop3cc, src1, 0, 0); insn++;
1686
1687         insn->branch.op = 0;
1688         insn->branch.cond = BEcond;
1689         insn->branch.op2 = BICCop2;
1690         insn->branch.anneal = false;
1691         insn->branch.disp22 = dest/4;
1692         insn++;
1693
1694         generateNOOP(insn);
1695         base += sizeof(instruction)*3;
1696         return(base - 2*sizeof(instruction));
1697     } else if (op ==  trampPreamble) {
1698 #ifdef ndef
1699         // save and restore are done inthe base tramp now
1700         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1701         base += sizeof(instruction);
1702         insn++;
1703
1704         // generate code to save global registers
1705         for (unsigned u = 0; u < 4; u++) {
1706           genStoreD(insn, 2*u, REG_FP, - (8 + 8*u));
1707           base += sizeof(instruction);
1708           insn++;
1709         }
1710 #endif
1711         // generate code to update the observed cost.
1712         // sethi %hi(dest), %l0
1713         generateSetHi(insn, dest, REG_L0);
1714         base += sizeof(instruction);
1715         insn++;
1716   
1717         // ld [%l0+ lo(dest)], %l1
1718         generateLoad(insn, REG_L0, dest, REG_L1);
1719         base += sizeof(instruction);
1720         insn++;
1721   
1722         // update value
1723         if (src1 <= MAX_IMM13) {
1724             genImmInsn(insn, ADDop3, REG_L1, src1, REG_L1);
1725             base += sizeof(instruction);
1726             insn++;
1727         } else {
1728             // load in two parts
1729             generateSetHi(insn, src1, REG_L2);
1730             base += sizeof(instruction);
1731             insn++;
1732
1733             // or regd,imm,regd
1734             genImmInsn(insn, ORop3, REG_L2, LOW(src1), REG_L2);
1735             base += sizeof(instruction);
1736             insn++;
1737
1738             // now add it
1739             genSimpleInsn(insn, ADDop3, REG_L1, REG_L2, REG_L1);
1740             base += sizeof(instruction);
1741             insn++;
1742         }
1743   
1744         // store result st %l1, [%l0+ lo(dest)];
1745         generateStore(insn, REG_L1, REG_L0, dest);
1746         base += sizeof(instruction);
1747         insn++;
1748     } else if (op ==  trampTrailer) {
1749 #ifdef ndef
1750         // save and restore are done inthe base tramp now
1751         // generate code to restore global registers
1752         for (unsigned u = 0; u < 4; u++) {
1753           genLoadD(insn, REG_FP, - (8 + 8*u), 2*u);
1754           base += sizeof(instruction);
1755           insn++;
1756         }
1757
1758         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); 
1759         base += sizeof(instruction);
1760         insn++;
1761
1762         generateNOOP(insn);
1763         base += sizeof(instruction);
1764         insn++;
1765 #endif
1766         // dest is in words of offset and generateBranchInsn is bytes offset
1767         generateBranchInsn(insn, dest << 2);
1768         base += sizeof(instruction);
1769         insn++;
1770
1771         // add no-op, SS-5 sometimes seems to try to decode this insn - jkh 2/14
1772         generateNOOP(insn);
1773         insn++;
1774         base += sizeof(instruction);
1775
1776         return(base -  2 * sizeof(instruction));
1777     } else if (op == noOp) {
1778         generateNOOP(insn);
1779         base += sizeof(instruction);
1780     } else if (op == getParamOp) {
1781         // first 8 parameters are in register 24 ....
1782         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1783         insn++;
1784
1785         generateStore(insn, 24+src1, REG_SP, 68+4*src1); 
1786         insn++;
1787               
1788         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1789         insn++;
1790
1791         generateLoad(insn, REG_SP, 112+68+4*src1, 24+src1); 
1792         insn++;
1793
1794         base += 4*sizeof(instruction);
1795         
1796         if (src1 <= 8) {
1797             return(24+src1);
1798         }
1799         
1800         abort();
1801     } else if (op == getSysParamOp) {
1802         
1803         if (src1 <= 8) {
1804             return(24+src1);
1805         }       
1806     } else if (op == getRetValOp) {
1807         // return value is in register 24
1808         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1809         insn++;
1810
1811         generateStore(insn, 24, REG_SP, 68); 
1812         insn++;
1813               
1814         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1815         insn++;
1816
1817         generateLoad(insn, REG_SP, 112+68, 24); 
1818         insn++;
1819
1820         base += 4*sizeof(instruction);
1821
1822         return(24);
1823
1824     } else if (op == getSysRetValOp) {
1825         return(24);
1826     } else if (op == saveRegOp) {
1827         // should never be called for this platform.
1828         abort();
1829     } else {
1830       int op3=-1;
1831         switch (op) {
1832             // integer ops
1833             case plusOp:
1834                 op3 = ADDop3;
1835                 break;
1836
1837             case minusOp:
1838                 op3 = SUBop3;
1839                 break;
1840
1841             case timesOp:
1842                 op3 = SMULop3;
1843                 break;
1844
1845             case divOp:
1846                 op3 = SDIVop3;
1847                 break;
1848
1849             // Bool ops
1850             case orOp:
1851                 op3 = ORop3;
1852                 break;
1853
1854             case andOp:
1855                 op3 = ANDop3;
1856                 break;
1857
1858             // rel ops
1859             // For a particular condition (e.g. <=) we need to use the
1860             // the opposite in order to get the right value (e.g. for >=
1861             // we need BLTcond) - naim
1862             case eqOp:
1863                 genRelOp(insn, BNEcond, src1, src2, dest, base);
1864                 return(0);
1865                 break;
1866
1867             case neOp:
1868                 genRelOp(insn, BEcond, src1, src2, dest, base);
1869                 return(0);
1870                 break;
1871
1872             case lessOp:
1873                 genRelOp(insn, BGEcond, src1, src2, dest, base);
1874                 return(0);
1875                 break;
1876
1877             case leOp:
1878                 genRelOp(insn, BGTcond, src1, src2, dest, base);
1879                 return(0);
1880                 break;
1881
1882             case greaterOp:
1883                 genRelOp(insn, BLEcond, src1, src2, dest, base);
1884                 return(0);
1885                 break;
1886
1887             case geOp:
1888                 genRelOp(insn, BLTcond, src1, src2, dest, base);
1889                 return(0);
1890                 break;
1891
1892             default:
1893                 abort();
1894                 break;
1895         }
1896         genSimpleInsn(insn, op3, src1, src2, dest);
1897
1898         base += sizeof(instruction);
1899       }
1900     return(0);
1901 }
1902
1903 //
1904 // All values based on Cypress0 && Cypress1 implementations as documented in
1905 //   SPARC v.8 manual p. 291
1906 //
1907 int getInsnCost(opCode op)
1908 {
1909     if (op == loadConstOp) {
1910         return(1);
1911     } else if (op ==  loadOp) {
1912         // sethi + load single
1913         return(1+1);
1914     } else if (op ==  shiftOp) {
1915         return(1);
1916     } else if (op ==  storeOp) {
1917         // sethi + store single
1918         // return(1+3); 
1919         // for SS-5 ?
1920         return(1+2); 
1921     } else if (op ==  ifOp) {
1922         // subcc
1923         // be
1924         // nop
1925         return(1+1+1);
1926     } else if (op ==  callOp) {
1927         int count = 0;
1928
1929         // mov src1, %o0
1930         count += 1;
1931
1932         // mov src2, %o1
1933         count += 1;
1934
1935         // clr i2
1936         count += 1;
1937
1938         // clr i3
1939         count += 1;
1940
1941         // sethi
1942         count += 1;
1943
1944         // jmpl
1945         count += 1;
1946
1947         // noop
1948         count += 1;
1949
1950         return(count);
1951     } else if (op ==  trampPreamble) {
1952         // save
1953         // sethi %hi(obsCost), %l0
1954         // ld [%lo + %lo(obsCost)], %l1
1955         // add %l1, <cost>, %l1
1956         // st %l1, [%lo + %lo(obsCost)]
1957         // return(1+1+2+1+3);
1958         return(1+1+1+1+2 + 4);
1959     } else if (op ==  trampTrailer) {
1960         // restore
1961         // noop
1962         // retl
1963         return(1+1+1 + 4);
1964     } else if (op == noOp) {
1965         // noop
1966         return(1);
1967     } else if (op == getParamOp) {
1968         return(0);
1969     } else {
1970         switch (op) {
1971             // rel ops
1972             case eqOp:
1973             case neOp:
1974             case lessOp:
1975             case leOp:
1976             case greaterOp:
1977             case geOp:
1978                 // bne -- assume taken
1979                 return(2);
1980                 break;
1981             default:
1982                 return(1);
1983                 break;
1984         }
1985     }
1986 }
1987
1988 bool isReturnInsn(const image *owner, Address adr, bool &lastOne)
1989 {
1990     instruction instr;
1991     
1992     instr.raw = owner->get_instruction(adr);
1993     lastOne = false;
1994
1995     if (isInsnType(instr, RETmask, RETmatch) ||
1996         isInsnType(instr, RETLmask, RETLmatch)) {
1997         if ((instr.resti.simm13 != 8) && (instr.resti.simm13 != 12)) {
1998             logLine("*** FATAL Error:");
1999             sprintf(errorLine, " unsupported return\n");
2000             logLine(errorLine);
2001             showErrorCallback(55, "");
2002             P_abort();
2003         }
2004         return true;
2005     }
2006     return false;
2007 }
2008
2009 /*
2010  * Find the instPoints of this function.
2011  */
2012 bool pdFunction::findInstPoints(const image *owner) {
2013
2014    if (size() == 0) {
2015      return false;
2016    }
2017
2018    leaf = true;
2019    Address adr;
2020    Address adr1 = addr();
2021    instruction instr;
2022    instr.raw = owner->get_instruction(adr1);
2023    if (!IS_VALID_INSN(instr))
2024      return false;
2025
2026    // If it contains an instruction, I assume it would be s system call
2027    // which will be treat differently. 
2028    isTrap = false;
2029    not_relocating = false;
2030    for ( ; adr1 < addr() + size(); adr1 += 4) {
2031        instr.raw = owner->get_instruction(adr1);
2032
2033        // If there's an TRAP instruction in the function, we 
2034        // assume that it is an system call and will relocate it 
2035        // to the heap
2036        if (isInsnType(instr, TRAPmask, TRAPmatch)) {
2037            isTrap = true;
2038            not_relocating = true;
2039            notInstalled = true;
2040            return findInstPoints(owner, addr(), 0);
2041        } 
2042
2043 #if defined(sparc_sun_solaris2_4)
2044        // TODO: This is a hacking for the solaris(solaris2.5 actually)
2045        // We will relocate that function if the function has been 
2046        // tail-call optimazed.
2047        // (Actully, the reason of this is that the system calls like 
2048        //  read, write, etc have the tail-call optimazation to call
2049        //  the _read, _write etc. which contain the TRAP instruction 
2050        if (isLibTag()) {
2051            if (isCallInsn(instr)) {
2052                instruction nexti; 
2053                nexti.raw = owner->get_instruction(adr1+4);
2054                
2055                if (nexti.rest.op == 2 
2056                    && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
2057                        || nexti.rest.op3 == RESTOREop3)) {
2058                    isTrap = true;
2059                    not_relocating = true;
2060                    notInstalled = true;
2061                    return findInstPoints(owner, addr(), 0);
2062                }
2063            }   
2064        }
2065 #endif
2066
2067        // The function Entry is defined as the first SAVE instruction plus
2068        // the instructions after this.
2069        // ( The first instruction for the nonleaf function is not 
2070        //   necessarily a SAVE instruction. ) 
2071        if (isInsnType(instr, SAVEmask, SAVEmatch)) {
2072              
2073            leaf = false;
2074            funcEntry_ = new instPoint(this, instr, owner, adr1, true, leaf, 
2075                                       functionEntry);
2076            adr = adr1;
2077            assert(funcEntry_);
2078        }
2079    }
2080
2081    // If there's no SAVE instruction found, this is a leaf function and
2082    // and function Entry will be defined from the first instruction
2083    if (leaf) {
2084        adr = addr();
2085        instr.raw = owner->get_instruction(adr);
2086        funcEntry_ = new instPoint(this, instr, owner, adr, true, leaf, functionEntry);
2087        assert(funcEntry_);
2088    }
2089
2090    for ( ; adr < addr() + size(); adr += sizeof(instruction)) {
2091
2092      instr.raw = owner->get_instruction(adr);
2093
2094      bool done;
2095
2096      // check for return insn and as a side affect decide if we are at the
2097      //   end of the function.
2098      if (isReturnInsn(owner, adr, done)) {
2099        // define the return point
2100        funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
2101                                     functionExit);
2102
2103      } else if (instr.branch.op == 0 
2104                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6) 
2105                 && (instr.branch.cond == 0 ||instr.branch.cond == 8)) {
2106        // find if this branch is going out of the function
2107        int disp = instr.branch.disp22;
2108        Address target = adr +  (disp << 2);
2109        if ((target < (addr()))  
2110            || (target >= (addr() + size()))) {
2111          instPoint *point = new instPoint(this, instr, owner, adr, false, leaf, 
2112                                           functionExit);
2113          funcReturns += point;
2114        }
2115
2116      } else if (isCallInsn(instr)) {
2117
2118        // if the call target is the address of the call instruction
2119        // then this is not something that we can instrument...
2120        // this occurs in functions with code that is modifined when 
2121        // they are loaded by the run-time linker, or when the .init
2122        // section is executed.  In this case the instructions in the
2123        // parsed image file are different from the ones in the executable
2124        // process.
2125        if(instr.call.op == CALLop) { 
2126            Address call_target = adr + (instr.call.disp30 << 2);
2127            if(call_target == adr){ 
2128                 return false;
2129        }}
2130        // first, check for tail-call optimization: a call where the instruction 
2131        // in the delay slot write to register %o7(15), usually just moving
2132        // the caller's return address, or doing a restore
2133        // Tail calls are instrumented as return points, not call points.
2134
2135
2136        instruction nexti; 
2137        nexti.raw = owner->get_instruction(adr+4);
2138
2139        if (nexti.rest.op == 2 
2140            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
2141               || nexti.rest.op3 == RESTOREop3)) {
2142          //fprintf(stderr, "#### Tail-call optimization in function %s, addr %x\n",
2143          //     prettyName().string_of(), adr);
2144          funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
2145                                       functionExit);
2146
2147        } else {
2148          // define a call point
2149          // this may update address - sparc - aggregate return value
2150          // want to skip instructions
2151          bool err;
2152          int dummyId;
2153          adr = newCallPoint(adr, instr, owner, err, dummyId, adr);
2154        }
2155      }
2156
2157      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
2158        /* A register indirect jump. Some jumps may exit the function 
2159           (e.g. read/write on SunOS). In general, the only way to 
2160           know if a jump is exiting the function is to instrument
2161           the jump to test if the target is outside the current 
2162           function. Instead of doing this, we just check the 
2163           previous two instructions, to see if they are loading
2164           an address that is out of the current function.
2165           This should catch the most common cases (e.g. read/write).
2166           For other cases, we would miss a return point.
2167
2168           This is the case considered:
2169
2170              sethi addr_hi, r
2171              or addr_lo, r, r
2172              jump r
2173         */
2174
2175        reg jumpreg = instr.rest.rs1;
2176        instruction prev1;
2177        instruction prev2;
2178
2179        prev1.raw = owner->get_instruction(adr-4);
2180        prev2.raw = owner->get_instruction(adr-8);
2181
2182        unsigned targetAddr;
2183
2184        if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
2185            && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
2186            && prev2.sethi.rd == (unsigned)jumpreg
2187            && prev1.rest.op == RESTop 
2188            && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
2189            && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg) {
2190
2191          targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
2192          targetAddr |= prev1.resti.simm13;
2193          if (targetAddr < addr() || targetAddr >= addr() + size()) {
2194            //fprintf(stderr, "Jump out of function %s at addr = %x, target = %x\n", 
2195            //    prettyName().string_of(), adr, targetAddr);
2196            instPoint *point = new instPoint(this, instr, owner, adr, false, leaf, 
2197                                             functionExit);
2198            funcReturns += point;
2199          }
2200        }
2201
2202      }
2203  }
2204
2205  return (checkInstPoints(owner)); 
2206 }
2207
2208 /*
2209  * Check all the instPoints within this function to see if there's 
2210  * any conficts happen.
2211  */
2212 bool pdFunction::checkInstPoints(const image *owner) {
2213
2214     // Our own library function, skip the test.
2215     if (prettyName_.prefixed_by("DYNINST")) 
2216         return true;
2217
2218     // The function is too small to be worthing instrumenting.
2219     if (size() <= 12)
2220         return false;
2221
2222     // No function return! return false;
2223     if (sizeof(funcReturns) == 0)
2224         return false;
2225
2226     instruction instr;
2227     Address adr = addr();
2228
2229     // Check if there's any branch instruction jump to the middle
2230     // of the instruction sequence in the function entry point
2231     // and function exit point.
2232     for ( ; adr < addr() + size(); adr += sizeof(instruction)) {
2233
2234         instr.raw = owner->get_instruction(adr);
2235
2236         if (isInsnType(instr, BRNCHmask, BRNCHmatch)||
2237             isInsnType(instr, FBRNCHmask, FBRNCHmatch)) {
2238
2239             int disp = instr.branch.disp22;
2240             Address target = adr + (disp << 2);
2241
2242             if ((target > funcEntry_->addr)&&
2243                 (target < (funcEntry_->addr + funcEntry_->size))) {
2244                 if (adr > (funcEntry_->addr+funcEntry_->size))
2245                     //cout << "Function " << prettyName_ <<" entry" << endl;
2246                     return false;
2247             }
2248
2249             for (u_int i = 0; i < funcReturns.size(); i++) {
2250                 if ((target > funcReturns[i]->addr)&&
2251                     (target < (funcReturns[i]->addr + funcReturns[i]->size))) {
2252                     if ((adr < funcReturns[i]->addr)||
2253                         (adr > (funcReturns[i]->addr + funcReturns[i]->size)))
2254                         // cout << "Function (at " << adr << ") " << prettyName_ <<" exit " << i << "  ( adr: " << funcReturns[i]->addr << "   size:" << funcReturns[i]->size<< ")" <<endl;
2255                         return false;
2256                 }
2257             }
2258         }
2259     }
2260
2261     // check that no instrumentation points could overlap
2262     Address func_entry = funcEntry_->addr + funcEntry_->size; 
2263     for (u_int i = 0; i < funcReturns.size(); i++) {
2264         if(func_entry >= funcReturns[i]->addr){
2265            return false;
2266         }
2267         if(i > 1){ // check if return points overlap
2268             Address prev_exit = funcReturns[i-1]->addr+funcReturns[i-1]->size;  
2269             if(funcReturns[i]->addr >= prev_exit) {
2270                 return false;
2271             } 
2272         }
2273     }
2274
2275     return true;        
2276 }
2277
2278
2279 /* The maximum length of relocatable function is 1k instructions */  
2280 static instruction newInstr[1024];
2281
2282 // This function is to find the inst Points for a function
2283 // that will be relocated if it is instrumented. 
2284 bool pdFunction::findInstPoints(const image *owner, Address newAdr, process*){
2285
2286    int i;
2287    if (size() == 0) {
2288      return false;
2289    }
2290
2291    Address adr = addr();
2292    instruction instr;
2293    instr.raw = owner->get_instruction(adr);
2294    if (!IS_VALID_INSN(instr))
2295      return false;
2296    
2297    if (size() <= 3*sizeof(instruction)) 
2298        return false;
2299
2300    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
2301                                     functionEntry, adr);
2302
2303    funcEntry_ = point;
2304
2305    // if the second instruction in a relocated function is a call instruction
2306    // or a branch instruction, then we can't deal with this 
2307    if(size() > sizeof(instruction)){
2308        Address second_adr = adr + sizeof(instruction);
2309        instruction second_instr;
2310        second_instr.raw =  owner->get_instruction(second_adr); 
2311        if ((isCallInsn(second_instr)) || 
2312                       (second_instr.branch.op == 0 && 
2313                       (second_instr.branch.op2 == 2 || 
2314                       second_instr.branch.op2 == 6))) {
2315            return false;
2316        }
2317    }
2318    
2319    assert(funcEntry_);
2320    int retId = 0;
2321    int callsId = 0; 
2322
2323    for (i = 0; adr < addr() + size(); adr += sizeof(instruction),  
2324         newAdr += sizeof(instruction), i++) {
2325
2326      instr.raw = owner->get_instruction(adr);
2327      newInstr[i] = instr;
2328      bool done;
2329
2330      // check for return insn and as a side affect decide if we are at the
2331      //   end of the function.
2332      if (isReturnInsn(owner, adr, done)) {
2333        // define the return point
2334        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
2335                                         functionExit, adr);
2336        funcReturns += point;
2337        funcReturns[retId] -> instId = retId++;
2338      } else if (instr.branch.op == 0 
2339                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
2340        // find if this branch is going out of the function
2341        int disp = instr.branch.disp22;
2342        Address target = adr + (disp << 2);
2343        if (target < addr() || target >= addr() + size()) {
2344            instPoint *point = new instPoint(this, newInstr[i], owner, 
2345                                             newAdr, false, 
2346                                             functionExit, adr);
2347            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
2348                point->isBranchOut = true;
2349                point->branchTarget = target;
2350            }
2351            funcReturns += point;
2352            funcReturns[retId] -> instId = retId++;
2353        }
2354
2355      } else if (isCallInsn(instr)) {
2356
2357        // first, check for tail-call optimization: a call where the instruction 
2358        // in the delay slot write to register %o7(15), usually just moving
2359        // the caller's return address, or doing a restore
2360        // Tail calls are instrumented as return points, not call points.
2361        instruction nexti; 
2362        nexti.raw = owner->get_instruction(adr+4);
2363
2364        if (nexti.rest.op == 2 
2365            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
2366               || nexti.rest.op3 == RESTOREop3)) {
2367
2368            instPoint *point = new instPoint(this, instr, owner, newAdr, false,
2369                                       functionExit, adr);
2370            funcReturns += point;
2371            funcReturns[retId] -> instId = retId++;
2372
2373        } else {
2374          // if this is a call instr to a location within the function, and if 
2375          // the offest is not 8 then do not define this function 
2376          if(instr.call.op == CALLop){ 
2377            Address call_target = adr + (instr.call.disp30 << 2);
2378            if((call_target >= addr()) && (call_target <= (addr() + size()))){ 
2379               if((instr.call.disp30 << 2) != 2*sizeof(instruction)) {
2380                 return false;
2381               }
2382            }
2383          }
2384          // define a call point
2385          // this may update address - sparc - aggregate return value
2386          // want to skip instructions
2387          bool err;
2388          adr = newCallPoint(newAdr, instr, owner, err, callsId, adr);
2389          if (err)
2390            return false;
2391        }
2392      }
2393
2394      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
2395        /* A register indirect jump. Some jumps may exit the function 
2396           (e.g. read/write on SunOS). In general, the only way to 
2397           know if a jump is exiting the function is to instrument
2398           the jump to test if the target is outside the current 
2399           function. Instead of doing this, we just check the 
2400           previous two instructions, to see if they are loading
2401           an address that is out of the current function.
2402           This should catch the most common cases (e.g. read/write).
2403           For other cases, we would miss a return point.
2404
2405           This is the case considered:
2406
2407              sethi addr_hi, r
2408              or addr_lo, r, r
2409              jump r
2410         */
2411
2412          reg jumpreg = instr.rest.rs1;
2413          instruction prev1;
2414          instruction prev2;
2415          
2416          prev1.raw = owner->get_instruction(adr-4);
2417          prev2.raw = owner->get_instruction(adr-8);
2418
2419          unsigned targetAddr;
2420
2421          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
2422              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
2423              && prev2.sethi.rd == (unsigned)jumpreg
2424              && prev1.rest.op == RESTop 
2425              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
2426              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
2427              
2428              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
2429              targetAddr |= prev1.resti.simm13;
2430              if (targetAddr < addr() || targetAddr >= addr() + size()) {
2431                  instPoint *point = new instPoint(this, instr, owner, 
2432                                                   newAdr, false,
2433                                                   functionExit, adr);
2434                  funcReturns += point;
2435                  funcReturns[retId] -> instId = retId++;
2436              }
2437          }
2438      }
2439  }
2440  return true;
2441 }
2442
2443 // This function assigns new address to instrumentation points of  
2444 // a function that has been relocated
2445 bool pdFunction::findNewInstPoints(const image *owner, 
2446                                 Address newAdr,
2447                                 process *proc,
2448                                 vector<instruction> &callInstrs) {
2449
2450    int i;
2451    if (size() == 0) {
2452      return false;
2453    }
2454
2455    Address adr = addr();
2456    instruction instr;
2457    instr.raw = owner->get_instruction(adr);
2458    if (!IS_VALID_INSN(instr))
2459      return false;
2460
2461    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
2462                                     functionEntry, adr);
2463
2464    *funcEntry_ = *point;
2465    assert(funcEntry_);
2466    int retId = 0;
2467    int callsId = 0; 
2468
2469    // get baseAddress if this is a shared object
2470    Address baseAddress = 0;
2471    if(!(proc->getBaseAddress(owner,baseAddress))){
2472         baseAddress =0;
2473    }
2474
2475    // if we have call instructions that need to be added after the instrs
2476    // to call the relocated instruction, the first address we can use is
2477    // the address of the 4th instruction in the function
2478    Address call_start_addr = addr() + baseAddress + 3*sizeof(instruction);
2479
2480    for (i = 0; adr < addr() + size(); adr += 4,  newAdr += 4, i++) {
2481     
2482
2483
2484      instr.raw = owner->get_instruction(adr);
2485      newInstr[i] = instr;
2486
2487      // printf("next address = %x next instr = %x\n",adr,instr.raw);
2488
2489      bool done;
2490
2491      // check for return insn and as a side affect decide if we are at the
2492      //   end of the function.
2493      if (isReturnInsn(owner, adr, done)) {
2494        // define the return point
2495        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
2496                                         functionExit, adr);
2497        *funcReturns[retId++] = *point;
2498      } else if (instr.branch.op == 0 
2499                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
2500        // find if this branch is going out of the function
2501        int disp = instr.branch.disp22;
2502        Address target = adr + baseAddress + (disp << 2);
2503        if ((target < (addr() + baseAddress)) 
2504            || (target >= (addr() + baseAddress + size()))) {
2505            relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
2506            instPoint *point = new instPoint(this, newInstr[i], owner, 
2507                                             newAdr, false, 
2508                                             functionExit, adr);
2509            disp = newInstr[i].branch.disp22;
2510            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
2511                point->isBranchOut = true;
2512                point->branchTarget = adr + (disp<<2);
2513            }
2514            *funcReturns[retId++] = *point;
2515        }
2516
2517      } else if (isCallInsn(instr)) {
2518
2519        // first, check for tail-call optimization: a call where the instruction 
2520        // in the delay slot write to register %o7(15), usually just moving
2521        // the caller's return address, or doing a restore
2522        // Tail calls are instrumented as return points, not call points.
2523        instruction nexti; 
2524        nexti.raw = owner->get_instruction(adr+4);
2525
2526        if (nexti.rest.op == 2 
2527            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
2528               || nexti.rest.op3 == RESTOREop3)) {
2529
2530             // Undoing the tail-call optimazation when the function
2531             // is relocated. Here is an example:
2532             //   before:          --->             after
2533             // ---------------------------------------------------
2534             //   call  %g1                        restore    
2535             //   restore                          st  %i0, [ %fp + 0x44 ]
2536             //                                    mov %o7 %i0
2537             //                                    call %g1 
2538             //                                    nop
2539             //                                    mov %i0,%o7
2540             //                                    st  [ %fp + 0x44 ], %i0
2541             //                              retl
2542             //                                    nop
2543             // Q: Here the assumption that register i1 is available 
2544             //    might be an question, is it?
2545             // A: I think it is appropriate because:
2546             //      (in situation A calls B and B calls C)
2547             //      The procedure C called via tail call is a leaf 
2548             //      procedure, the value arguments and return value between
2549             //      A and C are passed by register (o1...o5, o7)
2550             //      So even If B mess up the value of i0, it won't affect the
2551             //      commnucation between A and C. Also, we saved the value of
2552             //      i0 on stack and when we return from B, the value of i0
2553             //      won't be affected.
2554             //      If C is not a leaf procedure, it should be fine
2555             //      as it is.
2556             //    ( If you could give an counter-example, please
2557             //      let me know.                         --ling )
2558
2559             genSimpleInsn(&newInstr[i++], RESTOREop3, 0, 0, 0);
2560             generateStore(&newInstr[i++], 24, REG_FP, 0x44); 
2561             genImmInsn(&newInstr[i++], ORop3, 15, 0, 24); 
2562             newInstr[i++].raw = owner->get_instruction(adr);
2563             generateNOOP(&newInstr[i++]);
2564             genImmInsn(&newInstr[i++], ORop3, 24, 0, 15);
2565             generateLoad(&newInstr[i++], REG_FP, 0x44, 24);         
2566             generateJmplInsn(&newInstr[i++], 15, 8 ,0);
2567             newAdr += 28;
2568             generateNOOP(&newInstr[i]);
2569             instPoint *point = new instPoint(this, instr, owner, newAdr, false,
2570                                       functionExit, adr);
2571             point-> originalInstruction = newInstr[i-1];
2572             point-> delaySlotInsn = newInstr[i];
2573             point-> isDelayed = true;
2574             *funcReturns[retId++] = *point;
2575        } else {
2576          // define a call point
2577          // this may update address - sparc - aggregate return value
2578          // want to skip instructions
2579
2580          // if this is a call to an address within the same function, then
2581          // we need to set the 07 register to have the same value as it
2582          // would before the function was relocated
2583          // to do this we generate a call instruction back to the original
2584          // function location, and then at this location we generate a call 
2585          // instruction back to the relocated instruction.  In the delay 
2586          // slot of the second instruction the value of 07 is changed by 
2587          // the difference between the origninal call instruction, and 
2588          // the location of the call instruction back to the relocated
2589          // function.  This way the 07 register will contain the address
2590          // of the original call instruction
2591          Address call_target = adr + (instr.call.disp30 << 2);
2592          if((call_target >= addr()) 
2593                 && (call_target <= (addr() + size()))){ 
2594             assert((newInstr[i].call.disp30 << 2) == 8);
2595
2596             // generating call instruction to orginal function address
2597             // after the SAVE call RESTORE instr.s that call the relocated
2598             // function 
2599             newInstr[i].call.disp30 = ((call_start_addr -newAdr) >> 2); 
2600
2601             // generate call to relocated function from original function 
2602             // (this will get almost correct value for register 07)
2603             instruction new_inst;
2604             generateCallInsn(&new_inst,call_start_addr,
2605                              newAdr+sizeof(instruction));
2606             callInstrs += new_inst;
2607            
2608             // printf("adr = %x baseAddress = %x call_sart = %x offset = %x addr() = %x\n",adr,baseAddress,call_start_addr,adr+baseAddress-call_start_addr,addr()); 
2609             // generate add isntruction to get correct value for 07 register 
2610             // this will go in delay slot of previous call instr.
2611             genImmInsn(&new_inst,ADDop3,REG_O7,
2612                        (adr+baseAddress-call_start_addr),REG_O7);
2613             callInstrs += new_inst;
2614             call_start_addr += 2*sizeof(instruction);
2615          }
2616          else {
2617             // otherwise, this is a call instruction to a location
2618             // outside the function
2619             bool err;
2620             relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
2621             Address temp = newCallPoint(newAdr, newInstr[i], owner, err, 
2622                                         callsId, adr);
2623             if (err) return false;
2624          }
2625        }
2626      }
2627
2628      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
2629        /* A register indirect jump. Some jumps may exit the function 
2630           (e.g. read/write on SunOS). In general, the only way to 
2631           know if a jump is exiting the function is to instrument
2632           the jump to test if the target is outside the current 
2633           function. Instead of doing this, we just check the 
2634           previous two instructions, to see if they are loading
2635           an address that is out of the current function.
2636           This should catch the most common cases (e.g. read/write).
2637           For other cases, we would miss a return point.
2638
2639           This is the case considered:
2640
2641              sethi addr_hi, r
2642              or addr_lo, r, r
2643              jump r
2644         */
2645
2646          reg jumpreg = instr.rest.rs1;
2647          instruction prev1;
2648          instruction prev2;
2649          
2650          prev1.raw = owner->get_instruction(adr-4);
2651          prev2.raw = owner->get_instruction(adr-8);
2652
2653          unsigned targetAddr;
2654
2655          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
2656              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
2657              && prev2.sethi.rd == (unsigned)jumpreg
2658              && prev1.rest.op == RESTop 
2659              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
2660              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
2661              
2662              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
2663              targetAddr |= prev1.resti.simm13;
2664              if (targetAddr < addr() || targetAddr >= addr() + size()) {
2665                  instPoint *point = new instPoint(this, instr, owner, 
2666                                                   newAdr, false,
2667                                                   functionExit, adr);
2668                  *funcReturns[retId++] = *point;
2669              }
2670          }
2671      }
2672  }
2673    
2674    return true;
2675 }
2676
2677 //
2678 // called to relocate a function: when a request is made to instrument
2679 // a system call we relocate the entire function into the heap
2680 //
2681 bool pdFunction::relocateFunction(process *proc, instPoint *location,
2682                                  vector<instruction> &extra_instrs) {
2683
2684     unsigned ret;
2685     process *globalProc;
2686
2687     if (nodePseudoProcess && (proc->symbols == nodePseudoProcess->symbols)){
2688         globalProc = nodePseudoProcess;
2689     } else {
2690         globalProc = proc;
2691     }   
2692
2693     //Allocate the heap for the function to be relocated
2694     ret = inferiorMalloc(globalProc, size()+28, textHeap);
2695     newAddr = ret;
2696
2697     findNewInstPoints(location->image_ptr, ret, proc, extra_instrs);
2698     proc->writeDataSpace((caddr_t)ret, size()+28,(caddr_t) newInstr);
2699     return true;
2700 }
2701
2702
2703 // The exact semantics of the heap are processor specific.
2704 //
2705 // find all DYNINST symbols that are data symbols
2706 //
2707 bool image::heapIsOk(const vector<sym_data> &find_us) {
2708   Address curr, instHeapEnd;
2709   Symbol sym;
2710   string str;
2711
2712   for (unsigned i=0; i<find_us.size(); i++) {
2713     str = find_us[i].name;
2714     if (!linkedFile.get_symbol(str, sym)) {
2715       string str1 = string("_") + str.string_of();
2716       if (!linkedFile.get_symbol(str1, sym) && find_us[i].must_find) {
2717         string msg;
2718         msg = string("Cannot find ") + str + string(". Exiting");
2719         statusLine(msg.string_of());
2720         showErrorCallback(50, msg);
2721         return false;
2722       }
2723     }
2724     addInternalSymbol(str, sym.addr());
2725   }
2726
2727   string ghb = GLOBAL_HEAP_BASE;
2728   if (!linkedFile.get_symbol(ghb, sym)) {
2729     ghb = U_GLOBAL_HEAP_BASE;
2730     if (!linkedFile.get_symbol(ghb, sym)) {
2731       string msg;
2732       msg = string("Cannot find ") + str + string(". Exiting");
2733       statusLine(msg.string_of());
2734       showErrorCallback(50, msg);
2735       return false;
2736     }
2737   }
2738   instHeapEnd = sym.addr();
2739   addInternalSymbol(ghb, instHeapEnd);
2740   ghb = INFERIOR_HEAP_BASE;
2741
2742   if (!linkedFile.get_symbol(ghb, sym)) {
2743     ghb = UINFERIOR_HEAP_BASE;
2744     if (!linkedFile.get_symbol(ghb, sym)) {
2745       string msg;
2746       msg = string("Cannot find ") + str + string(". Cannot use this application");
2747       statusLine(msg.string_of());
2748       showErrorCallback(50, msg);
2749       return false;
2750     }
2751   }
2752   curr = sym.addr();
2753   addInternalSymbol(ghb, curr);
2754   if (curr > instHeapEnd) instHeapEnd = curr;
2755
2756   // check that we can get to our heap.
2757   //if (instHeapEnd > getMaxBranch()) {
2758   //  logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
2759   //  sprintf(errorLine, "    heap ends at %x\n", instHeapEnd);
2760   //  logLine(errorLine);
2761   //  return false;
2762   //} else if (instHeapEnd + SYN_INST_BUF_SIZE > getMaxBranch()) {
2763   //  logLine("WARNING: Program text + data could be too big for dyninst\n");
2764   //  showErrorCallback(54, "");
2765   //  return false;
2766   //}
2767   return true;
2768 }
2769
2770 // Certain registers (i0-i7 on a SPARC) may be available to be read
2771 // as an operand, but cannot be written.
2772 bool registerSpace::readOnlyRegister(reg reg_number) {
2773   if ((reg_number < 16) || (reg_number > 23))
2774       return true;
2775   else
2776       return false;
2777 }
2778
2779 bool returnInstance::checkReturnInstance(const Address adr) {
2780     if ((adr > addr_) && ( adr <= addr_+size_))
2781         return false;
2782     else 
2783         return true;
2784 }
2785  
2786 void returnInstance::installReturnInstance(process *proc) {
2787     proc->writeTextSpace((caddr_t)addr_, instSeqSize, 
2788                          (caddr_t) instructionSeq); 
2789 }
2790
2791 void returnInstance::addToReturnWaitingList(Address pc, process *proc) {
2792     instruction insn;
2793     instruction insnTrap;
2794     generateBreakPoint(insnTrap);
2795     proc->readDataSpace((caddr_t)pc, sizeof(insn), (char *)&insn, true);
2796     proc->writeTextSpace((caddr_t)pc, sizeof(insnTrap), (caddr_t)&insnTrap);
2797
2798     instWaitingList *instW = new instWaitingList; 
2799     
2800     instW->instructionSeq = instructionSeq;
2801     instW->instSeqSize = instSeqSize;
2802     instW->addr_ = addr_;
2803
2804     instW->relocatedInstruction = insn;
2805     instW->relocatedInsnAddr = pc;
2806
2807     instWList.add(instW, (void *)pc);
2808 }
2809
2810 void generateBreakPoint(instruction &insn) {
2811     insn.raw = BREAK_POINT_INSN;
2812 }
2813
2814 bool doNotOverflow(int value)
2815 {
2816   if ( (value <= 16383) && (value >= -16384) ) return(true);
2817   else return(false);
2818 }
2819
2820 void instWaitingList::cleanUp(process *proc, Address pc) {
2821     proc->writeTextSpace((caddr_t)pc, sizeof(relocatedInstruction),
2822                     (caddr_t)&relocatedInstruction);
2823     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t)instructionSeq);
2824 }