* Bugfix: InstrucIter no longer used for int_function iteration.
[dyninst.git] / dyninstAPI / src / addressSpace.C
1 /*
2  * Copyright (c) 1996-2004 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: addressSpace.C,v 1.11 2007/12/11 20:22:05 bill Exp $
43
44 #include "addressSpace.h"
45 #include "codeRange.h"
46 #include "process.h"
47 #include "binaryEdit.h"
48
49 #include "miniTramp.h"
50 #include "baseTramp.h"
51 #include "multiTramp.h" // multiTramp and instArea
52 #include "instPoint.h"
53
54 // Two-level codeRange structure
55 #include "mapped_object.h"
56
57 #include "InstrucIter.h"
58
59 // Implementations of non-virtual functions in the address space
60 // class.
61
62 AddressSpace::AddressSpace() :
63     trampTrapMapping(addrHash4),
64     multiTrampsById_(intHash),
65     trampGuardBase_(0),
66     up_ptr_(NULL),
67     costAddr_(0)
68 {}
69
70 AddressSpace::~AddressSpace() {}
71
72 process *AddressSpace::proc() {
73     return dynamic_cast<process *>(this);
74 }
75
76 BinaryEdit *AddressSpace::edit() {
77     return dynamic_cast<BinaryEdit *>(this);
78 }
79
80 // Fork constructor - and so we can assume a parent "process"
81 // rather than "address space"
82 void AddressSpace::copyAddressSpace(process *parent) {
83     deleteAddressSpace();
84
85     // This is only defined for process->process copy
86     // until someone can give a good reason for copying
87     // anything else...
88
89     assert(proc());
90
91     // Mapped objects first
92     for (unsigned i = 0; i < parent->mapped_objects.size(); i++) {
93         mapped_object *par_obj = parent->mapped_objects[i];
94         mapped_object *child_obj = new mapped_object(par_obj, proc());
95         if (!child_obj) {
96             delete child_obj;
97         }
98         
99         mapped_objects.push_back(child_obj);
100         addOrigRange(child_obj);
101         
102         // This clones funcs, which then clone instPoints, which then 
103         // clone baseTramps, which then clones miniTramps.
104     }
105     
106
107     /////////////////////////
108     // Inferior heap
109     /////////////////////////
110
111     heap_ = inferiorHeap(parent->heap_);
112     heapInitialized_ = parent->heapInitialized_;
113
114     /////////////////////////
115     // Instrumentation (multiTramps on down)
116     /////////////////////////
117
118     pdvector<codeRange *> ranges;
119     parent->modifiedRanges_.elements(ranges);
120
121     for (unsigned i = 0; i < ranges.size(); i++) {
122         instArea *area = dynamic_cast<instArea *>(ranges[i]);
123         replacedFunctionCall *rfc = dynamic_cast<replacedFunctionCall *>(ranges[i]);
124         // Not used yet
125         //functionReplacement *fr = dynamic_cast<functionReplacement *>(ranges[i]);
126         
127        if (area) {
128             // Create a new multiTramp and add it
129             multiTramp *pMulti = area->multi;
130             multiTramp *cMulti = new multiTramp(pMulti, proc());
131             addMultiTramp(cMulti);
132         }
133         else if (rfc) {
134             replacedFunctionCall *cRFC = new replacedFunctionCall((*rfc));
135             addReplacedCall(cRFC);
136         }
137 #if 0
138 // Apparently this was never implemented... it probably should be, though.
139         else if (fr) {
140             functionReplacement *cFR = new functionReplacement(cFR);
141             addFuncReplacement(cFR);
142         }
143 #endif
144     }
145     // That will also create all baseTramps, miniTramps, ...
146 }
147
148 void AddressSpace::deleteAddressSpace() {
149     // Methodically clear everything we have - it all went away
150     // We have the following member variables:
151
152     // bool heapInitialized_
153     // inferiorHeap heap_
154     // codeRangeTree textRanges_
155     // codeRangeTree modifiedCodeRanges_
156     // dictionary_hash multiTrampsById_
157
158     heapInitialized_ = false;
159     heap_.clear();
160
161     // We can just clear the originalCodeRanges structure - everything else
162     // is deleted elsewhere, and we won't leak.
163     textRanges_.clear();
164
165     // Delete only the wrapper objects
166     pdvector<codeRange *> ranges;
167     dataRanges_.elements(ranges);
168     for (unsigned i = 0; i < ranges.size(); i++) {
169         delete ranges[i];
170     }
171     ranges.clear();
172     dataRanges_.clear();
173
174     // Modified code ranges we have to take care of. 
175     modifiedRanges_.elements(ranges);
176     modifiedRanges_.clear();
177
178     for (unsigned i = 0; i < ranges.size(); i++) {
179         // This is either a:
180         // instArea
181         // replacedFunctionCall
182         // replacedFunction
183
184         // Either way, we can nuke 'em.
185         delete ranges[i];
186     }
187
188     multiTrampsById_.clear();
189
190     for (unsigned i = 0; i < mapped_objects.size(); i++) 
191         delete mapped_objects[i];
192
193     mapped_objects.clear();
194
195     trampGuardBase_ = 0;
196
197     // up_ptr_ is untouched
198     costAddr_ = 0;
199 }
200
201
202 // findRangeByAddr: finds the object (see below) that corresponds with
203 // a given absolute address. This includes:
204 //   Functions (non-relocated)
205 //   Base tramps
206 //   Mini tramps
207 //   Relocated functions
208 //
209 // The process class keeps a tree of objects occupying the address space.
210 // This top-level tree includes trampolines, relocated functions, and the
211 // application and shared objects. The search starts at the top of this tree.
212 // If the address resolves to a base tramp, mini tramp, or relocated function,
213 // that is returned. If the address resolves within the range of an shared
214 // object, the search recurses into the object (the offset into the object
215 // is calculated and the function lookup works from the offset). If the offset
216 // is within the a.out, we look up the function assuming the address given is
217 // the offset. 
218
219 // This function gives only "original" code - that is, code that either existed
220 // in the binary or that we added to unallocated space. If you're looking for places
221 // where things were overwritten (jumps to instrumentation, etc.) look at
222 // modifiedRanges_.
223
224 void AddressSpace::addOrigRange(codeRange *range) {
225     textRanges_.insert(range);
226     if (range->is_mapped_object()) {
227         // Hack... add data range
228         mappedObjData *data = new mappedObjData(range->is_mapped_object());
229         dataRanges_.insert(data);
230     }
231 }
232
233 void AddressSpace::addModifiedRange(codeRange *range) {
234     modifiedRanges_.insert(range);
235 }
236
237 void AddressSpace::removeOrigRange(codeRange *range) {
238     codeRange *tmp = NULL;
239     
240     if (!textRanges_.find(range->get_address_cr(), tmp))
241         return;
242
243     assert (range == tmp);
244
245     textRanges_.remove(range->get_address_cr());
246 }
247
248 void AddressSpace::removeModifiedRange(codeRange *range) {
249     codeRange *tmp = NULL;
250     
251     if (!modifiedRanges_.find(range->get_address_cr(), tmp))
252         return;
253
254     assert (range == tmp);
255
256     modifiedRanges_.remove(range->get_address_cr());
257
258     instArea *area = dynamic_cast<instArea *>(range);
259     if (area) {
260       // We have just removed a multiTramp. If the dictionary
261       // entry is the same as the instArea pointer, remove it
262       // from the dictionary as well so we can't accidentally
263       // access it that way.
264
265       // If the pointers aren't equal, squawk because that shouldn't
266       // happen.
267       
268       if (area->multi) {
269         if (multiTrampsById_[area->multi->id()] == area->multi)
270           multiTrampsById_[area->multi->id()] = NULL;
271         else {
272           fprintf(stderr, "%d[%d]: Warning: odd case in removing instArea\n",
273                   FILE__, __LINE__);
274         }
275         
276       }
277     }
278 }
279
280 codeRange *AddressSpace::findOrigByAddr(Address addr) {
281     codeRange *range = NULL;
282     
283     if (!textRanges_.find(addr, range)) {
284         return NULL;
285     }
286     
287     assert(range);
288     
289     bool in_range = (addr >= range->get_address_cr() &&
290                      addr <= (range->get_address_cr() + range->get_size_cr()));
291     assert(in_range); // Supposed to return NULL if this is the case
292     
293     // The top level tree doesn't go into mapped_objects, which is not
294     // what we want; so if we're in a mapped_object, poke inside.
295     // However, if we're in a function (int_function), minitramp,
296     // basetramp, ... return that right away.
297     
298     mapped_object *mobj = range->is_mapped_object();
299     if (mobj) {
300         codeRange *obj_range = mobj->findCodeRangeByAddress(addr);
301         if (obj_range) range = obj_range;
302     }
303     
304     return range;
305 }
306
307 codeRange *AddressSpace::findModByAddr(Address addr) {
308     codeRange *range = NULL;
309     
310     if (!modifiedRanges_.find(addr, range)) {
311         return NULL;
312     }
313     
314     assert(range);
315     
316     bool in_range = (addr >= range->get_address_cr() &&
317                      addr <= (range->get_address_cr() + range->get_size_cr()));
318     assert(in_range); // Supposed to return NULL if this is the case
319
320     return range;
321 }
322
323 // Returns the named symbol from the image or a shared object
324 bool AddressSpace::getSymbolInfo( const pdstring &name, Symbol &ret ) 
325 {
326   for (unsigned i = 0; i < mapped_objects.size(); i++) {
327     bool sflag;
328     sflag = mapped_objects[i]->getSymbolInfo( name, ret );
329     
330     if( sflag ) {
331       return true;
332     }
333   }
334   return false;
335 }
336
337
338
339 bool AddressSpace::getOrigRanges(pdvector<codeRange *> &ranges) {
340     textRanges_.elements(ranges);
341     return true;
342 }
343
344 bool AddressSpace::getModifiedRanges(pdvector<codeRange *> &ranges) {
345     modifiedRanges_.elements(ranges);
346     return true;
347 }
348
349 multiTramp *AddressSpace::findMultiTrampByAddr(Address addr) {    
350     codeRange *range = findModByAddr(addr);
351     if (range) {
352         instArea *area = dynamic_cast<instArea *>(range);
353         
354         if (area)
355             return area->multi;
356     }
357     range = findOrigByAddr(addr);
358
359     multiTramp *multi = dynamic_cast<multiTramp *>(range);
360     return multi;
361 }
362
363 multiTramp *AddressSpace::findMultiTrampById(unsigned int id) {
364     multiTramp *multi = NULL;
365     multiTrampsById_.find(id, multi);
366
367     return multi;
368 }
369
370 // Check to see if we're replacing an earlier multiTramp,
371 // add to the unmodifiedAreas list
372 void AddressSpace::addMultiTramp(multiTramp *multi) {
373     assert(multi);
374     assert(multi->instAddr());
375
376     if (multi->id() == 11286) {
377       fprintf(stderr, "Replacing multiTramp with id %d: new %p\n",
378               11286, multi);
379     }
380
381     // Actually... we haven't copied it yet, so don't add anything. 
382     //addOrigRange(multi);
383
384     codeRange *range = findModByAddr(multi->instAddr());
385     if (range) {
386         // We're overriding. Keep the instArea but update pointer.
387         instArea *area = dynamic_cast<instArea *>(range);
388         // It could be something else, which should have been
389         // caught already
390         if (!area) {
391             // Oops, someone already here... and multiTramps have
392             // the lowest priority.
393             return;
394         }
395         area->multi = multi;
396     }
397     else {
398         instArea *area = new instArea(multi);
399
400         modifiedRanges_.insert(area);
401     }
402
403     multiTrampsById_[multi->id()] = multi;
404 }
405
406 void AddressSpace::removeMultiTramp(multiTramp *multi) {
407     if (!multi) return;
408
409     assert(multi->instAddr());
410
411     removeOrigRange(multi);
412
413     // For multiTramps we also have the "wrapper" that
414     // represents the jump to the multiTramp. If that's
415     // still associated with this one, then nuke it
416     // as well. If not, ignore.
417
418     instArea *jump = dynamic_cast<instArea *>(findModByAddr(multi->instAddr()));
419
420     if (jump && jump->multi == multi) {
421         removeModifiedRange(jump);
422         delete jump;
423     }
424 }
425
426 functionReplacement *AddressSpace::findFuncReplacement(Address addr) {
427     codeRange *range = findModByAddr(addr);
428     if (!range) return NULL;
429     
430     functionReplacement *rep = dynamic_cast<functionReplacement *>(range);
431     return rep;
432 }
433
434 void AddressSpace::addFuncReplacement(functionReplacement *rep) {
435     assert(rep);
436     Address currAddr = rep->get_address_cr();
437
438     while (currAddr < (rep->get_address_cr() + rep->get_size_cr())) {
439         codeRange *range = findModByAddr(currAddr);
440
441         if (range) removeModifiedRange(range);
442         currAddr += 1;
443     }
444
445     addModifiedRange(rep);
446 }
447
448 void AddressSpace::removeFuncReplacement(functionReplacement *rep) {
449     removeModifiedRange(rep);
450 }
451
452 replacedFunctionCall *AddressSpace::findReplacedCall(Address addr) {
453     codeRange *range = findModByAddr(addr);
454     if (!range) return NULL;
455     
456     replacedFunctionCall *rep = dynamic_cast<replacedFunctionCall *>(range);
457     return rep;
458 }
459
460 void AddressSpace::addReplacedCall(replacedFunctionCall *repcall) {
461     codeRange *range = findModByAddr(repcall->get_address_cr());
462     if (range) {
463         // Can't replace instrumentation right now...
464         assert(dynamic_cast<replacedFunctionCall *>(range));
465         removeModifiedRange(range);
466         delete range;
467     }
468     assert(repcall);
469     addModifiedRange(repcall);
470 }
471
472 void AddressSpace::removeReplacedCall(replacedFunctionCall *repcall) {
473     removeModifiedRange(repcall);
474 }
475
476 //////////////////////////////////////////////////////////////////////////////
477 // Memory allocation routines
478 //////////////////////////////////////////////////////////////////////////////
479
480
481 void AddressSpace::inferiorFreeCompact() {
482   pdvector<heapItem *> &freeList = heap_.heapFree;
483   unsigned i, nbuf = freeList.size();
484
485   /* sort buffers by address */
486   VECTOR_SORT(freeList, heapItemCmpByAddr);
487
488   /* combine adjacent buffers */
489   bool needToCompact = false;
490   for (i = 1; i < freeList.size(); i++) {
491       heapItem *h1 = freeList[i-1];
492       heapItem *h2 = freeList[i];
493       assert(h1->length != 0);
494       if (h1->addr + h1->length > h2->addr) {
495           fprintf(stderr, "Error: heap 1 (%p) (0x%p to 0x%p) overlaps heap 2 (%p) (0x%p to 0x%p)\n",
496                   h1,
497                   (void *)h1->addr, (void *)(h1->addr + h1->length),
498                   h2,
499                   (void *)h2->addr, (void *)(h2->addr + h2->length));
500       }
501       assert(h1->addr + h1->length <= h2->addr);
502       if (h1->addr + h1->length == h2->addr
503           && h1->type == h2->type) {
504           h2->addr = h1->addr;
505           h2->length = h1->length + h2->length;
506           h1->length = 0;
507           nbuf--;
508           needToCompact = true;
509       }
510   }
511
512   /* remove any absorbed (empty) buffers */ 
513   if (needToCompact) {
514     pdvector<heapItem *> cleanList;
515     unsigned end = freeList.size();
516     for (i = 0; i < end; i++) {
517       heapItem *h1 = freeList[i];
518       if (h1->length != 0) {
519         cleanList.push_back(h1);
520       } else {
521         delete h1;
522       }
523     }
524     assert(cleanList.size() == nbuf);
525     for (i = 0; i < nbuf; i++) {
526       freeList[i] = cleanList[i];
527     }
528     freeList.resize(nbuf);
529     assert(freeList.size() == nbuf);
530   }
531 }
532     
533 int AddressSpace::findFreeIndex(unsigned size, int type, Address lo, Address hi) {
534     // type is a bitmask: match on any bit in the mask
535     pdvector<heapItem *> &freeList = heap_.heapFree;
536     
537     int best = -1;
538     for (unsigned i = 0; i < freeList.size(); i++) {
539         heapItem *h = freeList[i];
540         // check if free block matches allocation constraints
541         // Split out to facilitate debugging
542         if (h->addr >= lo &&
543             (h->addr + size - 1) <= hi &&
544             h->length >= size &&
545             h->type & type) {
546             if (best == -1)
547                 best = i;
548             // check for better match
549             if (h->length < freeList[best]->length) best = i;
550         }
551     }
552     return best;
553 }
554
555 void AddressSpace::addHeap(heapItem *h) {
556     heap_.bufferPool.push_back(h);
557     heapItem *h2 = new heapItem(h);
558     h2->status = HEAPfree;
559     heap_.heapFree.push_back(h2);
560     heap_.totalFreeMemAvailable += h2->length;
561 }
562
563 void AddressSpace::initializeHeap() {
564     // (re)initialize everything 
565     heap_.heapActive.clear();
566     heap_.heapFree.resize(0);
567     heap_.disabledList.resize(0);
568     heap_.disabledListTotalMem = 0;
569     heap_.freed = 0;
570     heap_.totalFreeMemAvailable = 0;
571
572     heapInitialized_ = true;
573 }
574
575 /* returns true if memory was allocated for a variable starting at address
576    "block", otherwise returns false
577 */
578 bool AddressSpace::isInferiorAllocated(Address block) {
579     heapItem *h = NULL;  
580     return heap_.heapActive.find(block, h);
581 }
582
583 Address AddressSpace::inferiorMallocInternal(unsigned size,
584                                              Address lo,
585                                              Address hi,
586                                              inferiorHeapType type) {
587     int freeIndex = findFreeIndex(size, type, lo, hi);
588     if (freeIndex == -1) return 0; // Failure is often an option
589
590
591     // adjust active and free lists
592     assert(freeIndex != -1);
593     heapItem *h = heap_.heapFree[freeIndex];
594     assert(h);
595     
596     // remove allocated buffer from free list
597     if (h->length != size) {
598         // size mismatch: put remainder of block on free list
599         heapItem *rem = new heapItem(h);
600         rem->addr += size;
601         rem->length -= size;
602         heap_.heapFree[freeIndex] = rem;
603     } else {
604         // size match: remove entire block from free list
605         unsigned last = heap_.heapFree.size();
606         heap_.heapFree[freeIndex] = heap_.heapFree[last-1];
607         heap_.heapFree.resize(last-1);
608     }
609     // add allocated block to active list
610     h->length = size;
611     h->status = HEAPallocated;
612     heap_.heapActive[h->addr] = h;
613     // bookkeeping
614     heap_.totalFreeMemAvailable -= size;
615     assert(h->addr);
616     
617     return(h->addr);
618 }
619
620 void AddressSpace::inferiorFree(Address block) {
621     // find block on active list
622     heapItem *h = NULL;  
623     if (!heap_.heapActive.find(block, h)) {
624         // We can do this if we're at process teardown.
625         return;
626     }
627     assert(h);
628     
629     // Remove from the active list
630     heap_.heapActive.undef(block);
631     
632     // Add to the free list
633     h->status = HEAPfree;
634     heap_.heapFree.push_back(h);
635     heap_.totalFreeMemAvailable += h->length;
636     heap_.freed += h->length;
637 }
638
639 void AddressSpace::inferiorMallocAlign(unsigned &size) {
640     // Align to the process word
641 #if !defined(arch_ia64)
642     unsigned alignment = (getAddressWidth() - 1);
643 #else
644     unsigned alignment = (128 - 1);
645 #endif
646
647     size = (size + alignment) & ~alignment;
648 }
649     
650 bool AddressSpace::inferiorRealloc(Address block, unsigned newSize) {
651 #if defined (cap_dynamic_heap)
652     // This is why it's not a reference...
653     inferiorMallocAlign(newSize);
654 #endif
655     
656     // find block on active list
657     heapItem *h = NULL;  
658     if (!heap_.heapActive.find(block, h)) {
659         // We can do this if we're at process teardown.
660         return false;
661     }
662     assert(h);
663     
664     if (h->length < newSize)
665         return false; // Cannot make bigger...
666     if (h->length == newSize)
667         return true;
668     
669     // We make a new "free" block that is the end of this one.
670     Address freeStart = block + newSize;
671     int shrink = h->length - newSize;
672     
673     assert(shrink > 0);
674     
675     h->length = newSize;
676     
677     heapItem *freeEnd = new heapItem(freeStart,
678                                      shrink,
679                                      h->type,
680                                      h->dynamic,
681                                      HEAPfree);
682     heap_.heapFree.push_back(freeEnd);
683     
684     heap_.totalFreeMemAvailable += shrink;
685     heap_.freed += shrink;
686     
687     // And run a compact; otherwise we'll end up with hugely fragmented memory.
688     inferiorFreeCompact();
689     
690     return true;
691 }
692
693 /////////////////////////////////////////
694 // Function lookup...
695 /////////////////////////////////////////
696
697 bool AddressSpace::findFuncsByAll(const pdstring &funcname,
698                              pdvector<int_function *> &res,
699                              const pdstring &libname) { // = "", btw
700     
701     unsigned starting_entries = res.size(); // We'll return true if we find something
702     for (unsigned i = 0; i < mapped_objects.size(); i++) {
703         if (libname == "" ||
704             mapped_objects[i]->fileName() == libname.c_str() ||
705             mapped_objects[i]->fullName() == libname.c_str()) {
706             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
707             if (pretty) {
708                 // We stop at first match...
709                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
710                     res.push_back((*pretty)[pm]);
711                 }
712             }
713             else {
714                 const pdvector<int_function *> *mangled = mapped_objects[i]->findFuncVectorByMangled(funcname);
715                 if (mangled) {
716                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
717                         res.push_back((*mangled)[mm]);
718                     }
719                 }
720             }
721         }
722     }
723     return (res.size() != starting_entries);
724 }
725
726
727 bool AddressSpace::findFuncsByPretty(const pdstring &funcname,
728                              pdvector<int_function *> &res,
729                              const pdstring &libname) { // = "", btw
730
731     unsigned starting_entries = res.size(); // We'll return true if we find something
732
733     for (unsigned i = 0; i < mapped_objects.size(); i++) {
734         if (libname == "" ||
735             mapped_objects[i]->fileName() == libname.c_str() ||
736             mapped_objects[i]->fullName() == libname.c_str()) {
737             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
738             if (pretty) {
739                 // We stop at first match...
740                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
741                     res.push_back((*pretty)[pm]);
742                 }
743             }
744         }
745     }
746     return res.size() != starting_entries;
747 }
748
749
750 bool AddressSpace::findFuncsByMangled(const pdstring &funcname,
751                                  pdvector<int_function *> &res,
752                                  const pdstring &libname) { // = "", btw
753     unsigned starting_entries = res.size(); // We'll return true if we find something
754
755     for (unsigned i = 0; i < mapped_objects.size(); i++) {
756         if (libname == "" ||
757             mapped_objects[i]->fileName() == libname.c_str() ||
758             mapped_objects[i]->fullName() == libname.c_str()) {
759             const pdvector<int_function *> *mangled = 
760                mapped_objects[i]->findFuncVectorByMangled(funcname);
761             if (mangled) {
762                 for (unsigned mm = 0; mm < mangled->size(); mm++) {
763                    res.push_back((*mangled)[mm]);
764                 }
765             }
766         }
767     }
768     return res.size() != starting_entries;
769 }
770
771 int_function *AddressSpace::findOnlyOneFunction(const string &name,
772                                            const string &lib) 
773 {
774     assert(mapped_objects.size());
775
776     pdvector<int_function *> allFuncs;
777     if (!findFuncsByAll(name.c_str(), allFuncs, lib.c_str()))
778         return NULL;
779     if (allFuncs.size() > 1) {
780         cerr << "Warning: multiple matches for " << name << ", returning first" << endl;
781     }
782     return allFuncs[0];
783 }
784
785 /////////////////////////////////////////
786 // Variable lookup...
787 /////////////////////////////////////////
788
789 bool AddressSpace::findVarsByAll(const pdstring &varname,
790                             pdvector<int_variable *> &res,
791                             const pdstring &libname) { // = "", btw
792     unsigned starting_entries = res.size(); // We'll return true if we find something
793     
794     for (unsigned i = 0; i < mapped_objects.size(); i++) {
795         if (libname == "" ||
796             mapped_objects[i]->fileName() == libname.c_str() ||
797             mapped_objects[i]->fullName() == libname.c_str()) {
798             const pdvector<int_variable *> *pretty = mapped_objects[i]->findVarVectorByPretty(varname);
799             if (pretty) {
800                 // We stop at first match...
801                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
802                     res.push_back((*pretty)[pm]);
803                 }
804             }
805             else {
806                 const pdvector<int_variable *> *mangled = mapped_objects[i]->findVarVectorByMangled(varname);
807                 if (mangled) {
808                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
809                         res.push_back((*mangled)[mm]);
810                     }
811                 }
812             }
813         }
814     }
815
816     return res.size() != starting_entries;
817 }
818
819
820
821 // Get me a pointer to the instruction: the return is a local
822 // (mutator-side) store for the mutatee. This may duck into the local
823 // copy for images, or a relocated function's self copy.
824 // TODO: is this really worth it? Or should we just use ptrace?
825
826 void *AddressSpace::getPtrToInstruction(Address addr) const {
827     codeRange *range;
828
829     if (textRanges_.find(addr, range)) {
830         return range->getPtrToInstruction(addr);
831     }
832     else if (dataRanges_.find(addr, range)) {
833         mappedObjData *data = dynamic_cast<mappedObjData *>(range);
834         assert(data);
835         return data->obj->getPtrToData(addr);
836     }
837     return NULL;
838 }
839
840 bool AddressSpace::isValidAddress(const Address& addr) const{
841     // "Is this part of the process address space?"
842     codeRange *dontcare;
843     if (textRanges_.find(addr, dontcare))
844         return true;
845     if (dataRanges_.find(addr, dontcare))
846         return true;
847     fprintf(stderr, "Warning: address 0x%p not valid!\n",
848             (void *)addr);
849     return false;
850 }        
851
852 mapped_object *AddressSpace::findObject(Address addr) {
853     for (unsigned i=0; i<mapped_objects.size(); i++)
854     {
855         if (addr >= mapped_objects[i]->codeAbs() &&
856             addr < mapped_objects[i]->codeAbs() + mapped_objects[i]->imageSize())
857         {
858             return mapped_objects[i];
859         }
860     }
861     return NULL;
862 }
863
864 int_function *AddressSpace::findFuncByAddr(Address addr) {
865     codeRange *range = findOrigByAddr(addr);
866     if (!range) return NULL;
867     
868     int_function *func_ptr = range->is_function();
869     multiTramp *multi = range->is_multitramp();
870     miniTrampInstance *mti = range->is_minitramp();
871
872     if(func_ptr) {
873        return func_ptr;
874     }
875     else if (multi) {
876         return multi->func();
877     }
878     else if (mti) {
879         return mti->baseTI->multiT->func();
880     }
881     else {
882         return NULL;
883     }
884 }
885
886 int_basicBlock *AddressSpace::findBasicBlockByAddr(Address addr) {
887     codeRange *range = findOrigByAddr(addr);
888     if (!range) return NULL;
889
890     int_basicBlock *b = range->is_basicBlock();
891     int_function *f = range->is_function();
892     multiTramp *mt = range->is_multitramp();
893     miniTrampInstance *mti = range->is_minitramp();
894
895     if(b) {
896         return b;
897     }
898     else if(f) {
899         return f->findBlockByAddr(addr);
900     }
901     else if(mt) {
902         return mt->func()->findBlockByAddr(addr);
903     }
904     else if(mti) {
905         return mti->baseTI->multiT->func()->findBlockByAddr(addr);
906     }
907     else
908         return NULL;
909 }
910
911 int_function *AddressSpace::findFuncByInternalFunc(image_func *ifunc) {
912     assert(ifunc);
913   
914     // Now we have to look up our specialized version
915     // Can't do module lookup because of DEFAULT_MODULE...
916     pdvector<int_function *> possibles;
917     if (!findFuncsByMangled(ifunc->symTabName().c_str(),
918                             possibles))
919         return NULL;
920
921     assert(possibles.size());
922   
923     for (unsigned i = 0; i < possibles.size(); i++) {
924         if (possibles[i]->ifunc() == ifunc) {
925             return possibles[i];
926         }
927     }
928     return NULL;
929 }
930
931 // findModule: returns the module associated with mod_name 
932 // this routine checks both the a.out image and any shared object
933 // images for this resource
934 mapped_module *AddressSpace::findModule(const pdstring &mod_name, bool wildcard)
935 {
936     // KLUDGE: first search any shared libraries for the module name 
937     //  (there is only one module in each shared library, and that 
938     //  is the library name)
939     for(u_int j=0; j < mapped_objects.size(); j++){
940         mapped_module *mod = mapped_objects[j]->findModule(mod_name.c_str(), wildcard);
941         if (mod) {
942             return (mod);
943         }
944     }
945     return NULL;
946 }
947
948 // findObject: returns the object associated with obj_name 
949 // This just iterates over the mapped object vector
950 mapped_object *AddressSpace::findObject(const pdstring &obj_name, bool wildcard)
951 {
952     for(u_int j=0; j < mapped_objects.size(); j++){
953         if (mapped_objects[j]->fileName() == obj_name.c_str() ||
954             mapped_objects[j]->fullName() == obj_name.c_str() ||
955             (wildcard &&
956              (obj_name.wildcardEquiv(mapped_objects[j]->fileName().c_str()) ||
957               obj_name.wildcardEquiv(mapped_objects[j]->fullName().c_str()))))
958             return mapped_objects[j];
959     }
960     return NULL;
961 }
962
963 // getAllFunctions: returns a vector of all functions defined in the
964 // a.out and in the shared objects
965
966 void AddressSpace::getAllFunctions(pdvector<int_function *> &funcs) {
967     for (unsigned i = 0; i < mapped_objects.size(); i++) {
968         mapped_objects[i]->getAllFunctions(funcs);
969     }
970 }
971       
972 // getAllModules: returns a vector of all modules defined in the
973 // a.out and in the shared objects
974
975 void AddressSpace::getAllModules(pdvector<mapped_module *> &mods){
976     for (unsigned i = 0; i < mapped_objects.size(); i++) {
977         const pdvector<mapped_module *> &obj_mods = mapped_objects[i]->getModules();
978         for (unsigned j = 0; j < obj_mods.size(); j++) {
979             mods.push_back(obj_mods[j]);
980         }
981     }
982 }
983
984 //Acts like findTargetFuncByAddr, but also finds the function if addr
985 // is an indirect jump to a function.
986 //I know this is an odd function, but darn I need it.
987 int_function *AddressSpace::findJumpTargetFuncByAddr(Address addr) {
988     Address addr2 = 0;
989     int_function *f = findFuncByAddr(addr);
990     if (f)
991         return f;
992
993     codeRange *range = findOrigByAddr(addr);
994     if (!range->is_mapped_object()) 
995         return NULL;
996     
997     InstrucIter ii(addr, this);
998     if (ii.isAJumpInstruction())
999         addr2 = ii.getBranchTargetAddress();
1000
1001     return findFuncByAddr(addr2);
1002 }
1003
1004 AstNodePtr AddressSpace::trampGuardAST() {
1005     if (!trampGuardBase_) {
1006         // Don't have it yet....
1007         return AstNodePtr();
1008     }
1009     if (trampGuardAST_) return trampGuardAST_;
1010
1011     trampGuardAST_ = AstNode::operandNode(AstNode::DataAddr, 
1012                                           (void *)trampGuardBase_);
1013
1014     return trampGuardAST_;
1015 }
1016
1017 // Add it at the bottom...
1018 void AddressSpace::deleteGeneratedCode(generatedCodeObject *delInst)
1019 {
1020 #if 0
1021     fprintf(stderr, "Deleting generated code %p, which is a:\n",
1022             delInst);
1023     if (dynamic_cast<multiTramp *>(delInst)) {
1024         fprintf(stderr, "   multiTramp\n");
1025     }
1026     else if (dynamic_cast<baseTrampInstance *>(delInst)) {
1027         fprintf(stderr, "   baseTramp\n");
1028     } 
1029     else if (dynamic_cast<miniTrampInstance *>(delInst)) {
1030         fprintf(stderr, "   miniTramp\n");
1031     }
1032     else {
1033         fprintf(stderr, "   unknown\n");
1034     }
1035 #endif    
1036
1037     delete delInst;
1038 }