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