This commit enables arbitrary instrumentation points at the last instruction
[dyninst.git] / dyninstAPI / src / inst-sparc.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 // $Id: inst-sparc.C,v 1.139 2003/03/13 17:00:15 jodom Exp $
43
44 #include "dyninstAPI/src/inst-sparc.h"
45 #include "dyninstAPI/src/instPoint.h"
46
47 #include "dyninstAPI/src/FunctionExpansionRecord.h"
48
49 #include "dyninstAPI/src/rpcMgr.h"
50
51 /****************************************************************************/
52 /****************************************************************************/
53 /****************************************************************************/
54
55 static dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
56
57 trampTemplate baseTemplate;
58 NonRecursiveTrampTemplate nonRecursiveBaseTemplate;
59
60 //declaration of conservative base trampoline template
61
62 trampTemplate conservativeBaseTemplate;
63 NonRecursiveTrampTemplate nonRecursiveConservativeBaseTemplate;
64
65
66
67 registerSpace *regSpace;
68
69 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
70 // registers 8 to 15: out registers 
71 // registers 16 to 22: local registers
72 Register deadList[] = {16, 17, 18, 19, 20, 21, 22 };
73 #else
74 Register deadList[] = {16, 17, 18, 19, 20, 21, 22, 23 };
75 #endif
76
77 int deadListSize = sizeof(deadList);
78
79 /****************************************************************************/
80 /****************************************************************************/
81 /****************************************************************************/
82
83 // Constructor for the instPoint class. 
84 instPoint::instPoint(pd_Function *f, const image *owner, Address &adr, 
85                      const bool delayOK, instPointType pointType, bool noCall)
86 : insnAddr(adr), addr(adr), 
87   firstPriorIsDCTI(false), 
88   secondPriorIsDCTI(false),
89   thirdPriorIsDCTI(false), 
90   firstIsDCTI(false), 
91   secondIsDCTI(false), 
92   thirdIsDCTI(false),
93   firstPriorIsAggregate(false),
94   thirdIsAggregate(false), 
95   fourthIsAggregate(false), 
96   fifthIsAggregate(false),
97   usesPriorInstructions(false),
98   numPriorInstructions(0),
99   callIndirect(false), callee(NULL), func(f), isBranchOut(false),
100   ipType(pointType), image_ptr(owner),
101   relocated_(false), needsLongJump(false), dontUseCall(noCall)
102 {
103
104   // If the base tramp is too far away from the function for a branch, 
105   // we will need to relocate at least two instructions to the base tramp
106   firstInstruction.raw   = owner->get_instruction(adr);
107
108   // For function call sites 
109   if (ipType == callSite) {
110
111       // Grab the second instruction
112       secondInstruction.raw  = owner->get_instruction(adr + 4);
113
114       firstIsDCTI = true;
115
116       // Only need to relocate two instructions as the destination
117       // of the original call is changed to the base tramp, and a call
118       // to the real target is generated in the base tramp
119       size = 2 * sizeof(instruction);
120
121
122       // we may need to move the instruction after the instruction in the
123       // call's delay slot, to deal with the case where the return value
124       // of the called function is a structure.
125       thirdInstruction.raw = owner->get_instruction(adr + 8);
126
127       if ( !IS_VALID_INSN(thirdInstruction) &&
128             thirdInstruction.raw != 0 ) {
129
130           thirdIsAggregate = true;
131           size = 3 * sizeof(instruction);
132       }
133
134
135   // For arbitrary instPoints
136   } else if (ipType == otherPoint) {
137
138       // Grab the second instruction
139       secondInstruction.raw  = owner->get_instruction(adr + 4);
140
141       size = 2 * sizeof(instruction);
142
143       if ( isDCTI(firstInstruction) ) {
144           firstIsDCTI = true;
145       }
146
147
148       // Instruction sequence looks like this:
149       //
150       // adr:      insn
151       // adr + 4:  insn
152
153       // If the second instruction is a delayed, control transfer
154       // instruction, we need to also move the instruction in its
155       // delay slot (if it is relocated to the base tramp).
156       if ( isDCTI(secondInstruction) ) {
157
158           secondIsDCTI = true;
159
160           // Will need to relocate a third instruction to the base trampoline
161           // if the base trampoline is outside of the range of a branch
162           thirdInstruction.raw   = owner->get_instruction(adr + 8);
163
164           size = 3 * sizeof(instruction);
165
166           // If the second instruction is a CALL instruction, we may 
167           // need to move the instruction after the instruction in the 
168           // delay slot, to deal with the case where the return value 
169           // of the called function is a structure.
170           if ( isCallInsn(secondInstruction) ) {
171
172               fourthInstruction.raw = owner->get_instruction(adr + 12);
173
174               if ( !IS_VALID_INSN(fourthInstruction) && 
175                     fourthInstruction.raw != 0 ) {
176
177                   fourthIsAggregate = true;
178                   size = 4 * sizeof(instruction);
179               }
180           }
181       }
182
183   // For function entry instPoints
184   } else if (ipType == functionEntry) {
185
186       // Grab the second instruction
187       secondInstruction.raw  = owner->get_instruction(adr + 4);
188
189       // Will need to relocate a third instruction to the base trampoline
190       // if the base trampoline is outside of the range of a branch
191       thirdInstruction.raw   = owner->get_instruction(adr + 8);
192
193       size = 3 * sizeof(instruction);
194
195       // Instruction sequence looks like this:
196       //
197       // adr:      insn
198       // adr + 4:  insn
199       // adr + 8:  insn
200
201
202       // If the first instruction is a delayed, control transfer
203       // instruction, we need to also move the instruction in its
204       // delay slot (if it is relocated to the base tramp).
205       if ( isDCTI(firstInstruction) ) {
206
207           firstIsDCTI = true;
208
209           // If the first instruction is a CALL instruction, we may 
210           // need to move the instruction after the instruction in its 
211           // delay slot, to deal with the case where the return value 
212           // of the called function is a structure.
213           if ( isCallInsn(firstInstruction) ) {
214
215               if ( !IS_VALID_INSN(thirdInstruction) && 
216                     thirdInstruction.raw != 0 ) {
217
218                   thirdIsAggregate = true;
219               }
220           }
221       }
222
223
224       // If the second instruction is a delayed, control transfer
225       // instruction, we need to also move the instruction in its
226       // delay slot (if it is relocated to the base tramp).
227       if ( isDCTI(secondInstruction) ) {
228
229           secondIsDCTI = true;
230
231           // If the second instruction is a CALL instruction, we may 
232           // need to move the instruction after the instruction in the 
233           // delay slot, to deal with the case where the return value 
234           // of the called function is a structure.
235           if ( isCallInsn(secondInstruction) ) {
236
237               fourthInstruction.raw = owner->get_instruction(adr + 12);
238
239               if ( !IS_VALID_INSN(fourthInstruction) && 
240                     fourthInstruction.raw != 0 ) {
241
242                   fourthIsAggregate = true;
243                   size = 4 * sizeof(instruction);
244               }
245           }
246       }
247
248
249       // If the third instruction is a delayed, control transfer
250       // instruction, we need to also move the instruction in its
251       // delay slot (if it is relocated to the base tramp).
252       if ( isDCTI(thirdInstruction) ) {
253
254           thirdIsDCTI = true;
255
256           fourthInstruction.raw = owner->get_instruction(adr + 12);
257
258           // If the third instruction is a CALL instruction, we may 
259           // need to move the instruction after the instruction in the 
260           // delay slot, to deal with the case where the return value 
261           // of the called function is a structure.
262           if ( isCallInsn(thirdInstruction) ) {
263
264               fifthInstruction.raw = owner->get_instruction(adr + 16);
265
266               if ( !IS_VALID_INSN(fifthInstruction) && 
267                     fifthInstruction.raw != 0 ) {
268
269                   fifthIsAggregate = true;
270                   size = 5 * sizeof(instruction);
271               }
272           }
273       }
274
275
276   // For function exit points
277   } else {
278
279       assert(ipType == functionExit);
280
281       firstIsDCTI = true;
282
283       // if the function has no stack frame
284       if (this->hasNoStackFrame()) {
285
286           // If the base trampoline is too far away to use a branch 
287           // instruction, we will need to claim the instructions before
288           // the exit instructions, to be able to transfer to the base
289           // trampoline.
290           usesPriorInstructions = true;
291
292           // Grab the instruction just before the exit instructions  
293           firstPriorInstruction.raw = owner->get_instruction(adr - 4);
294           numPriorInstructions      = 1;
295           size                      = 3 * sizeof(instruction);
296
297
298           // If the first Prior instruction is a DCTI, then this point is part
299           // of a tail call optimization and we need to have firstInstruction
300           // pointing to the DCTI, not the delay slot instruction.
301           if ( isDCTI(firstPriorInstruction) ) {
302
303               firstInstruction.raw  = owner->get_instruction(adr - 4);
304               secondInstruction.raw = owner->get_instruction(adr);
305               numPriorInstructions  = 0;
306               size                  = 2 * sizeof(instruction);
307
308
309           } else {
310
311               // Grab the second instruction
312               secondInstruction.raw  = owner->get_instruction(adr + 4);
313
314
315               // If the 'firstPriorInstruction' is in the delay slot of the 
316               // instruction just before it, we have to copy both of those
317               // instructions to the base tramp
318               if (owner->isValidAddress(adr - 8)) {
319
320                   // Grab the instruction before the 'firstPriorInstruction' 
321                   secondPriorInstruction.raw = owner->get_instruction(adr - 8);
322
323                   if ( isDCTI(secondPriorInstruction) && !delayOK ) {
324
325                       secondPriorIsDCTI    = true;
326                       numPriorInstructions = 2;
327                       size                 = 4 * sizeof(instruction);
328
329                   }
330               }
331
332
333               // If the 'firstPriorInstruction' is the aggregate instruction
334               // for a call, we need to copy the three prior instructions to
335               // the base trampoline. 
336               if (owner->isValidAddress(adr - 12)) {
337
338                   // Grab the instruction just before secondPriorInstruction 
339                   thirdPriorInstruction.raw = owner->get_instruction(adr - 12);
340
341                   if ( isDCTI(thirdPriorInstruction) && !delayOK ) {
342
343                       // If the 'firstPriorInstruction' is an aggregate
344                       // instruction for the 'thirdPriorInstruction', copy
345                       // all three prior instructions to the base tramp
346                       if ( !IS_VALID_INSN(firstPriorInstruction) && 
347                             firstPriorInstruction.raw != 0 ) {
348
349                           thirdPriorIsDCTI      = true;
350                           firstPriorIsAggregate = true;
351                           numPriorInstructions  = 3;
352                           size                  = 5 * sizeof(instruction);
353                       }
354                   }
355               }
356           }
357
358       // Function has a stack frame.
359       } else {
360
361           // Grab the second instruction
362           secondInstruction.raw  = owner->get_instruction(adr + 4);
363
364           // No need to save registers before branching to exit 
365           // instrumentation
366           size = 2 * sizeof(instruction);
367       }
368   }
369
370
371   // return the address in the code segment after this instruction
372   // sequence. (there's a -1 here because one will be added up later in
373   // the function findInstPoints)  
374   adr = addr + (size - sizeof(instruction));
375 }
376
377
378 /****************************************************************************/
379 /****************************************************************************/
380 /****************************************************************************/
381
382 // constructor for instPoint class for functions that have been relocated
383 instPoint::instPoint(pd_Function *f, const instruction instr[], 
384                      int arrayOffset, const image *owner, Address &adr, 
385                      bool delayOK, instPointType pointType)
386 : insnAddr(adr), addr(adr), 
387   firstPriorIsDCTI(false), 
388   secondPriorIsDCTI(false),
389   thirdPriorIsDCTI(false), 
390   firstIsDCTI(false), 
391   secondIsDCTI(false), 
392   thirdIsDCTI(false),
393   firstPriorIsAggregate(false),
394   thirdIsAggregate(false), 
395   fourthIsAggregate(false), 
396   fifthIsAggregate(false),
397   usesPriorInstructions(false),
398   numPriorInstructions(0),
399   callIndirect(false), callee(NULL), func(f), isBranchOut(false),
400   ipType(pointType), image_ptr(owner),
401   relocated_(true), needsLongJump(false), dontUseCall(false)
402 {
403
404   // If the base tramp is too far away from the function for a branch, 
405   // we will need to relocate at least two instructions to the base tramp
406   firstInstruction.raw   = instr[arrayOffset].raw;
407   secondInstruction.raw  = instr[arrayOffset + 1].raw;
408
409
410   // For function call sites 
411   if (ipType == callSite) {
412
413     //assert( isCallInsn(firstInstruction) );
414
415       firstIsDCTI = true;
416
417       // Only need to relocate two instructions as the destination
418       // of the original call is changed to the base tramp, and a call
419       // to the real target is generated in the base tramp
420       size = 2 * sizeof(instruction);
421
422
423       // we may need to move the instruction after the instruction in the
424       // call's delay slot, to deal with the case where the return value
425       // of the called function is a structure.
426       thirdInstruction.raw = instr[arrayOffset + 2].raw;
427
428       if ( !IS_VALID_INSN(thirdInstruction) &&
429             thirdInstruction.raw != 0 ) {
430
431           thirdIsAggregate = true;
432           size = 3 * sizeof(instruction);
433       }
434
435   // For arbitrary instPoints
436   } else if (ipType == otherPoint) {
437
438       // Grab the second instruction
439       secondInstruction.raw  = instr[arrayOffset + 1].raw;
440
441       size = 2 * sizeof(instruction);
442
443       if ( isDCTI(firstInstruction) ) {
444           firstIsDCTI = true;
445       }
446
447
448       // Instruction sequence looks like this:
449       //
450       // adr:      insn
451       // adr + 4:  insn
452
453       // If the second instruction is a delayed, control transfer
454       // instruction, we need to also move the instruction in its
455       // delay slot (if it is relocated to the base tramp).
456       if ( isDCTI(secondInstruction) ) {
457
458           secondIsDCTI = true;
459
460           // Will need to relocate a third instruction to the base trampoline
461           // if the base trampoline is outside of the range of a branch
462           thirdInstruction.raw = instr[arrayOffset + 2].raw;
463
464           size = 3 * sizeof(instruction);
465
466           // If the second instruction is a CALL instruction, we may 
467           // need to move the instruction after the instruction in the 
468           // delay slot, to deal with the case where the return value 
469           // of the called function is a structure.
470           if ( isCallInsn(secondInstruction) ) {
471
472               fourthInstruction.raw = instr[arrayOffset + 3].raw;
473
474               if ( !IS_VALID_INSN(fourthInstruction) && 
475                     fourthInstruction.raw != 0 ) {
476
477                   fourthIsAggregate = true;
478                   size = 4 * sizeof(instruction);
479               }
480           }
481       }
482
483   // For function entry instPoints
484   } else if (ipType == functionEntry) {
485
486       // Will to relocate a third instruction to the base trampoline
487       // if the base trampoline is outside of the range of a branch
488       thirdInstruction.raw = instr[arrayOffset + 2].raw;
489
490       size = 3 * sizeof(instruction);
491
492       // Instruction sequence looks like this:
493       //
494       // adr:      insn
495       // adr + 4:  insn
496       // adr + 8:  insn
497
498
499       // If the first instruction is a delayed, control transfer
500       // instruction, we need to also move the instruction in its
501       // delay slot (if it is relocated to the base tramp).
502       if ( isDCTI(firstInstruction) ) {
503
504           firstIsDCTI = true;
505
506           // If the first instruction is a CALL instruction, we may 
507           // need to move the instruction after the instruction in its 
508           // delay slot, to deal with the case where the return value 
509           // of the called function is a structure.
510           if ( isCallInsn(firstInstruction) ) {
511
512               if ( !IS_VALID_INSN(thirdInstruction) && 
513                     thirdInstruction.raw != 0 ) {
514
515                   thirdIsAggregate = true;
516               }
517           }
518       }
519
520
521       // If the second instruction is a delayed, control transfer
522       // instruction, we need to also move the instruction in its
523       // delay slot (if it is relocated to the base tramp).
524       if ( isDCTI(secondInstruction) ) {
525
526           secondIsDCTI = true;
527
528           // If the second instruction is a CALL instruction, we may 
529           // need to move the instruction after the instruction in the 
530           // delay slot, to deal with the case where the return value 
531           // of the called function is a structure.
532           if ( isCallInsn(secondInstruction) ) {
533
534               fourthInstruction.raw = instr[arrayOffset + 3].raw;
535
536               if ( !IS_VALID_INSN(fourthInstruction) && 
537                     fourthInstruction.raw != 0 ) {
538
539                   fourthIsAggregate = true;
540                   size = 4 * sizeof(instruction);
541               }
542           }
543       }
544
545
546       // If the third instruction is a delayed, control transfer
547       // instruction, we need to also move the instruction in its
548       // delay slot (if it is relocated to the base tramp).
549       if ( isDCTI(thirdInstruction) ) {
550
551           thirdIsDCTI = true;
552
553           fourthInstruction.raw = instr[arrayOffset + 3].raw;
554
555           // If the third instruction is a CALL instruction, we may 
556           // need to move the instruction after the instruction in the 
557           // delay slot, to deal with the case where the return value 
558           // of the called function is a structure.
559           if ( isCallInsn(thirdInstruction) ) {
560
561               fifthInstruction.raw = instr[arrayOffset + 4].raw;
562
563               if ( !IS_VALID_INSN(fifthInstruction) && 
564                     fifthInstruction.raw != 0 ) {
565
566                   fifthIsAggregate = true;
567                   size = 5 * sizeof(instruction);
568               }
569           }
570       }
571
572   // For function exit points
573   } else {
574
575       assert(ipType == functionExit);
576
577       firstIsDCTI = true;
578
579       // if the function has no stack frame
580       if (this->hasNoStackFrame()) {
581
582         // Nops were added to the end of the function, so there is no
583         // need to use prior instructions 
584         size = 3 * sizeof(instruction);
585
586       // Function has a stack frame.
587       } else {
588
589           // No need to save registers before branching to exit 
590           // instrumentation
591           size = 2 * sizeof(instruction);
592       }
593   }
594
595
596   // return the address in the code segment after this instruction
597   // sequence. (there's a -1 here because one will be added up later in
598   // the function findInstPoints)  
599   adr = addr + (size - sizeof(instruction));
600 }
601
602 /****************************************************************************/
603 /****************************************************************************/
604 /****************************************************************************/
605
606 // Add the astNode opt to generate one instruction to get the 
607 // return value for the compiler optimazed case
608 void
609 AstNode::optRetVal(AstNode *opt) {
610
611     if (oType == ReturnVal) {
612         cout << "Optimazed Return." << endl;
613         if (loperand == 0) {
614             loperand = opt;
615             return;
616         } else if (opt == 0) {
617             delete loperand;
618             loperand = NULL;
619             return; 
620         }
621     }
622     if (loperand) loperand->optRetVal(opt);
623     if (roperand) roperand->optRetVal(opt);
624     for (unsigned i = 0; i < operands.size(); i++) 
625         operands[i] -> optRetVal(opt);
626 }
627
628 /****************************************************************************/
629 /****************************************************************************/
630 /****************************************************************************/
631
632 bool 
633 processOptimaRet(instPoint *location, AstNode *&ast) {
634
635     // For optimazed return code
636     if (location->ipType == functionExit) {
637
638         if ((isInsnType(location->firstInstruction, RETmask, RETmatch)) ||
639             (isInsnType(location->firstInstruction, RETLmask, RETLmatch))) {
640
641             if (isInsnType(location->secondInstruction, RESTOREmask, 
642                                                         RESTOREmatch) &&
643                 (location->secondInstruction.raw | 0xc1e82000) != 0xc1e82000) {
644
645                 /* cout << "Optimazed Retrun Value:  Addr " << hex << 
646                     location->addr << " in "
647                         << location -> func -> prettyName() << endl; */
648                 AstNode *opt = new AstNode(AstNode::Constant,
649                                    (void *)location->secondInstruction.raw);
650                 ast->optRetVal(opt);
651                 return true;
652             }
653         }
654     }
655
656     return false;
657 }
658
659 /****************************************************************************/
660 /****************************************************************************/
661 /****************************************************************************/
662
663 Register
664 emitOptReturn(instruction i, Register src, char *insn, Address &base, 
665               bool noCost, const instPoint *location) {
666     
667     unsigned instr = i.raw;
668
669     cout << "Handling a special case for optimized return value." << endl;
670
671     assert(((instr&0x3e000000)>>25) <= 16);
672
673     if ((instr&0x02000)>>13)
674         emitImm(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
675                 ((instr&0x3e000000)>>25)+16, insn, base, noCost);
676     else
677         (void) emitV(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
678              ((instr&0x3e000000)>>25)+16, insn, base, noCost);
679     
680     return emitR(getSysRetValOp, 0, 0, src, insn, base, noCost, location);
681 }
682
683 /****************************************************************************/
684 /****************************************************************************/
685 /****************************************************************************/
686
687 //
688 // initDefaultPointFrequencyTable - define the expected call frequency of
689 //    procedures.  Currently we just define several one shots with a
690 //    frequency of one, and provide a hook to read a file with more accurate
691 //    information.
692 //
693 void initDefaultPointFrequencyTable()
694 {
695     FILE *fp;
696     float value;
697     char name[512];
698
699     funcFrequencyTable["main"] = 1;
700     funcFrequencyTable["DYNINSTsampleValues"] = 1;
701     funcFrequencyTable[EXIT_NAME] = 1;
702
703     // try to read file.
704     fp = fopen("freq.input", "r");
705     if (!fp) {
706         return;
707     } else {
708         printf("found freq.input file\n");
709     }
710     while (!feof(fp)) {
711         fscanf(fp, "%s %f\n", name, &value);
712         funcFrequencyTable[name] = (int) value;
713         printf("adding %s %f\n", name, value);
714     }
715     fclose(fp);
716 }
717
718 /****************************************************************************/
719 /****************************************************************************/
720 /****************************************************************************/
721
722 /*
723  * Get an estimate of the frequency for the passed instPoint.  
724  *    This is not (always) the same as the function that contains the point.
725  * 
726  *  The function is selected as follows:
727  *
728  *  If the point is an entry or an exit return the function name.
729  *  If the point is a call and the callee can be determined, return the called
730  *     function.
731  *  else return the funcation containing the point.
732  *
733  *  WARNING: This code contins arbitray values for func frequency (both user 
734  *     and system).  This should be refined over time.
735  *
736  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
737  *      -- jkh 6/24/94
738  *
739  */
740 float getPointFrequency(instPoint *point)
741 {
742
743     pd_Function *func;
744
745     if (point->callee)
746         func = point->callee;
747     else
748         func = point->func;
749
750     if (!funcFrequencyTable.defines(func->prettyName())) {
751       // Changing this value from 250 to 100 because predictedCost was
752       // too high - naim 07/18/96
753       return(100); 
754       
755     } else {
756       return (funcFrequencyTable[func->prettyName()]);
757     }
758 }
759
760 /****************************************************************************/
761 /****************************************************************************/
762 /****************************************************************************/
763
764 //
765 // return cost in cycles of executing at this point.  This is the cost
766 //   of the base tramp if it is the first at this point or 0 otherwise.
767 //
768 int getPointCost(process *proc, const instPoint *point)
769 {
770     if (proc->baseMap.defines(point)) {
771         return(0);
772     } else {
773         // 70 cycles for base tramp (worst case)
774         return(70);
775     }
776 }
777
778 /****************************************************************************/
779 /****************************************************************************/
780 /****************************************************************************/
781
782 void initATramp (trampTemplate *thisTemp, Address tramp,
783                  bool isConservative=false)
784 {
785     instruction *temp;
786
787     if(!isConservative){
788
789         thisTemp->savePreInsOffset = 
790                         ((Address)baseTramp_savePreInsn - tramp);
791         thisTemp->restorePreInsOffset = 
792                         ((Address)baseTramp_restorePreInsn - tramp);
793         thisTemp->savePostInsOffset = 
794                         ((Address)baseTramp_savePostInsn - tramp);
795         thisTemp->restorePostInsOffset = 
796                         ((Address)baseTramp_restorePostInsn - tramp);
797     }else{
798         thisTemp->savePreInsOffset =
799                 ((Address)conservativeBaseTramp_savePreInsn - tramp);
800         thisTemp->restorePreInsOffset =
801                 ((Address)conservativeBaseTramp_restorePreInsn - tramp);
802         thisTemp->savePostInsOffset =
803                 ((Address)conservativeBaseTramp_savePostInsn - tramp);
804         thisTemp->restorePostInsOffset =
805                 ((Address)conservativeBaseTramp_restorePostInsn - tramp);
806     }
807
808     // TODO - are these offsets always positive?
809     thisTemp->trampTemp = (void *) tramp;
810     for (temp = (instruction*)tramp; temp->raw != END_TRAMP; temp++) {
811         const Address offset = (Address)temp - tramp;
812         switch (temp->raw) {
813             case LOCAL_PRE_BRANCH:
814                 thisTemp->localPreOffset = offset;
815                 thisTemp->localPreReturnOffset = thisTemp->localPreOffset 
816                                                 + sizeof(temp->raw);
817                 break;
818             case GLOBAL_PRE_BRANCH:
819                 thisTemp->globalPreOffset = offset;
820                 break;
821             case LOCAL_POST_BRANCH:
822                 thisTemp->localPostOffset = offset;
823                 thisTemp->localPostReturnOffset = thisTemp->localPostOffset
824                                                 + sizeof(temp->raw);
825                 break;
826             case GLOBAL_POST_BRANCH:
827                 thisTemp->globalPostOffset = offset;
828                 break;
829             case SKIP_PRE_INSN:
830                 thisTemp->skipPreInsOffset = offset;
831                 break;
832             case UPDATE_COST_INSN:
833                 thisTemp->updateCostOffset = offset;
834                 break;
835             case SKIP_POST_INSN:
836                 thisTemp->skipPostInsOffset = offset;
837                 break;
838             case RETURN_INSN:
839                 thisTemp->returnInsOffset = offset;
840                 break;
841             case EMULATE_INSN:
842                 thisTemp->emulateInsOffset = offset;
843                 break;
844             case CONSERVATIVE_TRAMP_READ_CONDITION:
845                 if(isConservative)
846                         temp->raw = 0x83408000; /*read condition codes to g1*/
847                 break;
848             case CONSERVATIVE_TRAMP_WRITE_CONDITION:
849                 if(isConservative)
850                         temp->raw = 0x85806000; /*write condition codes fromg1*/
851                 break;
852         }       
853     }
854
855     // Cost with the skip branches.
856     thisTemp->cost = 14;  
857     thisTemp->prevBaseCost = 20 +
858       RECURSIVE_GUARD_ON_CODE_SIZE + RECURSIVE_GUARD_OFF_CODE_SIZE;
859     thisTemp->postBaseCost = 22 +
860       RECURSIVE_GUARD_ON_CODE_SIZE + RECURSIVE_GUARD_OFF_CODE_SIZE;
861     thisTemp->prevInstru = thisTemp->postInstru = false;
862     thisTemp->size = (int) temp - (int) tramp;
863 }
864
865 /****************************************************************************/
866 /****************************************************************************/
867 /****************************************************************************/
868
869 void initATramp(NonRecursiveTrampTemplate *thisTemp, Address tramp,
870                 bool isConservative=false)
871 {
872   initATramp((trampTemplate *)thisTemp, tramp,isConservative);
873
874   instruction *temp;
875
876   for (temp = (instruction*)tramp; temp->raw != END_TRAMP; temp++) {
877     const Address offset = (Address)temp - tramp;
878     switch (temp->raw)
879       {
880
881       case RECURSIVE_GUARD_ON_PRE_INSN:
882         thisTemp->guardOnPre_beginOffset = offset;
883         thisTemp->guardOnPre_endOffset = thisTemp->guardOnPre_beginOffset
884                 + RECURSIVE_GUARD_ON_CODE_SIZE * INSN_SIZE;
885         break;
886
887       case RECURSIVE_GUARD_OFF_PRE_INSN:
888         thisTemp->guardOffPre_beginOffset = offset;
889         thisTemp->guardOffPre_endOffset = thisTemp->guardOffPre_beginOffset
890                 + RECURSIVE_GUARD_OFF_CODE_SIZE * INSN_SIZE;
891         break;
892
893       case RECURSIVE_GUARD_ON_POST_INSN:
894         thisTemp->guardOnPost_beginOffset = offset;
895         thisTemp->guardOnPost_endOffset = thisTemp->guardOnPost_beginOffset
896                 + RECURSIVE_GUARD_ON_CODE_SIZE * INSN_SIZE;
897         break;
898
899       case RECURSIVE_GUARD_OFF_POST_INSN:
900         thisTemp->guardOffPost_beginOffset = offset;
901         thisTemp->guardOffPost_endOffset = thisTemp->guardOffPost_beginOffset
902                 + RECURSIVE_GUARD_OFF_CODE_SIZE * INSN_SIZE;
903         break;
904
905       }
906   }
907 }
908
909 /****************************************************************************/
910 /****************************************************************************/
911 /****************************************************************************/
912
913 void initTramps()
914 {
915     static bool inited=false;
916
917     if (inited) return;
918     inited = true;
919
920     initATramp(&baseTemplate, (Address) baseTramp);
921     initATramp(&nonRecursiveBaseTemplate, (Address)baseTramp);
922
923
924     initATramp(&conservativeBaseTemplate,
925                (Address)conservativeBaseTramp,true);
926     initATramp(&nonRecursiveConservativeBaseTemplate,
927                (Address)conservativeBaseTramp,true);
928
929     regSpace = new registerSpace(sizeof(deadList)/sizeof(Register), deadList,
930                                          0, NULL);
931     assert(regSpace);
932 }
933
934 /****************************************************************************/
935 /****************************************************************************/
936 /****************************************************************************/
937
938 void generateNoOp(process *proc, Address addr)
939 {
940     instruction insn;
941
942     /* fill with no-op */
943     insn.raw = 0;
944     insn.branch.op = 0;
945     insn.branch.op2 = NOOPop2;
946
947     proc->writeTextWord((caddr_t)addr, insn.raw);
948 }
949
950
951 /****************************************************************************/
952 /****************************************************************************/
953 /****************************************************************************/
954
955 /*
956  * change the insn at addr to be a branch to newAddr.
957  *   Used to add multiple tramps to a point.
958  */
959 void generateBranch(process *proc, Address fromAddr, Address newAddr)
960 {
961     int disp;
962     instruction insn;
963
964     disp = newAddr-fromAddr;
965     generateBranchInsn(&insn, disp);
966
967     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
968 }
969 void generateBranchOrCall(process *proc, Address fromAddr, Address newAddr)
970 {
971     int disp;
972     instruction insn;
973
974     disp = newAddr-fromAddr;
975     if (offsetWithinRangeOfBranchInsn(disp)){
976         generateBranchInsn(&insn, disp);
977         proc->writeTextWord((caddr_t)fromAddr, insn.raw);
978     }
979     else{
980         genImmInsn(&insn,SAVEop3,14,-112,14);
981         proc->writeTextWord((caddr_t)fromAddr, insn.raw);
982
983         fromAddr += sizeof(Address);
984         generateCallInsn(&insn,fromAddr,newAddr);
985         proc->writeTextWord((caddr_t)fromAddr, insn.raw);
986
987         fromAddr += sizeof(Address);
988         genSimpleInsn(&insn,RESTOREop3,0,0,0);
989         proc->writeTextWord((caddr_t)fromAddr, insn.raw);
990     }
991 }
992
993 /****************************************************************************/
994 /****************************************************************************/
995 /****************************************************************************/
996
997 void generateCall(process *proc, Address fromAddr, Address newAddr)
998 {
999     instruction insn; 
1000     generateCallInsn(&insn, fromAddr, newAddr);
1001
1002     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1003
1004 }
1005
1006 /****************************************************************************/
1007 /****************************************************************************/
1008 /****************************************************************************/
1009
1010 void genImm(process *proc, Address fromAddr, int op, 
1011                         Register rs1, int immd, Register rd)
1012 {
1013     instruction insn;
1014     genImmInsn(&insn, op, rs1, immd, rd);
1015
1016     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1017 }
1018
1019 /****************************************************************************/
1020 /****************************************************************************/
1021 /****************************************************************************/
1022
1023 /*
1024  *  change the target of the branch at fromAddr, to be newAddr.
1025  */
1026 void changeBranch(process *proc, Address fromAddr, Address newAddr, 
1027                   instruction originalBranch) {
1028     int disp = newAddr-fromAddr;
1029     instruction insn;
1030     insn.raw = originalBranch.raw;
1031     insn.branch.disp22 = disp >> 2;
1032     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1033 }
1034
1035 /****************************************************************************/
1036 /****************************************************************************/
1037 /****************************************************************************/
1038
1039 int callsTrackedFuncP(instPoint *point)
1040 {
1041     if (point->callIndirect) {
1042         return(true);
1043     } else {
1044         if (point->callee) {
1045             return(true);
1046         } else {
1047             return(false);
1048         }
1049     }
1050 }
1051
1052 /****************************************************************************/
1053 /****************************************************************************/
1054 /****************************************************************************/
1055
1056 /*
1057  * return the function asociated with a point.
1058  *
1059  *     If the point is a funcation call, and we know the function being called,
1060  *          then we use that.  Otherwise it is the function that contains the
1061  *          point.
1062  *  
1063  *   This is done to return a better idea of which function we are using.
1064  */
1065 pd_Function *getFunction(instPoint *point)
1066 {
1067     return(point->callee ? point->callee : point->func);
1068 }
1069
1070 /****************************************************************************/
1071 /****************************************************************************/
1072 /****************************************************************************/
1073
1074 bool rpcMgr::emitInferiorRPCheader(void *insnPtr, Address &baseBytes,
1075                                    bool /*isFunclet*/) 
1076 {
1077    instruction *insn = (instruction *)insnPtr;
1078    Address baseInstruc = baseBytes / sizeof(instruction);
1079
1080    genImmInsn(&insn[baseInstruc++], SAVEop3, 14, -112, 14);
1081
1082    baseBytes = baseInstruc * sizeof(instruction); // convert back
1083    return true;
1084 }
1085
1086
1087 /****************************************************************************/
1088 /****************************************************************************/
1089 /****************************************************************************/
1090
1091 bool rpcMgr::emitInferiorRPCtrailer(void *insnPtr, Address &baseBytes,
1092                                     unsigned &breakOffset, bool stopForResult,
1093                                     unsigned &stopForResultOffset,
1094                                     unsigned &justAfter_stopForResultOffset,
1095                                     bool isFunclet)
1096 {
1097
1098    // Sequence: restore, trap, illegal
1099
1100    instruction *insn = (instruction *)insnPtr;
1101    Address baseInstruc = baseBytes / sizeof(instruction);
1102
1103    if (stopForResult) {
1104       // trap insn:
1105       genBreakpointTrap(&insn[baseInstruc]);
1106       stopForResultOffset = baseInstruc * sizeof(instruction);
1107       baseInstruc++;
1108       justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
1109    }
1110
1111
1112    if (isFunclet) { 
1113      //ret instruction
1114      genImmInsn(&insn[baseInstruc++], JMPLop3, REG_I(7), 0x08, REG_G(0)) ;
1115    }
1116
1117    genSimpleInsn(&insn[baseInstruc++], RESTOREop3, 0, 0, 0);
1118
1119    // Now that the inferior has executed the 'restore' instruction, the %in 
1120    // and %local registers have been restored.  We mustn't modify them after
1121    // this point!! (reminder: the %in and %local registers aren't saved and 
1122    // set with ptrace GETREGS/SETREGS call)
1123
1124
1125    // If non-threaded, or if threaded and not safe RPC
1126    if (!isFunclet) {
1127      // Trap instruction:
1128      genBreakpointTrap(&insn[baseInstruc]); // ta 1
1129      breakOffset = baseInstruc * sizeof(instruction);
1130      baseInstruc++;
1131      
1132      // And just to make sure that we don't continue from the trap:
1133      genUnimplementedInsn(&insn[baseInstruc++]); // UNIMP 0
1134    }
1135
1136    baseBytes = baseInstruc * sizeof(instruction); // convert back
1137
1138    return true; // success
1139 }
1140
1141 /****************************************************************************/
1142 /****************************************************************************/
1143 /****************************************************************************/
1144
1145 void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, 
1146              char *i, Address &base, bool noCost)
1147 {
1148         instruction *insn = (instruction *) ((void*)&i[base]);
1149         RegValue op3 = -1;
1150         int result = -1;
1151         switch (op) {
1152             // integer ops
1153             case plusOp:
1154                 op3 = ADDop3;
1155                 genImmInsn(insn, op3, src1, src2imm, dest);
1156                 break;
1157
1158             case minusOp:
1159                 op3 = SUBop3;
1160                 genImmInsn(insn, op3, src1, src2imm, dest);
1161                 break;
1162
1163             case timesOp:
1164                 op3 = SMULop3;
1165                 if (isPowerOf2(src2imm,result) && (result<32))
1166                   generateLShift(insn, src1, (Register)result, dest);           
1167                 else 
1168                   genImmInsn(insn, op3, src1, src2imm, dest);
1169                 break;
1170
1171             case divOp:
1172                 op3 = SDIVop3;
1173                 if (isPowerOf2(src2imm,result) && (result<32))
1174                   generateRShift(insn, src1, (Register)result, dest);           
1175                 else { // needs to set the Y register to zero first
1176                   // Set the Y register to zero: Zhichen
1177                   genImmInsn(insn, WRYop3, REG_G(0), 0, 0);
1178                   base += sizeof(instruction);
1179                   insn = (instruction *) ((void*)&i[base]);
1180                   genImmInsn(insn, op3, src1, src2imm, dest);
1181                 }
1182
1183                 break;
1184
1185             // Bool ops
1186             case orOp:
1187                 op3 = ORop3;
1188                 genImmInsn(insn, op3, src1, src2imm, dest);
1189                 break;
1190
1191             case andOp:
1192                 op3 = ANDop3;
1193                 genImmInsn(insn, op3, src1, src2imm, dest);
1194                 break;
1195
1196             // rel ops
1197             // For a particular condition (e.g. <=) we need to use the
1198             // the opposite in order to get the right value (e.g. for >=
1199             // we need BLTcond) - naim
1200             case eqOp:
1201                 genImmRelOp(insn, BNEcond, src1, src2imm, dest, base);
1202                 return;
1203                 break;
1204
1205             case neOp:
1206                 genImmRelOp(insn, BEcond, src1, src2imm, dest, base);
1207                 return;
1208                 break;
1209
1210             case lessOp:
1211                 genImmRelOp(insn, BGEcond, src1, src2imm, dest, base);
1212                 return;
1213                 break;
1214
1215             case leOp:
1216                 genImmRelOp(insn, BGTcond, src1, src2imm, dest, base);
1217                 return;
1218                 break;
1219
1220             case greaterOp:
1221                 genImmRelOp(insn, BLEcond, src1, src2imm, dest, base);
1222                 return;
1223                 break;
1224
1225             case geOp:
1226                 genImmRelOp(insn, BLTcond, src1, src2imm, dest, base);
1227                 return;
1228                 break;
1229
1230             default:
1231                 Register dest2 = regSpace->allocateRegister(i, base, noCost);
1232                 (void) emitV(loadConstOp, src2imm, dest2, dest2, i, base, noCost);
1233                 (void) emitV(op, src1, dest2, dest, i, base, noCost);
1234                 regSpace->freeRegister(dest2);
1235                 return;
1236                 break;
1237         }
1238         base += sizeof(instruction);
1239         return;
1240 }
1241
1242 /****************************************************************************/
1243 /****************************************************************************/
1244 /****************************************************************************/
1245
1246 //
1247 // All values based on Cypress0 && Cypress1 implementations as documented in
1248 //   SPARC v.8 manual p. 291
1249 //
1250 int getInsnCost(opCode op)
1251 {
1252     /* XXX Need to add branchOp */
1253     if (op == loadConstOp) {
1254         return(1);
1255     } else if (op ==  loadOp) {
1256         // sethi + load single
1257         return(1+1);
1258     } else if (op ==  loadIndirOp) {
1259         return(1);
1260     } else if (op ==  storeOp) {
1261         // sethi + store single
1262         // return(1+3); 
1263         // for SS-5 ?
1264         return(1+2); 
1265     } else if (op ==  storeIndirOp) {
1266         return(2); 
1267     } else if (op ==  ifOp) {
1268         // subcc
1269         // be
1270         // nop
1271         return(1+1+1);
1272     } else if (op ==  callOp) {
1273         int count = 0;
1274
1275         // mov src1, %o0
1276         count += 1;
1277
1278         // mov src2, %o1
1279         count += 1;
1280
1281         // clr i2
1282         count += 1;
1283
1284         // clr i3
1285         count += 1;
1286
1287         // sethi
1288         count += 1;
1289
1290         // jmpl
1291         count += 1;
1292
1293         // noop
1294         count += 1;
1295
1296         return(count);
1297     } else if (op ==  updateCostOp) {
1298         // sethi %hi(obsCost), %l0
1299         // ld [%lo + %lo(obsCost)], %l1
1300         // add %l1, <cost>, %l1
1301         // st %l1, [%lo + %lo(obsCost)]
1302         return(1+2+1+3);
1303     } else if (op ==  trampPreamble) {
1304         return(0);
1305     } else if (op ==  trampTrailer) {
1306         // retl
1307         return(2);
1308     } else if (op == noOp) {
1309         // noop
1310         return(1);
1311     } else if (op == getParamOp) {
1312         return(0);
1313     } else {
1314         switch (op) {
1315             // rel ops
1316             case eqOp:
1317             case neOp:
1318             case lessOp:
1319             case leOp:
1320             case greaterOp:
1321             case geOp:
1322                 // bne -- assume taken
1323                 return(2);
1324                 break;
1325             default:
1326                 return(1);
1327                 break;
1328         }
1329     }
1330 }
1331
1332 /****************************************************************************/
1333 /****************************************************************************/
1334 /****************************************************************************/
1335
1336 bool isReturnInsn(instruction instr, Address addr, string name) {
1337     if (isInsnType(instr, RETmask, RETmatch) ||
1338         isInsnType(instr, RETLmask, RETLmatch)) {
1339         //  Why 8 or 12?
1340         //  According to the sparc arch manual (289), ret or retl are
1341         //   synthetic instructions for jmpl %i7+8, %g0 or jmpl %o7+8, %go.
1342         //  Apparently, the +8 is not really a hard limit though, as 
1343         //   sometimes some extra space is allocated after the jump 
1344         //   instruction for various reasons.
1345         //  1 possible reason is to include information on the size of
1346         //   returned structure (4 bytes).
1347         //  So, 8 or 12 here is a heuristic, but doesn't seem to 
1348         //   absolutely have to be true.
1349         //  -matt
1350         if ((instr.resti.simm13 != 8) && (instr.resti.simm13 != 12) 
1351                     && (instr.resti.simm13 != 16)) {
1352           sprintf(errorLine,"WARNING: unsupported return at address 0x%lx"
1353                         " in function %s - appears to be return to PC + %i", 
1354                   addr, name.c_str(), (int)instr.resti.simm13);
1355           showErrorCallback(55, errorLine);
1356         } else { 
1357           return true;
1358         }
1359     }
1360     return false;
1361 }
1362
1363 /****************************************************************************/
1364 /****************************************************************************/
1365 /****************************************************************************/
1366
1367 bool isReturnInsn(const image *owner, Address adr, bool &lastOne, string name)
1368 {
1369     instruction instr;
1370
1371     instr.raw = owner->get_instruction(adr);
1372     lastOne = false;
1373
1374     return isReturnInsn(instr, adr, name);
1375 }
1376
1377 /****************************************************************************/
1378 /****************************************************************************/
1379 /****************************************************************************/
1380
1381 bool isBranchInsn(instruction instr) {
1382     if (instr.branch.op == 0 
1383                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) 
1384           return true;
1385     return false;
1386 }
1387
1388 /****************************************************************************/
1389 /****************************************************************************/
1390 /****************************************************************************/
1391
1392 // modifyInstPoint: if the function associated with the process was 
1393 // recently relocated, then the instPoint may have the old pre-relocated
1394 // address (this can occur because we are getting instPoints in mdl routines 
1395 // and passing these to routines that do the instrumentation, it would
1396 // be better to let the routines that do the instrumenting find the points)
1397 void pd_Function::modifyInstPoint(const instPoint *&location,process *proc)
1398 {
1399
1400     if(relocatable_ && !(location->relocated_)){
1401         for(u_int i=0; i < relocatedByProcess.size(); i++){
1402             if((relocatedByProcess[i])->getProcess() == proc){
1403                 if(location->ipType == functionEntry){
1404                     const instPoint *new_entry = 
1405                                 (relocatedByProcess[i])->funcEntry();
1406                     location = new_entry;
1407                 } 
1408                 else if(location->ipType == functionExit){
1409                     const pdvector<instPoint *> new_returns = 
1410                         (relocatedByProcess[i])->funcReturns(); 
1411                     if(funcReturns.size() != new_returns.size()){
1412                         printf("funcReturns = %d new_returns = %d\n",
1413                                 funcReturns.size(),new_returns.size());
1414                         fflush(stdout);
1415                     }
1416                     assert(funcReturns.size() == new_returns.size());
1417                     for(u_int j=0; j < new_returns.size(); j++){
1418                         if(funcReturns[j] == location){
1419                             location = (new_returns[j]);
1420                             break;
1421                         }
1422                     }
1423                 }
1424                 else if(location->ipType == otherPoint) {
1425                     const pdvector<instPoint *> new_arbitrary = 
1426                         (relocatedByProcess[i])->funcArbitraryPoints(); 
1427
1428                     assert(arbitraryPoints.size() == new_arbitrary.size());
1429                     for(u_int j=0; j < new_arbitrary.size(); j++){
1430                         if(arbitraryPoints[j] == location){
1431                             location = (new_arbitrary[j]);
1432                             break;
1433                         }
1434                     }
1435                 }
1436                 else {
1437                     const pdvector<instPoint *> new_calls = 
1438                                 (relocatedByProcess[i])->funcCallSites(); 
1439                     assert(calls.size() == new_calls.size());
1440                     for(u_int j=0; j < new_calls.size(); j++){
1441                         if(calls[j] == location){
1442                             location = (new_calls[j]);
1443                             break;
1444                         }
1445                     }
1446
1447                 }
1448                 break;
1449     } } }
1450 }
1451
1452 /****************************************************************************/
1453 /****************************************************************************/
1454 /****************************************************************************/
1455
1456 // The exact semantics of the heap are processor specific.
1457 //
1458 // find all DYNINST symbols that are data symbols
1459 //
1460 bool process::heapIsOk(const pdvector<sym_data> &find_us) {
1461   Symbol sym;
1462   Address baseAddr;
1463
1464   // find the main function
1465   // first look for main or _main
1466   if (!((mainFunction = findOneFunction("main")) 
1467         || (mainFunction = findOneFunction("_main")))) {
1468      string msg = "Cannot find main. Exiting.";
1469      statusLine(msg.c_str());
1470 #if defined(BPATCH_LIBRARY)
1471      BPatch_reportError(BPatchWarning, 50, msg.c_str());
1472 #else
1473      showErrorCallback(50, msg);
1474 #endif
1475      return false;
1476   }
1477
1478   for (unsigned i=0; i<find_us.size(); i++) {
1479     const string &str = find_us[i].name;
1480     if (!getSymbolInfo(str, sym, baseAddr)) {
1481       string str1 = string("_") + str.c_str();
1482       if (!getSymbolInfo(str1, sym, baseAddr) && find_us[i].must_find) {
1483         string msg;
1484         msg = string("Cannot find ") + str + string(". Exiting");
1485         statusLine(msg.c_str());
1486         showErrorCallback(50, msg);
1487         return false;
1488       }
1489     }
1490   }
1491
1492 //  string ghb = GLOBAL_HEAP_BASE;
1493 //  if (!getSymbolInfo(ghb, sym, baseAddr)) {
1494 //    ghb = U_GLOBAL_HEAP_BASE;
1495 //    if (!linkedFile.get_symbol(ghb, sym)) {
1496 //      string msg;
1497 //      msg = string("Cannot find ") + ghb + string(". Exiting");
1498 //      statusLine(msg.c_str());
1499 //      showErrorCallback(50, msg);
1500 //      return false;
1501 //    }
1502 //  }
1503 //  Address instHeapEnd = sym.addr()+baseAddr;
1504 //  addInternalSymbol(ghb, instHeapEnd);
1505
1506
1507 #ifdef ndef
1508   /* Not needed with the new heap type system */
1509
1510   string ihb = INFERIOR_HEAP_BASE;
1511   if (!getSymbolInfo(ihb, sym, baseAddr)) {
1512     ihb = UINFERIOR_HEAP_BASE;
1513     if (!getSymbolInfo(ihb, sym, baseAddr)) {
1514       string msg;
1515       msg = string("Cannot find ") + ihb + string(". Cannot use this application");
1516       statusLine(msg.c_str());
1517       showErrorCallback(50, msg);
1518       return false;
1519     }
1520   }
1521
1522   Address curr = sym.addr()+baseAddr;
1523   // Check that we can patch up user code to jump to our base trampolines
1524   // (Perhaps this code is no longer needed for sparc platforms, since we use full
1525   // 32-bit jumps)
1526   const Address instHeapStart = curr;
1527   const Address instHeapEnd = instHeapStart + SYN_INST_BUF_SIZE - 1;
1528
1529   if (instHeapEnd > getMaxBranch3Insn()) {
1530     logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
1531     sprintf(errorLine, "    heap starts at %x and ends at %x; maxbranch=%x\n",
1532             instHeapStart, instHeapEnd, getMaxBranch3Insn());
1533     logLine(errorLine);
1534     return false;
1535   }
1536 #endif
1537
1538   return true;
1539 }
1540
1541 /****************************************************************************/
1542 /****************************************************************************/
1543 /****************************************************************************/
1544
1545 // Certain registers (i0-i7 on a SPARC) may be available to be read
1546 // as an operand, but cannot be written.
1547 bool registerSpace::readOnlyRegister(Register /*reg_number*/) {
1548 // -- this code removed, since it seems incorrect
1549 //if ((reg_number < REG_L(0)) || (reg_number > REG_L(7)))
1550 //    return true;
1551 //else
1552       return false;
1553 }
1554
1555 /****************************************************************************/
1556 /****************************************************************************/
1557 /****************************************************************************/
1558
1559 bool returnInstance::checkReturnInstance(const pdvector<pdvector<Frame> > &stackWalks)
1560 {
1561   // If false (unsafe) is returned, then 'index' is set to the first unsafe call stack
1562   // index.
1563   for (unsigned walk_iter = 0; walk_iter < stackWalks.size(); walk_iter++)
1564     for (u_int i=0; i < stackWalks[walk_iter].size(); i++) {
1565       // Is the following check correct?  Shouldn't the ">" be changed to ">=",
1566       // and the "<=" be changed to "<" ??? --ari 6/11/97
1567       // No, because we want to return false if the PC is in the stackwalk
1568       // footprint (from addr_ to addr_+size_) -- bernat 10OCT02
1569         if ((stackWalks[walk_iter][i].getPC() > addr_) && 
1570             (stackWalks[walk_iter][i].getPC() < addr_+size_))
1571             return false;
1572     }
1573   
1574   return true;
1575 }
1576
1577 /****************************************************************************/
1578 /****************************************************************************/
1579 /****************************************************************************/
1580
1581 void returnInstance::installReturnInstance(process *proc) {
1582     proc->writeTextSpace((caddr_t)addr_, instSeqSize, 
1583                          (caddr_t) instructionSeq); 
1584     installed = true;
1585 }
1586
1587 /****************************************************************************/
1588 /****************************************************************************/
1589 /****************************************************************************/
1590
1591 void generateBreakPoint(instruction &insn) {
1592     insn.raw = BREAK_POINT_INSN;
1593 }
1594
1595 /****************************************************************************/
1596 /****************************************************************************/
1597 /****************************************************************************/
1598
1599 void returnInstance::addToReturnWaitingList(Address pc, process *proc) {
1600     // if there already is a TRAP set at this pc for this process don't
1601     // generate a trap instruction again...you will get the wrong original
1602     // instruction if you do a readDataSpace
1603     bool found = false;
1604     instruction insn;
1605     for (u_int i=0; i < instWList.size(); i++) {
1606          if (instWList[i]->pc_ == pc && instWList[i]->which_proc == proc) {
1607              found = true;
1608              insn = instWList[i]->relocatedInstruction;
1609              break;
1610          }
1611     }
1612     if(!found) {
1613         instruction insnTrap;
1614         generateBreakPoint(insnTrap);
1615         proc->readDataSpace((caddr_t)pc, sizeof(insn), (char *)&insn, true);
1616         proc->writeTextSpace((caddr_t)pc, sizeof(insnTrap), (caddr_t)&insnTrap);
1617     }
1618     else {
1619     }
1620
1621     instWaitingList *instW = new instWaitingList(instructionSeq,instSeqSize,
1622                                                  addr_,pc,insn,pc,proc);
1623     instWList.push_back(instW);
1624 }
1625
1626 /****************************************************************************/
1627 /****************************************************************************/
1628 /****************************************************************************/
1629
1630 bool doNotOverflow(int value)
1631 {
1632   // we are assuming that we have 13 bits to store the immediate operand.
1633   //if ( (value <= 16383) && (value >= -16384) ) return(true);
1634   if ( (value <= MAX_IMM13) && (value >= MIN_IMM13) ) return(true);
1635   else return(false);
1636 }
1637
1638 /****************************************************************************/
1639 /****************************************************************************/
1640 /****************************************************************************/
1641
1642 void instWaitingList::cleanUp(process *proc, Address pc) {
1643     proc->writeTextSpace((caddr_t)pc, sizeof(relocatedInstruction),
1644                     (caddr_t)&relocatedInstruction);
1645     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t)instructionSeq);
1646 }
1647
1648 /****************************************************************************/
1649 /****************************************************************************/
1650 /****************************************************************************/
1651
1652 // process::replaceFunctionCall
1653 //
1654 // Replace the function call at the given instrumentation point with a call to
1655 // a different function, or with a NOOP.  In order to replace the call with a
1656 // NOOP, pass NULL as the parameter "func."
1657 // Returns true if sucessful, false if not.  Fails if the site is not a call
1658 // site, or if the site has already been instrumented using a base tramp.
1659 bool process::replaceFunctionCall(const instPoint *point,
1660                                   const function_base *func) {
1661     // Must be a call site
1662     if (point->ipType != callSite)
1663         return false;
1664
1665     // Cannot already be instrumented with a base tramp
1666     if (baseMap.defines(point))
1667         return false;
1668
1669     // Replace the call
1670     Address addr = point->addr;
1671
1672 #ifdef BPATCH_LIBRARY
1673     // Make sure our address is absolute, and not relative
1674     if (point->getBPatch_point() != NULL &&
1675         point->getBPatch_point()->func != NULL) {
1676       pd_Function *pdfp;
1677
1678       pdfp = dynamic_cast<pd_Function *>(point->getBPatch_point()->func->func);
1679       if (pdfp != NULL) {
1680         Address base;
1681         getBaseAddress(pdfp->file()->exec(), base);
1682         addr += base;
1683       }
1684     }
1685 #endif
1686     if (func == NULL)
1687         generateNoOp(this, addr);
1688     else
1689         generateCall(this, addr,
1690                      func->getEffectiveAddress(this));
1691
1692     return true;
1693 }
1694
1695 /****************************************************************************/
1696 /****************************************************************************/
1697 /****************************************************************************/
1698
1699 #ifndef BPATCH_LIBRARY
1700 bool process::isDynamicCallSite(instPoint *callSite){
1701   function_base *temp;
1702   if(!findCallee(*(callSite),temp)){
1703     //True call instructions are not dynamic on sparc,
1704     //they are always to a pc relative offset
1705     if(!isTrueCallInsn(callSite->firstInstruction))
1706       return true;
1707   }
1708   return false;
1709 }
1710
1711 /****************************************************************************/
1712 /****************************************************************************/
1713 /****************************************************************************/
1714
1715 bool process::MonitorCallSite(instPoint *callSite){
1716  
1717   if(isJmplInsn(callSite->firstInstruction)){
1718     pdvector<AstNode *> the_args(2);
1719     
1720     //this instruction is a jmpl with i == 1, meaning it
1721     //calling function register rs1+simm13
1722     if(callSite->firstInstruction.rest.i == 1){
1723       
1724       AstNode *base =  new AstNode(AstNode::PreviousStackFrameDataReg,
1725                           (void *) callSite->firstInstruction.rest.rs1);
1726       AstNode *offset = new AstNode(AstNode::Constant, 
1727                         (void *) callSite->firstInstruction.resti.simm13);
1728       the_args[0] = new AstNode(plusOp, base, offset);
1729     } 
1730     
1731     //This instruction is a jmpl with i == 0, meaning its
1732     //two operands are registers
1733     else if(callSite->firstInstruction.rest.i == 0){
1734       //Calculate the byte offset from the contents of the %fp reg
1735       //that the registers from the previous stack frame 
1736       //specified by rs1 and rs2 are stored on the stack
1737       AstNode *callee_addr1 = 
1738         new AstNode(AstNode::PreviousStackFrameDataReg,
1739                     (void *) callSite->firstInstruction.rest.rs1);
1740       AstNode *callee_addr2 = 
1741         new AstNode(AstNode::PreviousStackFrameDataReg, 
1742                     (void *) callSite->firstInstruction.rest.rs2);
1743       the_args[0] = new AstNode(plusOp, callee_addr1, callee_addr2);
1744     }
1745     else assert(0);
1746     
1747     the_args[1] = new AstNode(AstNode::Constant,
1748                               (void *) callSite->iPgetAddress());
1749     AstNode *func = new AstNode("DYNINSTRegisterCallee", 
1750                                 the_args);
1751     miniTrampHandle mtHandle;
1752     addInstFunc(&mtHandle, this, callSite, func, callPreInsn,
1753                 orderFirstAtPoint, true, false);
1754   }
1755   else if(isTrueCallInsn(callSite->firstInstruction)){
1756     //True call destinations are always statically determinable.
1757     return true;
1758   }
1759   else return false;
1760
1761   return true;
1762 }
1763 #endif
1764
1765 /****************************************************************************/
1766 /****************************************************************************/
1767 /****************************************************************************/
1768
1769 // Emit code to jump to function CALLEE without linking.  (I.e., when
1770 // CALLEE returns, it returns to the current caller.)  On SPARC, we do
1771 // this by ensuring that the register context upon entry to CALLEE is
1772 // the register context of function we are instrumenting, popped once.
1773 void emitFuncJump(opCode op, char *i, Address &base, 
1774                   const function_base *callee, process *proc,
1775                   const instPoint *, bool)
1776 {
1777         assert(op == funcJumpOp);
1778         Address addr;
1779         void cleanUpAndExit(int status);
1780
1781         addr = callee->getEffectiveAddress(proc);
1782         // TODO cast
1783         instruction *insn = (instruction *) ((void*)&i[base]);
1784
1785         generateSetHi(insn, addr, 13); insn++;
1786         // don't want the return address to be used
1787         genImmInsn(insn, JMPLop3, 13, LOW10(addr), 0); insn++;
1788         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); insn++;
1789         base += 3 * sizeof(instruction);
1790 }
1791
1792
1793 // If there is a base trampoline installed for this instPoint delete it
1794 // and undo the operations done in findAndInstallBaseTramp. (i.e. replace
1795 // the ba, a and save; call; restore; sequences with the instructions
1796 // originally at those locations in the function
1797 bool deleteBaseTramp(process *proc, instPoint* location,
1798                      trampTemplate *baseInstance, 
1799                      instInstance *lastMT)
1800 {
1801   Address ipAddr, baseAddress;
1802   trampTemplate* currentBaseTramp;
1803
1804   if(!proc->baseMap.find((const instPoint*)location,currentBaseTramp)) {
1805     return false;
1806   }
1807
1808   assert(currentBaseTramp == baseInstance);
1809
1810   // If the function has been relocated and the instPoint is from
1811   // the original instPoint, change the instPoint to be the one 
1812   // in the corresponding relocated function instead
1813   if(location->func->isInstalled(proc) && !location->relocated_) {
1814
1815     location->func->modifyInstPoint( (const instPoint *)(location), proc );
1816   }
1817
1818   // Get the base address of the shared object
1819   proc->getBaseAddress(location->image_ptr, baseAddress);
1820
1821   // Get the address of the instPoint
1822   ipAddr = location->iPgetAddress() + baseAddress;
1823
1824
1825   // Replace the branch instruction with the instruction that was
1826   // originally there
1827   if( !location->needsLongJump ) {
1828
1829     proc->writeTextWord( (caddr_t)(ipAddr), location->firstInstruction.raw );
1830
1831   } else {
1832
1833       // A call was used to transfer to the base tramp, clear out the
1834       // call and any other instructions that were written into the
1835       // function
1836
1837       // Address of the first instruction in the instPoint's footprint
1838       Address firstAddress = ipAddr;
1839
1840       if( location->hasNoStackFrame() ) {
1841
1842           if (location->usesPriorInstructions) {
1843
1844             firstAddress = ipAddr - 
1845                            location->numPriorInstructions*sizeof(instruction);
1846           }
1847
1848           // Replace the instruction overwritten by the save instruction
1849           proc->writeTextWord( (caddr_t)(firstAddress), 
1850                                location->firstInstruction.raw );
1851
1852           // Replace the instruction overwritten by the call instruction
1853           proc->writeTextWord( (caddr_t)(firstAddress) + sizeof(instruction), 
1854                                location->secondInstruction.raw );
1855
1856           if (location->ipType != otherPoint) {
1857
1858               // Replace the instruction overwritten by the nop instruction
1859               proc->writeTextWord( (caddr_t)(firstAddress) + 
1860                                      2*sizeof(instruction),
1861                                     location->thirdInstruction.raw );
1862           }
1863
1864       } else {
1865
1866           if (location->ipType == functionEntry) {
1867
1868             // Replace the instruction overwritten by the save instruction
1869             proc->writeTextWord( (caddr_t)(firstAddress),
1870                                  location->firstInstruction.raw);
1871
1872             // Replace the instruction overwritten by the call instruction
1873             proc->writeTextWord( (caddr_t)(firstAddress) + 
1874                                    sizeof(instruction),
1875                                  location->secondInstruction.raw);
1876   
1877             // Replace the instruction overwritten by the nop instruction
1878             proc->writeTextWord( (caddr_t)(firstAddress) + 
1879                                    2*sizeof(instruction),
1880                                  location->thirdInstruction.raw);
1881
1882           } else if ( location->ipType == callSite || 
1883                       location->ipType == functionExit ) {
1884
1885               // Replace the instruction overwritten by the call instruction
1886               proc->writeTextWord( (caddr_t)(firstAddress),
1887                                    location->firstInstruction.raw);
1888   
1889               // Replace the instruction overwritten by the nop instruction
1890               proc->writeTextWord( (caddr_t)(firstAddress) + 
1891                                      sizeof(instruction),
1892                                    location->secondInstruction.raw);
1893
1894
1895           } else if (location->ipType == otherPoint) {
1896
1897               // Replace the instruction overwritten by the call instruction
1898               proc->writeTextWord( (caddr_t)(firstAddress), 
1899                                    location->firstInstruction.raw );
1900
1901               // Replace the instruction overwritten by the nop instruction
1902               proc->writeTextWord( (caddr_t)(firstAddress) + 
1903                                      sizeof(instruction), 
1904                                    location->secondInstruction.raw );
1905
1906           }
1907       }
1908   }
1909
1910   // Grrr... well, the inferiorFree mechanism has been replaced
1911   // with one that handles instInstances extremely well. Unfortunately,
1912   // this doesn't match up with a base tramp. 
1913   // The correct answer is probably to come up with a generic
1914   // "installed instrumentation" data structure and use that. For
1915   // now we fake an instInstance and add it to the list.
1916
1917   // Free up the base trampoline
1918   proc->deleteBaseTramp(currentBaseTramp, lastMT);
1919
1920   return true;
1921 }
1922
1923
1924 #ifdef BPATCH_LIBRARY
1925
1926 #include "BPatch_flowGraph.h"
1927 #include "BPatch_function.h"
1928
1929 #include <sys/systeminfo.h>
1930
1931 // VG(4/24/2002) It seems a good idea to cache the result.
1932 // This is not thread safe, but should be okay since the 
1933 // result shoud be the same for all threads...
1934 /*
1935  * function which check whether the architecture is 
1936  * sparcv8plus or not. For the earlier architectures 
1937  * it is not possible to support random instrumentation 
1938  */
1939 bool isV8plusISA()
1940 {
1941   static bool result;
1942   static bool gotresult = false;
1943
1944   if(gotresult)
1945     return result;
1946   else {
1947     char isaOptions[256];
1948
1949     if (sysinfo(SI_ISALIST, isaOptions, 256) < 0)
1950       return false;
1951     if (strstr(isaOptions, "sparcv8plus"))
1952       return true;
1953     return false;
1954   }
1955 }
1956
1957 /*
1958  * function which check whether the architecture is 
1959  * sparcv9 or later. For the earlier architectures 
1960  * it is not possible to support ajacent arbitrary 
1961  * instrumentation points
1962  */
1963 bool isV9ISA()
1964 {
1965   static bool result;
1966   static bool gotresult = false;
1967
1968   if(gotresult)
1969     return result;
1970   else { 
1971     char isaOptions[256];
1972
1973     if (sysinfo(SI_ISALIST, isaOptions, 256) < 0)
1974       return false;
1975     if (strstr(isaOptions, "sparcv9"))
1976       return true;
1977     return false;
1978   }
1979 }
1980
1981
1982 /*
1983  * createInstructionInstPoint
1984  *
1985  * Create a BPatch_point instrumentation point at the given address, which
1986  * is guaranteed not be one of the "standard" inst points.
1987  *
1988  * proc         The process in which to create the inst point.
1989  * address      The address for which to create the point.
1990  */
1991
1992 BPatch_point* createInstructionInstPoint(process *proc, void *address,
1993                                          BPatch_point** alternative,
1994                                          BPatch_function* bpf)
1995 {
1996     unsigned i;
1997     Address begin_addr,end_addr,curr_addr;
1998     bool dontUseCallHere = false;
1999     bool needsRelocate = false;
2000
2001     //the method to check whether conservative base tramp can be installed
2002     //or not since it contains condition code instructions which is
2003     //available after version8plus of sparc
2004
2005     if(!isV8plusISA()){
2006         cerr << "BPatch_image::createInstPointAtAddr : is not supported for";
2007         cerr << " sparc architecture earlier than v8plus\n";
2008         return NULL;
2009     }
2010
2011     //fprintf(stderr, "Called for %p\n", address);
2012
2013     curr_addr = (Address)address;
2014
2015     //if the address is not aligned then there is a problem
2016     if(!isAligned(curr_addr))   
2017         return NULL;
2018
2019     function_base *func = NULL;
2020     if(bpf)
2021         func = bpf->func;
2022     else
2023         func = proc->findFuncByAddr(curr_addr);
2024
2025     pd_Function* pointFunction = (pd_Function*)func;
2026     Address pointImageBase = 0;
2027     image* pointImage = pointFunction->file()->exec();
2028     proc->getBaseAddress((const image*)pointImage,pointImageBase);
2029
2030     BPatch_function *bpfunc = proc->findOrCreateBPFunc((pd_Function*)func);
2031     
2032     BPatch_flowGraph *cfg = bpfunc->getCFG();
2033     BPatch_Set<BPatch_basicBlock*> allBlocks;
2034     cfg->getAllBasicBlocks(allBlocks);
2035
2036     BPatch_basicBlock** belements =
2037                 new BPatch_basicBlock*[allBlocks.size()];
2038     allBlocks.elements(belements);
2039
2040     for(i=0; i< (unsigned)allBlocks.size(); i++) {
2041         void *bbsa, *bbea;
2042         if (belements[i]->getAddressRange(bbsa,bbea)) {
2043             begin_addr = (Address)bbsa;
2044             if ((begin_addr - INSN_SIZE) == curr_addr) {
2045               if (pointFunction->canBeRelocated())
2046                 needsRelocate = true;
2047               else {
2048                 delete[] belements;
2049                 BPatch_reportError(BPatchSerious, 118,
2050                                    "point uninstrumentable (0)");
2051                 return NULL;
2052               }
2053             }
2054         }
2055     }
2056     delete[] belements;
2057
2058     curr_addr -= pointImageBase;
2059
2060     if (func != NULL) {
2061         instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
2062         assert(entry);
2063
2064         begin_addr = entry->iPgetAddress();
2065         end_addr = begin_addr + entry->Size();
2066
2067         if(((begin_addr - INSN_SIZE) <= curr_addr) && 
2068            (curr_addr < end_addr)){ 
2069             BPatch_reportError(BPatchSerious, 117,
2070                                "instrumentation point conflict 1");
2071             if(alternative)
2072                 *alternative = proc->findOrCreateBPPoint(bpfunc, entry, BPatch_entry);
2073             return NULL;
2074         }
2075
2076         const pdvector<instPoint*> &exits = func->funcExits(NULL);
2077         for (i = 0; i < exits.size(); i++) {
2078             assert(exits[i]);
2079
2080             begin_addr = exits[i]->iPgetAddress();
2081             end_addr = begin_addr + exits[i]->Size();
2082
2083             if (((begin_addr - INSN_SIZE) <= curr_addr) &&
2084                 (curr_addr < end_addr)){
2085                 BPatch_reportError(BPatchSerious, 117,
2086                                    "instrumentation point conflict 2");
2087                 if(alternative)
2088                         *alternative = proc->findOrCreateBPPoint(bpfunc,exits[i],BPatch_exit);
2089                 return NULL;
2090             }
2091         }
2092
2093         const pdvector<instPoint*> &calls = func->funcCalls(NULL);
2094         for (i = 0; i < calls.size(); i++) {
2095             assert(calls[i]);
2096
2097             begin_addr = calls[i]->iPgetAddress();
2098             end_addr = begin_addr + calls[i]->Size();
2099
2100             if (((begin_addr - INSN_SIZE) <= curr_addr) &&
2101                 (curr_addr < end_addr)){
2102                 BPatch_reportError(BPatchSerious, 117,
2103                                    "instrumentation point conflict3 ");
2104                 if(alternative)
2105                         *alternative = proc->findOrCreateBPPoint(bpfunc,calls[i],BPatch_subroutine);
2106                 return NULL;
2107             }
2108         }
2109     }
2110
2111     curr_addr += pointImageBase;
2112
2113     /* Check for conflict with a previously created inst point. */
2114     // VG(4/24/2002): there is no conflict on v9.
2115     if (proc->instPointMap.defines(curr_addr - INSN_SIZE)) {
2116       //NOTE:if the previous instrumentation point is instrumented and
2117       //instrumentation used call instruction, anomaly occurs
2118       if(isV9ISA())
2119         (proc->instPointMap)[curr_addr-INSN_SIZE]->point->dontUseCall = true;
2120       else {
2121         BPatch_reportError(BPatchSerious,117,"instrumentation point conflict 4");
2122         return NULL;
2123       }
2124       if(alternative)
2125         *alternative = (proc->instPointMap)[curr_addr-INSN_SIZE];
2126
2127     } else if (proc->instPointMap.defines(curr_addr + INSN_SIZE)) {
2128       if(isV9ISA())
2129         dontUseCallHere=true;
2130       else {
2131         BPatch_reportError(BPatchSerious,117,"instrumentation point conflict 5");
2132         return NULL;
2133       }
2134       if(alternative)
2135         *alternative = (proc->instPointMap)[curr_addr+INSN_SIZE];
2136     }
2137
2138     // VG(4/24/2002): Should also modify this no to bother with b,a on v9
2139     /* Check for instrumenting just before or after a branch. */
2140
2141     bool decrement = false;
2142     if ((Address)address > func->getEffectiveAddress(proc)) {
2143       //fprintf(stderr, "Wierd1=true@%x\n", address);
2144         instruction prevInstr;
2145         proc->readTextSpace((char *)address - INSN_SIZE,
2146                             sizeof(instruction),
2147                             &prevInstr.raw);
2148         if (isDCTI(prevInstr)){
2149           if((prevInstr.call.op == CALLop) ||
2150              ((prevInstr.call.op != CALLop) && !prevInstr.branch.anneal))
2151           {
2152               BPatch_reportError(BPatchSerious, 118, "point uninstrumentable (1)");
2153               return NULL;
2154           }
2155           if(!(isV9ISA() && isUBA(prevInstr))) {
2156             fprintf(stderr, "decrement=true@%x\n", address);
2157             decrement = true;
2158           }
2159         }
2160     }
2161
2162     if ((Address)address + INSN_SIZE <
2163         func->getEffectiveAddress(proc) + func->size()) {
2164       //fprintf(stderr, "Wierd2=true@%p\n", address); 
2165         instruction nextInstr;
2166         proc->readTextSpace((char *)address + INSN_SIZE,
2167                             sizeof(instruction),
2168                             &nextInstr.raw);
2169         //fprintf(stderr, "next@%lx->%x\n", (Address)address + INSN_SIZE, nextInstr.raw);
2170         // VG(4/24/2002): If we're on v9 and the next instruction is a DCTI, 
2171         // then we cannot use a call.
2172         // TODO: There rare case where it is trap was not dealt with...
2173         if (isDCTI(nextInstr)){
2174           //fprintf(stderr, "isDCTI=true@%lx->%x\n", (Address)address + INSN_SIZE, nextInstr.raw);
2175           if(isV9ISA())
2176             dontUseCallHere=true;
2177           else {
2178             proc->readTextSpace((char *)address + 2*INSN_SIZE,
2179                                 sizeof(instruction),
2180                                 &nextInstr.raw);
2181             if(!isNopInsn(nextInstr)){
2182               fprintf(stderr, "failes @ %p\n", address);
2183               BPatch_reportError(BPatchSerious, 118,
2184                                  "point uninstrumentable (2)");
2185               return NULL;
2186             }
2187           }
2188         }
2189     }
2190
2191     if(decrement){
2192       address = (void*)((Address)address - INSN_SIZE);
2193       curr_addr -= INSN_SIZE;
2194     }
2195
2196     if (needsRelocate == true)
2197       pointFunction->setRelocatable(true);
2198
2199     instruction instr;
2200     proc->readTextSpace(address, sizeof(instruction), &instr.raw);
2201         
2202     curr_addr -= pointImageBase;
2203     //then create the instrumentation point object for the address
2204     instPoint *newpt = new instPoint(pointFunction,
2205                                      (const image*)pointImage,
2206                                      (Address &)curr_addr,
2207                                      false, // bool delayOk - ignored,
2208                                      otherPoint, dontUseCallHere);
2209
2210     pointFunction->addArbitraryPoint(newpt,proc);
2211
2212     return proc->findOrCreateBPPoint(bpfunc, newpt, BPatch_instruction);
2213 }
2214
2215 /*
2216  * BPatch_point::getDisplacedInstructions
2217  *
2218  * Returns the instructions to be relocated when instrumentation is inserted
2219  * at this point.  Returns the number of bytes taken up by these instructions.
2220  *
2221  * maxSize      The maximum number of bytes of instructions to return.
2222  * insns        A pointer to a buffer in which to return the instructions.
2223  */
2224 int BPatch_point::getDisplacedInstructions(int maxSize, void* insns)
2225 {
2226     int count = 0;
2227     instruction copyOut[10];    // I think 7 is the max - jkh 8/3/00
2228
2229     //
2230     // This function is based on what is contained in the instPoint 
2231     //    constructor in the file inst-sparc-solaris.C
2232     //
2233     if (!point->hasNoStackFrame()) {
2234         if (point->ipType == functionEntry) {
2235             copyOut[count++].raw = point->secondInstruction.raw;
2236             copyOut[count++].raw = point->thirdInstruction.raw;
2237
2238             if (point->secondIsDCTI) {
2239                 if (point->fourthIsAggregate) {
2240                     copyOut[count++].raw = point->fourthInstruction.raw;
2241                 }
2242             }
2243
2244             if (point->thirdIsDCTI) {
2245                 copyOut[count++].raw = point->fourthInstruction.raw;
2246                 if (point->fifthIsAggregate) {
2247                     copyOut[count++].raw = point->fifthInstruction.raw;
2248                 }
2249             }
2250
2251         } else if (point->ipType == callSite) {
2252
2253             copyOut[count++].raw = point->firstInstruction.raw;
2254             copyOut[count++].raw = point->secondInstruction.raw;
2255
2256             if (point->thirdIsAggregate) {
2257                 copyOut[count++].raw = point->thirdInstruction.raw;
2258             }
2259
2260         } else {
2261
2262             copyOut[count++].raw = point->firstInstruction.raw;
2263             copyOut[count++].raw = point->secondInstruction.raw;
2264         }
2265
2266     } else {
2267
2268         if (point->ipType == functionEntry) {
2269
2270             copyOut[count++].raw = point->firstInstruction.raw;
2271             copyOut[count++].raw = point->secondInstruction.raw;
2272             copyOut[count++].raw = point->thirdInstruction.raw;
2273             if (point->thirdIsDCTI) {
2274                 copyOut[count++].raw = point->fourthInstruction.raw;
2275             }
2276
2277         } else if (point->ipType == functionExit) {
2278
2279             if (point->thirdPriorIsDCTI && point->firstPriorIsAggregate) {
2280                 copyOut[count++].raw = point->thirdPriorInstruction.raw;
2281                 copyOut[count++].raw = point->secondPriorInstruction.raw;
2282             }
2283
2284             if (point->secondPriorIsDCTI) {
2285                 copyOut[count++].raw = point->secondPriorInstruction.raw;
2286             }
2287
2288             copyOut[count++].raw = point->firstPriorInstruction.raw;
2289             copyOut[count++].raw = point->firstInstruction.raw;
2290             copyOut[count++].raw = point->secondInstruction.raw;
2291
2292         } else if(point->ipType == otherPoint) {
2293
2294            copyOut[count++].raw = point->firstInstruction.raw;
2295            copyOut[count++].raw = point->secondInstruction.raw;
2296            if (point->secondIsDCTI) {
2297                copyOut[count++].raw = point->thirdInstruction.raw;
2298
2299                if (point->thirdIsAggregate) {
2300                    copyOut[count++].raw = point->fourthInstruction.raw;
2301                }
2302            }
2303
2304         } else {
2305
2306            assert(point->ipType == callSite);
2307            copyOut[count++].raw = point->firstInstruction.raw;
2308            copyOut[count++].raw = point->secondInstruction.raw;
2309            if (point->thirdIsAggregate) {
2310                copyOut[count++].raw = point->thirdInstruction.raw;
2311            }
2312         }
2313     }
2314
2315     if (count * sizeof(instruction) > (unsigned) maxSize) {
2316         return -1;
2317     } else {
2318         memcpy(insns, copyOut, count * sizeof(instruction));
2319         return count * sizeof(instruction);
2320     }
2321 }
2322
2323 #endif
2324
2325 // needed in metric.C
2326 bool instPoint::match(instPoint *p)
2327 {
2328   if (this == p)
2329     return true;
2330   
2331   // should we check anything else?
2332   if (addr == p->addr)
2333     return true;
2334   
2335   return false;
2336 }