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