Compile fix after removing deprecated SymtabAPI methods.
[dyninst.git] / dyninstAPI / src / parse-cfg.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: parse-cfg.h,v 1.37 2008/09/03 06:08:44 jaw Exp $
32
33 #ifndef IMAGE_FUNC_H
34 #define IMAGE_FUNC_H
35
36 #include <string>
37 #include "common/h/Vector.h"
38 #include "common/h/Types.h"
39 #include "common/h/Pair.h"
40 #include "common/h/arch.h" // instruction
41 #include "codeRange.h"
42 #include "parRegion.h"
43 #include "common/h/Dictionary.h"
44 #include "symtabAPI/h/Symbol.h"
45 #include "bitArray.h"
46 #include "InstructionCache.h"
47 #include <set>
48
49 #include "Parsing.h"
50
51 #include "symtabAPI/h/Function.h"
52
53 #include <queue>
54
55 using namespace Dyninst;
56
57 class pdmodule;
58
59 class parse_block;
60 class image_edge;
61
62 class parse_block : public codeRange, public ParseAPI::Block  {
63     friend class parse_func;
64     friend class DynCFGFactory;
65  private:
66     parse_block(ParseAPI::CodeObject *, ParseAPI::CodeRegion*, Address);
67  public:
68     parse_block(parse_func*,ParseAPI::CodeRegion*,Address);
69     ~parse_block();
70
71     // just pass through to Block
72     Address firstInsnOffset() const;
73     Address lastInsnOffset() const;
74     Address endOffset() const;
75     Address getSize() const;
76
77     // cfg access & various predicates 
78     bool isShared() const { return containingFuncs() > 1; }
79     bool isExitBlock();
80     bool isCallBlock();
81     bool isEntryBlock(parse_func * f) const;
82     parse_func *getEntryFunc() const;  // func starting with this bock
83
84     bool unresolvedCF() const { return unresolvedCF_; }
85     bool abruptEnd() const { return abruptEnd_; }
86     void setUnresolvedCF(bool newVal);
87     void setAbruptEnd(bool newVal) { abruptEnd_ = newVal; }
88
89     // misc utility
90     int id() const { return blockNumber_; }
91     void debugPrint();
92     image *img();
93     
94     // Find callees
95     parse_func *getCallee();
96     // Returns the address of our callee (if we're a call block, of course)
97     std::pair<bool, Address> callTarget();
98
99     // instrumentation-related
100     bool needsRelocation() const { return needsRelocation_; }
101     void markAsNeedingRelocation() { needsRelocation_ = true; }
102
103     // codeRange implementation
104     void *getPtrToInstruction(Address addr) const;
105     Address get_address() const { return firstInsnOffset(); }
106     unsigned get_size() const { return getSize(); }
107
108     // etc.
109     struct compare {
110         bool operator()(parse_block * const &b1,
111                         parse_block * const &b2) const {
112             if(b1->firstInsnOffset() < b2->firstInsnOffset())
113                 return true;
114             if(b2->firstInsnOffset() < b1->firstInsnOffset())
115                 return false;
116
117             // XXX the remainder is debugging, and should be removed
118             if(b1 != b2)
119                 fprintf(stderr,"error: two blocks (%p,%p) at 0x%lx\n",
120                     b1,b2,b1->firstInsnOffset());
121
122             assert(b1 == b2);
123             return false;
124         }
125     };
126     typedef std::set<parse_block *, parse_block::compare> blockSet;
127
128 #if defined(cap_liveness)
129     const bitArray &getLivenessIn(parse_func * context);
130     // This is copied from the union of all successor blocks
131     const bitArray getLivenessOut(parse_func * context);
132 #endif
133
134     typedef std::map<Offset, InstructionAPI::Instruction::Ptr> Insns;
135     // The provided parameter is a magic offset to add to each instruction's
136     // address; we do this to avoid a copy when getting Insns from block_instances
137     void getInsns(Insns &instances, Address offset = 0);
138
139  private:
140     bool needsRelocation_;
141     int blockNumber_;
142
143     bool unresolvedCF_;
144     bool abruptEnd_;
145
146 #if defined(cap_liveness)
147     /* Liveness analysis variables */
148     /** gen registers */
149     
150     bitArray use; // Registers used by instructions within the block
151     bitArray def; // Registers defined by instructions within the block
152     bitArray in;  // Summarized input liveness; we calculate output on the fly
153  public:
154     static InstructionCache cachedLivenessInfo;
155     
156  private:
157     void summarizeBlockLivenessInfo(parse_func * context);
158     // Returns true if any information changed; false otherwise
159     bool updateBlockLivenessInfo(parse_func * context);
160 #endif
161
162
163 };
164
165 inline Address 
166 parse_block::firstInsnOffset() const {
167     return ParseAPI::Block::start(); 
168 }
169 inline Address 
170 parse_block::lastInsnOffset() const {
171     return ParseAPI::Block::lastInsnAddr();
172 }
173 inline Address 
174 parse_block::endOffset() const {
175     return ParseAPI::Block::end();
176 }
177 inline Address 
178 parse_block::getSize() const {
179     return ParseAPI::Block::size();
180 }
181
182 void checkIfRelocatable (instruction insn, bool &canBeRelocated);
183
184 class image_edge : public ParseAPI::Edge {
185     friend class parse_block;
186  public:
187     image_edge(parse_block *source, 
188                parse_block *target, 
189                EdgeTypeEnum type) :
190     ParseAPI::Edge(source,target,type)
191    { }
192
193     // MSVC++ 2003 does not properly support covariant return types
194     // in overloaded methods
195 #if !defined _MSC_VER || _MSC_VER > 1310 
196    virtual parse_block * src() const { return (parse_block*)_source; }
197    virtual parse_block * trg() const { return (parse_block*)_target; }
198 #endif
199
200    const char * getTypeString();
201 };
202
203 #include "ast.h"
204 class parse_func_registers {
205  public:
206   std::set<Register> generalPurposeRegisters;
207   std::set<Register> floatingPointRegisters;
208   std::set<Register> specialPurposeRegisters;
209 };
210
211 class parse_func : public ParseAPI::Function
212 {
213    enum UnresolvedCF {
214       UNSET_CF,
215       HAS_UNRESOLVED_CF,
216       NO_UNRESOLVED_CF
217    };
218
219   friend class DynCFGFactory;
220   friend class DynParseCallback;
221   public:
222    /* Annotatable requires a default constructor */
223    parse_func() { }
224   public:
225    parse_func(SymtabAPI::Function *func, 
226         pdmodule *m, 
227         image *i, 
228         ParseAPI::CodeObject * obj,
229         ParseAPI::CodeRegion * reg,
230         InstructionSource * isrc,
231         FuncSource src);
232
233    ~parse_func();
234
235    SymtabAPI::Function* getSymtabFunction() const{
236       return  func_; 
237    }    
238
239    /*** Function naming ***/
240    const string &symTabName() const { 
241        return func_->getFirstSymbol()->getMangledName();
242    }
243    const string &prettyName() const {
244        return func_->getFirstSymbol()->getPrettyName();
245    }
246    const string &typedName() const {
247        return func_->getFirstSymbol()->getTypedName();
248    }
249    const vector<string> &symTabNameVector() const {
250        return func_->getAllMangledNames();
251    }
252    const vector<string> &prettyNameVector() const {
253        return func_->getAllPrettyNames();
254    }
255    const vector<string> &typedNameVector() const {
256        return func_->getAllTypedNames();
257    }
258    void copyNames(parse_func *duplicate);
259    // return true if the name is new (and therefore added)
260    bool addSymTabName(std::string name, bool isPrimary = false);
261    bool addPrettyName(std::string name, bool isPrimary = false);
262    bool addTypedName(std::string name, bool isPrimary = false);
263
264    /*** Location queries ***/
265    Address getOffset() const;
266    Address getPtrOffset() const;
267    unsigned getSymTabSize() const;
268    Address getEndOffset(); // May trigger parsing
269
270    void *getPtrToInstruction(Address addr) const;
271
272    /*** Debugging output operators ***/
273    ostream & operator<<(ostream &s) const;
274    friend ostream &operator<<(ostream &os, parse_func &f);
275
276    /*** misc. accessors ***/
277    pdmodule *pdmod() const { return mod_;}
278    image *img() const { return image_; }
279    void changeModule(pdmodule *mod);
280
281    ////////////////////////////////////////////////
282    // CFG and other function body methods
283    ////////////////////////////////////////////////
284
285    bool makesNoCalls();
286
287    ////////////////////////////////////////////////
288    // Instpoints!
289    ////////////////////////////////////////////////
290
291    // Initiate parsing on this function
292    bool parse();
293  
294    const pdvector<image_parRegion*> &parRegions();
295
296    bool isInstrumentable();
297    bool hasUnresolvedCF();
298
299    // ----------------------------------------------------------------------
300
301
302    ///////////////////////////////////////////////////
303    // Mutable function code, used for hybrid analysis
304    ///////////////////////////////////////////////////
305    
306    void getReachableBlocks
307    ( const std::set<parse_block*> &exceptBlocks, // input
308      const std::list<parse_block*> &seedBlocks, // input
309      std::set<parse_block*> &reachableBlocks ); // output
310    ParseAPI::FuncReturnStatus init_retstatus() const; // only call on defensive binaries
311    void setinit_retstatus(ParseAPI::FuncReturnStatus rs); //also sets retstatus
312    bool hasWeirdInsns() { return hasWeirdInsns_; } // true if we stopped the 
313                                 // parse at a weird instruction (e.g., arpl)
314    void setHasWeirdInsns(bool wi);
315    void setPrevBlocksUnresolvedCF(int newVal) { prevBlocksUnresolvedCF_ = newVal; };
316    int getPrevBlocksUnresolvedCF() const { return prevBlocksUnresolvedCF_; };
317
318
319    // ----------------------------------------------------------------------
320
321
322    ////////////////////////////////////////////////
323    // Misc
324    ////////////////////////////////////////////////
325
326     struct compare {
327         bool operator()(parse_func * const &f1,
328                         parse_func * const &f2) const {
329             return (f1->getOffset() < f2->getOffset());
330         }
331     };
332
333 #if defined(arch_x86) || defined(arch_x86_64)
334    bool isTrueCallInsn(const instruction insn);
335 #endif
336
337 #if defined(arch_power)
338    bool savesReturnAddr() const { return ppc_saves_return_addr_; }
339 #endif
340
341    bool containsSharedBlocks() const { return containsSharedBlocks_; }
342
343    parse_block * entryBlock();
344
345    /****** OpenMP Parsing Functions *******/
346    std::string calcParentFunc(const parse_func * imf, pdvector<image_parRegion *> & pR);
347    void parseOMP(image_parRegion * parReg, parse_func * parentFunc, int & currentSectionNum);
348    void parseOMPSectFunc(parse_func * parentFunc);
349    void parseOMPFunc(bool hasLoop);
350    bool parseOMPParent(image_parRegion * iPar, int desiredNum, int & currentSectionNum);
351    void addRegion(image_parRegion * iPar) { parRegionsList.push_back(iPar); }
352    bool OMPparsed() { return OMPparsed_; }
353    /****************************************/
354    bool isPLTFunction();
355
356    std::set<Register> * usedGPRs() { calcUsedRegs(); return &(usedRegisters->generalPurposeRegisters);}
357    std::set<Register> * usedFPRs() { calcUsedRegs(); return &(usedRegisters->floatingPointRegisters);}
358
359    bool isLeafFunc();
360
361    bool writesFPRs(unsigned level = 0);
362    bool writesSPRs(unsigned level = 0);
363
364
365 #if defined(cap_liveness)
366    void invalidateLiveness() { livenessCalculated_ = false; }
367    void calcBlockLevelLiveness();
368 #endif
369
370    const SymtabAPI::Function *func() const { return func_; }
371
372  private:
373    void calcUsedRegs();/* Does one time calculation of registers used in a function, if called again
374                           it just refers to the stored values and returns that */
375
376    ///////////////////// Basic func info
377    SymtabAPI::Function *func_;                  /* pointer to the underlying symtab Function */
378
379    pdmodule *mod_;              /* pointer to file that defines func. */
380    image *image_;
381    bool OMPparsed_;              /* Set true in parseOMPFunc */
382
383    /////  Variables for liveness Analysis
384    enum regUseState { unknown, used, unused };
385    parse_func_registers * usedRegisters;
386    regUseState containsFPRWrites_;   // floating point registers
387    regUseState containsSPRWrites_;   // stack pointer registers
388
389    ///////////////////// CFG and function body
390    bool containsSharedBlocks_;  // True if one or more blocks in this
391                                 // function are shared with another function.
392
393    //  OpenMP (and other parallel language) support
394    pdvector<image_parRegion*> parRegionsList; /* vector of all parallel regions within function */
395     void addParRegion(Address begin, Address end, parRegType t);
396    // End OpenMP support
397
398    bool hasWeirdInsns_;            // true if we stopped the parse at a 
399                                                                            // weird instruction (e.g., arpl)
400    int prevBlocksUnresolvedCF_; // num func blocks when calculated
401
402    // Some functions are known to be unparesable by name
403    bool isInstrumentableByFunctionName();
404    UnresolvedCF unresolvedCF_;
405
406    ParseAPI::FuncReturnStatus init_retstatus_;
407
408    // Architecture specific data
409    bool o7_live;
410    bool ppc_saves_return_addr_;
411
412 #if defined(cap_liveness)
413    bool livenessCalculated_;
414 #endif
415    bool isPLTFunction_;
416 };
417
418 typedef parse_func *ifuncPtr;
419
420 struct ifuncCmp
421 {
422     int operator()( const ifuncPtr &f1, const ifuncPtr &f2 ) const
423     {
424         if( f1->getOffset() > f2->getOffset() )
425             return 1;
426         if( f1->getOffset() < f2->getOffset() )
427             return -1;
428         return 0;
429     }
430 };
431
432 inline Address 
433 parse_func::getOffset() const {
434     return ParseAPI::Function::addr();
435 }
436 inline Address 
437 parse_func::getPtrOffset() const {
438     return func_->getFirstSymbol()->getPtrOffset();
439 }
440 inline unsigned 
441 parse_func::getSymTabSize() const { 
442     return func_->getFirstSymbol()->getSize();
443 }
444
445
446
447 #endif /* FUNCTION_H */