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
23class ElfFile;
24class DwarfCU;
25
26/* Encapsulates an object that wraps up a DIE, cached during
27 * ELF file parsing.
28 */
29class 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   */
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. */
125  const Dwarf_DIE* die() const {
126    return die_;
127  }
128
129  /* Gets compilation unit this DIE belongs to. */
130  DwarfCU* parent_cu() const {
131    return parent_cu_;
132  }
133
134  /* Gets parent DIE object for this 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   */
143  DIEObject* last_child() const {
144    return last_child_;
145  }
146
147  /* Links next child to the list of this DIE childs. */
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. */
153  DIEObject* prev_sibling() const {
154    return prev_sibling_;
155  }
156
157  /* Links next sibling to the list of this DIE siblings. */
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   */
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   */
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