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