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/DWARFDebugRnglists.cpp
35269 views
1
//===- DWARFDebugRnglists.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/DWARFDebugRnglists.h"
10
#include "llvm/BinaryFormat/Dwarf.h"
11
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
12
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
13
#include "llvm/Support/Errc.h"
14
#include "llvm/Support/Error.h"
15
#include "llvm/Support/Format.h"
16
#include "llvm/Support/raw_ostream.h"
17
18
using namespace llvm;
19
20
Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
21
Offset = *OffsetPtr;
22
SectionIndex = -1ULL;
23
// The caller should guarantee that we have at least 1 byte available, so
24
// we just assert instead of revalidate.
25
assert(*OffsetPtr < Data.size() &&
26
"not enough space to extract a rangelist encoding");
27
uint8_t Encoding = Data.getU8(OffsetPtr);
28
29
DataExtractor::Cursor C(*OffsetPtr);
30
switch (Encoding) {
31
case dwarf::DW_RLE_end_of_list:
32
Value0 = Value1 = 0;
33
break;
34
// TODO: Support other encodings.
35
case dwarf::DW_RLE_base_addressx: {
36
Value0 = Data.getULEB128(C);
37
break;
38
}
39
case dwarf::DW_RLE_startx_endx:
40
Value0 = Data.getULEB128(C);
41
Value1 = Data.getULEB128(C);
42
break;
43
case dwarf::DW_RLE_startx_length: {
44
Value0 = Data.getULEB128(C);
45
Value1 = Data.getULEB128(C);
46
break;
47
}
48
case dwarf::DW_RLE_offset_pair: {
49
Value0 = Data.getULEB128(C);
50
Value1 = Data.getULEB128(C);
51
break;
52
}
53
case dwarf::DW_RLE_base_address: {
54
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
55
break;
56
}
57
case dwarf::DW_RLE_start_end: {
58
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
59
Value1 = Data.getRelocatedAddress(C);
60
break;
61
}
62
case dwarf::DW_RLE_start_length: {
63
Value0 = Data.getRelocatedAddress(C, &SectionIndex);
64
Value1 = Data.getULEB128(C);
65
break;
66
}
67
default:
68
consumeError(C.takeError());
69
return createStringError(errc::not_supported,
70
"unknown rnglists encoding 0x%" PRIx32
71
" at offset 0x%" PRIx64,
72
uint32_t(Encoding), Offset);
73
}
74
75
if (!C) {
76
consumeError(C.takeError());
77
return createStringError(
78
errc::invalid_argument,
79
"read past end of table when reading %s encoding at offset 0x%" PRIx64,
80
dwarf::RLEString(Encoding).data(), Offset);
81
}
82
83
*OffsetPtr = C.tell();
84
EntryKind = Encoding;
85
return Error::success();
86
}
87
88
DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
89
std::optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
90
return getAbsoluteRanges(
91
BaseAddr, U.getAddressByteSize(),
92
[&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
93
}
94
95
DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
96
std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
97
function_ref<std::optional<object::SectionedAddress>(uint32_t)>
98
LookupPooledAddress) const {
99
DWARFAddressRangesVector Res;
100
uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
101
for (const RangeListEntry &RLE : Entries) {
102
if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
103
break;
104
if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
105
BaseAddr = LookupPooledAddress(RLE.Value0);
106
if (!BaseAddr)
107
BaseAddr = {RLE.Value0, -1ULL};
108
continue;
109
}
110
if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
111
BaseAddr = {RLE.Value0, RLE.SectionIndex};
112
continue;
113
}
114
115
DWARFAddressRange E;
116
E.SectionIndex = RLE.SectionIndex;
117
if (BaseAddr && E.SectionIndex == -1ULL)
118
E.SectionIndex = BaseAddr->SectionIndex;
119
120
switch (RLE.EntryKind) {
121
case dwarf::DW_RLE_offset_pair:
122
E.LowPC = RLE.Value0;
123
if (E.LowPC == Tombstone)
124
continue;
125
E.HighPC = RLE.Value1;
126
if (BaseAddr) {
127
if (BaseAddr->Address == Tombstone)
128
continue;
129
E.LowPC += BaseAddr->Address;
130
E.HighPC += BaseAddr->Address;
131
}
132
break;
133
case dwarf::DW_RLE_start_end:
134
E.LowPC = RLE.Value0;
135
E.HighPC = RLE.Value1;
136
break;
137
case dwarf::DW_RLE_start_length:
138
E.LowPC = RLE.Value0;
139
E.HighPC = E.LowPC + RLE.Value1;
140
break;
141
case dwarf::DW_RLE_startx_length: {
142
auto Start = LookupPooledAddress(RLE.Value0);
143
if (!Start)
144
Start = {0, -1ULL};
145
E.SectionIndex = Start->SectionIndex;
146
E.LowPC = Start->Address;
147
E.HighPC = E.LowPC + RLE.Value1;
148
break;
149
}
150
case dwarf::DW_RLE_startx_endx: {
151
auto Start = LookupPooledAddress(RLE.Value0);
152
if (!Start)
153
Start = {0, -1ULL};
154
auto End = LookupPooledAddress(RLE.Value1);
155
if (!End)
156
End = {0, -1ULL};
157
// FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
158
E.SectionIndex = Start->SectionIndex;
159
E.LowPC = Start->Address;
160
E.HighPC = End->Address;
161
break;
162
}
163
default:
164
// Unsupported encodings should have been reported during extraction,
165
// so we should not run into any here.
166
llvm_unreachable("Unsupported range list encoding");
167
}
168
if (E.LowPC == Tombstone)
169
continue;
170
Res.push_back(E);
171
}
172
return Res;
173
}
174
175
void RangeListEntry::dump(
176
raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
177
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
178
llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
179
LookupPooledAddress) const {
180
auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
181
uint8_t AddrSize, DIDumpOptions DumpOpts) {
182
if (DumpOpts.Verbose) {
183
DumpOpts.DisplayRawContents = true;
184
DWARFAddressRange(Entry.Value0, Entry.Value1)
185
.dump(OS, AddrSize, DumpOpts);
186
OS << " => ";
187
}
188
};
189
190
if (DumpOpts.Verbose) {
191
// Print the section offset in verbose mode.
192
OS << format("0x%8.8" PRIx64 ":", Offset);
193
auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
194
// Unsupported encodings should have been reported during parsing.
195
assert(!EncodingString.empty() && "Unknown range entry encoding");
196
OS << format(" [%s%*c", EncodingString.data(),
197
MaxEncodingStringLength - EncodingString.size() + 1, ']');
198
if (EntryKind != dwarf::DW_RLE_end_of_list)
199
OS << ": ";
200
}
201
202
uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
203
204
switch (EntryKind) {
205
case dwarf::DW_RLE_end_of_list:
206
OS << (DumpOpts.Verbose ? "" : "<End of list>");
207
break;
208
case dwarf::DW_RLE_base_addressx: {
209
if (auto SA = LookupPooledAddress(Value0))
210
CurrentBase = SA->Address;
211
else
212
CurrentBase = Value0;
213
if (!DumpOpts.Verbose)
214
return;
215
DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
216
break;
217
}
218
case dwarf::DW_RLE_base_address:
219
// In non-verbose mode we do not print anything for this entry.
220
CurrentBase = Value0;
221
if (!DumpOpts.Verbose)
222
return;
223
DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
224
break;
225
case dwarf::DW_RLE_start_length:
226
PrintRawEntry(OS, *this, AddrSize, DumpOpts);
227
DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
228
break;
229
case dwarf::DW_RLE_offset_pair:
230
PrintRawEntry(OS, *this, AddrSize, DumpOpts);
231
if (CurrentBase != Tombstone)
232
DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
233
.dump(OS, AddrSize, DumpOpts);
234
else
235
OS << "dead code";
236
break;
237
case dwarf::DW_RLE_start_end:
238
DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
239
break;
240
case dwarf::DW_RLE_startx_length: {
241
PrintRawEntry(OS, *this, AddrSize, DumpOpts);
242
uint64_t Start = 0;
243
if (auto SA = LookupPooledAddress(Value0))
244
Start = SA->Address;
245
DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
246
break;
247
}
248
case dwarf::DW_RLE_startx_endx: {
249
PrintRawEntry(OS, *this, AddrSize, DumpOpts);
250
uint64_t Start = 0;
251
if (auto SA = LookupPooledAddress(Value0))
252
Start = SA->Address;
253
uint64_t End = 0;
254
if (auto SA = LookupPooledAddress(Value1))
255
End = SA->Address;
256
DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
257
break;
258
}
259
default:
260
llvm_unreachable("Unsupported range list encoding");
261
}
262
OS << "\n";
263
}
264
265