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