LLVM 17.0.0git
DWARFDebugRnglists.cpp
Go to the documentation of this file.
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
13#include "llvm/Support/Errc.h"
14#include "llvm/Support/Error.h"
15#include "llvm/Support/Format.h"
17
18using namespace llvm;
19
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());
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(
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
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
96 std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
97 function_ref<std::optional<object::SectionedAddress>(uint32_t)>
98 LookupPooledAddress) const {
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
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
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}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
if(VerifyEach)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
DWARFAddressRangesVector getAbsoluteRanges(std::optional< object::SectionedAddress > BaseAddr, uint8_t AddressByteSize, function_ref< std::optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress) const
Build a DWARFAddressRangesVector from a rangelist.
void dumpAddress(raw_ostream &OS, uint64_t Address) const
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:319
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
StringRef RangeListEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:515
StringRef RLEString(unsigned RLE)
Definition: Dwarf.cpp:805
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
uint64_t computeTombstoneAddress(uint8_t AddressByteSize)
Definition: Dwarf.h:859
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:189
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts={}, const DWARFObject *Obj=nullptr) const
uint64_t SectionIndex
The index of the section this entry belongs to.
uint8_t EntryKind
The DWARF encoding (DW_RLE_* or DW_LLE_*).
uint64_t Offset
The offset at which the entry is located in the section.
A class representing a single range list entry.
Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr)
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref< std::optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress) const
uint64_t Value0
The values making up the range list entry.