1c2dfd502SJames Henderson //===- DWARFDebugRnglists.cpp ---------------------------------------------===// 2c2dfd502SJames Henderson // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c2dfd502SJames Henderson // 7c2dfd502SJames Henderson //===----------------------------------------------------------------------===// 8c2dfd502SJames Henderson 9c2dfd502SJames Henderson #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 10c2dfd502SJames Henderson #include "llvm/BinaryFormat/Dwarf.h" 11ad60559bSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 12cba595daSVictor Leschuk #include "llvm/Support/Errc.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 19ad68a8b9SDavid Blaikie Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) { 203fb9e3f3SWolfgang Pieb Offset = *OffsetPtr; 21ad60559bSWolfgang Pieb SectionIndex = -1ULL; 223fb9e3f3SWolfgang Pieb // The caller should guarantee that we have at least 1 byte available, so 233fb9e3f3SWolfgang Pieb // we just assert instead of revalidate. 24ad68a8b9SDavid Blaikie assert(*OffsetPtr < Data.size() && 253fb9e3f3SWolfgang Pieb "not enough space to extract a rangelist encoding"); 26f39a9bbeSWolfgang Pieb uint8_t Encoding = Data.getU8(OffsetPtr); 273fb9e3f3SWolfgang Pieb 28ad68a8b9SDavid Blaikie DataExtractor::Cursor C(*OffsetPtr); 29c2dfd502SJames Henderson switch (Encoding) { 30c2dfd502SJames Henderson case dwarf::DW_RLE_end_of_list: 313fb9e3f3SWolfgang Pieb Value0 = Value1 = 0; 32c2dfd502SJames Henderson break; 33c2dfd502SJames Henderson // TODO: Support other encodings. 3459ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 35ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 3659ac2064SDavid Blaikie break; 3759ac2064SDavid Blaikie } 38c2dfd502SJames Henderson case dwarf::DW_RLE_startx_endx: 39ad68a8b9SDavid Blaikie consumeError(C.takeError()); 40ad68a8b9SDavid Blaikie return createStringError( 41ad68a8b9SDavid Blaikie errc::not_supported, 42cba595daSVictor Leschuk "unsupported rnglists encoding DW_RLE_startx_endx at " 43f26a70a5SIgor Kudrin "offset 0x%" PRIx64, 44ad68a8b9SDavid Blaikie Offset); 4559ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 46ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 47ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 4859ac2064SDavid Blaikie break; 4959ac2064SDavid Blaikie } 50ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: { 51ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 52ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 53ab068eaaSWolfgang Pieb break; 54ab068eaaSWolfgang Pieb } 55f39a9bbeSWolfgang Pieb case dwarf::DW_RLE_base_address: { 56ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 57ab068eaaSWolfgang Pieb break; 58f39a9bbeSWolfgang Pieb } 59f39a9bbeSWolfgang Pieb case dwarf::DW_RLE_start_end: { 60ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 61ad68a8b9SDavid Blaikie Value1 = Data.getRelocatedAddress(C); 62c2dfd502SJames Henderson break; 63f39a9bbeSWolfgang Pieb } 64c2dfd502SJames Henderson case dwarf::DW_RLE_start_length: { 65ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 66ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 67c2dfd502SJames Henderson break; 68c2dfd502SJames Henderson } 69c2dfd502SJames Henderson default: 70ad68a8b9SDavid Blaikie consumeError(C.takeError()); 71cba595daSVictor Leschuk return createStringError(errc::not_supported, 72cba595daSVictor Leschuk "unknown rnglists encoding 0x%" PRIx32 73f26a70a5SIgor Kudrin " at offset 0x%" PRIx64, 74ad68a8b9SDavid Blaikie uint32_t(Encoding), Offset); 75c2dfd502SJames Henderson } 763fb9e3f3SWolfgang Pieb 77ad68a8b9SDavid Blaikie if (!C) { 78ad68a8b9SDavid Blaikie consumeError(C.takeError()); 79ad68a8b9SDavid Blaikie return createStringError( 80ad68a8b9SDavid Blaikie errc::invalid_argument, 81ad68a8b9SDavid Blaikie "read past end of table when reading %s encoding at offset 0x%" PRIx64, 82ad68a8b9SDavid Blaikie dwarf::RLEString(Encoding).data(), Offset); 83ad68a8b9SDavid Blaikie } 84ad68a8b9SDavid Blaikie 85ad68a8b9SDavid Blaikie *OffsetPtr = C.tell(); 863fb9e3f3SWolfgang Pieb EntryKind = Encoding; 873fb9e3f3SWolfgang Pieb return Error::success(); 88c2dfd502SJames Henderson } 89c2dfd502SJames Henderson 9077fc1f60SAlexey Lapshin DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( 9177fc1f60SAlexey Lapshin llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const { 92*8036cf7fSDavid Blaikie return getAbsoluteRanges( 93*8036cf7fSDavid Blaikie BaseAddr, U.getAddressByteSize(), 94*8036cf7fSDavid Blaikie [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); }); 95d34927e7SPavel Labath } 96d34927e7SPavel Labath 97d34927e7SPavel Labath DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( 98*8036cf7fSDavid Blaikie Optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize, 99d34927e7SPavel Labath function_ref<Optional<object::SectionedAddress>(uint32_t)> 100d34927e7SPavel Labath LookupPooledAddress) const { 101ad60559bSWolfgang Pieb DWARFAddressRangesVector Res; 102*8036cf7fSDavid Blaikie uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize); 103ad60559bSWolfgang Pieb for (const RangeListEntry &RLE : Entries) { 104ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 105ad60559bSWolfgang Pieb break; 10659ac2064SDavid Blaikie if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { 107d34927e7SPavel Labath BaseAddr = LookupPooledAddress(RLE.Value0); 10859ac2064SDavid Blaikie if (!BaseAddr) 1096d85c583SGeorge Rimar BaseAddr = {RLE.Value0, -1ULL}; 11059ac2064SDavid Blaikie continue; 11159ac2064SDavid Blaikie } 112ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 113ad60559bSWolfgang Pieb BaseAddr = {RLE.Value0, RLE.SectionIndex}; 114ad60559bSWolfgang Pieb continue; 115ad60559bSWolfgang Pieb } 116ad60559bSWolfgang Pieb 117ad60559bSWolfgang Pieb DWARFAddressRange E; 118ad60559bSWolfgang Pieb E.SectionIndex = RLE.SectionIndex; 119ad60559bSWolfgang Pieb if (BaseAddr && E.SectionIndex == -1ULL) 120ad60559bSWolfgang Pieb E.SectionIndex = BaseAddr->SectionIndex; 121ad60559bSWolfgang Pieb 122ad60559bSWolfgang Pieb switch (RLE.EntryKind) { 123ad60559bSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 124ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 125*8036cf7fSDavid Blaikie if (E.LowPC == Tombstone) 126*8036cf7fSDavid Blaikie continue; 127ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 128ad60559bSWolfgang Pieb if (BaseAddr) { 129*8036cf7fSDavid Blaikie if (BaseAddr->Address == Tombstone) 130*8036cf7fSDavid Blaikie continue; 131ad60559bSWolfgang Pieb E.LowPC += BaseAddr->Address; 132ad60559bSWolfgang Pieb E.HighPC += BaseAddr->Address; 133ad60559bSWolfgang Pieb } 134ad60559bSWolfgang Pieb break; 135ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_end: 136ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 137ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 138ad60559bSWolfgang Pieb break; 139ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_length: 140ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 141ad60559bSWolfgang Pieb E.HighPC = E.LowPC + RLE.Value1; 142ad60559bSWolfgang Pieb break; 14359ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 144d34927e7SPavel Labath auto Start = LookupPooledAddress(RLE.Value0); 14559ac2064SDavid Blaikie if (!Start) 1466d85c583SGeorge Rimar Start = {0, -1ULL}; 14759ac2064SDavid Blaikie E.SectionIndex = Start->SectionIndex; 14859ac2064SDavid Blaikie E.LowPC = Start->Address; 14959ac2064SDavid Blaikie E.HighPC = E.LowPC + RLE.Value1; 15059ac2064SDavid Blaikie break; 15159ac2064SDavid Blaikie } 152ad60559bSWolfgang Pieb default: 153ad60559bSWolfgang Pieb // Unsupported encodings should have been reported during extraction, 154ad60559bSWolfgang Pieb // so we should not run into any here. 155ad60559bSWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 156ad60559bSWolfgang Pieb } 157*8036cf7fSDavid Blaikie if (E.LowPC == Tombstone) 158*8036cf7fSDavid Blaikie continue; 159ad60559bSWolfgang Pieb Res.push_back(E); 160ad60559bSWolfgang Pieb } 161ad60559bSWolfgang Pieb return Res; 162ad60559bSWolfgang Pieb } 163ad60559bSWolfgang Pieb 16459ac2064SDavid Blaikie void RangeListEntry::dump( 165f39a9bbeSWolfgang Pieb raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, 166f39a9bbeSWolfgang Pieb uint64_t &CurrentBase, DIDumpOptions DumpOpts, 16777fc1f60SAlexey Lapshin llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> 16859ac2064SDavid Blaikie LookupPooledAddress) const { 169439801baSWolfgang Pieb auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 170ab068eaaSWolfgang Pieb uint8_t AddrSize, DIDumpOptions DumpOpts) { 171ab068eaaSWolfgang Pieb if (DumpOpts.Verbose) { 172ab068eaaSWolfgang Pieb DumpOpts.DisplayRawContents = true; 173ab068eaaSWolfgang Pieb DWARFAddressRange(Entry.Value0, Entry.Value1) 174ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 175ab068eaaSWolfgang Pieb OS << " => "; 176ab068eaaSWolfgang Pieb } 177ab068eaaSWolfgang Pieb }; 178ab068eaaSWolfgang Pieb 179a0729d41SWolfgang Pieb if (DumpOpts.Verbose) { 180a0729d41SWolfgang Pieb // Print the section offset in verbose mode. 181f26a70a5SIgor Kudrin OS << format("0x%8.8" PRIx64 ":", Offset); 182439801baSWolfgang Pieb auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 183a0729d41SWolfgang Pieb // Unsupported encodings should have been reported during parsing. 184a0729d41SWolfgang Pieb assert(!EncodingString.empty() && "Unknown range entry encoding"); 185a0729d41SWolfgang Pieb OS << format(" [%s%*c", EncodingString.data(), 186a0729d41SWolfgang Pieb MaxEncodingStringLength - EncodingString.size() + 1, ']'); 187f39a9bbeSWolfgang Pieb if (EntryKind != dwarf::DW_RLE_end_of_list) 188a0729d41SWolfgang Pieb OS << ": "; 189a0729d41SWolfgang Pieb } 190a0729d41SWolfgang Pieb 191*8036cf7fSDavid Blaikie uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize); 192*8036cf7fSDavid Blaikie 193439801baSWolfgang Pieb switch (EntryKind) { 194a0729d41SWolfgang Pieb case dwarf::DW_RLE_end_of_list: 195e74e0f11SAlexander Kornienko OS << (DumpOpts.Verbose ? "" : "<End of list>"); 196a0729d41SWolfgang Pieb break; 19759ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 19859ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 19959ac2064SDavid Blaikie CurrentBase = SA->Address; 20059ac2064SDavid Blaikie else 20159ac2064SDavid Blaikie CurrentBase = Value0; 20259ac2064SDavid Blaikie if (!DumpOpts.Verbose) 20359ac2064SDavid Blaikie return; 20459ac2064SDavid Blaikie OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 20559ac2064SDavid Blaikie break; 20659ac2064SDavid Blaikie } 207ab068eaaSWolfgang Pieb case dwarf::DW_RLE_base_address: 208e74e0f11SAlexander Kornienko // In non-verbose mode we do not print anything for this entry. 209439801baSWolfgang Pieb CurrentBase = Value0; 210ab068eaaSWolfgang Pieb if (!DumpOpts.Verbose) 211ab068eaaSWolfgang Pieb return; 212439801baSWolfgang Pieb OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); 213ab068eaaSWolfgang Pieb break; 214a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_length: 215439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 216439801baSWolfgang Pieb DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 217a0729d41SWolfgang Pieb break; 218ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 219439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 220*8036cf7fSDavid Blaikie if (CurrentBase != Tombstone) 221439801baSWolfgang Pieb DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 222ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 223*8036cf7fSDavid Blaikie else 224*8036cf7fSDavid Blaikie OS << "dead code"; 225ab068eaaSWolfgang Pieb break; 226a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_end: 227439801baSWolfgang Pieb DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 228a0729d41SWolfgang Pieb break; 22959ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 23059ac2064SDavid Blaikie PrintRawEntry(OS, *this, AddrSize, DumpOpts); 23159ac2064SDavid Blaikie uint64_t Start = 0; 23259ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 23359ac2064SDavid Blaikie Start = SA->Address; 23459ac2064SDavid Blaikie DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); 23559ac2064SDavid Blaikie break; 23640483e18SFangrui Song } 237a0729d41SWolfgang Pieb default: 238a0729d41SWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 239a0729d41SWolfgang Pieb } 240a0729d41SWolfgang Pieb OS << "\n"; 241a0729d41SWolfgang Pieb } 242