[clang] NFC, add a "continue" bailout in the for-loop of
[llvm-project.git] / llvm / lib / DebugInfo / DWARF / DWARFDebugRnglists.cpp
blobb428c2adfe0b320a65ea50f1e9e85319bf8d7594
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 //===----------------------------------------------------------------------===//
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"
18 using namespace llvm;
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);
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;
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;
48 case dwarf::DW_RLE_offset_pair: {
49 Value0 = Data.getULEB128(C);
50 Value1 = Data.getULEB128(C);
51 break;
53 case dwarf::DW_RLE_base_address: {
54 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
55 break;
57 case dwarf::DW_RLE_start_end: {
58 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
59 Value1 = Data.getRelocatedAddress(C);
60 break;
62 case dwarf::DW_RLE_start_length: {
63 Value0 = Data.getRelocatedAddress(C, &SectionIndex);
64 Value1 = Data.getULEB128(C);
65 break;
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);
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);
83 *OffsetPtr = C.tell();
84 EntryKind = Encoding;
85 return Error::success();
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); });
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;
110 if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
111 BaseAddr = {RLE.Value0, RLE.SectionIndex};
112 continue;
115 DWARFAddressRange E;
116 E.SectionIndex = RLE.SectionIndex;
117 if (BaseAddr && E.SectionIndex == -1ULL)
118 E.SectionIndex = BaseAddr->SectionIndex;
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;
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;
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;
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");
168 if (E.LowPC == Tombstone)
169 continue;
170 Res.push_back(E);
172 return Res;
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 << " => ";
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 << ": ";
202 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
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;
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;
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;
259 default:
260 llvm_unreachable("Unsupported range list encoding");
262 OS << "\n";