Define cap_stack_mods and properly limit stack mods to x86,x86_64
[dyninst.git] / dyninstAPI / src / function.h
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 // $Id: function.h,v 1.52 2008/09/08 16:44:02 bernat Exp $
32
33 #ifndef FUNCTION_H
34 #define FUNCTION_H
35
36 #include <string>
37 #include "common/src/Vector.h"
38 #include "common/src/Types.h"
39 #include "common/src/Pair.h"
40 #include "codegen.h"
41 #include "codeRange.h"
42 #include "util.h"
43 #include "parse-cfg.h"
44
45 #include "bitArray.h"
46
47 #include "block.h"
48 #include "instPoint.h"
49 #include "PatchCFG.h"
50 #include "Point.h"
51
52 #include "Variable.h"
53 #include "stackanalysis.h"
54 #if defined(cap_stack_mods)
55 #include "StackMod.h"
56 #include "StackMod/OffsetVector.h"
57 #include "StackMod/StackAccess.h"
58 #include "StackMod/StackLocation.h"
59 #include "StackMod/TMap.h"
60 #endif
61
62 class PCProcess;
63 class mapped_module;
64 class mapped_object;
65
66 class func_instance;
67 class block_instance;
68 class edge_instance;
69 class instPoint;
70
71 typedef enum callType {
72   unknown_call,
73   cdecl_call,
74   stdcall_call,
75   fastcall_call,
76   thiscall_call
77 } callType;
78
79 using Dyninst::PatchAPI::Point;
80
81 class func_instance : public patchTarget, public Dyninst::PatchAPI::PatchFunction {
82   friend class block_instance;
83   friend class edge_instance;
84   friend class instPoint;
85   public:
86     // Almost everythcing gets filled in later.
87     func_instance(parse_func *f,
88                   Address baseAddr,
89                   mapped_module *mod);
90
91     func_instance(const func_instance *parent,
92                   mapped_module *child_mod);
93
94     ~func_instance();
95
96   ////////////////////////////////////////////////
97   // Passthrough functions.
98   ////////////////////////////////////////////////
99   // To minimize wasted memory (since there will be many copies of
100   // this function) we make most methods passthroughs to the original
101   // parsed version.
102
103   string symTabName() const { return ifunc()->symTabName(); };
104   string prettyName() const { return ifunc()->prettyName(); };
105   string typedName() const { return ifunc()->typedName(); };
106   string name() const { return symTabName(); }
107
108   SymtabAPI::Aggregate::name_iter symtab_names_begin() const 
109    {
110      return ifunc()->symtab_names_begin();
111    }
112    SymtabAPI::Aggregate::name_iter symtab_names_end() const 
113    {
114      return ifunc()->symtab_names_end();
115    }
116    SymtabAPI::Aggregate::name_iter pretty_names_begin() const 
117    {
118      return ifunc()->pretty_names_begin();
119    }
120    SymtabAPI::Aggregate::name_iter pretty_names_end() const 
121    {
122      return ifunc()->pretty_names_end();
123    }
124    SymtabAPI::Aggregate::name_iter typed_names_begin() const 
125    {
126      return ifunc()->typed_names_begin();
127    }
128    SymtabAPI::Aggregate::name_iter typed_names_end() const 
129    {
130      return ifunc()->typed_names_end();
131    }
132    //vector<string> symTabNameVector() const { return ifunc()->symTabNameVector(); }
133    //vector<string> prettyNameVector() const { return ifunc()->prettyNameVector(); }
134    //vector<string> typedNameVector() const { return ifunc()->typedNameVector(); }
135
136   // Debuggering functions
137   void debugPrint() const;
138
139   // And add...
140   // Don't make the std::string a reference; we want a copy.
141   void addSymTabName(const std::string name, bool isPrimary = false);
142   void addPrettyName(const std::string name, bool isPrimary = false);
143
144   Address getPtrAddress() const {return ptrAddr_;}
145
146   // Not defined here so we don't have to play header file magic
147   // Not const; we can add names via the Dyninst layer
148   parse_func *ifunc() const { return SCAST_PF(func_); }
149   mapped_module *mod() const { return mod_; }
150   mapped_object *obj() const;
151
152   AddressSpace *proc() const;
153   std::string format() const;
154
155   ////////////////////////////////////////////////
156   // CFG and other function body methods
157   ////////////////////////////////////////////////
158   typedef AddrOrderedBlockSet BlockSet;
159
160   block_instance *entryBlock();
161
162   // Kevin's defensive mode shtuff
163   // Blocks that have a sink target, essentially.
164   const BlockSet &unresolvedCF();// Blocks that have a sink target, essentially
165   const BlockSet &abruptEnds(); // Blocks where we provisionally stopped 
166                                 // parsing because things looked weird.
167   block_instance * setNewEntry(block_instance *def, // if no better choice
168                                std::set<block_instance*> &deadBlocks);
169   // kevin signal-handler information
170   bool isSignalHandler() {return handlerFaultAddr_ != 0;}
171   Address getHandlerFaultAddr() {return handlerFaultAddr_;}
172   Address getHandlerFaultAddrAddr() {return handlerFaultAddrAddr_;}
173   void setHandlerFaultAddr(Address fa);
174   void setHandlerFaultAddrAddr(Address faa, bool set);
175   void triggerModified();
176
177   block_instance *getBlockByEntry(const Address addr);
178   // get all blocks that contain the given address
179   bool getBlocks(const Address addr, std::set<block_instance*> &blks);
180   // Get the block with an instruction that starts at addr
181   block_instance *getBlock(const Address addr);
182
183   Offset addrToOffset(const Address addr) const;
184
185   bool hasNoStackFrame() const {return ifunc()->hasNoStackFrame();}
186   bool savesFramePointer() const {return ifunc()->savesFramePointer();}
187
188   ////////////////////////////////////////////////
189   // Legacy/inter-module calls. Arguably should be an
190   // interprocedural edge, but I expect that would
191   // break all manner of things
192   ////////////////////////////////////////////////
193   func_instance *findCallee(block_instance *callBlock);
194
195   bool isInstrumentable();
196
197   Address get_address() const;
198   unsigned get_size() const;
199   unsigned footprint(); // not const, calls ifunc()->extents()
200   std::string get_name() const;
201
202 #if defined(arch_x86) || defined(arch_x86_64)
203   //Replaces the function with a 'return val' statement.
204   // currently needed only on Linux/x86
205   // Defined in inst-x86.C
206   bool setReturnValue(int val);
207
208 #endif
209
210   ////////////////////////////////////////////////
211   // Code overlapping
212   ////////////////////////////////////////////////
213   // Get all functions that "share" the block. Actually, the
214   // block_instance will not be shared (they are per function),
215   // but the underlying parse_block records the sharing status.
216   // So dodge through to the image layer and find out that info.
217   // Returns true if such functions exist.
218
219   bool getSharingFuncs(block_instance *b,
220                        std::set<func_instance *> &funcs);
221
222   // The same, but for any function that overlaps with any of
223   // our basic blocks.
224   // OPTIMIZATION: we're not checking all blocks, only an exit
225   // point; this _should_ work :) but needs to change if we
226   // ever do flow-sensitive parsing
227   bool getSharingFuncs(std::set<func_instance *> &funcs);
228
229   // Slower version of the above that also finds functions that occupy
230   // the same address range, even if they do not share blocks - this can
231   // be caused by overlapping but disjoint assembly sequences
232   bool getOverlappingFuncs(std::set<func_instance *> &funcs);
233   bool getOverlappingFuncs(block_instance *b, std::set<func_instance *> &funcs);
234
235   ////////////////////////////////////////////////
236   // Misc
237   ////////////////////////////////////////////////
238
239
240   const pdvector< int_parRegion* > &parRegions();
241
242   bool containsSharedBlocks() const { return ifunc()->containsSharedBlocks(); }
243   unsigned getNumDynamicCalls();
244
245   // Fill the <callers> vector with pointers to the statically-determined
246   // list of functions that call this function.
247   template <class OutputIterator>
248     void getCallerBlocks(OutputIterator result);
249   template <class OutputIterator>
250     void getCallerFuncs(OutputIterator result);
251   bool getLiveCallerBlocks(const std::set<block_instance*> &deadBlocks,
252                            const std::list<func_instance*> &deadFuncs,
253                            std::map<Address,vector<block_instance*> > & output_stubs);
254
255
256
257 #if defined(arch_power)
258   bool savesReturnAddr() const { return ifunc()->savesReturnAddr(); }
259 #endif
260
261 #if defined(os_windows)
262   //Calling convention for this function
263   callType func_instance::getCallingConvention();
264   int getParamSize() { return paramSize; }
265   void setParamSize(int s) { paramSize = s; }
266 #endif
267
268   void getReachableBlocks(const std::set<block_instance*> &exceptBlocks,
269                           const std::list<block_instance*> &seedBlocks,
270                           std::set<block_instance*> &reachBlocks);//output
271
272
273   // So we can assert(consistency());
274   bool consistency() const;
275
276   // Wrappers for patchapi findPoints to find a single instPoint
277   instPoint *funcEntryPoint(bool create);
278   instPoint *funcExitPoint(block_instance* blk, bool create);
279   instPoint *preCallPoint(block_instance* blk, bool create);
280   instPoint *postCallPoint(block_instance* blk, bool create);
281   instPoint *blockEntryPoint(block_instance* blk, bool create);
282   instPoint *blockExitPoint(block_instance* b, bool create);
283   instPoint *preInsnPoint(block_instance* b, Address a,
284                           InstructionAPI::Instruction::Ptr ptr,
285                           bool trusted, bool create);
286   instPoint *postInsnPoint(block_instance* b, Address a,
287                            InstructionAPI::Instruction::Ptr ptr,
288                            bool trusted, bool create);
289   instPoint *edgePoint(edge_instance* eg, bool create);
290
291   // Wrappers for patchapi findPoints to find all instPoints w/ certain type
292   typedef std::vector<instPoint*> Points;
293   void funcExitPoints(Points*);
294   void callPoints(Points*);
295   void blockInsnPoints(block_instance*, Points*);
296   void edgePoints(Points*);
297
298   // Function wrapping
299   bool addSymbolsForCopy();
300   bool updateRelocationsToSym(Dyninst::SymtabAPI::Symbol *oldsym, 
301                               Dyninst::SymtabAPI::Symbol *newsym);
302   Dyninst::SymtabAPI::Symbol *getWrapperSymbol();
303   Dyninst::SymtabAPI::Symbol *getRelocSymbol();
304   void createWrapperSymbol(Address entry, std::string name);
305
306   static void destroy(func_instance *f);
307   void removeBlock(block_instance *block);
308
309   void split_block_cb(block_instance *b1, block_instance *b2);
310   void add_block_cb(block_instance *block);
311
312   virtual void markModified();
313
314 #if defined(cap_stack_mods)
315   // Stack modification
316   void addParam(Dyninst::SymtabAPI::localVar* p) { _params.insert(p); }
317   void addVar(Dyninst::SymtabAPI::localVar* v) { _vars.insert(v); }
318   std::set<Dyninst::SymtabAPI::localVar*> getParams() const { return _params; }
319   std::set<Dyninst::SymtabAPI::localVar*> getVars() const { return _vars; }
320
321   void setStackMod(bool b) { _hasStackMod = b; }
322   bool hasStackMod() const { return _hasStackMod; }
323
324   void addMod(StackMod* m, TMap* tMap);
325   void removeMod(StackMod* m);
326   std::set<StackMod*>* getMods() const { return _modifications; }
327   void printMods() const;
328
329   Accesses* getAccesses(Address addr);
330
331   void setCanary(bool b) { _hasCanary = b; }
332   bool hasCanary() { return _hasCanary; }
333
334   bool hasRandomize() { return _randomizeStackFrame; }
335
336   bool hasOffsetVector() const { return _processedOffsetVector; }
337   bool hasValidOffsetVector() const { return _validOffsetVector; }
338   bool createOffsetVector();
339   OffsetVector* getOffsetVector() const { return _offVec; }
340
341   TMap* getTMap() const { return _tMap; }
342   void replaceTMap(TMap* newTMap) { _tMap = newTMap; }
343
344   bool randomize(TMap* tMap, bool seeded = false, int seed = -1);
345 #endif
346
347   bool operator<(func_instance& rhs) {
348       return addr() < rhs.addr();
349   }
350
351  private:
352
353   // helper func for block_instance::setNotAbruptEnd(), do not call directly 
354   void removeAbruptEnd(const block_instance *); 
355
356   ///////////////////// Basic func info
357   //Address addr_; // Absolute address of the start of the function
358   Address ptrAddr_; // Absolute address of the function descriptor, if exists
359
360   // parse_func *ifunc_;
361   mapped_module *mod_; // This is really a dodge; translate a list of
362   // parse_funcs to int_funcs
363
364   ///////////////////// CFG and function body
365   // Defensive mode
366   BlockSet unresolvedCF_;
367   BlockSet abruptEnds_;
368   size_t prevBlocksAbruptEnds_; // num func blocks when calculated
369
370
371   Address handlerFaultAddr_; /* if this is a signal handler, faultAddr_ is
372                                 set to -1, or to the address of the fault
373                                 that last caused the handler to be invoked. */
374   Address handlerFaultAddrAddr_;
375
376   //////////////////////////  Parallel Regions
377   pdvector<int_parRegion*> parallelRegions_; /* pointer to the parallel regions */
378
379   void addblock_instance(block_instance *instance);
380
381 #if defined(os_windows)
382   callType callingConv;
383   int paramSize;
384 #endif
385
386    Dyninst::SymtabAPI::Symbol *wrapperSym_;
387
388 #if defined(cap_stack_mods)
389   // Stack modification
390   bool createOffsetVector_Symbols();
391
392   bool createOffsetVector_Analysis(ParseAPI::Function* func,
393           ParseAPI::Block* block,
394           InstructionAPI::Instruction::Ptr insn,
395           Address addr);
396
397   bool addToOffsetVector(StackAnalysis::Height off,
398           int size,
399           StackAccess::StackAccessType type,
400           bool isRegisterHeight,
401           ValidPCRange* valid,
402           MachRegister reg = MachRegister());
403
404   void createTMap_internal(StackMod* mod, StackLocation* loc, TMap* tMap);
405   void createTMap_internal(StackMod* mod, TMap* tMap);
406
407   std::set<Dyninst::SymtabAPI::localVar*> _params;
408   std::set<Dyninst::SymtabAPI::localVar*> _vars;
409   bool _hasDebugSymbols;
410
411   bool _hasStackMod;
412   std::set<StackMod*>* _modifications;
413
414   bool _seeded;
415   int _seed;
416   bool _randomizeStackFrame;
417   bool _hasCanary;
418
419   bool _processedOffsetVector;
420   bool _validOffsetVector;
421   OffsetVector* _offVec;
422   set<tmpObject, less_tmpObject >* _tmpObjects;
423
424   TMap* _tMap;
425   std::map<Address, Accesses*>* _accessMap;
426 #endif
427 };
428
429 template <class OutputIterator>
430 void func_instance::getCallerBlocks(OutputIterator result)
431 {
432   if(!ifunc() || !ifunc()->entryBlock())
433     return;
434   /*
435   const block_instance::edgelist &ins = entryBlock()->sources();
436   for (block_instance::edgelist::const_iterator iter = ins.begin();
437        iter != ins.end(); ++iter) {
438   */
439   const PatchBlock::edgelist &ins = entryBlock()->sources();
440   for (PatchBlock::edgelist::const_iterator iter = ins.begin();
441        iter != ins.end(); ++iter) 
442   {
443       if ((*iter)->type() == ParseAPI::CALL) {
444         *result = SCAST_EI(*iter)->src();
445         ++result;
446       }
447   }
448 }
449
450 template <class OutputIterator>
451 void func_instance::getCallerFuncs(OutputIterator result)
452 {
453   std::set<block_instance *> callerBlocks;
454   getCallerBlocks(std::inserter(callerBlocks, callerBlocks.end()));
455   for (std::set<block_instance *>::iterator iter = callerBlocks.begin();
456        iter != callerBlocks.end(); ++iter) {
457     (*iter)->getFuncs(result);
458   }
459 }
460
461 #endif /* FUNCTION_H */