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
20namespace llvm {
21
22class DataExtractor;
23class DWARFUnit;
24class raw_ostream;
25
26class DWARFAbbreviationDeclaration {
27public:
28 enum class ExtractState { Complete, MoreItems };
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> extract(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
184private:
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

source code of llvm/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h