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