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