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