dwarfWalker.h

Go to the documentation of this file.
00001 
00002 #if !defined(_dwarf_walker_h_)
00003 #define _dwarf_walker_h_
00004 
00005 #include "elf.h"
00006 #include "libelf.h"
00007 #include "libdwarf.h"
00008 #include <stack>
00009 #include <vector>
00010 #include <string>
00011 #include <set>
00012 #include "dyntypes.h"
00013 #include "VariableLocation.h"
00014 #include "Type.h"
00015 
00016 namespace Dyninst {
00017 namespace SymtabAPI {
00018 
00019 // A restructuring of walkDwarvenTree
00020 
00021    class Symtab;
00022    class Module;
00023    class Object;
00024    class Function;
00025    class typeCommon;
00026    class typeEnum;
00027    class fieldListType;
00028    class typeCollection;
00029    class Type;
00030 
00031 class DwarfWalker {
00032    typedef std::vector<std::pair<Address, Address> > range_set_t;
00033    typedef boost::shared_ptr<std::vector<std::pair<Address, Address> > > range_set_ptr;
00034 
00035    struct Contexts {
00036       struct Context {
00037          Function *func;
00038          typeCommon *commonBlock;
00039          typeEnum *enumType;
00040          fieldListType *enclosure;
00041          bool parseSibling;
00042          bool parseChild;
00043          Dwarf_Die entry;
00044          Dwarf_Die specEntry;
00045          Dwarf_Die abstractEntry;
00046          Dwarf_Off offset;
00047          Dwarf_Half tag;
00048          Address base;
00049          range_set_ptr ranges;
00050          Context() :
00051             func(NULL), commonBlock(NULL),
00052             enumType(NULL), enclosure(NULL),
00053             parseSibling(true), parseChild(true), 
00054             base(0) {};
00055       };
00056       
00057       std::stack<Context> c;
00058       void push();
00059       void pop();
00060       Function *curFunc() { return c.top().func; }
00061       typeCommon * curCommon() { return c.top().commonBlock; }
00062       typeEnum *curEnum() { return c.top().enumType; }
00063       fieldListType *curEnclosure() { return c.top().enclosure; }
00064       bool parseSibling() { return c.top().parseSibling; }
00065       bool parseChild() { return c.top().parseChild; }
00066       Dwarf_Die entry() { return c.top().entry; }
00067       Dwarf_Die specEntry() { return c.top().specEntry; }
00068       Dwarf_Die abstractEntry() { return c.top().abstractEntry; }
00069       Dwarf_Off offset() { return c.top().offset; }
00070       Dwarf_Half tag() { return c.top().tag; }
00071       Address base() { return c.top().base; }
00072       range_set_ptr ranges() { return c.top().ranges; }
00073 
00074       void setFunc(Function *f); 
00075       void setCommon(typeCommon *tc) { c.top().commonBlock = tc; }
00076       void setEnum(typeEnum *e) { c.top().enumType = e; }
00077       void setEnclosure(fieldListType *f) { c.top().enclosure = f; }
00078       void setParseSibling(bool p) { c.top().parseSibling = p; }
00079       void setParseChild(bool p) { c.top().parseChild = p; }
00080       void setEntry(Dwarf_Die e) { c.top().entry = e; }
00081       void setSpecEntry(Dwarf_Die e) { c.top().specEntry = e; }
00082       void setAbstractEntry(Dwarf_Die e) { c.top().abstractEntry = e; }
00083       void setOffset(Dwarf_Off o) { c.top().offset = o; }
00084       void setTag(Dwarf_Tag t) { c.top().tag = t; }
00085       void setBase(Address a) { c.top().base = a; }
00086       void setRange(std::pair<Address, Address> range) { 
00087          if (!c.top().ranges)
00088             c.top().ranges = range_set_ptr(new std::vector<std::pair<Address, Address> >);
00089          c.top().ranges->push_back(range);
00090       }
00091       void clearRanges() {
00092          c.top().ranges = range_set_ptr();
00093       }
00094       void clearFunc();
00095    };
00096 
00097   public:
00098    typedef enum {
00099       NoError
00100 
00101    } Error;
00102 
00103    DwarfWalker(Symtab *symtab, Dwarf_Debug &dbg);
00104 
00105    ~DwarfWalker();
00106 
00107    bool parse();
00108 
00109   private:
00110    bool setup(Dwarf_Die dieEntry,
00111               Dwarf_Off modOffset,
00112               Address lowpc);
00113 
00114    // Takes current debug state as represented by dbg_;
00115    bool parseModule(Module *&fixUnknownMod);
00116    
00117    // Non-recursive version of parse
00118    // A Context must be provided as an _input_ to this function,
00119    // whereas parse creates a context.
00120    bool parse_int(Dwarf_Die entry, bool parseSiblings);
00121 
00122    bool parseSubprogram();
00123    bool parseLexicalBlock();
00124    bool parseCommonBlock();
00125    bool parseConstant();
00126    bool parseVariable();
00127    bool parseFormalParam();
00128    bool parseBaseType();
00129    bool parseTypedef();
00130    bool parseArray();
00131    bool parseSubrange();
00132    bool parseEnum();
00133    bool parseInheritance();
00134    bool parseStructUnionClass();
00135    bool parseEnumEntry();
00136    bool parseMember();
00137    bool parseConstPackedVolatile();
00138    bool parseTypeReferences();
00139 
00140    // These vary as we parse the tree
00141    Function *curFunc() { return contexts_.curFunc(); }
00142    typeCommon *curCommon() { return contexts_.curCommon(); }
00143    typeEnum *curEnum() { return contexts_.curEnum(); }
00144    fieldListType *curEnclosure() { return contexts_.curEnclosure(); }
00145 
00146    void setFunc(Function *f) { contexts_.setFunc(f); }
00147    void setCommon(typeCommon *c) { contexts_.setCommon(c); }
00148    void setEnum(typeEnum *e) { contexts_.setEnum(e); }
00149    void setEnclosure(fieldListType *f) { contexts_.setEnclosure(f); }
00150 
00151    // This is a handy scratch space that is cleared for each parse. 
00152    std::string &curName() { return name_; }
00153    bool nameDefined() { return name_ != ""; }
00154    // These are invariant across a parse
00155    Object *obj(); 
00156    Symtab *symtab() { return symtab_; }
00157    Module *mod() { return mod_; }
00158    std::vector<std::string> &srcFiles() { return srcFiles_; }
00159    typeCollection *tc() { return tc_; }
00160    Dwarf_Debug &dbg() { return dbg_; }
00161 
00162    bool parseSibling() { return contexts_.parseSibling(); }
00163    bool parseChild() { return contexts_.parseChild(); }
00164    void setParseSibling(bool p) { return contexts_.setParseSibling(p); }
00165    void setParseChild(bool p) { return contexts_.setParseChild(p); }
00166 
00167    Dwarf_Half tag() { return contexts_.tag(); }
00168    Dwarf_Off offset() { return contexts_.offset(); }
00169    Dwarf_Die entry() { return contexts_.entry(); }
00170    // For functions and variables with a separate specification, a 
00171    // pointer to that spec. For everyone else, this points to entry
00172    Dwarf_Die specEntry() { return contexts_.specEntry(); }
00173    // We might be able to fold this into specEntry and call it
00174    // "authoritativeEntry" or something. 
00175    Dwarf_Die abstractEntry() { return contexts_.abstractEntry(); }
00176    void clearRanges() { contexts_.clearRanges(); }
00177    bool hasRanges() { return contexts_.ranges() != NULL; }
00178    range_set_t::iterator ranges_begin() { return contexts_.ranges()->begin(); }
00179    range_set_t::iterator ranges_end() { return contexts_.ranges()->end(); }
00180 
00181    // A printable ID for a particular entry
00182    unsigned long id() { return (unsigned long) (offset() - compile_offset); }
00183 
00184    void setEntry(Dwarf_Die entry);
00185    void setSpecEntry(Dwarf_Die se) { contexts_.setSpecEntry(se); }
00186    void setAbstractEntry(Dwarf_Die se) { contexts_.setAbstractEntry(se); }
00187    void setTag(Dwarf_Half tag) { contexts_.setTag(tag); }
00188    void setOffset(Dwarf_Off offset) { contexts_.setOffset(offset); }
00189    void setRange(std::pair<Address, Address> range) { contexts_.setRange(range); }
00190 
00191    bool buildSrcFiles(Dwarf_Die entry);
00192    bool hasDeclaration(bool &decl);
00193    bool findTag();
00194    bool findOffset();
00195    bool handleAbstractOrigin(bool &isAbstractOrigin);
00196    bool handleSpecification(bool &hasSpec);
00197    bool findFuncName();
00198    bool findFunction(bool &found);
00199    bool findBaseAddr();
00200    bool getFrameBase();
00201    bool getReturnType(bool hasSpecification, Type *&returnType);
00202    bool addFuncToContainer(Type *returnType);
00203    bool findType(Type *&, bool defaultToVoid);
00204    bool getLineInformation(Dwarf_Unsigned &variableLineNo,
00205                            bool &hasLineNumber,
00206                            std::string &filename); 
00207    bool findName(std::string &);
00208    void removeFortranUnderscore(std::string &);
00209    bool findSize(unsigned &size);
00210    bool findVisibility(visibility_t &visibility);
00211    bool findValue(long &value, bool &valid);
00212    bool fixName(std::string &name, Type *type);
00213    bool fixBitFields(std::vector<VariableLocation> &locs, long &size);
00214    bool findEntryToUse(Dwarf_Half attr, bool &found, Dwarf_Die &entry);
00215    bool parseSubrangeAUX(Dwarf_Die entry,
00216                          std::string &lobound,
00217                          std::string &hibound);
00218    bool decodeLocationList(Dwarf_Half attr,
00219                            Address *initialVal,
00220                            std::vector<VariableLocation> &locs);
00221    bool checkForConstantOrExpr(Dwarf_Half attr,
00222                    Dwarf_Attribute &locationAttribute,
00223                    bool &constant,
00224                    bool &expr,
00225                    Dwarf_Half &form);
00226    bool findConstant(Dwarf_Half attr, Address &value);
00227    bool findConstantWithForm(Dwarf_Attribute &attr,
00228                                Dwarf_Half form,
00229                                Address &value);
00230    bool decodeConstantLocation(Dwarf_Attribute &attr, Dwarf_Half form, 
00231                                std::vector<VariableLocation> &locs);
00232    bool constructConstantVariableLocation(Address value,
00233                                           std::vector<VariableLocation> &locs);
00234    typeArray *parseMultiDimensionalArray(Dwarf_Die firstRange,
00235                                          Type *elementType);
00236    bool decipherBound(Dwarf_Attribute boundAttribute, std::string &name);
00237 
00238    bool decodeExpression(Dwarf_Attribute &attr,
00239              std::vector<VariableLocation> &locs);
00240 
00241    bool decodeLocationListForStaticOffsetOrAddress(Dwarf_Locdesc **locationList, 
00242                                                    Dwarf_Signed listLength, 
00243                                                    std::vector<VariableLocation>& locs, 
00244                                                    Address * initialStackValue = NULL);
00245    void deallocateLocationList(Dwarf_Locdesc *locationList,
00246                                Dwarf_Signed listLength);
00247    void deallocateLocationList(Dwarf_Locdesc **locationList,
00248                                Dwarf_Signed listLength);
00249 
00250    // A BG-Q XLC hack; clear any function-level enclosure from the context stack
00251    // to handle a bug where they don't finish off functions. 
00252    void clearFunc() { contexts_.clearFunc(); }
00253 
00254    // Track which enclosure (array, struct, class, etc.) contains the current
00255    // dwarf parsee
00256    std::map<Dwarf_Off, fieldListType *> enclosureMap;
00257    // Header-only functions get multiple parsed.
00258    std::set<Function *> parsedFuncs;
00259    
00260    Contexts contexts_;
00261 
00262    Dwarf_Debug &dbg_;
00263    Module *mod_;
00264    Symtab *symtab_;
00265    std::vector<std::string> srcFiles_;
00266    typeCollection *tc_;
00267 
00268    std::string name_;
00269 
00270    // Per-module info
00271    Address modLow;
00272    Address modHigh;
00273    Dwarf_Unsigned cu_header_length;
00274    Dwarf_Half version;
00275    Dwarf_Unsigned abbrev_offset;
00276    Dwarf_Half addr_size;
00277    Dwarf_Half offset_size;
00278    Dwarf_Half extension_size;
00279    Dwarf_Sig8 signature;
00280    Dwarf_Unsigned typeoffset;
00281    Dwarf_Unsigned next_cu_header;
00282 
00283    // For debugging purposes; to match dwarfdump's output,
00284    // we need to subtract a "header overall offset". 
00285    Dwarf_Off compile_offset;
00286 
00287 };
00288 
00289 };
00290 };
00291 
00292 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1