Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / BPatch_addressSpace.C
1 /*
2  * Copyright (c) 1996-2011 Barton P. Miller
3  *
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  *
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #define BPATCH_FILE
33
34 #include "process.h"
35 #include "binaryEdit.h"
36 #include "EventHandler.h"
37 #include "mailbox.h"
38 #include "signalgenerator.h"
39 #include "inst.h"
40 #include "instP.h"
41 #include "instPoint.h"
42 #include "function.h" // func_instance
43 #include "codeRange.h"
44 #include "dyn_thread.h"
45 #include "miniTramp.h"
46 #include "addressSpace.h"
47
48 #include "mapped_module.h"
49
50 #include "BPatch_libInfo.h"
51 #include "BPatch_asyncEventHandler.h"
52 #include "BPatch.h"
53 #include "BPatch_thread.h"
54 #include "BPatch_function.h"
55 #include "BPatch_point.h"
56 #include "callbacks.h"
57
58 #include "BPatch_private.h"
59
60 #include "ast.h"
61
62 #include "BPatch_addressSpace.h"
63
64 #include "BPatch_instruction.h"
65
66 #include "mapped_object.h"
67
68 #include <sstream>
69 #include "Parsing.h"
70
71 #include "Command.h"
72 #include "Relocation/DynInstrumenter.h"
73
74 using Dyninst::PatchAPI::Patcher;
75 using Dyninst::PatchAPI::PatcherPtr;
76 using Dyninst::PatchAPI::DynInsertSnipCommand;
77 using Dyninst::PatchAPI::DynReplaceFuncCommand;
78 using Dyninst::PatchAPI::DynModifyCallCommand;
79 using Dyninst::PatchAPI::DynRemoveCallCommand;
80
81 BPatch_addressSpace::BPatch_addressSpace() :
82    image(NULL)
83 {
84 }
85
86 BPatch_addressSpace::~BPatch_addressSpace()
87 {}
88
89
90 BPatch_function *BPatch_addressSpace::findOrCreateBPFunc(func_instance* ifunc,
91                                                          BPatch_module *bpmod)
92 {
93    if (!bpmod)
94       bpmod = image->findOrCreateModule(ifunc->mod());
95    assert(bpmod);
96    if (bpmod->func_map.count(ifunc)) {
97       BPatch_function *bpf = bpmod->func_map[ifunc];
98       assert(bpf);
99       assert(bpf->func == ifunc);
100       return bpf;
101    }
102
103    // Find the module that contains the function
104    if (bpmod == NULL && ifunc->mod() != NULL) {
105       bpmod = getImage()->findModule(ifunc->mod()->fileName().c_str());
106    }
107
108    // findModule has a tendency to make new function objects... so
109    // check the map again
110    if (bpmod->func_map.count(ifunc)) {
111       BPatch_function *bpf = bpmod->func_map[ifunc];
112       assert(bpf);
113       assert(bpf->func == ifunc);
114       return bpf;
115    }
116
117    BPatch_function *ret = new BPatch_function(this, ifunc, bpmod);
118    assert( ret != NULL );
119    assert(ret->func == ifunc);
120    return ret;
121 }
122
123
124
125
126 BPatch_point *BPatch_addressSpace::findOrCreateBPPoint(BPatch_function *bpfunc,
127                                                        instPoint *ip,
128                                                        BPatch_procedureLocation pointType)
129 {
130    assert(ip);
131
132    BPatch_module *mod = image->findOrCreateModule(ip->func()->mod());
133    assert(mod);
134
135    if (mod->instp_map.count(ip))
136       return mod->instp_map[ip];
137
138    if (pointType == BPatch_locUnknownLocation) {
139       cerr << "Error: point type not specified!" << endl;
140       assert(0);
141       return NULL;
142    }
143
144    AddressSpace *lladdrSpace = ip->func()->proc();
145    if (!bpfunc)
146       bpfunc = findOrCreateBPFunc(ip->func(), mod);
147
148    assert(bpfunc->func == ip->func());
149    std::pair<instPoint *, instPoint *> pointsToUse = instPoint::getInstpointPair(ip);
150
151    BPatch_point *pt = new BPatch_point(this, bpfunc,
152                                        pointsToUse.first, pointsToUse.second,
153                                        pointType, lladdrSpace);
154    mod->instp_map[ip] = pt;
155
156    return pt;
157 }
158
159 BPatch_variableExpr *BPatch_addressSpace::findOrCreateVariable(int_variable *v,
160                                                                BPatch_type *type)
161 {
162    BPatch_module *mod = image->findOrCreateModule(v->mod());
163    assert(mod);
164    if (mod->var_map.count(v))
165       return mod->var_map[v];
166
167    if (!type) {
168       SymtabAPI::Type *stype = v->ivar()->svar()->getType();
169
170       if (stype){
171          type = BPatch_type::findOrCreateType(stype);
172       }else{
173          type = BPatch::bpatch->type_Untyped;
174       }
175    }
176
177    BPatch_variableExpr *var = BPatch_variableExpr::makeVariableExpr(this, v, type);
178    mod->var_map[v] = var;
179    return var;
180 }
181
182
183
184 BPatch_function *BPatch_addressSpace::createBPFuncCB(AddressSpace *a, func_instance *f)
185 {
186    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
187    assert(aS);
188    return aS->findOrCreateBPFunc(f, NULL);
189 }
190
191 BPatch_point *BPatch_addressSpace::createBPPointCB(AddressSpace *a,
192                                                    func_instance *f,
193                                                    instPoint *ip, int type)
194 {
195    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
196    assert(aS);
197
198    BPatch_module *bpmod = aS->getImageInt()->findOrCreateModule(f->mod());
199    assert(bpmod);
200
201    BPatch_function *func = aS->findOrCreateBPFunc(f, bpmod);
202    assert(func);
203
204    return aS->findOrCreateBPPoint(func, ip, (BPatch_procedureLocation) type);
205 }
206
207
208
209 /***************************************************************************
210  * Bpatch_snippetHandle
211  ***************************************************************************/
212
213 /*
214  * BPatchSnippetHandle::BPatchSnippetHandle
215  *
216  * Constructor for BPatchSnippetHandle.  Delete the snippet instance(s)
217  * associated with the BPatchSnippetHandle.
218  */
219 BPatchSnippetHandle::BPatchSnippetHandle(BPatch_addressSpace * addSpace) :
220    addSpace_(addSpace)
221 {
222 }
223
224 /*
225  * BPatchSnippetHandle::~BPatchSnippetHandle
226  *
227  * Destructor for BPatchSnippetHandle.  Delete the snippet instance(s)
228  * associated with the BPatchSnippetHandle.
229  */
230 void BPatchSnippetHandle::BPatchSnippetHandle_dtor()
231 {
232    // don't delete inst instances since they are might have been copied
233 }
234
235 BPatch_addressSpace *BPatchSnippetHandle::getAddressSpaceInt()
236 {
237    return addSpace_;
238 }
239
240 BPatch_process *BPatchSnippetHandle::getProcessInt()
241 {
242    return dynamic_cast<BPatch_process *>(addSpace_);
243 }
244
245 BPatch_Vector<BPatch_thread *> &BPatchSnippetHandle::getCatchupThreadsInt()
246 {
247    return catchup_threads;
248 }
249
250
251 BPatch_image * BPatch_addressSpace::getImageInt()
252 {
253    return image;
254 }
255
256
257 /*
258  * BPatch_addressSpace::deleteSnippet
259  *
260  * Deletes an instance of a snippet.
261  *
262  * handle       The handle returned by insertSnippet when the instance to
263  *              deleted was created.
264  */
265
266 bool BPatch_addressSpace::deleteSnippetInt(BPatchSnippetHandle *handle)
267 {
268    if (getTerminated()) return true;
269
270    if (handle == NULL) {
271        bperr("Request to delete NULL snippet handle, returning false\n");
272        return false;
273    }
274
275    if (handle->addSpace_ != this) {
276      bperr("Error: wrong address space in deleteSnippet\n");
277      return false;
278    }
279
280    // if this is a process, check to see if the instrumentation is
281    // executing on the call stack
282    if ( handle->getProcess() && handle->mtHandles_.size() > 0 &&
283        BPatch_normalMode !=
284         handle->mtHandles_[0]->instP()->func()->obj()->hybridMode())
285    {
286        if (handle->mtHandles_.size() > 1) {
287            mal_printf("ERROR: Removing snippet that is installed in "
288                           "multiple miniTramps %s[%d]\n",FILE__,__LINE__);
289      }
290    }
291
292    // uninstrument and remove snippet handle from point datastructures
293    for (unsigned int i=0; i < handle->mtHandles_.size(); i++)
294      {
295        instPoint *iPoint = handle->mtHandles_[i]->instP();
296        handle->mtHandles_[i]->uninstrument();
297        BPatch_point *bPoint = findOrCreateBPPoint(NULL, iPoint,
298                                                   BPatch_point::convertInstPointType_t(iPoint->type()));
299        assert(bPoint);
300        bPoint->removeSnippet(handle);
301      }
302
303    //delete handle; //KEVINTODO: fix this, add instrumentation-removal callback
304    handle->mtHandles_.clear();
305
306    if (pendingInsertions == NULL) {
307      // Trigger it now
308      bool tmp;
309      finalizeInsertionSet(false, &tmp);
310    }
311
312    return true;
313 }
314
315 /*
316  * BPatch_addressSpace::replaceCode
317  *
318  * Replace a given instruction with a BPatch_snippet.
319  *
320  * point       Represents the instruction to be replaced
321  * snippet     The replacing snippet
322  */
323
324 bool BPatch_addressSpace::replaceCodeInt(BPatch_point *point,
325       BPatch_snippet *snippet)
326 {
327    // Need to reevaluate how this code works. I don't think it should be
328    // point-based, though.
329
330    assert(0);
331    return false;
332 }
333
334 /*
335  * BPatch_addressSpace::replaceFunctionCall
336  *
337  * Replace a function call with a call to a different function.  Returns true
338  * upon success, false upon failure.
339  *
340  * point        The call site that is to be changed.
341  * newFunc      The function that the call site will now call.
342  */
343 bool BPatch_addressSpace::replaceFunctionCallInt(BPatch_point &point,
344       BPatch_function &newFunc)
345 {
346    char name[1024];
347    newFunc.getName(name, 1024);
348
349    // Can't make changes to code when mutations are not active.
350    if (!getMutationsActive())
351       return false;
352
353    assert(point.point && newFunc.lowlevel_func());
354
355   /* PatchAPI stuffs */
356    AddressSpace* addr_space = point.getAS();
357    DynModifyCallCommand::Ptr rep_call = DynModifyCallCommand::create(addr_space,
358       point.point->block(), newFunc.lowlevel_func(), point.point->func());
359   addr_space->patcher()->add(rep_call);
360   /* End of PatchAPI */
361   /*
362    point.getAS()->modifyCall(point.point->block(),
363                              newFunc.lowlevel_func(),
364                              point.point->func());
365   */
366    if (pendingInsertions == NULL) {
367      // Trigger it now
368      bool tmp;
369      finalizeInsertionSet(false, &tmp);
370    }
371    return true;
372 }
373
374 /*
375  * BPatch_addressSpace::removeFunctionCall
376  *
377  * Replace a function call with a NOOP.  Returns true upon success, false upon
378  * failure.
379  *
380  * point        The call site that is to be NOOPed out.
381  */
382 bool BPatch_addressSpace::removeFunctionCallInt(BPatch_point &point)
383 {
384    // Can't make changes to code when mutations are not active.
385    if (!getMutationsActive())
386       return false;
387
388    assert(point.point);
389
390   /* PatchAPI stuffs */
391    AddressSpace* addr_space = point.getAS();
392    DynRemoveCallCommand::Ptr remove_call = DynRemoveCallCommand::create(addr_space,
393       point.point->block(), point.point->func());
394   addr_space->patcher()->add(remove_call);
395   /* End of PatchAPI */
396    // point.getAS()->removeCall(point.point->block(), point.point->func());
397
398    if (pendingInsertions == NULL) {
399      // Trigger it now
400      bool tmp;
401      finalizeInsertionSet(false, &tmp);
402    }
403
404    return true;
405 }
406
407
408 /*
409  * BPatch_addressSpace::replaceFunction
410  *
411  * Replace all calls to function OLDFUNC with calls to NEWFUNC.
412  * Returns true upon success, false upon failure.
413  *
414  * oldFunc      The function to replace
415  * newFunc      The replacement function
416  */
417 bool BPatch_addressSpace::replaceFunctionInt(BPatch_function &oldFunc,
418       BPatch_function &newFunc)
419 {
420   assert(oldFunc.lowlevel_func() && newFunc.lowlevel_func());
421   if (!getMutationsActive())
422     return false;
423
424   // Self replacement is a nop
425   // We should just test direct equivalence here...
426   if (oldFunc.lowlevel_func() == newFunc.lowlevel_func()) {
427     return true;
428   }
429
430   /* PatchAPI stuffs */
431   AddressSpace* addr_space = oldFunc.lowlevel_func()->proc();
432   DynReplaceFuncCommand::Ptr rep_func = DynReplaceFuncCommand::create(addr_space,
433      oldFunc.lowlevel_func(), newFunc.lowlevel_func());
434   addr_space->patcher()->add(rep_func);
435   /* End of PatchAPI */
436
437   //oldFunc.lowlevel_func()->proc()->replaceFunction(oldFunc.lowlevel_func(), newFunc.lowlevel_func());
438
439   if (pendingInsertions == NULL) {
440     // Trigger it now
441     bool tmp;
442     finalizeInsertionSet(false, &tmp);
443   }
444   return true;
445 }
446
447 bool BPatch_addressSpace::wrapFunctionInt(BPatch_function *original,
448                                           BPatch_function *wrapper,
449                                           Dyninst::SymtabAPI::Symbol *clone)
450 {
451    assert(original->lowlevel_func() && wrapper->lowlevel_func());
452    if (!getMutationsActive())
453       return false;
454
455    // Self replacement is a nop
456    // We should just test direct equivalence here...
457    if (original->lowlevel_func() == wrapper->lowlevel_func()) {
458       return true;
459    }
460
461    if (!original->lowlevel_func()->proc()->wrapFunction(original->lowlevel_func(), 
462                                                       wrapper->lowlevel_func(),
463                                                       clone))
464       return false;
465
466    if (pendingInsertions == NULL) {
467       // Trigger it now
468       bool tmp;
469       finalizeInsertionSet(false, &tmp);
470    }
471    return true;
472 }
473
474
475 bool BPatch_addressSpace::getAddressRangesInt( const char * fileName,
476       unsigned int lineNo,
477       std::vector< std::pair< unsigned long, unsigned long > > & ranges )
478 {
479    unsigned int originalSize = ranges.size();
480    BPatch_Vector< BPatch_module * > * modules = image->getModules();
481
482    /* Iteratate over the modules, looking for addr in each. */
483    for ( unsigned int i = 0; i < modules->size(); i++ ) {
484       BPatch_module *m = (*modules)[i];
485       m->getAddressRanges(fileName, lineNo, ranges);
486    }
487
488    if ( ranges.size() != originalSize ) { return true; }
489
490    return false;
491 } /* end getAddressRangesInt() */
492
493 bool BPatch_addressSpace::getSourceLinesInt( unsigned long addr,
494       BPatch_Vector< BPatch_statement > & lines )
495 {
496    return image->getSourceLinesInt(addr, lines);
497 } /* end getLineAndFile() */
498
499
500 /*
501  * BPatch_process::malloc
502  *
503  * Allocate memory in the thread's address space.
504  *
505  * n    The number of bytes to allocate.
506  *
507  * Returns:
508  *      A pointer to a BPatch_variableExpr representing the memory.
509  *
510  * If otherwise unspecified when binary rewriting, then the allocation
511  * happens in the original object.
512  */
513
514 BPatch_variableExpr *BPatch_addressSpace::mallocInt(int n, std::string name)
515 {
516    std::vector<AddressSpace *> as;
517    assert(BPatch::bpatch != NULL);
518    getAS(as);
519    assert(as.size());
520    void *ptr = (void *) as[0]->inferiorMalloc(n, dataHeap);
521    if (!ptr) return NULL;
522    if(name.empty()){
523       std::stringstream namestr;
524       namestr << "dyn_malloc_0x" << std::hex << ptr << "_" << n << "_bytes";
525       name = namestr.str();
526    }
527    BPatch_type *type = BPatch::bpatch->createScalar(name.c_str(), n);
528
529    return BPatch_variableExpr::makeVariableExpr(this, as[0], name, ptr,
530                                                 type);
531 }
532
533
534 /*
535  * BPatch_process::malloc
536  *
537  * Allocate memory in the thread's address space for a variable of the given
538  * type.
539  *
540  * type         The type of variable for which to allocate space.
541  *
542  * Returns:
543  *      A pointer to a BPatch_variableExpr representing the memory.
544  *
545  * XXX Should return NULL on failure, but the function which it calls,
546  *     inferiorMalloc, calls exit rather than returning an error, so this
547  *     is not currently possible.
548  */
549
550 BPatch_variableExpr *BPatch_addressSpace::mallocByType(const BPatch_type &type, std::string name)
551 {
552    std::vector<AddressSpace *> as;
553    assert(BPatch::bpatch != NULL);
554    getAS(as);
555    assert(as.size());
556    BPatch_type &t = const_cast<BPatch_type &>(type);
557    void *mem = (void *) as[0]->inferiorMalloc(t.getSize(), dataHeap);
558    if (!mem) return NULL;
559    if(name.empty()){
560       std::stringstream namestr;
561       namestr << "dyn_malloc_0x" << std::hex << mem << "_" << type.getName();
562       name = namestr.str();
563    }
564    BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, &t);
565    return varExpr;
566 }
567
568
569 /*
570  * BPatch_process::free
571  *
572  * Free memory that was allocated with BPatch_process::malloc.
573  *
574  * ptr          A BPatch_variableExpr representing the memory to free.
575  */
576
577 bool BPatch_addressSpace::freeInt(BPatch_variableExpr &ptr)
578 {
579   if(ptr.intvar)
580   {
581     // kill the symbols
582
583   }
584
585    ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr());
586    return true;
587 }
588
589 BPatch_variableExpr *BPatch_addressSpace::createVariableInt(std::string name,
590                                                             Dyninst::Address addr,
591                                                             BPatch_type *type) {
592     assert(BPatch::bpatch != NULL);
593     std::vector<AddressSpace *> as;
594     getAS(as);
595     assert(as.size());
596
597 //dynC added feature
598     if(strstr(name.c_str(), "dynC") == name.c_str()){
599        void *mem = (void *) as[0]->inferiorMalloc(type->getSize(), dataHeap);
600        if (!mem) return NULL;
601        BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, type);
602        BPatch_module *mod = image->findOrCreateModule(varExpr->intvar->mod());
603        assert(mod);
604        mod->var_map[varExpr->intvar] = varExpr;
605        return varExpr;
606     }
607
608     BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this,
609                                                  as[0],
610                                                  name,
611                                                  (void *)addr,
612                                                  type);
613
614     return varExpr;
615 }
616
617 /*
618  * BPatch_addressSpace::findFunctionByAddr
619  *
620  * Returns the function that contains the specified address, or NULL if the
621  * address is not within a function.
622  *
623  * addr         The address to use for the lookup.
624  */
625 BPatch_function *BPatch_addressSpace::findFunctionByAddrInt(void *addr)
626 {
627    std::vector<AddressSpace *> as;
628
629    getAS(as);
630    assert(as.size());
631    std::set<func_instance *> funcs;
632    if (!as[0]->findFuncsByAddr((Address) addr, funcs)) {
633       // if it's a mapped_object that has yet to be analyzed,
634       // trigger analysis and re-invoke this function
635        mapped_object *obj = as[0]->findObject((Address) addr);
636        if (obj &&
637            !obj->isAnalyzed()) {
638          obj->analyze();
639          return findFunctionByAddrInt(addr);
640       }
641       return NULL;
642    }
643    if (funcs.empty()) return NULL;
644
645    if (funcs.size() > 1) {
646        bpwarn("Warning: deprecated function findFunctionByAddr found "
647               "multiple functions sharing address 0x%lx, picking one at "
648               "random.  Use findFunctionByEntry or findFunctionsByAddr\n",
649               addr);
650    }
651
652    return findOrCreateBPFunc((*(funcs.begin())), NULL);
653 }
654
655 /*
656  *  BPatch_addressSpace::findFunctionByEntry
657  *
658  *  Returns the function starting at the given address, or NULL if the
659  *  address is not within a function.
660  *
661  *  entry       The address to use for the lookup.
662  */
663 BPatch_function *BPatch_addressSpace::findFunctionByEntryInt(Address entry)
664 {
665     vector<BPatch_function*> funcs;
666     findFunctionsByAddr(entry, funcs);
667     vector<BPatch_function*>::iterator fit;
668     for (fit = funcs.begin(); fit != funcs.end(); fit++) {
669         if (entry == (Address)(*fit)->getBaseAddrInt()) {
670             return *fit;
671         }
672     }
673     return NULL;
674 }
675
676 bool BPatch_addressSpace::findFuncsByRange(Address startAddr,
677                                            Address endAddr,
678                                            std::set<BPatch_function*> &bpFuncs)
679 {
680     std::vector<AddressSpace *> as;
681     getAS(as);
682     assert(as.size());
683
684     // find the first code range in the region
685     mapped_object* mobj = as[0]->findObject(startAddr);
686     assert(mobj);
687     set<func_instance*> intFuncs;
688     mobj->findFuncsByRange(startAddr,endAddr,intFuncs);
689     set<func_instance*>::iterator fIter = intFuncs.begin();
690     for (; fIter != intFuncs.end(); fIter++) {
691         BPatch_function * bpfunc = findOrCreateBPFunc(*fIter,NULL);
692         bpFuncs.insert(bpfunc);
693     }
694     return 0 != bpFuncs.size();
695 }
696
697
698 /*
699  * BPatch_addressSpace::findFunctionsByAddr
700  *
701  * Returns the functions that contain the specified address, or NULL if the
702  * address is not within a function. (there could be multiple functions
703  * because of the possibility of shared code)
704  *
705  * addr         The address to use for the lookup.
706  * returns false if there were no functions that matched the address
707  */
708 bool BPatch_addressSpace::findFunctionsByAddrInt
709     (Address addr, std::vector<BPatch_function*> &funcs)
710 {
711     std::vector<AddressSpace *> as;
712     getAS(as);
713     assert(as.size());
714
715     // grab the funcs, return false if there aren't any
716     std::set<func_instance*> intfuncs;
717     if (!as[0]->findFuncsByAddr( addr, intfuncs )) {
718         return false;
719     }
720     // convert to BPatch_functions
721     for (std::set<func_instance*>::iterator fiter=intfuncs.begin();
722          fiter != intfuncs.end(); fiter++)
723     {
724         funcs.push_back(findOrCreateBPFunc(*fiter, NULL));
725     }
726     return 0 < funcs.size();
727 }
728
729
730 /*
731  * BPatch_addressSpace::findModuleByAddr
732  *
733  * Returns the module that contains the specified address, or NULL if the
734  * address is not within a module.  Does NOT trigger parsing
735  *
736  * addr         The address to use for the lookup.
737  */
738 BPatch_module *BPatch_addressSpace::findModuleByAddr(Address addr)
739 {
740    std::vector<AddressSpace *> as;
741    getAS(as);
742    assert(as.size());
743
744    mapped_object *obj = as[0]->findObject(addr);
745    if ( ! obj )
746        return NULL;
747
748    const pdvector<mapped_module*> mods = obj->getModules();
749    if (mods.size()) {
750        return getImage()->findOrCreateModule(mods[0]);
751    }
752    return NULL;
753 }
754
755
756 /*
757  * BPatch_addressSpace::insertSnippet
758  *
759  * Insert a code snippet at a given instrumentation point.  Upon success,
760  * returns a handle to the created instance of the snippet, which can be used
761  * to delete it.  Otherwise returns NULL.
762  *
763  * expr         The snippet to insert.
764  * point        The point at which to insert it.
765  */
766
767 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetInt(const BPatch_snippet &expr,
768       BPatch_point &point,
769       BPatch_snippetOrder order)
770 {
771    BPatch_callWhen when;
772    if (point.getPointType() == BPatch_exit)
773       when = BPatch_callAfter;
774    else
775       when = BPatch_callBefore;
776
777    return insertSnippetWhen(expr, point, when, order);
778 }
779
780 /*
781  * BPatch_addressSpace::insertSnippet
782  *
783  * Insert a code snippet at a given instrumentation point.  Upon succes,
784  * returns a handle to the created instance of the snippet, which can be used
785  * to delete it.  Otherwise returns NULL.
786  *
787  * expr         The snippet to insert.
788  * point        The point at which to insert it.
789  */
790
791 // This handles conversion without requiring inst.h in a header file...
792 extern bool BPatchToInternalArgs(BPatch_point *point,
793       BPatch_callWhen when,
794       BPatch_snippetOrder order,
795       callWhen &ipWhen,
796       callOrder &ipOrder);
797
798
799 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetWhen(const BPatch_snippet &expr,
800       BPatch_point &point,
801       BPatch_callWhen when,
802       BPatch_snippetOrder order)
803 {
804    BPatch_Vector<BPatch_point *> points;
805    points.push_back(&point);
806    return insertSnippetAtPointsWhen(expr,
807          points,
808          when,
809          order);
810 }
811
812 extern int dyn_debug_ast;
813
814 /*
815  * BPatch_addressSpace::insertSnippet
816  *
817  * Insert a code snippet at each of a list of instrumentation points.  Upon
818  * success, Returns a handle to the created instances of the snippet, which
819  * can be used to delete them (as a unit).  Otherwise returns NULL.
820  *
821  * expr         The snippet to insert.
822  * points       The list of points at which to insert it.
823  */
824
825 // A lot duplicated from the single-point version. This is unfortunate.
826 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetAtPointsWhen(const BPatch_snippet &expr,
827                                                                     const BPatch_Vector<BPatch_point *> &points,
828                                                                     BPatch_callWhen when,
829                                                                     BPatch_snippetOrder order)
830 {
831   BPatchSnippetHandle *retHandle = new BPatchSnippetHandle(this);
832
833   if (dyn_debug_inst) {
834       BPatch_function *f;
835       for (unsigned i=0; i<points.size(); i++) {
836          f = points[i]->getFunction();
837          const char *sname = f->func->prettyName().c_str();
838          inst_printf("[%s:%u] - %d. Insert instrumentation at function %s, "
839                "address %p, when %d, order %d\n",
840                FILE__, __LINE__, i,
841                sname, points[i]->getAddress(), (int) when, (int) order);
842
843       }
844   }
845
846   if (BPatch::bpatch->isTypeChecked()) {
847       if (expr.ast_wrapper->checkType() == BPatch::bpatch->type_Error) {
848         fprintf(stderr, "[%s:%u] - Type error inserting instrumentation\n",
849                 FILE__, __LINE__);
850          expr.ast_wrapper->debugPrint();
851          return false;
852       }
853    }
854
855    if (!points.size()) {
856      fprintf(stderr, "%s[%d]:  request to insert snippet at zero points!\n", FILE__, __LINE__);
857       return false;
858    }
859
860    for (unsigned i = 0; i < points.size(); i++) {
861       BPatch_point *bppoint = points[i];
862
863       if (bppoint->addSpace == NULL) {
864          fprintf(stderr, "Error: attempt to use point with no process info\n");
865          continue;
866       }
867
868       if (dynamic_cast<BPatch_addressSpace *>(bppoint->addSpace) != this) {
869          fprintf(stderr, "Error: attempt to use point specific to a different process\n");
870          continue;
871       }
872
873       callWhen ipWhen;
874       callOrder ipOrder;
875
876       if (!BPatchToInternalArgs(bppoint, when, order, ipWhen, ipOrder)) {
877         fprintf(stderr, "[%s:%u] - BPatchToInternalArgs failed for point %d\n",
878                FILE__, __LINE__, i);
879          return retHandle;
880       }
881
882       /* PatchAPI stuffs */
883       instPoint* ipoint = bppoint->getPoint(when);
884       AddressSpace* ias = ipoint->proc();
885       PatcherPtr patcher = ias->patcher();
886       DynInsertSnipCommand::Ptr ins_snip = DynInsertSnipCommand::create(ipoint,
887               ipOrder, expr.ast_wrapper, BPatch::bpatch->isTrampRecursive());
888       miniTramp* mini = ins_snip->mini();
889       patcher->add(ins_snip);
890       /* End of PatchAPI stuffs */
891
892       if (mini) {
893         retHandle->mtHandles_.push_back(mini);
894         bppoint->recordSnippet(when, order, retHandle);
895       }
896    }
897
898    if (pendingInsertions == NULL) {
899      // Trigger it now
900      bool tmp;
901      finalizeInsertionSet(false, &tmp); //KEVINTODO: do we really want this?
902    }
903    return retHandle;
904 }
905
906
907 /*
908  * BPatch_addressSpace::insertSnippet
909  *
910  * Insert a code snippet at each of a list of instrumentation points.  Upon
911  * success, Returns a handle to the created instances of the snippet, which
912  * can be used to delete them (as a unit).  Otherwise returns NULL.
913  *
914  * expr         The snippet to insert.
915  * points       The list of points at which to insert it.
916  */
917
918 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetAtPoints(
919       const BPatch_snippet &expr,
920       const BPatch_Vector<BPatch_point *> &points,
921       BPatch_snippetOrder order)
922 {
923    return insertSnippetAtPointsWhen(expr,
924          points,
925          BPatch_callUnset,
926          order);
927 }
928
929 /*
930  * BPatch_addressSpace::isStaticExecutable
931  *
932  * Returns true if the underlying image represents a statically-linked executable, false otherwise.
933  */
934 bool BPatch_addressSpace::isStaticExecutableInt() {
935    std::vector<AddressSpace *> as;
936    getAS(as);
937
938    if( !as.size() ) return false;
939
940    AddressSpace *aout = as[0];
941    return aout->getAOut()->isStaticExec();
942 }
943
944 #include "registerSpace.h"
945
946 #if defined(cap_registers)
947 bool BPatch_addressSpace::getRegistersInt(std::vector<BPatch_register> &regs) {
948    if (registers_.size()) {
949        regs = registers_;
950        return true;
951    }
952
953    std::vector<AddressSpace *> as;
954
955    getAS(as);
956    assert(as.size());
957
958    registerSpace *rs = registerSpace::getRegisterSpace(as[0]);
959
960    for (unsigned i = 0; i < rs->realRegs().size(); i++) {
961        // Let's do just GPRs for now
962        registerSlot *regslot = rs->realRegs()[i];
963        registers_.push_back(BPatch_register(regslot->name, regslot->number));
964    }
965    regs = registers_;
966    return true;
967 }
968 #else
969 bool BPatch_addressSpace::getRegistersInt(std::vector<BPatch_register> &) {
970     // Empty vector since we're not supporting register objects on
971     // these platforms (yet)
972    return false;
973 }
974 #endif
975
976 #if defined(cap_registers)
977 bool BPatch_addressSpace::createRegister_NPInt(std::string regName,
978                                                BPatch_register &reg) {
979     // Build the register list.
980     std::vector<BPatch_register> dontcare;
981     getRegisters(dontcare);
982
983     for (unsigned i = 0; i < registers_.size(); i++) {
984         if (registers_[i].name() == regName) {
985             reg = registers_[i];
986             return true;
987         }
988     }
989     return false;
990 }
991 #else
992 bool BPatch_addressSpace::createRegister_NPInt(std::string,
993                                                BPatch_register &)
994 {
995    return false;
996 }
997 #endif
998
999 bool BPatch_addressSpace::loadLibraryInt(const char * /*libname*/, bool /*reload*/)
1000 {
1001         return false;
1002 }
1003
1004 void BPatch_addressSpace::allowTrapsInt(bool allowtraps)
1005 {
1006    std::vector<AddressSpace *> as;
1007    getAS(as);
1008
1009    for (std::vector<AddressSpace *>::iterator i = as.begin(); i != as.end(); i++)
1010    {
1011       (*i)->setUseTraps(allowtraps);
1012    }
1013 }
1014
1015 BPatch_variableExpr *BPatch_addressSpace::createVariableInt(
1016                         Dyninst::Address at_addr,
1017                         BPatch_type *type, std::string var_name,
1018                         BPatch_module *in_module)
1019 {
1020    BPatch_binaryEdit *binEdit = dynamic_cast<BPatch_binaryEdit *>(this);
1021    if (binEdit && !in_module) {
1022       //Address alone isn't unique when binary rewriting
1023       return NULL;
1024    }
1025    if (!type) {
1026       //Required for size information.
1027       return NULL;
1028    }
1029    AddressSpace *ll_addressSpace = NULL;
1030
1031    std::vector<AddressSpace *> as;
1032    getAS(as);
1033    if (binEdit) {
1034       std::vector<AddressSpace *>::iterator as_i;
1035       for (as_i = as.begin(); as_i != as.end(); as_i++)
1036       {
1037          BinaryEdit *b = dynamic_cast<BinaryEdit *>(*as_i);
1038          assert(b);
1039          if (in_module->mod->obj() == b->getMappedObject()) {
1040             ll_addressSpace = *as_i;
1041             break;
1042          }
1043       }
1044    }
1045    else {
1046       assert(as.size() == 1);
1047       ll_addressSpace = as[0];
1048    }
1049
1050    if (!ll_addressSpace) {
1051       //in_module doesn't belong to 'this'
1052       return NULL;
1053    }
1054
1055    if (!var_name.size()) {
1056       std::stringstream namestream;
1057       namestream << "dyninst_var_" << std::hex << at_addr;
1058       var_name = namestream.str();
1059    }
1060
1061    return BPatch_variableExpr::makeVariableExpr(this, ll_addressSpace, var_name,
1062                                                 (void *) at_addr, type);
1063 }
1064