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