Compile fix after removing deprecated SymtabAPI methods.
[dyninst.git] / dyninstAPI / src / binaryEdit.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: binaryEdit.C,v 1.26 2008/10/28 18:42:44 bernat Exp $
32
33 #include "binaryEdit.h"
34 #include "common/h/headers.h"
35 #include "mapped_object.h"
36 #include "mapped_module.h"
37 #include "debug.h"
38 #include "os.h"
39 #include "instPoint.h"
40 #include "function.h"
41
42 using namespace Dyninst::SymtabAPI;
43
44 // #define USE_ADDRESS_MAPS
45
46 // Reading and writing get somewhat interesting. We are building
47 // a false address space - that of the "inferior" binary we're editing. 
48 // However, that address space doesn't exist - and so we must overlay
49 // it on ours. In the dynamic case this is easy, of course. So what
50 // we have is a mapping. An "Address" that we get (inOther), can
51 // map to one of the following:
52 //  1) An area created with inferiorMalloc
53 //  2) A section of the binary that is original
54 //  3) A section of the binary that was modified
55
56 bool BinaryEdit::readTextSpace(const void *inOther,
57                                u_int size,
58                                void *inSelf) {
59     Address addr = (Address) inOther;
60     
61     // Look up this address in the code range tree of memory
62     codeRange *range = NULL;
63     if (!memoryTracker_->find(addr, range))
64         return false;
65     assert(addr >= range->get_address());
66
67     Address offset = addr - range->get_address();
68     assert(offset < range->get_size());
69
70     void *local_ptr = ((void *) (offset + (Address)range->get_local_ptr()));
71     memcpy(inSelf, local_ptr, size);
72
73     return true;
74 }
75
76 bool BinaryEdit::writeTextSpace(void *inOther,
77                             u_int size,
78                             const void *inSelf) {
79     // This assumes we already have a memory tracker; inefficient, but
80     // it works. 
81     Address addr = (Address) inOther;
82     unsigned int to_do = size;
83     Address local = (Address) inSelf;
84     markDirty();
85
86     while (to_do) {
87        // Look up this address in the code range tree of memory
88        codeRange *range = NULL;
89        if (!memoryTracker_->find(addr, range)) {
90           return false;
91        }
92        
93        // We might (due to fragmentation) be overlapping multiple backing
94        // store "chunks", so this has to be iterative rather than a one-shot.
95        
96        Address chunk_start = range->get_address();
97        Address chunk_end = range->get_address() + range->get_size();
98        
99        assert (addr >= chunk_start);
100        
101        unsigned chunk_size = 0;
102        if ((addr + to_do) <= chunk_end) {
103           chunk_size = to_do;
104        }
105        else {
106           chunk_size = chunk_end - addr;
107        }
108        
109        Address offset = addr - range->get_address();
110        assert(offset < range->get_size());
111        
112        void *local_ptr = ((void *) (offset + (Address)range->get_local_ptr()));
113        inst_printf("Copying to 0x%lx [base=0x%lx] from 0x%lx (%d bytes)  target=0x%lx  offset=0x%lx\n", 
114               local_ptr, range->get_local_ptr(), local, chunk_size, addr, offset);
115        //range->print_range();
116        memcpy(local_ptr, (void *)local, chunk_size);
117        memoryTracker* mt = dynamic_cast<memoryTracker*>(range);
118        assert(mt);
119        mt->dirty = true;
120        
121        to_do -= chunk_size;
122        addr += chunk_size;
123        local += chunk_size;
124     }
125
126     return true;
127 }    
128
129 bool BinaryEdit::readDataSpace(const void *inOther,
130                            u_int amount,
131                            void *inSelf,
132                            bool) {
133     return readTextSpace(inOther, amount, inSelf);
134 }
135
136 bool BinaryEdit::writeDataSpace(void *inOther,
137                             u_int amount,
138                             const void *inSelf) {
139     return writeTextSpace(inOther, amount, inSelf);
140 }
141
142 bool BinaryEdit::readTextWord(const void *inOther,
143                               u_int size,
144                               void *inSelf)
145 { return readTextSpace(inOther, size, inSelf); }
146
147 bool BinaryEdit::writeTextWord(void *inOther,
148                                u_int size,
149                                const void *inSelf)
150 { return writeTextSpace(inOther, size, inSelf); }
151
152 bool BinaryEdit::readDataWord(const void *inOther,
153                               u_int amount,
154                               void *inSelf,
155                               bool)
156 { return readTextSpace(inOther, amount, inSelf); }
157
158 bool BinaryEdit::writeDataWord(void *inOther,
159                                u_int amount,
160                                const void *inSelf)
161 { return writeTextSpace(inOther, amount, inSelf); }
162
163 const Address ADDRESS_LO = (Address)0;
164 const Address ADDRESS_HI = (Address)(~(Address)0);
165 const unsigned HEAP_STAT_BUF_SIZE = (0x100000);
166
167 Address BinaryEdit::inferiorMalloc(unsigned size,
168                                inferiorHeapType /*ignored*/,
169                                Address /*near*/,
170                                bool *err) {
171     // It looks like we're ignoring near...
172     Address ret = 0;
173
174     Address lo = ADDRESS_LO;
175     Address hi = ADDRESS_HI;
176
177     if (err) *err = false;
178    
179     inferiorMallocAlign(size); // align size
180
181     int freeIndex = -1;
182     int ntry = 0;
183     for (ntry = 0; freeIndex == -1; ntry++) {
184         switch(ntry) {
185         case 0: 
186             // See if we have available memory
187             break;
188         case 1:
189             inferiorFreeCompact();
190             break;
191         case 2:
192             inferiorMallocStatic(size);
193             break;
194         default:
195             return 0;
196         }
197         ret = inferiorMallocInternal(size, lo, hi, anyHeap);
198         if (ret) {
199           memoryTracker *newTracker = new memoryTracker(ret, size);
200           newTracker->alloced = true;
201           if (!memoryTracker_)
202             memoryTracker_ = new codeRangeTree();
203           memoryTracker_->insert(newTracker);
204
205           break;
206         }
207     }
208
209     return ret;
210 }
211
212 void BinaryEdit::inferiorFree(Address item)
213 {
214   inferiorFreeInternal(item);
215
216   codeRange *obj;
217   if(!memoryTracker_->find(item, obj))
218   {
219     // Warn the user?
220     return;
221   }
222   
223   
224   delete obj;
225   
226   memoryTracker_->remove(item);
227 }
228
229 bool BinaryEdit::inferiorRealloc(Address item, unsigned newsize)
230 {
231   bool result = inferiorReallocInternal(item, newsize);
232   if (!result)
233     return false;
234
235   maxAllocedAddr();
236
237   codeRange *obj;
238   result = memoryTracker_->find(item, obj);
239   assert(result);
240
241   memoryTracker_->remove(item);
242
243   memoryTracker *mem_track = dynamic_cast<memoryTracker *>(obj);
244   assert(mem_track);
245   mem_track->realloc(newsize);
246
247   memoryTracker_->insert(obj);
248   return true;
249 }
250
251 Architecture BinaryEdit::getArch() const {
252   assert(mapped_objects.size());
253     // XXX presumably all of the objects in the BinaryEdit collection
254     //     must be the same architecture.
255   return mapped_objects[0]->parse_img()->codeObject()->cs()->getArch();
256 }
257
258 unsigned BinaryEdit::getAddressWidth() const {
259   assert(!mapped_objects.empty());
260   return mapped_objects[0]->parse_img()->codeObject()->cs()->getAddressWidth();
261 }
262 Address BinaryEdit::offset() const {
263     fprintf(stderr,"error BinaryEdit::offset() unimpl\n");
264     return 0;
265 }
266 Address BinaryEdit::length() const {
267     fprintf(stderr,"error BinaryEdit::length() unimpl\n");
268     return 0;
269 }
270
271 bool BinaryEdit::multithread_capable(bool) {
272    return multithread_capable_;
273 }
274
275 bool BinaryEdit::multithread_ready(bool) {
276     return multithread_capable();
277 }
278
279 BinaryEdit::BinaryEdit() : 
280    highWaterMark_(0),
281    lowWaterMark_(0),
282    isDirty_(false),
283    memoryTracker_(NULL),
284    multithread_capable_(false) {
285    trapMapping.shouldBlockFlushes(true);
286 }
287
288 BinaryEdit::~BinaryEdit() 
289 {
290 }
291
292 void BinaryEdit::deleteBinaryEdit() {
293     deleteAddressSpace();
294     highWaterMark_ = 0;
295     lowWaterMark_ = 0;
296
297     // TODO: is this cleanup necessary?
298     depRelocation *rel;
299     while (dependentRelocations.size() > 0) {
300         rel = dependentRelocations[0];
301         dependentRelocations.erase(dependentRelocations.begin());
302         delete rel;
303     }
304 }
305
306 BinaryEdit *BinaryEdit::openFile(const std::string &file, 
307                                  PatchMgrPtr mgr, 
308                                  Dyninst::PatchAPI::Patcher *patch,
309                                  const std::string &member) {
310     if (!OS::executableExists(file)) {
311         startup_printf("%s[%d]:  failed to read file %s\n", FILE__, __LINE__, file.c_str());
312         std::string msg = std::string("Can't read executable file ") + file + (": ") + strerror(errno);
313         showErrorCallback(68, msg.c_str());
314         return NULL;
315     }
316     
317     fileDescriptor desc;
318     if (!getStatFileDescriptor(file, desc)) {
319         startup_printf("%s[%d]: failed to create file descriptor for %s!\n",
320                        FILE__, __LINE__, file.c_str());
321         return NULL;
322     }
323     
324     // Open the mapped object as an archive member
325     if( !member.empty() ) {
326         desc.setMember(member);
327     }
328
329     BinaryEdit *newBinaryEdit = new BinaryEdit();
330     if (!newBinaryEdit) {
331         startup_printf("%s[%d]: failed to create binary representation for %s!\n",
332                        FILE__, __LINE__, file.c_str());
333     }
334
335     newBinaryEdit->mobj = mapped_object::createMappedObject(desc, newBinaryEdit);
336     if (!newBinaryEdit->mobj) {
337         startup_printf("%s[%d]: failed to create mapped object for %s\n",
338                        FILE__, __LINE__, file.c_str());
339         return NULL;
340     }
341
342     /* PatchAPI stuffs */
343     if (!mgr) {
344        newBinaryEdit->initPatchAPI();
345     } else {
346        newBinaryEdit->setMgr(mgr);
347        assert(patch);
348        newBinaryEdit->setPatcher(patch);
349     }
350     newBinaryEdit->addMappedObject(newBinaryEdit->mobj);
351     /* End of PatchAPI stuffs */
352
353     // We now need to access the start of the new section we're creating.
354
355     // I'm going through the mapped_object interface for now - 
356     // I assume we'll pass it to DynSymtab, then add our base
357     // address to it at the mapped_ level. 
358     Symtab* linkedFile = newBinaryEdit->getAOut()->parse_img()->getObject();
359     Region *newSec = NULL;
360     linkedFile->findRegion(newSec, ".dyninstInst");
361     if (newSec) {
362          // We're re-instrumenting - will fail for now
363          fprintf(stderr, "ERROR:  unable to open/reinstrument previously instrumented binary %s!\n", file.c_str());
364          return NULL;
365     }
366     newBinaryEdit->highWaterMark_ = linkedFile->getFreeOffset(50*1024*1024);
367     newBinaryEdit->lowWaterMark_ = newBinaryEdit->highWaterMark_;
368
369     newBinaryEdit->makeInitAndFiniIfNeeded();
370
371     newBinaryEdit->createMemoryBackingStore(newBinaryEdit->getAOut());
372     newBinaryEdit->initialize();
373
374     //Don't count initialization in determining dirty
375     newBinaryEdit->isDirty_ = false; //!(foundInit && foundFini);
376     return newBinaryEdit;
377 }
378
379 #if !defined(os_linux) && !defined(os_freebsd)
380 void BinaryEdit::makeInitAndFiniIfNeeded()
381 {
382 }
383
384 bool BinaryEdit::archSpecificMultithreadCapable() {
385     return false;
386 }
387 #endif
388
389 bool BinaryEdit::getStatFileDescriptor(const std::string &name, fileDescriptor &desc) {
390    desc = fileDescriptor(name.c_str(),
391                          0, // code base address
392                          0); // data base address
393    return true;
394 }
395
396 #if !defined(os_linux) && !defined(os_freebsd)
397 mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename, std::map<std::string, BinaryEdit *> &allOpened) {
398     /*
399      * Note: this does not actually do any library name resolution, as that is OS-dependent
400      * If resolution is required, it should be implemented in an OS-dependent file
401      * (see linux.C for an example)
402      *
403      * However, this version allows the RT library to be opened with this function regardless
404      * if library name resolution has been implemented on a platform.
405      */
406     std::map<std::string, BinaryEdit *> retMap;
407     assert(mgr());
408     BinaryEdit *temp = BinaryEdit::openFile(filename, mgr(), patcher());
409
410     if( temp && temp->getAddressWidth() == getAddressWidth() ) {
411        allOpened.insert(std::make_pair(filename, temp));
412        return temp->getMappedObject();
413     }
414     
415     return NULL;
416 }
417
418 bool BinaryEdit::getResolvedLibraryPath(const std::string &, std::vector<std::string> &) {
419     assert(!"Not implemented");
420     return false;
421 }
422 #endif
423
424 #if !(defined(cap_binary_rewriter) && (defined(arch_x86) || defined(arch_x86_64) || defined(arch_power))) 
425 bool BinaryEdit::doStaticBinarySpecialCases() {
426     return true;
427 }
428 #endif
429
430 bool BinaryEdit::isMultiThreadCapable()
431 {
432    Symtab *symtab = mobj->parse_img()->getObject();
433    std::vector<std::string> depends = symtab->getDependencies();
434    for (std::vector<std::string>::iterator curDep = depends.begin();
435         curDep != depends.end(); curDep++) {
436      if(    (curDep->find("libpthread") != std::string::npos) 
437          || (curDep->find("libthread") != std::string::npos)
438          || (curDep->find("libthr") != std::string::npos) )
439      {
440         return true;
441      }
442    }
443
444    return archSpecificMultithreadCapable();
445 }
446
447 bool BinaryEdit::getAllDependencies(std::map<std::string, BinaryEdit*>& deps)
448 {
449    Symtab *symtab = mobj->parse_img()->getObject();
450    std::deque<std::string> depends;
451    std::copy(symtab->getDependencies().begin(), symtab->getDependencies().end(), std::back_inserter(depends));
452    while(!depends.empty())
453    {
454      std::string lib = depends.front();
455      if(deps.find(lib) == deps.end()) {
456         std::map<std::string, BinaryEdit*> res;
457         openResolvedLibraryName(lib, res);
458          std::map<std::string, BinaryEdit*>::iterator bedit_it;
459          for(bedit_it = res.begin(); bedit_it != res.end(); ++bedit_it) {
460            if (bedit_it->second) {
461              deps.insert(*bedit_it);
462              if(!bedit_it->second->getAllDependencies(deps))
463              {
464                return false;
465              }
466            } else {
467              return false;
468            }
469          }
470      }
471      depends.pop_front();
472    }
473    return true;
474 }
475
476 #if 0 //KEVINTODO: I think this is redundant, SymtabAPI::emitWin.C does this
477 static unsigned long addTrapTableSpace_win(AddressSpace *as)
478 {
479 #if defined (os_windows)
480     return as->getAddressWidth() + 16;
481 #else
482     return 0;
483 #endif
484 }
485
486 void addTrapTable_win(newSectionPtr, Address tableAddr)
487 {
488 }
489 #endif
490
491 bool BinaryEdit::writeFile(const std::string &newFileName) 
492 {
493    // Step 1: changes. 
494
495
496       inst_printf(" writing %s ... \n", newFileName.c_str());
497
498       Symtab *symObj = mobj->parse_img()->getObject();
499
500       // link to the runtime library if tramp guards are currently enabled
501       if ( !symObj->isStaticBinary() && !BPatch::bpatch->isTrampRecursive() ) {
502           assert(!runtime_lib.empty());
503           symObj->addLibraryPrereq((*runtime_lib.begin())->fileName());
504       }
505
506       if( symObj->isStaticBinary() && isDirty() ) {
507          if( !doStaticBinarySpecialCases() ) {
508             return false;
509          }
510       }
511
512    delayRelocation_ = false;
513       relocate();
514       
515       vector<Region*> oldSegs;
516       symObj->getAllRegions(oldSegs);
517
518       //Write any traps to the mutatee
519       if (canUseTraps()) {
520          trapMapping.shouldBlockFlushes(false);
521          trapMapping.flush();
522       }
523
524       // Now, we need to copy in the memory of the new segments
525       for (unsigned i = 0; i < oldSegs.size(); i++) {
526          codeRange *segRange = NULL;
527          if (!memoryTracker_->find(oldSegs[i]->getMemOffset(), segRange)) {
528 #if 0
529             // Looks like BSS
530             if (newSegs[i].name == ".bss")
531 #endif
532                continue;
533             //inst_printf (" segment name: %s\n", newSegs[i].name.c_str());
534             //assert(0);
535          }
536          //inst_printf(" ==> memtracker: Copying to 0x%lx from 0x%lx\n", 
537          //newSegs[i].loadaddr, segRange->get_local_ptr());
538          memoryTracker* mt = dynamic_cast<memoryTracker*>(segRange);
539          assert(mt);
540          if(mt->dirty) {
541             oldSegs[i]->setPtrToRawData(segRange->get_local_ptr(), oldSegs[i]->getMemSize());
542          }
543          
544          //newSegs[i].data = segRange->get_local_ptr();
545       }
546
547       // Okay, that does it for the old stuff.
548
549       // Now we need to get the new stuff. That's all the allocated memory. First, big
550       // buffer to hold it.
551
552       void *newSectionPtr = malloc(highWaterMark_ - lowWaterMark_);
553
554       pdvector<codeRange *> writes;
555       memoryTracker_->elements(writes);
556
557       for (unsigned i = 0; i < writes.size(); i++) {
558          assert(newSectionPtr);
559          memoryTracker *tracker = dynamic_cast<memoryTracker *>(writes[i]);
560          assert(tracker);
561          //inst_printf("memory tracker: 0x%lx  load=0x%lx  size=%d  %s\n", 
562          //tracker->get_local_ptr(), tracker->get_address(), tracker->get_size(),
563          //tracker->alloced ? "[A]" : "");
564          if (!tracker->alloced) continue;
565
566          // Copy whatever is in there into the big buffer, at the appropriate address
567          assert(tracker->get_address() >= lowWaterMark_);
568          Address offset = tracker->get_address() - lowWaterMark_;
569          assert((offset + tracker->get_size()) < highWaterMark_);
570          void *ptr = (void *)(offset + (Address)newSectionPtr);
571          memcpy(ptr, tracker->get_local_ptr(), tracker->get_size());
572       }
573             
574       // Righto. Now, that includes the old binary - by design - 
575       // so skip it and see what we're talking about size-wise. Which should
576       // be less than the highWaterMark, so we can double-check.
577
578       // Next, make a new section. We have the following parameters:
579       // Offset vaddr: we get this from Symtab - "first free address with sufficient space"
580       // std::string name: without reflection, ".dyninstInst"
581       // unsigned long flags: these are a SymtabAPI abstraction. We're going with text|data because
582       //    we might have both.
583       // bool loadable: heck yeah...
584         
585       Region *newSec = NULL;
586       symObj->findRegion(newSec, ".dyninstInst");
587       if (newSec) {
588          // We're re-instrumenting - will fail for now
589          fprintf(stderr, "ERROR:  unable to open/reinstrument previously instrumented binary %s!\n", newFileName.c_str());
590          return false;
591       }
592
593       symObj->addRegion(lowWaterMark_,
594                         newSectionPtr,
595                         highWaterMark_ - lowWaterMark_,
596                         ".dyninstInst",
597                         Region::RT_TEXTDATA,
598                         true);
599       
600       symObj->findRegion(newSec, ".dyninstInst");
601       assert(newSec);
602
603       
604       if (mobj == getAOut()) {
605          // Add dynamic symbol relocations
606          for (unsigned i=0; i < dependentRelocations.size(); i++) {
607             Address to = dependentRelocations[i]->getAddress();
608             Symbol *referring = dependentRelocations[i]->getReferring();
609             
610             /*
611               if (!symObj->isStaticBinary() && !symObj->hasReldyn() && !symObj->hasReladyn()) {
612               Address addr = referring->getOffset();
613               bool result = writeDataSpace((void *) to, getAddressWidth(), &addr);
614               assert(result);
615               continue;
616               }
617             */
618                
619             // Create the relocationEntry
620             relocationEntry localRel(to, referring->getMangledName(), referring,
621                                      relocationEntry::getGlobalRelType(getAddressWidth()));
622             
623             /*
624               if( mobj->isSharedLib() ) {
625               localRel.setRelAddr(to - mobj->imageOffset());
626               }
627             */
628             
629             symObj->addExternalSymbolReference(referring, newSec, localRel);
630             
631             /*
632               newSymbol = new Symbol(referring->getName(), 
633               Symbol::ST_FUNCTION, 
634               Symbol::SL_GLOBAL,
635               Symbol::SV_DEFAULT, 
636               (Address)0, 
637               symObj->getDefaultModule(),
638               NULL, 
639               8,
640               true, 
641               false);
642               symObj->addSymbol(newSymbol, referring);
643               if (!symObj->hasReldyn() && symObj->hasReladyn()) {
644               newSec->addRelocationEntry(to, newSymbol, relocationEntry::dynrel, Region::RT_RELA);
645               } else {
646               newSec->addRelocationEntry(to, newSymbol, relocationEntry::dynrel);
647               }
648             */
649          }
650       }
651       
652       pdvector<Symbol *> newSyms;
653       buildDyninstSymbols(newSyms, newSec, symObj->getOrCreateModule("dyninstInst",
654                                                                      lowWaterMark_));
655       for (unsigned i = 0; i < newSyms.size(); i++) {
656          symObj->addSymbol(newSyms[i]);
657       }
658       
659       // Okay, now...
660       // Hand textSection and newSection to DynSymtab.
661         
662       // First, textSection.
663         
664       // From the SymtabAPI documentation: we have the following methods we want to use.
665       // Symtab::addSection(Offset vaddr, void *data, unsigned int dataSize, std::string name, 
666       //                    unsigned long flags, bool loadable)
667       // Symtab::updateCode(void *buffer, unsigned size)
668       // Symtab::emit(std::string filename)
669         
670       // First, text
671       assert(symObj);
672       
673       
674       // And now we generate the new binary
675       //if (!symObj->emit(newFileName.c_str())) {
676       if (!symObj->emit(newFileName.c_str())) {
677          SymtabError lastError = Symtab::getLastSymtabError();
678          showErrorCallback(109, Symtab::printError(lastError));
679          return false;
680       }
681    return true;
682 }
683
684 Address BinaryEdit::maxAllocedAddr() {
685    inferiorFreeCompact();
686    Address hi = lowWaterMark_;
687
688    for (dictionary_hash<Address, heapItem *>::iterator iter = heap_.heapActive.begin();
689         iter != heap_.heapActive.end(); ++iter) {
690       Address localHi = (*iter)->addr + (*iter)->length;
691       if (localHi > hi) hi = localHi;
692    }
693    return hi;
694 }
695
696
697 bool BinaryEdit::inferiorMallocStatic(unsigned size) {
698     // Should be set by now
699     assert(highWaterMark_ != 0);
700
701 #if defined(USE_ADDRESS_MAPS)
702     void *buf = malloc(size);
703     if (!buf) return false;
704 #endif
705     
706     Address newStart = highWaterMark_;
707
708     // If there is a free heap that _ends_ at the highWaterMark,
709     // just extend it. This is a special case of inferiorFreeCompact;
710     // when we make that function faster, we can just call it. 
711     bool found = false;
712     for (unsigned i = 0; i < heap_.heapFree.size(); i++) {
713         heapItem *h = heap_.heapFree[i];
714         assert(h);
715         Address end = h->addr + h->length;
716         if (end == newStart) {
717             found = true;
718             h->length += size;
719             break;
720         }
721     }
722     if (!found) {
723         // Build tracking objects for it
724         heapItem *h = new heapItem(highWaterMark_, 
725                                    size,
726                                    anyHeap,
727                                    true,
728                                    HEAPfree);
729         addHeap(h);
730     }
731
732     highWaterMark_ += size;
733
734     return true;
735 }
736
737
738 bool BinaryEdit::createMemoryBackingStore(mapped_object *obj) {
739     // We want to create a buffer for every section in the
740     // binary so that we can store updates.
741
742     Symtab *symObj = obj->parse_img()->getObject();
743     vector<Region*> regs;
744     symObj->getAllRegions(regs);
745
746    for (unsigned i = 0; i < regs.size(); i++) {
747       memoryTracker *newTracker = NULL;
748       if (regs[i]->getRegionType() == Region::RT_BSS || (regs[i]->getMemSize() == 0))
749       {
750          continue;
751       }
752       else {
753          newTracker = new memoryTracker(regs[i]->getMemOffset(),
754                                         regs[i]->getMemSize(),
755                                         regs[i]->getPtrToRawData());
756          
757       }
758       newTracker->alloced = false;
759       if (!memoryTracker_)
760          memoryTracker_ = new codeRangeTree();
761       memoryTracker_->insert(newTracker);
762    }
763
764     
765    return true;
766 }
767
768
769 bool BinaryEdit::initialize() {
770    //Load the RT library
771    
772    // Create the tramp guard
773    
774    // Initialization. For now we're skipping threads, since we can't
775    // get the functions we need. However, we kinda need the recursion
776    // guard. This is an integer (one per thread, for now - 1) that 
777    // begins initialized to 1.
778
779     return true;
780 }
781
782 void BinaryEdit::addDependentRelocation(Address to, Symbol *referring) {
783     // prevent duplicate relocations
784     std::vector<depRelocation *>::iterator it;
785     for (it = dependentRelocations.begin(); it != dependentRelocations.end(); it++)
786         if ((*it)->getAddress() == to && (*it)->getReferring() == referring)
787             return;
788     // create a new relocation and add it to the collection
789         depRelocation *reloc = new depRelocation(to, referring);
790         dependentRelocations.push_back(reloc);
791 }
792
793 Address BinaryEdit::getDependentRelocationAddr(Symbol *referring) {
794         Address retAddr = 0x0;
795         for (unsigned i=0; i < dependentRelocations.size(); i++) {
796                 if (dependentRelocations[i]->getReferring() == referring) {
797                         retAddr = dependentRelocations[i]->getAddress();
798                         break;
799                 }
800         }
801         return retAddr;
802 }
803
804 void BinaryEdit::addLibraryPrereq(std::string libname) {
805    Symtab *symObj = mobj->parse_img()->getObject();
806    symObj->addLibraryPrereq(libname);
807 }
808
809
810 // Build a list of symbols describing instrumentation and relocated functions. 
811 // To keep this list (somewhat) short, we're doing one symbol per extent of 
812 // instrumentation + relocation for a particular function. 
813 // New: do this for one mapped object. 
814 void BinaryEdit::buildDyninstSymbols(pdvector<Symbol *> &newSyms, 
815                                      Region *newSec,
816                                      Module *newMod) {
817    for (std::vector<SymtabAPI::Symbol *>::iterator iter = newDyninstSyms_.begin();
818         iter != newDyninstSyms_.end(); ++iter) {
819       (*iter)->setModule(newMod);
820       (*iter)->setRegion(newSec);
821       newSyms.push_back(*iter);
822    }
823                                                                               
824
825    for (CodeTrackers::iterator i = relocatedCode_.begin();
826         i != relocatedCode_.end(); ++i) {
827       Relocation::CodeTracker *CT = *i;
828       func_instance *currFunc = NULL;
829       Address start = 0;
830       unsigned size = 0;
831       
832       for (Relocation::CodeTracker::TrackerList::const_iterator iter = CT->trackers().begin();
833            iter != CT->trackers().end(); ++iter) {
834          const Relocation::TrackerElement *tracker = *iter;
835          
836          func_instance *tfunc = tracker->func();
837          
838          if (currFunc != tfunc) {
839             // Starting a new function
840             if (currFunc) {
841                // Record the old one
842                // currfunc set
843                // start set
844                size = tracker->reloc() - start;
845                
846                std::string name = currFunc->prettyName();
847                name.append("_dyninst");
848                
849                Symbol *newSym = new Symbol(name.c_str(),
850                                            Symbol::ST_FUNCTION,
851                                            Symbol::SL_GLOBAL,
852                                            Symbol::SV_DEFAULT,
853                                            start,
854                                            newMod,
855                                            newSec,
856                                            size);                                        
857                newSyms.push_back(newSym);
858             }
859             currFunc = tfunc;
860             start = tracker->reloc();
861             size = 0;
862          }
863          else {
864             // Accumulate size
865             size = tracker->reloc() - start;
866          }
867       }
868    }
869 }
870     
871 void BinaryEdit::markDirty()
872 {
873    isDirty_ = true;
874 }
875
876 bool BinaryEdit::isDirty()
877 {
878    return isDirty_;
879 }
880
881 mapped_object *BinaryEdit::getMappedObject()
882 {
883    return mobj;
884 }
885
886 void BinaryEdit::setupRTLibrary(std::vector<BinaryEdit *> &r)
887 {
888    rtlib = r;
889
890    // Update addressSpace collection for RT library
891    runtime_lib.clear();
892    std::vector<BinaryEdit *>::iterator rtlib_it;
893    for(rtlib_it = r.begin(); rtlib_it != r.end(); ++rtlib_it) {
894        runtime_lib.insert((*rtlib_it)->getMappedObject());
895    }
896 }
897
898 void BinaryEdit::setTrampGuard(int_variable* tg)
899 {
900   trampGuardBase_ = tg;
901 }
902
903
904 int_variable* BinaryEdit::createTrampGuard()
905 {
906   // If we have one, just return it
907   if(trampGuardBase_) return trampGuardBase_;
908   assert(rtlib.size());
909
910   std::vector<BinaryEdit *>::iterator rtlib_it;
911   const int_variable *var = NULL;
912   for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
913       mapped_object *mobj = (*rtlib_it)->getMappedObject();
914       var = mobj->getVariable("DYNINST_default_tramp_guards");
915       if( var ) break;
916   }
917   
918   assert(var);
919   trampGuardBase_ = const_cast<int_variable *>(var);
920   
921   return trampGuardBase_;
922 }
923
924 vector<BinaryEdit *> &BinaryEdit::rtLibrary()
925 {
926    return rtlib;
927 }
928
929 func_instance *BinaryEdit::findOnlyOneFunction(const std::string &name,
930                                               const std::string &libname,
931                                               bool search_rt_lib)
932 {
933    func_instance *f = AddressSpace::findOnlyOneFunction(name, libname, search_rt_lib);
934    if (!f && search_rt_lib) {
935       std::vector<BinaryEdit *>::iterator rtlib_it;
936       for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
937           f = (*rtlib_it)->findOnlyOneFunction(name, libname, false);
938           if( f ) break;
939       }
940    }
941    return f;
942 }
943
944 void BinaryEdit::setMultiThreadCapable(bool b)
945 {
946    multithread_capable_ = b;
947 }
948
949 void BinaryEdit::addSibling(BinaryEdit *be)
950 {
951    if (this != be) {
952       siblings.push_back(be);
953    }
954 }
955
956 std::vector<BinaryEdit *> &BinaryEdit::getSiblings()
957 {
958    return siblings;
959 }
960
961
962
963 // Here's the story. We may need to install a trap handler for instrumentation
964 // to work in the rewritten binary. This doesn't play nicely with trap handlers
965 // that the binary itself registers. So we're going to replace every call to
966 // sigaction in the binary with a call to our wrapper. This wrapper:
967 //   1) Ignores attempts to register a SIGTRAP
968 //   2) Passes everything else through to sigaction
969 // It's called "dyn_sigaction".
970
971 bool BinaryEdit::usedATrap() {
972     return (!trapMapping.empty());
973 }
974
975 // Find all calls to sigaction equivalents and replace with
976 // calls to dyn_<sigaction_equivalent_name>. 
977 bool BinaryEdit::replaceTrapHandler() {
978
979     vector<string> sigaction_names;
980     OS::get_sigaction_names(sigaction_names);
981
982     pdvector<func_instance *> allFuncs;
983     getAllFunctions(allFuncs);
984     
985     bool replaced = false;
986     for (unsigned nidx = 0; nidx < sigaction_names.size(); nidx++) 
987     {
988         // find replacement function
989         std::stringstream repname;
990         repname << "dyn_" << sigaction_names[nidx];
991         func_instance *repfunc = findOnlyOneFunction(repname.str().c_str());
992         assert(repfunc);
993     
994         // replace all callsites to current sigaction function
995         for (unsigned i = 0; i < allFuncs.size(); i++) {
996             func_instance *func = allFuncs[i];        
997             assert(func);
998
999             for (PatchFunction::Blockset::const_iterator iter = func->blocks().begin();
1000                  iter != func->blocks().end(); ++iter) {
1001                 block_instance* iblk = SCAST_BI(*iter);
1002                 if (iblk->containsCall()) {
1003                     
1004                     // the function name could have up to two underscores
1005                     // prepended (e.g., sigaction, _sigaction, __sigaction),
1006                     // try all three possibilities for each name
1007                     std::string calleeName = iblk->calleeName();
1008                     std::string sigactName = sigaction_names[nidx];
1009                     for (int num_s=0; 
1010                          num_s <= 2; 
1011                          num_s++, sigactName.append(string("_"),0,1)) {
1012                         if (calleeName == sigactName) {
1013                             modifyCall(iblk, repfunc, func);
1014                             replaced = true;
1015                             break;
1016                         }
1017                     }
1018                 }
1019             } // for each func in the rewritten binary
1020         } // for each sigaction-equivalent function to replace
1021     }
1022
1023     if (!replaced) return true;
1024
1025     /* PatchAPI stuffs */
1026     return AddressSpace::patch(this);
1027     /* End of PatchAPI stuffs */
1028     // return relocate();
1029 }
1030
1031 bool BinaryEdit::needsPIC()
1032 {
1033    Symtab *symtab = getMappedObject()->parse_img()->getObject();
1034    assert(symtab);
1035    if(getMappedObject()->fileName().find("lib") == 0)
1036    {
1037        if(getMappedObject()->fileName().find(".so") != std::string::npos)
1038        {
1039            return true;
1040        }
1041    }
1042    //If there is a fixed load address, then we can calculate 
1043    // absolute addresses.
1044    return (symtab->getLoadAddress() == 0);  
1045 }
1046
1047 void BinaryEdit::addTrap(Address from, Address to, codeGen &gen) {
1048    gen.invalidate();
1049    gen.allocate(4);
1050    gen.setAddrSpace(this);
1051    gen.setAddr(from);
1052    insnCodeGen::generateTrap(gen);
1053    trapMapping.addTrapMapping(from, to, true);
1054 }
1055