xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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