Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / addressSpace.h
1 /*
2  * Copyright (c) 1996-2011 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: addressSpace.h,v 1.9 2008/06/20 22:00:04 legendre Exp $
33
34 #ifndef ADDRESS_SPACE_H
35 #define ADDRESS_SPACE_H
36
37 #include "infHeap.h"
38 #include "codeRange.h"
39 #include "ast.h"
40 #include "symtabAPI/h/Symtab.h"
41 #include "dyninstAPI/src/trapMappings.h"
42 #include <list>
43
44 #include "common/h/IntervalTree.h"
45
46 #include "parseAPI/h/CodeObject.h"
47 #include "parseAPI/h/InstructionSource.h"
48 #include "Relocation/Relocation.h"
49 #include "Relocation/CodeTracker.h"
50
51 #include "PatchMgr.h"
52 #include "Command.h"
53
54 class codeRange;
55 class replacedFunctionCall;
56
57 class func_instance;
58 class block_instance;
59 class edge_instance;
60
61 class parse_func;
62 class parse_block;
63
64 struct edgeStub;
65 class int_variable;
66 class mapped_module;
67 class mapped_object;
68 class instPoint;
69
70 class BPatch_process;
71 class BPatch_function;
72 class BPatch_point;
73
74 class Emitter;
75 class generatedCodeObject;
76 class fileDescriptor;
77
78 using namespace Dyninst;
79 //using namespace SymtabAPI;
80
81 class func_instance;
82 class int_symbol;
83
84 class Dyn_Symbol;
85 class BinaryEdit;
86 class trampTrapMappings;
87
88 class baseTramp;
89
90 namespace Dyninst {
91    class MemoryEmulator;
92
93    namespace InstructionAPI {
94       class Instruction;
95    }
96 };
97
98 // This file serves to define an "address space", a set of routines that 
99 // code generation and instrumentation rely on to perform their duties. 
100 // This was derived from the process class and serves as a parent to that
101 // class and the static_space class for the rewriter. 
102
103 // The methods in this class were determined by what the code currently
104 // uses, not a particular design. As such, I expect this to change wildly
105 // by the time the refactoring is complete. 
106 //
107 // bernat, 5SEP07
108
109 // Note: this is a pure virtual class; it serves as an interface
110 // specification.
111
112 class AddressSpace : public InstructionSource {
113  public:
114
115    // This is a little complex, so let me explain my logic
116    // Map from B -> F_c -> F
117    // B identifies a call site
118    // F_c identifies an (optional) function context for the replacement
119    //   ... if F_c is not specified, we use NULL
120    // F specifies the replacement callee; if we want to remove the call entirely,
121    // also use NULL
122    //typedef std::map<block_instance *, std::map<func_instance *, func_instance *> > CallModMap;
123    //typedef std::map<func_instance *, func_instance *> FuncModMap;
124     
125     // Down-conversion functions
126     process *proc();
127     BinaryEdit *edit();
128
129     // Read/write
130
131     // We have read/write for both "text" and "data". This comes in handy,
132     // somewhere, I'm sure
133     virtual bool readDataWord(const void *inOther, 
134                               u_int amount, 
135                               void *inSelf, 
136                               bool showError) = 0;
137     virtual bool readDataSpace(const void *inOther, 
138                                u_int amount, 
139                                void *inSelf, 
140                                bool showError) = 0;
141     virtual bool readTextWord(const void *inOther, 
142                               u_int amount, 
143                               void *inSelf) = 0;
144     virtual bool readTextSpace(const void *inOther, 
145                                u_int amount, 
146                                void *inSelf) = 0;
147     
148
149     virtual bool writeDataWord(void *inOther,
150                                u_int amount,
151                                const void *inSelf) = 0;
152     virtual bool writeDataSpace(void *inOther,
153                                 u_int amount,
154                                 const void *inSelf) = 0;
155     virtual bool writeTextWord(void *inOther,
156                                u_int amount,
157                                const void *inSelf) = 0;
158     virtual bool writeTextSpace(void *inOther,
159                                 u_int amount,
160                                 const void *inSelf) = 0;
161
162     // Memory allocation
163     // We don't specify how it should be done, only that it is. The model is
164     // that you ask for an allocation "near" a point, where "near" has an
165     // internal, platform-specific definition. The allocation mechanism does its
166     // best to give you what you want, but there are no promises - check the
167     // address of the returned buffer to be sure.
168
169     virtual Address inferiorMalloc(unsigned size, inferiorHeapType type=anyHeap,
170                                    Address near = 0, bool *err = NULL) = 0;
171     virtual void inferiorFree(Address item) = 0;
172     void inferiorFreeInternal(Address item);
173     // And a "constrain" call to free unused memory. This is useful because our
174     // instrumentation is incredibly wasteful.
175     virtual bool inferiorRealloc(Address item, unsigned newSize) = 0;
176     bool inferiorReallocInternal(Address item, unsigned newSize);
177     bool inferiorShrinkBlock(heapItem *h, Address block, unsigned newSize);
178     bool inferiorExpandBlock(heapItem *h, Address block, unsigned newSize);
179
180
181     bool isInferiorAllocated(Address block);
182
183     bool getDyninstRTLibName();
184
185     // InstructionSource 
186     virtual bool isValidAddress(const Address) const;
187     virtual void *getPtrToInstruction(const Address) const;
188     virtual void *getPtrToData(const Address a) const { return getPtrToInstruction(a); }
189     virtual unsigned getAddressWidth() const = 0;
190     virtual bool isCode(const Address) const;
191     virtual bool isData(const Address) const;
192     virtual Address offset() const = 0;
193     virtual Address length() const = 0;
194     virtual Architecture getArch() const = 0;
195
196     // Trap address to base tramp address (for trap instrumentation)
197     trampTrapMappings trapMapping;
198     
199     //////////////////////////////////////////////////////////////
200     // Function/variable lookup code
201     // Turns out that instrumentation needs this... so the 
202     // AddressSpace keeps growing. 
203     //////////////////////////////////////////////////////////////
204
205     // findFuncByName: returns function associated with "func_name"
206     // This routine checks both the a.out image and any shared object images 
207     // for this function
208     //func_instance *findFuncByName(const std::string &func_name);
209     
210     bool findFuncsByAll(const std::string &funcname,
211                         pdvector<func_instance *> &res,
212                         const std::string &libname = "");
213     
214     // Specific versions...
215     bool findFuncsByPretty(const std::string &funcname,
216                            pdvector<func_instance *> &res,
217                            const std::string &libname = "");
218     bool findFuncsByMangled(const std::string &funcname, 
219                             pdvector<func_instance *> &res,
220                             const std::string &libname = "");
221     
222     bool findVarsByAll(const std::string &varname,
223                        pdvector<int_variable *> &res,
224                        const std::string &libname = "");
225     
226     // And we often internally want to wrap the above to return one
227     // and only one func...
228     virtual func_instance *findOnlyOneFunction(const std::string &name,
229                                               const std::string &libname = "",
230                                               bool search_rt_lib = true);
231
232
233     // This will find the named symbol in the image or in a shared object
234     // Necessary since some things don't show up as a function or variable.
235     //    bool getSymbolInfo( const std::string &name, Dyn_Symbol &ret );
236     // This gets wrapped with an int_symbol and returned.
237     bool getSymbolInfo( const std::string &name, int_symbol &ret );
238
239     // getAllFunctions: returns a vector of all functions defined in the
240     // a.out and in the shared objects
241     void getAllFunctions(pdvector<func_instance *> &);
242     
243     // Find the code sequence containing an address
244     bool findFuncsByAddr(Address addr, std::set<func_instance *> &funcs, bool includeReloc = false);
245     bool findBlocksByAddr(Address addr, std::set<block_instance *> &blocks, bool includeReloc = false);
246     // Don't use this...
247     // I take it back. Use it when you _know_ that you want one function,
248     // picked arbitrarily, from the possible functions.
249     func_instance *findOneFuncByAddr(Address addr);
250     // And the one thing that is unique: entry address!
251     func_instance *findFuncByEntry(Address addr);
252     block_instance *findBlockByEntry(Address addr);
253
254     // And a lookup by "internal" function to find clones during fork...
255     func_instance *findFunction(parse_func *ifunc);
256     block_instance *findBlock(parse_block *iblock);
257     edge_instance *findEdge(ParseAPI::Edge *iedge);
258
259         // Fast lookups across all mapped_objects
260         func_instance *findFuncByEntry(const block_instance *block);
261
262     //findJumpTargetFuncByAddr Acts like findFunc, but if it fails,
263     // checks if 'addr' is a jump to a function.
264     func_instance *findJumpTargetFuncByAddr(Address addr);
265     
266     // true if the addrs are in the same object and region within the object
267     bool sameRegion(Dyninst::Address addr1, Dyninst::Address addr2);
268
269     // findModule: returns the module associated with "mod_name" 
270     // this routine checks both the a.out image and any shared object 
271     // images for this module
272     // if check_excluded is true it checks to see if the module is excluded
273     // and if it is it returns 0.  If check_excluded is false it doesn't check
274     //  if substring_match is true, the first module whose name contains
275     //  the provided string is returned.
276     // Wildcard: handles "*" and "?"
277     mapped_module *findModule(const std::string &mod_name, bool wildcard = false);
278     // And the same for objects
279     // Wildcard: handles "*" and "?"
280     mapped_object *findObject(const std::string &obj_name, bool wildcard = false) const;
281     mapped_object *findObject(Address addr) const;
282     mapped_object *findObject(fileDescriptor desc) const;
283     mapped_object *findObject(const ParseAPI::CodeObject *co) const;
284
285     mapped_object *getAOut() { assert(mapped_objects.size()); return mapped_objects[0];}
286     
287     // getAllModules: returns a vector of all modules defined in the
288     // a.out and in the shared objects
289     void getAllModules(pdvector<mapped_module *> &);
290
291     // return the list of dynamically linked libs
292     const pdvector<mapped_object *> &mappedObjects() { return mapped_objects;  } 
293
294     // And a shortcut pointer
295     std::set<mapped_object *> runtime_lib;
296     // ... and keep the name around
297     std::string dyninstRT_name;
298     
299     // If true is passed for ignore_if_mt_not_set, then an error won't be
300     // initiated if we're unable to determine if the program is multi-threaded.
301     // We are unable to determine this if the daemon hasn't yet figured out
302     // what libraries are linked against the application.  Currently, we
303     // identify an application as being multi-threaded if it is linked against
304     // a thread library (eg. libpthreads.a on AIX).  There are cases where we
305     // are querying whether the app is multi-threaded, but it can't be
306     // determined yet but it also isn't necessary to know.
307     virtual bool multithread_capable(bool ignore_if_mt_not_set = false) = 0;
308     
309     // Do we have the RT-side multithread functions available
310     virtual bool multithread_ready(bool ignore_if_mt_not_set = false) = 0;
311
312     //////////////////////////////////////////////////////
313     // Process-level instrumentation (?)
314     /////////////////////////////////////////////////////
315
316     // instPoint isn't const; it may get an updated list of
317     // instances since we generate them lazily.
318     // Shouldn't this be an instPoint member function?
319     void modifyCall(block_instance *callBlock, func_instance *newCallee, func_instance *context = NULL);
320     void revertCall(block_instance *callBlock, func_instance *context = NULL);
321     void replaceFunction(func_instance *oldfunc, func_instance *newfunc);
322     bool wrapFunction(func_instance *original, func_instance *wrapper, SymtabAPI::Symbol *clone);
323     void revertReplacedFunction(func_instance *oldfunc);
324     void removeCall(block_instance *callBlock, func_instance *context = NULL);
325
326     // And this....
327     typedef dyn_detail::boost::shared_ptr<Dyninst::InstructionAPI::Instruction> InstructionPtr;
328     bool getDynamicCallSiteArgs(InstructionPtr insn,
329                                 Address addr,
330                                 pdvector<AstNodePtr> &args);
331
332     // Default to "nope"
333     virtual bool hasBeenBound(const SymtabAPI::relocationEntry &, 
334                               func_instance *&, 
335                               Address) { return false; }
336     
337     // Trampoline guard get/set functions
338     int_variable* trampGuardBase(void) { return trampGuardBase_; }
339     AstNodePtr trampGuardAST(void);
340
341     // Get the current code generator (or emitter)
342     Emitter *getEmitter();
343
344     //True if any reference to this address space needs PIC
345     virtual bool needsPIC() = 0;
346     //True if we need PIC to reference the given variable or function
347     // from this addressSpace.
348     bool needsPIC(int_variable *v); 
349     bool needsPIC(func_instance *f);
350     bool needsPIC(AddressSpace *s);
351     
352     //////////////////////////////////////////////////////
353     // BPatch-level stuff
354     //////////////////////////////////////////////////////
355     // Callbacks for higher level code (like BPatch) to learn about new 
356     //  functions and InstPoints.
357  private:
358     BPatch_function *(*new_func_cb)(AddressSpace *a, func_instance *f);
359     BPatch_point *(*new_instp_cb)(AddressSpace *a, func_instance *f, instPoint *ip, 
360                                   int type);
361  public:
362     //Trigger the callbacks from a lower level
363     BPatch_function *newFunctionCB(func_instance *f) 
364         { assert(new_func_cb); return new_func_cb(this, f); }
365     BPatch_point *newInstPointCB(func_instance *f, instPoint *pt, int type)
366         { assert(new_instp_cb); return new_instp_cb(this, f, pt, type); }
367     
368     //Register callbacks from the higher level
369     void registerFunctionCallback(BPatch_function *(*f)(AddressSpace *p, 
370                                                         func_instance *f))
371         { new_func_cb = f; };
372     void registerInstPointCallback(BPatch_point *(*f)(AddressSpace *p, func_instance *f,
373                                                       instPoint *ip, int type))
374         { new_instp_cb = f; }
375     
376     
377     //Anonymous up pointer to the containing process.  This is BPatch_process
378     // in Dyninst.  Currently stored as an void pointer in case we do
379     // anything with this during the library split.
380     void *up_ptr() { return up_ptr_; }
381     void set_up_ptr(void *ptr) { up_ptr_ = ptr; }
382     
383     //////////////////////////////////////////////////////
384     // Internal and cleanup 
385     //////////////////////////////////////////////////////
386
387     // Clear things out (e.g., deleteProcess)
388     void deleteAddressSpace();
389     // Fork psuedo-constructor
390     void copyAddressSpace(process *parent);
391
392     // Aaand constructor/destructor
393     AddressSpace();
394     virtual ~AddressSpace();
395
396
397     //////////////////////////////////////////////////////
398     // Yuck
399     //////////////////////////////////////////////////////
400     Address getObservedCostAddr() const { return costAddr_; }
401     void updateObservedCostAddr(Address addr) { costAddr_ = addr;}
402
403     // Can we use traps if necessary?
404     bool canUseTraps();
405     void setUseTraps(bool usetraps);
406
407     //////////////////////////////////////////////////////
408     // The New Hotness
409     //////////////////////////////////////////////////////
410     //
411     // This is the top interface for the new (experimental)
412     // (probably not working) code generation interface. 
413     // The core idea is to feed a set of func_instances 
414     // (actually, a set of blocks, but functions are convenient)
415     // into a CodeMover class, let it chew on the code, and 
416     // spit out a buffer of moved code. 
417     // We also get a priority list of patches; (origAddr,
418     // movedAddr) pairs. We then get to decide what we want
419     // to do with those patches: put in a branch or say to 
420     // heck with it.
421     
422     bool relocate();
423                    
424
425     // Get the list of addresses an address (in a block) 
426     // has been relocated to.
427     void getRelocAddrs(Address orig,
428                        block_instance *block,
429                        func_instance *func,
430                        std::list<Address> &relocs,
431                        bool getInstrumentationAddrs) const;
432
433
434     bool getAddrInfo(Address relocAddr,//input
435                                           Address &origAddr,
436                      std::vector<func_instance *> &origFuncs,
437                      baseTramp *&baseTramp);
438     typedef Relocation::CodeTracker::RelocInfo RelocInfo;
439     bool getRelocInfo(Address relocAddr,
440                       RelocInfo &relocInfo);
441     // defensive mode code // 
442
443     void causeTemplateInstantiations();
444
445     // Debugging method
446     bool inEmulatedCode(Address addr);
447
448     std::map<func_instance*,std::vector<edgeStub> > 
449     getStubs(const std::list<block_instance *> &owBBIs,
450              const std::set<block_instance*> &delBBIs,
451              const std::list<func_instance*> &deadFuncs);
452
453     void addDefensivePad(block_instance *callBlock, func_instance *callFunc,
454                          Address padStart, unsigned size);
455
456     void getPreviousInstrumentationInstances(baseTramp *bt,
457                                              std::set<Address>::iterator &b,
458                                              std::set<Address>::iterator &e);
459     void addInstrumentationInstance(baseTramp *bt, Address addr);
460
461     void addModifiedFunction(func_instance *func);
462     void addModifiedBlock(block_instance *block);
463
464     void updateMemEmulator();
465     bool isMemoryEmulated() { return emulateMem_; }
466     bool emulatingPC() { return emulatePC_; }
467     MemoryEmulator *getMemEm();
468     void invalidateMemory(Address base, Address size);
469
470     bool delayRelocation() const { return delayRelocation_; }
471  protected:
472
473     // inferior malloc support functions
474     void inferiorFreeCompact();
475     int findFreeIndex(unsigned size, int type, Address lo, Address hi);
476     void addHeap(heapItem *h);
477     void initializeHeap();
478     
479     // Centralization of certain inferiorMalloc operations
480     Address inferiorMallocInternal(unsigned size, Address lo, Address hi, 
481                                    inferiorHeapType type);
482     void inferiorMallocAlign(unsigned &size);
483
484     bool heapInitialized_;
485     bool useTraps_;
486     inferiorHeap heap_;
487
488     // Loaded mapped objects (may be just 1)
489     pdvector<mapped_object *> mapped_objects;
490
491     int_variable* trampGuardBase_; // Tramp recursion index mapping
492     AstNodePtr trampGuardAST_;
493
494     void *up_ptr_;
495
496     Address costAddr_;
497
498     /////// New instrumentation system
499     typedef std::list<Relocation::CodeTracker *> CodeTrackers;
500     CodeTrackers relocatedCode_;
501
502     bool transform(Dyninst::Relocation::CodeMoverPtr cm);
503     Address generateCode(Dyninst::Relocation::CodeMoverPtr cm, Address near);
504     bool patchCode(Dyninst::Relocation::CodeMoverPtr cm,
505                    Dyninst::Relocation::SpringboardBuilderPtr spb);
506
507     typedef std::set<func_instance *> FuncSet;
508     std::map<mapped_object *, FuncSet> modifiedFunctions_;
509
510     bool relocateInt(FuncSet::const_iterator begin, FuncSet::const_iterator end, Address near);
511
512     // defensive mode code
513     typedef std::pair<Address, unsigned> DefensivePad;
514     std::map<instPoint *, std::set<DefensivePad> > forwardDefensiveMap_;
515     IntervalTree<Address, instPoint *> reverseDefensiveMap_;
516
517     // Tracking instrumentation for fast removal
518     std::map<baseTramp *, std::set<Address> > instrumentationInstances_;
519
520     // Track desired function replacements/removals/call replacements
521     // CallModMap callModifications_;
522     // FuncModMap functionReplacements_;
523     // FuncModMap functionWraps_;
524
525     void addAllocatedRegion(Address start, unsigned size);
526     void addModifiedRegion(mapped_object *obj);
527
528     MemoryEmulator *memEmulator_;
529
530     bool emulateMem_;
531     bool emulatePC_;
532
533     bool delayRelocation_;
534
535   // PatchAPI stuffs
536   public:
537     Dyninst::PatchAPI::PatchMgrPtr mgr() const { return mgr_; }
538     void setMgr(Dyninst::PatchAPI::PatchMgrPtr m) { mgr_ = m; }
539     void setPatcher(Dyninst::PatchAPI::PatcherPtr p) { patcher_ = p; }
540     void initPatchAPI(mapped_object* aout);
541     void addMappedObject(mapped_object* obj);
542     Dyninst::PatchAPI::PatcherPtr patcher() { return patcher_; }
543     static bool patch(AddressSpace*);
544   protected:
545     Dyninst::PatchAPI::PatchMgrPtr mgr_;
546     Dyninst::PatchAPI::PatcherPtr patcher_;
547 };
548
549
550 extern int heapItemCmpByAddr(const heapItem **A, const heapItem **B);
551
552 #endif // ADDRESS_SPACE_H