LLVM 20.0.0git
DWARFAbbreviationDeclaration.cpp
Go to the documentation of this file.
1//===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//
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
10
18#include <cstddef>
19#include <cstdint>
20
21using namespace llvm;
22using namespace dwarf;
23
24void DWARFAbbreviationDeclaration::clear() {
25 Code = 0;
26 Tag = DW_TAG_null;
27 CodeByteSize = 0;
28 HasChildren = false;
29 AttributeSpecs.clear();
30 FixedAttributeSize.reset();
31}
32
34 clear();
35}
36
39 clear();
40 const uint64_t Offset = *OffsetPtr;
41 Error Err = Error::success();
42 Code = Data.getULEB128(OffsetPtr, &Err);
43 if (Err)
44 return std::move(Err);
45
46 if (Code == 0)
48
49 CodeByteSize = *OffsetPtr - Offset;
50 Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr, &Err));
51 if (Err)
52 return std::move(Err);
53
54 if (Tag == DW_TAG_null) {
55 clear();
56 return make_error<llvm::object::GenericBinaryError>(
57 "abbreviation declaration requires a non-null tag");
58 }
59 uint8_t ChildrenByte = Data.getU8(OffsetPtr, &Err);
60 if (Err)
61 return std::move(Err);
62
63 HasChildren = (ChildrenByte == DW_CHILDREN_yes);
64 // Assign a value to our optional FixedAttributeSize member variable. If
65 // this member variable still has a value after the while loop below, then
66 // all attribute data in this abbreviation declaration has a fixed byte size.
67 FixedAttributeSize = FixedSizeInfo();
68
69 // Read all of the abbreviation attributes and forms.
70 while (Data.isValidOffset(*OffsetPtr)) {
71 auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr, &Err));
72 if (Err)
73 return std::move(Err);
74
75 auto F = static_cast<Form>(Data.getULEB128(OffsetPtr, &Err));
76 if (Err)
77 return std::move(Err);
78
79 // We successfully reached the end of this abbreviation declaration
80 // since both attribute and form are zero. There may be more abbreviation
81 // declarations afterwards.
82 if (!A && !F)
84
85 if (!A || !F) {
86 // Attribute and form pairs must either both be non-zero, in which case
87 // they are added to the abbreviation declaration, or both be zero to
88 // terminate the abbrevation declaration. In this case only one was
89 // zero which is an error.
90 clear();
91 return make_error<llvm::object::GenericBinaryError>(
92 "malformed abbreviation declaration attribute. Either the attribute "
93 "or the form is zero while the other is not");
94 }
95
96 bool IsImplicitConst = (F == DW_FORM_implicit_const);
97 if (IsImplicitConst) {
98 int64_t V = Data.getSLEB128(OffsetPtr);
99 AttributeSpecs.push_back(AttributeSpec(A, F, V));
100 continue;
101 }
102 std::optional<uint8_t> ByteSize;
103 // If this abbrevation still has a fixed byte size, then update the
104 // FixedAttributeSize as needed.
105 switch (F) {
106 case DW_FORM_addr:
107 if (FixedAttributeSize)
108 ++FixedAttributeSize->NumAddrs;
109 break;
110
111 case DW_FORM_ref_addr:
112 if (FixedAttributeSize)
113 ++FixedAttributeSize->NumRefAddrs;
114 break;
115
116 case DW_FORM_strp:
117 case DW_FORM_GNU_ref_alt:
118 case DW_FORM_GNU_strp_alt:
119 case DW_FORM_line_strp:
120 case DW_FORM_sec_offset:
121 case DW_FORM_strp_sup:
122 if (FixedAttributeSize)
123 ++FixedAttributeSize->NumDwarfOffsets;
124 break;
125
126 default:
127 // The form has a byte size that doesn't depend on Params.
128 // If it's a fixed size, keep track of it.
129 if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) {
130 if (FixedAttributeSize)
131 FixedAttributeSize->NumBytes += *ByteSize;
132 break;
133 }
134 // Indicate we no longer have a fixed byte size for this
135 // abbreviation by clearing the FixedAttributeSize optional value
136 // so it doesn't have a value.
137 FixedAttributeSize.reset();
138 break;
139 }
140 // Record this attribute and its fixed size if it has one.
141 AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));
142 }
143 return make_error<llvm::object::GenericBinaryError>(
144 "abbreviation declaration attribute list was not terminated with a null "
145 "entry");
146}
147
149 OS << '[' << getCode() << "] ";
150 OS << formatv("{0}", getTag());
151 OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
152 for (const AttributeSpec &Spec : AttributeSpecs) {
153 OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
154 if (Spec.isImplicitConst())
155 OS << '\t' << Spec.getImplicitConstValue();
156 OS << '\n';
157 }
158 OS << '\n';
159}
160
161std::optional<uint32_t>
163 for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
164 if (AttributeSpecs[i].Attr == Attr)
165 return i;
166 }
167 return std::nullopt;
168}
169
171 uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const {
172 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
173
174 // Add the byte size of ULEB that for the abbrev Code so we can start
175 // skipping the attribute data.
176 uint64_t Offset = DIEOffset + CodeByteSize;
177 for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx)
178 // Match Offset along until we get to the attribute we want.
179 if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U))
180 Offset += *FixedSize;
181 else
182 DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData,
183 &Offset, U.getFormParams());
184 return Offset;
185}
186
187std::optional<DWARFFormValue>
189 uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const {
190 assert(AttributeSpecs.size() > AttrIndex &&
191 "Attribute Index is out of bounds.");
192
193 // We have arrived at the attribute to extract, extract if from Offset.
194 const AttributeSpec &Spec = AttributeSpecs[AttrIndex];
195 if (Spec.isImplicitConst())
197 Spec.getImplicitConstValue());
198
199 DWARFFormValue FormValue(Spec.Form);
200 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
201 if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
202 return FormValue;
203 return std::nullopt;
204}
205
206std::optional<DWARFFormValue>
208 const dwarf::Attribute Attr,
209 const DWARFUnit &U) const {
210 // Check if this abbreviation has this attribute without needing to skip
211 // any data so we can return quickly if it doesn't.
212 std::optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
213 if (!MatchAttrIndex)
214 return std::nullopt;
215
216 uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U);
217
218 return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U);
219}
220
221size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
222 const DWARFUnit &U) const {
223 size_t ByteSize = NumBytes;
224 if (NumAddrs)
225 ByteSize += NumAddrs * U.getAddressByteSize();
226 if (NumRefAddrs)
227 ByteSize += NumRefAddrs * U.getRefAddrByteSize();
228 if (NumDwarfOffsets)
229 ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
230 return ByteSize;
231}
232
234 const DWARFUnit &U) const {
235 if (isImplicitConst())
236 return 0;
237 if (ByteSize.HasByteSize)
238 return ByteSize.ByteSize;
239 std::optional<int64_t> S;
240 auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams());
241 if (FixedByteSize)
242 S = *FixedByteSize;
243 return S;
244}
245
247 const DWARFUnit &U) const {
248 if (FixedAttributeSize)
249 return FixedAttributeSize->getByteSize(U);
250 return std::nullopt;
251}
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains constants used for implementing Dwarf debug support.
#define F(x, y, z)
Definition: MD5.cpp:55
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
llvm::Expected< ExtractState > extract(DataExtractor Data, uint64_t *OffsetPtr)
uint64_t getAttributeOffsetFromIndex(uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const
Compute an offset from a DIE specified by DIE offset and attribute index.
std::optional< uint32_t > findAttributeIndex(dwarf::Attribute attr) const
Get the index of the specified attribute.
std::optional< DWARFFormValue > getAttributeValue(const uint64_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U) const
Extract a DWARF form value from a DIE specified by DIE offset.
std::optional< size_t > getFixedAttributesByteSize(const DWARFUnit &U) const
std::optional< DWARFFormValue > getAttributeValueFromOffset(uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const
Extract a DWARF form value from a DIE speccified by attribute index and its offset.
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context=nullptr, const DWARFUnit *Unit=nullptr)
Extracts a value in Data at offset *OffsetPtr.
static DWARFFormValue createFromSValue(dwarf::Form F, int64_t V)
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const
Skip a form's value in DebugInfoData at the offset specified by OffsetPtr.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
size_t size() const
Definition: SmallVector.h:92
void push_back(const T &Elt)
Definition: SmallVector.h:427
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
Attribute
Attributes.
Definition: Dwarf.h:123
std::optional< uint8_t > getFixedFormByteSize(dwarf::Form Form, FormParams Params)
Get the fixed byte size for a given form.
Definition: Dwarf.cpp:771
@ DW_CHILDREN_yes
Definition: Dwarf.h:838
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::optional< int64_t > getByteSize(const DWARFUnit &U) const
Get the fixed byte size of this Form if possible.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition: Dwarf.h:1077