1 | //===- DWARFAbbreviationDeclaration.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 LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H |
10 | #define LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H |
11 | |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "llvm/ADT/iterator_range.h" |
14 | #include "llvm/BinaryFormat/Dwarf.h" |
15 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
16 | #include <cassert> |
17 | #include <cstddef> |
18 | #include <cstdint> |
19 | |
20 | namespace llvm { |
21 | |
22 | class ; |
23 | class DWARFUnit; |
24 | class raw_ostream; |
25 | |
26 | class DWARFAbbreviationDeclaration { |
27 | public: |
28 | enum class { , }; |
29 | struct AttributeSpec { |
30 | AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value) |
31 | : Attr(A), Form(F), Value(Value) { |
32 | assert(isImplicitConst()); |
33 | } |
34 | AttributeSpec(dwarf::Attribute A, dwarf::Form F, |
35 | std::optional<uint8_t> ByteSize) |
36 | : Attr(A), Form(F) { |
37 | assert(!isImplicitConst()); |
38 | this->ByteSize.HasByteSize = ByteSize.has_value(); |
39 | if (this->ByteSize.HasByteSize) |
40 | this->ByteSize.ByteSize = *ByteSize; |
41 | } |
42 | |
43 | DWARFFormValue getFormValue() const { |
44 | if (Form == dwarf::DW_FORM_implicit_const) |
45 | return DWARFFormValue::createFromSValue(F: Form, V: getImplicitConstValue()); |
46 | |
47 | return DWARFFormValue(Form); |
48 | } |
49 | |
50 | dwarf::Attribute Attr; |
51 | dwarf::Form Form; |
52 | |
53 | private: |
54 | /// The following field is used for ByteSize for non-implicit_const |
55 | /// attributes and as value for implicit_const ones, indicated by |
56 | /// Form == DW_FORM_implicit_const. |
57 | /// The following cases are distinguished: |
58 | /// * Form != DW_FORM_implicit_const and HasByteSize is true: |
59 | /// ByteSize contains the fixed size in bytes for the Form in this |
60 | /// object. |
61 | /// * Form != DW_FORM_implicit_const and HasByteSize is false: |
62 | /// byte size of Form either varies according to the DWARFUnit |
63 | /// that it is contained in or the value size varies and must be |
64 | /// decoded from the debug information in order to determine its size. |
65 | /// * Form == DW_FORM_implicit_const: |
66 | /// Value contains value for the implicit_const attribute. |
67 | struct ByteSizeStorage { |
68 | bool HasByteSize; |
69 | uint8_t ByteSize; |
70 | }; |
71 | union { |
72 | ByteSizeStorage ByteSize; |
73 | int64_t Value; |
74 | }; |
75 | |
76 | public: |
77 | bool isImplicitConst() const { |
78 | return Form == dwarf::DW_FORM_implicit_const; |
79 | } |
80 | |
81 | int64_t getImplicitConstValue() const { |
82 | assert(isImplicitConst()); |
83 | return Value; |
84 | } |
85 | |
86 | /// Get the fixed byte size of this Form if possible. This function might |
87 | /// use the DWARFUnit to calculate the size of the Form, like for |
88 | /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for |
89 | /// the ByteSize member. |
90 | std::optional<int64_t> getByteSize(const DWARFUnit &U) const; |
91 | }; |
92 | using AttributeSpecVector = SmallVector<AttributeSpec, 8>; |
93 | |
94 | DWARFAbbreviationDeclaration(); |
95 | |
96 | uint32_t getCode() const { return Code; } |
97 | uint8_t getCodeByteSize() const { return CodeByteSize; } |
98 | dwarf::Tag getTag() const { return Tag; } |
99 | bool hasChildren() const { return HasChildren; } |
100 | |
101 | using attr_iterator_range = |
102 | iterator_range<AttributeSpecVector::const_iterator>; |
103 | |
104 | attr_iterator_range attributes() const { |
105 | return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); |
106 | } |
107 | |
108 | dwarf::Form getFormByIndex(uint32_t idx) const { |
109 | assert(idx < AttributeSpecs.size()); |
110 | return AttributeSpecs[idx].Form; |
111 | } |
112 | |
113 | size_t getNumAttributes() const { |
114 | return AttributeSpecs.size(); |
115 | } |
116 | |
117 | dwarf::Attribute getAttrByIndex(uint32_t idx) const { |
118 | assert(idx < AttributeSpecs.size()); |
119 | return AttributeSpecs[idx].Attr; |
120 | } |
121 | |
122 | bool getAttrIsImplicitConstByIndex(uint32_t idx) const { |
123 | assert(idx < AttributeSpecs.size()); |
124 | return AttributeSpecs[idx].isImplicitConst(); |
125 | } |
126 | |
127 | int64_t getAttrImplicitConstValueByIndex(uint32_t idx) const { |
128 | assert(idx < AttributeSpecs.size()); |
129 | return AttributeSpecs[idx].getImplicitConstValue(); |
130 | } |
131 | |
132 | /// Get the index of the specified attribute. |
133 | /// |
134 | /// Searches the this abbreviation declaration for the index of the specified |
135 | /// attribute. |
136 | /// |
137 | /// \param attr DWARF attribute to search for. |
138 | /// \returns Optional index of the attribute if found, std::nullopt otherwise. |
139 | std::optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const; |
140 | |
141 | /// Extract a DWARF form value from a DIE specified by DIE offset. |
142 | /// |
143 | /// Extract an attribute value for a DWARFUnit given the DIE offset and the |
144 | /// attribute. |
145 | /// |
146 | /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation |
147 | /// code in the .debug_info data. |
148 | /// \param Attr DWARF attribute to search for. |
149 | /// \param U the DWARFUnit the contains the DIE. |
150 | /// \returns Optional DWARF form value if the attribute was extracted. |
151 | std::optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset, |
152 | const dwarf::Attribute Attr, |
153 | const DWARFUnit &U) const; |
154 | |
155 | /// Compute an offset from a DIE specified by DIE offset and attribute index. |
156 | /// |
157 | /// \param AttrIndex an index of DWARF attribute. |
158 | /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation |
159 | /// code in the .debug_info data. |
160 | /// \param U the DWARFUnit the contains the DIE. |
161 | /// \returns an offset of the attribute. |
162 | uint64_t getAttributeOffsetFromIndex(uint32_t AttrIndex, uint64_t DIEOffset, |
163 | const DWARFUnit &U) const; |
164 | |
165 | /// Extract a DWARF form value from a DIE speccified by attribute index and |
166 | /// its offset. |
167 | /// |
168 | /// \param AttrIndex an index of DWARF attribute. |
169 | /// \param Offset offset of the attribute. |
170 | /// \param U the DWARFUnit the contains the DIE. |
171 | /// \returns Optional DWARF form value if the attribute was extracted. |
172 | std::optional<DWARFFormValue> |
173 | getAttributeValueFromOffset(uint32_t AttrIndex, uint64_t Offset, |
174 | const DWARFUnit &U) const; |
175 | |
176 | llvm::Expected<ExtractState> (DataExtractor Data, uint64_t *OffsetPtr); |
177 | void dump(raw_ostream &OS) const; |
178 | |
179 | // Return an optional byte size of all attribute data in this abbreviation |
180 | // if a constant byte size can be calculated given a DWARFUnit. This allows |
181 | // DWARF parsing to be faster as many DWARF DIEs have a fixed byte size. |
182 | std::optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const; |
183 | |
184 | private: |
185 | void clear(); |
186 | |
187 | /// A helper structure that can quickly determine the size in bytes of an |
188 | /// abbreviation declaration. |
189 | struct FixedSizeInfo { |
190 | /// The fixed byte size for fixed size forms. |
191 | uint16_t NumBytes = 0; |
192 | /// Number of DW_FORM_address forms in this abbrevation declaration. |
193 | uint8_t NumAddrs = 0; |
194 | /// Number of DW_FORM_ref_addr forms in this abbrevation declaration. |
195 | uint8_t NumRefAddrs = 0; |
196 | /// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms. |
197 | uint8_t NumDwarfOffsets = 0; |
198 | |
199 | FixedSizeInfo() = default; |
200 | |
201 | /// Calculate the fixed size in bytes given a DWARFUnit. |
202 | /// |
203 | /// \param U the DWARFUnit to use when determing the byte size. |
204 | /// \returns the size in bytes for all attribute data in this abbreviation. |
205 | /// The returned size does not include bytes for the ULEB128 abbreviation |
206 | /// code |
207 | size_t getByteSize(const DWARFUnit &U) const; |
208 | }; |
209 | |
210 | uint32_t Code; |
211 | dwarf::Tag Tag; |
212 | uint8_t CodeByteSize; |
213 | bool HasChildren; |
214 | AttributeSpecVector AttributeSpecs; |
215 | /// If this abbreviation has a fixed byte size then FixedAttributeSize member |
216 | /// variable below will have a value. |
217 | std::optional<FixedSizeInfo> FixedAttributeSize; |
218 | }; |
219 | |
220 | } // end namespace llvm |
221 | |
222 | #endif // LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H |
223 | |