264 lines · cpp
1//===- DWARFDebugRnglists.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"10#include "llvm/BinaryFormat/Dwarf.h"11#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"12#include "llvm/DebugInfo/DWARF/DWARFUnit.h"13#include "llvm/Support/Errc.h"14#include "llvm/Support/Error.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/raw_ostream.h"17 18using namespace llvm;19 20Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {21 Offset = *OffsetPtr;22 SectionIndex = -1ULL;23 // The caller should guarantee that we have at least 1 byte available, so24 // we just assert instead of revalidate.25 assert(*OffsetPtr < Data.size() &&26 "not enough space to extract a rangelist encoding");27 uint8_t Encoding = Data.getU8(OffsetPtr);28 29 DataExtractor::Cursor C(*OffsetPtr);30 switch (Encoding) {31 case dwarf::DW_RLE_end_of_list:32 Value0 = Value1 = 0;33 break;34 // TODO: Support other encodings.35 case dwarf::DW_RLE_base_addressx: {36 Value0 = Data.getULEB128(C);37 break;38 }39 case dwarf::DW_RLE_startx_endx:40 Value0 = Data.getULEB128(C);41 Value1 = Data.getULEB128(C);42 break;43 case dwarf::DW_RLE_startx_length: {44 Value0 = Data.getULEB128(C);45 Value1 = Data.getULEB128(C);46 break;47 }48 case dwarf::DW_RLE_offset_pair: {49 Value0 = Data.getULEB128(C);50 Value1 = Data.getULEB128(C);51 break;52 }53 case dwarf::DW_RLE_base_address: {54 Value0 = Data.getRelocatedAddress(C, &SectionIndex);55 break;56 }57 case dwarf::DW_RLE_start_end: {58 Value0 = Data.getRelocatedAddress(C, &SectionIndex);59 Value1 = Data.getRelocatedAddress(C);60 break;61 }62 case dwarf::DW_RLE_start_length: {63 Value0 = Data.getRelocatedAddress(C, &SectionIndex);64 Value1 = Data.getULEB128(C);65 break;66 }67 default:68 consumeError(C.takeError());69 return createStringError(errc::not_supported,70 "unknown rnglists encoding 0x%" PRIx3271 " at offset 0x%" PRIx64,72 uint32_t(Encoding), Offset);73 }74 75 if (!C) {76 consumeError(C.takeError());77 return createStringError(78 errc::invalid_argument,79 "read past end of table when reading %s encoding at offset 0x%" PRIx64,80 dwarf::RLEString(Encoding).data(), Offset);81 }82 83 *OffsetPtr = C.tell();84 EntryKind = Encoding;85 return Error::success();86}87 88DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(89 std::optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {90 return getAbsoluteRanges(91 BaseAddr, U.getAddressByteSize(),92 [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });93}94 95DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(96 std::optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,97 function_ref<std::optional<object::SectionedAddress>(uint32_t)>98 LookupPooledAddress) const {99 DWARFAddressRangesVector Res;100 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);101 for (const RangeListEntry &RLE : Entries) {102 if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)103 break;104 if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {105 BaseAddr = LookupPooledAddress(RLE.Value0);106 if (!BaseAddr)107 BaseAddr = {RLE.Value0, -1ULL};108 continue;109 }110 if (RLE.EntryKind == dwarf::DW_RLE_base_address) {111 BaseAddr = {RLE.Value0, RLE.SectionIndex};112 continue;113 }114 115 DWARFAddressRange E;116 E.SectionIndex = RLE.SectionIndex;117 if (BaseAddr && E.SectionIndex == -1ULL)118 E.SectionIndex = BaseAddr->SectionIndex;119 120 switch (RLE.EntryKind) {121 case dwarf::DW_RLE_offset_pair:122 E.LowPC = RLE.Value0;123 if (E.LowPC == Tombstone)124 continue;125 E.HighPC = RLE.Value1;126 if (BaseAddr) {127 if (BaseAddr->Address == Tombstone)128 continue;129 E.LowPC += BaseAddr->Address;130 E.HighPC += BaseAddr->Address;131 }132 break;133 case dwarf::DW_RLE_start_end:134 E.LowPC = RLE.Value0;135 E.HighPC = RLE.Value1;136 break;137 case dwarf::DW_RLE_start_length:138 E.LowPC = RLE.Value0;139 E.HighPC = E.LowPC + RLE.Value1;140 break;141 case dwarf::DW_RLE_startx_length: {142 auto Start = LookupPooledAddress(RLE.Value0);143 if (!Start)144 Start = {0, -1ULL};145 E.SectionIndex = Start->SectionIndex;146 E.LowPC = Start->Address;147 E.HighPC = E.LowPC + RLE.Value1;148 break;149 }150 case dwarf::DW_RLE_startx_endx: {151 auto Start = LookupPooledAddress(RLE.Value0);152 if (!Start)153 Start = {0, -1ULL};154 auto End = LookupPooledAddress(RLE.Value1);155 if (!End)156 End = {0, -1ULL};157 // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex158 E.SectionIndex = Start->SectionIndex;159 E.LowPC = Start->Address;160 E.HighPC = End->Address;161 break;162 }163 default:164 // Unsupported encodings should have been reported during extraction,165 // so we should not run into any here.166 llvm_unreachable("Unsupported range list encoding");167 }168 if (E.LowPC == Tombstone)169 continue;170 Res.push_back(E);171 }172 return Res;173}174 175void RangeListEntry::dump(176 raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,177 uint64_t &CurrentBase, DIDumpOptions DumpOpts,178 llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>179 LookupPooledAddress) const {180 auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,181 uint8_t AddrSize, DIDumpOptions DumpOpts) {182 if (DumpOpts.Verbose) {183 DumpOpts.DisplayRawContents = true;184 DWARFAddressRange(Entry.Value0, Entry.Value1)185 .dump(OS, AddrSize, DumpOpts);186 OS << " => ";187 }188 };189 190 if (DumpOpts.Verbose) {191 // Print the section offset in verbose mode.192 OS << format("0x%8.8" PRIx64 ":", Offset);193 auto EncodingString = dwarf::RangeListEncodingString(EntryKind);194 // Unsupported encodings should have been reported during parsing.195 assert(!EncodingString.empty() && "Unknown range entry encoding");196 OS << format(" [%s%*c", EncodingString.data(),197 MaxEncodingStringLength - EncodingString.size() + 1, ']');198 if (EntryKind != dwarf::DW_RLE_end_of_list)199 OS << ": ";200 }201 202 uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);203 204 switch (EntryKind) {205 case dwarf::DW_RLE_end_of_list:206 OS << (DumpOpts.Verbose ? "" : "<End of list>");207 break;208 case dwarf::DW_RLE_base_addressx: {209 if (auto SA = LookupPooledAddress(Value0))210 CurrentBase = SA->Address;211 else212 CurrentBase = Value0;213 if (!DumpOpts.Verbose)214 return;215 DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);216 break;217 }218 case dwarf::DW_RLE_base_address:219 // In non-verbose mode we do not print anything for this entry.220 CurrentBase = Value0;221 if (!DumpOpts.Verbose)222 return;223 DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);224 break;225 case dwarf::DW_RLE_start_length:226 PrintRawEntry(OS, *this, AddrSize, DumpOpts);227 DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);228 break;229 case dwarf::DW_RLE_offset_pair:230 PrintRawEntry(OS, *this, AddrSize, DumpOpts);231 if (CurrentBase != Tombstone)232 DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)233 .dump(OS, AddrSize, DumpOpts);234 else235 OS << "dead code";236 break;237 case dwarf::DW_RLE_start_end:238 DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);239 break;240 case dwarf::DW_RLE_startx_length: {241 PrintRawEntry(OS, *this, AddrSize, DumpOpts);242 uint64_t Start = 0;243 if (auto SA = LookupPooledAddress(Value0))244 Start = SA->Address;245 DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);246 break;247 }248 case dwarf::DW_RLE_startx_endx: {249 PrintRawEntry(OS, *this, AddrSize, DumpOpts);250 uint64_t Start = 0;251 if (auto SA = LookupPooledAddress(Value0))252 Start = SA->Address;253 uint64_t End = 0;254 if (auto SA = LookupPooledAddress(Value1))255 End = SA->Address;256 DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);257 break;258 }259 default:260 llvm_unreachable("Unsupported range list encoding");261 }262 OS << "\n";263}264