Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
35266 views
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
9
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
10
11
#include "llvm/BinaryFormat/Dwarf.h"
12
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
13
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
14
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
15
#include "llvm/Support/DataExtractor.h"
16
#include "llvm/Support/FormatVariadic.h"
17
#include "llvm/Support/raw_ostream.h"
18
#include <cstddef>
19
#include <cstdint>
20
21
using namespace llvm;
22
using namespace dwarf;
23
24
void DWARFAbbreviationDeclaration::clear() {
25
Code = 0;
26
Tag = DW_TAG_null;
27
CodeByteSize = 0;
28
HasChildren = false;
29
AttributeSpecs.clear();
30
FixedAttributeSize.reset();
31
}
32
33
DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
34
clear();
35
}
36
37
llvm::Expected<DWARFAbbreviationDeclaration::ExtractState>
38
DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint64_t *OffsetPtr) {
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)
47
return ExtractState::Complete;
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)
83
return ExtractState::MoreItems;
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
148
void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
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
161
std::optional<uint32_t>
162
DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
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
170
uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex(
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
187
std::optional<DWARFFormValue>
188
DWARFAbbreviationDeclaration::getAttributeValueFromOffset(
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())
196
return DWARFFormValue::createFromSValue(Spec.Form,
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
206
std::optional<DWARFFormValue>
207
DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset,
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
221
size_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
233
std::optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
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
246
std::optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
247
const DWARFUnit &U) const {
248
if (FixedAttributeSize)
249
return FixedAttributeSize->getByteSize(U);
250
return std::nullopt;
251
}
252
253