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