1 //===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H
10 #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H
11 
12 #include "SymbolFileDWARF.h"
13 #include "llvm/ADT/SmallVector.h"
14 
15 #include "DWARFAttribute.h"
16 #include "DWARFBaseDIE.h"
17 #include "DWARFDebugRanges.h"
18 #include <map>
19 #include <optional>
20 #include <set>
21 #include <vector>
22 
23 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
24 
25 namespace lldb_private::plugin {
26 namespace dwarf {
27 class DWARFDeclContext;
28 
29 #define DIE_SIBLING_IDX_BITSIZE 31
30 
31 /// DWARFDebugInfoEntry objects assume that they are living in one big
32 /// vector and do pointer arithmetic on their this pointers. Don't
33 /// pass them by value. Due to the way they are constructed in a
34 /// std::vector, we cannot delete the copy constructor.
35 class DWARFDebugInfoEntry {
36 public:
37   typedef std::vector<DWARFDebugInfoEntry> collection;
38   typedef collection::iterator iterator;
39   typedef collection::const_iterator const_iterator;
40 
DWARFDebugInfoEntry()41   DWARFDebugInfoEntry()
42       : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0),
43         m_has_children(false) {}
44 
45   explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
46   bool operator==(const DWARFDebugInfoEntry &rhs) const;
47   bool operator!=(const DWARFDebugInfoEntry &rhs) const;
48 
49   void BuildFunctionAddressRangeTable(DWARFUnit *cu,
50                                       DWARFDebugAranges *debug_aranges) const;
51 
52   bool Extract(const DWARFDataExtractor &data, const DWARFUnit *cu,
53                lldb::offset_t *offset_ptr);
54 
55   using Recurse = DWARFBaseDIE::Recurse;
56   DWARFAttributes GetAttributes(DWARFUnit *cu,
57                                 Recurse recurse = Recurse::yes) const {
58     DWARFAttributes attrs;
59     GetAttributes(cu, attrs, recurse, 0 /* curr_depth */);
60     return attrs;
61   }
62 
63   dw_offset_t
64   GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr,
65                     DWARFFormValue &formValue,
66                     dw_offset_t *end_attr_offset_ptr = nullptr,
67                     bool check_specification_or_abstract_origin = false) const;
68 
69   const char *GetAttributeValueAsString(
70       const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value,
71       bool check_specification_or_abstract_origin = false) const;
72 
73   uint64_t GetAttributeValueAsUnsigned(
74       const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
75       bool check_specification_or_abstract_origin = false) const;
76 
77   std::optional<uint64_t> GetAttributeValueAsOptionalUnsigned(
78       const DWARFUnit *cu, const dw_attr_t attr,
79       bool check_specification_or_abstract_origin = false) const;
80 
81   DWARFDIE GetAttributeValueAsReference(
82       const DWARFUnit *cu, const dw_attr_t attr,
83       bool check_specification_or_abstract_origin = false) const;
84 
85   uint64_t GetAttributeValueAsAddress(
86       const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value,
87       bool check_specification_or_abstract_origin = false) const;
88 
89   dw_addr_t
90   GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
91                      bool check_specification_or_abstract_origin = false) const;
92 
93   bool GetAttributeAddressRange(
94       const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
95       uint64_t fail_value,
96       bool check_specification_or_abstract_origin = false) const;
97 
98   DWARFRangeList GetAttributeAddressRanges(
99       DWARFUnit *cu, bool check_hi_lo_pc,
100       bool check_specification_or_abstract_origin = false) const;
101 
102   const char *GetName(const DWARFUnit *cu) const;
103 
104   const char *GetMangledName(const DWARFUnit *cu,
105                              bool substitute_name_allowed = true) const;
106 
107   const char *GetPubname(const DWARFUnit *cu) const;
108 
109   bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name,
110                             const char *&mangled, DWARFRangeList &rangeList,
111                             std::optional<int> &decl_file,
112                             std::optional<int> &decl_line,
113                             std::optional<int> &decl_column,
114                             std::optional<int> &call_file,
115                             std::optional<int> &call_line,
116                             std::optional<int> &call_column,
117                             DWARFExpressionList *frame_base = nullptr) const;
118 
119   const llvm::DWARFAbbreviationDeclaration *
120   GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const;
121 
122   lldb::offset_t GetFirstAttributeOffset() const;
123 
Tag()124   dw_tag_t Tag() const { return m_tag; }
125 
IsNULL()126   bool IsNULL() const { return m_abbr_idx == 0; }
127 
GetOffset()128   dw_offset_t GetOffset() const { return m_offset; }
129 
HasChildren()130   bool HasChildren() const { return m_has_children; }
131 
SetHasChildren(bool b)132   void SetHasChildren(bool b) { m_has_children = b; }
133 
134   // We know we are kept in a vector of contiguous entries, so we know
135   // our parent will be some index behind "this".
GetParent()136   DWARFDebugInfoEntry *GetParent() {
137     return m_parent_idx > 0 ? this - m_parent_idx : nullptr;
138   }
GetParent()139   const DWARFDebugInfoEntry *GetParent() const {
140     return m_parent_idx > 0 ? this - m_parent_idx : nullptr;
141   }
142   // We know we are kept in a vector of contiguous entries, so we know
143   // our sibling will be some index after "this".
GetSibling()144   DWARFDebugInfoEntry *GetSibling() {
145     return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr;
146   }
GetSibling()147   const DWARFDebugInfoEntry *GetSibling() const {
148     return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr;
149   }
150   // We know we are kept in a vector of contiguous entries, so we know
151   // we don't need to store our child pointer, if we have a child it will
152   // be the next entry in the list...
GetFirstChild()153   DWARFDebugInfoEntry *GetFirstChild() {
154     return HasChildren() ? this + 1 : nullptr;
155   }
GetFirstChild()156   const DWARFDebugInfoEntry *GetFirstChild() const {
157     return HasChildren() ? this + 1 : nullptr;
158   }
159 
160   DWARFDeclContext GetDWARFDeclContext(DWARFUnit *cu) const;
161 
162   DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu) const;
163   DWARFDIE GetParentDeclContextDIE(DWARFUnit *cu,
164                                    const DWARFAttributes &attributes) const;
165 
SetSiblingIndex(uint32_t idx)166   void SetSiblingIndex(uint32_t idx) { m_sibling_idx = idx; }
SetParentIndex(uint32_t idx)167   void SetParentIndex(uint32_t idx) { m_parent_idx = idx; }
168 
169   // This function returns true if the variable scope is either
170   // global or (file-static). It will return false for static variables
171   // that are local to a function, as they have local scope.
172   bool IsGlobalOrStaticScopeVariable() const;
173 
174 protected:
175   static DWARFDeclContext
176   GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu);
177 
178   // Up to 2TB offset within the .debug_info/.debug_types
179   dw_offset_t m_offset : DW_DIE_OFFSET_MAX_BITSIZE;
180   // How many to subtract from "this" to get the parent. If zero this die has no
181   // parent
182   dw_offset_t m_parent_idx : 64 - DW_DIE_OFFSET_MAX_BITSIZE;
183   // How many to add to "this" to get the sibling.
184   // If it is zero, then the DIE doesn't have children,
185   // or the DWARF claimed it had children but the DIE
186   // only contained a single NULL terminating child.
187   uint32_t m_sibling_idx : 31, m_has_children : 1;
188   uint16_t m_abbr_idx = 0;
189   /// A copy of the DW_TAG value so we don't have to go through the compile
190   /// unit abbrev table
191   dw_tag_t m_tag = llvm::dwarf::DW_TAG_null;
192 
193 private:
194   void GetAttributes(DWARFUnit *cu, DWARFAttributes &attrs, Recurse recurse,
195                      uint32_t curr_depth) const;
196 };
197 } // namespace dwarf
198 } // namespace lldb_private::plugin
199 
200 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H
201