2 * Copyright (c) 1996-2009 Barton P. Miller
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.
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.
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.
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.
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
35 #include "binaryEdit.h"
36 #include "EventHandler.h"
38 #include "signalgenerator.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"
48 #include "mapped_module.h"
50 #include "BPatch_libInfo.h"
51 #include "BPatch_asyncEventHandler.h"
53 #include "BPatch_thread.h"
54 #include "BPatch_function.h"
55 #include "callbacks.h"
57 #include "BPatch_private.h"
61 #include "BPatch_addressSpace.h"
63 #include "BPatch_instruction.h"
67 BPatch_addressSpace::BPatch_addressSpace() :
72 BPatch_addressSpace::~BPatch_addressSpace()
76 BPatch_function *BPatch_addressSpace::findOrCreateBPFunc(int_function* ifunc,
80 bpmod = image->findOrCreateModule(ifunc->mod());
82 if (bpmod->func_map.count(ifunc)) {
83 BPatch_function *bpf = bpmod->func_map[ifunc];
88 // Find the module that contains the function
89 if (bpmod == NULL && ifunc->mod() != NULL) {
90 bpmod = getImage()->findModule(ifunc->mod()->fileName().c_str());
93 // findModule has a tendency to make new function objects... so
94 // check the map again
95 if (bpmod->func_map.count(ifunc)) {
96 BPatch_function *bpf = bpmod->func_map[ifunc];
101 BPatch_function *ret = new BPatch_function(this, ifunc, bpmod);
102 assert( ret != NULL );
109 BPatch_point *BPatch_addressSpace::findOrCreateBPPoint(BPatch_function *bpfunc,
110 instPoint *ip, BPatch_procedureLocation pointType)
114 BPatch_module *mod = image->findOrCreateModule(ip->func()->mod());
117 if (mod->instp_map.count(ip))
118 return mod->instp_map[ip];
120 if (pointType == BPatch_locUnknownLocation)
123 AddressSpace *lladdrSpace = ip->func()->proc();
125 bpfunc = findOrCreateBPFunc(ip->func(), mod);
127 BPatch_point *pt = new BPatch_point(this, bpfunc, ip, pointType, lladdrSpace);
128 mod->instp_map[ip] = pt;
133 BPatch_variableExpr *BPatch_addressSpace::findOrCreateVariable(int_variable *v,
136 BPatch_module *mod = image->findOrCreateModule(v->mod());
138 if (mod->var_map.count(v))
139 return mod->var_map[v];
142 SymtabAPI::Type *stype = v->ivar()->svar()->getType();
144 type = BPatch_type::findOrCreateType(stype);
146 type = BPatch::bpatch->type_Untyped;
149 BPatch_variableExpr *var = BPatch_variableExpr::makeVariableExpr(this, v, type);
150 mod->var_map[v] = var;
156 BPatch_function *BPatch_addressSpace::createBPFuncCB(AddressSpace *a, int_function *f)
158 BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
160 return aS->findOrCreateBPFunc(f, NULL);
163 BPatch_point *BPatch_addressSpace::createBPPointCB(AddressSpace *a,
165 instPoint *ip, int type)
167 BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
170 BPatch_module *bpmod = aS->getImageInt()->findOrCreateModule(f->mod());
173 BPatch_function *func = aS->findOrCreateBPFunc(f, bpmod);
176 return aS->findOrCreateBPPoint(func, ip, (BPatch_procedureLocation) type);
181 /***************************************************************************
182 * Bpatch_snippetHandle
183 ***************************************************************************/
186 * BPatchSnippetHandle::BPatchSnippetHandle
188 * Constructor for BPatchSnippetHandle. Delete the snippet instance(s)
189 * associated with the BPatchSnippetHandle.
191 BPatchSnippetHandle::BPatchSnippetHandle(BPatch_addressSpace * addSpace) :
197 * BPatchSnippetHandle::~BPatchSnippetHandle
199 * Destructor for BPatchSnippetHandle. Delete the snippet instance(s)
200 * associated with the BPatchSnippetHandle.
202 void BPatchSnippetHandle::BPatchSnippetHandle_dtor()
204 // don't delete inst instances since they are might have been copied
207 BPatch_addressSpace *BPatchSnippetHandle::getAddressSpaceInt()
212 BPatch_process *BPatchSnippetHandle::getProcessInt()
214 return dynamic_cast<BPatch_process *>(addSpace_);
217 BPatch_Vector<BPatch_thread *> &BPatchSnippetHandle::getCatchupThreadsInt()
219 return catchup_threads;
223 BPatch_image * BPatch_addressSpace::getImageInt()
230 * BPatch_addressSpace::deleteSnippet
232 * Deletes an instance of a snippet.
234 * handle The handle returned by insertSnippet when the instance to
235 * deleted was created.
238 bool BPatch_addressSpace::deleteSnippetInt(BPatchSnippetHandle *handle)
240 if (getTerminated()) return true;
242 if (handle == NULL) {
243 bperr("Request to delete NULL snippet handle, returning false\n");
247 if (handle->addSpace_ == this) {
249 // if this is a process, check to see if the instrumentation is
250 // executing on the call stack
251 if ( handle->getProcess() ) {
252 handle->getProcess()->lowlevel_process()->updateActiveMultis();
253 if (handle->mtHandles_.size() > 1) {
254 mal_printf("ERROR: Removing snippet that is installed in "
255 "multiple miniTramps %s[%d]\n",FILE__,__LINE__);
259 // uninstrument and remove snippet handle from point datastructures
260 for (unsigned int i=0; i < handle->mtHandles_.size(); i++)
262 instPoint *iPoint = handle->mtHandles_[i]->instP();
263 handle->mtHandles_[i]->uninstrument();
264 BPatch_point *bPoint = findOrCreateBPPoint(NULL, iPoint);
266 bPoint->deleteSnippet(handle);
273 // Handle isn't to a snippet instance in this process
274 bperr("Error: wrong address space in deleteSnippet\n");
279 * BPatch_addressSpace::replaceCode
281 * Replace a given instruction with a BPatch_snippet.
283 * point Represents the instruction to be replaced
284 * snippet The replacing snippet
287 bool BPatch_addressSpace::replaceCodeInt(BPatch_point *point,
288 BPatch_snippet *snippet)
290 if (!getMutationsActive())
296 if (getTerminated()) {
305 return point->point->replaceCode(snippet->ast_wrapper);
311 * BPatch_addressSpace::replaceFunctionCall
313 * Replace a function call with a call to a different function. Returns true
314 * upon success, false upon failure.
316 * point The call site that is to be changed.
317 * newFunc The function that the call site will now call.
319 bool BPatch_addressSpace::replaceFunctionCallInt(BPatch_point &point,
320 BPatch_function &newFunc)
323 newFunc.getName(name, 1024);
325 // Can't make changes to code when mutations are not active.
326 if (!getMutationsActive())
329 assert(point.point && newFunc.lowlevel_func());
331 #if defined(arch_x86) || defined(arch_x86_64)
332 bool old_recursion_flag = BPatch::bpatch->isTrampRecursive();
333 BPatch::bpatch->setTrampRecursive( true );
335 BPatch_funcJumpExpr fjmp(newFunc, true);
336 insertSnippet(fjmp, point, BPatch_lastSnippet);
338 BPatch::bpatch->setTrampRecursive( old_recursion_flag );
341 return point.getAS()->replaceFunctionCall(point.point,
342 newFunc.lowlevel_func());
347 * BPatch_addressSpace::removeFunctionCall
349 * Replace a function call with a NOOP. Returns true upon success, false upon
352 * point The call site that is to be NOOPed out.
354 bool BPatch_addressSpace::removeFunctionCallInt(BPatch_point &point)
356 // Can't make changes to code when mutations are not active.
357 if (!getMutationsActive())
362 return point.getAS()->replaceFunctionCall(point.point, NULL);
367 * BPatch_addressSpace::replaceFunction
369 * Replace all calls to function OLDFUNC with calls to NEWFUNC.
370 * Returns true upon success, false upon failure.
372 * oldFunc The function to replace
373 * newFunc The replacement function
375 bool BPatch_addressSpace::replaceFunctionInt(BPatch_function &oldFunc,
376 BPatch_function &newFunc)
380 oldFunc.getName(oldname, 1024);
381 newFunc.getName(newname, 1024);
382 assert(oldFunc.lowlevel_func() && newFunc.lowlevel_func());
383 if (!getMutationsActive())
386 // Self replacement is a nop
387 // We should just test direct equivalence here...
388 if (oldFunc.lowlevel_func() == newFunc.lowlevel_func()) {
392 BPatch_Vector<BPatch_point *> *pts = oldFunc.findPoint(BPatch_entry);
394 if (! pts || ! pts->size()) {
398 BPatch_funcJumpExpr fje(newFunc);
399 //#if defined(cap_instruction_replacement) && defined(arch_power)
401 // Replace the first instruction with fje
402 for (unsigned i = 0; i < pts->size(); i++) {
403 BPatch_point *point = (*pts)[i];
404 point->getPoint()->replaceCode(fje.ast_wrapper);
410 bool old_recursion_flag = BPatch::bpatch->isTrampRecursive();
411 BPatch::bpatch->setTrampRecursive( true );
413 // We replace functions by instrumenting the entry of OLDFUNC with
414 // a non-linking jump to NEWFUNC. Calls to OLDFUNC do actually
415 // transfer to OLDFUNC, but then our jump shunts them to NEWFUNC.
416 // The non-linking jump ensures that when NEWFUNC returns, it
417 // returns directly to the caller of OLDFUNC.
420 BPatchSnippetHandle * result = insertSnippet(fje, *pts, BPatch_callBefore);
422 BPatch::bpatch->setTrampRecursive( old_recursion_flag );
424 return (NULL != result);
429 bool BPatch_addressSpace::getAddressRangesInt( const char * fileName,
431 std::vector< std::pair< unsigned long, unsigned long > > & ranges )
433 unsigned int originalSize = ranges.size();
434 BPatch_Vector< BPatch_module * > * modules = image->getModules();
436 /* Iteratate over the modules, looking for addr in each. */
437 for ( unsigned int i = 0; i < modules->size(); i++ ) {
438 BPatch_module *m = (*modules)[i];
439 m->getAddressRanges(fileName, lineNo, ranges);
442 if ( ranges.size() != originalSize ) { return true; }
445 } /* end getAddressRangesInt() */
447 bool BPatch_addressSpace::getSourceLinesInt( unsigned long addr,
448 BPatch_Vector< BPatch_statement > & lines )
450 return image->getSourceLinesInt(addr, lines);
451 } /* end getLineAndFile() */
455 * BPatch_process::malloc
457 * Allocate memory in the thread's address space.
459 * n The number of bytes to allocate.
462 * A pointer to a BPatch_variableExpr representing the memory.
464 * If otherwise unspecified when binary rewriting, then the allocation
465 * happens in the original object.
468 BPatch_variableExpr *BPatch_addressSpace::mallocInt(int n)
470 std::vector<AddressSpace *> as;
471 assert(BPatch::bpatch != NULL);
474 void *ptr = (void *) as[0]->inferiorMalloc(n, dataHeap);
475 if (!ptr) return NULL;
476 std::stringstream namestr;
477 namestr << "dyn_malloc_0x" << std::hex << ptr << "_" << n << "_bytes";
478 std::string name = namestr.str();
480 BPatch_type *type = BPatch::bpatch->createScalar(name.c_str(), n);
482 return BPatch_variableExpr::makeVariableExpr(this, as[0], name, ptr,
488 * BPatch_process::malloc
490 * Allocate memory in the thread's address space for a variable of the given
493 * type The type of variable for which to allocate space.
496 * A pointer to a BPatch_variableExpr representing the memory.
498 * XXX Should return NULL on failure, but the function which it calls,
499 * inferiorMalloc, calls exit rather than returning an error, so this
500 * is not currently possible.
503 BPatch_variableExpr *BPatch_addressSpace::mallocByType(const BPatch_type &type)
505 std::vector<AddressSpace *> as;
506 assert(BPatch::bpatch != NULL);
509 BPatch_type &t = const_cast<BPatch_type &>(type);
510 void *mem = (void *) as[0]->inferiorMalloc(t.getSize(), dataHeap);
511 if (!mem) return NULL;
512 std::stringstream namestr;
513 namestr << "dyn_malloc_0x" << std::hex << mem << "_" << type.getName();
514 std::string name = namestr.str();
515 return BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, &t);
520 * BPatch_process::free
522 * Free memory that was allocated with BPatch_process::malloc.
524 * ptr A BPatch_variableExpr representing the memory to free.
527 bool BPatch_addressSpace::freeInt(BPatch_variableExpr &ptr)
535 ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr());
539 BPatch_variableExpr *BPatch_addressSpace::createVariableInt(std::string name,
540 Dyninst::Address addr,
542 assert(BPatch::bpatch != NULL);
543 std::vector<AddressSpace *> as;
547 return BPatch_variableExpr::makeVariableExpr(this,
556 * BPatch_addressSpace::findFunctionByAddr
558 * Returns the function that contains the specified address, or NULL if the
559 * address is not within a function.
561 * addr The address to use for the lookup.
564 BPatch_function *BPatch_addressSpace::findFunctionByAddrInt(void *addr)
567 std::vector<AddressSpace *> as;
571 codeRange *range = as[0]->findOrigByAddr((Address) addr);
575 func = range->is_function();
578 // if it's a mapped_object that has yet to be analyzed,
579 // trigger analysis and re-invoke this function
580 if ( range->is_mapped_object() &&
581 ! ((mapped_object*)range)->isAnalyzed() ) {
582 ((mapped_object*)range)->analyze();
583 return findFunctionByAddrInt(addr);
588 return findOrCreateBPFunc(func, NULL);
591 bool BPatch_addressSpace::findFuncsByRange(Address startAddr,
593 std::set<BPatch_function*> &bpFuncs)
595 std::vector<AddressSpace *> as;
599 // find the first code range in the region
600 mapped_object* mobj = as[0]->findObject(startAddr);
602 set<int_function*> intFuncs;
603 mobj->findFuncsByRange(startAddr,endAddr,intFuncs);
604 set<int_function*>::iterator fIter = intFuncs.begin();
605 for (; fIter != intFuncs.end(); fIter++) {
606 BPatch_function * bpfunc = findOrCreateBPFunc(*fIter,NULL);
607 bpFuncs.insert(bpfunc);
609 return 0 != bpFuncs.size();
614 * BPatch_addressSpace::findFunctionsByAddr
616 * Returns the functions that contain the specified address, or NULL if the
617 * address is not within a function. (there could be multiple functions
618 * because of the possibility of shared code)
620 * addr The address to use for the lookup.
621 * returns false if there were no functions that matched the address
623 bool BPatch_addressSpace::findFunctionsByAddrInt
624 (Address addr, std::vector<BPatch_function*> &funcs)
626 std::vector<AddressSpace *> as;
630 // grab the funcs, return false if there aren't any
631 std::vector<int_function*> intfuncs;
632 if (!as[0]->findFuncsByAddr( addr, intfuncs )) {
635 // convert to BPatch_functions
636 for (std::vector<int_function*>::iterator fiter=intfuncs.begin();
637 fiter != intfuncs.end(); fiter++)
639 funcs.push_back(findOrCreateBPFunc(*fiter, NULL));
641 return 0 < funcs.size();
646 * BPatch_addressSpace::findModuleByAddr
648 * Returns the module that contains the specified address, or NULL if the
649 * address is not within a module. Does NOT trigger parsing
651 * addr The address to use for the lookup.
653 BPatch_module *BPatch_addressSpace::findModuleByAddr(Address addr)
655 std::vector<AddressSpace *> as;
659 mapped_object *obj = as[0]->findObject(addr);
663 const pdvector<mapped_module*> mods = obj->getModules();
665 return getImage()->findOrCreateModule(mods[0]);
672 * BPatch_addressSpace::insertSnippet
674 * Insert a code snippet at a given instrumentation point. Upon success,
675 * returns a handle to the created instance of the snippet, which can be used
676 * to delete it. Otherwise returns NULL.
678 * expr The snippet to insert.
679 * point The point at which to insert it.
682 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetInt(const BPatch_snippet &expr,
684 BPatch_snippetOrder order)
686 BPatch_callWhen when;
687 if (point.getPointType() == BPatch_exit)
688 when = BPatch_callAfter;
690 when = BPatch_callBefore;
692 return insertSnippetWhen(expr, point, when, order);
696 * BPatch_addressSpace::insertSnippet
698 * Insert a code snippet at a given instrumentation point. Upon succes,
699 * returns a handle to the created instance of the snippet, which can be used
700 * to delete it. Otherwise returns NULL.
702 * expr The snippet to insert.
703 * point The point at which to insert it.
706 // This handles conversion without requiring inst.h in a header file...
707 extern bool BPatchToInternalArgs(BPatch_point *point,
708 BPatch_callWhen when,
709 BPatch_snippetOrder order,
714 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetWhen(const BPatch_snippet &expr,
716 BPatch_callWhen when,
717 BPatch_snippetOrder order)
719 BPatch_Vector<BPatch_point *> points;
720 points.push_back(&point);
722 return insertSnippetAtPointsWhen(expr,
730 * BPatch_addressSpace::insertSnippet
732 * Insert a code snippet at each of a list of instrumentation points. Upon
733 * success, Returns a handle to the created instances of the snippet, which
734 * can be used to delete them (as a unit). Otherwise returns NULL.
736 * expr The snippet to insert.
737 * points The list of points at which to insert it.
740 // A lot duplicated from the single-point version. This is unfortunate.
741 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetAtPointsWhen(const BPatch_snippet &expr,
742 const BPatch_Vector<BPatch_point *> &points,
743 BPatch_callWhen when,
744 BPatch_snippetOrder order)
747 if (dyn_debug_inst) {
749 for (unsigned i=0; i<points.size(); i++) {
750 f = points[i]->getFunction();
751 const char *sname = f->func->prettyName().c_str();
752 inst_printf("[%s:%u] - %d. Insert instrumentation at function %s, "
753 "address %p, when %d, order %d\n",
755 sname, points[i]->getAddress(), (int) when, (int) order);
760 if (BPatch::bpatch->isTypeChecked()) {
761 if (expr.ast_wrapper->checkType() == BPatch::bpatch->type_Error) {
762 inst_printf("[%s:%u] - Type error inserting instrumentation\n",
764 expr.ast_wrapper->debugPrint();
769 if (!points.size()) {
770 inst_printf("%s[%d]: request to insert snippet at zero points!\n", FILE__, __LINE__);
775 batchInsertionRecord *rec = new batchInsertionRecord;
778 rec->trampRecursive_ = BPatch::bpatch->isTrampRecursive();
780 BPatchSnippetHandle *ret = new BPatchSnippetHandle(this);
783 for (unsigned i = 0; i < points.size(); i++) {
784 BPatch_point *point = points[i];
786 if (point->addSpace == NULL) {
787 fprintf(stderr, "Error: attempt to use point with no process info\n");
791 if (dynamic_cast<BPatch_addressSpace *>(point->addSpace) != this) {
792 fprintf(stderr, "Error: attempt to use point specific to a different process\n");
799 if (!BPatchToInternalArgs(point, when, order, ipWhen, ipOrder)) {
800 inst_printf("[%s:%u] - BPatchToInternalArgs failed for point %d\n",
801 FILE__, __LINE__, i);
805 rec->points_.push_back(point);
806 rec->when_.push_back(ipWhen);
807 rec->order_ = ipOrder;
809 point->recordSnippet(when, order, ret);
812 assert(rec->points_.size() == rec->when_.size());
814 // Okey dokey... now see if we just tack it on, or insert now.
815 if (pendingInsertions) {
816 pendingInsertions->push_back(rec);
819 BPatch_process *proc = dynamic_cast<BPatch_process *>(this);
821 proc->beginInsertionSetInt();
822 pendingInsertions->push_back(rec);
823 // All the insertion work was moved here...
824 proc->finalizeInsertionSetInt(false);
831 * BPatch_addressSpace::insertSnippet
833 * Insert a code snippet at each of a list of instrumentation points. Upon
834 * success, Returns a handle to the created instances of the snippet, which
835 * can be used to delete them (as a unit). Otherwise returns NULL.
837 * expr The snippet to insert.
838 * points The list of points at which to insert it.
841 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetAtPoints(
842 const BPatch_snippet &expr,
843 const BPatch_Vector<BPatch_point *> &points,
844 BPatch_snippetOrder order)
846 return insertSnippetAtPointsWhen(expr,
853 * BPatch_addressSpace::isStaticExecutable
855 * Returns true if the underlying image represents a statically-linked executable, false otherwise.
857 bool BPatch_addressSpace::isStaticExecutableInt() {
858 std::vector<AddressSpace *> as;
861 if( !as.size() ) return false;
863 AddressSpace *aout = as[0];
864 return aout->getAOut()->isStaticExec();
867 #include "registerSpace.h"
869 #if defined(cap_registers)
870 bool BPatch_addressSpace::getRegistersInt(std::vector<BPatch_register> ®s) {
871 if (registers_.size()) {
876 std::vector<AddressSpace *> as;
881 registerSpace *rs = registerSpace::getRegisterSpace(as[0]);
883 for (unsigned i = 0; i < rs->realRegs().size(); i++) {
884 // Let's do just GPRs for now
885 registerSlot *regslot = rs->realRegs()[i];
886 registers_.push_back(BPatch_register(regslot->name, regslot->number));
892 bool BPatch_addressSpace::getRegistersInt(std::vector<BPatch_register> &) {
893 // Empty vector since we're not supporting register objects on
894 // these platforms (yet)
899 #if defined(cap_registers)
900 bool BPatch_addressSpace::createRegister_NPInt(std::string regName,
901 BPatch_register ®) {
902 // Build the register list.
903 std::vector<BPatch_register> dontcare;
904 getRegisters(dontcare);
906 for (unsigned i = 0; i < registers_.size(); i++) {
907 if (registers_[i].name() == regName) {
915 bool BPatch_addressSpace::createRegister_NPInt(std::string,
922 bool BPatch_addressSpace::loadLibraryInt(const char * /*libname*/, bool /*reload*/)
927 void BPatch_addressSpace::allowTrapsInt(bool allowtraps)
929 std::vector<AddressSpace *> as;
932 for (std::vector<AddressSpace *>::iterator i = as.begin(); i != as.end(); i++)
934 (*i)->setUseTraps(allowtraps);
938 BPatch_variableExpr *BPatch_addressSpace::createVariableInt(
939 Dyninst::Address at_addr,
940 BPatch_type *type, std::string var_name,
941 BPatch_module *in_module)
943 BPatch_binaryEdit *binEdit = dynamic_cast<BPatch_binaryEdit *>(this);
944 if (binEdit && !in_module) {
945 //Address alone isn't unique when binary rewriting
949 //Required for size information.
952 AddressSpace *ll_addressSpace = NULL;
954 std::vector<AddressSpace *> as;
957 std::vector<AddressSpace *>::iterator as_i;
958 for (as_i = as.begin(); as_i != as.end(); as_i++)
960 BinaryEdit *b = dynamic_cast<BinaryEdit *>(*as_i);
962 if (in_module->mod->obj() == b->getMappedObject()) {
963 ll_addressSpace = *as_i;
969 assert(as.size() == 1);
970 ll_addressSpace = as[0];
973 if (!ll_addressSpace) {
974 //in_module doesn't belong to 'this'
978 if (!var_name.size()) {
979 std::stringstream namestream;
980 namestream << "dyninst_var_" << std::hex << at_addr;
981 var_name = namestream.str();
984 return BPatch_variableExpr::makeVariableExpr(this, ll_addressSpace, var_name,
985 (void *) at_addr, type);