/* Copyright (C) 2007-2010 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ /* * Contains declarations of classes defined for a variety of DWARF objects. */ #ifndef ELFF_DWARF_DIE_H_ #define ELFF_DWARF_DIE_H_ #include "dwarf_defs.h" #include "elf_alloc.h" class ElfFile; class DwarfCU; /* Encapsulates an object that wraps up a DIE, cached during * ELF file parsing. */ class DIEObject : public DwarfAllocBase { public: /* Constructs DIEObject intance. * Param: * die - DIE represented with this instance. * parent_cu - Compilation unit this DIE belongs to. * parent_die - Parent DIE object for this DIE. This parameter can be NULL * only for compilation unit DIEs. */ DIEObject(const Dwarf_DIE* die, DwarfCU* parent_cu, DIEObject* parent_die) : die_(die), parent_cu_(parent_cu), parent_die_(parent_die), last_child_(NULL), prev_sibling_(NULL) { } /* Destructs DIEObject intance. */ ~DIEObject(); /* Gets ELF file this DIE belongs to. */ ElfFile* elf_file() const; /* Gets DWARF tag (DW_TAG_Xxx) for the DIE represented with this instance. */ Dwarf_Tag get_tag() const; /* Gets the best name for this DIE. * Some DIEs (such as inline routine DIEs) may have no DW_AT_name property, * but may reference to another DIE that may contain DIE name. This method * tries its best to get DIE name by iterating through different methods of * naming the DIE. * Return: * Name for this DIE, or NULL if it was not possible to find a relevant DIE * with DW_AT_name property. */ const char* get_name() const; /* Gets DIE's attribute by its ID. * Param: * at_id - ID (DW_AT_Xxx) of the attribute to get. * attr - Upon successful return contains requested attribute information. * Return: * true on success, or false if attribute for the given ID doesn't exist * in the DIE's attribute list. */ bool get_attrib(Dwarf_At at, DIEAttrib* attr) const; /* Gets the leaf DIE object containing given address. * See DwarfCU::get_leaf_die_for_address() for method details. * See DIEObject::contains_address() for implementation details. */ DIEObject* get_leaf_for_address(Elf_Xword address); /* Finds a DIE object for the given die in the branch starting with * this DIE object. */ DIEObject* find_die_object(const Dwarf_DIE* die_to_find); /* Dumps this object to stdout. * Param: * only_this - If true, only this object will be dumped. If this parameter * is false, all the childs and siblings of this object will be dumped * along with this object. */ void dump(bool only_this) const; protected: /* Checks if this DIE object containing given address. * Template param: * AddrType - Type of compilation unin address (4, or 8 bytes), defined by * address_size field of the CU header. Must be Elf_Xword for 8 bytes * address, or Elf_Word for 4 bytes address. * Param: * address - Address ti check. * Return: * True, if this DIE address ranges (including low_pc, high_pc attributes) * contain given address, or false otherwise. */ template <typename AddrType> bool contains_address(Elf_Xword address); /* Advances to the DIE's property list. * Param: * at_abbr - Upon successful return contains a pointer to the beginning of * DIE attribute abbreviation list. This parameter can be NULL, if the * caller is not interested in attribute abbreviation list for this DIE. * tag - Upon successful return contains DIE's tag. This parameter can be * NULL, if the caller is not interested in the tag value for this DIE. * Return: * Pointer to the beginning of the DIE attribute list in mapped .debug_info * section on success, or NULL on failure. */ const Elf_Byte* advance(const Dwarf_Abbr_AT** at_abbr, Dwarf_Tag* tag) const; public: /* Gets DIE represented with this instance. */ const Dwarf_DIE* die() const { return die_; } /* Gets compilation unit this DIE belongs to. */ DwarfCU* parent_cu() const { return parent_cu_; } /* Gets parent DIE object for this die. */ DIEObject* parent_die() const { return parent_die_; } /* Gets last child object in the list of this DIE's childs. NOTE: for better * performace the list is created in reverse order (relatively to the order, * in which children DIEs have been discovered). */ DIEObject* last_child() const { return last_child_; } /* Links next child to the list of this DIE childs. */ void link_child(DIEObject* child) { last_child_ = child; } /* Gets previous sibling of this DIE in the parent's DIE object list. */ DIEObject* prev_sibling() const { return prev_sibling_; } /* Links next sibling to the list of this DIE siblings. */ void link_sibling(DIEObject* sibl) { prev_sibling_ = sibl; } /* Checks if this DIE object represents a CU DIE. * We relay here on the fact that only CU DIE objects have no parent * DIE objects. */ bool is_cu_die() const { return parent_die_ == NULL; } /* Gets this DIE level in the branch. * DIE level defines DIE's distance from the CU DIE in the branch this DIE * belongs to. In other words, DIE level defines how many parent DIEs exist * between this DIE, and the CU DIE. For instance, the CU DIE has level 0, * a subroutine a() in this compilation unit has level 1, a soubroutine b(), * that has been inlined into subroutine a() will have level 2, a try/catch * block in the inlined subroutine b() will have level 3, and so on. */ Elf_Word get_level() const { return parent_die_ != NULL ? parent_die_->get_level() + 1 : 0; } protected: /* DIE that is represented with this instance. */ const Dwarf_DIE* die_; /* Compilation unit this DIE belongs to. */ DwarfCU* parent_cu_; /* Parent DIE object for this die. */ DIEObject* parent_die_; /* Last child object in the list of this DIE's childs. NOTE: for better * performace the list is created in reverse order (relatively to the order, * in which children DIEs have been discovered). */ DIEObject* last_child_; /* Previous sibling of this DIE in the parent's DIE object list. */ DIEObject* prev_sibling_; }; #endif // ELFF_DWARF_DIE_H_