brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.4 KiB · b428c2a Raw
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