More gcc 4.8 fixes.
[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             base(0) {};
56       };
57       
58       std::stack<Context> c;
59       void push();
60       void pop();
61       FunctionBase *curFunc() { return c.top().func; }
62       typeCommon * curCommon() { return c.top().commonBlock; }
63       typeEnum *curEnum() { return c.top().enumType; }
64       fieldListType *curEnclosure() { return c.top().enclosure; }
65       bool parseSibling() { return c.top().parseSibling; }
66       bool parseChild() { return c.top().parseChild; }
67       Dwarf_Die entry() { return c.top().entry; }
68       Dwarf_Die specEntry() { return c.top().specEntry; }
69       Dwarf_Die abstractEntry() { return c.top().abstractEntry; }
70       Dwarf_Off offset() { return c.top().offset; }
71       Dwarf_Half tag() { return c.top().tag; }
72       Address base() { return c.top().base; }
73       range_set_ptr ranges() { return c.top().ranges; }
74
75       void setFunc(FunctionBase *f); 
76       void setCommon(typeCommon *tc) { c.top().commonBlock = tc; }
77       void setEnum(typeEnum *e) { c.top().enumType = e; }
78       void setEnclosure(fieldListType *f) { c.top().enclosure = f; }
79       void setParseSibling(bool p) { c.top().parseSibling = p; }
80       void setParseChild(bool p) { c.top().parseChild = p; }
81       void setEntry(Dwarf_Die e) { c.top().entry = e; }
82       void setSpecEntry(Dwarf_Die e) { c.top().specEntry = e; }
83       void setAbstractEntry(Dwarf_Die e) { c.top().abstractEntry = e; }
84       void setOffset(Dwarf_Off o) { c.top().offset = o; }
85       void setTag(Dwarf_Tag t) { c.top().tag = t; }
86       void setBase(Address a) { c.top().base = a; }
87       void setRange(std::pair<Address, Address> range) { 
88          if (range.first >= range.second)
89             return;
90          if (!c.top().ranges)
91             c.top().ranges = range_set_ptr(new std::vector<std::pair<Address, Address> >);
92          c.top().ranges->push_back(range);
93       }
94       void clearRanges() {
95          c.top().ranges = range_set_ptr();
96       }
97       void clearFunc();
98    };
99
100   public:
101    typedef enum {
102       NoError
103
104    } Error;
105
106    DwarfWalker(Symtab *symtab, Dwarf_Debug &dbg);
107
108    ~DwarfWalker();
109
110    bool parse();
111
112   private:
113    bool setup(Dwarf_Die dieEntry,
114               Dwarf_Off modOffset,
115               Address lowpc);
116
117    // Takes current debug state as represented by dbg_;
118    bool parseModule(Module *&fixUnknownMod);
119    
120    // Non-recursive version of parse
121    // A Context must be provided as an _input_ to this function,
122    // whereas parse creates a context.
123    bool parse_int(Dwarf_Die entry, bool parseSiblings);
124
125    enum inline_t {
126       NormalFunc,
127       InlinedFunc
128    };
129
130    bool parseSubprogram(inline_t func_type);
131    bool parseLexicalBlock();
132    bool parseRangeTypes();
133    bool parseCommonBlock();
134    bool parseConstant();
135    bool parseVariable();
136    bool parseFormalParam();
137    bool parseBaseType();
138    bool parseTypedef();
139    bool parseArray();
140    bool parseSubrange();
141    bool parseEnum();
142    bool parseInheritance();
143    bool parseStructUnionClass();
144    bool parseEnumEntry();
145    bool parseMember();
146    bool parseConstPackedVolatile();
147    bool parseTypeReferences();
148    bool parseHighPCLowPC();
149    
150
151    // These vary as we parse the tree
152    FunctionBase *curFunc() { return contexts_.curFunc(); }
153    typeCommon *curCommon() { return contexts_.curCommon(); }
154    typeEnum *curEnum() { return contexts_.curEnum(); }
155    fieldListType *curEnclosure() { return contexts_.curEnclosure(); }
156
157    void setFunc(FunctionBase *f) { contexts_.setFunc(f); }
158    void setCommon(typeCommon *c) { contexts_.setCommon(c); }
159    void setEnum(typeEnum *e) { contexts_.setEnum(e); }
160    void setEnclosure(fieldListType *f) { contexts_.setEnclosure(f); }
161
162    // This is a handy scratch space that is cleared for each parse. 
163    std::string &curName() { return name_; }
164    bool isMangledName() { return is_mangled_name_; }
165    void setMangledName(bool b) { is_mangled_name_ = b; }
166    bool nameDefined() { return name_ != ""; }
167    // These are invariant across a parse
168    Object *obj(); 
169    Symtab *symtab() { return symtab_; }
170    Module *mod() { return mod_; }
171    std::vector<std::string> &srcFiles() { return srcFiles_; }
172    typeCollection *tc() { return tc_; }
173    Dwarf_Debug &dbg() { return dbg_; }
174
175    bool parseSibling() { return contexts_.parseSibling(); }
176    bool parseChild() { return contexts_.parseChild(); }
177    void setParseSibling(bool p) { return contexts_.setParseSibling(p); }
178    void setParseChild(bool p) { return contexts_.setParseChild(p); }
179
180    Dwarf_Half tag() { return contexts_.tag(); }
181    Dwarf_Off offset() { return contexts_.offset(); }
182    Dwarf_Die entry() { return contexts_.entry(); }
183    // For functions and variables with a separate specification, a 
184    // pointer to that spec. For everyone else, this points to entry
185    Dwarf_Die specEntry() { return contexts_.specEntry(); }
186    // We might be able to fold this into specEntry and call it
187    // "authoritativeEntry" or something. 
188    Dwarf_Die abstractEntry() { return contexts_.abstractEntry(); }
189    void clearRanges() { contexts_.clearRanges(); }
190    bool hasRanges() { return contexts_.ranges() != NULL; }
191    size_t rangesSize() { return contexts_.ranges()->size(); }
192    range_set_t::iterator ranges_begin() { return contexts_.ranges()->begin(); }
193    range_set_t::iterator ranges_end() { return contexts_.ranges()->end(); }
194
195    // A printable ID for a particular entry
196    unsigned long id() { return (unsigned long) (offset() - compile_offset); }
197
198    void setEntry(Dwarf_Die entry);
199    void setSpecEntry(Dwarf_Die se) { contexts_.setSpecEntry(se); }
200    void setAbstractEntry(Dwarf_Die se) { contexts_.setAbstractEntry(se); }
201    void setTag(Dwarf_Half tag) { contexts_.setTag(tag); }
202    void setOffset(Dwarf_Off offset) { contexts_.setOffset(offset); }
203    void setRange(std::pair<Address, Address> range) { contexts_.setRange(range); }
204
205    bool parseCallsite();
206    bool buildSrcFiles(Dwarf_Die entry);
207    bool hasDeclaration(bool &decl);
208    bool findTag();
209    bool findOffset();
210    bool handleAbstractOrigin(bool &isAbstractOrigin);
211    bool handleSpecification(bool &hasSpec);
212    bool findFuncName();
213    bool findBaseAddr();
214    bool setFunctionFromRange(inline_t func_type);
215    bool getFrameBase();
216    bool getReturnType(bool hasSpecification, Type *&returnType);
217    bool addFuncToContainer(Type *returnType);
218    bool findType(Type *&, bool defaultToVoid);
219    bool getLineInformation(Dwarf_Unsigned &variableLineNo,
220                            bool &hasLineNumber,
221                            std::string &filename); 
222    bool findName(std::string &);
223    void removeFortranUnderscore(std::string &);
224    bool findSize(unsigned &size);
225    bool findVisibility(visibility_t &visibility);
226    bool findValue(long &value, bool &valid);
227    bool fixName(std::string &name, Type *type);
228    bool fixBitFields(std::vector<VariableLocation> &locs, long &size);
229    bool findEntryToUse(Dwarf_Half attr, bool &found, Dwarf_Die &entry);
230    bool parseSubrangeAUX(Dwarf_Die entry,
231                          std::string &lobound,
232                          std::string &hibound);
233    bool decodeLocationList(Dwarf_Half attr,
234                            Address *initialVal,
235                            std::vector<VariableLocation> &locs);
236    bool checkForConstantOrExpr(Dwarf_Half attr,
237                                Dwarf_Attribute &locationAttribute,
238                                bool &constant,
239                                bool &expr,
240                                Dwarf_Half &form);
241    bool findString(Dwarf_Half attr, std::string &str);
242    bool findConstant(Dwarf_Half attr, Address &value);
243    bool findConstantWithForm(Dwarf_Attribute &attr,
244                                Dwarf_Half form,
245                                Address &value);
246    bool decodeConstantLocation(Dwarf_Attribute &attr, Dwarf_Half form, 
247                                std::vector<VariableLocation> &locs);
248    bool constructConstantVariableLocation(Address value,
249                                           std::vector<VariableLocation> &locs);
250    typeArray *parseMultiDimensionalArray(Dwarf_Die firstRange,
251                                          Type *elementType);
252    bool decipherBound(Dwarf_Attribute boundAttribute, std::string &name);
253
254    bool decodeExpression(Dwarf_Attribute &attr,
255                          std::vector<VariableLocation> &locs);
256
257    bool decodeLocationListForStaticOffsetOrAddress(Dwarf_Locdesc **locationList, 
258                                                    Dwarf_Signed listLength, 
259                                                    std::vector<VariableLocation>& locs, 
260                                                    Address * initialStackValue = NULL);
261    void deallocateLocationList(Dwarf_Locdesc *locationList,
262                                Dwarf_Signed listLength);
263    void deallocateLocationList(Dwarf_Locdesc **locationList,
264                                Dwarf_Signed listLength);
265
266    // A BG-Q XLC hack; clear any function-level enclosure from the context stack
267    // to handle a bug where they don't finish off functions. 
268    void clearFunc() { contexts_.clearFunc(); }
269
270    // Track which enclosure (array, struct, class, etc.) contains the current
271    // dwarf parsee
272    std::map<Dwarf_Off, fieldListType *> enclosureMap;
273    // Header-only functions get multiple parsed.
274    std::set<FunctionBase *> parsedFuncs;
275    
276    Contexts contexts_;
277
278    Dwarf_Debug &dbg_;
279    Module *mod_;
280    Symtab *symtab_;
281    std::vector<std::string> srcFiles_;
282    typeCollection *tc_;
283
284    std::string name_;
285    bool is_mangled_name_;
286
287    // Per-module info
288    Address modLow;
289    Address modHigh;
290    Dwarf_Unsigned cu_header_length;
291    Dwarf_Half version;
292    Dwarf_Unsigned abbrev_offset;
293    Dwarf_Half addr_size;
294    Dwarf_Half offset_size;
295    Dwarf_Half extension_size;
296    Dwarf_Sig8 signature;
297    Dwarf_Unsigned typeoffset;
298    Dwarf_Unsigned next_cu_header;
299
300    // For debugging purposes; to match dwarfdump's output,
301    // we need to subtract a "header overall offset". 
302    Dwarf_Off compile_offset;
303
304 };
305
306 };
307 };
308
309 #endif