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/DWARFDebugLoc.cpp
35269 views
1
//===- DWARFDebugLoc.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/DWARFDebugLoc.h"
10
#include "llvm/ADT/StringRef.h"
11
#include "llvm/BinaryFormat/Dwarf.h"
12
#include "llvm/DebugInfo/DIContext.h"
13
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
14
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
15
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
17
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
18
#include "llvm/Support/Format.h"
19
#include "llvm/Support/raw_ostream.h"
20
#include <algorithm>
21
#include <cinttypes>
22
#include <cstdint>
23
24
using namespace llvm;
25
using object::SectionedAddress;
26
27
namespace llvm {
28
class DWARFObject;
29
}
30
31
namespace {
32
class DWARFLocationInterpreter {
33
std::optional<object::SectionedAddress> Base;
34
std::function<std::optional<object::SectionedAddress>(uint32_t)> LookupAddr;
35
36
public:
37
DWARFLocationInterpreter(
38
std::optional<object::SectionedAddress> Base,
39
std::function<std::optional<object::SectionedAddress>(uint32_t)>
40
LookupAddr)
41
: Base(Base), LookupAddr(std::move(LookupAddr)) {}
42
43
Expected<std::optional<DWARFLocationExpression>>
44
Interpret(const DWARFLocationEntry &E);
45
};
46
} // namespace
47
48
static Error createResolverError(uint32_t Index, unsigned Kind) {
49
return make_error<ResolverError>(Index, (dwarf::LoclistEntries)Kind);
50
}
51
52
Expected<std::optional<DWARFLocationExpression>>
53
DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) {
54
switch (E.Kind) {
55
case dwarf::DW_LLE_end_of_list:
56
return std::nullopt;
57
case dwarf::DW_LLE_base_addressx: {
58
Base = LookupAddr(E.Value0);
59
if (!Base)
60
return createResolverError(E.Value0, E.Kind);
61
return std::nullopt;
62
}
63
case dwarf::DW_LLE_startx_endx: {
64
std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0);
65
if (!LowPC)
66
return createResolverError(E.Value0, E.Kind);
67
std::optional<SectionedAddress> HighPC = LookupAddr(E.Value1);
68
if (!HighPC)
69
return createResolverError(E.Value1, E.Kind);
70
return DWARFLocationExpression{
71
DWARFAddressRange{LowPC->Address, HighPC->Address, LowPC->SectionIndex},
72
E.Loc};
73
}
74
case dwarf::DW_LLE_startx_length: {
75
std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0);
76
if (!LowPC)
77
return createResolverError(E.Value0, E.Kind);
78
return DWARFLocationExpression{DWARFAddressRange{LowPC->Address,
79
LowPC->Address + E.Value1,
80
LowPC->SectionIndex},
81
E.Loc};
82
}
83
case dwarf::DW_LLE_offset_pair: {
84
if (!Base) {
85
return createStringError(inconvertibleErrorCode(),
86
"Unable to resolve location list offset pair: "
87
"Base address not defined");
88
}
89
DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1,
90
Base->SectionIndex};
91
if (Range.SectionIndex == SectionedAddress::UndefSection)
92
Range.SectionIndex = E.SectionIndex;
93
return DWARFLocationExpression{Range, E.Loc};
94
}
95
case dwarf::DW_LLE_default_location:
96
return DWARFLocationExpression{std::nullopt, E.Loc};
97
case dwarf::DW_LLE_base_address:
98
Base = SectionedAddress{E.Value0, E.SectionIndex};
99
return std::nullopt;
100
case dwarf::DW_LLE_start_end:
101
return DWARFLocationExpression{
102
DWARFAddressRange{E.Value0, E.Value1, E.SectionIndex}, E.Loc};
103
case dwarf::DW_LLE_start_length:
104
return DWARFLocationExpression{
105
DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex},
106
E.Loc};
107
default:
108
llvm_unreachable("unreachable locations list kind");
109
}
110
}
111
112
static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts,
113
ArrayRef<uint8_t> Data, bool IsLittleEndian,
114
unsigned AddressSize, DWARFUnit *U) {
115
DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize);
116
// Note. We do not pass any format to DWARFExpression, even if the
117
// corresponding unit is known. For now, there is only one operation,
118
// DW_OP_call_ref, which depends on the format; it is rarely used, and
119
// is unexpected in location tables.
120
DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, U);
121
}
122
123
bool DWARFLocationTable::dumpLocationList(
124
uint64_t *Offset, raw_ostream &OS, std::optional<SectionedAddress> BaseAddr,
125
const DWARFObject &Obj, DWARFUnit *U, DIDumpOptions DumpOpts,
126
unsigned Indent) const {
127
DWARFLocationInterpreter Interp(
128
BaseAddr, [U](uint32_t Index) -> std::optional<SectionedAddress> {
129
if (U)
130
return U->getAddrOffsetSectionItem(Index);
131
return std::nullopt;
132
});
133
OS << format("0x%8.8" PRIx64 ": ", *Offset);
134
Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) {
135
Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
136
if (!Loc || DumpOpts.DisplayRawContents)
137
dumpRawEntry(E, OS, Indent, DumpOpts, Obj);
138
if (Loc && *Loc) {
139
OS << "\n";
140
OS.indent(Indent);
141
if (DumpOpts.DisplayRawContents)
142
OS << " => ";
143
144
DIDumpOptions RangeDumpOpts(DumpOpts);
145
RangeDumpOpts.DisplayRawContents = false;
146
if (Loc.get()->Range)
147
Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj);
148
else
149
OS << "<default>";
150
}
151
if (!Loc)
152
consumeError(Loc.takeError());
153
154
if (E.Kind != dwarf::DW_LLE_base_address &&
155
E.Kind != dwarf::DW_LLE_base_addressx &&
156
E.Kind != dwarf::DW_LLE_end_of_list) {
157
OS << ": ";
158
dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(),
159
Data.getAddressSize(), U);
160
}
161
return true;
162
});
163
if (E) {
164
DumpOpts.RecoverableErrorHandler(std::move(E));
165
return false;
166
}
167
return true;
168
}
169
170
Error DWARFLocationTable::visitAbsoluteLocationList(
171
uint64_t Offset, std::optional<SectionedAddress> BaseAddr,
172
std::function<std::optional<SectionedAddress>(uint32_t)> LookupAddr,
173
function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const {
174
DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr));
175
return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) {
176
Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
177
if (!Loc)
178
return Callback(Loc.takeError());
179
if (*Loc)
180
return Callback(**Loc);
181
return true;
182
});
183
}
184
185
void DWARFDebugLoc::dump(raw_ostream &OS, const DWARFObject &Obj,
186
DIDumpOptions DumpOpts,
187
std::optional<uint64_t> DumpOffset) const {
188
auto BaseAddr = std::nullopt;
189
unsigned Indent = 12;
190
if (DumpOffset) {
191
dumpLocationList(&*DumpOffset, OS, BaseAddr, Obj, nullptr, DumpOpts,
192
Indent);
193
} else {
194
uint64_t Offset = 0;
195
StringRef Separator;
196
bool CanContinue = true;
197
while (CanContinue && Data.isValidOffset(Offset)) {
198
OS << Separator;
199
Separator = "\n";
200
201
CanContinue = dumpLocationList(&Offset, OS, BaseAddr, Obj, nullptr,
202
DumpOpts, Indent);
203
OS << '\n';
204
}
205
}
206
}
207
208
Error DWARFDebugLoc::visitLocationList(
209
uint64_t *Offset,
210
function_ref<bool(const DWARFLocationEntry &)> Callback) const {
211
DataExtractor::Cursor C(*Offset);
212
while (true) {
213
uint64_t SectionIndex;
214
uint64_t Value0 = Data.getRelocatedAddress(C);
215
uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex);
216
217
DWARFLocationEntry E;
218
219
// The end of any given location list is marked by an end of list entry,
220
// which consists of a 0 for the beginning address offset and a 0 for the
221
// ending address offset. A beginning offset of 0xff...f marks the base
222
// address selection entry.
223
if (Value0 == 0 && Value1 == 0) {
224
E.Kind = dwarf::DW_LLE_end_of_list;
225
} else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) {
226
E.Kind = dwarf::DW_LLE_base_address;
227
E.Value0 = Value1;
228
E.SectionIndex = SectionIndex;
229
} else {
230
E.Kind = dwarf::DW_LLE_offset_pair;
231
E.Value0 = Value0;
232
E.Value1 = Value1;
233
E.SectionIndex = SectionIndex;
234
unsigned Bytes = Data.getU16(C);
235
// A single location description describing the location of the object...
236
Data.getU8(C, E.Loc, Bytes);
237
}
238
239
if (!C)
240
return C.takeError();
241
if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list)
242
break;
243
}
244
*Offset = C.tell();
245
return Error::success();
246
}
247
248
void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry,
249
raw_ostream &OS, unsigned Indent,
250
DIDumpOptions DumpOpts,
251
const DWARFObject &Obj) const {
252
uint64_t Value0, Value1;
253
switch (Entry.Kind) {
254
case dwarf::DW_LLE_base_address:
255
Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL;
256
Value1 = Entry.Value0;
257
break;
258
case dwarf::DW_LLE_offset_pair:
259
Value0 = Entry.Value0;
260
Value1 = Entry.Value1;
261
break;
262
case dwarf::DW_LLE_end_of_list:
263
return;
264
default:
265
llvm_unreachable("Not possible in DWARF4!");
266
}
267
OS << '\n';
268
OS.indent(Indent);
269
OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", "
270
<< format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')';
271
DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);
272
}
273
274
Error DWARFDebugLoclists::visitLocationList(
275
uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const {
276
277
DataExtractor::Cursor C(*Offset);
278
bool Continue = true;
279
while (Continue) {
280
DWARFLocationEntry E;
281
E.Kind = Data.getU8(C);
282
switch (E.Kind) {
283
case dwarf::DW_LLE_end_of_list:
284
break;
285
case dwarf::DW_LLE_base_addressx:
286
E.Value0 = Data.getULEB128(C);
287
break;
288
case dwarf::DW_LLE_startx_endx:
289
E.Value0 = Data.getULEB128(C);
290
E.Value1 = Data.getULEB128(C);
291
break;
292
case dwarf::DW_LLE_startx_length:
293
E.Value0 = Data.getULEB128(C);
294
// Pre-DWARF 5 has different interpretation of the length field. We have
295
// to support both pre- and standartized styles for the compatibility.
296
if (Version < 5)
297
E.Value1 = Data.getU32(C);
298
else
299
E.Value1 = Data.getULEB128(C);
300
break;
301
case dwarf::DW_LLE_offset_pair:
302
E.Value0 = Data.getULEB128(C);
303
E.Value1 = Data.getULEB128(C);
304
E.SectionIndex = SectionedAddress::UndefSection;
305
break;
306
case dwarf::DW_LLE_default_location:
307
break;
308
case dwarf::DW_LLE_base_address:
309
E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
310
break;
311
case dwarf::DW_LLE_start_end:
312
E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
313
E.Value1 = Data.getRelocatedAddress(C);
314
break;
315
case dwarf::DW_LLE_start_length:
316
E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
317
E.Value1 = Data.getULEB128(C);
318
break;
319
default:
320
cantFail(C.takeError());
321
return createStringError(errc::illegal_byte_sequence,
322
"LLE of kind %x not supported", (int)E.Kind);
323
}
324
325
if (E.Kind != dwarf::DW_LLE_base_address &&
326
E.Kind != dwarf::DW_LLE_base_addressx &&
327
E.Kind != dwarf::DW_LLE_end_of_list) {
328
unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C);
329
// A single location description describing the location of the object...
330
Data.getU8(C, E.Loc, Bytes);
331
}
332
333
if (!C)
334
return C.takeError();
335
Continue = F(E) && E.Kind != dwarf::DW_LLE_end_of_list;
336
}
337
*Offset = C.tell();
338
return Error::success();
339
}
340
341
void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry,
342
raw_ostream &OS, unsigned Indent,
343
DIDumpOptions DumpOpts,
344
const DWARFObject &Obj) const {
345
size_t MaxEncodingStringLength = 0;
346
#define HANDLE_DW_LLE(ID, NAME) \
347
MaxEncodingStringLength = std::max(MaxEncodingStringLength, \
348
dwarf::LocListEncodingString(ID).size());
349
#include "llvm/BinaryFormat/Dwarf.def"
350
351
OS << "\n";
352
OS.indent(Indent);
353
StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind);
354
// Unsupported encodings should have been reported during parsing.
355
assert(!EncodingString.empty() && "Unknown loclist entry encoding");
356
OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data());
357
unsigned FieldSize = 2 + 2 * Data.getAddressSize();
358
switch (Entry.Kind) {
359
case dwarf::DW_LLE_end_of_list:
360
case dwarf::DW_LLE_default_location:
361
break;
362
case dwarf::DW_LLE_startx_endx:
363
case dwarf::DW_LLE_startx_length:
364
case dwarf::DW_LLE_offset_pair:
365
case dwarf::DW_LLE_start_end:
366
case dwarf::DW_LLE_start_length:
367
OS << format_hex(Entry.Value0, FieldSize) << ", "
368
<< format_hex(Entry.Value1, FieldSize);
369
break;
370
case dwarf::DW_LLE_base_addressx:
371
case dwarf::DW_LLE_base_address:
372
OS << format_hex(Entry.Value0, FieldSize);
373
break;
374
}
375
OS << ')';
376
switch (Entry.Kind) {
377
case dwarf::DW_LLE_base_address:
378
case dwarf::DW_LLE_start_end:
379
case dwarf::DW_LLE_start_length:
380
DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);
381
break;
382
default:
383
break;
384
}
385
}
386
387
void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
388
raw_ostream &OS, const DWARFObject &Obj,
389
DIDumpOptions DumpOpts) {
390
if (!Data.isValidOffsetForDataOfSize(StartOffset, Size)) {
391
OS << "Invalid dump range\n";
392
return;
393
}
394
uint64_t Offset = StartOffset;
395
StringRef Separator;
396
bool CanContinue = true;
397
while (CanContinue && Offset < StartOffset + Size) {
398
OS << Separator;
399
Separator = "\n";
400
401
CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
402
nullptr, DumpOpts, /*Indent=*/12);
403
OS << '\n';
404
}
405
}
406
407
void llvm::ResolverError::log(raw_ostream &OS) const {
408
OS << format("unable to resolve indirect address %u for: %s", Index,
409
dwarf::LocListEncodingString(Kind).data());
410
}
411
412
char llvm::ResolverError::ID;
413
414