1 /* Copyright (C) 2007-2010 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 /*
14  * Contains declarations of classes defined for a variety of DWARF objects.
15  */
16 
17 #ifndef ELFF_DWARF_DIE_H_
18 #define ELFF_DWARF_DIE_H_
19 
20 #include "dwarf_defs.h"
21 #include "elf_alloc.h"
22 
23 class ElfFile;
24 class DwarfCU;
25 
26 /* Encapsulates an object that wraps up a DIE, cached during
27  * ELF file parsing.
28  */
29 class DIEObject : public DwarfAllocBase {
30  public:
31   /* Constructs DIEObject intance.
32    * Param:
33    *  die - DIE represented with this instance.
34    *  parent_cu - Compilation unit this DIE belongs to.
35    *  parent_die - Parent DIE object for this DIE. This parameter can be NULL
36    *    only for compilation unit DIEs.
37    */
DIEObject(const Dwarf_DIE * die,DwarfCU * parent_cu,DIEObject * parent_die)38   DIEObject(const Dwarf_DIE* die, DwarfCU* parent_cu, DIEObject* parent_die)
39       : die_(die),
40         parent_cu_(parent_cu),
41         parent_die_(parent_die),
42         last_child_(NULL),
43         prev_sibling_(NULL) {
44   }
45 
46   /* Destructs DIEObject intance. */
47   ~DIEObject();
48 
49   /* Gets ELF file this DIE belongs to. */
50   ElfFile* elf_file() const;
51 
52   /* Gets DWARF tag (DW_TAG_Xxx) for the DIE represented with this instance. */
53   Dwarf_Tag get_tag() const;
54 
55   /* Gets the best name for this DIE.
56    * Some DIEs (such as inline routine DIEs) may have no DW_AT_name property,
57    * but may reference to another DIE that may contain DIE name. This method
58    * tries its best to get DIE name by iterating through different methods of
59    * naming the DIE.
60    * Return:
61    *  Name for this DIE, or NULL if it was not possible to find a relevant DIE
62    *  with DW_AT_name property.
63    */
64   const char* get_name() const;
65 
66   /* Gets DIE's attribute by its ID.
67    * Param:
68    *  at_id - ID (DW_AT_Xxx) of the attribute to get.
69    *  attr - Upon successful return contains requested attribute information.
70    * Return:
71    *  true on success, or false if attribute for the given ID doesn't exist
72    *  in the DIE's attribute list.
73    */
74   bool get_attrib(Dwarf_At at, DIEAttrib* attr) const;
75 
76   /* Gets the leaf DIE object containing given address.
77    * See DwarfCU::get_leaf_die_for_address() for method details.
78    * See DIEObject::contains_address() for implementation details.
79    */
80   DIEObject* get_leaf_for_address(Elf_Xword address);
81 
82   /* Finds a DIE object for the given die in the branch starting with
83    * this DIE object.
84    */
85   DIEObject* find_die_object(const Dwarf_DIE* die_to_find);
86 
87   /* Dumps this object to stdout.
88    * Param:
89    *  only_this - If true, only this object will be dumped. If this parameter
90    *    is false, all the childs and siblings of this object will be dumped
91    *    along with this object.
92    */
93   void dump(bool only_this) const;
94 
95  protected:
96   /* Checks if this DIE object containing given address.
97    * Template param:
98    *  AddrType - Type of compilation unin address (4, or 8 bytes), defined by
99    *    address_size field of the CU header. Must be Elf_Xword for 8 bytes
100    *    address, or Elf_Word for 4 bytes address.
101    * Param:
102    *  address - Address ti check.
103    * Return:
104    *  True, if this DIE address ranges (including low_pc, high_pc attributes)
105    *  contain given address, or false otherwise.
106    */
107   template <typename AddrType>
108   bool contains_address(Elf_Xword address);
109 
110   /* Advances to the DIE's property list.
111    * Param:
112    *  at_abbr - Upon successful return contains a pointer to the beginning of
113    *    DIE attribute abbreviation list. This parameter can be NULL, if the
114    *    caller is not interested in attribute abbreviation list for this DIE.
115    *  tag - Upon successful return contains DIE's tag. This parameter can be
116    *    NULL, if the caller is not interested in the tag value for this DIE.
117    * Return:
118    *  Pointer to the beginning of the DIE attribute list in mapped .debug_info
119    *  section on success, or NULL on failure.
120    */
121   const Elf_Byte* advance(const Dwarf_Abbr_AT** at_abbr, Dwarf_Tag* tag) const;
122 
123  public:
124   /* Gets DIE represented with this instance. */
die()125   const Dwarf_DIE* die() const {
126     return die_;
127   }
128 
129   /* Gets compilation unit this DIE belongs to. */
parent_cu()130   DwarfCU* parent_cu() const {
131     return parent_cu_;
132   }
133 
134   /* Gets parent DIE object for this die. */
parent_die()135   DIEObject* parent_die() const {
136     return parent_die_;
137   }
138 
139   /* Gets last child object in the list of this DIE's childs. NOTE: for better
140    * performace the list is created in reverse order (relatively to the order,
141    * in which children DIEs have been discovered).
142    */
last_child()143   DIEObject* last_child() const {
144     return last_child_;
145   }
146 
147   /* Links next child to the list of this DIE childs. */
link_child(DIEObject * child)148   void link_child(DIEObject* child) {
149     last_child_ = child;
150   }
151 
152   /* Gets previous sibling of this DIE in the parent's DIE object list. */
prev_sibling()153   DIEObject* prev_sibling() const {
154     return prev_sibling_;
155   }
156 
157   /* Links next sibling to the list of this DIE siblings. */
link_sibling(DIEObject * sibl)158   void link_sibling(DIEObject* sibl) {
159     prev_sibling_ = sibl;
160   }
161 
162   /* Checks if this DIE object represents a CU DIE.
163    * We relay here on the fact that only CU DIE objects have no parent
164    * DIE objects.
165    */
is_cu_die()166   bool is_cu_die() const {
167     return parent_die_ == NULL;
168   }
169 
170   /* Gets this DIE level in the branch.
171    * DIE level defines DIE's distance from the CU DIE in the branch this DIE
172    * belongs to. In other words, DIE level defines how many parent DIEs exist
173    * between this DIE, and the CU DIE. For instance, the CU DIE has level 0,
174    * a subroutine a() in this compilation unit has level 1, a soubroutine b(),
175    * that has been inlined into subroutine a() will have level 2, a try/catch
176    * block in the inlined subroutine b() will have level 3, and so on.
177    */
get_level()178   Elf_Word get_level() const {
179     return parent_die_ != NULL ? parent_die_->get_level() + 1 : 0;
180   }
181 
182  protected:
183   /* DIE that is represented with this instance. */
184   const Dwarf_DIE*  die_;
185 
186   /* Compilation unit this DIE belongs to. */
187   DwarfCU*          parent_cu_;
188 
189   /* Parent DIE object for this die. */
190   DIEObject*        parent_die_;
191 
192   /* Last child object in the list of this DIE's childs. NOTE: for better
193    * performace the list is created in reverse order (relatively to the order,
194    * in which children DIEs have been discovered).
195    */
196   DIEObject*        last_child_;
197 
198   /* Previous sibling of this DIE in the parent's DIE object list. */
199   DIEObject*        prev_sibling_;
200 };
201 
202 #endif  // ELFF_DWARF_DIE_H_
203