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