DWARFDie.h revision 321369
1321369Sdim//===- DWARFDie.h -----------------------------------------------*- C++ -*-===//
2311116Sdim//
3311116Sdim//                     The LLVM Compiler Infrastructure
4311116Sdim//
5311116Sdim// This file is distributed under the University of Illinois Open Source
6311116Sdim// License. See LICENSE.TXT for details.
7311116Sdim//
8311116Sdim//===----------------------------------------------------------------------===//
9311116Sdim
10321369Sdim#ifndef LLVM_DEBUGINFO_DWARFDIE_H
11321369Sdim#define LLVM_DEBUGINFO_DWARFDIE_H
12311116Sdim
13321369Sdim#include "llvm/ADT/ArrayRef.h"
14321369Sdim#include "llvm/ADT/Optional.h"
15311544Sdim#include "llvm/ADT/iterator.h"
16311544Sdim#include "llvm/ADT/iterator_range.h"
17321369Sdim#include "llvm/BinaryFormat/Dwarf.h"
18321369Sdim#include "llvm/DebugInfo/DIContext.h"
19321369Sdim#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
20311116Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
21321369Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
22321369Sdim#include <cassert>
23321369Sdim#include <cstdint>
24321369Sdim#include <iterator>
25311116Sdim
26311116Sdimnamespace llvm {
27321369Sdim
28311116Sdimclass DWARFUnit;
29311116Sdimclass raw_ostream;
30321369Sdim
31311116Sdim//===----------------------------------------------------------------------===//
32311116Sdim/// Utility class that carries the DWARF compile/type unit and the debug info
33311116Sdim/// entry in an object.
34311116Sdim///
35311116Sdim/// When accessing information from a debug info entry we always need to DWARF
36311116Sdim/// compile/type unit in order to extract the info correctly as some information
37311116Sdim/// is relative to the compile/type unit. Prior to this class the DWARFUnit and
38311116Sdim/// the DWARFDebugInfoEntry was passed around separately and there was the
39311116Sdim/// possibility for error if the wrong DWARFUnit was used to extract a unit
40311116Sdim/// relative offset. This class helps to ensure that this doesn't happen and
41311116Sdim/// also simplifies the attribute extraction calls by not having to specify the
42311116Sdim/// DWARFUnit for each call.
43311116Sdimclass DWARFDie {
44321369Sdim  DWARFUnit *U = nullptr;
45321369Sdim  const DWARFDebugInfoEntry *Die = nullptr;
46321369Sdim
47311116Sdimpublic:
48321369Sdim  DWARFDie() = default;
49311116Sdim  DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry * D) : U(Unit), Die(D) {}
50321369Sdim
51311116Sdim  bool isValid() const { return U && Die; }
52311116Sdim  explicit operator bool() const { return isValid(); }
53311116Sdim  const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; }
54311116Sdim  DWARFUnit *getDwarfUnit() const { return U; }
55311116Sdim
56311116Sdim  /// Get the abbreviation declaration for this DIE.
57311116Sdim  ///
58311116Sdim  /// \returns the abbreviation declaration or NULL for null tags.
59311116Sdim  const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
60311116Sdim    assert(isValid() && "must check validity prior to calling");
61311116Sdim    return Die->getAbbreviationDeclarationPtr();
62311116Sdim  }
63311116Sdim
64311116Sdim  /// Get the absolute offset into the debug info or types section.
65311116Sdim  ///
66311116Sdim  /// \returns the DIE offset or -1U if invalid.
67311116Sdim  uint32_t getOffset() const {
68311116Sdim    assert(isValid() && "must check validity prior to calling");
69311116Sdim    return Die->getOffset();
70311116Sdim  }
71321369Sdim
72311116Sdim  dwarf::Tag getTag() const {
73311116Sdim    auto AbbrevDecl = getAbbreviationDeclarationPtr();
74311116Sdim    if (AbbrevDecl)
75311116Sdim      return AbbrevDecl->getTag();
76311116Sdim    return dwarf::DW_TAG_null;
77311116Sdim  }
78311116Sdim
79311116Sdim  bool hasChildren() const {
80311116Sdim    assert(isValid() && "must check validity prior to calling");
81311116Sdim    return Die->hasChildren();
82311116Sdim  }
83321369Sdim
84311116Sdim  /// Returns true for a valid DIE that terminates a sibling chain.
85311116Sdim  bool isNULL() const {
86311116Sdim    return getAbbreviationDeclarationPtr() == nullptr;
87311116Sdim  }
88321369Sdim
89311116Sdim  /// Returns true if DIE represents a subprogram (not inlined).
90311116Sdim  bool isSubprogramDIE() const;
91311116Sdim
92311116Sdim  /// Returns true if DIE represents a subprogram or an inlined subroutine.
93311116Sdim  bool isSubroutineDIE() const;
94311116Sdim
95311116Sdim  /// Get the parent of this DIE object.
96311116Sdim  ///
97311116Sdim  /// \returns a valid DWARFDie instance if this object has a parent or an
98311116Sdim  /// invalid DWARFDie instance if it doesn't.
99311116Sdim  DWARFDie getParent() const;
100321369Sdim
101311116Sdim  /// Get the sibling of this DIE object.
102311116Sdim  ///
103311116Sdim  /// \returns a valid DWARFDie instance if this object has a sibling or an
104311116Sdim  /// invalid DWARFDie instance if it doesn't.
105311116Sdim  DWARFDie getSibling() const;
106321369Sdim
107311116Sdim  /// Get the first child of this DIE object.
108311116Sdim  ///
109311116Sdim  /// \returns a valid DWARFDie instance if this object has children or an
110311116Sdim  /// invalid DWARFDie instance if it doesn't.
111311116Sdim  DWARFDie getFirstChild() const {
112311116Sdim    if (isValid() && Die->hasChildren())
113311116Sdim      return DWARFDie(U, Die + 1);
114311116Sdim    return DWARFDie();
115311116Sdim  }
116321369Sdim
117311116Sdim  /// Dump the DIE and all of its attributes to the supplied stream.
118311116Sdim  ///
119311116Sdim  /// \param OS the stream to use for output.
120311116Sdim  /// \param recurseDepth the depth to recurse to when dumping this DIE and its
121311116Sdim  /// children.
122311116Sdim  /// \param indent the number of characters to indent each line that is output.
123321369Sdim  void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0,
124321369Sdim            DIDumpOptions DumpOpts = DIDumpOptions()) const;
125321369Sdim
126311116Sdim  /// Extract the specified attribute from this DIE.
127311116Sdim  ///
128311116Sdim  /// Extract an attribute value from this DIE only. This call doesn't look
129311116Sdim  /// for the attribute value in any DW_AT_specification or
130311116Sdim  /// DW_AT_abstract_origin referenced DIEs.
131311116Sdim  ///
132311116Sdim  /// \param Attr the attribute to extract.
133311116Sdim  /// \returns an optional DWARFFormValue that will have the form value if the
134311116Sdim  /// attribute was successfully extracted.
135321369Sdim  Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
136321369Sdim
137321369Sdim  /// Extract the first value of any attribute in Attrs from this DIE.
138311116Sdim  ///
139321369Sdim  /// Extract the first attribute that matches from this DIE only. This call
140321369Sdim  /// doesn't look for the attribute value in any DW_AT_specification or
141321369Sdim  /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched
142321369Sdim  /// linearly in the order they are specified within Attrs.
143311116Sdim  ///
144321369Sdim  /// \param Attrs an array of DWARF attribute to look for.
145321369Sdim  /// \returns an optional that has a valid DWARFFormValue for the first
146321369Sdim  /// matching attribute in Attrs, or None if none of the attributes in Attrs
147321369Sdim  /// exist in this DIE.
148321369Sdim  Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const;
149321369Sdim
150321369Sdim  /// Extract the first value of any attribute in Attrs from this DIE and
151321369Sdim  /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced
152321369Sdim  /// DIEs.
153311116Sdim  ///
154321369Sdim  /// \param Attrs an array of DWARF attribute to look for.
155321369Sdim  /// \returns an optional that has a valid DWARFFormValue for the first
156321369Sdim  /// matching attribute in Attrs, or None if none of the attributes in Attrs
157321369Sdim  /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin
158321369Sdim  /// DIEs.
159321369Sdim  Optional<DWARFFormValue>
160321369Sdim  findRecursively(ArrayRef<dwarf::Attribute> Attrs) const;
161311116Sdim
162311116Sdim  /// Extract the specified attribute from this DIE as the referenced DIE.
163311116Sdim  ///
164311116Sdim  /// Regardless of the reference type, return the correct DWARFDie instance if
165311116Sdim  /// the attribute exists. The returned DWARFDie object might be from another
166311116Sdim  /// DWARFUnit, but that is all encapsulated in the new DWARFDie object.
167311116Sdim  ///
168311116Sdim  /// Extract an attribute value from this DIE only. This call doesn't look
169311116Sdim  /// for the attribute value in any DW_AT_specification or
170311116Sdim  /// DW_AT_abstract_origin referenced DIEs.
171311116Sdim  ///
172311116Sdim  /// \param Attr the attribute to extract.
173311116Sdim  /// \returns a valid DWARFDie instance if the attribute exists, or an invalid
174311116Sdim  /// DWARFDie object if it doesn't.
175311116Sdim  DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
176311116Sdim
177311116Sdim  /// Extract the range base attribute from this DIE as absolute section offset.
178311116Sdim  ///
179311116Sdim  /// This is a utility function that checks for either the DW_AT_rnglists_base
180311116Sdim  /// or DW_AT_GNU_ranges_base attribute.
181311116Sdim  ///
182311116Sdim  /// \returns anm optional absolute section offset value for the attribute.
183311116Sdim  Optional<uint64_t> getRangesBaseAttribute() const;
184321369Sdim
185311116Sdim  /// Get the DW_AT_high_pc attribute value as an address.
186311116Sdim  ///
187311116Sdim  /// In DWARF version 4 and later the high PC can be encoded as an offset from
188311116Sdim  /// the DW_AT_low_pc. This function takes care of extracting the value as an
189311116Sdim  /// address or offset and adds it to the low PC if needed and returns the
190311116Sdim  /// value as an optional in case the DIE doesn't have a DW_AT_high_pc
191311116Sdim  /// attribute.
192311116Sdim  ///
193311116Sdim  /// \param LowPC the low PC that might be needed to calculate the high PC.
194311116Sdim  /// \returns an optional address value for the attribute.
195311116Sdim  Optional<uint64_t> getHighPC(uint64_t LowPC) const;
196311116Sdim
197311116Sdim  /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
198311116Sdim  /// Returns true if both attributes are present.
199321369Sdim  bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
200321369Sdim                       uint64_t &SectionIndex) const;
201321369Sdim
202311116Sdim  /// Get the address ranges for this DIE.
203311116Sdim  ///
204311116Sdim  /// Get the hi/low PC range if both attributes are available or exrtracts the
205311116Sdim  /// non-contiguous address ranges from the DW_AT_ranges attribute.
206311116Sdim  ///
207311116Sdim  /// Extracts the range information from this DIE only. This call doesn't look
208311116Sdim  /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs.
209311116Sdim  ///
210311116Sdim  /// \returns a address range vector that might be empty if no address range
211311116Sdim  /// information is available.
212311116Sdim  DWARFAddressRangesVector getAddressRanges() const;
213321369Sdim
214311116Sdim  /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any
215311116Sdim  /// of its children.
216311116Sdim  ///
217311116Sdim  /// Get the hi/low PC range if both attributes are available or exrtracts the
218311116Sdim  /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE
219311116Sdim  /// and all children.
220311116Sdim  ///
221311116Sdim  /// \param Ranges the addres range vector to fill in.
222311116Sdim  void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const;
223321369Sdim
224311116Sdim  bool addressRangeContainsAddress(const uint64_t Address) const;
225321369Sdim
226311116Sdim  /// If a DIE represents a subprogram (or inlined subroutine), returns its
227311116Sdim  /// mangled name (or short name, if mangled is missing). This name may be
228311116Sdim  /// fetched from specification or abstract origin for this subprogram.
229311116Sdim  /// Returns null if no name is found.
230311116Sdim  const char *getSubroutineName(DINameKind Kind) const;
231321369Sdim
232311116Sdim  /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin
233311116Sdim  /// references if necessary. Returns null if no name is found.
234311116Sdim  const char *getName(DINameKind Kind) const;
235321369Sdim
236321369Sdim  /// Returns the declaration line (start line) for a DIE, assuming it specifies
237321369Sdim  /// a subprogram. This may be fetched from specification or abstract origin
238321369Sdim  /// for this subprogram by resolving DW_AT_sepcification or
239321369Sdim  /// DW_AT_abstract_origin references if necessary.
240321369Sdim  uint64_t getDeclLine() const;
241321369Sdim
242311116Sdim  /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
243311116Sdim  /// from DIE (or zeroes if they are missing). This function looks for
244311116Sdim  /// DW_AT_call attributes in this DIE only, it will not resolve the attribute
245311116Sdim  /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs.
246311116Sdim  /// \param CallFile filled in with non-zero if successful, zero if there is no
247311116Sdim  /// DW_AT_call_file attribute in this DIE.
248311116Sdim  /// \param CallLine filled in with non-zero if successful, zero if there is no
249311116Sdim  /// DW_AT_call_line attribute in this DIE.
250311116Sdim  /// \param CallColumn filled in with non-zero if successful, zero if there is
251311116Sdim  /// no DW_AT_call_column attribute in this DIE.
252321369Sdim  /// \param CallDiscriminator filled in with non-zero if successful, zero if
253321369Sdim  /// there is no DW_AT_GNU_discriminator attribute in this DIE.
254311116Sdim  void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
255321369Sdim                      uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
256311116Sdim
257321369Sdim  class attribute_iterator;
258321369Sdim
259321369Sdim  /// Get an iterator range to all attributes in the current DIE only.
260321369Sdim  ///
261321369Sdim  /// \returns an iterator range for the attributes of the current DIE.
262321369Sdim  iterator_range<attribute_iterator> attributes() const;
263321369Sdim
264311544Sdim  class iterator;
265321369Sdim
266311544Sdim  iterator begin() const;
267311544Sdim  iterator end() const;
268311544Sdim  iterator_range<iterator> children() const;
269311116Sdim};
270311116Sdim
271321369Sdimclass DWARFDie::attribute_iterator :
272321369Sdim    public iterator_facade_base<attribute_iterator, std::forward_iterator_tag,
273321369Sdim                                const DWARFAttribute> {
274321369Sdim  /// The DWARF DIE we are extracting attributes from.
275321369Sdim  DWARFDie Die;
276321369Sdim  /// The value vended to clients via the operator*() or operator->().
277321369Sdim  DWARFAttribute AttrValue;
278321369Sdim  /// The attribute index within the abbreviation declaration in Die.
279321369Sdim  uint32_t Index;
280321369Sdim
281321369Sdim  /// Update the attribute index and attempt to read the attribute value. If the
282321369Sdim  /// attribute is able to be read, update AttrValue and the Index member
283321369Sdim  /// variable. If the attribute value is not able to be read, an appropriate
284321369Sdim  /// error will be set if the Err member variable is non-NULL and the iterator
285321369Sdim  /// will be set to the end value so iteration stops.
286321369Sdim  void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I);
287321369Sdim
288321369Sdimpublic:
289321369Sdim  attribute_iterator() = delete;
290321369Sdim  explicit attribute_iterator(DWARFDie D, bool End);
291321369Sdim
292321369Sdim  attribute_iterator &operator++();
293321369Sdim  explicit operator bool() const { return AttrValue.isValid(); }
294321369Sdim  const DWARFAttribute &operator*() const { return AttrValue; }
295321369Sdim  bool operator==(const attribute_iterator &X) const { return Index == X.Index; }
296321369Sdim};
297321369Sdim
298311544Sdiminline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) {
299311544Sdim  return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() &&
300311544Sdim      LHS.getDwarfUnit() == RHS.getDwarfUnit();
301311544Sdim}
302311116Sdim
303311544Sdiminline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) {
304311544Sdim  return !(LHS == RHS);
305311544Sdim}
306311544Sdim
307311544Sdimclass DWARFDie::iterator : public iterator_facade_base<iterator,
308311544Sdim                                                      std::forward_iterator_tag,
309311544Sdim                                                      const DWARFDie> {
310311544Sdim  DWARFDie Die;
311311544Sdim  void skipNull() {
312311544Sdim    if (Die && Die.isNULL())
313311544Sdim      Die = DWARFDie();
314311544Sdim  }
315311544Sdimpublic:
316311544Sdim  iterator() = default;
317321369Sdim
318311544Sdim  explicit iterator(DWARFDie D) : Die(D) {
319311544Sdim    // If we start out with only a Null DIE then invalidate.
320311544Sdim    skipNull();
321311544Sdim  }
322321369Sdim
323311544Sdim  iterator &operator++() {
324311544Sdim    Die = Die.getSibling();
325311544Sdim    // Don't include the NULL die when iterating.
326311544Sdim    skipNull();
327311544Sdim    return *this;
328311544Sdim  }
329321369Sdim
330311544Sdim  explicit operator bool() const { return Die.isValid(); }
331311544Sdim  const DWARFDie &operator*() const { return Die; }
332311544Sdim  bool operator==(const iterator &X) const { return Die == X.Die; }
333311544Sdim};
334311544Sdim
335311544Sdim// These inline functions must follow the DWARFDie::iterator definition above
336311544Sdim// as they use functions from that class.
337311544Sdiminline DWARFDie::iterator DWARFDie::begin() const {
338311544Sdim  return iterator(getFirstChild());
339311544Sdim}
340311544Sdim
341311544Sdiminline DWARFDie::iterator DWARFDie::end() const {
342311544Sdim  return iterator();
343311544Sdim}
344311544Sdim
345311544Sdiminline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
346311544Sdim  return make_range(begin(), end());
347311544Sdim}
348311544Sdim
349311116Sdim} // end namespace llvm
350311116Sdim
351321369Sdim#endif // LLVM_DEBUGINFO_DWARFDIE_H
352