1c2dfd502SJames Henderson //===- DWARFDebugRnglists.cpp ---------------------------------------------===//
2c2dfd502SJames Henderson //
3c2dfd502SJames Henderson //                     The LLVM Compiler Infrastructure
4c2dfd502SJames Henderson //
5c2dfd502SJames Henderson // This file is distributed under the University of Illinois Open Source
6c2dfd502SJames Henderson // License. See LICENSE.TXT for details.
7c2dfd502SJames Henderson //
8c2dfd502SJames Henderson //===----------------------------------------------------------------------===//
9c2dfd502SJames Henderson 
10c2dfd502SJames Henderson #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
11c2dfd502SJames Henderson #include "llvm/BinaryFormat/Dwarf.h"
12*ad60559bSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
13c2dfd502SJames Henderson #include "llvm/Support/Error.h"
14c2dfd502SJames Henderson #include "llvm/Support/Format.h"
15c2dfd502SJames Henderson #include "llvm/Support/raw_ostream.h"
16c2dfd502SJames Henderson 
17c2dfd502SJames Henderson using namespace llvm;
18c2dfd502SJames Henderson 
193fb9e3f3SWolfgang Pieb void DWARFDebugRnglistTable::clear() {
20c2dfd502SJames Henderson   HeaderData = {};
21c2dfd502SJames Henderson   Offsets.clear();
22c2dfd502SJames Henderson   Ranges.clear();
23c2dfd502SJames Henderson }
24c2dfd502SJames Henderson 
25c2dfd502SJames Henderson template <typename... Ts>
26c2dfd502SJames Henderson static Error createError(char const *Fmt, const Ts &... Vals) {
27c2dfd502SJames Henderson   std::string Buffer;
28c2dfd502SJames Henderson   raw_string_ostream Stream(Buffer);
29c2dfd502SJames Henderson   Stream << format(Fmt, Vals...);
30c2dfd502SJames Henderson   return make_error<StringError>(Stream.str(), inconvertibleErrorCode());
31c2dfd502SJames Henderson }
32c2dfd502SJames Henderson 
333fb9e3f3SWolfgang Pieb Error DWARFDebugRnglistTable::extractHeaderAndOffsets(DWARFDataExtractor Data,
34c2dfd502SJames Henderson                                                       uint32_t *OffsetPtr) {
35a0729d41SWolfgang Pieb   HeaderOffset = *OffsetPtr;
36c2dfd502SJames Henderson   // Read and verify the length field.
37c2dfd502SJames Henderson   if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
38c2dfd502SJames Henderson     return createError("section is not large enough to contain a "
39c2dfd502SJames Henderson                        ".debug_rnglists table length at offset 0x%" PRIx32,
40c2dfd502SJames Henderson                        *OffsetPtr);
41c2dfd502SJames Henderson   // TODO: Add support for DWARF64.
42c2dfd502SJames Henderson   HeaderData.Length = Data.getU32(OffsetPtr);
43a0729d41SWolfgang Pieb   if (HeaderData.Length == 0xffffffffu)
44a0729d41SWolfgang Pieb     return createError(
45a0729d41SWolfgang Pieb         "DWARF64 is not supported in .debug_rnglists at offset 0x%" PRIx32,
46a0729d41SWolfgang Pieb         HeaderOffset);
47*ad60559bSWolfgang Pieb   Format = dwarf::DwarfFormat::DWARF32;
48c2dfd502SJames Henderson   if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
49c2dfd502SJames Henderson     return createError(".debug_rnglists table at offset 0x%" PRIx32
50c2dfd502SJames Henderson                        " has too small length (0x%" PRIx32
51c2dfd502SJames Henderson                        ") to contain a complete header",
52a0729d41SWolfgang Pieb                        HeaderOffset, length());
53a0729d41SWolfgang Pieb   uint32_t End = HeaderOffset + length();
54a0729d41SWolfgang Pieb   if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
55c2dfd502SJames Henderson     return createError(
56c2dfd502SJames Henderson         "section is not large enough to contain a .debug_rnglists table "
57c2dfd502SJames Henderson         "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
58a0729d41SWolfgang Pieb         length(), HeaderOffset);
59c2dfd502SJames Henderson 
60c2dfd502SJames Henderson   HeaderData.Version = Data.getU16(OffsetPtr);
61c2dfd502SJames Henderson   HeaderData.AddrSize = Data.getU8(OffsetPtr);
62c2dfd502SJames Henderson   HeaderData.SegSize = Data.getU8(OffsetPtr);
63c2dfd502SJames Henderson   HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
64c2dfd502SJames Henderson 
65c2dfd502SJames Henderson   // Perform basic validation of the remaining header fields.
66c2dfd502SJames Henderson   if (HeaderData.Version != 5)
67c2dfd502SJames Henderson     return createError("unrecognised .debug_rnglists table version %" PRIu16
68c2dfd502SJames Henderson                        " in table at offset 0x%" PRIx32,
69a0729d41SWolfgang Pieb                        HeaderData.Version, HeaderOffset);
70c2dfd502SJames Henderson   if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
71c2dfd502SJames Henderson     return createError(".debug_rnglists table at offset 0x%" PRIx32
72c2dfd502SJames Henderson                        " has unsupported address size %hhu",
73a0729d41SWolfgang Pieb                        HeaderOffset, HeaderData.AddrSize);
74c2dfd502SJames Henderson   if (HeaderData.SegSize != 0)
75c2dfd502SJames Henderson     return createError(".debug_rnglists table at offset 0x%" PRIx32
76c2dfd502SJames Henderson                        " has unsupported segment selector size %" PRIu8,
77a0729d41SWolfgang Pieb                        HeaderOffset, HeaderData.SegSize);
78a0729d41SWolfgang Pieb   if (End < HeaderOffset + sizeof(HeaderData) +
79c2dfd502SJames Henderson                 HeaderData.OffsetEntryCount * sizeof(uint32_t))
80c2dfd502SJames Henderson     return createError(".debug_rnglists table at offset 0x%" PRIx32
81c2dfd502SJames Henderson                        " has more offset entries (%" PRIu32
82c2dfd502SJames Henderson                        ") than there is space for",
83a0729d41SWolfgang Pieb                        HeaderOffset, HeaderData.OffsetEntryCount);
84c2dfd502SJames Henderson   Data.setAddressSize(HeaderData.AddrSize);
85c2dfd502SJames Henderson   for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
86c2dfd502SJames Henderson     Offsets.push_back(Data.getU32(OffsetPtr));
873fb9e3f3SWolfgang Pieb   return Error::success();
883fb9e3f3SWolfgang Pieb }
89c2dfd502SJames Henderson 
903fb9e3f3SWolfgang Pieb Error DWARFDebugRnglist::RangeListEntry::extract(DWARFDataExtractor Data,
913fb9e3f3SWolfgang Pieb                                                  uint32_t End,
923fb9e3f3SWolfgang Pieb                                                  uint32_t *OffsetPtr) {
933fb9e3f3SWolfgang Pieb   Offset = *OffsetPtr;
94*ad60559bSWolfgang Pieb   SectionIndex = -1ULL;
953fb9e3f3SWolfgang Pieb   // The caller should guarantee that we have at least 1 byte available, so
963fb9e3f3SWolfgang Pieb   // we just assert instead of revalidate.
973fb9e3f3SWolfgang Pieb   assert(*OffsetPtr < End &&
983fb9e3f3SWolfgang Pieb          "not enough space to extract a rangelist encoding");
99c2dfd502SJames Henderson   uint8_t Encoding = Data.getU8(OffsetPtr);
1003fb9e3f3SWolfgang Pieb 
101c2dfd502SJames Henderson   switch (Encoding) {
102c2dfd502SJames Henderson   case dwarf::DW_RLE_end_of_list:
1033fb9e3f3SWolfgang Pieb     Value0 = Value1 = 0;
104c2dfd502SJames Henderson     break;
105c2dfd502SJames Henderson   // TODO: Support other encodings.
106c2dfd502SJames Henderson   case dwarf::DW_RLE_base_addressx:
107c2dfd502SJames Henderson     return createError("unsupported rnglists encoding DW_RLE_base_addressx "
108c2dfd502SJames Henderson                        "at offset 0x%" PRIx32,
109c2dfd502SJames Henderson                        *OffsetPtr - 1);
110c2dfd502SJames Henderson   case dwarf::DW_RLE_startx_endx:
111c2dfd502SJames Henderson     return createError("unsupported rnglists encoding DW_RLE_startx_endx at "
112c2dfd502SJames Henderson                        "offset 0x%" PRIx32,
113c2dfd502SJames Henderson                        *OffsetPtr - 1);
114c2dfd502SJames Henderson   case dwarf::DW_RLE_startx_length:
115c2dfd502SJames Henderson     return createError("unsupported rnglists encoding DW_RLE_startx_length "
116c2dfd502SJames Henderson                        "at offset 0x%" PRIx32,
117c2dfd502SJames Henderson                        *OffsetPtr - 1);
118ab068eaaSWolfgang Pieb   case dwarf::DW_RLE_offset_pair: {
119ab068eaaSWolfgang Pieb     uint32_t PreviousOffset = *OffsetPtr - 1;
1203fb9e3f3SWolfgang Pieb     Value0 = Data.getULEB128(OffsetPtr);
1213fb9e3f3SWolfgang Pieb     Value1 = Data.getULEB128(OffsetPtr);
122ab068eaaSWolfgang Pieb     if (End < *OffsetPtr)
123ab068eaaSWolfgang Pieb       return createError("read past end of table when reading "
124ab068eaaSWolfgang Pieb                          "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
125ab068eaaSWolfgang Pieb                          PreviousOffset);
126ab068eaaSWolfgang Pieb     break;
127ab068eaaSWolfgang Pieb   }
128ab068eaaSWolfgang Pieb   case dwarf::DW_RLE_base_address: {
1293fb9e3f3SWolfgang Pieb     if ((End - *OffsetPtr) < Data.getAddressSize())
130ab068eaaSWolfgang Pieb       return createError("insufficient space remaining in table for "
131ab068eaaSWolfgang Pieb                          "DW_RLE_base_address encoding at offset 0x%" PRIx32,
132c2dfd502SJames Henderson                          *OffsetPtr - 1);
133*ad60559bSWolfgang Pieb     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
134ab068eaaSWolfgang Pieb     break;
135ab068eaaSWolfgang Pieb   }
136c2dfd502SJames Henderson   case dwarf::DW_RLE_start_end: {
1373fb9e3f3SWolfgang Pieb     if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
138c2dfd502SJames Henderson       return createError("insufficient space remaining in table for "
139c2dfd502SJames Henderson                          "DW_RLE_start_end encoding "
140c2dfd502SJames Henderson                          "at offset 0x%" PRIx32,
141c2dfd502SJames Henderson                          *OffsetPtr - 1);
142*ad60559bSWolfgang Pieb     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
143*ad60559bSWolfgang Pieb     Value1 = Data.getRelocatedAddress(OffsetPtr);
144c2dfd502SJames Henderson     break;
145c2dfd502SJames Henderson   }
146c2dfd502SJames Henderson   case dwarf::DW_RLE_start_length: {
147c2dfd502SJames Henderson     uint32_t PreviousOffset = *OffsetPtr - 1;
148*ad60559bSWolfgang Pieb     Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
1493fb9e3f3SWolfgang Pieb     Value1 = Data.getULEB128(OffsetPtr);
150c2dfd502SJames Henderson     if (End < *OffsetPtr)
151c2dfd502SJames Henderson       return createError("read past end of table when reading "
152c2dfd502SJames Henderson                          "DW_RLE_start_length encoding at offset 0x%" PRIx32,
153c2dfd502SJames Henderson                          PreviousOffset);
154c2dfd502SJames Henderson     break;
155c2dfd502SJames Henderson   }
156c2dfd502SJames Henderson   default:
157c2dfd502SJames Henderson     return createError("unknown rnglists encoding 0x%" PRIx32
158c2dfd502SJames Henderson                        " at offset 0x%" PRIx32,
159c2dfd502SJames Henderson                        uint32_t(Encoding), *OffsetPtr - 1);
160c2dfd502SJames Henderson   }
1613fb9e3f3SWolfgang Pieb 
1623fb9e3f3SWolfgang Pieb   EntryKind = Encoding;
1633fb9e3f3SWolfgang Pieb   return Error::success();
164c2dfd502SJames Henderson }
165c2dfd502SJames Henderson 
166*ad60559bSWolfgang Pieb DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
167*ad60559bSWolfgang Pieb     llvm::Optional<BaseAddress> BaseAddr) const {
168*ad60559bSWolfgang Pieb   DWARFAddressRangesVector Res;
169*ad60559bSWolfgang Pieb   for (const RangeListEntry &RLE : Entries) {
170*ad60559bSWolfgang Pieb     if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
171*ad60559bSWolfgang Pieb       break;
172*ad60559bSWolfgang Pieb     if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
173*ad60559bSWolfgang Pieb       BaseAddr = {RLE.Value0, RLE.SectionIndex};
174*ad60559bSWolfgang Pieb       continue;
175*ad60559bSWolfgang Pieb     }
176*ad60559bSWolfgang Pieb 
177*ad60559bSWolfgang Pieb     DWARFAddressRange E;
178*ad60559bSWolfgang Pieb     E.SectionIndex = RLE.SectionIndex;
179*ad60559bSWolfgang Pieb     if (BaseAddr && E.SectionIndex == -1ULL)
180*ad60559bSWolfgang Pieb       E.SectionIndex = BaseAddr->SectionIndex;
181*ad60559bSWolfgang Pieb 
182*ad60559bSWolfgang Pieb     switch (RLE.EntryKind) {
183*ad60559bSWolfgang Pieb     case dwarf::DW_RLE_offset_pair:
184*ad60559bSWolfgang Pieb       E.LowPC = RLE.Value0;
185*ad60559bSWolfgang Pieb       E.HighPC = RLE.Value1;
186*ad60559bSWolfgang Pieb       if (BaseAddr) {
187*ad60559bSWolfgang Pieb         E.LowPC += BaseAddr->Address;
188*ad60559bSWolfgang Pieb         E.HighPC += BaseAddr->Address;
189*ad60559bSWolfgang Pieb       }
190*ad60559bSWolfgang Pieb       break;
191*ad60559bSWolfgang Pieb     case dwarf::DW_RLE_start_end:
192*ad60559bSWolfgang Pieb       E.LowPC = RLE.Value0;
193*ad60559bSWolfgang Pieb       E.HighPC = RLE.Value1;
194*ad60559bSWolfgang Pieb       break;
195*ad60559bSWolfgang Pieb     case dwarf::DW_RLE_start_length:
196*ad60559bSWolfgang Pieb       E.LowPC = RLE.Value0;
197*ad60559bSWolfgang Pieb       E.HighPC = E.LowPC + RLE.Value1;
198*ad60559bSWolfgang Pieb       break;
199*ad60559bSWolfgang Pieb     default:
200*ad60559bSWolfgang Pieb       // Unsupported encodings should have been reported during extraction,
201*ad60559bSWolfgang Pieb       // so we should not run into any here.
202*ad60559bSWolfgang Pieb       llvm_unreachable("Unsupported range list encoding");
203*ad60559bSWolfgang Pieb     }
204*ad60559bSWolfgang Pieb     Res.push_back(E);
205*ad60559bSWolfgang Pieb   }
206*ad60559bSWolfgang Pieb   return Res;
207*ad60559bSWolfgang Pieb }
208*ad60559bSWolfgang Pieb 
2093fb9e3f3SWolfgang Pieb Error DWARFDebugRnglist::extract(DWARFDataExtractor Data, uint32_t HeaderOffset,
2103fb9e3f3SWolfgang Pieb                                  uint32_t End, uint32_t *OffsetPtr) {
2113fb9e3f3SWolfgang Pieb   Entries.clear();
2123fb9e3f3SWolfgang Pieb   while (*OffsetPtr < End) {
2133fb9e3f3SWolfgang Pieb     RangeListEntry Entry{0, 0, 0, 0};
2143fb9e3f3SWolfgang Pieb     if (Error E = Entry.extract(Data, End, OffsetPtr))
2153fb9e3f3SWolfgang Pieb       return E;
2163fb9e3f3SWolfgang Pieb     Entries.push_back(Entry);
2173fb9e3f3SWolfgang Pieb     if (Entry.EntryKind == dwarf::DW_RLE_end_of_list)
2183fb9e3f3SWolfgang Pieb       return Error::success();
2193fb9e3f3SWolfgang Pieb   }
220c2dfd502SJames Henderson   return createError(
221c2dfd502SJames Henderson       "no end of list marker detected at end of .debug_rnglists table "
222c2dfd502SJames Henderson       "starting at offset 0x%" PRIx32,
223a0729d41SWolfgang Pieb       HeaderOffset);
2243fb9e3f3SWolfgang Pieb }
2253fb9e3f3SWolfgang Pieb 
2263fb9e3f3SWolfgang Pieb Error DWARFDebugRnglistTable::extract(DWARFDataExtractor Data,
2273fb9e3f3SWolfgang Pieb                                       uint32_t *OffsetPtr) {
2283fb9e3f3SWolfgang Pieb   clear();
2293fb9e3f3SWolfgang Pieb   if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
2303fb9e3f3SWolfgang Pieb     return E;
2313fb9e3f3SWolfgang Pieb 
2323fb9e3f3SWolfgang Pieb   Data.setAddressSize(HeaderData.AddrSize);
2333fb9e3f3SWolfgang Pieb   uint32_t End = HeaderOffset + length();
2343fb9e3f3SWolfgang Pieb   while (*OffsetPtr < End) {
2353fb9e3f3SWolfgang Pieb     DWARFDebugRnglist CurrentRangeList;
2363fb9e3f3SWolfgang Pieb     uint32_t Off = *OffsetPtr;
2373fb9e3f3SWolfgang Pieb     if (Error E = CurrentRangeList.extract(Data, HeaderOffset, End, OffsetPtr))
2383fb9e3f3SWolfgang Pieb       return E;
2393fb9e3f3SWolfgang Pieb     Ranges[Off] = CurrentRangeList;
2403fb9e3f3SWolfgang Pieb   }
2413fb9e3f3SWolfgang Pieb 
2423fb9e3f3SWolfgang Pieb   assert(*OffsetPtr == End &&
2433fb9e3f3SWolfgang Pieb          "mismatch between expected length of .debug_rnglists table and length "
2443fb9e3f3SWolfgang Pieb          "of extracted data");
245c2dfd502SJames Henderson   return Error::success();
246c2dfd502SJames Henderson }
247c2dfd502SJames Henderson 
248a0729d41SWolfgang Pieb static void dumpRangeEntry(raw_ostream &OS,
2493fb9e3f3SWolfgang Pieb                            DWARFDebugRnglist::RangeListEntry Entry,
250a0729d41SWolfgang Pieb                            uint8_t AddrSize, uint8_t MaxEncodingStringLength,
251ab068eaaSWolfgang Pieb                            uint64_t &CurrentBase, DIDumpOptions DumpOpts) {
252ab068eaaSWolfgang Pieb   auto PrintRawEntry = [](raw_ostream &OS,
2533fb9e3f3SWolfgang Pieb                           DWARFDebugRnglist::RangeListEntry Entry,
254ab068eaaSWolfgang Pieb                           uint8_t AddrSize, DIDumpOptions DumpOpts) {
255ab068eaaSWolfgang Pieb     if (DumpOpts.Verbose) {
256ab068eaaSWolfgang Pieb       DumpOpts.DisplayRawContents = true;
257ab068eaaSWolfgang Pieb       DWARFAddressRange(Entry.Value0, Entry.Value1)
258ab068eaaSWolfgang Pieb           .dump(OS, AddrSize, DumpOpts);
259ab068eaaSWolfgang Pieb       OS << " => ";
260ab068eaaSWolfgang Pieb     }
261ab068eaaSWolfgang Pieb   };
262ab068eaaSWolfgang Pieb 
263a0729d41SWolfgang Pieb   if (DumpOpts.Verbose) {
264a0729d41SWolfgang Pieb     // Print the section offset in verbose mode.
265a0729d41SWolfgang Pieb     OS << format("0x%8.8" PRIx32 ":", Entry.Offset);
266a0729d41SWolfgang Pieb     auto EncodingString = dwarf::RangeListEncodingString(Entry.EntryKind);
267a0729d41SWolfgang Pieb     // Unsupported encodings should have been reported during parsing.
268a0729d41SWolfgang Pieb     assert(!EncodingString.empty() && "Unknown range entry encoding");
269a0729d41SWolfgang Pieb     OS << format(" [%s%*c", EncodingString.data(),
270a0729d41SWolfgang Pieb                  MaxEncodingStringLength - EncodingString.size() + 1, ']');
271a0729d41SWolfgang Pieb     if (Entry.EntryKind != dwarf::DW_RLE_end_of_list)
272a0729d41SWolfgang Pieb       OS << ": ";
273a0729d41SWolfgang Pieb   }
274a0729d41SWolfgang Pieb 
275a0729d41SWolfgang Pieb   switch (Entry.EntryKind) {
276a0729d41SWolfgang Pieb   case dwarf::DW_RLE_end_of_list:
277a0729d41SWolfgang Pieb     OS << (DumpOpts.Verbose ? "" : "<End of list>");
278a0729d41SWolfgang Pieb     break;
279ab068eaaSWolfgang Pieb   case dwarf::DW_RLE_base_address:
280ab068eaaSWolfgang Pieb     // In non-verbose mode we do not print anything for this entry.
281ab068eaaSWolfgang Pieb     CurrentBase = Entry.Value0;
282ab068eaaSWolfgang Pieb     if (!DumpOpts.Verbose)
283ab068eaaSWolfgang Pieb       return;
284ab068eaaSWolfgang Pieb     OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Entry.Value0);
285ab068eaaSWolfgang Pieb     break;
286a0729d41SWolfgang Pieb   case dwarf::DW_RLE_start_length:
287ab068eaaSWolfgang Pieb     PrintRawEntry(OS, Entry, AddrSize, DumpOpts);
288a0729d41SWolfgang Pieb     DWARFAddressRange(Entry.Value0, Entry.Value0 + Entry.Value1)
289a0729d41SWolfgang Pieb         .dump(OS, AddrSize, DumpOpts);
290a0729d41SWolfgang Pieb     break;
291ab068eaaSWolfgang Pieb   case dwarf::DW_RLE_offset_pair:
292ab068eaaSWolfgang Pieb     PrintRawEntry(OS, Entry, AddrSize, DumpOpts);
293ab068eaaSWolfgang Pieb     DWARFAddressRange(Entry.Value0 + CurrentBase, Entry.Value1 + CurrentBase)
294ab068eaaSWolfgang Pieb         .dump(OS, AddrSize, DumpOpts);
295ab068eaaSWolfgang Pieb     break;
296a0729d41SWolfgang Pieb   case dwarf::DW_RLE_start_end:
297a0729d41SWolfgang Pieb     DWARFAddressRange(Entry.Value0, Entry.Value1).dump(OS, AddrSize, DumpOpts);
298a0729d41SWolfgang Pieb     break;
299a0729d41SWolfgang Pieb   default:
300a0729d41SWolfgang Pieb     llvm_unreachable("Unsupported range list encoding");
301a0729d41SWolfgang Pieb   }
302a0729d41SWolfgang Pieb   OS << "\n";
303a0729d41SWolfgang Pieb }
304a0729d41SWolfgang Pieb 
3053fb9e3f3SWolfgang Pieb void DWARFDebugRnglistTable::dump(raw_ostream &OS,
3063fb9e3f3SWolfgang Pieb                                   DIDumpOptions DumpOpts) const {
307a0729d41SWolfgang Pieb   if (DumpOpts.Verbose)
308a0729d41SWolfgang Pieb     OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
30910392cdbSJames Henderson   OS << format("Range List Header: length = 0x%8.8" PRIx32
31010392cdbSJames Henderson                ", version = 0x%4.4" PRIx16 ", "
31110392cdbSJames Henderson                "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8
31210392cdbSJames Henderson                ", offset_entry_count = "
31310392cdbSJames Henderson                "0x%8.8" PRIx32 "\n",
314c2dfd502SJames Henderson                HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
315c2dfd502SJames Henderson                HeaderData.SegSize, HeaderData.OffsetEntryCount);
316c2dfd502SJames Henderson 
317c2dfd502SJames Henderson   if (HeaderData.OffsetEntryCount > 0) {
318c2dfd502SJames Henderson     OS << "Offsets: [";
319a0729d41SWolfgang Pieb     for (const auto &Off : Offsets) {
32010392cdbSJames Henderson       OS << format("\n0x%8.8" PRIx32, Off);
321a0729d41SWolfgang Pieb       if (DumpOpts.Verbose)
322a0729d41SWolfgang Pieb         OS << format(" => 0x%8.8" PRIx32,
323a0729d41SWolfgang Pieb                      Off + HeaderOffset + sizeof(HeaderData));
324a0729d41SWolfgang Pieb     }
325c2dfd502SJames Henderson     OS << "\n]\n";
326c2dfd502SJames Henderson   }
327c2dfd502SJames Henderson   OS << "Ranges:\n";
328c2dfd502SJames Henderson 
3293fb9e3f3SWolfgang Pieb   // Determine the length of the longest encoding string we have in the table,
3303fb9e3f3SWolfgang Pieb   // so we can align the output properly. We only need this in verbose mode.
3313fb9e3f3SWolfgang Pieb   size_t MaxEncodingStringLength = 0;
3323fb9e3f3SWolfgang Pieb   if (DumpOpts.Verbose) {
3333fb9e3f3SWolfgang Pieb     for (const auto &List : Ranges)
3343fb9e3f3SWolfgang Pieb       for (const auto &Entry : List.second.getEntries())
3353fb9e3f3SWolfgang Pieb         MaxEncodingStringLength =
3363fb9e3f3SWolfgang Pieb             std::max(MaxEncodingStringLength,
3373fb9e3f3SWolfgang Pieb                      dwarf::RangeListEncodingString(Entry.EntryKind).size());
3383fb9e3f3SWolfgang Pieb   }
3393fb9e3f3SWolfgang Pieb 
340ab068eaaSWolfgang Pieb   uint64_t CurrentBase = 0;
341a0729d41SWolfgang Pieb   for (const auto &List : Ranges)
3423fb9e3f3SWolfgang Pieb     for (const auto &Entry : List.second.getEntries())
343a0729d41SWolfgang Pieb       dumpRangeEntry(OS, Entry, HeaderData.AddrSize, MaxEncodingStringLength,
344ab068eaaSWolfgang Pieb                      CurrentBase, DumpOpts);
345c2dfd502SJames Henderson }
346c2dfd502SJames Henderson 
3473fb9e3f3SWolfgang Pieb uint32_t DWARFDebugRnglistTable::length() const {
348c2dfd502SJames Henderson   if (HeaderData.Length == 0)
349c2dfd502SJames Henderson     return 0;
350c2dfd502SJames Henderson   // TODO: DWARF64 support.
351c2dfd502SJames Henderson   return HeaderData.Length + sizeof(uint32_t);
352c2dfd502SJames Henderson }
353*ad60559bSWolfgang Pieb 
354*ad60559bSWolfgang Pieb Optional<DWARFDebugRnglist>
355*ad60559bSWolfgang Pieb DWARFDebugRnglistTable::findRangeList(DWARFDataExtractor Data,
356*ad60559bSWolfgang Pieb                                       uint32_t Offset) {
357*ad60559bSWolfgang Pieb   auto Entry = Ranges.find(Offset);
358*ad60559bSWolfgang Pieb   if (Entry != Ranges.end())
359*ad60559bSWolfgang Pieb     return Entry->second;
360*ad60559bSWolfgang Pieb 
361*ad60559bSWolfgang Pieb   // Extract the rangelist from the section and enter it into the ranges map.
362*ad60559bSWolfgang Pieb   DWARFDebugRnglist RngList;
363*ad60559bSWolfgang Pieb   uint32_t End = HeaderOffset + length();
364*ad60559bSWolfgang Pieb   uint32_t StartingOffset = Offset;
365*ad60559bSWolfgang Pieb   if (Error E = RngList.extract(Data, HeaderOffset, End, &Offset)) {
366*ad60559bSWolfgang Pieb     llvm::consumeError(std::move(E));
367*ad60559bSWolfgang Pieb     return None;
368*ad60559bSWolfgang Pieb   }
369*ad60559bSWolfgang Pieb   Ranges[StartingOffset] = RngList;
370*ad60559bSWolfgang Pieb   return RngList;
371*ad60559bSWolfgang Pieb }
372