Add new interface for creating variables
[dyninst.git] / dyninstAPI / src / BPatch_addressSpace.C
1 /*
2  * Copyright (c) 1996-2004 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #define BPATCH_FILE
43
44 #include "process.h"
45 #include "binaryEdit.h"
46 #include "EventHandler.h"
47 #include "mailbox.h"
48 #include "signalgenerator.h"
49 #include "inst.h"
50 #include "instP.h"
51 #include "instPoint.h"
52 #include "function.h" // int_function
53 #include "codeRange.h"
54 #include "dyn_thread.h"
55 #include "miniTramp.h"
56 #include "addressSpace.h"
57
58 #include "mapped_module.h"
59
60 #include "BPatch_libInfo.h"
61 #include "BPatch_asyncEventHandler.h"
62 #include "BPatch.h"
63 #include "BPatch_thread.h"
64 #include "BPatch_function.h"
65 #include "callbacks.h"
66
67 #include "BPatch_private.h"
68
69 #include "ast.h"
70
71 #include "BPatch_addressSpace.h"
72
73 #include "BPatch_instruction.h"
74
75 #include <sstream>
76
77 BPatch_addressSpace::BPatch_addressSpace() :
78    image(NULL)
79 {
80 }
81
82 BPatch_addressSpace::~BPatch_addressSpace()
83 {}
84
85
86 BPatch_function *BPatch_addressSpace::findOrCreateBPFunc(int_function* ifunc,
87                                                          BPatch_module *bpmod)
88 {
89    if (!bpmod)
90       bpmod = image->findOrCreateModule(ifunc->mod());
91    assert(bpmod);
92    if (bpmod->func_map.count(ifunc)) {
93       BPatch_function *bpf = bpmod->func_map[ifunc];
94       assert(bpf);
95       return bpf;
96    }
97
98    // Find the module that contains the function
99    if (bpmod == NULL && ifunc->mod() != NULL) {
100       bpmod = getImage()->findModule(ifunc->mod()->fileName().c_str());
101    }
102
103    // findModule has a tendency to make new function objects... so
104    // check the map again
105    if (bpmod->func_map.count(ifunc)) {
106       BPatch_function *bpf = bpmod->func_map[ifunc];
107       assert(bpf);
108       return bpf;
109    }
110
111    BPatch_function *ret = new BPatch_function(this, ifunc, bpmod);
112    assert( ret != NULL );
113    return ret;
114 }
115
116
117
118
119 BPatch_point *BPatch_addressSpace::findOrCreateBPPoint(BPatch_function *bpfunc,
120                               instPoint *ip, BPatch_procedureLocation pointType)
121 {
122    assert(ip);
123    
124    BPatch_module *mod = image->findOrCreateModule(ip->func()->mod());
125    assert(mod);
126    
127    if (mod->instp_map.count(ip)) 
128       return mod->instp_map[ip];
129
130    if (pointType == BPatch_locUnknownLocation)
131       return NULL;
132
133    AddressSpace *lladdrSpace = ip->func()->proc();
134    if (!bpfunc) 
135       bpfunc = findOrCreateBPFunc(ip->func(), mod);
136
137    BPatch_point *pt = new BPatch_point(this, bpfunc, ip, pointType, lladdrSpace);
138    mod->instp_map[ip] = pt;
139
140    return pt;
141 }
142
143 BPatch_variableExpr *BPatch_addressSpace::findOrCreateVariable(int_variable *v,
144                                                                BPatch_type *type)
145 {
146    BPatch_module *mod = image->findOrCreateModule(v->mod());
147    assert(mod);
148    if (mod->var_map.count(v))
149       return mod->var_map[v];
150
151    if (!type) {
152       SymtabAPI::Type *stype = v->ivar()->svar()->getType();
153       if (stype)
154          type = BPatch_type::findOrCreateType(stype);
155       else
156          type = BPatch::bpatch->type_Untyped;
157    }
158    
159    BPatch_variableExpr *var = BPatch_variableExpr::makeVariableExpr(this, v, type);
160    mod->var_map[v] = var;
161    return var;
162 }
163                                                                
164
165
166 BPatch_function *BPatch_addressSpace::createBPFuncCB(AddressSpace *a, int_function *f)
167 {
168    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
169    assert(aS);
170    return aS->findOrCreateBPFunc(f, NULL);
171 }
172
173 BPatch_point *BPatch_addressSpace::createBPPointCB(AddressSpace *a, 
174                                                    int_function *f, 
175                                                    instPoint *ip, int type)
176 {
177    BPatch_addressSpace *aS = (BPatch_addressSpace *)a->up_ptr();
178    assert(aS);
179
180    BPatch_module *bpmod = aS->getImageInt()->findOrCreateModule(f->mod());
181    assert(bpmod);
182
183    BPatch_function *func = aS->findOrCreateBPFunc(f, bpmod);
184    assert(func);
185    
186    return aS->findOrCreateBPPoint(func, ip, (BPatch_procedureLocation) type);
187 }
188
189
190
191 /***************************************************************************
192  * Bpatch_snippetHandle
193  ***************************************************************************/
194
195 /*
196  * BPatchSnippetHandle::BPatchSnippetHandle
197  *
198  * Constructor for BPatchSnippetHandle.  Delete the snippet instance(s)
199  * associated with the BPatchSnippetHandle.
200  */
201 BPatchSnippetHandle::BPatchSnippetHandle(BPatch_addressSpace * addSpace) :
202    addSpace_(addSpace)
203 {
204 }
205
206 /*
207  * BPatchSnippetHandle::~BPatchSnippetHandle
208  *
209  * Destructor for BPatchSnippetHandle.  Delete the snippet instance(s)
210  * associated with the BPatchSnippetHandle.
211  */
212 void BPatchSnippetHandle::BPatchSnippetHandle_dtor()
213 {
214    // don't delete inst instances since they are might have been copied
215 }
216
217 BPatch_addressSpace *BPatchSnippetHandle::getAddressSpaceInt()
218 {
219    return addSpace_;
220 }
221
222 BPatch_process *BPatchSnippetHandle::getProcessInt()
223 {
224    return dynamic_cast<BPatch_process *>(addSpace_);
225 }
226
227 BPatch_Vector<BPatch_thread *> &BPatchSnippetHandle::getCatchupThreadsInt()
228 {
229    return catchup_threads;
230 }
231
232
233 BPatch_image * BPatch_addressSpace::getImageInt()
234 {
235    return image;
236 }
237
238
239 /*
240  * BPatch_addressSpace::deleteSnippet
241  * 
242  * Deletes an instance of a snippet.
243  *
244  * handle       The handle returned by insertSnippet when the instance to
245  *              deleted was created.
246  */
247
248 bool BPatch_addressSpace::deleteSnippetInt(BPatchSnippetHandle *handle)
249 {   
250    if (getTerminated()) return true;
251
252    if (handle == NULL) {
253        bperr("Request to delete NULL snippet handle, returning false\n");
254        return false;
255    }
256
257    if (handle->addSpace_ == this) {  
258        for (unsigned int i=0; i < handle->mtHandles_.size(); i++)
259            handle->mtHandles_[i]->uninstrument();
260        delete handle;
261        return true;
262    } 
263    // Handle isn't to a snippet instance in this process
264    bperr("Error: wrong address space in deleteSnippet\n");
265    return false;
266 }
267
268 /*
269  * BPatch_addressSpace::replaceCode
270  *
271  * Replace a given instruction with a BPatch_snippet.
272  *
273  * point       Represents the instruction to be replaced
274  * snippet     The replacing snippet
275  */
276
277 bool BPatch_addressSpace::replaceCodeInt(BPatch_point *point,
278       BPatch_snippet *snippet) 
279 {
280    if (!getMutationsActive())
281       return false;
282
283    if (!point) {
284       return false;
285    }
286    if (getTerminated()) {
287       return true;
288    }
289
290    if (point->edge_) {
291       return false;
292    }
293
294
295    return point->point->replaceCode(snippet->ast_wrapper);
296 }
297
298
299
300 /*
301  * BPatch_addressSpace::replaceFunctionCall
302  *
303  * Replace a function call with a call to a different function.  Returns true
304  * upon success, false upon failure.
305  * 
306  * point        The call site that is to be changed.
307  * newFunc      The function that the call site will now call.
308  */
309 bool BPatch_addressSpace::replaceFunctionCallInt(BPatch_point &point,
310       BPatch_function &newFunc)
311 {
312    // Can't make changes to code when mutations are not active.
313    if (!getMutationsActive())
314       return false;
315
316    assert(point.point && newFunc.lowlevel_func());
317
318    return point.getAS()->replaceFunctionCall(point.point, 
319                                              newFunc.lowlevel_func());
320 }
321
322 /*
323  * BPatch_addressSpace::removeFunctionCall
324  *
325  * Replace a function call with a NOOP.  Returns true upon success, false upon
326  * failure.
327  * 
328  * point        The call site that is to be NOOPed out.
329  */
330 bool BPatch_addressSpace::removeFunctionCallInt(BPatch_point &point)
331 {
332    // Can't make changes to code when mutations are not active.
333    if (!getMutationsActive())
334       return false;   
335
336    assert(point.point);
337
338    return point.getAS()->replaceFunctionCall(point.point, NULL);
339 }
340
341
342 /*
343  * BPatch_addressSpace::replaceFunction
344  *
345  * Replace all calls to function OLDFUNC with calls to NEWFUNC.
346  * Returns true upon success, false upon failure.
347  * 
348  * oldFunc      The function to replace
349  * newFunc      The replacement function
350  */
351 bool BPatch_addressSpace::replaceFunctionInt(BPatch_function &oldFunc,
352       BPatch_function &newFunc)
353 {
354
355    assert(oldFunc.lowlevel_func() && newFunc.lowlevel_func());
356    if (!getMutationsActive())
357       return false;
358
359    // Self replacement is a nop
360    // We should just test direct equivalence here...
361    if (oldFunc.lowlevel_func() == newFunc.lowlevel_func()) {
362       return true;
363    }
364
365    BPatch_Vector<BPatch_point *> *pts = oldFunc.findPoint(BPatch_entry);
366
367    if (! pts || ! pts->size()) {
368       return false;
369    }
370
371    BPatch_funcJumpExpr fje(newFunc);
372
373 #if defined(cap_instruction_replacement) && defined(arch_power)
374    // Replace the first instruction with fje
375    for (unsigned i = 0; i < pts->size(); i++) {
376        BPatch_point *point = (*pts)[i];
377        point->getPoint()->replaceCode(fje.ast_wrapper);
378    }
379
380    return true;
381 #else
382
383    bool old_recursion_flag = BPatch::bpatch->isTrampRecursive();
384    BPatch::bpatch->setTrampRecursive( true );
385
386    // We replace functions by instrumenting the entry of OLDFUNC with
387    // a non-linking jump to NEWFUNC.  Calls to OLDFUNC do actually
388    // transfer to OLDFUNC, but then our jump shunts them to NEWFUNC.
389    // The non-linking jump ensures that when NEWFUNC returns, it
390    // returns directly to the caller of OLDFUNC.
391
392
393    BPatchSnippetHandle * result = insertSnippet(fje, *pts, BPatch_callBefore);
394
395    BPatch::bpatch->setTrampRecursive( old_recursion_flag );
396
397    return (NULL != result);
398 #endif
399 }
400
401
402 bool BPatch_addressSpace::getAddressRangesInt( const char * fileName, 
403       unsigned int lineNo, 
404       std::vector< std::pair< unsigned long, unsigned long > > & ranges ) 
405 {
406    unsigned int originalSize = ranges.size();
407    BPatch_Vector< BPatch_module * > * modules = image->getModules();
408
409    /* Iteratate over the modules, looking for addr in each. */
410    for ( unsigned int i = 0; i < modules->size(); i++ ) {
411       BPatch_module *m = (*modules)[i];
412       m->getAddressRanges(fileName, lineNo, ranges);
413    }
414
415    if ( ranges.size() != originalSize ) { return true; }
416
417    return false;
418 } /* end getAddressRangesInt() */
419
420 bool BPatch_addressSpace::getSourceLinesInt( unsigned long addr, 
421       BPatch_Vector< BPatch_statement > & lines ) 
422 {
423    return image->getSourceLinesInt(addr, lines);
424 } /* end getLineAndFile() */
425
426
427 /*
428  * BPatch_process::malloc
429  *
430  * Allocate memory in the thread's address space.
431  *
432  * n    The number of bytes to allocate.
433  *
434  * Returns:
435  *      A pointer to a BPatch_variableExpr representing the memory.
436  *
437  * If otherwise unspecified when binary rewriting, then the allocation
438  * happens in the original object.
439  */
440
441 BPatch_variableExpr *BPatch_addressSpace::mallocInt(int n)
442 {
443    std::vector<AddressSpace *> as;
444    assert(BPatch::bpatch != NULL);
445    getAS(as);
446    assert(as.size());
447    void *ptr = (void *) as[0]->inferiorMalloc(n, dataHeap);
448    if (!ptr) return NULL;
449    std::stringstream namestr;
450    namestr << "dyn_malloc_0x" << std::hex << ptr << "_" << n << "_bytes";
451    std::string name = namestr.str();
452    
453    BPatch_type *type = BPatch::bpatch->createScalar(name.c_str(), n);
454
455    return BPatch_variableExpr::makeVariableExpr(this, as[0], name, ptr,
456                                                 type);
457 }
458
459
460 /*
461  * BPatch_process::malloc
462  *
463  * Allocate memory in the thread's address space for a variable of the given
464  * type.
465  *
466  * type         The type of variable for which to allocate space.
467  *
468  * Returns:
469  *      A pointer to a BPatch_variableExpr representing the memory.
470  *
471  * XXX Should return NULL on failure, but the function which it calls,
472  *     inferiorMalloc, calls exit rather than returning an error, so this
473  *     is not currently possible.
474  */
475
476 BPatch_variableExpr *BPatch_addressSpace::mallocByType(const BPatch_type &type)
477 {
478    std::vector<AddressSpace *> as;
479    assert(BPatch::bpatch != NULL);
480    getAS(as);
481    assert(as.size());
482    BPatch_type &t = const_cast<BPatch_type &>(type);
483    void *mem = (void *) as[0]->inferiorMalloc(t.getSize(), dataHeap);
484    if (!mem) return NULL;
485    std::stringstream namestr;
486    namestr << "dyn_malloc_0x" << std::hex << mem << "_" << type.getName();
487    std::string name = namestr.str();
488    return BPatch_variableExpr::makeVariableExpr(this, as[0], name, mem, &t);
489 }
490
491
492 /*
493  * BPatch_process::free
494  *
495  * Free memory that was allocated with BPatch_process::malloc.
496  *
497  * ptr          A BPatch_variableExpr representing the memory to free.
498  */
499
500 bool BPatch_addressSpace::freeInt(BPatch_variableExpr &ptr)
501 {
502   if(ptr.intvar)
503   {
504     // kill the symbols
505     
506   }
507   
508    ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr());
509    return true;
510 }
511
512 BPatch_variableExpr *BPatch_addressSpace::createVariableInt(std::string name,
513                                                             Dyninst::Address addr,
514                                                             BPatch_type *type) {
515     assert(BPatch::bpatch != NULL);
516     std::vector<AddressSpace *> as;
517     getAS(as);
518     assert(as.size());
519
520     return BPatch_variableExpr::makeVariableExpr(this, 
521                                                  as[0],
522                                                  name,
523                                                  (void *)addr, 
524                                                  type);
525 }
526
527
528 /*
529  * BPatch_addressSpace::findFunctionByAddr
530  *
531  * Returns the function that contains the specified address, or NULL if the
532  * address is not within a function.
533  *
534  * addr         The address to use for the lookup.
535  */
536
537 BPatch_function *BPatch_addressSpace::findFunctionByAddrInt(void *addr)
538 {
539    int_function *func;   
540    std::vector<AddressSpace *> as;
541
542    getAS(as);
543    assert(as.size());
544    codeRange *range = as[0]->findOrigByAddr((Address) addr);
545    if (!range)
546       return NULL;
547
548    func = range->is_function();
549
550    if (!func) {
551       // if it's a mapped_object that has yet to be analyzed, 
552       // trigger analysis and re-invoke this function
553       if ( range->is_mapped_object() && 
554           ! ((mapped_object*)range)->isAnalyzed() ) {
555          ((mapped_object*)range)->analyze();
556          return findFunctionByAddrInt(addr);
557       }
558       return NULL;
559    }
560
561    return findOrCreateBPFunc(func, NULL);
562 }
563
564
565 /*
566  * BPatch_addressSpace::insertSnippet
567  *
568  * Insert a code snippet at a given instrumentation point.  Upon success,
569  * returns a handle to the created instance of the snippet, which can be used
570  * to delete it.  Otherwise returns NULL.
571  *
572  * expr         The snippet to insert.
573  * point        The point at which to insert it.
574  */
575
576 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetInt(const BPatch_snippet &expr, 
577       BPatch_point &point, 
578       BPatch_snippetOrder order)
579 {
580    BPatch_callWhen when;
581    if (point.getPointType() == BPatch_exit)
582       when = BPatch_callAfter;
583    else
584       when = BPatch_callBefore;
585
586    return insertSnippetWhen(expr, point, when, order);
587 }
588
589 /*
590  * BPatch_addressSpace::insertSnippet
591  *
592  * Insert a code snippet at a given instrumentation point.  Upon succes,
593  * returns a handle to the created instance of the snippet, which can be used
594  * to delete it.  Otherwise returns NULL.
595  *
596  * expr         The snippet to insert.
597  * point        The point at which to insert it.
598  */
599
600 // This handles conversion without requiring inst.h in a header file...
601 extern bool BPatchToInternalArgs(BPatch_point *point,
602       BPatch_callWhen when,
603       BPatch_snippetOrder order,
604       callWhen &ipWhen,
605       callOrder &ipOrder);
606
607
608 BPatchSnippetHandle *BPatch_addressSpace::insertSnippetWhen(const BPatch_snippet &expr,
609       BPatch_point &point,
610       BPatch_callWhen when,
611       BPatch_snippetOrder order)
612 {
613    BPatch_Vector<BPatch_point *> points;
614    points.push_back(&point);
615
616    return insertSnippetAtPointsWhen(expr,
617          points,
618          when,
619          order);
620
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