Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / addressSpace.C
1 /*
2  * Copyright (c) 1996-2011 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "addressSpace.h"
33 #include "codeRange.h"
34 #include "process.h"
35 #include "function.h"
36 #include "binaryEdit.h"
37 #include "miniTramp.h"
38 #include "baseTramp.h"
39
40 #include "instPoint.h"
41
42 // Two-level codeRange structure
43 #include "mapped_object.h"
44 #include "mapped_module.h"
45 #include "InstructionDecoder.h"
46 #include "Instruction.h"
47
48 #include "dynutil/h/AST.h"
49 #include "Relocation/CodeMover.h"
50 #include "Relocation/Springboard.h"
51 #include "Relocation/Transformers/Include.h"
52 #include "Relocation/CodeTracker.h"
53
54 #include "MemoryEmulator/memEmulator.h"
55 #include "parseAPI/h/CodeObject.h"
56 #include <boost/tuple/tuple.hpp>
57
58 #include "PatchMgr.h"
59 #include "Relocation/DynAddrSpace.h"
60 #include "Relocation/DynPointMaker.h"
61 #include "Relocation/DynObject.h"
62 #include "Relocation/DynInstrumenter.h"
63
64 // Implementations of non-virtual functions in the address space
65 // class.
66
67 using namespace Dyninst;
68 using PatchAPI::DynObjectPtr;
69 using PatchAPI::DynObject;
70 using PatchAPI::DynAddrSpace;
71 using PatchAPI::DynAddrSpacePtr;
72 using PatchAPI::PatchMgr;
73 using PatchAPI::Patcher;
74 using PatchAPI::PointMakerPtr;
75 using PatchAPI::DynInstrumenterPtr;
76 using PatchAPI::DynInstrumenter;
77
78 AddressSpace::AddressSpace () :
79     trapMapping(this),
80     useTraps_(true),
81     trampGuardBase_(NULL),
82     up_ptr_(NULL),
83     costAddr_(0),
84     memEmulator_(NULL),
85     emulateMem_(false),
86     emulatePC_(false),
87     delayRelocation_(false)
88 {
89    if ( getenv("DYNINST_EMULATE_MEMORY") ) {
90        printf("emulating memory\n");
91        memEmulator_ = new MemoryEmulator(this);
92        emulateMem_ = true;
93        emulatePC_ = true;
94    }
95 }
96
97 AddressSpace::~AddressSpace() {
98    if (memEmulator_)
99       delete memEmulator_;
100 }
101
102 process *AddressSpace::proc() {
103     return dynamic_cast<process *>(this);
104 }
105
106 BinaryEdit *AddressSpace::edit() {
107     return dynamic_cast<BinaryEdit *>(this);
108 }
109
110 // Fork constructor - and so we can assume a parent "process"
111 // rather than "address space"
112 void AddressSpace::copyAddressSpace(process *parent) {
113    deleteAddressSpace();
114
115     // This is only defined for process->process copy
116     // until someone can give a good reason for copying
117     // anything else...
118
119     assert(proc());
120
121     mapped_object *par_aout = parent->getAOut();
122     mapped_object *child_aout = new mapped_object(par_aout, proc());
123     initPatchAPI(child_aout);
124     addMappedObject(child_aout);
125
126     // Mapped objects first
127     for (unsigned i = 0; i < parent->mapped_objects.size(); i++) {
128         mapped_object *par_obj = parent->mapped_objects[i];
129         if (parent->getAOut() != par_obj) {
130           mapped_object *child_obj = new mapped_object(par_obj, proc());
131           assert(child_obj);
132           addMappedObject(child_obj);
133         }
134         // This clones funcs, which then clone instPoints, which then 
135         // clone baseTramps, which then clones miniTramps.
136     }
137
138
139     // Clone the tramp guard base
140     trampGuardBase_ = new int_variable(parent->trampGuardBase_, getAOut()->getDefaultModule());
141
142     /////////////////////////
143     // Inferior heap
144     /////////////////////////
145
146     heap_ = inferiorHeap(parent->heap_);
147     heapInitialized_ = parent->heapInitialized_;
148
149     /////////////////////////
150     // Trap mappings
151     /////////////////////////
152     trapMapping.copyTrapMappings(& (parent->trapMapping));
153
154     /////////////////////////
155     // Overly complex code tracking system
156     /////////////////////////
157     for (CodeTrackers::iterator iter = parent->relocatedCode_.begin();
158          iter != parent->relocatedCode_.end(); ++iter) {
159        // Efficiency; this avoids a spurious copy of the entire
160        // CodeTracker. 
161
162        relocatedCode_.push_back(Relocation::CodeTracker::fork(*iter, this));
163     }
164     
165     // Let's assume we're not forking _in the middle of instrumentation_
166     // (good Lord), and so leave modifiedFunctions_ alone.
167     /*
168     for (CallModMap::iterator iter = parent->callModifications_.begin(); 
169          iter != parent->callModifications_.end(); ++iter) {
170        // Need to forward map the lot
171        block_instance *newB = findBlock(iter->first->llb());
172        for (std::map<func_instance *, func_instance *>::iterator iter2 = iter->second.begin();
173             iter2 != iter->second.end(); ++iter2) {
174           func_instance *context = (iter2->first == NULL) ? NULL : findFunction(iter2->first->ifunc());
175           func_instance *target = (iter2->second == NULL) ? NULL : findFunction(iter2->second->ifunc());
176           callModifications_[newB][context] = target;
177        }
178     }
179     */
180
181     assert(parent->mgr());
182     PatchAPI::CallModMap& cmm = parent->mgr()->instrumenter()->callModMap();
183     for (PatchAPI::CallModMap::iterator iter = cmm.begin(); iter != cmm.end(); ++iter) {
184        // Need to forward map the lot
185       block_instance *newB = findBlock(SCAST_BI(iter->first)->llb());
186       for (std::map<PatchFunction*, PatchFunction*>::iterator iter2 = iter->second.begin();
187             iter2 != iter->second.end(); ++iter2) {
188         func_instance *context = (SCAST_FI(iter2->first) == NULL) ? NULL : findFunction(SCAST_FI(iter2->first)->ifunc());
189         func_instance *target = (SCAST_FI(iter2->second) == NULL) ? NULL : findFunction(SCAST_FI(iter2->second)->ifunc());
190         cmm[newB][context] = target;
191        }
192     }
193
194     PatchAPI::FuncModMap& frm = parent->mgr()->instrumenter()->funcRepMap();
195     for (PatchAPI::FuncModMap::iterator iter = frm.begin(); iter != frm.end(); ++iter) {
196       func_instance *from = findFunction(SCAST_FI(iter->first)->ifunc());
197       func_instance *to = findFunction(SCAST_FI(iter->second)->ifunc());
198       frm[from] = to;
199     }
200
201     PatchAPI::FuncWrapMap& fwm = parent->mgr()->instrumenter()->funcWrapMap();
202     for (PatchAPI::FuncWrapMap::iterator iter = fwm.begin(); iter != fwm.end(); ++iter) {
203       func_instance *from = findFunction(SCAST_FI(iter->first)->ifunc());
204       func_instance *to = findFunction(SCAST_FI(iter->second.first)->ifunc());
205       fwm[from] = std::make_pair(to, iter->second.second);
206     }
207
208     if (memEmulator_) assert(0 && "FIXME!");
209     emulateMem_ = parent->emulateMem_;
210     emulatePC_ = parent->emulatePC_;
211 }
212
213 void AddressSpace::deleteAddressSpace() {
214    // Methodically clear everything we have - it all went away
215    // We have the following member variables:
216
217    // bool heapInitialized_
218    // inferiorHeap heap_
219
220    heapInitialized_ = false;
221    heap_.clear();
222    for (unsigned i = 0; i < mapped_objects.size(); i++) 
223       delete mapped_objects[i];
224
225    mapped_objects.clear();
226
227    runtime_lib.clear();
228
229    trampGuardBase_ = NULL;
230    trampGuardAST_ = AstNodePtr();
231
232    // up_ptr_ is untouched
233    costAddr_ = 0;
234    for (CodeTrackers::iterator iter = relocatedCode_.begin(); 
235         iter != relocatedCode_.end(); ++iter) {
236       delete *iter;
237    }
238    relocatedCode_.clear();
239    modifiedFunctions_.clear();
240    forwardDefensiveMap_.clear();
241    reverseDefensiveMap_.clear();
242    instrumentationInstances_.clear();
243
244    if (memEmulator_) delete memEmulator_;
245    memEmulator_ = NULL;
246 }
247
248
249
250 // Returns the named symbol from the image or a shared object
251 bool AddressSpace::getSymbolInfo( const std::string &name, int_symbol &ret ) 
252 {
253    for (unsigned i = 0; i < mapped_objects.size(); i++) {
254       if (mapped_objects[i]->getSymbolInfo( name, ret ))
255          return true;
256    }
257    return false;
258 }
259
260 bool heapItemLessByAddr(const heapItem *a, const heapItem *b)
261 {
262    if (a->addr < b->addr) {
263       return true;
264    }
265    return false;
266 }
267
268 //////////////////////////////////////////////////////////////////////////////
269 // Memory allocation routines
270 //////////////////////////////////////////////////////////////////////////////
271
272
273 void AddressSpace::inferiorFreeCompact() {
274    pdvector<heapItem *> &freeList = heap_.heapFree;
275    unsigned i, nbuf = freeList.size();
276
277    /* sort buffers by address */
278 #if defined (cap_use_pdvector)
279    VECTOR_SORT(freeList, heapItemCmpByAddr);
280 #else
281    VECTOR_SORT(freeList, heapItemLessByAddr);
282 #endif
283
284
285    /* combine adjacent buffers */
286    bool needToCompact = false;
287    for (i = 1; i < freeList.size(); i++) {
288       heapItem *h1 = freeList[i-1];
289       heapItem *h2 = freeList[i];
290       assert(h1->length != 0);
291       if (h1->addr + h1->length > h2->addr) {
292          fprintf(stderr, "Error: heap 1 (%p) (0x%p to 0x%p) overlaps heap 2 (%p) (0x%p to 0x%p)\n",
293                  h1,
294                  (void *)h1->addr, (void *)(h1->addr + h1->length),
295                  h2,
296                  (void *)h2->addr, (void *)(h2->addr + h2->length));
297       }
298       assert(h1->addr + h1->length <= h2->addr);
299       if (h1->addr + h1->length == h2->addr
300           && h1->type == h2->type) {
301          h2->addr = h1->addr;
302          h2->length = h1->length + h2->length;
303          h1->length = 0;
304          nbuf--;
305          needToCompact = true;
306       }
307    }
308
309    /* remove any absorbed (empty) buffers */ 
310    if (needToCompact) {
311       pdvector<heapItem *> cleanList;
312       unsigned end = freeList.size();
313       for (i = 0; i < end; i++) {
314          heapItem *h1 = freeList[i];
315          if (h1->length != 0) {
316             cleanList.push_back(h1);
317          } else {
318             delete h1;
319          }
320       }
321       assert(cleanList.size() == nbuf);
322       for (i = 0; i < nbuf; i++) {
323          freeList[i] = cleanList[i];
324       }
325       freeList.resize(nbuf);
326       assert(freeList.size() == nbuf);
327    }
328 }
329     
330 int AddressSpace::findFreeIndex(unsigned size, int type, Address lo, Address hi) {
331    // type is a bitmask: match on any bit in the mask
332    pdvector<heapItem *> &freeList = heap_.heapFree;
333     
334    int best = -1;
335    for (unsigned i = 0; i < freeList.size(); i++) {
336       heapItem *h = freeList[i];
337       // check if free block matches allocation constraints
338       // Split out to facilitate debugging
339       infmalloc_printf("%s[%d]: comparing heap %d: 0x%lx-0x%lx/%d to desired %d bytes in 0x%lx-0x%lx/%d\n",
340                        FILE__, __LINE__, 
341                        i,
342                        h->addr, 
343                        h->addr + h->length,
344                        h->type,
345                        size,
346                        lo, 
347                        hi,
348                        type);
349       if (h->addr >= lo &&
350           (h->addr + size - 1) <= hi &&
351           h->length >= size &&
352           h->type & type) {
353          if (best == -1)
354             best = i;
355          // check for better match
356          if (h->length < freeList[best]->length) best = i;
357       }
358    }
359    infmalloc_printf("%s[%d]: returning match %d\n", FILE__, __LINE__, best);
360    return best;
361 }
362
363 void AddressSpace::addHeap(heapItem *h) {
364    heap_.bufferPool.push_back(h);
365    heapItem *h2 = new heapItem(h);
366    h2->status = HEAPfree;
367    heap_.heapFree.push_back(h2);
368    heap_.totalFreeMemAvailable += h2->length;
369
370    if (h->dynamic) {
371       addAllocatedRegion(h->addr, h->length);
372    }
373 }
374
375 void AddressSpace::initializeHeap() {
376    // (re)initialize everything 
377    heap_.heapActive.clear();
378    heap_.heapFree.resize(0);
379    heap_.disabledList.resize(0);
380    heap_.disabledListTotalMem = 0;
381    heap_.freed = 0;
382    heap_.totalFreeMemAvailable = 0;
383
384    heapInitialized_ = true;
385 }
386
387 /* returns true if memory was allocated for a variable starting at address
388    "block", otherwise returns false
389 */
390 bool AddressSpace::isInferiorAllocated(Address block) {
391    heapItem *h = NULL;  
392    return heap_.heapActive.find(block, h);
393 }
394
395 Address AddressSpace::inferiorMallocInternal(unsigned size,
396                                              Address lo,
397                                              Address hi,
398                                              inferiorHeapType type) {
399    infmalloc_printf("%s[%d]: inferiorMallocInternal, %d bytes, type %d, between 0x%lx - 0x%lx\n",
400                     FILE__, __LINE__, size, type, lo, hi);
401    int freeIndex = findFreeIndex(size, type, lo, hi);
402    if (freeIndex == -1) return 0; // Failure is often an option
403
404
405    // adjust active and free lists
406    assert(freeIndex != -1);
407    heapItem *h = heap_.heapFree[freeIndex];
408    assert(h);
409     
410    // remove allocated buffer from free list
411    if (h->length != size) {
412       // size mismatch: put remainder of block on free list
413       heapItem *rem = new heapItem(h);
414       rem->addr += size;
415       rem->length -= size;
416       heap_.heapFree[freeIndex] = rem;
417    } else {
418       // size match: remove entire block from free list
419       unsigned last = heap_.heapFree.size();
420       heap_.heapFree[freeIndex] = heap_.heapFree[last-1];
421       heap_.heapFree.resize(last-1);
422    }
423    // add allocated block to active list
424    h->length = size;
425    h->status = HEAPallocated;
426    heap_.heapActive[h->addr] = h;
427    // bookkeeping
428    heap_.totalFreeMemAvailable -= size;
429    assert(h->addr);
430     
431    return(h->addr);
432 }
433
434 void AddressSpace::inferiorFreeInternal(Address block) {
435    // find block on active list
436    infmalloc_printf("%s[%d]: inferiorFree for block at 0x%lx\n", FILE__, __LINE__, block);
437    heapItem *h = NULL;  
438    if (!heap_.heapActive.find(block, h)) {
439       // We can do this if we're at process teardown.
440       return;
441    }
442    assert(h);
443     
444    // Remove from the active list
445    heap_.heapActive.undef(block);
446     
447    // Add to the free list
448    h->status = HEAPfree;
449    heap_.heapFree.push_back(h);
450    heap_.totalFreeMemAvailable += h->length;
451    heap_.freed += h->length;
452    infmalloc_printf("%s[%d]: Freed block from 0x%lx - 0x%lx, %d bytes, type %d\n",
453                     FILE__, __LINE__,
454                     h->addr,
455                     h->addr + h->length,
456                     h->length,
457                     h->type);
458 }
459
460 void AddressSpace::inferiorMallocAlign(unsigned &size) {
461    // Align to the process word
462    unsigned alignment = (getAddressWidth() - 1);
463    size = (size + alignment) & ~alignment;
464 }
465     
466 bool AddressSpace::inferiorReallocInternal(Address block, unsigned newSize) {
467 #if defined (cap_dynamic_heap)
468    // This is why it's not a reference...
469    inferiorMallocAlign(newSize);
470 #endif
471     
472    infmalloc_printf("%s[%d]: inferiorRealloc for block 0x%lx, new size %d\n",
473                     FILE__, __LINE__, block, newSize);
474
475    // find block on active list
476    heapItem *h = NULL;  
477    if (!heap_.heapActive.find(block, h)) {
478       // We can do this if we're at process teardown.
479       infmalloc_printf("%s[%d]: inferiorRealloc unable to find block, returning\n", FILE__, __LINE__);
480       return false;
481    }
482    assert(h);
483    infmalloc_printf("%s[%d]: inferiorRealloc found block with addr 0x%lx, length %d\n",
484                     FILE__, __LINE__, h->addr, h->length);
485
486    if (h->length == newSize)
487       return true;
488    else if (h->length > newSize) {
489       // Shrink the block
490       return inferiorShrinkBlock(h, block, newSize);
491    }
492    else {
493       // See if we can grow this block
494       return inferiorExpandBlock(h, block, newSize);
495    }
496 }
497
498 bool AddressSpace::inferiorShrinkBlock(heapItem *h, 
499                                        Address block, 
500                                        unsigned newSize) {
501
502    // We make a new "free" block that is the end of this one.
503    Address freeStart = block + newSize;
504    Address succAddr = h->addr + h->length;
505    int shrink = h->length - newSize;
506     
507    assert(shrink > 0);
508     
509    h->length = newSize;
510     
511    // New speedy way. Find the block that is the successor of the
512    // active block; if it exists, simply enlarge it "downwards". Otherwise,
513    // make a new block. 
514    heapItem *succ = NULL;
515    for (unsigned i = 0; i < heap_.heapFree.size(); i++) {
516       heapItem *tmp = heap_.heapFree[i];
517       assert(tmp);
518       if (tmp->addr == succAddr) {
519          succ = tmp;
520          break;
521       }
522    }
523    if (succ != NULL) {
524       infmalloc_printf("%s[%d]: enlarging existing block; old 0x%lx - 0x%lx (%d), new 0x%lx - 0x%lx (%d)\n",
525                        FILE__, __LINE__,
526                        succ->addr,
527                        succ->addr + succ->length,
528                        succ->addr,
529                        succ->addr - shrink,
530                        succ->addr + succ->length,
531                        succ->length + shrink);
532
533
534       succ->addr -= shrink;
535       succ->length += shrink;
536    }
537    else {
538       // Must make a new block to represent the free memory
539       infmalloc_printf("%s[%d]: inferiorRealloc: creating new block 0x%lx to 0x%lx (%d), type %d\n",
540                        FILE__, __LINE__, 
541                        freeStart, 
542                        freeStart + shrink,
543                        shrink,
544                        h->type);
545
546       heapItem *freeEnd = new heapItem(freeStart,
547                                        shrink,
548                                        h->type,
549                                        h->dynamic,
550                                        HEAPfree);
551       heap_.heapFree.push_back(freeEnd);
552    }
553
554    heap_.totalFreeMemAvailable += shrink;
555    heap_.freed += shrink;
556
557    return true;
558 }    
559
560 bool AddressSpace::inferiorExpandBlock(heapItem *h, 
561                                        Address, 
562                                        unsigned newSize) {
563    // We attempt to find a free block that immediately succeeds
564    // this one. If we find such a block we expand this block into
565    // the next; if this is possible we return true. Otherwise
566    // we return false.
567
568    Address succAddr = h->addr + h->length;
569    int expand = newSize - h->length;
570    assert(expand > 0);
571     
572    // New speedy way. Find the block that is the successor of the
573    // active block; if it exists, simply enlarge it "downwards". Otherwise,
574    // make a new block. 
575    heapItem *succ = NULL;
576    for (unsigned i = 0; i < heap_.heapFree.size(); i++) {
577       heapItem *tmp = heap_.heapFree[i];
578       assert(tmp);
579       if (tmp->addr == succAddr) {
580          succ = tmp;
581          break;
582       }
583    }
584    if (succ != NULL) {
585       if (succ->length < (unsigned) expand) {
586          // Can't fit
587          return false;
588       }
589       Address newFreeBase = succAddr + expand;
590       int newFreeLen = succ->length - expand;
591       succ->addr = newFreeBase;
592       succ->length = newFreeLen;
593    }
594    else {
595       return false;
596    }
597
598    heap_.totalFreeMemAvailable -= expand;
599   
600    return true;
601 }    
602
603 /////////////////////////////////////////
604 // Function lookup...
605 /////////////////////////////////////////
606
607 bool AddressSpace::findFuncsByAll(const std::string &funcname,
608                                   pdvector<func_instance *> &res,
609                                   const std::string &libname) { // = "", btw
610     
611    unsigned starting_entries = res.size(); // We'll return true if we find something
612    for (unsigned i = 0; i < mapped_objects.size(); i++) {
613       if (libname == "" ||
614           mapped_objects[i]->fileName() == libname.c_str() ||
615           mapped_objects[i]->fullName() == libname.c_str()) {
616          const pdvector<func_instance *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
617          if (pretty) {
618             // We stop at first match...
619             for (unsigned pm = 0; pm < pretty->size(); pm++) {
620                res.push_back((*pretty)[pm]);
621             }
622          }
623          else {
624             const pdvector<func_instance *> *mangled = mapped_objects[i]->findFuncVectorByMangled(funcname);
625             if (mangled) {
626                for (unsigned mm = 0; mm < mangled->size(); mm++) {
627                   res.push_back((*mangled)[mm]);
628                }
629             }
630          }
631       }
632    }
633
634    return (res.size() != starting_entries);
635 }
636
637
638 bool AddressSpace::findFuncsByPretty(const std::string &funcname,
639                                      pdvector<func_instance *> &res,
640                                      const std::string &libname) { // = "", btw
641
642    unsigned starting_entries = res.size(); // We'll return true if we find something
643
644    for (unsigned i = 0; i < mapped_objects.size(); i++) {
645       if (libname == "" ||
646           mapped_objects[i]->fileName() == libname.c_str() ||
647           mapped_objects[i]->fullName() == libname.c_str()) {
648          const pdvector<func_instance *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
649          if (pretty) {
650             // We stop at first match...
651             for (unsigned pm = 0; pm < pretty->size(); pm++) {
652                res.push_back((*pretty)[pm]);
653             }
654          }
655       }
656    }
657    return res.size() != starting_entries;
658 }
659
660
661 bool AddressSpace::findFuncsByMangled(const std::string &funcname,
662                                       pdvector<func_instance *> &res,
663                                       const std::string &libname) { // = "", btw
664    unsigned starting_entries = res.size(); // We'll return true if we find something
665
666    for (unsigned i = 0; i < mapped_objects.size(); i++) {
667       if (libname == "" ||
668           mapped_objects[i]->fileName() == libname.c_str() ||
669           mapped_objects[i]->fullName() == libname.c_str()) {
670          const pdvector<func_instance *> *mangled = 
671             mapped_objects[i]->findFuncVectorByMangled(funcname);
672          if (mangled) {
673             for (unsigned mm = 0; mm < mangled->size(); mm++) {
674                res.push_back((*mangled)[mm]);
675             }
676          }
677       }
678    }
679    return res.size() != starting_entries;
680 }
681
682 func_instance *AddressSpace::findOnlyOneFunction(const string &name,
683                                                  const string &lib,
684                                                  bool /*search_rt_lib*/) 
685 {
686    assert(mapped_objects.size());
687
688    pdvector<func_instance *> allFuncs;
689
690    if (!findFuncsByAll(name.c_str(), allFuncs, lib.c_str()))
691       return NULL;
692
693    if (allFuncs.size() > 1) 
694    {
695       //cerr << "Warning: multiple matches for " << name << ", returning first" << endl;
696    }
697
698    return allFuncs[0];
699 }
700
701 /////////////////////////////////////////
702 // Variable lookup...
703 /////////////////////////////////////////
704
705 bool AddressSpace::findVarsByAll(const std::string &varname,
706                                  pdvector<int_variable *> &res,
707                                  const std::string &libname) { // = "", btw
708    unsigned starting_entries = res.size(); // We'll return true if we find something
709     
710    for (unsigned i = 0; i < mapped_objects.size(); i++) {
711       if (libname == "" ||
712           mapped_objects[i]->fileName() == libname.c_str() ||
713           mapped_objects[i]->fullName() == libname.c_str()) {
714          const pdvector<int_variable *> *pretty = mapped_objects[i]->findVarVectorByPretty(varname);
715          if (pretty) {
716             // We stop at first match...
717             for (unsigned pm = 0; pm < pretty->size(); pm++) {
718                res.push_back((*pretty)[pm]);
719             }
720          }
721          else {
722             const pdvector<int_variable *> *mangled = mapped_objects[i]->findVarVectorByMangled(varname);
723             if (mangled) {
724                for (unsigned mm = 0; mm < mangled->size(); mm++) {
725                   res.push_back((*mangled)[mm]);
726                }
727             }
728          }
729       }
730    }
731
732    return res.size() != starting_entries;
733 }
734
735
736
737 // Get me a pointer to the instruction: the return is a local
738 // (mutator-side) store for the mutatee. This may duck into the local
739 // copy for images, or a relocated function's self copy.
740 // TODO: is this really worth it? Or should we just use ptrace?
741
742 void *AddressSpace::getPtrToInstruction(const Address addr) const {
743    mapped_object *obj = findObject(addr);
744    if (obj) return obj->getPtrToInstruction(addr);
745
746    fprintf(stderr,"[%s:%d] failed to find matching range for address %lx\n",
747            FILE__,__LINE__,addr);
748    assert(0);
749    return NULL;
750 }
751
752 bool AddressSpace::isCode(const Address addr) const {
753    mapped_object *obj = findObject(addr);
754    if (!obj) return false;
755
756    Address objStart = obj->codeAbs();
757    Address objEnd;
758    if (BPatch_defensiveMode == obj->hybridMode()) {
759       objEnd = obj->memoryEnd();
760    } else {
761       objEnd = objStart + obj->imageSize();
762    }
763
764    return (addr >= objStart && addr <= objEnd);
765
766 }
767 bool AddressSpace::isData(const Address addr) const {
768    mapped_object *obj = findObject(addr);
769    if (!obj) return false;
770    
771    Address dataStart = obj->dataAbs();
772    if (addr >= dataStart &&
773        addr < (dataStart + obj->dataSize())) return true;
774    return false;
775 }
776
777 bool AddressSpace::isValidAddress(const Address addr) const {
778    mapped_object *obj = findObject(addr);
779    if (!obj) return false;
780    if ( obj->parse_img()->getObject()->isCode(addr - obj->codeBase()) ||
781         obj->parse_img()->getObject()->isData(addr - obj->dataBase())   )
782       return true;
783    return false;
784 }
785
786 mapped_object *AddressSpace::findObject(Address addr) const {
787    for (unsigned i=0; i<mapped_objects.size(); i++)
788    {
789       Address objStart = mapped_objects[i]->codeAbs();
790       Address objEnd; // calculate objEnd
791       if (BPatch_defensiveMode == mapped_objects[i]->hybridMode()) {
792          objEnd = mapped_objects[i]->memoryEnd();
793       } else {
794          objEnd = objStart + mapped_objects[i]->imageSize();
795       }
796
797       if (addr >= objStart && addr < objEnd)
798       {
799          return mapped_objects[i];
800       }
801    }
802    return NULL;
803 }
804
805 mapped_object *AddressSpace::findObject(const ParseAPI::CodeObject *co) const {
806    mapped_object *obj = 
807       findObject(static_cast<ParseAPI::SymtabCodeSource*>(co->cs())->
808                  getSymtabObject()->file());
809    return obj;
810 }
811
812 func_instance *AddressSpace::findFunction(parse_func *ifunc) {
813    assert(ifunc);
814
815    return findObject(ifunc->obj())->findFunction(ifunc);
816 }
817
818 block_instance *AddressSpace::findBlock(parse_block *iblk) {
819    assert(iblk);
820
821    return findObject(iblk->obj())->findBlock(iblk);
822 }
823
824 edge_instance *AddressSpace::findEdge(ParseAPI::Edge *iedge) {
825    assert(iedge);
826    return findObject(iedge->src()->obj())->findEdge(iedge);
827 }
828
829 // findModule: returns the module associated with mod_name 
830 // this routine checks both the a.out image and any shared object
831 // images for this resource
832 mapped_module *AddressSpace::findModule(const std::string &mod_name, bool wildcard)
833 {
834    // KLUDGE: first search any shared libraries for the module name 
835    //  (there is only one module in each shared library, and that 
836    //  is the library name)
837    for(u_int j=0; j < mapped_objects.size(); j++){
838       mapped_module *mod = mapped_objects[j]->findModule(mod_name.c_str(), wildcard);
839       if (mod) {
840          return (mod);
841       }
842    }
843    return NULL;
844 }
845
846 // findObject: returns the object associated with obj_name 
847 // This just iterates over the mapped object vector
848 mapped_object *AddressSpace::findObject(const std::string &obj_name, bool wildcard) const
849 {
850    for(u_int j=0; j < mapped_objects.size(); j++){
851       if (mapped_objects[j]->fileName() == obj_name.c_str() ||
852           mapped_objects[j]->fullName() == obj_name.c_str() ||
853           (wildcard &&
854            (wildcardEquiv(obj_name, mapped_objects[j]->fileName()) ||
855             wildcardEquiv(obj_name, mapped_objects[j]->fullName()))))
856          return mapped_objects[j];
857    }
858    return NULL;
859 }
860
861 // findObject: returns the object associated with obj_name 
862 // This just iterates over the mapped object vector
863 mapped_object *AddressSpace::findObject(fileDescriptor desc) const
864 {
865    for(u_int j=0; j < mapped_objects.size(); j++){
866       if (desc == mapped_objects[j]->getFileDesc()) 
867          return mapped_objects[j];
868    }
869    return NULL;
870 }
871
872 // getAllFunctions: returns a vector of all functions defined in the
873 // a.out and in the shared objects
874
875 void AddressSpace::getAllFunctions(pdvector<func_instance *> &funcs) {
876    for (unsigned i = 0; i < mapped_objects.size(); i++) {
877       mapped_objects[i]->getAllFunctions(funcs);
878    }
879 }
880       
881 // getAllModules: returns a vector of all modules defined in the
882 // a.out and in the shared objects
883
884 void AddressSpace::getAllModules(pdvector<mapped_module *> &mods){
885    for (unsigned i = 0; i < mapped_objects.size(); i++) {
886       const pdvector<mapped_module *> &obj_mods = mapped_objects[i]->getModules();
887       for (unsigned j = 0; j < obj_mods.size(); j++) {
888          mods.push_back(obj_mods[j]);
889       }
890    }
891 }
892
893 //Acts like findTargetFuncByAddr, but also finds the function if addr
894 // is an indirect jump to a function.
895 //I know this is an odd function, but darn I need it.
896 func_instance *AddressSpace::findJumpTargetFuncByAddr(Address addr) {
897
898    Address addr2 = 0;
899    func_instance *f = findOneFuncByAddr(addr);
900    if (f)
901       return f;
902
903    if (!findObject(addr)) return NULL;
904
905    using namespace Dyninst::InstructionAPI;
906    InstructionDecoder decoder((const unsigned char*)getPtrToInstruction(addr),
907                               InstructionDecoder::maxInstructionLength,
908                               getArch());
909    Instruction::Ptr curInsn = decoder.decode();
910     
911    Expression::Ptr target = curInsn->getControlFlowTarget();
912    RegisterAST thePC = RegisterAST::makePC(getArch());
913    target->bind(&thePC, Result(u32, addr));
914    Result cft = target->eval();
915    if(cft.defined)
916    {
917       switch(cft.type)
918       {
919          case u32:
920             addr2 = cft.val.u32val;
921             break;
922          case s32:
923             addr2 = cft.val.s32val;
924             break;
925          default:
926             assert(!"Not implemented for non-32 bit CFTs yet!");
927             break;
928       }
929    }
930    return findOneFuncByAddr(addr2);
931 }
932
933 AstNodePtr AddressSpace::trampGuardAST() {
934    if (!trampGuardBase_) {
935       // Don't have it yet....
936       return AstNodePtr();
937    }
938
939    if (trampGuardAST_) return trampGuardAST_;
940
941    trampGuardAST_ = AstNode::operandNode(AstNode::variableAddr, trampGuardBase_->ivar());
942    return trampGuardAST_;
943 }
944
945
946 trampTrapMappings::trampTrapMappings(AddressSpace *a) :
947    needs_updating(false),
948    as(a),
949    trapTableUsed(NULL),
950    trapTableVersion(NULL),
951    trapTable(NULL),
952    trapTableSorted(NULL),
953    table_version(0),
954    table_used(0),
955    table_allocated(0),
956    table_mutatee_size(0),
957    current_table(0x0),
958    table_header(0x0),
959    blockFlushes(false)
960 {
961 }
962
963 void trampTrapMappings::copyTrapMappings(trampTrapMappings *parent)
964 {
965    needs_updating = parent->needs_updating;
966    trapTableUsed = NULL;
967    trapTableVersion = NULL;
968    trapTable = NULL;
969    trapTableSorted = NULL;
970    table_version = parent->table_version;
971    table_used = parent->table_used;
972    table_allocated = parent->table_allocated;
973    table_mutatee_size = parent->table_mutatee_size;
974    current_table = parent->current_table;
975    mapping = parent->mapping;
976 }
977
978 void trampTrapMappings::clearTrapMappings()
979 {
980    needs_updating = false;
981    trapTableUsed = NULL;
982    trapTableVersion = NULL;
983    trapTable = NULL;
984    trapTableSorted = NULL;
985    table_version = 0;
986    table_used = 0;
987    table_allocated = 0;
988    table_mutatee_size = 0;
989    current_table = 0;
990    mapping.clear();
991 }
992
993 void trampTrapMappings::addTrapMapping(Address from, Address to, 
994                                        bool write_to_mutatee)
995 {
996 #if defined(arch_x86) || defined(arch_x86_64)
997    //x86 traps occur at +1 addr
998    from++;
999 #endif
1000    tramp_mapping_t m;
1001    bool existing_trap = (mapping.count(from) != 0);
1002    m.from_addr = from;
1003    m.to_addr = to;
1004    m.written = false;
1005    m.cur_index = existing_trap ? mapping[from].cur_index : INDEX_INVALID;
1006    m.mutatee_side = write_to_mutatee;
1007    mapping[from] = m;
1008 #if defined(cap_mutatee_traps)
1009    updated_mappings.insert(& mapping[from]);
1010    if (write_to_mutatee && !existing_trap) {
1011       table_mutatee_size++;
1012    }
1013    needs_updating = true;
1014 #endif
1015 }
1016
1017 bool trampTrapMappings::definesTrapMapping(Address from)
1018 {
1019    return mapping.count(from) != 0;
1020 }
1021
1022 Address trampTrapMappings::getTrapMapping(Address from)
1023 {
1024    if (!mapping.count(from))
1025       return 0;
1026    return mapping[from].to_addr;
1027 }
1028
1029 bool trampTrapMappings::needsUpdating()
1030 {
1031    return needs_updating;
1032 }
1033
1034 bool trampTrapMappings::empty() {
1035    return mapping.empty();
1036 }
1037
1038
1039 AddressSpace *trampTrapMappings::proc() const {
1040    return as;
1041 }
1042
1043 bool mapping_sort(const trampTrapMappings::tramp_mapping_t *lhs,
1044                   const trampTrapMappings::tramp_mapping_t *rhs)
1045 {
1046    return lhs->from_addr < rhs->from_addr;
1047 }
1048
1049 #if defined(cap_32_64)
1050 void trampTrapMappings::writeToBuffer(unsigned char *buffer, unsigned long val,
1051                                       unsigned addr_width)
1052 {
1053    //Deal with the case when mutatee word size != mutator word size
1054    if (addr_width != sizeof(Address)) {
1055       //Currently only support 64-bit mutators with 32-bit mutatees
1056       assert(addr_width == 4);
1057       assert(sizeof(Address) == 8);
1058       *((uint32_t *) buffer) = (uint32_t) val;
1059       return;
1060    }
1061    *((unsigned long *) buffer) = val;
1062 }
1063 #else
1064 void trampTrapMappings::writeToBuffer(unsigned char *buffer, unsigned long val,
1065                                       unsigned)
1066 {
1067    *((unsigned long *)(void*) buffer) = val;
1068 }
1069 #endif
1070
1071
1072 void trampTrapMappings::writeTrampVariable(const int_variable *var, 
1073                                            unsigned long val)
1074 {
1075    unsigned char buffer[16];
1076    unsigned aw = proc()->getAddressWidth();
1077
1078    writeToBuffer(buffer, val, aw);
1079    bool result = proc()->writeDataSpace((void *) var->getAddress(), aw, buffer);
1080    assert(result);
1081 }
1082                   
1083 void trampTrapMappings::arrange_mapping(tramp_mapping_t &m, bool should_sort,
1084                                         std::vector<tramp_mapping_t*> &mappings_to_add,
1085                                         std::vector<tramp_mapping_t*> &mappings_to_update)
1086 {
1087    if (!m.mutatee_side || (m.written && !should_sort))
1088       return;
1089    m.written = true;
1090    if (should_sort || m.cur_index == INDEX_INVALID)
1091       mappings_to_add.push_back(&m);
1092    else if (m.cur_index != INDEX_INVALID)
1093       mappings_to_update.push_back(&m);
1094 }
1095
1096 void trampTrapMappings::flush() {
1097    if (!needs_updating || blockFlushes)
1098       return;
1099
1100    set<mapped_object *> &rtlib = proc()->runtime_lib;
1101
1102    //We'll sort addresses in the binary rewritter (when writting only happens
1103    // once and we may do frequent lookups)
1104    //If we're using the dynamic instrumentor and creating a new table we might
1105    // as well sort it.
1106    //If we're just adding a few entries to the table which already fit, then
1107    // we'll just append them to the end of the table.
1108    //
1109    //If we're sorting, then everytime we update we'll generate a whole new table
1110    //If we're not sorting, then each update will just append to the end of the
1111    // table.
1112    bool should_sort = (dynamic_cast<process *>(proc()) == NULL ||
1113                        table_mutatee_size > table_allocated);
1114
1115    if (should_sort) {
1116       table_used = 0; //We're rebuilding the table, nothing's used.
1117    }
1118
1119    /**
1120     * Fill in the mappings_to_add and mappings_to_update vectors.
1121     * As an optimization, we keep a list of the mappings that have
1122     * changed in updated_mappings.  If we're not completly regenerating
1123     * the table we'll get our trap list out of updated_mappings, 
1124     * otherwise we'll get our change list out of the entire dyn_hash_map.
1125     **/
1126    std::vector<tramp_mapping_t*> mappings_to_add;
1127    std::vector<tramp_mapping_t*> mappings_to_update;
1128    if (should_sort) {
1129       dyn_hash_map<Address, tramp_mapping_t>::iterator i;
1130       for (i = mapping.begin(); i != mapping.end(); i++) {
1131          arrange_mapping((*i).second, should_sort, 
1132                          mappings_to_add, mappings_to_update);
1133       }
1134    } 
1135    else {
1136       std::set<tramp_mapping_t *>::iterator i;
1137       for (i = updated_mappings.begin(); i != updated_mappings.end(); i++) {
1138          arrange_mapping(**i, should_sort, 
1139                          mappings_to_add, mappings_to_update);
1140       }
1141    }
1142    updated_mappings.clear();
1143
1144    assert(mappings_to_add.size() + table_used == table_mutatee_size);
1145
1146    for (unsigned k=0; k<mappings_to_add.size(); k++)
1147    {
1148       mappings_to_add[k]->written = true;
1149    }
1150
1151    //Sort the mappings (if needed) 
1152    if (should_sort) 
1153       std::sort(mappings_to_add.begin(), mappings_to_add.end(), mapping_sort);
1154
1155    // Assign the cur_index field of each entry in the new mappings we're adding
1156    for (unsigned j=0; j<mappings_to_add.size(); j++) {
1157       mappings_to_add[j]->cur_index = table_used + j;
1158    }
1159    
1160    //Each table entry has two pointers.
1161    unsigned entry_size = proc()->getAddressWidth() * 2;
1162
1163    Address write_addr = 0x0;
1164
1165    allocateTable();
1166
1167    //Add any new entries to the table
1168    unsigned char *buffer = NULL;
1169    if (mappings_to_add.size()) {
1170       //Create a buffer containing the new entries we're going to write.
1171       unsigned long bytes_to_add = mappings_to_add.size() * entry_size;
1172       buffer = (unsigned char *) malloc(bytes_to_add);
1173       assert(buffer);
1174       
1175       unsigned char *cur = buffer;
1176       std::vector<tramp_mapping_t*>::iterator j;
1177       for (j = mappings_to_add.begin(); j != mappings_to_add.end(); j++) {
1178          tramp_mapping_t &tm = **j;
1179          writeToBuffer(cur, tm.from_addr, proc()->getAddressWidth());
1180          cur += proc()->getAddressWidth();
1181          writeToBuffer(cur, tm.to_addr, proc()->getAddressWidth());
1182          cur += proc()->getAddressWidth();
1183       }
1184       assert(cur == buffer + bytes_to_add);
1185       
1186       //Write the new entries into the process
1187       write_addr = current_table + (table_used * entry_size);
1188       bool result = proc()->writeDataSpace((void *) write_addr, bytes_to_add, 
1189                                            buffer);
1190       assert(result);
1191       free(buffer);
1192       buffer = NULL;
1193
1194       table_used += mappings_to_add.size();
1195    }
1196
1197    //Now we get to update existing entries that have been modified.
1198    if (mappings_to_update.size()) {
1199       assert(!should_sort);
1200       unsigned aw = proc()->getAddressWidth();
1201       buffer = (unsigned char *) malloc(aw);
1202       assert(buffer);
1203
1204       //For each entry, use its cur_index field to figure out where in the
1205       // process it is, and write it.
1206       //We only need to update the to_addr, since this is an update of an
1207       // existing from_addr
1208       std::vector<tramp_mapping_t*>::iterator j;
1209       for (j = mappings_to_update.begin(); j != mappings_to_update.end(); j++) {
1210          tramp_mapping_t &tm = **j;
1211          writeToBuffer(buffer, tm.to_addr, aw);
1212
1213          Address write_addr = current_table + (tm.cur_index * entry_size) + aw;
1214          bool result = proc()->writeDataSpace((void *) write_addr, aw, buffer);
1215          assert(result);
1216       }
1217       
1218       free(buffer);
1219       buffer = NULL;
1220    }
1221
1222    //This function just keeps going... Now we need to take all of those 
1223    // mutatee side variables and update them.
1224    if (dynamic_cast<process *>(proc())) 
1225    {
1226       if (!trapTable) {
1227          //Lookup all variables that are in the rtlib
1228          set<mapped_object *>::iterator rtlib_it;
1229          for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
1230             if( !trapTableUsed ) trapTableUsed = (*rtlib_it)->getVariable("dyninstTrapTableUsed");
1231             if( !trapTableVersion ) trapTableVersion = (*rtlib_it)->getVariable("dyninstTrapTableVersion");
1232             if( !trapTable ) trapTable = (*rtlib_it)->getVariable("dyninstTrapTable");
1233             if( !trapTableSorted ) trapTableSorted = (*rtlib_it)->getVariable("dyninstTrapTableIsSorted");
1234          }
1235          
1236          if (!trapTableUsed) {
1237             fprintf(stderr, "Dyninst is about to crash with an assert.  Either your dyninstAPI_RT library is stripped, or you're using an older version of dyninstAPI_RT with a newer version of dyninst.  Check your DYNINSTAPI_RT_LIB enviroment variable.\n");
1238          }
1239          assert(trapTableUsed);
1240          assert(trapTableVersion);
1241          assert(trapTable);
1242          assert(trapTableSorted);
1243       }
1244    
1245       writeTrampVariable(trapTableUsed, table_used);
1246       writeTrampVariable(trapTableVersion, ++table_version);
1247       writeTrampVariable(trapTable, (unsigned long) current_table);
1248       writeTrampVariable(trapTableSorted, should_sort ? 1 : 0);
1249    }
1250
1251    needs_updating = false;
1252 }
1253
1254 void trampTrapMappings::allocateTable()
1255 {
1256    unsigned entry_size = proc()->getAddressWidth() * 2;
1257
1258    if (dynamic_cast<process *>(proc()))
1259    {
1260       //Dynamic rewriting
1261
1262       //Allocate the space for the tramp mapping table, or make sure that enough
1263       // space already exists.
1264       if (table_mutatee_size > table_allocated) {
1265          //Free old table
1266          if (current_table) {
1267             proc()->inferiorFree(current_table);
1268          }
1269          
1270          //Calculate size of new table
1271          table_allocated = (unsigned long) (table_mutatee_size * 1.5);
1272          if (table_allocated < MIN_TRAP_TABLE_SIZE)
1273             table_allocated = MIN_TRAP_TABLE_SIZE;
1274          
1275          //allocate
1276          current_table = proc()->inferiorMalloc(table_allocated * entry_size);
1277          assert(current_table);
1278       }
1279       return;
1280    }
1281
1282    //Static rewriting
1283    BinaryEdit *binedit = dynamic_cast<BinaryEdit *>(proc());
1284    assert(!current_table);
1285    assert(binedit);
1286    
1287    table_allocated = (unsigned long) table_mutatee_size;
1288    table_header = proc()->inferiorMalloc(table_allocated * entry_size + 
1289                                          sizeof(trap_mapping_header));
1290    trap_mapping_header header;
1291    header.signature = TRAP_HEADER_SIG;
1292    header.num_entries = table_mutatee_size;
1293    header.pos = -1;
1294    header.low_entry = 0;
1295    header.high_entry = 0;
1296
1297    bool result = proc()->writeDataSpace((void *) table_header, 
1298                                         sizeof(trap_mapping_header),
1299                                         &header);
1300    assert(result);   
1301    current_table = table_header + sizeof(trap_mapping_header);
1302
1303    SymtabAPI::Symtab *symtab = 
1304       binedit->getMappedObject()->parse_img()->getObject();
1305    if( !symtab->isStaticBinary() ) {
1306        symtab->addSysVDynamic(DT_DYNINST, table_header);
1307        symtab->addLibraryPrereq(proc()->dyninstRT_name);
1308       symtab->addSysVDynamic(DT_DYNINST, table_header);
1309       symtab->addLibraryPrereq(proc()->dyninstRT_name);
1310 #if defined (os_windows)
1311       symtab->addTrapHeader_win((Address)table_header);
1312 #endif
1313
1314    }
1315 }
1316
1317 bool AddressSpace::findFuncsByAddr(Address addr, std::set<func_instance*> &funcs, bool includeReloc)
1318 {
1319    if (includeReloc) {
1320       RelocInfo ri;
1321       if (getRelocInfo(addr, ri)) {
1322          if (ri.func) {
1323             // We cloned for some reason. Nifty.
1324             funcs.insert(ri.func);
1325          }
1326          else {
1327             // We copied a block sans function context, so...
1328             // grab everyone
1329             ri.block->getFuncs(std::inserter(funcs, funcs.end()));
1330          }
1331          return true;
1332       }
1333    }
1334    mapped_object *obj = findObject(addr);
1335    if (!obj) return false;
1336    return obj->findFuncsByAddr(addr, funcs);
1337 }
1338
1339 bool AddressSpace::findBlocksByAddr(Address addr, std::set<block_instance *> &blocks, bool includeReloc) {
1340    if (includeReloc) {
1341       RelocInfo ri;
1342       if (getRelocInfo(addr, ri)) {
1343          blocks.insert(ri.block);
1344          return true;
1345       }
1346    }
1347
1348    mapped_object *obj = findObject(addr);
1349    if (!obj) return false;
1350    bool ret = obj->findBlocksByAddr(addr, blocks);
1351    if (ret || !includeReloc)
1352       return ret;
1353    return false;
1354 }
1355
1356 func_instance *AddressSpace::findFuncByEntry(const block_instance *block) {
1357    mapped_object *obj = findObject(block->start());
1358    if (!obj) return NULL;
1359    return obj->findFuncByEntry(block);
1360 }
1361
1362 block_instance *AddressSpace::findBlockByEntry(Address a) {
1363    mapped_object *obj = findObject(a);
1364    if (!obj) return NULL;
1365    return obj->findBlockByEntry(a);
1366 }
1367
1368 func_instance *AddressSpace::findOneFuncByAddr(Address addr) {
1369    std::set<func_instance *> funcs;
1370    if (!findFuncsByAddr(addr, funcs)) return NULL;
1371    if (funcs.empty()) return NULL;
1372    if (funcs.size() == 1) return *(funcs.begin());
1373    // Arbitrarily pick one...
1374    Address last = 0;
1375    func_instance *ret = NULL;
1376    for (std::set<func_instance *>::iterator iter = funcs.begin();
1377         iter != funcs.end(); ++iter) {
1378       if (ret == NULL ||
1379           ((*iter)->entryBlock()->start() > last)) {
1380          ret = *iter;
1381          last = (*iter)->entryBlock()->start();
1382       }
1383    }
1384    return ret;
1385 }
1386
1387 func_instance *AddressSpace::findFuncByEntry(Address addr) {
1388    std::set<func_instance *> funcs;
1389    if (!findFuncsByAddr(addr, funcs)) return NULL;
1390    if (funcs.empty()) return NULL;
1391
1392    for (std::set<func_instance *>::iterator iter = funcs.begin();
1393         iter != funcs.end(); ++iter) {
1394       if ((*iter)->entryBlock()->start() == addr) {
1395          return *iter;
1396       }
1397    }
1398    return NULL;
1399 }
1400
1401
1402 bool AddressSpace::canUseTraps()
1403 {
1404    BinaryEdit *binEdit = dynamic_cast<BinaryEdit *>(this);
1405    if (binEdit && binEdit->getMappedObject()->parse_img()->getObject()->isStaticBinary())
1406       return false;
1407
1408 #if !defined(cap_mutatee_traps)
1409    return false;
1410 #endif
1411    
1412    return useTraps_;
1413 }
1414
1415 void AddressSpace::setUseTraps(bool usetraps)
1416 {
1417    useTraps_ = usetraps;
1418 }
1419
1420 bool AddressSpace::needsPIC(int_variable *v)
1421 {
1422    return needsPIC(v->mod()->proc());
1423 }
1424
1425 bool AddressSpace::needsPIC(func_instance *f)
1426 {
1427    return needsPIC(f->proc());
1428 }
1429
1430 bool AddressSpace::needsPIC(AddressSpace *s)
1431 {
1432    if (proc())
1433       return false; //Never PIC for dynamic
1434    if (this != s)
1435       return true; //Use PIC cross module
1436    return s->needsPIC(); //Use target module
1437 }
1438
1439 bool AddressSpace::sameRegion(Address addr1, Address addr2)
1440 {
1441    mapped_object *mobj = findObject(addr1);
1442    if (!mobj || mobj != findObject(addr2)) {
1443       return false;
1444    }
1445    Address baseAddr = mobj->codeBase();
1446
1447    SymtabAPI::Region *reg1 = 
1448       mobj->parse_img()->getObject()->findEnclosingRegion( addr1 - baseAddr );
1449
1450    if (!reg1 || reg1 != mobj->parse_img()->getObject()->
1451        findEnclosingRegion( addr2 - baseAddr )) {
1452       return false;
1453    }
1454    return true;
1455 }
1456 ////////////////////////////////////////////////////////////////////////////////////////
1457
1458 void AddressSpace::modifyCall(block_instance *block, func_instance *newFunc, func_instance *context) {
1459    // Just register it for later code generation
1460    //callModifications_[block][context] = newFunc;
1461    mgr()->instrumenter()->modifyCall(block, newFunc, context);
1462    if (context) addModifiedFunction(context);
1463    else addModifiedBlock(block);
1464 }
1465
1466 void AddressSpace::replaceFunction(func_instance *oldfunc, func_instance *newfunc) {
1467    mgr()->instrumenter()->replaceFunction(oldfunc, newfunc);
1468    addModifiedFunction(oldfunc);
1469 }
1470
1471 bool AddressSpace::wrapFunction(func_instance *original, 
1472                                 func_instance *wrapper,
1473                                 SymtabAPI::Symbol *clone) {
1474    if (!original) return false;
1475    if (!wrapper) return false;
1476    if (!clone) return false;
1477
1478    if (original->proc() != this) {
1479       return original->proc()->wrapFunction(original, wrapper, clone);
1480    }
1481    assert(original->proc() == this);
1482
1483
1484    // 1) Replace original with wrapper via entry point jumps;
1485    //    this is handled in the instrumenter. 
1486    // 2) Create a copy of original with the new provided name. 
1487    // 3) (binary editing): update the various Symtab tables
1488    //    with the new name.
1489
1490    // TODO: once we have PatchAPI updated a bit, break this into
1491    // steps 1-3. For now, keep it together. 
1492    mgr()->instrumenter()->wrapFunction(original, wrapper, clone->getMangledName());
1493    addModifiedFunction(original);
1494
1495    if (edit()) {
1496       if (!AddressSpace::patch(this)) return false;
1497       if (!original->addSymbolsForCopy()) return false;
1498    }
1499    else {
1500       addModifiedFunction(wrapper);
1501       // TODO dynamic mode; we need to update the names. 
1502       return false;
1503    }
1504    return true;
1505 }
1506
1507 void AddressSpace::removeCall(block_instance *block, func_instance *context) {
1508   mgr()->instrumenter()->removeCall(block, context);
1509 }
1510
1511 void AddressSpace::revertCall(block_instance *block, func_instance *context) {
1512   /*
1513    if (callModifications_.find(block) != callModifications_.end()) {
1514       callModifications_[block].erase(context);
1515    }
1516   */
1517   mgr()->instrumenter()->revertModifiedCall(block, context);
1518   if (context) addModifiedFunction(context);
1519   else addModifiedBlock(block);
1520 }
1521
1522 void AddressSpace::revertReplacedFunction(func_instance *oldfunc) {
1523   //functionReplacements_.erase(oldfunc);
1524   mgr()->instrumenter()->revertReplacedFunction(oldfunc);
1525   addModifiedFunction(oldfunc);
1526 }
1527
1528
1529 using namespace Dyninst;
1530 using namespace Relocation;
1531
1532 bool AddressSpace::relocate() {
1533    if (delayRelocation()) return true;
1534
1535
1536   relocation_cerr << "ADDRSPACE::Relocate called!" << endl;
1537   if (!mapped_objects.size()) {
1538     relocation_cerr << "WARNING: No mapped_object in this addressSpace!\n";
1539     return false;
1540   }
1541
1542   bool ret = true;
1543   for (std::map<mapped_object *, FuncSet>::iterator iter = modifiedFunctions_.begin();
1544        iter != modifiedFunctions_.end(); ++iter) {
1545     assert(iter->first);
1546
1547     bool repeat;
1548     FuncSet checkFuncs;
1549     checkFuncs.insert(iter->second.begin(), iter->second.end());
1550     do { // add overlapping functions in a fixpoint calculation
1551         repeat = false;
1552         FuncSet overlappingFuncs;
1553         for (FuncSet::iterator iter2 = checkFuncs.begin(); iter2 != checkFuncs.end(); ++iter2) {
1554            (*iter2)->getOverlappingFuncs(overlappingFuncs);
1555         }
1556         // init checkFuncs for next iteration
1557         unsigned int prevSize = iter->second.size();
1558         checkFuncs.clear();
1559         checkFuncs.insert(overlappingFuncs.begin(), overlappingFuncs.end());
1560         for (FuncSet::iterator iter2=iter->second.begin(); 
1561              iter2 != iter->second.end(); 
1562              iter2++) 
1563         {
1564             checkFuncs.erase(*iter2);
1565         }
1566         // add overlapping funcs, if any
1567         iter->second.insert(overlappingFuncs.begin(), overlappingFuncs.end());
1568         if (prevSize < iter->second.size()) {
1569             repeat = true;
1570         }
1571     } while (repeat);
1572
1573     addModifiedRegion(iter->first);
1574
1575     Address middle = (iter->first->codeAbs() + (iter->first->imageSize() / 2));
1576
1577     if (!relocateInt(iter->second.begin(), iter->second.end(), middle)) {
1578       ret = false;
1579     }
1580
1581   }
1582
1583   updateMemEmulator();
1584
1585   modifiedFunctions_.clear();
1586   return ret;
1587 }
1588
1589 // iter is some sort of functions
1590 bool AddressSpace::relocateInt(FuncSet::const_iterator begin, FuncSet::const_iterator end, Address nearTo) {
1591
1592   if (begin == end) {
1593     return true;
1594   }
1595
1596   // Create a CodeMover covering these functions
1597   //cerr << "Creating a CodeMover" << endl;
1598
1599   relocatedCode_.push_back(new CodeTracker());
1600   CodeMover::Ptr cm = CodeMover::create(relocatedCode_.back());
1601   if (!cm->addFunctions(begin, end)) return false;
1602
1603   SpringboardBuilder::Ptr spb = SpringboardBuilder::createFunc(begin, end, this);
1604
1605   relocation_cerr << "Debugging CodeMover (pre-transform)" << endl;
1606   relocation_cerr << cm->format() << endl;
1607   transform(cm);
1608
1609   relocation_cerr << "Debugging CodeMover" << endl;
1610   relocation_cerr << cm->format() << endl;
1611
1612   relocation_cerr << "  Entering code generation loop" << endl;
1613   Address baseAddr = generateCode(cm, nearTo);
1614   if (!baseAddr) {
1615     relocation_cerr << "  ERROR: generateCode returned baseAddr of " << baseAddr << ", exiting" << endl;
1616     return false;
1617   }
1618
1619   if (dyn_debug_reloc || dyn_debug_write) {
1620       using namespace InstructionAPI;
1621       // Print out the buffer we just created
1622       cerr << "DUMPING RELOCATION BUFFER" << endl;
1623
1624       Address base = baseAddr;
1625       InstructionDecoder deco
1626         (cm->ptr(),cm->size(),getArch());
1627       Instruction::Ptr insn = deco.decode();
1628       while(insn) {
1629         cerr << "\t" << hex << base << ": " << insn->format(base) << endl;
1630         base += insn->size();
1631         insn = deco.decode();
1632       }
1633       cerr << dec;
1634       cerr << endl;
1635       cerr << cm->format() << endl;
1636
1637   }
1638
1639
1640   // Copy it in
1641   relocation_cerr << "  Writing " << cm->size() << " bytes of data into program at "
1642                   << std::hex << baseAddr << std::dec << endl;
1643   if (!writeTextSpace((void *)baseAddr,
1644                       cm->size(),
1645                       cm->ptr()))
1646     return false;
1647
1648   // Now handle patching; AKA linking
1649   relocation_cerr << "  Patching in jumps to generated code" << endl;
1650
1651   if (!patchCode(cm, spb)) {
1652       cerr << "Error: patching in jumps failed, ret false!" << endl;
1653     return false;
1654   }
1655
1656   // Build the address mapping index
1657   relocatedCode_.back()->createIndices();
1658     
1659   // Kevin's stuff
1660   cm->extractDefensivePads(this);
1661
1662   if (proc() && BPatch_defensiveMode == proc()->getHybridMode()) {
1663       // adjust PC if active frame is in a modified function, this 
1664       // forces the instrumented version of the code to execute right 
1665       // away and is needed for code overwrites
1666       vector<dyn_thread*>::const_iterator titer;
1667       for (titer=proc()->threads.begin();
1668            titer != proc()->threads.end(); 
1669            titer++) 
1670       {
1671           // translate thread's active PC to orig addr
1672           Frame tframe = (*titer)->getActiveFrame();
1673           Address relocAddr = tframe.getPC();
1674           mal_printf("Attempting to change PC: current addr is 0x%lx\n", relocAddr);
1675
1676           RelocInfo ri;
1677           if (!getRelocInfo(relocAddr, ri)) continue; // Not in instrumentation already
1678
1679           // HACK: if we're in the middle of an emulation block, add that
1680           // offset to where we transfer to. 
1681           TrackerElement *te = NULL;
1682           for (CodeTrackers::const_iterator iter = relocatedCode_.begin();
1683                iter != relocatedCode_.end(); ++iter) {
1684              te = (*iter)->findByReloc(relocAddr);
1685              if (te) break;
1686           }
1687
1688           Address offset = 0;
1689           if (te && te->type() == TrackerElement::emulated) {
1690              offset = relocAddr - te->reloc();
1691              assert(offset < te->size());
1692           }
1693           
1694           list<Address> relocPCs;
1695           getRelocAddrs(ri.orig, ri.block, ri.func, relocPCs, false);
1696           if (relocPCs.size()) {
1697              (*titer)->get_lwp()->changePC(relocPCs.back() + offset,NULL);
1698              mal_printf("Pulling active frame PC into newest relocation "
1699                         "orig[%lx], cur[%lx], new[%lx (0x%lx + 0x%lx)] %s[%d]\n", ri.orig, 
1700                         tframe.getPC(), relocPCs.back() + offset, relocPCs.back(), offset,
1701                         FILE__,__LINE__);
1702              break;
1703           }
1704       }
1705   }
1706   
1707   return true;
1708 }
1709
1710 bool AddressSpace::transform(CodeMover::Ptr cm) {
1711
1712    adhocMovementTransformer a(this);
1713    cm->transform(a);
1714
1715 #if 0
1716    if (proc() && BPatch_defensiveMode != proc()->getHybridMode()) {
1717    }
1718    else {
1719        PCSensitiveTransformer pc(this, cm->priorityMap());
1720         cm->transform(pc);
1721    }
1722 #endif
1723
1724 #if defined(cap_mem_emulation)
1725    if (emulateMem_) {
1726       MemEmulatorTransformer m;
1727       cm->transform(m);
1728   }
1729 #endif
1730
1731   // Add instrumentation
1732   relocation_cerr << "Inst transformer" << endl;
1733   Instrumenter i;
1734   cm->transform(i);
1735
1736    Modification mod(mgr()->instrumenter()->callModMap(),
1737                     mgr()->instrumenter()->funcRepMap(),
1738                     mgr()->instrumenter()->funcWrapMap());
1739    cm->transform(mod);
1740
1741   return true;
1742
1743 }
1744
1745 Address AddressSpace::generateCode(CodeMover::Ptr cm, Address nearTo) {
1746   // And now we start the relocation process.
1747   // This is at heart an iterative process, using the following
1748   // algorithm
1749   // size = code size estimate
1750   // done = false
1751   // While (!done), do
1752   //   addr = inferiorMalloc(size)
1753   //   cm.relocate(addr)
1754   //   if ((cm.size <= size) || (inferiorRealloc(addr, cm.size)))
1755   //     done = true
1756   //   else
1757   //     size = cm.size
1758   //     inferiorFree(addr)
1759   // In effect, we keep trying until we get a code generation that fits
1760   // in the space we have allocated.
1761
1762   Address baseAddr = 0;
1763
1764   codeGen genTemplate;
1765   genTemplate.setAddrSpace(this);
1766   // Set the code emitter?
1767   
1768   if (!cm->initialize(genTemplate)) {
1769     return 0;
1770   }
1771
1772   while (1) {
1773      relocation_cerr << "   Attempting to allocate " << cm->size() << "bytes" << endl;
1774     unsigned size = cm->size();
1775     if (!size) {
1776         // This can happen if the only thing being moved are control flow instructions
1777         // (or other things that are _only_ patches)
1778         // inferiorMalloc horks if we hand it zero, so make sure it's non-zero.
1779         size = 1;
1780     }
1781     baseAddr = inferiorMalloc(size, anyHeap, nearTo);
1782     
1783     
1784     relocation_cerr << "   Calling CodeMover::relocate" << endl;
1785     if (!cm->relocate(baseAddr)) {
1786        // Whoa
1787        relocation_cerr << "   ERROR: CodeMover failed relocation!" << endl;
1788        return 0;
1789     }
1790     
1791     // Either attempt to expand or shrink...
1792     relocation_cerr << "   Calling inferiorRealloc to fit new size " << cm->size() 
1793                     << ", current base addr is " 
1794                     << std::hex << baseAddr << std::dec << endl;
1795     if (!inferiorRealloc(baseAddr, cm->size())) {
1796       relocation_cerr << "   ... inferiorRealloc failed, trying again" << endl;
1797       inferiorFree(baseAddr);
1798       continue;
1799     }
1800     else {
1801       relocation_cerr << "   ... inferiorRealloc succeeded, finished" << endl;
1802       break;
1803     }
1804   }
1805   
1806   if (!cm->finalize()) {
1807      return 0;
1808   }
1809
1810   //addrMap.debug();
1811
1812   return baseAddr;
1813 }
1814
1815 bool AddressSpace::patchCode(CodeMover::Ptr cm,
1816                              SpringboardBuilder::Ptr spb) {
1817    SpringboardMap &p = cm->sBoardMap(this);
1818   
1819   // A SpringboardMap has three priority sets: Required, Suggested, and
1820   // NotRequired. We care about:
1821   // Required: all
1822   // Suggested: function entries
1823   // NotRequired: none
1824
1825   std::list<codeGen> patches;
1826
1827   if (!spb->generate(patches, p)) {
1828       cerr << "Failed springboard generation, ret false" << endl;
1829     return false;
1830   }
1831
1832   for (std::list<codeGen>::iterator iter = patches.begin();
1833        iter != patches.end(); ++iter) 
1834   {
1835      relocation_cerr << "Writing springboard @ " << hex << iter->startAddr() << endl;
1836         if (!writeTextSpace((void *)iter->startAddr(),
1837           iter->used(),
1838           iter->start_ptr())) 
1839       {
1840           cerr << "Failed writing a springboard branch, ret false" << endl;
1841           return false;
1842       }
1843
1844     mapped_object *obj = findObject(iter->startAddr());
1845     if (obj && runtime_lib.end() == runtime_lib.find(obj)) {
1846         Address objBase = obj->codeBase();
1847         SymtabAPI::Region * reg = obj->parse_img()->getObject()->
1848             findEnclosingRegion(iter->startAddr() - objBase);
1849         if (memEmulator_)
1850            memEmulator_->addSpringboard(reg, 
1851                                         iter->startAddr() - objBase - reg->getMemOffset(),
1852                                         iter->used());
1853     }
1854   }
1855
1856   return true;
1857 };
1858
1859 void AddressSpace::causeTemplateInstantiations() {
1860 }
1861
1862 void AddressSpace::getRelocAddrs(Address orig, 
1863                                  block_instance *block,
1864                                  func_instance *func,
1865                                  std::list<Address> &relocs,
1866                                  bool getInstrumentationAddrs) const {
1867   for (CodeTrackers::const_iterator iter = relocatedCode_.begin();
1868        iter != relocatedCode_.end(); ++iter) {
1869     Relocation::CodeTracker::RelocatedElements reloc;
1870     if ((*iter)->origToReloc(orig, block, func, reloc)) {
1871       // Pick instrumentation if it's there, otherwise use the reloc instruction
1872       if (reloc.instrumentation && getInstrumentationAddrs) {
1873         relocs.push_back(reloc.instrumentation);
1874       }
1875       else {
1876         assert(reloc.instruction);
1877         relocs.push_back(reloc.instruction);
1878       }
1879     }
1880   }
1881 }      
1882
1883 bool AddressSpace::getAddrInfo(Address relocAddr,
1884                                Address &origAddr,
1885                                vector<func_instance *> &origFuncs,
1886                                baseTramp *&baseT) 
1887 {
1888    CodeTracker::RelocInfo ri;
1889    if (getRelocInfo(relocAddr, ri)) {
1890       origAddr = ri.orig;
1891       baseT = ri.bt;
1892       if (ri.func)
1893          origFuncs.push_back(ri.func);
1894       else {
1895          // We copied a block sans function context, so...
1896          // grab everyone
1897          ri.block->getFuncs(std::back_inserter(origFuncs));
1898       }
1899       return true;
1900    }      
1901    
1902    std::set<func_instance *> tmpFuncs;
1903    if (findFuncsByAddr(relocAddr, tmpFuncs)) {
1904       origAddr = relocAddr;
1905       std::copy(tmpFuncs.begin(), tmpFuncs.end(), std::back_inserter(origFuncs));
1906       baseT = NULL;
1907       return true;
1908    }
1909       
1910    return false;
1911 }
1912
1913
1914 bool AddressSpace::getRelocInfo(Address relocAddr,
1915                                 RelocInfo &ri) {
1916   bool ret = false;
1917   // address is relocated (or bad), check relocation maps
1918   for (CodeTrackers::const_iterator iter = relocatedCode_.begin();
1919        iter != relocatedCode_.end(); ++iter) {
1920      if ((*iter)->relocToOrig(relocAddr, ri)) {
1921         assert(!ret);
1922         ret = true;
1923      }
1924   }
1925   return ret;
1926 }
1927
1928 bool AddressSpace::inEmulatedCode(Address addr) {
1929   // address is relocated (or bad), check relocation maps
1930   for (CodeTrackers::const_iterator iter = relocatedCode_.begin();
1931        iter != relocatedCode_.end(); ++iter)  {
1932      TrackerElement *te = (*iter)->findByReloc(addr);
1933      if (te) {
1934         if (te->type() == TrackerElement::emulated ||
1935             te->type() == TrackerElement::instrumentation) {
1936            return true;
1937         }
1938      }
1939   }
1940   return false;
1941 }
1942
1943 void AddressSpace::addModifiedFunction(func_instance *func) {
1944   assert(func->obj());
1945
1946   modifiedFunctions_[func->obj()].insert(func);
1947 }
1948
1949 void AddressSpace::addModifiedBlock(block_instance *block) {
1950    // TODO someday this will decouple from functions. Until
1951    // then...
1952    std::list<func_instance *> tmp;
1953    block->getFuncs(std::back_inserter(tmp));
1954    for (std::list<func_instance *>::iterator iter = tmp.begin();
1955         iter != tmp.end(); ++iter) {
1956       addModifiedFunction(*iter);
1957    }
1958 }
1959
1960
1961 void AddressSpace::addDefensivePad(block_instance *callBlock, func_instance *callFunc,
1962                                    Address padStart, unsigned size) {
1963   // We want to register these in terms of a block_instance that the pad ends, but 
1964   // the CFG can change out from under us; therefore, for lookup we use an instPoint
1965   // as they are invariant. 
1966    instPoint *point = instPoint::preCall(callFunc, callBlock);
1967    if (!point) {
1968       // We recorded a gap for some other reason than a return-address-modifying call;
1969       // ignore (for now). 
1970       //cerr << "Error: no preCall point for " << callBlock->long_format() << endl;
1971       return;
1972    }
1973    if (!point || point->empty()) {
1974        // Kevin didn't instrument it so we don't care :)
1975        return;
1976    }
1977    
1978    forwardDefensiveMap_[point].insert(std::make_pair(padStart, size));
1979    reverseDefensiveMap_.insert(padStart, padStart+size, point);
1980 }
1981
1982 void AddressSpace::getPreviousInstrumentationInstances(baseTramp *bt,
1983                                                        std::set<Address>::iterator &b,
1984                                                        std::set<Address>::iterator &e) {
1985   b = instrumentationInstances_[bt].begin();
1986   e = instrumentationInstances_[bt].end();
1987   return;
1988 }
1989
1990 void AddressSpace::addInstrumentationInstance(baseTramp *bt,
1991                                               Address a) {
1992   instrumentationInstances_[bt].insert(a);
1993 }
1994
1995 void AddressSpace::addAllocatedRegion(Address start, unsigned size) {
1996    if (memEmulator_) memEmulator_->addAllocatedRegion(start, size);
1997 }
1998
1999 void AddressSpace::addModifiedRegion(mapped_object *obj) {
2000    if (memEmulator_) memEmulator_->addRegion(obj);
2001    return;
2002 }
2003
2004 void AddressSpace::updateMemEmulator() {
2005    if (memEmulator_) memEmulator_->update();
2006 }
2007
2008 MemoryEmulator * AddressSpace::getMemEm() {
2009     return memEmulator_;
2010 }
2011
2012 void AddressSpace::invalidateMemory(Address addr, Address size) {
2013         // To do list:
2014         // Remove this section from the memory shadow
2015         // Flush the RT cache of indirect transfers
2016         // Ensure that we will catch if we transfer into this code again.
2017         // Add an override to the mapped_object so that we don't try to
2018         // set permissions on the deallocated range. 
2019         return;
2020
2021         if (memEmulator_) memEmulator_->removeRegion(addr, size);
2022
2023         proc()->flushAddressCache_RT(addr, size);
2024
2025         std::set<func_instance *> funcsToDelete;
2026         for (Address i = addr; i < (addr + size); ++i)
2027         {
2028                 findFuncsByAddr(i, funcsToDelete);
2029         }
2030
2031 }
2032
2033
2034 // create stub edge set which is: all edges such that: 
2035 //     e->trg() in owBBIs and
2036 //     while e->src() in delBlocks try e->src()->sources()
2037 std::map<func_instance*,vector<edgeStub> > 
2038 AddressSpace::getStubs(const std::list<block_instance *> &owBBIs,
2039                        const std::set<block_instance*> &delBBIs,
2040                        const std::list<func_instance*> &deadFuncs)
2041 {
2042     std::map<func_instance*,vector<edgeStub> > stubs;
2043     assert(0 && "TODO");
2044 #if 0
2045
2046     std::list<edgeStub> deadStubs;
2047     
2048     for (list<block_instance*>::const_iterator deadIter = owBBIs.begin();
2049          deadIter != owBBIs.end(); 
2050          deadIter++) 
2051     {
2052         bool inDeadFunc = false;
2053         for (list<func_instance*>::const_iterator dfit = deadFuncs.begin();
2054              dfit != deadFuncs.end(); dfit++) 
2055         {
2056            if ((*deadIter)->func() == *dfit) {
2057               inDeadFunc = true;
2058               break;
2059            }
2060         }
2061         if (inDeadFunc) {
2062             continue;
2063         }
2064              
2065         using namespace ParseAPI;
2066         SingleContext epred_((*deadIter)->func()->ifunc(),true,true);
2067         Intraproc epred(&epred_);
2068         parse_block *curImgBlock = (*deadIter)->llb();
2069         ParseAPI::Block::edgelist & sourceEdges = curImgBlock->sources();
2070         ParseAPI::Block::edgelist::iterator eit = sourceEdges.begin(&epred);
2071         Address baseAddr = (*deadIter)->start() 
2072             - curImgBlock->firstInsnOffset();
2073
2074         // find all stub blocks for this edge
2075         for( ; eit != sourceEdges.end(); ++eit) {
2076             parse_block *sourceBlock = 
2077                 static_cast<parse_block*>((*eit)->src());
2078             block_instance *src = (*deadIter)->func()->findBlockByEntry(baseAddr + sourceBlock->start());
2079             assert(src);
2080
2081             edgeStub st(src, 
2082                     curImgBlock->start() + baseAddr, 
2083                     (*eit)->type());
2084             if (delBBIs.end() == delBBIs.find(src) ) {
2085                 stubs[src->func()].push_back(st);
2086             } 
2087         }
2088     }
2089 #endif
2090     return stubs;
2091 }
2092
2093 /* PatchAPI Stuffs */
2094 void AddressSpace::initPatchAPI(mapped_object* aout) {
2095    DynAddrSpacePtr addr_space = DynAddrSpace::create(aout);
2096    assert(addr_space);
2097
2098   mgr_ = PatchMgr::create(addr_space,
2099                            DynPointMakerPtr(new DynPointMaker),
2100                            DynInstrumenterPtr(new DynInstrumenter));
2101    patcher_ = Patcher::create(mgr_);
2102
2103    assert(mgr());
2104    mgr()->instrumenter()->callModMap().clear();
2105    mgr()->instrumenter()->funcRepMap().clear();
2106    mgr()->instrumenter()->funcWrapMap().clear();
2107 }
2108
2109 bool AddressSpace::patch(AddressSpace* as) {
2110   return as->patcher()->commit();
2111 }
2112
2113 void AddressSpace::addMappedObject(mapped_object* obj) {
2114   mapped_objects.push_back(obj);
2115   DYN_CAST(DynAddrSpace, mgr_->as())->loadLibrary(obj);
2116 }