emitInferiorRPCtrailer can now stop to make use of the result
[dyninst.git] / paradynd / 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 #include "paradynd/src/inst-sparc.h"
43
44 instruction newInstr[1024];
45 static dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
46
47 trampTemplate baseTemplate;
48 registerSpace *regSpace;
49
50 #if defined(MT_THREAD)
51 // registers 8 to 15: out registers 
52 // registers 16 to 22: local registers
53 int deadList[] = {16, 17, 18, 19, 20, 21, 22 };
54 #else
55 int deadList[] = {16, 17, 18, 19, 20, 21, 22, 23 };
56 #endif
57
58 // Constructor for the class instPoint. This one defines the 
59 // instPoints for the relocated function. Since the function reloated
60 // to the heap don't need to worry about that jump could be out of
61 // reach, the instructions to be moved are the one instruction at that
62 // point plus others if necessary(i.e. instruction in the delayed
63 // slot and maybe the aggregate instuction ).    
64 instPoint::instPoint(pdFunction *f, const instruction &instr, 
65                      const image *owner, Address &adr, bool delayOK, 
66                      instPointType pointType, Address &oldAddr)
67 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
68   callIndirect(false), callAggregate(false), callee(NULL), func(f), 
69   ipType(pointType), image_ptr(owner), firstIsConditional(false), 
70   relocated_(false)
71 {
72   assert(f->isTrapFunc() == true);  
73
74   isBranchOut = false;
75   delaySlotInsn.raw = owner->get_instruction(oldAddr+4);
76   aggregateInsn.raw = owner->get_instruction(oldAddr+8);
77
78   // If the instruction is a DCTI, the instruction in the delayed 
79   // slot is to be moved.
80   if (IS_DELAYED_INST(instr))
81     isDelayed = true;
82
83   // If this function call another function which return an aggregate
84   // value, move the aggregate instruction, too. 
85   if (ipType == callSite) {
86       if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
87           callAggregate = true;
88           adr += 8;
89           oldAddr += 8;
90       }
91   }
92
93   if (owner->isValidAddress(oldAddr-4)) {
94     instruction iplus1;
95     iplus1.raw = owner->get_instruction(oldAddr-4);
96     if (IS_DELAYED_INST(iplus1) && !delayOK) {
97       // ostrstream os(errorLine, 1024, ios::out);
98       // os << "** inst point " << func->file->fullName << "/"
99       //  << func->prettyName() << " at addr " << addr <<
100       //        " in a delay slot\n";
101       // logLine(errorLine);
102       inDelaySlot = true;
103     }
104   }
105 }
106
107 //
108 // initDefaultPointFrequencyTable - define the expected call frequency of
109 //    procedures.  Currently we just define several one shots with a
110 //    frequency of one, and provide a hook to read a file with more accurate
111 //    information.
112 //
113 void initDefaultPointFrequencyTable()
114 {
115     FILE *fp;
116     float value;
117     char name[512];
118
119     funcFrequencyTable["main"] = 1;
120     funcFrequencyTable["DYNINSTsampleValues"] = 1;
121     funcFrequencyTable[EXIT_NAME] = 1;
122
123     // try to read file.
124     fp = fopen("freq.input", "r");
125     if (!fp) {
126         return;
127     } else {
128         printf("found freq.input file\n");
129     }
130     while (!feof(fp)) {
131         fscanf(fp, "%s %f\n", name, &value);
132         funcFrequencyTable[name] = (int) value;
133         printf("adding %s %f\n", name, value);
134     }
135     fclose(fp);
136 }
137
138 /*
139  * Get an etimate of the frequency for the passed instPoint.  
140  *    This is not (always) the same as the function that contains the point.
141  * 
142  *  The function is selected as follows:
143  *
144  *  If the point is an entry or an exit return the function name.
145  *  If the point is a call and the callee can be determined, return the called
146  *     function.
147  *  else return the funcation containing the point.
148  *
149  *  WARNING: This code contins arbitray values for func frequency (both user 
150  *     and system).  This should be refined over time.
151  *
152  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
153  *      -- jkh 6/24/94
154  *
155  */
156 float getPointFrequency(instPoint *point)
157 {
158
159     pdFunction *func;
160
161     if (point->callee)
162         func = point->callee;
163     else
164         func = point->func;
165
166     if (!funcFrequencyTable.defines(func->prettyName())) {
167       if (func->isLibTag()) {
168         return(100);
169       } else {
170         // Changing this value from 250 to 100 because predictedCost was
171         // too high - naim 07/18/96
172         return(100); 
173       }
174     } else {
175       return (funcFrequencyTable[func->prettyName()]);
176     }
177 }
178
179 //
180 // return cost in cycles of executing at this point.  This is the cost
181 //   of the base tramp if it is the first at this point or 0 otherwise.
182 //
183 int getPointCost(process *proc, const instPoint *point)
184 {
185     if (proc->baseMap.defines(point)) {
186         return(0);
187     } else {
188         // 70 cycles for base tramp (worst case)
189         return(70);
190     }
191 }
192
193
194 void initATramp(trampTemplate *thisTemp, instruction *tramp)
195 {
196     instruction *temp;
197
198     // TODO - are these offset always positive?
199     thisTemp->trampTemp = (void *) tramp;
200     for (temp = tramp; temp->raw != END_TRAMP; temp++) {
201         switch (temp->raw) {
202             case LOCAL_PRE_BRANCH:
203                 thisTemp->localPreOffset = ((void*)temp - (void*)tramp);
204                 thisTemp->localPreReturnOffset = thisTemp->localPreOffset 
205                                                  + sizeof(temp->raw);
206                 break;
207             case GLOBAL_PRE_BRANCH:
208                 thisTemp->globalPreOffset = ((void*)temp - (void*)tramp);
209                 break;
210             case LOCAL_POST_BRANCH:
211                 thisTemp->localPostOffset = ((void*)temp - (void*)tramp);
212                 thisTemp->localPostReturnOffset = thisTemp->localPostOffset
213                                                   + sizeof(temp->raw);
214                 break;
215             case GLOBAL_POST_BRANCH:
216                 thisTemp->globalPostOffset = ((void*)temp - (void*)tramp);
217                 break;
218             case SKIP_PRE_INSN:
219                 thisTemp->skipPreInsOffset = ((void*)temp - (void*)tramp);
220                 break;
221             case UPDATE_COST_INSN:
222                 thisTemp->updateCostOffset = ((void*)temp - (void*)tramp);
223                 break;
224             case SKIP_POST_INSN:
225                 thisTemp->skipPostInsOffset = ((void*)temp - (void*)tramp);
226                 break;
227             case RETURN_INSN:
228                 thisTemp->returnInsOffset = ((void*)temp - (void*)tramp);
229                 break;
230             case EMULATE_INSN:
231                 thisTemp->emulateInsOffset = ((void*)temp - (void*)tramp);
232                 break;
233         }       
234     }
235
236     // Cost with the skip branchs.
237     thisTemp->cost = 14;  
238     thisTemp->prevBaseCost = 20;
239     thisTemp->postBaseCost = 22;
240     thisTemp->prevInstru = thisTemp->postInstru = false;
241     thisTemp->size = (int) temp - (int) tramp;
242 }
243
244
245 void initTramps()
246 {
247     static bool inited=false;
248
249     if (inited) return;
250     inited = true;
251
252     initATramp(&baseTemplate, (instruction *) baseTramp);
253
254     regSpace = new registerSpace(sizeof(deadList)/sizeof(int), deadList,                                         0, NULL);
255     assert(regSpace);
256 }
257
258 void generateMTpreamble(char *insn, unsigned &base, process *proc)
259 {
260   AstNode *t1,*t2,*t3,*t4,*t5;;
261   vector<AstNode *> dummy;
262   unsigned tableAddr;
263   int value; 
264   bool err;
265   reg src = -1;
266
267   /* t3=DYNINSTthreadTable[thr_self()] */
268   t1 = new AstNode("DYNINSTthreadPos", dummy);
269   value = sizeof(unsigned);
270   t4 = new AstNode(AstNode::Constant,(void *)value);
271   t2 = new AstNode(timesOp, t1, t4);
272   removeAst(t1);
273   removeAst(t4);
274
275   tableAddr = proc->findInternalAddress("DYNINSTthreadTable",true,err);
276   assert(!err);
277   t5 = new AstNode(AstNode::Constant, (void *)tableAddr);
278   t3 = new AstNode(plusOp, t2, t5);
279   removeAst(t2);
280   removeAst(t5);
281   src = t3->generateCode(proc, regSpace, insn, base, false);
282   removeAst(t3);
283   (void) emit(orOp, src, 0, REG_MT, insn, base, false);
284   regSpace->freeRegister(src);
285 }
286
287 void generateNoOp(process *proc, int addr)
288 {
289     instruction insn;
290
291     /* fill with no-op */
292     insn.raw = 0;
293     insn.branch.op = 0;
294     insn.branch.op2 = NOOPop2;
295
296     // TODO cast
297     proc->writeTextWord((caddr_t)addr, insn.raw);
298 }
299
300 void AstNode::sysFlag(instPoint *location)
301 {
302     astFlag = location->func->isTrapFunc();
303     if (loperand)
304         loperand->sysFlag(location);
305     if (roperand)
306         roperand->sysFlag(location); 
307
308     for (unsigned u = 0; u < operands.size(); u++) {
309         operands[u]->sysFlag(location);
310     }
311 }
312
313 /*
314  * change the insn at addr to be a branch to newAddr.
315  *   Used to add multiple tramps to a point.
316  */
317 void generateBranch(process *proc, unsigned fromAddr, unsigned newAddr)
318 {
319     int disp;
320     instruction insn;
321
322     disp = newAddr-fromAddr;
323     generateBranchInsn(&insn, disp);
324
325     // TODO cast
326     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
327 }
328
329 void generateCall(process *proc, unsigned fromAddr,unsigned newAddr)
330 {
331     instruction insn; 
332     generateCallInsn(&insn, fromAddr, newAddr);
333
334     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
335
336 }
337
338 void genImm(process *proc, Address fromAddr,int op, reg rs1, int immd, reg rd)
339 {
340     instruction insn;
341     genImmInsn(&insn, op, rs1, immd, rd);
342
343     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
344 }
345
346 /*
347  *  change the target of the branch at fromAddr, to be newAddr.
348  */
349 void changeBranch(process *proc, unsigned fromAddr, unsigned newAddr, 
350                   instruction originalBranch) {
351     int disp = newAddr-fromAddr;
352     instruction insn;
353     insn.raw = originalBranch.raw;
354     insn.branch.disp22 = disp >> 2;
355     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
356 }
357
358 int callsTrackedFuncP(instPoint *point)
359 {
360     if (point->callIndirect) {
361         return(true);
362     } else {
363         if (point->callee && !(point->callee->isLibTag())) {
364             return(true);
365         } else {
366             return(false);
367         }
368     }
369 }
370
371 /*
372  * return the function asociated with a point.
373  *
374  *     If the point is a funcation call, and we know the function being called,
375  *          then we use that.  Otherwise it is the function that contains the
376  *          point.
377  *  
378  *   This is done to return a better idea of which function we are using.
379  */
380 pdFunction *getFunction(instPoint *point)
381 {
382     return(point->callee ? point->callee : point->func);
383 }
384
385 bool process::emitInferiorRPCheader(void *insnPtr, unsigned &baseBytes) {
386    instruction *insn = (instruction *)insnPtr;
387    unsigned baseInstruc = baseBytes / sizeof(instruction);
388
389    genImmInsn(&insn[baseInstruc++], SAVEop3, 14, -112, 14);
390
391    baseBytes = baseInstruc * sizeof(instruction); // convert back
392    return true;
393 }
394
395
396 bool process::emitInferiorRPCtrailer(void *insnPtr, unsigned &baseBytes,
397                                      unsigned &breakOffset,
398                                      bool stopForResult,
399                                      unsigned &stopForResultOffset,
400                                      unsigned &justAfter_stopForResultOffset) {
401    // Sequence: restore, trap, illegal
402
403    instruction *insn = (instruction *)insnPtr;
404    unsigned baseInstruc = baseBytes / sizeof(instruction);
405
406    if (stopForResult) {
407       // trap insn:
408       genBreakpointTrap(&insn[baseInstruc]);
409       stopForResultOffset = baseInstruc * sizeof(instruction);
410       baseInstruc++;
411       justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
412    }
413
414    genSimpleInsn(&insn[baseInstruc++], RESTOREop3, 0, 0, 0);
415
416    // Now that the inferior has executed the 'restore' instruction, the %in and
417    // %local registers have been restored.  We mustn't modify them after this point!!
418    // (reminder: the %in and %local registers aren't saved and set with ptrace
419    //  GETREGS/SETREGS call)
420
421    // Trap instruction:
422    genBreakpointTrap(&insn[baseInstruc]); // ta 1
423    breakOffset = baseInstruc * sizeof(instruction);
424    baseInstruc++;
425
426    // And just to make sure that we don't continue from the trap:
427    genUnimplementedInsn(&insn[baseInstruc++]); // UNIMP 0
428
429    baseBytes = baseInstruc * sizeof(instruction); // convert back
430
431    return true; // success
432 }
433
434 unsigned emitImm(opCode op, reg src1, reg src2, reg dest, char *i, 
435                  unsigned &base, bool noCost)
436 {
437         instruction *insn = (instruction *) ((void*)&i[base]);
438         int op3=-1;
439         int result;
440         switch (op) {
441             // integer ops
442             case plusOp:
443                 op3 = ADDop3;
444                 genImmInsn(insn, op3, src1, src2, dest);
445                 break;
446
447             case minusOp:
448                 op3 = SUBop3;
449                 genImmInsn(insn, op3, src1, src2, dest);
450                 break;
451
452             case timesOp:
453                 op3 = SMULop3;
454                 if (isPowerOf2(src2,result) && (result<32))
455                   generateLShift(insn, src1, (reg)result, dest);           
456                 else 
457                   genImmInsn(insn, op3, src1, src2, dest);
458                 break;
459
460             case divOp:
461                 op3 = SDIVop3;
462                 if (isPowerOf2(src2,result) && (result<32))
463                   generateRShift(insn, src1, (reg)result, dest);           
464                 else 
465                   genImmInsn(insn, op3, src1, src2, dest);
466                 break;
467
468             // Bool ops
469             case orOp:
470                 op3 = ORop3;
471                 genImmInsn(insn, op3, src1, src2, dest);
472                 break;
473
474             case andOp:
475                 op3 = ANDop3;
476                 genImmInsn(insn, op3, src1, src2, dest);
477                 break;
478
479             // rel ops
480             // For a particular condition (e.g. <=) we need to use the
481             // the opposite in order to get the right value (e.g. for >=
482             // we need BLTcond) - naim
483             case eqOp:
484                 genImmRelOp(insn, BNEcond, src1, src2, dest, base);
485                 return(0);
486                 break;
487
488             case neOp:
489                 genImmRelOp(insn, BEcond, src1, src2, dest, base);
490                 return(0);
491                 break;
492
493             case lessOp:
494                 genImmRelOp(insn, BGEcond, src1, src2, dest, base);
495                 return(0);
496                 break;
497
498             case leOp:
499                 genImmRelOp(insn, BGTcond, src1, src2, dest, base);
500                 return(0);
501                 break;
502
503             case greaterOp:
504                 genImmRelOp(insn, BLEcond, src1, src2, dest, base);
505                 return(0);
506                 break;
507
508             case geOp:
509                 genImmRelOp(insn, BLTcond, src1, src2, dest, base);
510                 return(0);
511                 break;
512
513             default:
514                 reg dest2 = regSpace->allocateRegister(i, base, noCost);
515                 (void) emit(loadConstOp, src2, dest2, dest2, i, base, noCost);
516                 (void) emit(op, src1, dest2, dest, i, base, noCost);
517                 regSpace->freeRegister(dest2);
518                 return(0);
519                 break;
520         }
521         base += sizeof(instruction);
522         return(0);
523 }
524
525 //
526 // All values based on Cypress0 && Cypress1 implementations as documented in
527 //   SPARC v.8 manual p. 291
528 //
529 int getInsnCost(opCode op)
530 {
531     if (op == loadConstOp) {
532         return(1);
533     } else if (op ==  loadOp) {
534         // sethi + load single
535         return(1+1);
536     } else if (op ==  loadIndirOp) {
537         return(1);
538     } else if (op ==  storeOp) {
539         // sethi + store single
540         // return(1+3); 
541         // for SS-5 ?
542         return(1+2); 
543     } else if (op ==  storeIndirOp) {
544         return(2); 
545     } else if (op ==  ifOp) {
546         // subcc
547         // be
548         // nop
549         return(1+1+1);
550     } else if (op ==  callOp) {
551         int count = 0;
552
553         // mov src1, %o0
554         count += 1;
555
556         // mov src2, %o1
557         count += 1;
558
559         // clr i2
560         count += 1;
561
562         // clr i3
563         count += 1;
564
565         // sethi
566         count += 1;
567
568         // jmpl
569         count += 1;
570
571         // noop
572         count += 1;
573
574         return(count);
575     } else if (op ==  updateCostOp) {
576         // sethi %hi(obsCost), %l0
577         // ld [%lo + %lo(obsCost)], %l1
578         // add %l1, <cost>, %l1
579         // st %l1, [%lo + %lo(obsCost)]
580         return(1+2+1+3);
581     } else if (op ==  trampPreamble) {
582         return(0);
583     } else if (op ==  trampTrailer) {
584         // retl
585         return(2);
586     } else if (op == noOp) {
587         // noop
588         return(1);
589     } else if (op == getParamOp) {
590         return(0);
591     } else {
592         switch (op) {
593             // rel ops
594             case eqOp:
595             case neOp:
596             case lessOp:
597             case leOp:
598             case greaterOp:
599             case geOp:
600                 // bne -- assume taken
601                 return(2);
602                 break;
603             default:
604                 return(1);
605                 break;
606         }
607     }
608 }
609
610 bool isReturnInsn(const image *owner, Address adr, bool &lastOne)
611 {
612     instruction instr;
613     
614     instr.raw = owner->get_instruction(adr);
615     lastOne = false;
616
617     if (isInsnType(instr, RETmask, RETmatch) ||
618         isInsnType(instr, RETLmask, RETLmatch)) {
619         if ((instr.resti.simm13 != 8) && (instr.resti.simm13 != 12)) {
620             logLine("*** FATAL Error:");
621             sprintf(errorLine, " unsupported return\n");
622             logLine(errorLine);
623             showErrorCallback(55, "");
624             P_abort();
625         }
626         return true;
627     }
628     return false;
629 }
630
631
632 //
633 // called to relocate a function: when a request is made to instrument
634 // a system call we relocate the entire function into the heap
635 //
636 bool pdFunction::relocateFunction(process *proc, 
637                                  const instPoint *&location,
638                                  vector<instruction> &extra_instrs) {
639
640     relocatedFuncInfo *reloc_info = 0;
641     // check to see if this process already has a relocation record 
642     // for this function
643     for(u_int i=0; i < relocatedByProcess.size(); i++){
644         if((relocatedByProcess[i])->getProcess() == proc){
645             reloc_info = relocatedByProcess[i];
646         }
647     }
648     u_int ret = 0;
649     if(!reloc_info){
650         //Allocate the heap for the function to be relocated
651         ret = inferiorMalloc(proc, size()+32, textHeap);
652         if(!ret)  return false;
653         reloc_info = new relocatedFuncInfo(proc,ret);
654         relocatedByProcess += reloc_info;
655     }
656     if(!(findNewInstPoints(location->image_ptr, location, ret, proc, 
657                            extra_instrs, reloc_info))){
658     }
659     proc->writeDataSpace((caddr_t)ret, size()+32,(caddr_t) newInstr);
660     return true;
661 }
662
663 // modifyInstPoint: if the function associated with the process was 
664 // recently relocated, then the instPoint may have the old pre-relocated
665 // address (this can occur because we are getting instPoints in mdl routines 
666 // and passing these to routines that do the instrumentation, it would
667 // be better to let the routines that do the instrumenting find the points)
668 void pdFunction::modifyInstPoint(const instPoint *&location,process *proc)
669 {
670
671     if(relocatable_ && !(location->relocated_)){
672         for(u_int i=0; i < relocatedByProcess.size(); i++){
673             if((relocatedByProcess[i])->getProcess() == proc){
674                 if(location->ipType == functionEntry){
675                     const instPoint *new_entry = 
676                                 (relocatedByProcess[i])->funcEntry();
677                     location = new_entry;
678                 } 
679                 else if(location->ipType == functionExit){
680                     const vector<instPoint *> new_returns = 
681                         (relocatedByProcess[i])->funcReturns(); 
682                     assert(funcReturns.size() == new_returns.size());
683                     for(u_int j=0; j < new_returns.size(); j++){
684                         if(funcReturns[j] == location){
685                             location = (new_returns[j]);
686                             break;
687                         }
688                     }
689                 }
690                 else {
691                     const vector<instPoint *> new_calls = 
692                                 (relocatedByProcess[i])->funcCallSites(); 
693                     assert(calls.size() == new_calls.size());
694                     for(u_int j=0; j < new_calls.size(); j++){
695                         if(calls[j] == location){
696                             location = (new_calls[j]);
697                             break;
698                         }
699                     }
700
701                 }
702                 break;
703     } } }
704 }
705
706
707 // The exact semantics of the heap are processor specific.
708 //
709 // find all DYNINST symbols that are data symbols
710 //
711 bool image::heapIsOk(const vector<sym_data> &find_us) {
712   Symbol sym;
713
714   for (unsigned i=0; i<find_us.size(); i++) {
715     const string &str = find_us[i].name;
716     if (!linkedFile.get_symbol(str, sym)) {
717       string str1 = string("_") + str.string_of();
718       if (!linkedFile.get_symbol(str1, sym) && find_us[i].must_find) {
719         string msg;
720         msg = string("Cannot find ") + str + string(". Exiting");
721         statusLine(msg.string_of());
722         showErrorCallback(50, msg);
723         return false;
724       }
725     }
726     addInternalSymbol(str, sym.addr());
727   }
728
729 //  string ghb = GLOBAL_HEAP_BASE;
730 //  if (!linkedFile.get_symbol(ghb, sym)) {
731 //    ghb = U_GLOBAL_HEAP_BASE;
732 //    if (!linkedFile.get_symbol(ghb, sym)) {
733 //      string msg;
734 //      msg = string("Cannot find ") + ghb + string(". Exiting");
735 //      statusLine(msg.string_of());
736 //      showErrorCallback(50, msg);
737 //      return false;
738 //    }
739 //  }
740 //  Address instHeapEnd = sym.addr();
741 //  addInternalSymbol(ghb, instHeapEnd);
742
743   string ihb = INFERIOR_HEAP_BASE;
744   if (!linkedFile.get_symbol(ihb, sym)) {
745     ihb = UINFERIOR_HEAP_BASE;
746     if (!linkedFile.get_symbol(ihb, sym)) {
747       string msg;
748       msg = string("Cannot find ") + ihb + string(". Cannot use this application");
749       statusLine(msg.string_of());
750       showErrorCallback(50, msg);
751       return false;
752     }
753   }
754   Address curr = sym.addr();
755   addInternalSymbol(ihb, curr);
756
757   // Check that we can patch up user code to jump to our base trampolines
758   // (Perhaps this code is no longer needed for sparc platforms, since we use full
759   // 32-bit jumps)
760   const Address instHeapStart = curr;
761   const Address instHeapEnd = instHeapStart + SYN_INST_BUF_SIZE - 1;
762
763   if (instHeapEnd > getMaxBranch3Insn()) {
764     logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
765     sprintf(errorLine, "    heap starts at %x and ends at %x; maxbranch=%x\n",
766             instHeapStart, instHeapEnd, getMaxBranch3Insn());
767     logLine(errorLine);
768     return false;
769   }
770
771   return true;
772 }
773
774 // Certain registers (i0-i7 on a SPARC) may be available to be read
775 // as an operand, but cannot be written.
776 bool registerSpace::readOnlyRegister(reg reg_number) {
777   if ((reg_number < 16) || (reg_number > 23))
778       return true;
779   else
780       return false;
781 }
782
783 bool returnInstance::checkReturnInstance(const vector<Address> adr,u_int &index)
784 {
785     for(u_int i=0; i < adr.size(); i++){
786         index = i;
787         if ((adr[i] > addr_) && ( adr[i] <= addr_+size_)){
788             return false;
789         }
790     }
791     return true;
792 }
793
794 void returnInstance::installReturnInstance(process *proc) {
795     proc->writeTextSpace((caddr_t)addr_, instSeqSize, 
796                          (caddr_t) instructionSeq); 
797 }
798
799 void generateBreakPoint(instruction &insn) {
800     insn.raw = BREAK_POINT_INSN;
801 }
802
803 void returnInstance::addToReturnWaitingList(Address pc, process *proc) {
804
805     // if there already is a TRAP set at this pc for this process don't
806     // generate a trap instruction again...you will get the wrong original
807     // instruction if you do a readDataSpace
808     bool found = false;
809     instruction insn;
810     for(u_int i=0; i < instWList.size(); i++){
811          if(((instWList[i])->pc_ == pc)&&((instWList[i])->which_proc == proc)){
812              found = true;
813              insn = (instWList[i])->relocatedInstruction;
814              break;
815     } }
816     if(!found) {
817         instruction insnTrap;
818         generateBreakPoint(insnTrap);
819         proc->readDataSpace((caddr_t)pc, sizeof(insn), (char *)&insn, true);
820         proc->writeTextSpace((caddr_t)pc, sizeof(insnTrap), (caddr_t)&insnTrap);
821     }
822     else {
823     }
824
825     instWaitingList *instW = new instWaitingList(instructionSeq,instSeqSize,
826                                      addr_,pc,insn,pc,proc);
827     instWList += instW;
828
829 }
830
831
832 bool doNotOverflow(int value)
833 {
834   // we are assuming that we have 13 bits to store the immediate operand.
835   if ( (value <= 16383) && (value >= -16384) ) return(true);
836   else return(false);
837 }
838
839 void instWaitingList::cleanUp(process *proc, Address pc) {
840     proc->writeTextSpace((caddr_t)pc, sizeof(relocatedInstruction),
841                     (caddr_t)&relocatedInstruction);
842     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t)instructionSeq);
843 }