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