Fix vpadd decoding. Clean up control flow target logic and shared pointer constructio...
[dyninst.git] / symtabAPI / src / dwarfWalker.h
1
2 #if !defined(_dwarf_walker_h_)
3 #define _dwarf_walker_h_
4
5 #include "elf.h"
6 #include "libelf.h"
7 #include "libdwarf.h"
8 #include <stack>
9 #include <vector>
10 #include <string>
11 #include <set>
12 #include "dyntypes.h"
13 #include "VariableLocation.h"
14 #include "Type.h"
15
16 namespace Dyninst {
17 namespace SymtabAPI {
18
19 // A restructuring of walkDwarvenTree
20
21    class Symtab;
22    class Module;
23    class Object;
24    class Function;
25    class FunctionBase;
26    class typeCommon;
27    class typeEnum;
28    class fieldListType;
29    class typeCollection;
30    class Type;
31
32 class DwarfWalker {
33    typedef std::vector<std::pair<Address, Address> > range_set_t;
34    typedef boost::shared_ptr<std::vector<std::pair<Address, Address> > > range_set_ptr;
35
36    struct Contexts {
37       struct Context {
38          FunctionBase *func;
39          typeCommon *commonBlock;
40          typeEnum *enumType;
41          fieldListType *enclosure;
42          bool parseSibling;
43          bool parseChild;
44          Dwarf_Die entry;
45          Dwarf_Die specEntry;
46          Dwarf_Die abstractEntry;
47          Dwarf_Off offset;
48          Dwarf_Half tag;
49          Address base;
50          range_set_ptr ranges;
51          Context() :
52             func(NULL), commonBlock(NULL),
53             enumType(NULL), enclosure(NULL),
54             parseSibling(true), parseChild(true), 
55             entry(NULL), specEntry(NULL), abstractEntry(NULL),
56             offset(0), tag(0), base(0) {};
57       };
58       
59       std::stack<Context> c;
60       void push();
61       void pop();
62       FunctionBase *curFunc() { return c.top().func; }
63       typeCommon * curCommon() { return c.top().commonBlock; }
64       typeEnum *curEnum() { return c.top().enumType; }
65       fieldListType *curEnclosure() { return c.top().enclosure; }
66       bool parseSibling() { return c.top().parseSibling; }
67       bool parseChild() { return c.top().parseChild; }
68       Dwarf_Die entry() { return c.top().entry; }
69       Dwarf_Die specEntry() { return c.top().specEntry; }
70       Dwarf_Die abstractEntry() { return c.top().abstractEntry; }
71       Dwarf_Off offset() { return c.top().offset; }
72       Dwarf_Half tag() { return c.top().tag; }
73       Address base() { return c.top().base; }
74       range_set_ptr ranges() { return c.top().ranges; }
75
76       void setFunc(FunctionBase *f); 
77       void setCommon(typeCommon *tc) { c.top().commonBlock = tc; }
78       void setEnum(typeEnum *e) { c.top().enumType = e; }
79       void setEnclosure(fieldListType *f) { c.top().enclosure = f; }
80       void setParseSibling(bool p) { c.top().parseSibling = p; }
81       void setParseChild(bool p) { c.top().parseChild = p; }
82       void setEntry(Dwarf_Die e) { c.top().entry = e; }
83       void setSpecEntry(Dwarf_Die e) { c.top().specEntry = e; }
84       void setAbstractEntry(Dwarf_Die e) { c.top().abstractEntry = e; }
85       void setOffset(Dwarf_Off o) { c.top().offset = o; }
86       void setTag(Dwarf_Tag t) { c.top().tag = t; }
87       void setBase(Address a) { c.top().base = a; }
88       void setRange(std::pair<Address, Address> range) { 
89          if (range.first >= range.second)
90             return;
91          if (!c.top().ranges)
92             c.top().ranges = range_set_ptr(new std::vector<std::pair<Address, Address> >);
93          c.top().ranges->push_back(range);
94       }
95       void clearRanges() {
96          c.top().ranges = range_set_ptr();
97       }
98       void clearFunc();
99    };
100
101    struct ContextGuard {
102      Contexts& c;
103      ContextGuard(Contexts& c): c(c) { c.push(); }
104      ~ContextGuard() { c.pop(); }
105    };
106
107   public:
108    typedef enum {
109       NoError
110
111    } Error;
112
113    DwarfWalker(Symtab *symtab, Dwarf_Debug &dbg);
114
115    ~DwarfWalker();
116
117    bool parse();
118
119   private:
120    bool setup(Dwarf_Die dieEntry,
121               Dwarf_Off modOffset,
122               Address lowpc);
123
124    // Takes current debug state as represented by dbg_;
125    bool parseModule(Dwarf_Bool is_info, Module *&fixUnknownMod);
126    
127    // Non-recursive version of parse
128    // A Context must be provided as an _input_ to this function,
129    // whereas parse creates a context.
130    bool parse_int(Dwarf_Die entry, bool parseSiblings);
131
132    enum inline_t {
133       NormalFunc,
134       InlinedFunc
135    };
136
137    bool parseSubprogram(inline_t func_type);
138    bool parseLexicalBlock();
139    bool parseRangeTypes();
140    bool parseCommonBlock();
141    bool parseConstant();
142    bool parseVariable();
143    bool parseFormalParam();
144    bool parseBaseType();
145    bool parseTypedef();
146    bool parseArray();
147    bool parseSubrange();
148    bool parseEnum();
149    bool parseInheritance();
150    bool parseStructUnionClass();
151    bool parseEnumEntry();
152    bool parseMember();
153    bool parseConstPackedVolatile();
154    bool parseTypeReferences();
155    bool parseHighPCLowPC();
156    
157
158    // These vary as we parse the tree
159    FunctionBase *curFunc() { return contexts_.curFunc(); }
160    typeCommon *curCommon() { return contexts_.curCommon(); }
161    typeEnum *curEnum() { return contexts_.curEnum(); }
162    fieldListType *curEnclosure() { return contexts_.curEnclosure(); }
163
164    void setFunc(FunctionBase *f) { contexts_.setFunc(f); }
165    void setCommon(typeCommon *c) { contexts_.setCommon(c); }
166    void setEnum(typeEnum *e) { contexts_.setEnum(e); }
167    void setEnclosure(fieldListType *f) { contexts_.setEnclosure(f); }
168
169    // This is a handy scratch space that is cleared for each parse. 
170    std::string &curName() { return name_; }
171    bool isMangledName() { return is_mangled_name_; }
172    void setMangledName(bool b) { is_mangled_name_ = b; }
173    bool nameDefined() { return name_ != ""; }
174    // These are invariant across a parse
175    Object *obj(); 
176    Symtab *symtab() { return symtab_; }
177    Module *mod() { return mod_; }
178    std::vector<const char*> &srcFiles() { return srcFiles_; }
179    typeCollection *tc() { return tc_; }
180    Dwarf_Debug &dbg() { return dbg_; }
181
182    bool parseSibling() { return contexts_.parseSibling(); }
183    bool parseChild() { return contexts_.parseChild(); }
184    void setParseSibling(bool p) { return contexts_.setParseSibling(p); }
185    void setParseChild(bool p) { return contexts_.setParseChild(p); }
186
187    Dwarf_Half tag() { return contexts_.tag(); }
188    Dwarf_Off offset() { return contexts_.offset(); }
189    Dwarf_Die entry() { return contexts_.entry(); }
190    // For functions and variables with a separate specification, a 
191    // pointer to that spec. For everyone else, this points to entry
192    Dwarf_Die specEntry() { return contexts_.specEntry(); }
193    // We might be able to fold this into specEntry and call it
194    // "authoritativeEntry" or something. 
195    Dwarf_Die abstractEntry() { return contexts_.abstractEntry(); }
196    void clearRanges() { contexts_.clearRanges(); }
197    bool hasRanges() { return contexts_.ranges() != NULL; }
198    size_t rangesSize() { return contexts_.ranges()->size(); }
199    range_set_t::iterator ranges_begin() { return contexts_.ranges()->begin(); }
200    range_set_t::iterator ranges_end() { return contexts_.ranges()->end(); }
201
202    // A printable ID for a particular entry
203    unsigned long id() { return (unsigned long) (offset() - compile_offset); }
204
205    void setEntry(Dwarf_Die entry);
206    void setSpecEntry(Dwarf_Die se) { contexts_.setSpecEntry(se); }
207    void setAbstractEntry(Dwarf_Die se) { contexts_.setAbstractEntry(se); }
208    void setTag(Dwarf_Half tag) { contexts_.setTag(tag); }
209    void setOffset(Dwarf_Off offset) { contexts_.setOffset(offset); }
210    void setRange(std::pair<Address, Address> range) { contexts_.setRange(range); }
211
212    bool parseCallsite();
213    bool buildSrcFiles(Dwarf_Die entry);
214    bool hasDeclaration(bool &decl);
215    bool findTag();
216    bool findOffset();
217    bool handleAbstractOrigin(bool &isAbstractOrigin);
218    bool handleSpecification(bool &hasSpec);
219    bool findFuncName();
220    bool findBaseAddr();
221    bool setFunctionFromRange(inline_t func_type);
222    bool getFrameBase();
223    bool getReturnType(bool hasSpecification, Type *&returnType);
224    bool addFuncToContainer(Type *returnType);
225    bool findType(Type *&, bool defaultToVoid);
226    bool findAnyType(Dwarf_Attribute typeAttribute,
227                     Dwarf_Bool is_info, Type *&type);
228    bool findDieOffset(Dwarf_Attribute attr, Dwarf_Off &offset);
229    bool getLineInformation(Dwarf_Unsigned &variableLineNo,
230                            bool &hasLineNumber,
231                            std::string &filename); 
232    bool findDieName(Dwarf_Die die, std::string &);
233    bool findName(std::string &);
234    void removeFortranUnderscore(std::string &);
235    bool findSize(unsigned &size);
236    bool findVisibility(visibility_t &visibility);
237    bool findValue(long &value, bool &valid);
238    bool fixName(std::string &name, Type *type);
239    bool fixBitFields(std::vector<VariableLocation> &locs, long &size);
240    bool findEntryToUse(Dwarf_Half attr, bool &found, Dwarf_Die &entry);
241    bool parseSubrangeAUX(Dwarf_Die entry,
242                          std::string &lobound,
243                          std::string &hibound);
244    bool decodeLocationList(Dwarf_Half attr,
245                            Address *initialVal,
246                            std::vector<VariableLocation> &locs);
247    bool checkForConstantOrExpr(Dwarf_Half attr,
248                                Dwarf_Attribute &locationAttribute,
249                                bool &constant,
250                                bool &expr,
251                                Dwarf_Half &form);
252    bool findString(Dwarf_Half attr, const char* &str);
253    bool findConstant(Dwarf_Half attr, Address &value);
254    bool findConstantWithForm(Dwarf_Attribute &attr,
255                                Dwarf_Half form,
256                                Address &value);
257    bool decodeConstantLocation(Dwarf_Attribute &attr, Dwarf_Half form, 
258                                std::vector<VariableLocation> &locs);
259    bool constructConstantVariableLocation(Address value,
260                                           std::vector<VariableLocation> &locs);
261    typeArray *parseMultiDimensionalArray(Dwarf_Die firstRange,
262                                          Type *elementType);
263    bool decipherBound(Dwarf_Attribute boundAttribute, Dwarf_Bool is_info,
264                       std::string &name);
265
266    bool decodeExpression(Dwarf_Attribute &attr,
267                          std::vector<VariableLocation> &locs);
268
269    bool decodeLocationListForStaticOffsetOrAddress(Dwarf_Locdesc **locationList, 
270                                                    Dwarf_Signed listLength, 
271                                                    std::vector<VariableLocation>& locs, 
272                                                    Address * initialStackValue = NULL);
273    void deallocateLocationList(Dwarf_Locdesc *locationList,
274                                Dwarf_Signed listLength);
275    void deallocateLocationList(Dwarf_Locdesc **locationList,
276                                Dwarf_Signed listLength);
277
278    // A BG-Q XLC hack; clear any function-level enclosure from the context stack
279    // to handle a bug where they don't finish off functions. 
280    void clearFunc() { contexts_.clearFunc(); }
281
282    // Header-only functions get multiple parsed.
283    std::set<FunctionBase *> parsedFuncs;
284    
285    Contexts contexts_;
286
287    Dwarf_Debug &dbg_;
288    Module *mod_;
289    Symtab *symtab_;
290    std::vector<const char*> srcFiles_;
291     char** srcFileList_;
292    typeCollection *tc_;
293
294    std::string name_;
295    bool is_mangled_name_;
296
297    // Per-module info
298    Address modLow;
299    Address modHigh;
300    Dwarf_Unsigned cu_header_length;
301    Dwarf_Half version;
302    Dwarf_Unsigned abbrev_offset;
303    Dwarf_Half addr_size;
304    Dwarf_Half offset_size;
305    Dwarf_Half extension_size;
306    Dwarf_Sig8 signature;
307    Dwarf_Unsigned typeoffset;
308    Dwarf_Unsigned next_cu_header;
309
310    // For debugging purposes; to match dwarfdump's output,
311    // we need to subtract a "header overall offset". 
312    Dwarf_Off compile_offset;
313
314    // Type IDs are just int, but Dwarf_Off is 64-bit and may be relative to
315    // either .debug_info or .debug_types.
316    dyn_hash_map<Dwarf_Off, typeId_t> info_type_ids_; // .debug_info offset -> id
317    dyn_hash_map<Dwarf_Off, typeId_t> types_type_ids_; // .debug_types offset -> id
318    typeId_t get_type_id(Dwarf_Off offset, bool is_info);
319    typeId_t type_id(); // get_type_id() for the current entry
320
321    // Map to connect DW_FORM_ref_sig8 to type IDs.
322    dyn_hash_map<uint64_t, typeId_t> sig8_type_ids_;
323    bool parseModuleSig8(Dwarf_Bool is_info);
324    void findAllSig8Types();
325    bool findSig8Type(Dwarf_Sig8 *signature, Type *&type);
326 };
327
328 };
329 };
330
331 #endif