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