Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / dyninstAPI / src / function.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: function.h,v 1.52 2008/09/08 16:44:02 bernat Exp $
33
34 #ifndef FUNCTION_H
35 #define FUNCTION_H
36
37 #include <string>
38 #include "common/h/Vector.h"
39 #include "common/h/Types.h"
40 #include "common/h/Pair.h"
41 #include "codegen.h"
42 #include "codeRange.h"
43 #include "util.h"
44 #include "parse-cfg.h"
45
46 #include "bitArray.h"
47
48 #include "dyn_detail/boost/shared_ptr.hpp"
49
50 #include "block.h"
51 #include "instPoint.h"
52 #include "PatchCFG.h"
53 #include "Point.h"
54
55 class process;
56 class mapped_module;
57 class mapped_object;
58
59 class func_instance;
60 class block_instance;
61 class edge_instance;
62 class instPoint;
63
64 typedef enum callType {
65   unknown_call,
66   cdecl_call,
67   stdcall_call,
68   fastcall_call,
69   thiscall_call
70 } callType;
71
72 using Dyninst::PatchAPI::Point;
73
74 class func_instance : public patchTarget, public Dyninst::PatchAPI::PatchFunction {
75   friend class block_instance;
76   friend class edge_instance;
77   friend class instPoint;
78   friend class BPatch_function;
79   public:
80     // Almost everythcing gets filled in later.
81     func_instance(parse_func *f,
82                   Address baseAddr,
83                   mapped_module *mod);
84
85     func_instance(const func_instance *parent,
86                   mapped_module *child_mod);
87
88     ~func_instance();
89
90   ////////////////////////////////////////////////
91   // Passthrough functions.
92   ////////////////////////////////////////////////
93   // To minimize wasted memory (since there will be many copies of
94   // this function) we make most methods passthroughs to the original
95   // parsed version.
96
97   const string &symTabName() const { return ifunc()->symTabName(); };
98   const string &prettyName() const { return ifunc()->prettyName(); };
99   const string &typedName() const { return ifunc()->typedName(); };
100   const string &name() const { return symTabName(); }
101
102   const vector<string>& symTabNameVector() const { return ifunc()->symTabNameVector(); }
103   const vector<string>& prettyNameVector() const { return ifunc()->prettyNameVector(); }
104   const vector<string>& typedNameVector() const { return ifunc()->typedNameVector(); }
105
106   // Debuggering functions
107   void debugPrint() const;
108
109   // And add...
110   // Don't make the std::string a reference; we want a copy.
111   void addSymTabName(const std::string name, bool isPrimary = false);
112   void addPrettyName(const std::string name, bool isPrimary = false);
113
114   Address getPtrAddress() const {return ptrAddr_;}
115
116   // Not defined here so we don't have to play header file magic
117   // Not const; we can add names via the Dyninst layer
118   parse_func *ifunc() const { return SCAST_PF(func_); }
119   mapped_module *mod() const { return mod_; }
120   mapped_object *obj() const;
121
122   AddressSpace *proc() const;
123   std::string format() const;
124
125   ////////////////////////////////////////////////
126   // CFG and other function body methods
127   ////////////////////////////////////////////////
128   typedef AddrOrderedBlockSet BlockSet;
129
130   block_instance *entryBlock();
131
132   // Kevin's defensive mode shtuff
133   // Blocks that have a sink target, essentially.
134   const BlockSet &unresolvedCF();
135   // Blocks where we provisionally stopped parsing because things looked weird.
136   const BlockSet &abruptEnds();
137
138   block_instance *getBlock(const Address addr);
139
140   Offset addrToOffset(const Address addr) const;
141
142   bool hasNoStackFrame() const {return ifunc()->hasNoStackFrame();}
143   bool savesFramePointer() const {return ifunc()->savesFramePointer();}
144
145   ////////////////////////////////////////////////
146   // Legacy/inter-module calls. Arguably should be an
147   // interprocedural edge, but I expect that would
148   // break all manner of things
149   ////////////////////////////////////////////////
150   func_instance *findCallee(block_instance *callBlock);
151
152   bool isSignalHandler() {return handlerFaultAddr_ != 0;}
153   Address getHandlerFaultAddr() {return handlerFaultAddr_;}
154   Address getHandlerFaultAddrAddr() {return handlerFaultAddrAddr_;}
155   void fixHandlerReturnAddr(Address newAddr);
156   void setHandlerFaultAddr(Address fa);
157   void setHandlerFaultAddrAddr(Address faa, bool set);
158
159   bool isInstrumentable();
160
161   Address get_address() const;
162   unsigned get_size() const;
163   std::string get_name() const;
164
165 #if defined(arch_x86) || defined(arch_x86_64)
166   //Replaces the function with a 'return val' statement.
167   // currently needed only on Linux/x86
168   // Defined in inst-x86.C
169   bool setReturnValue(int val);
170
171 #endif
172
173   ////////////////////////////////////////////////
174   // Relocation
175   ////////////////////////////////////////////////
176
177   bool canBeRelocated() const { return ifunc()->canBeRelocated(); }
178
179
180   ////////////////////////////////////////////////
181   // Code overlapping
182   ////////////////////////////////////////////////
183   // Get all functions that "share" the block. Actually, the
184   // block_instance will not be shared (they are per function),
185   // but the underlying parse_block records the sharing status.
186   // So dodge through to the image layer and find out that info.
187   // Returns true if such functions exist.
188
189   bool getSharingFuncs(block_instance *b,
190                        std::set<func_instance *> &funcs);
191
192   // The same, but for any function that overlaps with any of
193   // our basic blocks.
194   // OPTIMIZATION: we're not checking all blocks, only an exit
195   // point; this _should_ work :) but needs to change if we
196   // ever do flow-sensitive parsing
197   bool getSharingFuncs(std::set<func_instance *> &funcs);
198
199   // Slower version of the above that also finds functions that occupy
200   // the same address range, even if they do not share blocks - this can
201   // be caused by overlapping but disjoint assembly sequences
202   bool getOverlappingFuncs(std::set<func_instance *> &funcs);
203   bool getOverlappingFuncs(block_instance *b, std::set<func_instance *> &funcs);
204
205   ////////////////////////////////////////////////
206   // Misc
207   ////////////////////////////////////////////////
208
209
210   const pdvector< int_parRegion* > &parRegions();
211
212   bool containsSharedBlocks() const { return ifunc()->containsSharedBlocks(); }
213   unsigned getNumDynamicCalls();
214
215   // Fill the <callers> vector with pointers to the statically-determined
216   // list of functions that call this function.
217   template <class OutputIterator>
218     void getCallerBlocks(OutputIterator result);
219   template <class OutputIterator>
220     void getCallerFuncs(OutputIterator result);
221
222 #if defined(arch_power)
223   bool savesReturnAddr() const { return ifunc()->savesReturnAddr(); }
224 #endif
225
226 #if defined(os_windows)
227   //Calling convention for this function
228   callType func_instance::getCallingConvention();
229   int getParamSize() { return paramSize; }
230   void setParamSize(int s) { paramSize = s; }
231 #endif
232
233   void removeFromAll();
234   void getReachableBlocks(const std::set<block_instance*> &exceptBlocks,
235                           const std::list<block_instance*> &seedBlocks,
236                           std::set<block_instance*> &reachBlocks);//output
237
238
239   // So we can assert(consistency());
240   bool consistency() const;
241
242   // Wrappers for patchapi findPoints to find a single instPoint
243   instPoint *funcEntryPoint(bool create);
244   instPoint *funcExitPoint(block_instance* blk, bool create);
245   instPoint *preCallPoint(block_instance* blk, bool create);
246   instPoint *postCallPoint(block_instance* blk, bool create);
247   instPoint *blockEntryPoint(block_instance* blk, bool create);
248   instPoint *blockExitPoint(block_instance* b, bool create);
249   instPoint *preInsnPoint(block_instance* b, Address a,
250                           InstructionAPI::Instruction::Ptr ptr,
251                           bool trusted, bool create);
252   instPoint *postInsnPoint(block_instance* b, Address a,
253                            InstructionAPI::Instruction::Ptr ptr,
254                            bool trusted, bool create);
255   instPoint *edgePoint(edge_instance* eg, bool create);
256
257   // Wrappers for patchapi findPoints to find all instPoints w/ certain type
258   typedef std::vector<instPoint*> Points;
259   void funcExitPoints(Points*);
260   void callPoints(Points*);
261   void blockInsnPoints(block_instance*, Points*);
262   void edgePoints(Points*);
263
264   // Function wrapping
265   bool addSymbolsForCopy();
266   bool updateRelocationsToSym(Dyninst::SymtabAPI::Symbol *oldsym, 
267                               Dyninst::SymtabAPI::Symbol *newsym);
268   Dyninst::SymtabAPI::Symbol *getWrapperSymbol();
269   Dyninst::SymtabAPI::Symbol *getRelocSymbol();
270   void createWrapperSymbol(Address entry, std::string name);
271
272   static void destroy(func_instance *f);
273
274   void destroyBlock(block_instance *block);
275
276  private:
277
278   ///////////////////// Basic func info
279   //Address addr_; // Absolute address of the start of the function
280   Address ptrAddr_; // Absolute address of the function descriptor, if exists
281
282   // parse_func *ifunc_;
283   mapped_module *mod_; // This is really a dodge; translate a list of
284   // parse_funcs to int_funcs
285
286   ///////////////////// CFG and function body
287   // Defensive mode
288   BlockSet unresolvedCF_;
289   BlockSet abruptEnds_;
290
291
292   Address handlerFaultAddr_; /* if this is a signal handler, faultAddr_ is
293                                 set to -1, or to the address of the fault
294                                 that last caused the handler to be invoked. */
295   Address handlerFaultAddrAddr_;
296
297   //////////////////////////  Parallel Regions
298   pdvector<int_parRegion*> parallelRegions_; /* pointer to the parallel regions */
299
300   void addblock_instance(block_instance *instance);
301
302 #if defined(os_windows)
303   callType callingConv;
304   int paramSize;
305 #endif
306
307    Dyninst::SymtabAPI::Symbol *wrapperSym_;
308
309 };
310
311 template <class OutputIterator>
312 void func_instance::getCallerBlocks(OutputIterator result)
313 {
314   if(!ifunc() || !ifunc()->entryBlock())
315     return;
316   /*
317   const block_instance::edgelist &ins = entryBlock()->sources();
318   for (block_instance::edgelist::const_iterator iter = ins.begin();
319        iter != ins.end(); ++iter) {
320   */
321   const PatchBlock::edgelist &ins = entryBlock()->getSources();
322   for (PatchBlock::edgelist::const_iterator iter = ins.begin();
323        iter != ins.end(); ++iter) {
324     *result = SCAST_EI(*iter)->src();
325     ++result;
326   }
327 }
328
329 template <class OutputIterator>
330 void func_instance::getCallerFuncs(OutputIterator result)
331 {
332   std::set<block_instance *> callerBlocks;
333   getCallerBlocks(std::inserter(callerBlocks, callerBlocks.end()));
334   for (std::set<block_instance *>::iterator iter = callerBlocks.begin();
335        iter != callerBlocks.end(); ++iter) {
336     (*iter)->getFuncs(result);
337   }
338 }
339
340
341 #endif /* FUNCTION_H */