LLVM 24.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"
18
19using namespace llvm;
20
22 Offset = *OffsetPtr;
23 SectionIndex = -1ULL;
24 // The caller should guarantee that we have at least 1 byte available, so
25 // we just assert instead of revalidate.
26 assert(*OffsetPtr < Data.size() &&
27 "not enough space to extract a rangelist encoding");
28 uint8_t Encoding = Data.getU8(OffsetPtr);
29
30 DataExtractor::Cursor C(*OffsetPtr);
31 switch (Encoding) {
32 case dwarf::DW_RLE_end_of_list:
33 Value0 = Value1 = 0;
34 break;
35 // TODO: Support other encodings.
36 case dwarf::DW_RLE_base_addressx: {
37 Value0 = Data.getULEB128(C);
38 break;
39 }
40 case dwarf::DW_RLE_startx_endx:
41 Value0 = Data.getULEB128(C);
42 Value1 = Data.getULEB128(C);
43 break;
44 case dwarf::DW_RLE_startx_length: {
45 Value0 = Data.getULEB128(C);
46 Value1 = Data.getULEB128(C);
47 break;
48 }
49 case dwarf::DW_RLE_offset_pair: {
50 Value0 = Data.getULEB128(C);
51 Value1 = Data.getULEB128(C);
52 break;
53 }
54 case dwarf::DW_RLE_base_address: {
55 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
56 break;
57 }
58 case dwarf::DW_RLE_start_end: {
59 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
60 Value1 = Data.getRelocatedAddress(C);
61 break;
62 }
63 case dwarf::DW_RLE_start_length: {
64 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
65 Value1 = Data.getULEB128(C);
66 break;
67 }
68 default:
69 consumeError(C.takeError());
71 "unknown rnglists encoding 0x%" PRIx32
72 " at offset 0x%" PRIx64,
73 uint32_t(Encoding), Offset);
74 }
75
76 if (!C) {
77 consumeError(C.takeError());
78 return createStringError(
80 "read past end of table when reading %s encoding at offset 0x%" PRIx64,
81 dwarf::RLEString(Encoding).data(), Offset);
82 }
83
84 *OffsetPtr = C.tell();
85 EntryKind = Encoding;
86 return Error::success();
87}
88
90 std::optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
91 return getAbsoluteRanges(
92 BaseAddr, U.getAddressByteSize(),
93 [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
94}
95
97 std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
98 function_ref<std::optional<object::SectionedAddress>(uint32_t)>
99 LookupPooledAddress) const {
101 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
102 for (const RangeListEntry &RLE : Entries) {
103 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
104 break;
105 if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
106 BaseAddr = LookupPooledAddress(RLE.Value0);
107 if (!BaseAddr)
108 BaseAddr = {RLE.Value0, -1ULL};
109 continue;
110 }
111 if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
112 BaseAddr = {RLE.Value0, RLE.SectionIndex};
113 continue;
114 }
115
117 E.SectionIndex = RLE.SectionIndex;
118 if (BaseAddr && E.SectionIndex == -1ULL)
119 E.SectionIndex = BaseAddr->SectionIndex;
120
121 switch (RLE.EntryKind) {
122 case dwarf::DW_RLE_offset_pair:
123 E.LowPC = RLE.Value0;
124 if (E.LowPC == Tombstone)
125 continue;
126 E.HighPC = RLE.Value1;
127 if (BaseAddr) {
128 if (BaseAddr->Address == Tombstone)
129 continue;
130 E.LowPC += BaseAddr->Address;
131 E.HighPC += BaseAddr->Address;
132 }
133 break;
134 case dwarf::DW_RLE_start_end:
135 E.LowPC = RLE.Value0;
136 E.HighPC = RLE.Value1;
137 break;
138 case dwarf::DW_RLE_start_length:
139 E.LowPC = RLE.Value0;
140 E.HighPC = E.LowPC + RLE.Value1;
141 break;
142 case dwarf::DW_RLE_startx_length: {
143 auto Start = LookupPooledAddress(RLE.Value0);
144 if (!Start)
145 Start = {0, -1ULL};
146 E.SectionIndex = Start->SectionIndex;
147 E.LowPC = Start->Address;
148 E.HighPC = E.LowPC + RLE.Value1;
149 break;
150 }
151 case dwarf::DW_RLE_startx_endx: {
152 auto Start = LookupPooledAddress(RLE.Value0);
153 if (!Start)
154 Start = {0, -1ULL};
155 auto End = LookupPooledAddress(RLE.Value1);
156 if (!End)
157 End = {0, -1ULL};
158 // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
159 E.SectionIndex = Start->SectionIndex;
160 E.LowPC = Start->Address;
161 E.HighPC = End->Address;
162 break;
163 }
164 default:
165 // Unsupported encodings should have been reported during extraction,
166 // so we should not run into any here.
167 llvm_unreachable("Unsupported range list encoding");
168 }
169 if (E.LowPC == Tombstone)
170 continue;
171 Res.push_back(E);
172 }
173 return Res;
174}
175
177 raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
178 uint64_t &CurrentBase, DIDumpOptions DumpOpts,
179 llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
180 LookupPooledAddress) const {
181 auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
182 uint8_t AddrSize, DIDumpOptions DumpOpts) {
183 if (DumpOpts.Verbose) {
184 DumpOpts.DisplayRawContents = true;
185 DWARFAddressRange(Entry.Value0, Entry.Value1)
186 .dump(OS, AddrSize, DumpOpts);
187 OS << " => ";
188 }
189 };
190
191 if (DumpOpts.Verbose) {
192 // Print the section offset in verbose mode.
193 OS << formatv("{0:x8}:", Offset);
194 auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
195 // Unsupported encodings should have been reported during parsing.
196 assert(!EncodingString.empty() && "Unknown range entry encoding");
197 OS << formatv(" [{0}]",
198 fmt_pad(EncodingString.data(), 0,
199 MaxEncodingStringLength - EncodingString.size()));
200 if (EntryKind != dwarf::DW_RLE_end_of_list)
201 OS << ": ";
202 }
203
204 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
205
206 switch (EntryKind) {
207 case dwarf::DW_RLE_end_of_list:
208 OS << (DumpOpts.Verbose ? "" : "<End of list>");
209 break;
210 case dwarf::DW_RLE_base_addressx: {
211 if (auto SA = LookupPooledAddress(Value0))
212 CurrentBase = SA->Address;
213 else
214 CurrentBase = Value0;
215 if (!DumpOpts.Verbose)
216 return;
217 DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
218 break;
219 }
220 case dwarf::DW_RLE_base_address:
221 // In non-verbose mode we do not print anything for this entry.
222 CurrentBase = Value0;
223 if (!DumpOpts.Verbose)
224 return;
225 DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
226 break;
227 case dwarf::DW_RLE_start_length:
228 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
229 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
230 break;
231 case dwarf::DW_RLE_offset_pair:
232 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
233 if (CurrentBase != Tombstone)
234 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
235 .dump(OS, AddrSize, DumpOpts);
236 else
237 OS << "dead code";
238 break;
239 case dwarf::DW_RLE_start_end:
240 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
241 break;
242 case dwarf::DW_RLE_startx_length: {
243 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
244 uint64_t Start = 0;
245 if (auto SA = LookupPooledAddress(Value0))
246 Start = SA->Address;
247 DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
248 break;
249 }
250 case dwarf::DW_RLE_startx_endx: {
251 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
252 uint64_t Start = 0;
253 if (auto SA = LookupPooledAddress(Value0))
254 Start = SA->Address;
255 uint64_t End = 0;
256 if (auto SA = LookupPooledAddress(Value1))
257 End = SA->Address;
258 DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
259 break;
260 }
261 default:
262 llvm_unreachable("Unsupported range list encoding");
263 }
264 OS << "\n";
265}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains constants used for implementing Dwarf debug support.
static Split data
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
LLVM_ABI 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.
LLVM_ABI void dumpAddress(raw_ostream &OS, uint64_t Address) const
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
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:53
LLVM_ABI StringRef RangeListEncodingString(unsigned Encoding)
Definition Dwarf.cpp:779
LLVM_ABI StringRef RLEString(unsigned RLE)
Definition Dwarf.cpp:1076
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t computeTombstoneAddress(uint8_t AddressByteSize)
Definition Dwarf.h:1331
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ not_supported
Definition Errc.h:69
@ invalid_argument
Definition Errc.h:56
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
support::detail::PadAdapter< T > fmt_pad(T &&Item, size_t Left, size_t Right)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196
LLVM_ABI 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.
LLVM_ABI Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr)
LLVM_ABI 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.