10b57cec5SDimitry Andric //===- DWARFDebugRnglists.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
100b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
11e8d8bef9SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
130b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
140b57cec5SDimitry Andric #include "llvm/Support/Error.h"
150b57cec5SDimitry Andric #include "llvm/Support/Format.h"
160b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric
extract(DWARFDataExtractor Data,uint64_t * OffsetPtr)20e8d8bef9SDimitry Andric Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
210b57cec5SDimitry Andric Offset = *OffsetPtr;
220b57cec5SDimitry Andric SectionIndex = -1ULL;
230b57cec5SDimitry Andric // The caller should guarantee that we have at least 1 byte available, so
240b57cec5SDimitry Andric // we just assert instead of revalidate.
25e8d8bef9SDimitry Andric assert(*OffsetPtr < Data.size() &&
260b57cec5SDimitry Andric "not enough space to extract a rangelist encoding");
270b57cec5SDimitry Andric uint8_t Encoding = Data.getU8(OffsetPtr);
280b57cec5SDimitry Andric
29e8d8bef9SDimitry Andric DataExtractor::Cursor C(*OffsetPtr);
300b57cec5SDimitry Andric switch (Encoding) {
310b57cec5SDimitry Andric case dwarf::DW_RLE_end_of_list:
320b57cec5SDimitry Andric Value0 = Value1 = 0;
330b57cec5SDimitry Andric break;
340b57cec5SDimitry Andric // TODO: Support other encodings.
350b57cec5SDimitry Andric case dwarf::DW_RLE_base_addressx: {
36e8d8bef9SDimitry Andric Value0 = Data.getULEB128(C);
370b57cec5SDimitry Andric break;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric case dwarf::DW_RLE_startx_endx:
40e8d8bef9SDimitry Andric Value0 = Data.getULEB128(C);
41e8d8bef9SDimitry Andric Value1 = Data.getULEB128(C);
42e8d8bef9SDimitry Andric break;
430b57cec5SDimitry Andric case dwarf::DW_RLE_startx_length: {
44e8d8bef9SDimitry Andric Value0 = Data.getULEB128(C);
45e8d8bef9SDimitry Andric Value1 = Data.getULEB128(C);
460b57cec5SDimitry Andric break;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric case dwarf::DW_RLE_offset_pair: {
49e8d8bef9SDimitry Andric Value0 = Data.getULEB128(C);
50e8d8bef9SDimitry Andric Value1 = Data.getULEB128(C);
510b57cec5SDimitry Andric break;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric case dwarf::DW_RLE_base_address: {
54e8d8bef9SDimitry Andric Value0 = Data.getRelocatedAddress(C, &SectionIndex);
550b57cec5SDimitry Andric break;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric case dwarf::DW_RLE_start_end: {
58e8d8bef9SDimitry Andric Value0 = Data.getRelocatedAddress(C, &SectionIndex);
59e8d8bef9SDimitry Andric Value1 = Data.getRelocatedAddress(C);
600b57cec5SDimitry Andric break;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric case dwarf::DW_RLE_start_length: {
63e8d8bef9SDimitry Andric Value0 = Data.getRelocatedAddress(C, &SectionIndex);
64e8d8bef9SDimitry Andric Value1 = Data.getULEB128(C);
650b57cec5SDimitry Andric break;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric default:
68e8d8bef9SDimitry Andric consumeError(C.takeError());
690b57cec5SDimitry Andric return createStringError(errc::not_supported,
700b57cec5SDimitry Andric "unknown rnglists encoding 0x%" PRIx32
718bcb0991SDimitry Andric " at offset 0x%" PRIx64,
72e8d8bef9SDimitry Andric uint32_t(Encoding), Offset);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
75e8d8bef9SDimitry Andric if (!C) {
76e8d8bef9SDimitry Andric consumeError(C.takeError());
77e8d8bef9SDimitry Andric return createStringError(
78e8d8bef9SDimitry Andric errc::invalid_argument,
79e8d8bef9SDimitry Andric "read past end of table when reading %s encoding at offset 0x%" PRIx64,
80e8d8bef9SDimitry Andric dwarf::RLEString(Encoding).data(), Offset);
81e8d8bef9SDimitry Andric }
82e8d8bef9SDimitry Andric
83e8d8bef9SDimitry Andric *OffsetPtr = C.tell();
840b57cec5SDimitry Andric EntryKind = Encoding;
850b57cec5SDimitry Andric return Error::success();
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
getAbsoluteRanges(std::optional<object::SectionedAddress> BaseAddr,DWARFUnit & U) const880b57cec5SDimitry Andric DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
89*bdd1243dSDimitry Andric std::optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
90e8d8bef9SDimitry Andric return getAbsoluteRanges(
91e8d8bef9SDimitry Andric BaseAddr, U.getAddressByteSize(),
92e8d8bef9SDimitry Andric [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
93480093f4SDimitry Andric }
94480093f4SDimitry Andric
getAbsoluteRanges(std::optional<object::SectionedAddress> BaseAddr,uint8_t AddressByteSize,function_ref<std::optional<object::SectionedAddress> (uint32_t)> LookupPooledAddress) const95480093f4SDimitry Andric DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
96*bdd1243dSDimitry Andric std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
97*bdd1243dSDimitry Andric function_ref<std::optional<object::SectionedAddress>(uint32_t)>
98480093f4SDimitry Andric LookupPooledAddress) const {
990b57cec5SDimitry Andric DWARFAddressRangesVector Res;
100e8d8bef9SDimitry Andric uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
1010b57cec5SDimitry Andric for (const RangeListEntry &RLE : Entries) {
1020b57cec5SDimitry Andric if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
1030b57cec5SDimitry Andric break;
1040b57cec5SDimitry Andric if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
105480093f4SDimitry Andric BaseAddr = LookupPooledAddress(RLE.Value0);
1060b57cec5SDimitry Andric if (!BaseAddr)
1070b57cec5SDimitry Andric BaseAddr = {RLE.Value0, -1ULL};
1080b57cec5SDimitry Andric continue;
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
1110b57cec5SDimitry Andric BaseAddr = {RLE.Value0, RLE.SectionIndex};
1120b57cec5SDimitry Andric continue;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric DWARFAddressRange E;
1160b57cec5SDimitry Andric E.SectionIndex = RLE.SectionIndex;
1170b57cec5SDimitry Andric if (BaseAddr && E.SectionIndex == -1ULL)
1180b57cec5SDimitry Andric E.SectionIndex = BaseAddr->SectionIndex;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric switch (RLE.EntryKind) {
1210b57cec5SDimitry Andric case dwarf::DW_RLE_offset_pair:
1220b57cec5SDimitry Andric E.LowPC = RLE.Value0;
123e8d8bef9SDimitry Andric if (E.LowPC == Tombstone)
124e8d8bef9SDimitry Andric continue;
1250b57cec5SDimitry Andric E.HighPC = RLE.Value1;
1260b57cec5SDimitry Andric if (BaseAddr) {
127e8d8bef9SDimitry Andric if (BaseAddr->Address == Tombstone)
128e8d8bef9SDimitry Andric continue;
1290b57cec5SDimitry Andric E.LowPC += BaseAddr->Address;
1300b57cec5SDimitry Andric E.HighPC += BaseAddr->Address;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric break;
1330b57cec5SDimitry Andric case dwarf::DW_RLE_start_end:
1340b57cec5SDimitry Andric E.LowPC = RLE.Value0;
1350b57cec5SDimitry Andric E.HighPC = RLE.Value1;
1360b57cec5SDimitry Andric break;
1370b57cec5SDimitry Andric case dwarf::DW_RLE_start_length:
1380b57cec5SDimitry Andric E.LowPC = RLE.Value0;
1390b57cec5SDimitry Andric E.HighPC = E.LowPC + RLE.Value1;
1400b57cec5SDimitry Andric break;
1410b57cec5SDimitry Andric case dwarf::DW_RLE_startx_length: {
142480093f4SDimitry Andric auto Start = LookupPooledAddress(RLE.Value0);
1430b57cec5SDimitry Andric if (!Start)
1440b57cec5SDimitry Andric Start = {0, -1ULL};
1450b57cec5SDimitry Andric E.SectionIndex = Start->SectionIndex;
1460b57cec5SDimitry Andric E.LowPC = Start->Address;
1470b57cec5SDimitry Andric E.HighPC = E.LowPC + RLE.Value1;
1480b57cec5SDimitry Andric break;
1490b57cec5SDimitry Andric }
150e8d8bef9SDimitry Andric case dwarf::DW_RLE_startx_endx: {
151e8d8bef9SDimitry Andric auto Start = LookupPooledAddress(RLE.Value0);
152e8d8bef9SDimitry Andric if (!Start)
153e8d8bef9SDimitry Andric Start = {0, -1ULL};
154e8d8bef9SDimitry Andric auto End = LookupPooledAddress(RLE.Value1);
155e8d8bef9SDimitry Andric if (!End)
156e8d8bef9SDimitry Andric End = {0, -1ULL};
157e8d8bef9SDimitry Andric // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
158e8d8bef9SDimitry Andric E.SectionIndex = Start->SectionIndex;
159e8d8bef9SDimitry Andric E.LowPC = Start->Address;
160e8d8bef9SDimitry Andric E.HighPC = End->Address;
161e8d8bef9SDimitry Andric break;
162e8d8bef9SDimitry Andric }
1630b57cec5SDimitry Andric default:
1640b57cec5SDimitry Andric // Unsupported encodings should have been reported during extraction,
1650b57cec5SDimitry Andric // so we should not run into any here.
1660b57cec5SDimitry Andric llvm_unreachable("Unsupported range list encoding");
1670b57cec5SDimitry Andric }
168e8d8bef9SDimitry Andric if (E.LowPC == Tombstone)
169e8d8bef9SDimitry Andric continue;
1700b57cec5SDimitry Andric Res.push_back(E);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric return Res;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
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) const1750b57cec5SDimitry Andric void RangeListEntry::dump(
1760b57cec5SDimitry Andric raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
1770b57cec5SDimitry Andric uint64_t &CurrentBase, DIDumpOptions DumpOpts,
178*bdd1243dSDimitry Andric llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
1790b57cec5SDimitry Andric LookupPooledAddress) const {
1800b57cec5SDimitry Andric auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
1810b57cec5SDimitry Andric uint8_t AddrSize, DIDumpOptions DumpOpts) {
1820b57cec5SDimitry Andric if (DumpOpts.Verbose) {
1830b57cec5SDimitry Andric DumpOpts.DisplayRawContents = true;
1840b57cec5SDimitry Andric DWARFAddressRange(Entry.Value0, Entry.Value1)
1850b57cec5SDimitry Andric .dump(OS, AddrSize, DumpOpts);
1860b57cec5SDimitry Andric OS << " => ";
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric };
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric if (DumpOpts.Verbose) {
1910b57cec5SDimitry Andric // Print the section offset in verbose mode.
1928bcb0991SDimitry Andric OS << format("0x%8.8" PRIx64 ":", Offset);
1930b57cec5SDimitry Andric auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
1940b57cec5SDimitry Andric // Unsupported encodings should have been reported during parsing.
1950b57cec5SDimitry Andric assert(!EncodingString.empty() && "Unknown range entry encoding");
1960b57cec5SDimitry Andric OS << format(" [%s%*c", EncodingString.data(),
1970b57cec5SDimitry Andric MaxEncodingStringLength - EncodingString.size() + 1, ']');
1980b57cec5SDimitry Andric if (EntryKind != dwarf::DW_RLE_end_of_list)
1990b57cec5SDimitry Andric OS << ": ";
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
202e8d8bef9SDimitry Andric uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
203e8d8bef9SDimitry Andric
2040b57cec5SDimitry Andric switch (EntryKind) {
2050b57cec5SDimitry Andric case dwarf::DW_RLE_end_of_list:
2060b57cec5SDimitry Andric OS << (DumpOpts.Verbose ? "" : "<End of list>");
2070b57cec5SDimitry Andric break;
2080b57cec5SDimitry Andric case dwarf::DW_RLE_base_addressx: {
2090b57cec5SDimitry Andric if (auto SA = LookupPooledAddress(Value0))
2100b57cec5SDimitry Andric CurrentBase = SA->Address;
2110b57cec5SDimitry Andric else
2120b57cec5SDimitry Andric CurrentBase = Value0;
2130b57cec5SDimitry Andric if (!DumpOpts.Verbose)
2140b57cec5SDimitry Andric return;
215e8d8bef9SDimitry Andric DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
2160b57cec5SDimitry Andric break;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric case dwarf::DW_RLE_base_address:
2190b57cec5SDimitry Andric // In non-verbose mode we do not print anything for this entry.
2200b57cec5SDimitry Andric CurrentBase = Value0;
2210b57cec5SDimitry Andric if (!DumpOpts.Verbose)
2220b57cec5SDimitry Andric return;
223e8d8bef9SDimitry Andric DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
2240b57cec5SDimitry Andric break;
2250b57cec5SDimitry Andric case dwarf::DW_RLE_start_length:
2260b57cec5SDimitry Andric PrintRawEntry(OS, *this, AddrSize, DumpOpts);
2270b57cec5SDimitry Andric DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric case dwarf::DW_RLE_offset_pair:
2300b57cec5SDimitry Andric PrintRawEntry(OS, *this, AddrSize, DumpOpts);
231e8d8bef9SDimitry Andric if (CurrentBase != Tombstone)
2320b57cec5SDimitry Andric DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
2330b57cec5SDimitry Andric .dump(OS, AddrSize, DumpOpts);
234e8d8bef9SDimitry Andric else
235e8d8bef9SDimitry Andric OS << "dead code";
2360b57cec5SDimitry Andric break;
2370b57cec5SDimitry Andric case dwarf::DW_RLE_start_end:
2380b57cec5SDimitry Andric DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
2390b57cec5SDimitry Andric break;
2400b57cec5SDimitry Andric case dwarf::DW_RLE_startx_length: {
2410b57cec5SDimitry Andric PrintRawEntry(OS, *this, AddrSize, DumpOpts);
2420b57cec5SDimitry Andric uint64_t Start = 0;
2430b57cec5SDimitry Andric if (auto SA = LookupPooledAddress(Value0))
2440b57cec5SDimitry Andric Start = SA->Address;
2450b57cec5SDimitry Andric DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
2460b57cec5SDimitry Andric break;
2470b57cec5SDimitry Andric }
248e8d8bef9SDimitry Andric case dwarf::DW_RLE_startx_endx: {
249e8d8bef9SDimitry Andric PrintRawEntry(OS, *this, AddrSize, DumpOpts);
250e8d8bef9SDimitry Andric uint64_t Start = 0;
251e8d8bef9SDimitry Andric if (auto SA = LookupPooledAddress(Value0))
252e8d8bef9SDimitry Andric Start = SA->Address;
253e8d8bef9SDimitry Andric uint64_t End = 0;
254e8d8bef9SDimitry Andric if (auto SA = LookupPooledAddress(Value1))
255e8d8bef9SDimitry Andric End = SA->Address;
256e8d8bef9SDimitry Andric DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
257e8d8bef9SDimitry Andric break;
258e8d8bef9SDimitry Andric }
2590b57cec5SDimitry Andric default:
2600b57cec5SDimitry Andric llvm_unreachable("Unsupported range list encoding");
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric OS << "\n";
2630b57cec5SDimitry Andric }
264