Fix our tailcall parsing; we've observed conditional tailcalls in the wild and weren...
[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
246   mem_track->realloc(newsize);
247
248   memoryTracker_->insert(obj);
249   return true;
250 }
251
252 Architecture BinaryEdit::getArch() const {
253   assert(mapped_objects.size());
254     // XXX presumably all of the objects in the BinaryEdit collection
255     //     must be the same architecture.
256   return mapped_objects[0]->parse_img()->codeObject()->cs()->getArch();
257 }
258
259 unsigned BinaryEdit::getAddressWidth() const {
260   assert(!mapped_objects.empty());
261   return mapped_objects[0]->parse_img()->codeObject()->cs()->getAddressWidth();
262 }
263 Address BinaryEdit::offset() const {
264     fprintf(stderr,"error BinaryEdit::offset() unimpl\n");
265     return 0;
266 }
267 Address BinaryEdit::length() const {
268     fprintf(stderr,"error BinaryEdit::length() unimpl\n");
269     return 0;
270 }
271
272 bool BinaryEdit::multithread_capable(bool) {
273    return multithread_capable_;
274 }
275
276 bool BinaryEdit::multithread_ready(bool) {
277     return multithread_capable();
278 }
279
280 BinaryEdit::BinaryEdit() : 
281    highWaterMark_(0),
282    lowWaterMark_(0),
283    isDirty_(false),
284    memoryTracker_(NULL),
285    multithread_capable_(false) {
286    trapMapping.shouldBlockFlushes(true);
287 }
288
289 BinaryEdit::~BinaryEdit() 
290 {
291 }
292
293 void BinaryEdit::deleteBinaryEdit() {
294     deleteAddressSpace();
295     highWaterMark_ = 0;
296     lowWaterMark_ = 0;
297
298     // TODO: is this cleanup necessary?
299     depRelocation *rel;
300     while (dependentRelocations.size() > 0) {
301         rel = dependentRelocations[0];
302         dependentRelocations.erase(dependentRelocations.begin());
303         delete rel;
304     }
305 }
306
307 BinaryEdit *BinaryEdit::openFile(const std::string &file, 
308                                  PatchMgrPtr mgr, 
309                                  Dyninst::PatchAPI::Patcher *patch,
310                                  const std::string &member) {
311     if (!OS::executableExists(file)) {
312         startup_printf("%s[%d]:  failed to read file %s\n", FILE__, __LINE__, file.c_str());
313         std::string msg = std::string("Can't read executable file ") + file + (": ") + strerror(errno);
314         showErrorCallback(68, msg.c_str());
315         return NULL;
316     }
317     
318     fileDescriptor desc;
319     if (!getStatFileDescriptor(file, desc)) {
320         startup_printf("%s[%d]: failed to create file descriptor for %s!\n",
321                        FILE__, __LINE__, file.c_str());
322         return NULL;
323     }
324     
325     // Open the mapped object as an archive member
326     if( !member.empty() ) {
327         desc.setMember(member);
328     }
329
330     BinaryEdit *newBinaryEdit = new BinaryEdit();
331     if (!newBinaryEdit) {
332         startup_printf("%s[%d]: failed to create binary representation for %s!\n",
333                        FILE__, __LINE__, file.c_str());
334     }
335
336     newBinaryEdit->mobj = mapped_object::createMappedObject(desc, newBinaryEdit);
337     if (!newBinaryEdit->mobj) {
338         startup_printf("%s[%d]: failed to create mapped object for %s\n",
339                        FILE__, __LINE__, file.c_str());
340         return NULL;
341     }
342
343     /* PatchAPI stuffs */
344     if (!mgr) {
345        newBinaryEdit->initPatchAPI();
346     } else {
347        newBinaryEdit->setMgr(mgr);
348        assert(patch);
349        newBinaryEdit->setPatcher(patch);
350     }
351     newBinaryEdit->addMappedObject(newBinaryEdit->mobj);
352     /* End of PatchAPI stuffs */
353
354     // We now need to access the start of the new section we're creating.
355
356     // I'm going through the mapped_object interface for now - 
357     // I assume we'll pass it to DynSymtab, then add our base
358     // address to it at the mapped_ level. 
359     Symtab* linkedFile = newBinaryEdit->getAOut()->parse_img()->getObject();
360     Region *newSec = NULL;
361     linkedFile->findRegion(newSec, ".dyninstInst");
362     if (newSec) {
363          // We're re-instrumenting - will fail for now
364          fprintf(stderr, "ERROR:  unable to open/reinstrument previously instrumented binary %s!\n", file.c_str());
365          return NULL;
366     }
367     Address base = linkedFile->getFreeOffset(50*1024*1024);
368     base += (1024*1024);
369     base -= (base & (1024*1024-1));
370
371     newBinaryEdit->highWaterMark_ = base;
372     newBinaryEdit->lowWaterMark_ = newBinaryEdit->highWaterMark_;
373
374     // Testing
375
376     newBinaryEdit->makeInitAndFiniIfNeeded();
377
378     newBinaryEdit->createMemoryBackingStore(newBinaryEdit->getAOut());
379     newBinaryEdit->initialize();
380
381     //Don't count initialization in determining dirty
382     newBinaryEdit->isDirty_ = false; //!(foundInit && foundFini);
383     return newBinaryEdit;
384 }
385
386 #if !defined(os_linux) && !defined(os_freebsd)
387 void BinaryEdit::makeInitAndFiniIfNeeded()
388 {
389 }
390
391 bool BinaryEdit::archSpecificMultithreadCapable() {
392     return false;
393 }
394 #endif
395
396 bool BinaryEdit::getStatFileDescriptor(const std::string &name, fileDescriptor &desc) {
397    desc = fileDescriptor(name.c_str(),
398                          0, // code base address
399                          0); // data base address
400    return true;
401 }
402
403 #if !defined(os_linux) && !defined(os_freebsd)
404 mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename, std::map<std::string, BinaryEdit *> &allOpened) {
405     /*
406      * Note: this does not actually do any library name resolution, as that is OS-dependent
407      * If resolution is required, it should be implemented in an OS-dependent file
408      * (see linux.C for an example)
409      *
410      * However, this version allows the RT library to be opened with this function regardless
411      * if library name resolution has been implemented on a platform.
412      */
413     std::map<std::string, BinaryEdit *> retMap;
414     assert(mgr());
415     BinaryEdit *temp = BinaryEdit::openFile(filename, mgr(), patcher());
416
417     if( temp && temp->getAddressWidth() == getAddressWidth() ) {
418        allOpened.insert(std::make_pair(filename, temp));
419        return temp->getMappedObject();
420     }
421     
422     return NULL;
423 }
424
425 bool BinaryEdit::getResolvedLibraryPath(const std::string &, std::vector<std::string> &) {
426     assert(!"Not implemented");
427     return false;
428 }
429 #endif
430
431 #if !(defined(cap_binary_rewriter) && (defined(arch_x86) || defined(arch_x86_64) || defined(arch_power))) 
432 bool BinaryEdit::doStaticBinarySpecialCases() {
433     return true;
434 }
435 #endif
436
437 bool BinaryEdit::isMultiThreadCapable()
438 {
439    Symtab *symtab = mobj->parse_img()->getObject();
440    std::vector<std::string> depends = symtab->getDependencies();
441    for (std::vector<std::string>::iterator curDep = depends.begin();
442         curDep != depends.end(); curDep++) {
443      if(    (curDep->find("libpthread") != std::string::npos) 
444          || (curDep->find("libthread") != std::string::npos)
445          || (curDep->find("libthr") != std::string::npos) )
446      {
447         return true;
448      }
449    }
450
451    return archSpecificMultithreadCapable();
452 }
453
454 bool BinaryEdit::getAllDependencies(std::map<std::string, BinaryEdit*>& deps)
455 {
456    Symtab *symtab = mobj->parse_img()->getObject();
457    std::deque<std::string> depends;
458    depends.insert(depends.end(), symtab->getDependencies().begin(), symtab->getDependencies().end());
459    while(!depends.empty())
460    {
461      std::string lib = depends.front();
462      if(deps.find(lib) == deps.end()) {
463         std::map<std::string, BinaryEdit*> res;
464         if(!openResolvedLibraryName(lib, res)) return false;
465          std::map<std::string, BinaryEdit*>::iterator bedit_it;
466          for(bedit_it = res.begin(); bedit_it != res.end(); ++bedit_it) {
467            if (bedit_it->second) {
468              deps.insert(*bedit_it);
469              if(!bedit_it->second->getAllDependencies(deps))
470              {
471                return false;
472              }
473            } else {
474              return false;
475            }
476          }
477      }
478      depends.pop_front();
479    }
480    return true;
481 }
482
483 #if 0 //KEVINTODO: I think this is redundant, SymtabAPI::emitWin.C does this
484 static unsigned long addTrapTableSpace_win(AddressSpace *as)
485 {
486 #if defined (os_windows)
487     return as->getAddressWidth() + 16;
488 #else
489     return 0;
490 #endif
491 }
492
493 void addTrapTable_win(newSectionPtr, Address tableAddr)
494 {
495 }
496 #endif
497
498 bool BinaryEdit::writeFile(const std::string &newFileName) 
499 {
500    // Step 1: changes. 
501
502
503       inst_printf(" writing %s ... \n", newFileName.c_str());
504
505       Symtab *symObj = mobj->parse_img()->getObject();
506
507       // link to the runtime library if tramp guards are currently enabled
508       if ( !symObj->isStaticBinary() && !BPatch::bpatch->isTrampRecursive() ) {
509           assert(!runtime_lib.empty());
510           symObj->addLibraryPrereq((*runtime_lib.begin())->fileName());
511       }
512
513       if( symObj->isStaticBinary() && isDirty() ) {
514          if( !doStaticBinarySpecialCases() ) {
515             return false;
516          }
517       }
518
519    delayRelocation_ = false;
520       relocate();
521       
522       vector<Region*> oldSegs;
523       symObj->getAllRegions(oldSegs);
524
525       //Write any traps to the mutatee
526       if (canUseTraps()) {
527          trapMapping.shouldBlockFlushes(false);
528          trapMapping.flush();
529       }
530
531       // Now, we need to copy in the memory of the new segments
532       for (unsigned i = 0; i < oldSegs.size(); i++) {
533          codeRange *segRange = NULL;
534          if (!memoryTracker_->find(oldSegs[i]->getMemOffset(), segRange)) {
535 #if 0
536             // Looks like BSS
537             if (newSegs[i].name == ".bss")
538 #endif
539                continue;
540             //inst_printf (" segment name: %s\n", newSegs[i].name.c_str());
541             //assert(0);
542          }
543          //inst_printf(" ==> memtracker: Copying to 0x%lx from 0x%lx\n", 
544          //newSegs[i].loadaddr, segRange->get_local_ptr());
545          memoryTracker* mt = dynamic_cast<memoryTracker*>(segRange);
546          assert(mt);
547          if(mt->dirty) {
548             oldSegs[i]->setPtrToRawData(segRange->get_local_ptr(), oldSegs[i]->getMemSize());
549          }
550          
551          //newSegs[i].data = segRange->get_local_ptr();
552       }
553
554       // Okay, that does it for the old stuff.
555
556       // Now we need to get the new stuff. That's all the allocated memory. First, big
557       // buffer to hold it.
558
559       void *newSectionPtr = malloc(highWaterMark_ - lowWaterMark_);
560
561       pdvector<codeRange *> writes;
562       memoryTracker_->elements(writes);
563
564       for (unsigned i = 0; i < writes.size(); i++) {
565          assert(newSectionPtr);
566          memoryTracker *tracker = dynamic_cast<memoryTracker *>(writes[i]);
567          assert(tracker);
568          //inst_printf("memory tracker: 0x%lx  load=0x%lx  size=%d  %s\n", 
569          //tracker->get_local_ptr(), tracker->get_address(), tracker->get_size(),
570          //tracker->alloced ? "[A]" : "");
571          if (!tracker->alloced) continue;
572
573          // Copy whatever is in there into the big buffer, at the appropriate address
574          assert(tracker->get_address() >= lowWaterMark_);
575          Address offset = tracker->get_address() - lowWaterMark_;
576          assert((offset + tracker->get_size()) < highWaterMark_);
577          void *ptr = (void *)(offset + (Address)newSectionPtr);
578          memcpy(ptr, tracker->get_local_ptr(), tracker->get_size());
579       }
580             
581       // Righto. Now, that includes the old binary - by design - 
582       // so skip it and see what we're talking about size-wise. Which should
583       // be less than the highWaterMark, so we can double-check.
584
585       // Next, make a new section. We have the following parameters:
586       // Offset vaddr: we get this from Symtab - "first free address with sufficient space"
587       // std::string name: without reflection, ".dyninstInst"
588       // unsigned long flags: these are a SymtabAPI abstraction. We're going with text|data because
589       //    we might have both.
590       // bool loadable: heck yeah...
591         
592       Region *newSec = NULL;
593       symObj->findRegion(newSec, ".dyninstInst");
594       if (newSec) {
595          // We're re-instrumenting - will fail for now
596          fprintf(stderr, "ERROR:  unable to open/reinstrument previously instrumented binary %s!\n", newFileName.c_str());
597          return false;
598       }
599
600       symObj->addRegion(lowWaterMark_,
601                         newSectionPtr,
602                         highWaterMark_ - lowWaterMark_,
603                         ".dyninstInst",
604                         Region::RT_TEXTDATA,
605                         true);
606       
607       symObj->findRegion(newSec, ".dyninstInst");
608       assert(newSec);
609
610       
611       if (mobj == getAOut()) {
612          // Add dynamic symbol relocations
613          for (unsigned i=0; i < dependentRelocations.size(); i++) {
614             Address to = dependentRelocations[i]->getAddress();
615             Symbol *referring = dependentRelocations[i]->getReferring();
616             /*
617               if (!symObj->isStaticBinary() && !symObj->hasReldyn() && !symObj->hasReladyn()) {
618               Address addr = referring->getOffset();
619               bool result = writeDataSpace((void *) to, getAddressWidth(), &addr);
620               assert(result);
621               continue;
622               }
623             */
624                
625             // Create the relocationEntry
626             relocationEntry localRel(to, referring->getMangledName(), referring,
627                                      relocationEntry::getGlobalRelType(getAddressWidth(), referring));
628             
629             /*
630               if( mobj->isSharedLib() ) {
631               localRel.setRelAddr(to - mobj->imageOffset());
632               }
633             */
634             
635             symObj->addExternalSymbolReference(referring, newSec, localRel);
636             
637             /*
638               newSymbol = new Symbol(referring->getName(), 
639               Symbol::ST_FUNCTION, 
640               Symbol::SL_GLOBAL,
641               Symbol::SV_DEFAULT, 
642               (Address)0, 
643               symObj->getDefaultModule(),
644               NULL, 
645               8,
646               true, 
647               false);
648               symObj->addSymbol(newSymbol, referring);
649               if (!symObj->hasReldyn() && symObj->hasReladyn()) {
650               newSec->addRelocationEntry(to, newSymbol, relocationEntry::dynrel, Region::RT_RELA);
651               } else {
652               newSec->addRelocationEntry(to, newSymbol, relocationEntry::dynrel);
653               }
654             */
655          }
656       }
657       
658       pdvector<Symbol *> newSyms;
659       buildDyninstSymbols(newSyms, newSec, symObj->getOrCreateModule("dyninstInst",
660                                                                      lowWaterMark_));
661       for (unsigned i = 0; i < newSyms.size(); i++) {
662          symObj->addSymbol(newSyms[i]);
663       }
664       
665       // Okay, now...
666       // Hand textSection and newSection to DynSymtab.
667         
668       // First, textSection.
669         
670       // From the SymtabAPI documentation: we have the following methods we want to use.
671       // Symtab::addSection(Offset vaddr, void *data, unsigned int dataSize, std::string name, 
672       //                    unsigned long flags, bool loadable)
673       // Symtab::updateCode(void *buffer, unsigned size)
674       // Symtab::emit(std::string filename)
675         
676       // First, text
677       assert(symObj);
678       
679       
680       // And now we generate the new binary
681       //if (!symObj->emit(newFileName.c_str())) {
682       if (!symObj->emit(newFileName.c_str())) {
683          SymtabError lastError = Symtab::getLastSymtabError();
684          showErrorCallback(109, Symtab::printError(lastError));
685          return false;
686       }
687    return true;
688 }
689
690 Address BinaryEdit::maxAllocedAddr() {
691    inferiorFreeCompact();
692    Address hi = lowWaterMark_;
693
694    for (dictionary_hash<Address, heapItem *>::iterator iter = heap_.heapActive.begin();
695         iter != heap_.heapActive.end(); ++iter) {
696       Address localHi = (*iter)->addr + (*iter)->length;
697       if (localHi > hi) hi = localHi;
698    }
699    return hi;
700 }
701
702
703 bool BinaryEdit::inferiorMallocStatic(unsigned size) {
704     // Should be set by now
705     assert(highWaterMark_ != 0);
706
707 #if defined(USE_ADDRESS_MAPS)
708     void *buf = malloc(size);
709     if (!buf) return false;
710 #endif
711     
712     Address newStart = highWaterMark_;
713
714     // If there is a free heap that _ends_ at the highWaterMark,
715     // just extend it. This is a special case of inferiorFreeCompact;
716     // when we make that function faster, we can just call it. 
717     bool found = false;
718     for (unsigned i = 0; i < heap_.heapFree.size(); i++) {
719         heapItem *h = heap_.heapFree[i];
720         assert(h);
721         Address end = h->addr + h->length;
722         if (end == newStart) {
723             found = true;
724             h->length += size;
725             break;
726         }
727     }
728     if (!found) {
729         // Build tracking objects for it
730         heapItem *h = new heapItem(highWaterMark_, 
731                                    size,
732                                    anyHeap,
733                                    true,
734                                    HEAPfree);
735         addHeap(h);
736     }
737
738     highWaterMark_ += size;
739
740     return true;
741 }
742
743
744 bool BinaryEdit::createMemoryBackingStore(mapped_object *obj) {
745     // We want to create a buffer for every section in the
746     // binary so that we can store updates.
747
748     Symtab *symObj = obj->parse_img()->getObject();
749     vector<Region*> regs;
750     symObj->getAllRegions(regs);
751
752    for (unsigned i = 0; i < regs.size(); i++) {
753       memoryTracker *newTracker = NULL;
754       if (regs[i]->getRegionType() == Region::RT_BSS || (regs[i]->getMemSize() == 0))
755       {
756          continue;
757       }
758       else {
759          newTracker = new memoryTracker(regs[i]->getMemOffset(),
760                                         regs[i]->getMemSize(),
761                                         regs[i]->getPtrToRawData());
762          
763       }
764       newTracker->alloced = false;
765       if (!memoryTracker_)
766          memoryTracker_ = new codeRangeTree();
767       memoryTracker_->insert(newTracker);
768    }
769
770     
771    return true;
772 }
773
774
775 bool BinaryEdit::initialize() {
776    //Load the RT library
777    
778    // Create the tramp guard
779    
780    // Initialization. For now we're skipping threads, since we can't
781    // get the functions we need. However, we kinda need the recursion
782    // guard. This is an integer (one per thread, for now - 1) that 
783    // begins initialized to 1.
784
785     return true;
786 }
787
788 void BinaryEdit::addDependentRelocation(Address to, Symbol *referring) {
789   // prevent duplicate relocations
790   std::vector<depRelocation *>::iterator it;
791   for (it = dependentRelocations.begin(); it != dependentRelocations.end(); it++)
792     if ((*it)->getAddress() == to && (*it)->getReferring() == referring)
793       return;
794   // create a new relocation and add it to the collection
795   depRelocation *reloc = new depRelocation(to, referring);
796   dependentRelocations.push_back(reloc);
797 }
798
799 Address BinaryEdit::getDependentRelocationAddr(Symbol *referring) {
800         Address retAddr = 0x0;
801         for (unsigned i=0; i < dependentRelocations.size(); i++) {
802                 if (dependentRelocations[i]->getReferring() == referring) {
803                         retAddr = dependentRelocations[i]->getAddress();
804                         break;
805                 }
806         }
807         return retAddr;
808 }
809
810 void BinaryEdit::addLibraryPrereq(std::string libname) {
811    Symtab *symObj = mobj->parse_img()->getObject();
812    symObj->addLibraryPrereq(libname);
813 }
814
815
816 // Build a list of symbols describing instrumentation and relocated functions. 
817 // To keep this list (somewhat) short, we're doing one symbol per extent of 
818 // instrumentation + relocation for a particular function. 
819 // New: do this for one mapped object. 
820 void BinaryEdit::buildDyninstSymbols(pdvector<Symbol *> &newSyms, 
821                                      Region *newSec,
822                                      Module *newMod) {
823    for (std::vector<SymtabAPI::Symbol *>::iterator iter = newDyninstSyms_.begin();
824         iter != newDyninstSyms_.end(); ++iter) {
825       (*iter)->setModule(newMod);
826       (*iter)->setRegion(newSec);
827       newSyms.push_back(*iter);
828    }
829                                                                               
830
831    for (CodeTrackers::iterator i = relocatedCode_.begin();
832         i != relocatedCode_.end(); ++i) {
833       Relocation::CodeTracker *CT = *i;
834       func_instance *currFunc = NULL;
835       Address start = 0;
836       unsigned size = 0;
837       
838       for (Relocation::CodeTracker::TrackerList::const_iterator iter = CT->trackers().begin();
839            iter != CT->trackers().end(); ++iter) {
840          const Relocation::TrackerElement *tracker = *iter;
841          
842          func_instance *tfunc = tracker->func();
843          
844          if (currFunc != tfunc) {
845             // Starting a new function
846             if (currFunc) {
847                // Record the old one
848                // currfunc set
849                // start set
850                size = tracker->reloc() - start;
851                
852                std::string name = currFunc->prettyName();
853                name.append("_dyninst");
854                
855                Symbol *newSym = new Symbol(name.c_str(),
856                                            Symbol::ST_FUNCTION,
857                                            Symbol::SL_GLOBAL,
858                                            Symbol::SV_DEFAULT,
859                                            start,
860                                            newMod,
861                                            newSec,
862                                            size);                                        
863                newSyms.push_back(newSym);
864             }
865             currFunc = tfunc;
866             start = tracker->reloc();
867             size = 0;
868          }
869          else {
870             // Accumulate size
871             size = tracker->reloc() - start;
872          }
873       }
874    }
875 }
876     
877 void BinaryEdit::markDirty()
878 {
879    isDirty_ = true;
880 }
881
882 bool BinaryEdit::isDirty()
883 {
884    return isDirty_;
885 }
886
887 mapped_object *BinaryEdit::getMappedObject()
888 {
889    return mobj;
890 }
891
892 void BinaryEdit::setupRTLibrary(std::vector<BinaryEdit *> &r)
893 {
894    rtlib = r;
895
896    // Update addressSpace collection for RT library
897    runtime_lib.clear();
898    std::vector<BinaryEdit *>::iterator rtlib_it;
899    for(rtlib_it = r.begin(); rtlib_it != r.end(); ++rtlib_it) {
900        runtime_lib.insert((*rtlib_it)->getMappedObject());
901    }
902 }
903
904 void BinaryEdit::setTrampGuard(int_variable* tg)
905 {
906   trampGuardBase_ = tg;
907 }
908
909
910 int_variable* BinaryEdit::createTrampGuard()
911 {
912   // If we have one, just return it
913   if(trampGuardBase_) return trampGuardBase_;
914   assert(rtlib.size());
915
916   std::vector<BinaryEdit *>::iterator rtlib_it;
917   const int_variable *var = NULL;
918   for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
919       mapped_object *mobj = (*rtlib_it)->getMappedObject();
920       var = mobj->getVariable("DYNINST_default_tramp_guards");
921       if( var ) break;
922   }
923   
924   assert(var);
925   trampGuardBase_ = const_cast<int_variable *>(var);
926   
927   return trampGuardBase_;
928 }
929
930 vector<BinaryEdit *> &BinaryEdit::rtLibrary()
931 {
932    return rtlib;
933 }
934
935 func_instance *BinaryEdit::findOnlyOneFunction(const std::string &name,
936                                               const std::string &libname,
937                                               bool search_rt_lib)
938 {
939    func_instance *f = AddressSpace::findOnlyOneFunction(name, libname, search_rt_lib);
940    if (!f && search_rt_lib) {
941       std::vector<BinaryEdit *>::iterator rtlib_it;
942       for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
943           f = (*rtlib_it)->findOnlyOneFunction(name, libname, false);
944           if( f ) break;
945       }
946    }
947    return f;
948 }
949
950 void BinaryEdit::setMultiThreadCapable(bool b)
951 {
952    multithread_capable_ = b;
953 }
954
955 void BinaryEdit::addSibling(BinaryEdit *be)
956 {
957    if (this != be) {
958       siblings.push_back(be);
959    }
960 }
961
962 std::vector<BinaryEdit *> &BinaryEdit::getSiblings()
963 {
964    return siblings;
965 }
966
967
968
969 // Here's the story. We may need to install a trap handler for instrumentation
970 // to work in the rewritten binary. This doesn't play nicely with trap handlers
971 // that the binary itself registers. So we're going to replace every call to
972 // sigaction in the binary with a call to our wrapper. This wrapper:
973 //   1) Ignores attempts to register a SIGTRAP
974 //   2) Passes everything else through to sigaction
975 // It's called "dyn_sigaction".
976
977 bool BinaryEdit::usedATrap() {
978     return (!trapMapping.empty());
979 }
980
981 // Find all calls to sigaction equivalents and replace with
982 // calls to dyn_<sigaction_equivalent_name>. 
983 bool BinaryEdit::replaceTrapHandler() {
984
985     vector<string> sigaction_names;
986     OS::get_sigaction_names(sigaction_names);
987
988     pdvector<func_instance *> allFuncs;
989     getAllFunctions(allFuncs);
990     
991     bool replaced = false;
992     for (unsigned nidx = 0; nidx < sigaction_names.size(); nidx++) 
993     {
994         // find replacement function
995         std::stringstream repname;
996         repname << "dyn_" << sigaction_names[nidx];
997         func_instance *repfunc = findOnlyOneFunction(repname.str().c_str());
998         assert(repfunc);
999     
1000         // replace all callsites to current sigaction function
1001         for (unsigned i = 0; i < allFuncs.size(); i++) {
1002             func_instance *func = allFuncs[i];        
1003             assert(func);
1004
1005             for (PatchFunction::Blockset::const_iterator iter = func->blocks().begin();
1006                  iter != func->blocks().end(); ++iter) {
1007                 block_instance* iblk = SCAST_BI(*iter);
1008                 if (iblk->containsCall()) {
1009                     
1010                     // the function name could have up to two underscores
1011                     // prepended (e.g., sigaction, _sigaction, __sigaction),
1012                     // try all three possibilities for each name
1013                     std::string calleeName = iblk->calleeName();
1014                     std::string sigactName = sigaction_names[nidx];
1015                     for (int num_s=0; 
1016                          num_s <= 2; 
1017                          num_s++, sigactName.append(string("_"),0,1)) {
1018                         if (calleeName == sigactName) {
1019                             modifyCall(iblk, repfunc, func);
1020                             replaced = true;
1021                             break;
1022                         }
1023                     }
1024                 }
1025             } // for each func in the rewritten binary
1026         } // for each sigaction-equivalent function to replace
1027     }
1028
1029     if (!replaced) return true;
1030
1031     /* PatchAPI stuffs */
1032     return AddressSpace::patch(this);
1033     /* End of PatchAPI stuffs */
1034     // return relocate();
1035 }
1036
1037 bool BinaryEdit::needsPIC()
1038 {
1039    Symtab *symtab = getMappedObject()->parse_img()->getObject();
1040    assert(symtab);
1041    if(getMappedObject()->fileName().find("lib") == 0)
1042    {
1043        if(getMappedObject()->fileName().find(".so") != std::string::npos)
1044        {
1045            return true;
1046        }
1047    }
1048    //If there is a fixed load address, then we can calculate 
1049    // absolute addresses.
1050    return (symtab->getLoadAddress() == 0);  
1051 }
1052
1053 void BinaryEdit::addTrap(Address from, Address to, codeGen &gen) {
1054    gen.invalidate();
1055    gen.allocate(4);
1056    gen.setAddrSpace(this);
1057    gen.setAddr(from);
1058    insnCodeGen::generateTrap(gen);
1059    trapMapping.addTrapMapping(from, to, true);
1060 }
1061