xref: /openbsd-src/gnu/llvm/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- DWARFDebugRnglists.cpp ---------------------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
1009467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
1173471bf0Spatrick #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
1209467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
1309467b48Spatrick #include "llvm/Support/Errc.h"
1409467b48Spatrick #include "llvm/Support/Error.h"
1509467b48Spatrick #include "llvm/Support/Format.h"
1609467b48Spatrick #include "llvm/Support/raw_ostream.h"
1709467b48Spatrick 
1809467b48Spatrick using namespace llvm;
1909467b48Spatrick 
extract(DWARFDataExtractor Data,uint64_t * OffsetPtr)2073471bf0Spatrick Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
2109467b48Spatrick   Offset = *OffsetPtr;
2209467b48Spatrick   SectionIndex = -1ULL;
2309467b48Spatrick   // The caller should guarantee that we have at least 1 byte available, so
2409467b48Spatrick   // we just assert instead of revalidate.
2573471bf0Spatrick   assert(*OffsetPtr < Data.size() &&
2609467b48Spatrick          "not enough space to extract a rangelist encoding");
2709467b48Spatrick   uint8_t Encoding = Data.getU8(OffsetPtr);
2809467b48Spatrick 
2973471bf0Spatrick   DataExtractor::Cursor C(*OffsetPtr);
3009467b48Spatrick   switch (Encoding) {
3109467b48Spatrick   case dwarf::DW_RLE_end_of_list:
3209467b48Spatrick     Value0 = Value1 = 0;
3309467b48Spatrick     break;
3409467b48Spatrick   // TODO: Support other encodings.
3509467b48Spatrick   case dwarf::DW_RLE_base_addressx: {
3673471bf0Spatrick     Value0 = Data.getULEB128(C);
3709467b48Spatrick     break;
3809467b48Spatrick   }
3909467b48Spatrick   case dwarf::DW_RLE_startx_endx:
4073471bf0Spatrick     Value0 = Data.getULEB128(C);
4173471bf0Spatrick     Value1 = Data.getULEB128(C);
4273471bf0Spatrick     break;
4309467b48Spatrick   case dwarf::DW_RLE_startx_length: {
4473471bf0Spatrick     Value0 = Data.getULEB128(C);
4573471bf0Spatrick     Value1 = Data.getULEB128(C);
4609467b48Spatrick     break;
4709467b48Spatrick   }
4809467b48Spatrick   case dwarf::DW_RLE_offset_pair: {
4973471bf0Spatrick     Value0 = Data.getULEB128(C);
5073471bf0Spatrick     Value1 = Data.getULEB128(C);
5109467b48Spatrick     break;
5209467b48Spatrick   }
5309467b48Spatrick   case dwarf::DW_RLE_base_address: {
5473471bf0Spatrick     Value0 = Data.getRelocatedAddress(C, &SectionIndex);
5509467b48Spatrick     break;
5609467b48Spatrick   }
5709467b48Spatrick   case dwarf::DW_RLE_start_end: {
5873471bf0Spatrick     Value0 = Data.getRelocatedAddress(C, &SectionIndex);
5973471bf0Spatrick     Value1 = Data.getRelocatedAddress(C);
6009467b48Spatrick     break;
6109467b48Spatrick   }
6209467b48Spatrick   case dwarf::DW_RLE_start_length: {
6373471bf0Spatrick     Value0 = Data.getRelocatedAddress(C, &SectionIndex);
6473471bf0Spatrick     Value1 = Data.getULEB128(C);
6509467b48Spatrick     break;
6609467b48Spatrick   }
6709467b48Spatrick   default:
6873471bf0Spatrick     consumeError(C.takeError());
6909467b48Spatrick     return createStringError(errc::not_supported,
7009467b48Spatrick                              "unknown rnglists encoding 0x%" PRIx32
7109467b48Spatrick                              " at offset 0x%" PRIx64,
7273471bf0Spatrick                              uint32_t(Encoding), Offset);
7309467b48Spatrick   }
7409467b48Spatrick 
7573471bf0Spatrick   if (!C) {
7673471bf0Spatrick     consumeError(C.takeError());
7773471bf0Spatrick     return createStringError(
7873471bf0Spatrick         errc::invalid_argument,
7973471bf0Spatrick         "read past end of table when reading %s encoding at offset 0x%" PRIx64,
8073471bf0Spatrick         dwarf::RLEString(Encoding).data(), Offset);
8173471bf0Spatrick   }
8273471bf0Spatrick 
8373471bf0Spatrick   *OffsetPtr = C.tell();
8409467b48Spatrick   EntryKind = Encoding;
8509467b48Spatrick   return Error::success();
8609467b48Spatrick }
8709467b48Spatrick 
getAbsoluteRanges(std::optional<object::SectionedAddress> BaseAddr,DWARFUnit & U) const8809467b48Spatrick DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
89*d415bd75Srobert     std::optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
9073471bf0Spatrick   return getAbsoluteRanges(
9173471bf0Spatrick       BaseAddr, U.getAddressByteSize(),
9273471bf0Spatrick       [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
9309467b48Spatrick }
9409467b48Spatrick 
getAbsoluteRanges(std::optional<object::SectionedAddress> BaseAddr,uint8_t AddressByteSize,function_ref<std::optional<object::SectionedAddress> (uint32_t)> LookupPooledAddress) const9509467b48Spatrick DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
96*d415bd75Srobert     std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
97*d415bd75Srobert     function_ref<std::optional<object::SectionedAddress>(uint32_t)>
9809467b48Spatrick         LookupPooledAddress) const {
9909467b48Spatrick   DWARFAddressRangesVector Res;
10073471bf0Spatrick   uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
10109467b48Spatrick   for (const RangeListEntry &RLE : Entries) {
10209467b48Spatrick     if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
10309467b48Spatrick       break;
10409467b48Spatrick     if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
10509467b48Spatrick       BaseAddr = LookupPooledAddress(RLE.Value0);
10609467b48Spatrick       if (!BaseAddr)
10709467b48Spatrick         BaseAddr = {RLE.Value0, -1ULL};
10809467b48Spatrick       continue;
10909467b48Spatrick     }
11009467b48Spatrick     if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
11109467b48Spatrick       BaseAddr = {RLE.Value0, RLE.SectionIndex};
11209467b48Spatrick       continue;
11309467b48Spatrick     }
11409467b48Spatrick 
11509467b48Spatrick     DWARFAddressRange E;
11609467b48Spatrick     E.SectionIndex = RLE.SectionIndex;
11709467b48Spatrick     if (BaseAddr && E.SectionIndex == -1ULL)
11809467b48Spatrick       E.SectionIndex = BaseAddr->SectionIndex;
11909467b48Spatrick 
12009467b48Spatrick     switch (RLE.EntryKind) {
12109467b48Spatrick     case dwarf::DW_RLE_offset_pair:
12209467b48Spatrick       E.LowPC = RLE.Value0;
12373471bf0Spatrick       if (E.LowPC == Tombstone)
12473471bf0Spatrick         continue;
12509467b48Spatrick       E.HighPC = RLE.Value1;
12609467b48Spatrick       if (BaseAddr) {
12773471bf0Spatrick         if (BaseAddr->Address == Tombstone)
12873471bf0Spatrick           continue;
12909467b48Spatrick         E.LowPC += BaseAddr->Address;
13009467b48Spatrick         E.HighPC += BaseAddr->Address;
13109467b48Spatrick       }
13209467b48Spatrick       break;
13309467b48Spatrick     case dwarf::DW_RLE_start_end:
13409467b48Spatrick       E.LowPC = RLE.Value0;
13509467b48Spatrick       E.HighPC = RLE.Value1;
13609467b48Spatrick       break;
13709467b48Spatrick     case dwarf::DW_RLE_start_length:
13809467b48Spatrick       E.LowPC = RLE.Value0;
13909467b48Spatrick       E.HighPC = E.LowPC + RLE.Value1;
14009467b48Spatrick       break;
14109467b48Spatrick     case dwarf::DW_RLE_startx_length: {
14209467b48Spatrick       auto Start = LookupPooledAddress(RLE.Value0);
14309467b48Spatrick       if (!Start)
14409467b48Spatrick         Start = {0, -1ULL};
14509467b48Spatrick       E.SectionIndex = Start->SectionIndex;
14609467b48Spatrick       E.LowPC = Start->Address;
14709467b48Spatrick       E.HighPC = E.LowPC + RLE.Value1;
14809467b48Spatrick       break;
14909467b48Spatrick     }
15073471bf0Spatrick     case dwarf::DW_RLE_startx_endx: {
15173471bf0Spatrick       auto Start = LookupPooledAddress(RLE.Value0);
15273471bf0Spatrick       if (!Start)
15373471bf0Spatrick         Start = {0, -1ULL};
15473471bf0Spatrick       auto End = LookupPooledAddress(RLE.Value1);
15573471bf0Spatrick       if (!End)
15673471bf0Spatrick         End = {0, -1ULL};
15773471bf0Spatrick       // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
15873471bf0Spatrick       E.SectionIndex = Start->SectionIndex;
15973471bf0Spatrick       E.LowPC = Start->Address;
16073471bf0Spatrick       E.HighPC = End->Address;
16173471bf0Spatrick       break;
16273471bf0Spatrick     }
16309467b48Spatrick     default:
16409467b48Spatrick       // Unsupported encodings should have been reported during extraction,
16509467b48Spatrick       // so we should not run into any here.
16609467b48Spatrick       llvm_unreachable("Unsupported range list encoding");
16709467b48Spatrick     }
16873471bf0Spatrick     if (E.LowPC == Tombstone)
16973471bf0Spatrick       continue;
17009467b48Spatrick     Res.push_back(E);
17109467b48Spatrick   }
17209467b48Spatrick   return Res;
17309467b48Spatrick }
17409467b48Spatrick 
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) const17509467b48Spatrick void RangeListEntry::dump(
17609467b48Spatrick     raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
17709467b48Spatrick     uint64_t &CurrentBase, DIDumpOptions DumpOpts,
178*d415bd75Srobert     llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
17909467b48Spatrick         LookupPooledAddress) const {
18009467b48Spatrick   auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
18109467b48Spatrick                           uint8_t AddrSize, DIDumpOptions DumpOpts) {
18209467b48Spatrick     if (DumpOpts.Verbose) {
18309467b48Spatrick       DumpOpts.DisplayRawContents = true;
18409467b48Spatrick       DWARFAddressRange(Entry.Value0, Entry.Value1)
18509467b48Spatrick           .dump(OS, AddrSize, DumpOpts);
18609467b48Spatrick       OS << " => ";
18709467b48Spatrick     }
18809467b48Spatrick   };
18909467b48Spatrick 
19009467b48Spatrick   if (DumpOpts.Verbose) {
19109467b48Spatrick     // Print the section offset in verbose mode.
19209467b48Spatrick     OS << format("0x%8.8" PRIx64 ":", Offset);
19309467b48Spatrick     auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
19409467b48Spatrick     // Unsupported encodings should have been reported during parsing.
19509467b48Spatrick     assert(!EncodingString.empty() && "Unknown range entry encoding");
19609467b48Spatrick     OS << format(" [%s%*c", EncodingString.data(),
19709467b48Spatrick                  MaxEncodingStringLength - EncodingString.size() + 1, ']');
19809467b48Spatrick     if (EntryKind != dwarf::DW_RLE_end_of_list)
19909467b48Spatrick       OS << ": ";
20009467b48Spatrick   }
20109467b48Spatrick 
20273471bf0Spatrick   uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
20373471bf0Spatrick 
20409467b48Spatrick   switch (EntryKind) {
20509467b48Spatrick   case dwarf::DW_RLE_end_of_list:
20609467b48Spatrick     OS << (DumpOpts.Verbose ? "" : "<End of list>");
20709467b48Spatrick     break;
20809467b48Spatrick   case dwarf::DW_RLE_base_addressx: {
20909467b48Spatrick     if (auto SA = LookupPooledAddress(Value0))
21009467b48Spatrick       CurrentBase = SA->Address;
21109467b48Spatrick     else
21209467b48Spatrick       CurrentBase = Value0;
21309467b48Spatrick     if (!DumpOpts.Verbose)
21409467b48Spatrick       return;
21573471bf0Spatrick     DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
21609467b48Spatrick     break;
21709467b48Spatrick   }
21809467b48Spatrick   case dwarf::DW_RLE_base_address:
21909467b48Spatrick     // In non-verbose mode we do not print anything for this entry.
22009467b48Spatrick     CurrentBase = Value0;
22109467b48Spatrick     if (!DumpOpts.Verbose)
22209467b48Spatrick       return;
22373471bf0Spatrick     DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
22409467b48Spatrick     break;
22509467b48Spatrick   case dwarf::DW_RLE_start_length:
22609467b48Spatrick     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
22709467b48Spatrick     DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
22809467b48Spatrick     break;
22909467b48Spatrick   case dwarf::DW_RLE_offset_pair:
23009467b48Spatrick     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
23173471bf0Spatrick     if (CurrentBase != Tombstone)
23209467b48Spatrick       DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
23309467b48Spatrick           .dump(OS, AddrSize, DumpOpts);
23473471bf0Spatrick     else
23573471bf0Spatrick       OS << "dead code";
23609467b48Spatrick     break;
23709467b48Spatrick   case dwarf::DW_RLE_start_end:
23809467b48Spatrick     DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
23909467b48Spatrick     break;
24009467b48Spatrick   case dwarf::DW_RLE_startx_length: {
24109467b48Spatrick     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
24209467b48Spatrick     uint64_t Start = 0;
24309467b48Spatrick     if (auto SA = LookupPooledAddress(Value0))
24409467b48Spatrick       Start = SA->Address;
24509467b48Spatrick     DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
24609467b48Spatrick     break;
24709467b48Spatrick   }
24873471bf0Spatrick   case dwarf::DW_RLE_startx_endx: {
24973471bf0Spatrick     PrintRawEntry(OS, *this, AddrSize, DumpOpts);
25073471bf0Spatrick     uint64_t Start = 0;
25173471bf0Spatrick     if (auto SA = LookupPooledAddress(Value0))
25273471bf0Spatrick       Start = SA->Address;
25373471bf0Spatrick     uint64_t End = 0;
25473471bf0Spatrick     if (auto SA = LookupPooledAddress(Value1))
25573471bf0Spatrick       End = SA->Address;
25673471bf0Spatrick     DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
25773471bf0Spatrick     break;
25873471bf0Spatrick   }
25909467b48Spatrick   default:
26009467b48Spatrick     llvm_unreachable("Unsupported range list encoding");
26109467b48Spatrick   }
26209467b48Spatrick   OS << "\n";
26309467b48Spatrick }
264