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