1 //===- DWARFDebugRnglists.cpp ---------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
11 #include "llvm/BinaryFormat/Dwarf.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"
20 Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
21 uint32_t *OffsetPtr) {
24 // The caller should guarantee that we have at least 1 byte available, so
25 // we just assert instead of revalidate.
26 assert(*OffsetPtr < End &&
27 "not enough space to extract a rangelist encoding");
28 uint8_t Encoding = Data.getU8(OffsetPtr);
31 case dwarf::DW_RLE_end_of_list:
34 // TODO: Support other encodings.
35 case dwarf::DW_RLE_base_addressx: {
36 uint32_t PreviousOffset = *OffsetPtr - 1;
37 Value0 = Data.getULEB128(OffsetPtr);
39 return createStringError(
40 errc::invalid_argument,
41 "read past end of table when reading "
42 "DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
46 case dwarf::DW_RLE_startx_endx:
47 return createStringError(errc::not_supported,
48 "unsupported rnglists encoding DW_RLE_startx_endx at "
51 case dwarf::DW_RLE_startx_length: {
52 uint32_t PreviousOffset = *OffsetPtr - 1;
53 Value0 = Data.getULEB128(OffsetPtr);
54 Value1 = Data.getULEB128(OffsetPtr);
56 return createStringError(
57 errc::invalid_argument,
58 "read past end of table when reading "
59 "DW_RLE_startx_length encoding at offset 0x%" PRIx32,
63 case dwarf::DW_RLE_offset_pair: {
64 uint32_t PreviousOffset = *OffsetPtr - 1;
65 Value0 = Data.getULEB128(OffsetPtr);
66 Value1 = Data.getULEB128(OffsetPtr);
68 return createStringError(errc::invalid_argument,
69 "read past end of table when reading "
70 "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
74 case dwarf::DW_RLE_base_address: {
75 if ((End - *OffsetPtr) < Data.getAddressSize())
76 return createStringError(errc::invalid_argument,
77 "insufficient space remaining in table for "
78 "DW_RLE_base_address encoding at offset 0x%" PRIx32,
80 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
83 case dwarf::DW_RLE_start_end: {
84 if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
85 return createStringError(errc::invalid_argument,
86 "insufficient space remaining in table for "
87 "DW_RLE_start_end encoding "
88 "at offset 0x%" PRIx32,
90 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
91 Value1 = Data.getRelocatedAddress(OffsetPtr);
94 case dwarf::DW_RLE_start_length: {
95 uint32_t PreviousOffset = *OffsetPtr - 1;
96 Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
97 Value1 = Data.getULEB128(OffsetPtr);
99 return createStringError(errc::invalid_argument,
100 "read past end of table when reading "
101 "DW_RLE_start_length encoding at offset 0x%" PRIx32,
106 return createStringError(errc::not_supported,
107 "unknown rnglists encoding 0x%" PRIx32
108 " at offset 0x%" PRIx32,
109 uint32_t(Encoding), *OffsetPtr - 1);
112 EntryKind = Encoding;
113 return Error::success();
116 DWARFAddressRangesVector
117 DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
118 DWARFUnit &U) const {
119 DWARFAddressRangesVector Res;
120 for (const RangeListEntry &RLE : Entries) {
121 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
123 if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
124 BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
126 BaseAddr = {RLE.Value0, -1ULL};
129 if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
130 BaseAddr = {RLE.Value0, RLE.SectionIndex};
135 E.SectionIndex = RLE.SectionIndex;
136 if (BaseAddr && E.SectionIndex == -1ULL)
137 E.SectionIndex = BaseAddr->SectionIndex;
139 switch (RLE.EntryKind) {
140 case dwarf::DW_RLE_offset_pair:
141 E.LowPC = RLE.Value0;
142 E.HighPC = RLE.Value1;
144 E.LowPC += BaseAddr->Address;
145 E.HighPC += BaseAddr->Address;
148 case dwarf::DW_RLE_start_end:
149 E.LowPC = RLE.Value0;
150 E.HighPC = RLE.Value1;
152 case dwarf::DW_RLE_start_length:
153 E.LowPC = RLE.Value0;
154 E.HighPC = E.LowPC + RLE.Value1;
156 case dwarf::DW_RLE_startx_length: {
157 auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
160 E.SectionIndex = Start->SectionIndex;
161 E.LowPC = Start->Address;
162 E.HighPC = E.LowPC + RLE.Value1;
166 // Unsupported encodings should have been reported during extraction,
167 // so we should not run into any here.
168 llvm_unreachable("Unsupported range list encoding");
175 void RangeListEntry::dump(
176 raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
177 uint64_t &CurrentBase, DIDumpOptions DumpOpts,
178 llvm::function_ref<Optional<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);
190 if (DumpOpts.Verbose) {
191 // Print the section offset in verbose mode.
192 OS << format("0x%8.8" PRIx32 ":", 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)
203 case dwarf::DW_RLE_end_of_list:
204 OS << (DumpOpts.Verbose ? "" : "<End of list>");
206 // case dwarf::DW_RLE_base_addressx:
207 case dwarf::DW_RLE_base_addressx: {
208 if (auto SA = LookupPooledAddress(Value0))
209 CurrentBase = SA->Address;
211 CurrentBase = Value0;
212 if (!DumpOpts.Verbose)
214 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
217 case dwarf::DW_RLE_base_address:
218 // In non-verbose mode we do not print anything for this entry.
219 CurrentBase = Value0;
220 if (!DumpOpts.Verbose)
222 OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
224 case dwarf::DW_RLE_start_length:
225 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
226 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
228 case dwarf::DW_RLE_offset_pair:
229 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
230 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
231 .dump(OS, AddrSize, DumpOpts);
233 case dwarf::DW_RLE_start_end:
234 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
236 case dwarf::DW_RLE_startx_length: {
237 PrintRawEntry(OS, *this, AddrSize, DumpOpts);
239 if (auto SA = LookupPooledAddress(Value0))
241 DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
245 llvm_unreachable("Unsupported range list encoding");