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