More gcc 4.8 fixes.
[dyninst.git] / dyninstAPI / src / BPatch_addressSpace.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #define BPATCH_FILE
32
33 #include "binaryEdit.h"
34 #include "inst.h"
35 #include "instP.h"
36 #include "function.h" // Dyninst::PatchAPI::PatchFunction
37 #include "codeRange.h"
38 #include "addressSpace.h"
39 #include "dynProcess.h"
40 #include "debug.h"
41
42 #include "mapped_module.h"
43
44 #include "BPatch_libInfo.h"
45 #include "BPatch.h"
46 #include "BPatch_thread.h"
47 #include "BPatch_function.h"
48 #include "BPatch_point.h"
49
50 #include "BPatch_private.h"
51
52 #include "ast.h"
53
54 #include "BPatch_addressSpace.h"
55
56 #include "BPatch_instruction.h"
57
58 #include "mapped_object.h"
59
60 #include <sstream>
61 #include "Parsing.h"
62
63 #include "Command.h"
64 #include "Relocation/DynInstrumenter.h"
65
66 #include "PatchMgr.h"
67
68 using Dyninst::PatchAPI::Patcher;
69 using Dyninst::PatchAPI::DynInsertSnipCommand;
70 using Dyninst::PatchAPI::DynReplaceFuncCommand;
71 using Dyninst::PatchAPI::DynModifyCallCommand;
72 using Dyninst::PatchAPI::DynRemoveCallCommand;
73
74 BPatch_addressSpace::BPatch_addressSpace() :
75    image(NULL)
76 {
77 }
78
79 BPatch_addressSpace::~BPatch_addressSpace()
80 {}
81
82
83 BPatch_function *BPatch_addressSpace::findOrCreateBPFunc(Dyninst::PatchAPI::PatchFunction* ifunc,
84                                                          BPatch_module *bpmod)
85 {
86    func_instance *fi = static_cast<func_instance *>(ifunc);
87    if (!bpmod)
88       bpmod = image->findOrCreateModule(fi->mod());
89    assert(bpmod);
90    if (bpmod->func_map.count(ifunc)) {
91       BPatch_function *bpf = bpmod->func_map[ifunc];
92       assert(bpf);
93       assert(bpf->func == ifunc);
94       return bpf;
95    }
96
97    // Find the module that contains the function
98    if (bpmod == NULL && fi->mod() != NULL) {
99       bpmod = getImage()->findModule(fi->mod()->fileName().c_str());
100    }
101
102    // findModule has a tendency to make new function objects... so
103    // check the map again
104    if (bpmod->func_map.count(ifunc)) {
105       BPatch_function *bpf = bpmod->func_map[ifunc];
106       assert(bpf);
107       assert(bpf->func == ifunc);
108       return bpf;
109    }
110
111    BPatch_function *ret = new BPatch_function(this, fi, bpmod);
112    assert( ret != NULL );
113    assert(ret->func == ifunc);
114    return ret;
115 }
116
117
118
119
120 BPatch_point *BPatch_addressSpace::findOrCreateBPPoint(BPatch_function *bpfunc,
121                                                        Dyninst::PatchAPI::Point *p,
122                                                        BPatch_procedureLocation pointType)
123 {
124    instPoint *ip = static_cast<instPoint *>(p);
125    assert(ip);
126    func_instance *fi = static_cast<func_instance *>(ip->func());
127    if (!fi) return NULL; // PatchAPI can create function-less points, but we can't represent them as BPatch_points
128
129    BPatch_module *mod = image->findOrCreateModule(fi->mod());
130    assert(mod);
131
132    if (mod->instp_map.count(ip))
133       return mod->instp_map[ip];
134
135    if (pointType == BPatch_locUnknownLocation) {
136       cerr << "Error: point type not specified!" << endl;
137       assert(0);
138       return NULL;
139    }
140
141    AddressSpace *lladdrSpace = fi->proc();
142    if (!bpfunc)
143       bpfunc = findOrCreateBPFunc(fi, mod);
144
145    assert(bpfunc->func == ip->func());
146    std::pair<instPoint *, instPoint *> pointsToUse = instPoint::getInstpointPair(ip);
147
148    BPatch_point *pt = new BPatch_point(this, bpfunc,
149                                        pointsToUse.first, pointsToUse.second,
150                                        pointType, lladdrSpace);
151    mod->instp_map[ip] = pt;
152
153    return pt;
154 }
155
156 BPatch_variableExpr *BPatch_addressSpace::findOrCreateVariable(int_variable *v,
157                                                                BPatch_type *type)
158 {
159    BPatch_module *mod = image->findOrCreateModule(v->mod());
160    assert(mod);
161    if (mod->var_map.count(v))
162       return mod->var_map[v];
163
164    if (!type) {
165       SymtabAPI::Type *stype = v->ivar()->svar()->getType();
166
167       if (stype){
168          type = BPatch_type::findOrCreateType(stype);
169       }else{
170          type = BPatch::bpatch->type_Untyped;
171       }
172    }
173
174    BPatch_variableExpr *var = BPatch_variableExpr::makeVariableExpr(this, v, type);
175    mod->var_map[v] = var;
176    return var;
177 }
178
179
180
181 BPatch_function *BPatch_addressSpace::createBPFuncCB(AddressSpace *a, Dyninst::PatchAPI::PatchFunction *f)
182 {
183    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
184    assert(aS);
185    return aS->findOrCreateBPFunc(f, NULL);
186 }
187
188 BPatch_point *BPatch_addressSpace::createBPPointCB(AddressSpace *a,
189                                                    Dyninst::PatchAPI::PatchFunction *pf,
190                                                    Dyninst::PatchAPI::Point *p, int type)
191 {
192    func_instance *fi = static_cast<func_instance *>(pf);
193    instPoint *ip  = static_cast<instPoint *>(p);
194    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
195    assert(aS);
196
197    BPatch_module *bpmod = aS->getImage()->findOrCreateModule(fi->mod());
198    assert(bpmod);
199
200    BPatch_function *func = aS->findOrCreateBPFunc(fi, bpmod);
201    assert(func);
202
203    return aS->findOrCreateBPPoint(func, ip, (BPatch_procedureLocation) type);
204 }
205
206
207
208 /***************************************************************************
209  * Bpatch_snippetHandle
210  ***************************************************************************/
211
212 /*
213  * BPatchSnippetHandle::BPatchSnippetHandle
214  *
215  * Constructor for BPatchSnippetHandle.  Delete the snippet instance(s)
216  * associated with the BPatchSnippetHandle.
217  */
218 BPatchSnippetHandle::BPatchSnippetHandle(BPatch_addressSpace * addSpace) :
219    addSpace_(addSpace)
220 {
221 }
222
223 /*
224  * BPatchSnippetHandle::~BPatchSnippetHandle
225  *
226  * Destructor for BPatchSnippetHandle.  Delete the snippet instance(s)
227  * associated with the BPatchSnippetHandle.
228  */
229 BPatchSnippetHandle::~BPatchSnippetHandle()
230 {
231    // don't delete inst instances since they are might have been copied
232 }
233
234 BPatch_addressSpace *BPatchSnippetHandle::getAddressSpace()
235 {
236    return addSpace_;
237 }
238
239 BPatch_process *BPatchSnippetHandle::getProcess()
240 {
241    return dynamic_cast<BPatch_process *>(addSpace_);
242 }
243
244 BPatch_Vector<BPatch_thread *> &BPatchSnippetHandle::getCatchupThreads()
245 {
246    return catchup_threads;
247 }
248
249 // Return true if any sub-minitramp uses a trap? Other option
250 // is "if all"...
251 bool BPatchSnippetHandle::usesTrap() {
252     return false;
253 }
254
255 BPatch_function * BPatchSnippetHandle::getFunc()
256 {
257     if (!instances_.empty()) {
258        Dyninst::PatchAPI::PatchFunction *func = instances_.back()->point()->func();
259        BPatch_function *bpfunc = addSpace_->findOrCreateBPFunc(func,NULL);
260        return bpfunc;
261     }
262     return NULL;
263 }
264
265
266 BPatch_image * BPatch_addressSpace::getImage()
267 {
268    return image;
269 }
270
271
272 /*
273  * BPatch_addressSpace::deleteSnippet
274  *
275  * Deletes an instance of a snippet.
276  *
277  * handle       The handle returned by insertSnippet when the instance to
278  *              deleted was created.
279  */
280
281 bool BPatch_addressSpace::deleteSnippet(BPatchSnippetHandle *handle)
282 {
283    if (getTerminated()) return true;
284
285    if (handle == NULL) {
286        bperr("Request to delete NULL snippet handle, returning false\n");
287        return false;
288    }
289
290    if (handle->addSpace_ != this) {
291      bperr("Error: wrong address space in deleteSnippet\n");
292      return false;
293    }
294
295    mal_printf("deleting snippet handle from func at %lx, point at %lx of type %d\n",
296               (Address)handle->getFunc()->getBaseAddr(), 
297               handle->instances_.empty() ? 0 : handle->instances_[0]->point()->addr(),
298               handle->instances_.empty() ? -1 : handle->instances_[0]->point()->type());
299
300    // if this is a process, check to see if the instrumentation is
301    // executing on the call stack
302    instPoint *ip = static_cast<instPoint *>(handle->instances_[0]->point());
303
304    if ( handle->getProcess() && handle->instances_.size() > 0 &&
305        BPatch_normalMode !=
306         ip->func()->obj()->hybridMode())
307    {
308        if (handle->instances_.size() > 1) {
309            mal_printf("ERROR: Removing snippet that is installed in "
310                           "multiple miniTramps %s[%d]\n",FILE__,__LINE__);
311      }
312    }
313
314    // uninstrument and remove snippet handle from point datastructures
315    for (unsigned int i=0; i < handle->instances_.size(); i++)
316      {
317         uninstrument(handle->instances_[i]);
318         Dyninst::PatchAPI::Point *iPoint = handle->instances_[i]->point();
319         BPatch_point *bPoint = findOrCreateBPPoint(NULL, iPoint,
320                                                    BPatch_point::convertInstPointType_t(iPoint->type()));
321         assert(bPoint);
322         bPoint->removeSnippet(handle);
323      }
324
325    handle->instances_.clear();
326
327    if (pendingInsertions == NULL) {
328      // Trigger it now
329      bool tmp;
330      finalizeInsertionSet(false, &tmp);
331    }
332
333    //delete handle;
334    return true;
335 }
336
337 /*
338  * BPatch_addressSpace::replaceCode
339  *
340  * Replace a given instruction with a BPatch_snippet.
341  *
342  * point       Represents the instruction to be replaced
343  * snippet     The replacing snippet
344  */
345
346 bool BPatch_addressSpace::replaceCode(BPatch_point * /*point*/,
347                                          BPatch_snippet * /*snippet*/)
348 {
349    // Need to reevaluate how this code works. I don't think it should be
350    // point-based, though.
351
352    assert(0);
353    return false;
354 }
355
356 /*
357  * BPatch_addressSpace::replaceFunctionCall
358  *
359  * Replace a function call with a call to a different function.  Returns true
360  * upon success, false upon failure.
361  *
362  * point        The call site that is to be changed.
363  * newFunc      The function that the call site will now call.
364  */
365 bool BPatch_addressSpace::replaceFunctionCall(BPatch_point &point,
366       BPatch_function &newFunc)
367 {
368    char name[1024];
369    newFunc.getName(name, 1024);
370
371    // Can't make changes to code when mutations are not active.
372    if (!getMutationsActive())
373       return false;
374
375    assert(point.point && newFunc.lowlevel_func());
376
377   /* PatchAPI stuffs */
378    AddressSpace* addr_space = point.getAS();
379    DynModifyCallCommand* rep_call = DynModifyCallCommand::create(addr_space,
380       point.point->block(), newFunc.lowlevel_func(), point.point->func());
381   addr_space->patcher()->add(rep_call);
382   /* End of PatchAPI */
383
384    if (pendingInsertions == NULL) {
385      // Trigger it now
386      bool tmp;
387      finalizeInsertionSet(false, &tmp);
388    }
389    return true;
390 }
391
392 /*
393  * BPatch_addressSpace::removeFunctionCall
394  *
395  * Replace a function call with a NOOP.  Returns true upon success, false upon
396  * failure.
397  *
398  * point        The call site that is to be NOOPed out.
399  */
400 bool BPatch_addressSpace::removeFunctionCall(BPatch_point &point)
401 {
402    // Can't make changes to code when mutations are not active.
403    if (!getMutationsActive())
404       return false;
405
406    assert(point.point);
407
408   /* PatchAPI stuffs */
409    AddressSpace* addr_space = point.getAS();
410    DynRemoveCallCommand* remove_call = DynRemoveCallCommand::create(addr_space,
411       point.point->block(), point.point->func());
412   addr_space->patcher()->add(remove_call);
413   /* End of PatchAPI */
414
415    if (pendingInsertions == NULL) {
416      // Trigger it now
417      bool tmp;
418      finalizeInsertionSet(false, &tmp);
419    }
420
421    return true;
422 }
423
424
425 /*
426  * BPatch_addressSpace::replaceFunction
427  *
428  * Replace all calls to function OLDFUNC with calls to NEWFUNC.
429  * Returns true upon success, false upon failure.
430  *
431  * oldFunc      The function to replace
432  * newFunc      The replacement function
433  */
434 bool BPatch_addressSpace::replaceFunction(BPatch_function &oldFunc,
435       BPatch_function &newFunc)
436 {
437   assert(oldFunc.lowlevel_func() && newFunc.lowlevel_func());
438   if (!getMutationsActive())
439     return false;
440
441   // Self replacement is a nop
442   // We should just test direct equivalence here...
443   if (oldFunc.lowlevel_func() == newFunc.lowlevel_func()) {
444     return true;
445   }
446
447   /* PatchAPI stuffs */
448   AddressSpace* addr_space = oldFunc.lowlevel_func()->proc();
449   DynReplaceFuncCommand* rep_func = DynReplaceFuncCommand::create(addr_space,
450      oldFunc.lowlevel_func(), newFunc.lowlevel_func());
451   addr_space->patcher()->add(rep_func);
452   /* End of PatchAPI */
453
454   if (pendingInsertions == NULL) {
455     // Trigger it now
456     bool tmp;
457     finalizeInsertionSet(false, &tmp);
458   }
459   return true;
460 }
461
462 /*
463  * BPatch_addressSpace::revertReplaceFunction
464  *
465  * Undoes a replaceFunction operation
466  */
467 bool BPatch_addressSpace::revertReplaceFunction(BPatch_function &oldFunc)
468 {
469   assert(oldFunc.lowlevel_func());
470   if (!getMutationsActive())
471     return false;
472
473   func_instance *func = oldFunc.lowlevel_func();
474
475   func->proc()->revertReplacedFunction(func);
476
477   if (pendingInsertions == NULL) {
478     // Trigger it now
479     bool tmp;
480     finalizeInsertionSet(false, &tmp);
481   }
482   return true;
483 }
484
485 bool BPatch_addressSpace::wrapFunction(BPatch_function *original,
486                                           BPatch_function *wrapper,
487                                           Dyninst::SymtabAPI::Symbol *clone)
488 {
489    assert(original->lowlevel_func() && wrapper->lowlevel_func());
490    if (!getMutationsActive())
491       return false;
492
493    // Self replacement is a nop
494    // We should just test direct equivalence here...
495    if (original->lowlevel_func() == wrapper->lowlevel_func()) {
496       return true;
497    }
498
499    if (!original->lowlevel_func()->proc()->wrapFunction(original->lowlevel_func(), 
500                                                       wrapper->lowlevel_func(),
501                                                       clone))
502       return false;
503
504    if (pendingInsertions == NULL) {
505       // Trigger it now
506       bool tmp;
507       finalizeInsertionSet(false, &tmp);
508    }
509    return true;
510 }
511
512 bool BPatch_addressSpace::revertWrapFunction(BPatch_function *original)
513 {
514    assert(original->lowlevel_func());
515
516    func_instance *func = original->lowlevel_func();
517    assert(func);
518
519    func->proc()->revertWrapFunction(func);
520    
521    if (pendingInsertions == NULL) {
522       // Trigger it now
523       bool tmp;
524       finalizeInsertionSet(false, &tmp);
525    }
526    return true;
527 }
528
529
530 bool BPatch_addressSpace::getAddressRanges( const char * fileName,
531       unsigned int lineNo,
532       std::vector< std::pair< unsigned long, unsigned long > > & ranges )
533 {
534    unsigned int originalSize = ranges.size();
535    BPatch_Vector< BPatch_module * > * modules = image->getModules();
536
537    /* Iteratate over the modules, looking for addr in each. */
538    for ( unsigned int i = 0; i < modules->size(); i++ ) {
539       BPatch_module *m = (*modules)[i];
540       m->getAddressRanges(fileName, lineNo, ranges);
541    }
542
543    if ( ranges.size() != originalSize ) { return true; }
544
545    return false;
546 } /* end getAddressRanges() */
547
548 bool BPatch_addressSpace::getSourceLines( unsigned long addr,
549       BPatch_Vector< BPatch_statement > & lines )
550 {
551    return image->getSourceLines(addr, lines);
552 } /* end getLineAndFile() */
553
554
555 /*
556  * BPatch_process::malloc
557  *
558  * Allocate memory in the thread's address space.
559  *
560  * n    The number of bytes to allocate.
561  *
562  * Returns:
563  *      A pointer to a BPatch_variableExpr representing the memory.
564  *
565  * If otherwise unspecified when binary rewriting, then the allocation
566  * happens in the original object.
567  */
568
569 BPatch_variableExpr *BPatch_addressSpace::malloc(int n, std::string name)
570 {
571    std::vector<AddressSpace *> as;
572    assert(BPatch::bpatch != NULL);
573    getAS(as);
574    assert(as.size());
575    void *ptr = (void *) as[0]->inferiorMalloc(n, dataHeap);
576    if (!ptr) return NULL;
577    if(name.empty()){
578       std::stringstream namestr;
579       namestr << "dyn_malloc_0x" << std::hex << ptr << "_" << n << "_bytes";
580       name = namestr.str();
581    }
582    BPatch_type *type = BPatch::bpatch->createScalar(name.c_str(), n);
583
584    return BPatch_variableExpr::makeVariableExpr(this, as[0], name, ptr,
585                                                 type);
586 }
587
588
589 /*
590  * BPatch_process::malloc
591  *
592  * Allocate memory in the thread's address space for a variable of the given
593  * type.
594  *
595  * type         The type of variable for which to allocate space.
596  *
597  * Returns:
598  *      A pointer to a BPatch_variableExpr representing the memory.
599  *
600  * XXX Should return NULL on failure, but the function which it calls,
601  *     inferiorMalloc, calls exit rather than returning an error, so this
602  *     is not currently possible.
603  */
604
605 BPatch_variableExpr *BPatch_addressSpace::malloc(const BPatch_type &type, std::string name)
606 {
607    std::vector<AddressSpace *> as;
608    assert(BPatch::bpatch != NULL);
609    getAS(as);
610    assert(as.size());
611    BPatch_type &t = const_cast<BPatch_type &>(type);
612    void *mem = (void *) as[0]->inferiorMalloc(t.getSize(), dataHeap);
613    if (!mem) return NULL;
614    if(name.empty()){
615       std::stringstream namestr;
616       namestr << "dyn_malloc_0x" << std::hex << mem << "_" << type.getName();
617       name = namestr.str();
618    }
619    BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, &t);
620    return varExpr;
621 }
622
623 /*
624  * BPatch_process::free
625  *
626  * Free memory that was allocated with BPatch_process::malloc.
627  *
628  * ptr          A BPatch_variableExpr representing the memory to free.
629  */
630
631 bool BPatch_addressSpace::free(BPatch_variableExpr &ptr)
632 {
633   if(ptr.intvar)
634   {
635     // kill the symbols
636
637   }
638
639    ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr());
640    return true;
641 }
642
643 BPatch_variableExpr *BPatch_addressSpace::createVariable(std::string name,
644                                                             Dyninst::Address addr,
645                                                             BPatch_type *type) {
646     assert(BPatch::bpatch != NULL);
647     std::vector<AddressSpace *> as;
648     getAS(as);
649     assert(as.size());
650
651 //dynC added feature
652     if(strstr(name.c_str(), "dynC") == name.c_str()){
653        void *mem = (void *) as[0]->inferiorMalloc(type->getSize(), dataHeap);
654        if (!mem) return NULL;
655        BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, type);
656        BPatch_module *mod = image->findOrCreateModule(varExpr->intvar->mod());
657        assert(mod);
658        mod->var_map[varExpr->intvar] = varExpr;
659        return varExpr;
660     }
661
662     BPatch_variableExpr *varExpr = BPatch_variableExpr::makeVariableExpr(this,
663                                                  as[0],
664                                                  name,
665                                                  (void *)addr,
666                                                  type);
667
668     return varExpr;
669 }
670
671 /*
672  * BPatch_addressSpace::findFunctionByAddr
673  *
674  * Returns the function that contains the specified address, or NULL if the
675  * address is not within a function.
676  *
677  * addr         The address to use for the lookup.
678  */
679 BPatch_function *BPatch_addressSpace::findFunctionByAddr(void *addr)
680 {
681    std::vector<AddressSpace *> as;
682
683    getAS(as);
684    assert(as.size());
685    std::set<func_instance *> funcs;
686    if (!as[0]->findFuncsByAddr((Address) addr, funcs)) {
687       // if it's a mapped_object that has yet to be analyzed,
688       // trigger analysis and re-invoke this function
689        mapped_object *obj = as[0]->findObject((Address) addr);
690        if (obj &&
691            !obj->isAnalyzed()) {
692          obj->analyze();
693          return findFunctionByAddr(addr);
694       }
695       return NULL;
696    }
697    if (funcs.empty()) return NULL;
698
699    if (funcs.size() > 1) {
700        bpwarn("Warning: deprecated function findFunctionByAddr found "
701               "multiple functions sharing address 0x%lx, picking one at "
702               "random.  Use findFunctionByEntry or findFunctionsByAddr\n",
703               addr);
704    }
705
706    return findOrCreateBPFunc((*(funcs.begin())), NULL);
707 }
708
709 /*
710  *  BPatch_addressSpace::findFunctionByEntry
711  *
712  *  Returns the function starting at the given address, or NULL if the
713  *  address is not within a function.
714  *
715  *  entry       The address to use for the lookup.
716  */
717 BPatch_function *BPatch_addressSpace::findFunctionByEntry(Address entry)
718 {
719     vector<BPatch_function*> funcs;
720     findFunctionsByAddr(entry, funcs);
721     vector<BPatch_function*>::iterator fit;
722     for (fit = funcs.begin(); fit != funcs.end(); fit++) {
723         if (entry == (Address)(*fit)->getBaseAddr()) {
724             return *fit;
725         }
726     }
727     return NULL;
728 }
729
730 bool BPatch_addressSpace::findFuncsByRange(Address startAddr,
731                                            Address endAddr,
732                                            std::set<BPatch_function*> &bpFuncs)
733 {
734     std::vector<AddressSpace *> as;
735     getAS(as);
736     assert(as.size());
737
738     // find the first code range in the region
739     mapped_object* mobj = as[0]->findObject(startAddr);
740     assert(mobj);
741     set<func_instance*> intFuncs;
742     mobj->findFuncsByRange(startAddr,endAddr,intFuncs);
743     set<func_instance*>::iterator fIter = intFuncs.begin();
744     for (; fIter != intFuncs.end(); fIter++) {
745         BPatch_function * bpfunc = findOrCreateBPFunc(*fIter,NULL);
746         bpFuncs.insert(bpfunc);
747     }
748     return 0 != bpFuncs.size();
749 }
750
751
752 /*
753  * BPatch_addressSpace::findFunctionsByAddr
754  *
755  * Returns the functions that contain the specified address, or NULL if the
756  * address is not within a function. (there could be multiple functions
757  * because of the possibility of shared code)
758  *
759  * addr         The address to use for the lookup.
760  * returns false if there were no functions that matched the address
761  */
762 bool BPatch_addressSpace::findFunctionsByAddr(Address addr, std::vector<BPatch_function*> &funcs)
763 {
764     std::vector<AddressSpace *> as;
765     getAS(as);
766     assert(as.size());
767
768     // grab the funcs, return false if there aren't any
769     std::set<func_instance*> intfuncs;
770     if (!as[0]->findFuncsByAddr( addr, intfuncs )) {
771         return false;
772     }
773     // convert to BPatch_functions
774     for (std::set<func_instance *>::iterator fiter=intfuncs.begin();
775          fiter != intfuncs.end(); fiter++)
776     {
777         funcs.push_back(findOrCreateBPFunc(*fiter, NULL));
778     }
779     return 0 < funcs.size();
780 }
781
782
783 /*
784  * BPatch_addressSpace::findModuleByAddr
785  *
786  * Returns the module that contains the specified address, or NULL if the
787  * address is not within a module.  Does NOT trigger parsing
788  *
789  * addr         The address to use for the lookup.
790  */
791 BPatch_module *BPatch_addressSpace::findModuleByAddr(Address addr)
792 {
793    std::vector<AddressSpace *> as;
794    getAS(as);
795    assert(as.size());
796
797    mapped_object *obj = as[0]->findObject(addr);
798    if ( ! obj )
799        return NULL;
800
801    const pdvector<mapped_module*> mods = obj->getModules();
802    if (mods.size()) {
803        return getImage()->findOrCreateModule(mods[0]);
804    }
805    return NULL;
806 }
807
808
809 /*
810  * BPatch_addressSpace::insertSnippet
811  *
812  * Insert a code snippet at a given instrumentation point.  Upon success,
813  * returns a handle to the created instance of the snippet, which can be used
814  * to delete it.  Otherwise returns NULL.
815  *
816  * expr         The snippet to insert.
817  * point        The point at which to insert it.
818  */
819
820 BPatchSnippetHandle *BPatch_addressSpace::insertSnippet(const BPatch_snippet &expr,
821       BPatch_point &point,
822       BPatch_snippetOrder order)
823 {
824    BPatch_callWhen when;
825    if (point.getPointType() == BPatch_exit)
826       when = BPatch_callAfter;
827    else
828       when = BPatch_callBefore;
829
830    return insertSnippet(expr, point, when, order);
831 }
832
833 /*
834  * BPatch_addressSpace::insertSnippet
835  *
836  * Insert a code snippet at a given instrumentation point.  Upon succes,
837  * returns a handle to the created instance of the snippet, which can be used
838  * to delete it.  Otherwise returns NULL.
839  *
840  * expr         The snippet to insert.
841  * point        The point at which to insert it.
842  */
843
844 // This handles conversion without requiring inst.h in a header file...
845 extern bool BPatchToInternalArgs(BPatch_point *point,
846       BPatch_callWhen when,
847       BPatch_snippetOrder order,
848       callWhen &ipWhen,
849       callOrder &ipOrder);
850
851
852 BPatchSnippetHandle *BPatch_addressSpace::insertSnippet(const BPatch_snippet &expr,
853       BPatch_point &point,
854       BPatch_callWhen when,
855       BPatch_snippetOrder order)
856 {
857    BPatch_Vector<BPatch_point *> points;
858    points.push_back(&point);
859    return insertSnippet(expr,
860          points,
861          when,
862          order);
863 }
864
865 extern int dyn_debug_ast;
866
867 /*
868  * BPatch_addressSpace::insertSnippet
869  *
870  * Insert a code snippet at each of a list of instrumentation points.  Upon
871  * success, Returns a handle to the created instances of the snippet, which
872  * can be used to delete them (as a unit).  Otherwise returns NULL.
873  *
874  * expr         The snippet to insert.
875  * points       The list of points at which to insert it.
876  */
877
878 // A lot duplicated from the single-point version. This is unfortunate.
879 BPatchSnippetHandle *BPatch_addressSpace::insertSnippet(const BPatch_snippet &expr,
880                                                                     const BPatch_Vector<BPatch_point *> &points,
881                                                                     BPatch_callWhen when,
882                                                                     BPatch_snippetOrder order)
883 {
884   BPatchSnippetHandle *retHandle = new BPatchSnippetHandle(this);
885
886   if (dyn_debug_inst) {
887       BPatch_function *f;
888       for (unsigned i=0; i<points.size(); i++) {
889          f = points[i]->getFunction();
890          const char *sname = f->func->prettyName().c_str();
891          inst_printf("[%s:%u] - %d. Insert instrumentation at function %s, "
892                "address %p, when %d, order %d\n",
893                FILE__, __LINE__, i,
894                sname, points[i]->getAddress(), (int) when, (int) order);
895
896       }
897   }
898
899   if (BPatch::bpatch->isTypeChecked()) {
900       if (expr.ast_wrapper->checkType() == BPatch::bpatch->type_Error) {
901         fprintf(stderr, "[%s:%u] - Type error inserting instrumentation\n",
902                 FILE__, __LINE__);
903         //expr.ast_wrapper->debugPrint();
904          return NULL;
905       }
906    }
907
908    if (!points.size()) {
909       inst_printf("%s[%d]:  request to insert snippet at zero points!\n", FILE__, __LINE__);
910       return NULL;
911    }
912
913    for (unsigned i = 0; i < points.size(); i++) {
914       BPatch_point *bppoint = points[i];
915
916       if (bppoint->addSpace == NULL) {
917          fprintf(stderr, "Error: attempt to use point with no process info\n");
918          continue;
919       }
920
921       if (dynamic_cast<BPatch_addressSpace *>(bppoint->addSpace) != this) {
922          fprintf(stderr, "Error: attempt to use point specific to a different process\n");
923          continue;
924       }
925
926       callWhen ipWhen;
927       callOrder ipOrder;
928
929       if (!BPatchToInternalArgs(bppoint, when, order, ipWhen, ipOrder)) {
930         fprintf(stderr, "[%s:%u] - BPatchToInternalArgs failed for point %d\n",
931                FILE__, __LINE__, i);
932          return retHandle;
933       }
934       if(!expr.checkTypesAtPoint(bppoint)) 
935       {
936         continue;
937       }
938
939       /* PatchAPI stuffs */
940       instPoint *ipoint = static_cast<instPoint *>(bppoint->getPoint(when));
941       Dyninst::PatchAPI::InstancePtr instance = (ipOrder == orderFirstAtPoint) ?
942          ipoint->pushFront(expr.ast_wrapper) :
943          ipoint->pushBack(expr.ast_wrapper);
944       /* End of PatchAPI stuffs */
945       if (instance) {
946          if (BPatch::bpatch->isTrampRecursive()) {
947             instance->disableRecursiveGuard();
948          }
949          retHandle->addInstance(instance);
950          bppoint->recordSnippet(when, order, retHandle);
951       }
952    }
953    if (pendingInsertions == NULL) {
954      // There's no insertion set, instrument now
955      bool tmp;
956      if (!finalizeInsertionSet(false, &tmp)) {
957         return NULL;
958      }
959    }   
960    // If we inserted nothing successfully, NULL
961    if(retHandle->isEmpty()) return NULL;
962    
963    return retHandle;
964 }
965
966
967 /*
968  * BPatch_addressSpace::insertSnippet
969  *
970  * Insert a code snippet at each of a list of instrumentation points.  Upon
971  * success, Returns a handle to the created instances of the snippet, which
972  * can be used to delete them (as a unit).  Otherwise returns NULL.
973  *
974  * expr         The snippet to insert.
975  * points       The list of points at which to insert it.
976  */
977
978 BPatchSnippetHandle *BPatch_addressSpace::insertSnippet(
979       const BPatch_snippet &expr,
980       const BPatch_Vector<BPatch_point *> &points,
981       BPatch_snippetOrder order)
982 {
983    return insertSnippet(expr,
984          points,
985          BPatch_callUnset,
986          order);
987 }
988
989 /*
990  * BPatch_addressSpace::isStaticExecutable
991  *
992  * Returns true if the underlying image represents a statically-linked executable, false otherwise.
993  */
994 bool BPatch_addressSpace::isStaticExecutable() {
995    std::vector<AddressSpace *> as;
996    getAS(as);
997
998    if( !as.size() ) return false;
999
1000    AddressSpace *aout = as[0];
1001    return aout->getAOut()->isStaticExec();
1002 }
1003
1004 #include "registerSpace.h"
1005
1006 #if defined(cap_registers)
1007 bool BPatch_addressSpace::getRegisters(std::vector<BPatch_register> &regs) {
1008    if (registers_.size()) {
1009        regs = registers_;
1010        return true;
1011    }
1012
1013    std::vector<AddressSpace *> as;
1014
1015    getAS(as);
1016    assert(as.size());
1017
1018    registerSpace *rs = registerSpace::getRegisterSpace(as[0]);
1019
1020    for (unsigned i = 0; i < rs->realRegs().size(); i++) {
1021        // Let's do just GPRs for now
1022        registerSlot *regslot = rs->realRegs()[i];
1023        registers_.push_back(BPatch_register(regslot->name, regslot->number));
1024    }
1025
1026 // Temporary override: also return EFLAGS though it's certainly not a 
1027 #if defined(arch_x86) || defined(arch_x86_64)
1028    for (unsigned i = 0; i < rs->SPRs().size(); ++i) {
1029       if (rs->SPRs()[i]->name == "eflags") {
1030          registers_.push_back(BPatch_register(rs->SPRs()[i]->name, 
1031                                               rs->SPRs()[i]->number));
1032       }
1033    }
1034 #endif
1035
1036    regs = registers_;
1037    return true;
1038 }
1039 #else
1040 bool BPatch_addressSpace::getRegisters(std::vector<BPatch_register> &) {
1041     // Empty vector since we're not supporting register objects on
1042     // these platforms (yet)
1043    return false;
1044 }
1045 #endif
1046
1047 #if defined(cap_registers)
1048 bool BPatch_addressSpace::createRegister_NP(std::string regName,
1049                                                BPatch_register &reg) {
1050     // Build the register list.
1051     std::vector<BPatch_register> dontcare;
1052     getRegisters(dontcare);
1053
1054     for (unsigned i = 0; i < registers_.size(); i++) {
1055         if (registers_[i].name() == regName) {
1056             reg = registers_[i];
1057             return true;
1058         }
1059     }
1060     return false;
1061 }
1062 #else
1063 bool BPatch_addressSpace::createRegister_NP(std::string,
1064                                                BPatch_register &)
1065 {
1066    return false;
1067 }
1068 #endif
1069
1070 void BPatch_addressSpace::allowTraps(bool allowtraps)
1071 {
1072    std::vector<AddressSpace *> as;
1073    getAS(as);
1074
1075    for (std::vector<AddressSpace *>::iterator i = as.begin(); i != as.end(); i++)
1076    {
1077       (*i)->setUseTraps(allowtraps);
1078    }
1079 }
1080
1081 BPatch_variableExpr *BPatch_addressSpace::createVariable(
1082                         Dyninst::Address at_addr,
1083                         BPatch_type *type, std::string var_name,
1084                         BPatch_module *in_module)
1085 {
1086    BPatch_binaryEdit *binEdit = dynamic_cast<BPatch_binaryEdit *>(this);
1087    if (binEdit && !in_module) {
1088       //Address alone isn't unique when binary rewriting
1089       return NULL;
1090    }
1091    if (!type) {
1092       //Required for size information.
1093       return NULL;
1094    }
1095    AddressSpace *ll_addressSpace = NULL;
1096
1097    std::vector<AddressSpace *> as;
1098    getAS(as);
1099    if (binEdit) {
1100       std::vector<AddressSpace *>::iterator as_i;
1101       for (as_i = as.begin(); as_i != as.end(); as_i++)
1102       {
1103          BinaryEdit *b = dynamic_cast<BinaryEdit *>(*as_i);
1104          assert(b);
1105          if (in_module->mod->obj() == b->getMappedObject()) {
1106             ll_addressSpace = *as_i;
1107             break;
1108          }
1109       }
1110    }
1111    else {
1112       assert(as.size() == 1);
1113       ll_addressSpace = as[0];
1114    }
1115
1116    if (!ll_addressSpace) {
1117       //in_module doesn't belong to 'this'
1118       return NULL;
1119    }
1120
1121    if (!var_name.size()) {
1122       std::stringstream namestream;
1123       namestream << "dyninst_var_" << std::hex << at_addr;
1124       var_name = namestream.str();
1125    }
1126
1127    return BPatch_variableExpr::makeVariableExpr(this, ll_addressSpace, var_name,
1128                                                 (void *) at_addr, type);
1129 }
1130
1131 Dyninst::PatchAPI::PatchMgrPtr Dyninst::PatchAPI::convert(const BPatch_addressSpace *a) {
1132    const BPatch_binaryEdit *edit = dynamic_cast<const BPatch_binaryEdit *>(a);
1133    if (edit) {
1134       return edit->lowlevel_edit()->mgr();
1135    }
1136    else {
1137       const BPatch_process *proc = dynamic_cast<const BPatch_process *>(a);
1138       return proc->lowlevel_process()->mgr();
1139    }
1140 }
1141