Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / binaryEdit.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: binaryEdit.h,v 1.15 2008/10/28 18:42:45 bernat Exp $
33
34 #ifndef BINARY_H
35 #define BINARY_H
36
37 #include <map>
38 #include <functional>
39 #include <queue>
40
41 #include "infHeap.h"
42 #include "addressSpace.h"
43 #include "codeRange.h"
44 #include "ast.h"
45
46 #include "parseAPI/h/InstructionSource.h"
47 #include "PatchMgr.h"
48
49 class fileDescriptor;
50 class func_instance;
51 class memoryTracker;
52 class depRelocation;
53
54 class BinaryEdit : public AddressSpace {
55  public:
56     // We must implement the following virtual functions
57
58     // "Read"/"Write" to an address space
59     bool readDataSpace(const void *inOther, 
60                        u_int amount, 
61                        void *inSelf, 
62                        bool showError);
63     bool readTextSpace(const void *inOther, 
64                        u_int amount, 
65                        void *inSelf);
66
67     bool writeDataSpace(void *inOther,
68                         u_int amount,
69                         const void *inSelf);
70     bool writeTextSpace(void *inOther,
71                         u_int amount,
72                         const void *inSelf);
73
74     // "Read"/"Write" to an address space with correct endian swapping.
75     bool readDataWord(const void *inOther, 
76                       u_int amount, 
77                       void *inSelf, 
78                       bool showError);
79     bool readTextWord(const void *inOther, 
80                       u_int amount, 
81                       void *inSelf);
82
83     bool writeDataWord(void *inOther,
84                        u_int amount,
85                        const void *inSelf);
86     bool writeTextWord(void *inOther,
87                        u_int amount,
88                        const void *inSelf);
89
90     // Memory allocation
91     // We don't specify how it should be done, only that it is. The model is
92     // that you ask for an allocation "near" a point, where "near" has an
93     // internal, platform-specific definition. The allocation mechanism does its
94     // best to give you what you want, but there are no promises - check the
95     // address of the returned buffer to be sure.
96
97     Address inferiorMalloc(unsigned size, 
98                            inferiorHeapType type=anyHeap,
99                            Address near = 0, 
100                            bool *err = NULL);
101     virtual void inferiorFree(Address item);
102     virtual bool inferiorRealloc(Address item, unsigned newSize);
103
104     /* AddressSpace pure virtual implementation */
105     unsigned getAddressWidth() const;
106     Address offset() const;
107     Address length() const;
108     Architecture getArch() const;
109     /*
110     // Until we need these different from AddressSpace,
111     // I'm not implementing.
112     void *getPtrToInstruction(Address) const;
113     bool isValidAddress(const Address) const;
114     */
115
116     // If true is passed for ignore_if_mt_not_set, then an error won't be
117     // initiated if we're unable to determine if the program is multi-threaded.
118     // We are unable to determine this if the daemon hasn't yet figured out
119     // what libraries are linked against the application.  Currently, we
120     // identify an application as being multi-threaded if it is linked against
121     // a thread library (eg. libpthreads.a on AIX).  There are cases where we
122     // are querying whether the app is multi-threaded, but it can't be
123     // determined yet but it also isn't necessary to know.
124     bool multithread_capable(bool ignore_if_mt_not_set = false);
125     
126     // Do we have the RT-side multithread functions available
127     bool multithread_ready(bool ignore_if_mt_not_set = false);
128
129     // Default to "nope"
130     virtual bool hasBeenBound(const SymtabAPI::relocationEntry &, 
131                               func_instance *&, 
132                               Address) { return false; }
133
134     // Should be easy if the process isn't _executing_ where
135     // we're deleting...
136
137     bool needsPIC();
138
139     BinaryEdit();
140     ~BinaryEdit();
141
142     // Same usage pattern as process
143     void deleteBinaryEdit();
144
145     // And the "open" factory method.
146     static BinaryEdit *openFile(const std::string &file,
147                                 Dyninst::PatchAPI::PatchMgrPtr mgr = Dyninst::PatchAPI::PatchMgrPtr(),
148                                 const std::string &member = "");
149
150     bool writeFile(const std::string &newFileName);
151     
152     virtual func_instance *findOnlyOneFunction(const std::string &name,
153                                               const std::string &libname = "",
154                                               bool search_rt_lib = true);
155
156     // open a shared library and (optionally) all its dependencies
157     bool openSharedLibrary(const std::string &file, bool openDependencies = true);
158
159     // add a shared library relocation
160         void addDependentRelocation(Address to, SymtabAPI::Symbol *referring);
161
162     // search for a shared library relocation
163         Address getDependentRelocationAddr(SymtabAPI::Symbol *referring);
164
165    void setupRTLibrary(std::vector<BinaryEdit *> &r);
166    std::vector<BinaryEdit *> &rtLibrary();
167    bool getAllDependencies(std::map<std::string, BinaryEdit* > &deps);
168
169    void markDirty();
170    bool isDirty();
171
172    mapped_object *getMappedObject();
173    
174    int_variable* createTrampGuard();
175    void setTrampGuard(int_variable* tg); 
176
177    void setMultiThreadCapable(bool b);
178
179    void addSibling(BinaryEdit *);
180    std::vector<BinaryEdit *> &getSiblings();
181
182    bool replaceTrapHandler();
183    bool usedATrap();
184    bool isMultiThreadCapable();
185    std::map<std::string, BinaryEdit*> openResolvedLibraryName(std::string filename);
186
187    bool writing() { return writing_; }
188
189    void addDyninstSymbol(SymtabAPI::Symbol *sym) { newDyninstSyms_.push_back(sym); }
190
191  private:
192     Address highWaterMark_;
193     Address lowWaterMark_;
194     bool isDirty_;
195
196     static bool getStatFileDescriptor(const std::string &file,
197                                       fileDescriptor &desc);
198
199     static bool getResolvedLibraryPath(const std::string &filename, std::vector<std::string> &paths);
200
201     bool inferiorMallocStatic(unsigned size);
202
203     Address maxAllocedAddr();
204
205     bool createMemoryBackingStore(mapped_object *obj);
206
207     bool initialize();
208
209     void makeInitAndFiniIfNeeded();
210
211     bool archSpecificMultithreadCapable();
212
213    /* Function specific to rewritting static binaries */
214    bool doStaticBinarySpecialCases();
215     
216     codeRangeTree* memoryTracker_;
217
218     mapped_object * addSharedObject(const std::string *fullPath);
219
220     std::vector<depRelocation *> dependentRelocations;
221
222     void buildDyninstSymbols(pdvector<SymtabAPI::Symbol *> &newSyms, 
223                              SymtabAPI::Region *newSec,
224                              SymtabAPI::Module *newMod);
225     mapped_object *mobj;
226     std::vector<BinaryEdit *> rtlib;
227     std::vector<BinaryEdit *> siblings;
228     bool multithread_capable_;
229     bool writing_;
230
231     // Symbols that other people (e.g., functions) want us to add
232     std::vector<SymtabAPI::Symbol *> newDyninstSyms_;
233
234 };
235
236 class depRelocation {
237         public:
238                 depRelocation(Address a, SymtabAPI::Symbol *r) : to(a), referring(r) { }
239                 Address getAddress() const { return to; }
240                 SymtabAPI::Symbol *getReferring() const { return referring; }
241
242         private:
243                 Address to;
244                 SymtabAPI::Symbol *referring;
245 };
246
247 class memoryTracker : public codeRange {
248  public:
249     memoryTracker(Address a, unsigned s) :
250         alloced(false),  dirty(false), a_(a), s_(s) {
251         b_ = malloc(s_);
252     }
253
254     memoryTracker(Address a, unsigned s, void *b) :
255     alloced(false), dirty(false), a_(a), s_(s)
256         {
257             b_ = malloc(s_);
258             memcpy(b_, b, s_);
259         }
260     ~memoryTracker() { free(b_); }
261
262     Address get_address() const { return a_; }
263     unsigned get_size() const { return s_; }
264     void *get_local_ptr() const { return b_; }
265     void realloc(unsigned newsize) {
266       b_ = ::realloc(b_, newsize);
267       s_ = newsize;
268       if (!b_) {
269         cerr << "Odd: failed to realloc " << newsize << endl;
270         assert(b_);
271       }
272     }
273
274     bool alloced;
275     bool dirty;
276
277  private:
278     Address a_;
279     unsigned s_;
280     void *b_;
281     
282 };
283
284 #endif // BINARY_H