initial dyninstAPI commit for code coverage
[dyninst.git] / dyninstAPI / src / inst.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.C,v 1.83 2001/09/07 21:15:09 tikir Exp $
43 // Code to install and remove instrumentation from a running process.
44
45 #include <assert.h>
46 //#include <sys/signal.h>
47 //#include <sys/param.h>
48
49 #include "dyninstAPI/src/symtab.h"
50 #include "dyninstAPI/src/process.h"
51 #include "dyninstAPI/src/inst.h"
52 #include "dyninstAPI/src/instP.h"
53 #include "dyninstAPI/src/ast.h"
54 #include "dyninstAPI/src/util.h"
55 #include "dyninstAPI/src/stats.h"
56 #include "dyninstAPI/src/showerror.h"
57 #include "dyninstAPI/src/instPoint.h"
58 #ifndef BPATCH_LIBRARY
59 #include "paradynd/src/init.h"
60 #endif
61
62 dictionary_hash <string, unsigned> primitiveCosts(string::hash);
63
64 #if defined(rs6000_ibm_aix4_1)
65   extern void resetBRL(process *p, Address loc, unsigned val); //inst-power.C
66   extern void resetBR( process *p, Address loc);               //inst-power.C
67 #endif
68
69 #ifndef BPATCH_LIBRARY
70 static unsigned function_base_ptr_hash(function_base *const &f) {
71   function_base *ptr = f;
72   unsigned l = (unsigned)(Address)ptr;
73   return addrHash4(l); 
74 }
75
76 // Fill in <callees> with list of statically determined callees of
77 //  function.  
78 // Uses process specific info to try to fill in the unbound call
79 //  destinations through PLT entries.  Note that when it determines
80 //  the destination of a call through the PLT, it puts that
81 //  call destination into <callees>, but DOES NOT fill in the
82 //  call destination in the function's instPoint.  This is because
83 //  the (through PLT) binding is process specific.  It is possible, 
84 //  for example, that one could have 2 processes, both sharing the
85 //  same a.out image, but which are linked with different versions of
86 //  the same shared library (or with the same shared libraries in 
87 //  a different order), in which case the pd_Function data would be 
88 //  shared between the processes, but the (through-PLT) call 
89 //  destinations might NOT be the same.
90 // Should filter out any duplicates in this callees list....
91
92 bool pd_Function::getStaticCallees(process *proc,
93                                    vector <pd_Function *>&callees) {
94     unsigned u;
95     function_base *f;
96     bool found;
97     
98     dictionary_hash<function_base *, function_base *> 
99       filter(function_base_ptr_hash);
100     
101     callees.resize(0);
102
103     // possible algorithm : iterate over calls (vector of instPoint *)
104     //   for each elem : use iPgetCallee() to get statically determined
105     //   callee....
106     for(u=0;u<calls.size();u++) {
107       //this call to iPgetCallee is platform specific
108       f = const_cast<function_base *>(calls[u]->iPgetCallee());
109       
110       if (f == NULL) {
111         //cerr << " unkown call destination";
112         found = proc->findCallee((*calls[u]), f);
113         if (f != NULL) {
114           //cerr << " found w/ process specific PLT info" << endl;
115         } else {
116           //cerr << " not found in PLT info" << endl;
117         }
118       } else if (filter.defines(f)) {
119         //cerr << " call destination " << f->prettyName().string_of() << 
120         //" already seen by filer" << endl;
121       }
122       
123       if (f != NULL && !filter.defines(f)) {
124       callees += (pd_Function *)f;
125         filter[f] = f;
126         }
127       }
128     return true;
129 }
130 #endif
131
132 // get the address of the branch from the base to the minitramp
133 Address getBaseBranchAddr(process *, instInstance *inst)
134 {
135     Address fromAddr;
136
137     fromAddr = inst->baseInstance->baseAddr;
138     if (inst->when == callPreInsn) {
139         fromAddr += inst->baseInstance->localPreOffset;
140     } else {
141         fromAddr += inst->baseInstance->localPostOffset;
142     }
143     return(fromAddr);
144 }
145
146 // get the address in the base tramp where the minitramp should return to
147 Address getBaseReturnAddr(process *, instInstance *inst) {
148     Address returnAddr = inst->baseInstance->baseAddr;
149     if (inst->when == callPreInsn) {
150       returnAddr += inst->baseInstance->localPreReturnOffset;
151     } else {
152       returnAddr += inst->baseInstance->localPostReturnOffset;
153     }
154     return(returnAddr);
155 }
156
157 // clear the basetramp jump to a minitramp
158 void clearBaseBranch(process *proc, instInstance *inst)
159 {
160     Address addr;
161
162     addr = inst->baseInstance->baseAddr;
163     if (inst->when == callPreInsn) {
164         addr += inst->baseInstance->localPreOffset;
165     } else {
166         addr += inst->baseInstance->localPostOffset;
167     }
168     // stupid kludge because the instPoint class is defined in a .C file
169     // so we can't access any of its member functions
170 #if defined(rs6000_ibm_aix4_1)
171     resetBRL(proc, addr, 0);
172 #else
173     generateNoOp(proc, addr);
174 #endif
175     // If there is no instrumentation at this point, skip.
176     Address fromAddr, toAddr;
177
178     int trampCost;
179     if (inst->when == callPreInsn) {
180       fromAddr = inst->baseInstance->baseAddr + 
181                  inst->baseInstance->skipPreInsOffset;
182       toAddr = inst->baseInstance->baseAddr + 
183 #if defined(rs6000_ibm_aix4_1) || defined(alpha_dec_osf4_0)
184                inst->baseInstance->emulateInsOffset;
185 #else
186                inst->baseInstance->updateCostOffset;
187 #endif
188       inst->baseInstance->prevInstru = false;
189       trampCost = -(inst->baseInstance->prevBaseCost);
190     }
191     else {
192       fromAddr = inst->baseInstance->baseAddr + 
193                  inst->baseInstance->skipPostInsOffset; 
194       toAddr = inst->baseInstance->baseAddr + 
195                inst->baseInstance->returnInsOffset;
196       inst->baseInstance->postInstru = false;
197       trampCost = -(inst->baseInstance->postBaseCost);
198     }
199     inst->baseInstance->updateTrampCost(proc, trampCost);
200     generateBranch(proc,fromAddr,toAddr);
201 #if defined(MT_DEBUG)
202     sprintf(errorLine,"generating branch from address 0x%lx to address 0x%lx"
203         " - CLEAR\n",fromAddr,toAddr);
204     logLine(errorLine);
205 #endif
206 }
207
208 // implicit assumption that tramps generate to less than 64K bytes!!!
209 static int insn[65536/sizeof(int)]; // Made into array of int so it would be
210                                     // aligned correctly on platforms that
211                                     // need it to be (like SPARC) - BRB
212
213 static dictionary_hash<const instPoint*, point*> activePoints(ipHash);
214
215 vector<instWaitingList *> instWList;
216
217 // Shouldn't this be a member fn of class process?
218 instInstance *addInstFunc(process *proc, instPoint *&location,
219                           AstNode *&ast, // ast may change (sysFlag stuff)
220                           callWhen when, callOrder order,
221                           bool noCost,
222                           bool trampRecursiveDesired)
223 {
224     returnInstance *retInstance = NULL;
225        // describes how to jmp to the base tramp
226
227     bool deferred = false;  // dummy variable
228     instInstance *inst = addInstFunc(proc, location, ast, when, order,
229                                      noCost, retInstance, deferred,
230                                      trampRecursiveDesired);
231     if (retInstance) {
232        // Looking at the code for the other addInstFunc below, it seems that
233        // this will always be true...retInstance is never NULL.
234
235        retInstance-> installReturnInstance(proc);
236        // writes to addr space
237     }
238
239     // delete retInstance; 
240     // safe if NULL (may have been alloc'd by findAndInstallBaseTramp)
241
242     return inst;
243 }
244
245 // Shouldn't this be a member fn of class process?
246 // The trampRecursiveDesired flag decides which base tramp is used,
247 // _if_ a base tramp is installed. If there is already a base tramp
248 // at the instrumentation point, the flag is ignored.
249 instInstance *addInstFunc(process *proc, instPoint *&location,
250                           AstNode *&ast, // the ast could be changed 
251                           callWhen when, callOrder order,
252                           bool noCost,
253                           returnInstance *&retInstance, 
254                           bool &deferred,
255                           bool trampRecursiveDesired = false)
256 {
257
258     // retInstance gets filled in with info on how to jmp to the base tramp
259     // (the call to findAndInstallBaseTramp doesn't do that)
260
261     assert(proc && location);
262     initTramps();
263
264     instInstance *ret = new instInstance;
265     assert(ret);
266
267     ret->proc = proc;
268     ret->baseInstance = findAndInstallBaseTramp(proc, location, retInstance,
269                                                 trampRecursiveDesired, noCost, 
270                                                 deferred);
271
272     if (!ret->baseInstance)
273        return(NULL);
274
275 #if defined(MT_DEBUG_ON)
276     sprintf(errorLine,"==>BaseTramp is in 0x%lx\n",ret->baseInstance->baseAddr);
277     logLine(errorLine);
278 #endif
279
280     /* check if there are other inst points at this location. for this process
281        at the same pre/post mode */
282     instInstance *firstAtPoint = NULL;
283     instInstance *lastAtPoint = NULL;
284
285     point *thePoint;
286     if (!activePoints.find((const instPoint *)location, thePoint)) {
287        thePoint = new point;
288        activePoints[(const instPoint*)location] = thePoint;
289     }
290     
291 //    point *thePoint;
292 //    if (!activePoints.defines((const instPoint *)location)) {
293 //      thePoint = new point;
294 //      activePoints[(const instPoint*)location] = thePoint;
295 //    } else
296 //      thePoint = activePoints[(const instPoint*)location];
297 //    assert(thePoint);
298
299     instInstance *next;
300     for (next = thePoint->inst; next; next = next->next) {
301         if ((next->proc == proc) && (next->when == when)) {
302             if (!next->nextAtPoint) lastAtPoint = next;
303             if (!next->prevAtPoint) firstAtPoint = next;
304         }
305     }
306
307     // must do this before findAndInstallBaseTramp, puts the tramp in to
308     // get the correct cost.
309     // int trampCost = getPointCost(proc, (const instPoint*)location);
310
311     // 
312     // Generate the code for this (mini-)tramp.
313     //
314     // return value is offset of return stmnt.
315     //
316
317 #if defined(MEMSET)
318     // clear out old stuff - for debugging.
319     memset(insn, 0x00, 65536);
320 #endif
321
322     Address count = 0;
323
324 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)     
325     ast->sysFlag((instPoint*)location);  
326
327     // If the return value is in the case of compiler optimization,
328     // modify the ast node tree to insert an instruction to get the 
329     // return the value
330     extern bool processOptimaRet(instPoint *location, AstNode *&ast);
331     bool isOpt = processOptimaRet(location, ast);
332 #endif
333
334     int trampCost = 0;
335     ret->returnAddr = ast->generateTramp(proc, (char *)insn, count, trampCost, noCost);
336
337 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
338     // The ast node might be shared, so remove the changes made to
339     // ast node tree  
340     if (isOpt)
341         ast->optRetVal(NULL); 
342 #endif
343
344     if (!noCost) {
345         ret->cost = trampCost; 
346         ret->baseInstance->updateTrampCost(proc, trampCost);
347     }
348 #if defined(rs6000_ibm_aix4_1)
349     // We use the data heap on AIX because it is unlimited, unlike
350     // the textHeap. The text heap is allocated from spare parts of 
351     // pages, and as such can run out. Since minitramps can be arbitrarily
352     // far from the base tramp (link register branching), but only a 
353     // single jump from each other, we cluster them in the dataHeap.
354     // Note for future reference: shouldn't this near_ be the address
355     // of the previous/next minitramp instead of the base tramp?
356     inferiorHeapType htype = dataHeap;
357 #else
358     inferiorHeapType htype = (proc->splitHeaps) ? (textHeap) : (anyHeap);
359 #endif
360     Address near_ = ret->baseInstance->baseAddr;
361     bool err = false;
362     ret->trampBase = inferiorMalloc(proc, count, htype, near_, &err);
363
364     if (err) return NULL;
365     assert(ret->trampBase);
366
367     if (!ret->trampBase) return(NULL);
368     trampBytes += count;
369     ret->returnAddr += ret->trampBase;
370
371     ret->when = when;
372     ret->location = (instPoint*)location;
373
374     ret->next = thePoint->inst;
375     ret->prev = NULL;
376     if (thePoint->inst) thePoint->inst->prev = ret;
377     thePoint->inst = ret;
378
379     /*
380      * Now make the call to actually put the code in place.
381      *
382      */
383     installTramp(ret, (char *)insn, count); // install mini-tramp into inferior addr space
384
385     if (!lastAtPoint) {
386         // jump from the base tramp to the minitramp
387         Address fromAddr = getBaseBranchAddr(proc, ret);
388 #if defined(rs6000_ibm_aix4_1)
389         resetBRL(proc, fromAddr, ret->trampBase);
390 #else
391         generateBranch(proc, fromAddr, ret->trampBase);
392 #endif
393
394         // jump from the minitramp back to the basetramp
395 #if defined(rs6000_ibm_aix4_1)
396         resetBR(proc, ret->returnAddr);
397 #else
398         Address toAddr = getBaseReturnAddr(proc, ret);
399         generateBranch(proc, ret->returnAddr, toAddr);
400 #endif
401
402         // just activated this slot.
403         //activeSlots->value += 1.0;
404     } else if (order == orderLastAtPoint) {
405         /* patch previous tramp to call us rather than return */
406         generateBranch(proc,lastAtPoint->returnAddr,ret->trampBase);
407         lastAtPoint->nextAtPoint = ret;
408         ret->prevAtPoint = lastAtPoint;
409         
410         // jump from the minitramp to the basetramp
411 #if defined(rs6000_ibm_aix4_1)
412         resetBR(proc, ret->returnAddr);
413 #else
414         Address toAddr = getBaseReturnAddr(proc, ret);
415         generateBranch(proc, ret->returnAddr, toAddr);
416 #endif
417     } else {
418         /* first at point */
419         firstAtPoint->prevAtPoint = ret;
420         ret->nextAtPoint = firstAtPoint;
421
422         /* branch to the old first one */
423         generateBranch(proc, ret->returnAddr, firstAtPoint->trampBase);
424
425         /* base tramp branches to us */
426         Address fromAddr = getBaseBranchAddr(proc, ret);
427 #if defined(rs6000_ibm_aix4_1)
428         resetBRL(proc, fromAddr, ret->trampBase);
429 #else
430         generateBranch(proc, fromAddr, ret->trampBase);
431 #endif
432     }
433
434     return(ret);
435 }
436
437 bool trampTemplate::inBasetramp( Address addr ) {
438         return addr >= baseAddr && addr < ( baseAddr + size );
439 }
440
441
442 bool trampTemplate::inSavedRegion( Address addr ) {
443         if( !inBasetramp( addr ) )
444                 return false;
445         addr -= baseAddr;
446         return ( addr > (Address)savePreInsOffset && addr <= (Address)restorePreInsOffset )
447                 || ( addr > (Address)savePostInsOffset && addr <= (Address)restorePostInsOffset );
448 }
449
450
451 instPoint * findInstPointFromAddress(const process *proc, Address addr) {
452     unsigned u;
453
454     vector<const instPoint*> ips;
455     vector<trampTemplate*> bts;
456     ips = proc->baseMap.keys();
457     bts = proc->baseMap.values();
458     assert( ips.size() == bts.size() );
459     for( u = 0; u < bts.size(); ++u ) {
460         if( bts[u]->inBasetramp( addr ) )
461         {
462             return const_cast<instPoint*>( ips[u] );
463         }
464     }
465
466     vector<point*> allPoints = activePoints.values();
467
468     for( u = 0; u < allPoints.size(); ++u ) {
469         for( instInstance *inst = allPoints[u]->inst; inst; inst = inst->next ) {
470             if( inst->proc == proc ) {
471                 if( ( inst->trampBase <= addr && inst->returnAddr >= addr )
472                     || inst->baseInstance->inBasetramp( addr ) )
473                 {
474                     return inst->location;
475                 }
476             }
477         }
478     }
479     return NULL;
480 }
481
482 trampTemplate * findBaseTramp( const instPoint * ip, const process *proc ) {
483     if( activePoints.defines( ip ) ) {
484         point *p = activePoints[ ip ];
485         assert( p );
486         for( instInstance *ii = p->inst; ii; ii = ii->next )
487             if( ii->proc == proc )
488                 return ii->baseInstance;
489     }
490     return NULL;
491 }
492
493 instInstance * findMiniTramps( const instPoint * ip ) {
494     if( activePoints.defines( ip ) ) {
495         point *p = activePoints[ ip ];
496         assert( p );
497         return p->inst;
498     }
499     return NULL;
500 }
501
502
503 // TODO: this functionality overlaps with "findInstPointFromAddress()"
504 pd_Function *findAddressInFuncsAndTramps(process *p, Address addr,
505                                          instPoint *&ip,
506                                          trampTemplate *&bt,
507                                          instInstance *&mt)
508 {
509   unsigned n;
510
511   // default return values
512   ip = NULL;
513   bt = NULL;
514   mt = NULL;
515
516   // look for address in user code
517   function_base *fn = p->findFuncByAddr(addr);
518   if (fn != NULL) return (pd_Function *)fn;
519
520   // look for address in basetramps ("baseMap")
521   vector<const instPoint *> ips = p->baseMap.keys();
522   vector<trampTemplate *> bts = p->baseMap.values();
523   n = ips.size();
524   assert(n == bts.size());
525   for (unsigned i = 0; i < n; i++) {
526     if (bts[i]->inBasetramp(addr)) {
527       ip = const_cast<instPoint *>(ips[i]);
528       bt = bts[i];
529       return (pd_Function*)const_cast<function_base*>(ip->iPgetFunction());
530     }
531   }
532     
533   // look for address in minitramps ("activePoints")
534   vector<point *> pts = activePoints.values();
535   instInstance *inst;
536   n = pts.size();
537   for (unsigned i2 = 0; i2 < n; i2++) {
538     inst = pts[i2]->inst;
539     for ( ; inst != NULL; inst = inst->next) {
540       if (inst->proc == p) {
541         if (addr >= inst->trampBase && addr <= inst->returnAddr) {
542           ip = inst->location;
543           mt = inst;
544           return (pd_Function*)const_cast<function_base*>(ip->iPgetFunction());
545         } else if (inst->baseInstance->inBasetramp(addr)) {
546           // the basetramp search should have turned this up
547           assert(0);
548         }
549       }
550     }
551   }
552
553   return NULL;
554 }
555
556
557 //
558 // copyInstInstances: called when a process we are tracing forks.
559 // The child will have a copy of all instrumentation in the parent, so we
560 // must duplicate all instInstances of the parent for the child.
561 // 
562 // On return, for each active instInstance parentInst in the parent
563 // instInstanceMapping[parentInst] will be the corresponding instInstance for the
564 // child.
565 //
566
567 void getAllInstInstancesForProcess(const process *proc,
568                                    vector<instInstance*> &result) {
569     vector<point*> allPoints = activePoints.values();
570  
571     // find all instInstances of the parent process
572     for (unsigned u = 0; u < allPoints.size(); u++) {
573       for (instInstance *inst = allPoints[u]->inst; inst; inst = inst->next) {
574         if (inst->proc == proc)
575           result.push_back(inst);
576       }
577     }
578 }
579
580 void copyInstInstances(const process *parent, const process *child, 
581             dictionary_hash<instInstance *, instInstance *> &instInstanceMapping)
582 {
583     vector<instInstance*> instsToCopy;
584     getAllInstInstancesForProcess(parent, instsToCopy);
585  
586     // duplicate the parent instance for the child, and define instMapping
587     vector<instInstance *>newInsts;
588     for (unsigned u1 = 0; u1 < instsToCopy.size(); u1++) {
589       instInstance *old = instsToCopy[u1];
590       instInstance *newInst = new instInstance;
591       newInst->proc = const_cast<process *>(child);
592       newInst->when = old->when;
593       newInst->location = old->location;
594       newInst->trampBase = old->trampBase;
595       newInst->returnAddr = old->returnAddr;
596       newInst->baseInstance = old->baseInstance;
597       newInst->cost = old->cost;
598       instInstanceMapping[old] = newInst;
599       newInsts.push_back(newInst);
600     }
601
602     // update nextAtPoint and prevAtPoint
603     for (unsigned u2 = 0; u2 < newInsts.size(); u2++) {
604       instInstance *newInst = newInsts[u2];
605       instInstance *old = instsToCopy[u2];
606       newInst->nextAtPoint = instInstanceMapping[old->nextAtPoint];
607       newInst->prevAtPoint = instInstanceMapping[old->prevAtPoint];
608
609       assert(activePoints.defines(newInst->location));
610       point *thePoint = activePoints[newInst->location];
611       newInst->next = thePoint->inst;
612       newInst->prev = NULL;
613       if (thePoint->inst) thePoint->inst->prev = newInst;
614       thePoint->inst = newInst;
615     }
616 }
617
618 // This procedure assumes that any mini-tramp for an inst request could refer 
619 // to any data pointer for that request. A more complex analysis could check 
620 // what data pointers each mini-tramp really used, but I don't think it is 
621 // worth the trouble.
622 //
623 vector<Address> getAllTrampsAtPoint(instInstance *instance)
624 {
625     vector<Address> pointsToCheck;
626     instInstance *start;
627     instInstance *next;
628     point *thePoint;
629
630     if (instance) {
631       if (activePoints.defines(instance->location)) {
632         thePoint = activePoints[instance->location];
633         start = thePoint->inst;
634         // Base tramp
635         pointsToCheck.push_back(start->baseInstance->baseAddr); 
636         pointsToCheck.push_back(start->trampBase);
637         // All mini-tramps at this point
638         for (next = start->next; next; next = next->next) {
639           if ((next->location == instance->location) && 
640               (next->proc == instance->proc) &&
641               (next->when == instance->when)) {
642               if (next != instance) {
643                 pointsToCheck.push_back(next->trampBase);
644                 //pointsToCheck += start->trampBase;
645               }
646           }
647         }
648       }
649     }
650     return(pointsToCheck);
651 }
652
653 /*
654  * The tramps are chained together left to right, so we need to find the
655  *    tramps to the left anf right of the one to delete, and then patch the
656  *    call from the left one to the old to call the right one.
657  *    Also we need to patch the return from the right one to go to the left
658  *    one.
659  *
660  */
661 void deleteInst(instInstance *old, const vector<Address> &pointsToCheck)
662 {
663     point *thePoint;
664     instInstance *lag;
665     instInstance *left;
666     instInstance *right;
667     instInstance *othersAtPoint;
668
669     if (!old) {
670       // logLine("Internal error in inst.C: instInstance pointer \"old\" is NULL\n");
671       return;
672     }
673
674     /* check if there are other inst points at this location. */
675     othersAtPoint = NULL;
676     left = right = NULL;
677
678     if (!activePoints.defines(old->location)) {
679 #if !defined(MT_THREAD)
680       abort();
681 #else
682       cerr << "in inst.C: location is NOT defined in activePoints" << endl;
683       return ;
684 #endif
685     }
686     thePoint = activePoints[old->location];
687
688     for (lag= thePoint->inst; lag; lag = lag->next) {
689         if ((lag->location == old->location) && 
690             (lag->proc == old->proc) &&
691             (lag->when == old->when)) {
692             if (lag != old) {
693                 othersAtPoint = lag;
694                 left = old->prevAtPoint;
695                 right = old->nextAtPoint;
696                 assert(right || left);
697             }
698         }
699     }
700
701   if (old->proc->status() != exited) {
702     if (!othersAtPoint) {
703         clearBaseBranch(old->proc, old);
704         //activeSlots->value -= 1.0;
705     } else {
706         if (left) {
707             if (right) {
708                 /* set left's return insn to branch to tramp to the right */
709                 generateBranch(old->proc, left->returnAddr, right->trampBase);
710             } else {
711                 /* branch back to the correct point in the base tramp */
712 #if defined(rs6000_ibm_aix4_1)
713                 resetBR(old->proc, left->returnAddr);
714 #else
715                 Address toAddr = getBaseReturnAddr(old->proc, old);
716                 generateBranch(old->proc, left->returnAddr, toAddr);
717 #endif
718             }
719         } else {
720             /* old is first one make code call right tramp */
721             int fromAddr;
722             fromAddr = getBaseBranchAddr(old->proc, right);
723 #if defined(rs6000_ibm_aix4_1)
724             resetBRL(old->proc, fromAddr, right->trampBase);
725 #else
726             generateBranch(old->proc, fromAddr, right->trampBase);
727 #endif
728         }
729     }
730
731     vector< vector<Address> > tmp;
732     tmp.push_back((vector<Address>) pointsToCheck);
733
734 #ifdef FREEDEBUG1
735     sprintf(errorLine,"***** (pid=%d) In inst.C, calling inferiorFree, "
736             "pointer=0x%lx\n",old->proc->pid,old->trampBase);
737     logLine(errorLine);
738 #endif
739     inferiorFree(old->proc, old->trampBase, tmp);
740   }
741
742     /* remove old from atPoint linked list */
743     if (right) right->prevAtPoint = left;
744     if (left) left->nextAtPoint = right;
745
746     /* remove from doubly linked list for all insts */
747     if (old->prev) {
748         lag = old->prev;
749         lag->next = old->next;
750         if (old->next) old->next->prev = lag;
751     } else {
752         thePoint->inst = old->next;
753         if (old->next) old->next->prev = NULL;
754     }
755     int trampCost = 0-old->cost;
756     old->baseInstance->updateTrampCost(old->proc, trampCost);
757
758     // If the thePoint->inst value is NULL then there is no more
759     // instrumenttation instances left for this point.
760
761     if(BPatch::bpatch->baseTrampDeletion() &&
762        !thePoint->inst)
763     {
764         extern bool deleteBaseTramp(process*,instPoint*,instInstance*);
765         if(deleteBaseTramp(old->proc,old->location,old)){
766                 activePoints.undef((const instPoint*)(old->location));
767                 old->proc->baseMap.undef((const instPoint*)(old->location));
768                 delete[] old->baseInstance->trampTemp;
769                 delete old->baseInstance;
770         }
771     }
772
773     delete old;
774
775     //free(old);
776 }
777
778 //
779 // Routine that checks whether a particular address is valid before deleting
780 // the corresponding instrumentation associated to it.
781 //
782 bool isValidAddress(process * , Address )
783 {
784   bool result=true;
785   //
786   // Note: It seems that it is not necessary to do this step. In any case,
787   // calling "proc->symbols->isValidAddress(where)" usually returns false
788   // even for cases when the address looks ok. If it is required to have
789   // such a routine, we will have to figure out a better one. An idea
790   // could be to get the address for "start" and length of the code and
791   // make sure that the address "where" is between those two values (that's
792   // what gdb goes for sparcs) - naim
793   // 
794
795
796   return(result);
797 }
798
799
800 /*
801  * return the time required to execute the passed primitive.
802  *
803  */
804 unsigned getPrimitiveCost(const string &name)
805 {
806
807     static bool init=false;
808
809     if (!init) { init = 1; initPrimitiveCost(); }
810
811     if (!primitiveCosts.defines(name)) {
812       return 1;
813     } else
814       return (primitiveCosts[name]);
815 }
816
817
818 // find any tags to associate semantic meaning to function
819 unsigned findTags(const string ) {
820   return 0;
821 #ifdef notdef
822   if (tagDict.defines(funcName))
823     return (tagDict[funcName]);
824   else
825     return 0;
826 #endif
827 }
828
829
830 void
831 trampTemplate::updateTrampCost(process *proc, int trampCost) {
832
833 #ifndef alpha_dec_osf4_0 /* XXX We don't calculate cost yet on Alpha */
834     cost = cost + trampCost;
835     if (cost < 0) cost = 0;
836
837     char costInsn[40];
838     Address csize = 0;
839
840     // quick dirty hack; Will be changed soon so that we 
841     // don't call getObservedCostAddr() every time  --ling  
842     proc->getObservedCostAddr();   
843     Address caddr = proc->costAddr(); 
844
845     emitVupdate(updateCostOp, cost, 0, caddr, costInsn, csize, false);
846     proc->writeDataSpace((caddr_t)costAddr, csize, costInsn);
847 #endif
848 }
849
850 void cleanInstFromActivePoints(process *proc)
851 {
852     assert(proc);
853     vector<point*> allPoints = activePoints.values();
854  
855     // is it ok to have activePoints elements with empty points? - naim
856     for (unsigned u = 0; u < allPoints.size(); u++) {
857       instInstance *inst = allPoints[u]->inst;
858       while (inst) {
859         assert(inst->proc);
860         if (inst->proc->getPid() == proc->getPid()) {
861           if (!inst->prev) {
862             // this is the first one on the list
863             if (!inst->next) {
864               // this is the only one on the list
865               delete inst;
866               allPoints[u]->inst = NULL;
867               inst = NULL;
868             } else {
869               inst->next->prev = NULL;
870               allPoints[u]->inst = inst->next;
871               delete inst;
872               inst = allPoints[u]->inst;
873             }
874           } else {
875             // this is not the first one
876             if (!inst->next) {
877               // this is the last one
878               inst->prev->next = NULL;
879               delete inst;
880               inst = NULL;
881             } else {
882               // we are somewhere in the middle of the list
883               inst->prev->next = inst->next;
884               inst->next->prev = inst->prev;
885               instInstance *next_inst = inst->next;
886               delete inst;
887               inst = next_inst;
888             }
889           }
890         } else {
891           inst = inst->next;
892         }
893       }
894     }
895 }
896