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" 11*ea83e0b1SDavid Blaikie #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 12ad60559bSWolfgang Pieb #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 13cba595daSVictor Leschuk #include "llvm/Support/Errc.h" 14c2dfd502SJames Henderson #include "llvm/Support/Error.h" 15c2dfd502SJames Henderson #include "llvm/Support/Format.h" 16c2dfd502SJames Henderson #include "llvm/Support/raw_ostream.h" 17c2dfd502SJames Henderson 18c2dfd502SJames Henderson using namespace llvm; 19c2dfd502SJames Henderson 20ad68a8b9SDavid Blaikie Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) { 213fb9e3f3SWolfgang Pieb Offset = *OffsetPtr; 22ad60559bSWolfgang Pieb SectionIndex = -1ULL; 233fb9e3f3SWolfgang Pieb // The caller should guarantee that we have at least 1 byte available, so 243fb9e3f3SWolfgang Pieb // we just assert instead of revalidate. 25ad68a8b9SDavid Blaikie assert(*OffsetPtr < Data.size() && 263fb9e3f3SWolfgang Pieb "not enough space to extract a rangelist encoding"); 27f39a9bbeSWolfgang Pieb uint8_t Encoding = Data.getU8(OffsetPtr); 283fb9e3f3SWolfgang Pieb 29ad68a8b9SDavid Blaikie DataExtractor::Cursor C(*OffsetPtr); 30c2dfd502SJames Henderson switch (Encoding) { 31c2dfd502SJames Henderson case dwarf::DW_RLE_end_of_list: 323fb9e3f3SWolfgang Pieb Value0 = Value1 = 0; 33c2dfd502SJames Henderson break; 34c2dfd502SJames Henderson // TODO: Support other encodings. 3559ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 36ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 3759ac2064SDavid Blaikie break; 3859ac2064SDavid Blaikie } 39c2dfd502SJames Henderson case dwarf::DW_RLE_startx_endx: 40ad68a8b9SDavid Blaikie consumeError(C.takeError()); 41ad68a8b9SDavid Blaikie return createStringError( 42ad68a8b9SDavid Blaikie errc::not_supported, 43cba595daSVictor Leschuk "unsupported rnglists encoding DW_RLE_startx_endx at " 44f26a70a5SIgor Kudrin "offset 0x%" PRIx64, 45ad68a8b9SDavid Blaikie Offset); 4659ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 47ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 48ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 4959ac2064SDavid Blaikie break; 5059ac2064SDavid Blaikie } 51ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: { 52ad68a8b9SDavid Blaikie Value0 = Data.getULEB128(C); 53ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 54ab068eaaSWolfgang Pieb break; 55ab068eaaSWolfgang Pieb } 56f39a9bbeSWolfgang Pieb case dwarf::DW_RLE_base_address: { 57ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 58ab068eaaSWolfgang Pieb break; 59f39a9bbeSWolfgang Pieb } 60f39a9bbeSWolfgang Pieb case dwarf::DW_RLE_start_end: { 61ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 62ad68a8b9SDavid Blaikie Value1 = Data.getRelocatedAddress(C); 63c2dfd502SJames Henderson break; 64f39a9bbeSWolfgang Pieb } 65c2dfd502SJames Henderson case dwarf::DW_RLE_start_length: { 66ad68a8b9SDavid Blaikie Value0 = Data.getRelocatedAddress(C, &SectionIndex); 67ad68a8b9SDavid Blaikie Value1 = Data.getULEB128(C); 68c2dfd502SJames Henderson break; 69c2dfd502SJames Henderson } 70c2dfd502SJames Henderson default: 71ad68a8b9SDavid Blaikie consumeError(C.takeError()); 72cba595daSVictor Leschuk return createStringError(errc::not_supported, 73cba595daSVictor Leschuk "unknown rnglists encoding 0x%" PRIx32 74f26a70a5SIgor Kudrin " at offset 0x%" PRIx64, 75ad68a8b9SDavid Blaikie uint32_t(Encoding), Offset); 76c2dfd502SJames Henderson } 773fb9e3f3SWolfgang Pieb 78ad68a8b9SDavid Blaikie if (!C) { 79ad68a8b9SDavid Blaikie consumeError(C.takeError()); 80ad68a8b9SDavid Blaikie return createStringError( 81ad68a8b9SDavid Blaikie errc::invalid_argument, 82ad68a8b9SDavid Blaikie "read past end of table when reading %s encoding at offset 0x%" PRIx64, 83ad68a8b9SDavid Blaikie dwarf::RLEString(Encoding).data(), Offset); 84ad68a8b9SDavid Blaikie } 85ad68a8b9SDavid Blaikie 86ad68a8b9SDavid Blaikie *OffsetPtr = C.tell(); 873fb9e3f3SWolfgang Pieb EntryKind = Encoding; 883fb9e3f3SWolfgang Pieb return Error::success(); 89c2dfd502SJames Henderson } 90c2dfd502SJames Henderson 9177fc1f60SAlexey Lapshin DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( 9277fc1f60SAlexey Lapshin llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const { 938036cf7fSDavid Blaikie return getAbsoluteRanges( 948036cf7fSDavid Blaikie BaseAddr, U.getAddressByteSize(), 958036cf7fSDavid Blaikie [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); }); 96d34927e7SPavel Labath } 97d34927e7SPavel Labath 98d34927e7SPavel Labath DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( 998036cf7fSDavid Blaikie Optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize, 100d34927e7SPavel Labath function_ref<Optional<object::SectionedAddress>(uint32_t)> 101d34927e7SPavel Labath LookupPooledAddress) const { 102ad60559bSWolfgang Pieb DWARFAddressRangesVector Res; 1038036cf7fSDavid Blaikie uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize); 104ad60559bSWolfgang Pieb for (const RangeListEntry &RLE : Entries) { 105ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) 106ad60559bSWolfgang Pieb break; 10759ac2064SDavid Blaikie if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { 108d34927e7SPavel Labath BaseAddr = LookupPooledAddress(RLE.Value0); 10959ac2064SDavid Blaikie if (!BaseAddr) 1106d85c583SGeorge Rimar BaseAddr = {RLE.Value0, -1ULL}; 11159ac2064SDavid Blaikie continue; 11259ac2064SDavid Blaikie } 113ad60559bSWolfgang Pieb if (RLE.EntryKind == dwarf::DW_RLE_base_address) { 114ad60559bSWolfgang Pieb BaseAddr = {RLE.Value0, RLE.SectionIndex}; 115ad60559bSWolfgang Pieb continue; 116ad60559bSWolfgang Pieb } 117ad60559bSWolfgang Pieb 118ad60559bSWolfgang Pieb DWARFAddressRange E; 119ad60559bSWolfgang Pieb E.SectionIndex = RLE.SectionIndex; 120ad60559bSWolfgang Pieb if (BaseAddr && E.SectionIndex == -1ULL) 121ad60559bSWolfgang Pieb E.SectionIndex = BaseAddr->SectionIndex; 122ad60559bSWolfgang Pieb 123ad60559bSWolfgang Pieb switch (RLE.EntryKind) { 124ad60559bSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 125ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 1268036cf7fSDavid Blaikie if (E.LowPC == Tombstone) 1278036cf7fSDavid Blaikie continue; 128ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 129ad60559bSWolfgang Pieb if (BaseAddr) { 1308036cf7fSDavid Blaikie if (BaseAddr->Address == Tombstone) 1318036cf7fSDavid Blaikie continue; 132ad60559bSWolfgang Pieb E.LowPC += BaseAddr->Address; 133ad60559bSWolfgang Pieb E.HighPC += BaseAddr->Address; 134ad60559bSWolfgang Pieb } 135ad60559bSWolfgang Pieb break; 136ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_end: 137ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 138ad60559bSWolfgang Pieb E.HighPC = RLE.Value1; 139ad60559bSWolfgang Pieb break; 140ad60559bSWolfgang Pieb case dwarf::DW_RLE_start_length: 141ad60559bSWolfgang Pieb E.LowPC = RLE.Value0; 142ad60559bSWolfgang Pieb E.HighPC = E.LowPC + RLE.Value1; 143ad60559bSWolfgang Pieb break; 14459ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 145d34927e7SPavel Labath auto Start = LookupPooledAddress(RLE.Value0); 14659ac2064SDavid Blaikie if (!Start) 1476d85c583SGeorge Rimar Start = {0, -1ULL}; 14859ac2064SDavid Blaikie E.SectionIndex = Start->SectionIndex; 14959ac2064SDavid Blaikie E.LowPC = Start->Address; 15059ac2064SDavid Blaikie E.HighPC = E.LowPC + RLE.Value1; 15159ac2064SDavid Blaikie break; 15259ac2064SDavid Blaikie } 153ad60559bSWolfgang Pieb default: 154ad60559bSWolfgang Pieb // Unsupported encodings should have been reported during extraction, 155ad60559bSWolfgang Pieb // so we should not run into any here. 156ad60559bSWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 157ad60559bSWolfgang Pieb } 1588036cf7fSDavid Blaikie if (E.LowPC == Tombstone) 1598036cf7fSDavid Blaikie continue; 160ad60559bSWolfgang Pieb Res.push_back(E); 161ad60559bSWolfgang Pieb } 162ad60559bSWolfgang Pieb return Res; 163ad60559bSWolfgang Pieb } 164ad60559bSWolfgang Pieb 16559ac2064SDavid Blaikie void RangeListEntry::dump( 166f39a9bbeSWolfgang Pieb raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, 167f39a9bbeSWolfgang Pieb uint64_t &CurrentBase, DIDumpOptions DumpOpts, 16877fc1f60SAlexey Lapshin llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> 16959ac2064SDavid Blaikie LookupPooledAddress) const { 170439801baSWolfgang Pieb auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, 171ab068eaaSWolfgang Pieb uint8_t AddrSize, DIDumpOptions DumpOpts) { 172ab068eaaSWolfgang Pieb if (DumpOpts.Verbose) { 173ab068eaaSWolfgang Pieb DumpOpts.DisplayRawContents = true; 174ab068eaaSWolfgang Pieb DWARFAddressRange(Entry.Value0, Entry.Value1) 175ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 176ab068eaaSWolfgang Pieb OS << " => "; 177ab068eaaSWolfgang Pieb } 178ab068eaaSWolfgang Pieb }; 179ab068eaaSWolfgang Pieb 180a0729d41SWolfgang Pieb if (DumpOpts.Verbose) { 181a0729d41SWolfgang Pieb // Print the section offset in verbose mode. 182f26a70a5SIgor Kudrin OS << format("0x%8.8" PRIx64 ":", Offset); 183439801baSWolfgang Pieb auto EncodingString = dwarf::RangeListEncodingString(EntryKind); 184a0729d41SWolfgang Pieb // Unsupported encodings should have been reported during parsing. 185a0729d41SWolfgang Pieb assert(!EncodingString.empty() && "Unknown range entry encoding"); 186a0729d41SWolfgang Pieb OS << format(" [%s%*c", EncodingString.data(), 187a0729d41SWolfgang Pieb MaxEncodingStringLength - EncodingString.size() + 1, ']'); 188f39a9bbeSWolfgang Pieb if (EntryKind != dwarf::DW_RLE_end_of_list) 189a0729d41SWolfgang Pieb OS << ": "; 190a0729d41SWolfgang Pieb } 191a0729d41SWolfgang Pieb 1928036cf7fSDavid Blaikie uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize); 1938036cf7fSDavid Blaikie 194439801baSWolfgang Pieb switch (EntryKind) { 195a0729d41SWolfgang Pieb case dwarf::DW_RLE_end_of_list: 196e74e0f11SAlexander Kornienko OS << (DumpOpts.Verbose ? "" : "<End of list>"); 197a0729d41SWolfgang Pieb break; 19859ac2064SDavid Blaikie case dwarf::DW_RLE_base_addressx: { 19959ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 20059ac2064SDavid Blaikie CurrentBase = SA->Address; 20159ac2064SDavid Blaikie else 20259ac2064SDavid Blaikie CurrentBase = Value0; 20359ac2064SDavid Blaikie if (!DumpOpts.Verbose) 20459ac2064SDavid Blaikie return; 205*ea83e0b1SDavid Blaikie DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0); 20659ac2064SDavid Blaikie break; 20759ac2064SDavid Blaikie } 208ab068eaaSWolfgang Pieb case dwarf::DW_RLE_base_address: 209e74e0f11SAlexander Kornienko // In non-verbose mode we do not print anything for this entry. 210439801baSWolfgang Pieb CurrentBase = Value0; 211ab068eaaSWolfgang Pieb if (!DumpOpts.Verbose) 212ab068eaaSWolfgang Pieb return; 213*ea83e0b1SDavid Blaikie DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0); 214ab068eaaSWolfgang Pieb break; 215a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_length: 216439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 217439801baSWolfgang Pieb DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts); 218a0729d41SWolfgang Pieb break; 219ab068eaaSWolfgang Pieb case dwarf::DW_RLE_offset_pair: 220439801baSWolfgang Pieb PrintRawEntry(OS, *this, AddrSize, DumpOpts); 2218036cf7fSDavid Blaikie if (CurrentBase != Tombstone) 222439801baSWolfgang Pieb DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) 223ab068eaaSWolfgang Pieb .dump(OS, AddrSize, DumpOpts); 2248036cf7fSDavid Blaikie else 2258036cf7fSDavid Blaikie OS << "dead code"; 226ab068eaaSWolfgang Pieb break; 227a0729d41SWolfgang Pieb case dwarf::DW_RLE_start_end: 228439801baSWolfgang Pieb DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); 229a0729d41SWolfgang Pieb break; 23059ac2064SDavid Blaikie case dwarf::DW_RLE_startx_length: { 23159ac2064SDavid Blaikie PrintRawEntry(OS, *this, AddrSize, DumpOpts); 23259ac2064SDavid Blaikie uint64_t Start = 0; 23359ac2064SDavid Blaikie if (auto SA = LookupPooledAddress(Value0)) 23459ac2064SDavid Blaikie Start = SA->Address; 23559ac2064SDavid Blaikie DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); 23659ac2064SDavid Blaikie break; 23740483e18SFangrui Song } 238a0729d41SWolfgang Pieb default: 239a0729d41SWolfgang Pieb llvm_unreachable("Unsupported range list encoding"); 240a0729d41SWolfgang Pieb } 241a0729d41SWolfgang Pieb OS << "\n"; 242a0729d41SWolfgang Pieb } 243