brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.2 KiB · 5bd2427 Raw
414 lines · cpp
1//===- DWARFDebugLoc.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/DWARFDebugLoc.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/DebugInfo/DIContext.h"13#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"14#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"15#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"16#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"17#include "llvm/DebugInfo/DWARF/DWARFUnit.h"18#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"19#include "llvm/Support/Format.h"20#include "llvm/Support/raw_ostream.h"21#include <algorithm>22#include <cinttypes>23#include <cstdint>24 25using namespace llvm;26using object::SectionedAddress;27 28namespace llvm {29class DWARFObject;30}31 32namespace {33class DWARFLocationInterpreter {34  std::optional<object::SectionedAddress> Base;35  std::function<std::optional<object::SectionedAddress>(uint32_t)> LookupAddr;36 37public:38  DWARFLocationInterpreter(39      std::optional<object::SectionedAddress> Base,40      std::function<std::optional<object::SectionedAddress>(uint32_t)>41          LookupAddr)42      : Base(Base), LookupAddr(std::move(LookupAddr)) {}43 44  Expected<std::optional<DWARFLocationExpression>>45  Interpret(const DWARFLocationEntry &E);46};47} // namespace48 49static Error createResolverError(uint32_t Index, unsigned Kind) {50  return make_error<ResolverError>(Index, (dwarf::LoclistEntries)Kind);51}52 53Expected<std::optional<DWARFLocationExpression>>54DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) {55  switch (E.Kind) {56  case dwarf::DW_LLE_end_of_list:57    return std::nullopt;58  case dwarf::DW_LLE_base_addressx: {59    Base = LookupAddr(E.Value0);60    if (!Base)61      return createResolverError(E.Value0, E.Kind);62    return std::nullopt;63  }64  case dwarf::DW_LLE_startx_endx: {65    std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0);66    if (!LowPC)67      return createResolverError(E.Value0, E.Kind);68    std::optional<SectionedAddress> HighPC = LookupAddr(E.Value1);69    if (!HighPC)70      return createResolverError(E.Value1, E.Kind);71    return DWARFLocationExpression{72        DWARFAddressRange{LowPC->Address, HighPC->Address, LowPC->SectionIndex},73        E.Loc};74  }75  case dwarf::DW_LLE_startx_length: {76    std::optional<SectionedAddress> LowPC = LookupAddr(E.Value0);77    if (!LowPC)78      return createResolverError(E.Value0, E.Kind);79    return DWARFLocationExpression{DWARFAddressRange{LowPC->Address,80                                                     LowPC->Address + E.Value1,81                                                     LowPC->SectionIndex},82                                   E.Loc};83  }84  case dwarf::DW_LLE_offset_pair: {85    if (!Base) {86      return createStringError(inconvertibleErrorCode(),87                               "Unable to resolve location list offset pair: "88                               "Base address not defined");89    }90    DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1,91                            Base->SectionIndex};92    if (Range.SectionIndex == SectionedAddress::UndefSection)93      Range.SectionIndex = E.SectionIndex;94    return DWARFLocationExpression{Range, E.Loc};95  }96  case dwarf::DW_LLE_default_location:97    return DWARFLocationExpression{std::nullopt, E.Loc};98  case dwarf::DW_LLE_base_address:99    Base = SectionedAddress{E.Value0, E.SectionIndex};100    return std::nullopt;101  case dwarf::DW_LLE_start_end:102    return DWARFLocationExpression{103        DWARFAddressRange{E.Value0, E.Value1, E.SectionIndex}, E.Loc};104  case dwarf::DW_LLE_start_length:105    return DWARFLocationExpression{106        DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex},107        E.Loc};108  default:109    llvm_unreachable("unreachable locations list kind");110  }111}112 113static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts,114                           ArrayRef<uint8_t> Data, bool IsLittleEndian,115                           unsigned AddressSize, DWARFUnit *U) {116  DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize);117  std::optional<dwarf::DwarfFormat> Format;118  if (U)119    Format = U->getFormat();120  DWARFExpression E(Extractor, AddressSize, Format);121  printDwarfExpression(&E, OS, DumpOpts, U);122}123 124bool DWARFLocationTable::dumpLocationList(125    uint64_t *Offset, raw_ostream &OS, std::optional<SectionedAddress> BaseAddr,126    const DWARFObject &Obj, DWARFUnit *U, DIDumpOptions DumpOpts,127    unsigned Indent) const {128  DWARFLocationInterpreter Interp(129      BaseAddr, [U](uint32_t Index) -> std::optional<SectionedAddress> {130        if (U)131          return U->getAddrOffsetSectionItem(Index);132        return std::nullopt;133      });134  OS << format("0x%8.8" PRIx64 ": ", *Offset);135  Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) {136    Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);137    if (!Loc || DumpOpts.DisplayRawContents)138      dumpRawEntry(E, OS, Indent, DumpOpts, Obj);139    if (Loc && *Loc) {140      OS << "\n";141      OS.indent(Indent);142      if (DumpOpts.DisplayRawContents)143        OS << "          => ";144 145      DIDumpOptions RangeDumpOpts(DumpOpts);146      RangeDumpOpts.DisplayRawContents = false;147      if (Loc.get()->Range)148        Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj);149      else150        OS << "<default>";151    }152    if (!Loc)153      consumeError(Loc.takeError());154 155    if (E.Kind != dwarf::DW_LLE_base_address &&156        E.Kind != dwarf::DW_LLE_base_addressx &&157        E.Kind != dwarf::DW_LLE_end_of_list) {158      OS << ": ";159      dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(),160                     Data.getAddressSize(), U);161    }162    return true;163  });164  if (E) {165    DumpOpts.RecoverableErrorHandler(std::move(E));166    return false;167  }168  return true;169}170 171Error DWARFLocationTable::visitAbsoluteLocationList(172    uint64_t Offset, std::optional<SectionedAddress> BaseAddr,173    std::function<std::optional<SectionedAddress>(uint32_t)> LookupAddr,174    function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const {175  DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr));176  return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) {177    Expected<std::optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);178    if (!Loc)179      return Callback(Loc.takeError());180    if (*Loc)181      return Callback(**Loc);182    return true;183  });184}185 186void DWARFDebugLoc::dump(raw_ostream &OS, const DWARFObject &Obj,187                         DIDumpOptions DumpOpts,188                         std::optional<uint64_t> DumpOffset) const {189  auto BaseAddr = std::nullopt;190  unsigned Indent = 12;191  if (DumpOffset) {192    dumpLocationList(&*DumpOffset, OS, BaseAddr, Obj, nullptr, DumpOpts,193                     Indent);194  } else {195    uint64_t Offset = 0;196    StringRef Separator;197    bool CanContinue = true;198    while (CanContinue && Data.isValidOffset(Offset)) {199      OS << Separator;200      Separator = "\n";201 202      CanContinue = dumpLocationList(&Offset, OS, BaseAddr, Obj, nullptr,203                                     DumpOpts, Indent);204      OS << '\n';205    }206  }207}208 209Error DWARFDebugLoc::visitLocationList(210    uint64_t *Offset,211    function_ref<bool(const DWARFLocationEntry &)> Callback) const {212  DataExtractor::Cursor C(*Offset);213  while (true) {214    uint64_t SectionIndex;215    uint64_t Value0 = Data.getRelocatedAddress(C);216    uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex);217 218    DWARFLocationEntry E;219 220    // The end of any given location list is marked by an end of list entry,221    // which consists of a 0 for the beginning address offset and a 0 for the222    // ending address offset. A beginning offset of 0xff...f marks the base223    // address selection entry.224    if (Value0 == 0 && Value1 == 0) {225      E.Kind = dwarf::DW_LLE_end_of_list;226    } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) {227      E.Kind = dwarf::DW_LLE_base_address;228      E.Value0 = Value1;229      E.SectionIndex = SectionIndex;230    } else {231      E.Kind = dwarf::DW_LLE_offset_pair;232      E.Value0 = Value0;233      E.Value1 = Value1;234      E.SectionIndex = SectionIndex;235      unsigned Bytes = Data.getU16(C);236      // A single location description describing the location of the object...237      Data.getU8(C, E.Loc, Bytes);238    }239 240    if (!C)241      return C.takeError();242    if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list)243      break;244  }245  *Offset = C.tell();246  return Error::success();247}248 249void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry,250                                 raw_ostream &OS, unsigned Indent,251                                 DIDumpOptions DumpOpts,252                                 const DWARFObject &Obj) const {253  uint64_t Value0, Value1;254  switch (Entry.Kind) {255  case dwarf::DW_LLE_base_address:256    Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL;257    Value1 = Entry.Value0;258    break;259  case dwarf::DW_LLE_offset_pair:260    Value0 = Entry.Value0;261    Value1 = Entry.Value1;262    break;263  case dwarf::DW_LLE_end_of_list:264    return;265  default:266    llvm_unreachable("Not possible in DWARF4!");267  }268  OS << '\n';269  OS.indent(Indent);270  OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", "271     << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')';272  DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);273}274 275Error DWARFDebugLoclists::visitLocationList(276    uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const {277 278  DataExtractor::Cursor C(*Offset);279  bool Continue = true;280  while (Continue) {281    DWARFLocationEntry E;282    E.Kind = Data.getU8(C);283    switch (E.Kind) {284    case dwarf::DW_LLE_end_of_list:285      break;286    case dwarf::DW_LLE_base_addressx:287      E.Value0 = Data.getULEB128(C);288      break;289    case dwarf::DW_LLE_startx_endx:290      E.Value0 = Data.getULEB128(C);291      E.Value1 = Data.getULEB128(C);292      break;293    case dwarf::DW_LLE_startx_length:294      E.Value0 = Data.getULEB128(C);295      // Pre-DWARF 5 has different interpretation of the length field. We have296      // to support both pre- and standartized styles for the compatibility.297      if (Version < 5)298        E.Value1 = Data.getU32(C);299      else300        E.Value1 = Data.getULEB128(C);301      break;302    case dwarf::DW_LLE_offset_pair:303      E.Value0 = Data.getULEB128(C);304      E.Value1 = Data.getULEB128(C);305      E.SectionIndex = SectionedAddress::UndefSection;306      break;307    case dwarf::DW_LLE_default_location:308      break;309    case dwarf::DW_LLE_base_address:310      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);311      break;312    case dwarf::DW_LLE_start_end:313      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);314      E.Value1 = Data.getRelocatedAddress(C);315      break;316    case dwarf::DW_LLE_start_length:317      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);318      E.Value1 = Data.getULEB128(C);319      break;320    default:321      cantFail(C.takeError());322      return createStringError(errc::illegal_byte_sequence,323                               "LLE of kind %x not supported", (int)E.Kind);324    }325 326    if (E.Kind != dwarf::DW_LLE_base_address &&327        E.Kind != dwarf::DW_LLE_base_addressx &&328        E.Kind != dwarf::DW_LLE_end_of_list) {329      unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C);330      // A single location description describing the location of the object...331      Data.getU8(C, E.Loc, Bytes);332    }333 334    if (!C)335      return C.takeError();336    Continue = F(E) && E.Kind != dwarf::DW_LLE_end_of_list;337  }338  *Offset = C.tell();339  return Error::success();340}341 342void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry,343                                      raw_ostream &OS, unsigned Indent,344                                      DIDumpOptions DumpOpts,345                                      const DWARFObject &Obj) const {346  size_t MaxEncodingStringLength = 0;347#define HANDLE_DW_LLE(ID, NAME)                                                \348  MaxEncodingStringLength = std::max(MaxEncodingStringLength,                  \349                                     dwarf::LocListEncodingString(ID).size());350#include "llvm/BinaryFormat/Dwarf.def"351 352  OS << "\n";353  OS.indent(Indent);354  StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind);355  // Unsupported encodings should have been reported during parsing.356  assert(!EncodingString.empty() && "Unknown loclist entry encoding");357  OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data());358  unsigned FieldSize = 2 + 2 * Data.getAddressSize();359  switch (Entry.Kind) {360  case dwarf::DW_LLE_end_of_list:361  case dwarf::DW_LLE_default_location:362    break;363  case dwarf::DW_LLE_startx_endx:364  case dwarf::DW_LLE_startx_length:365  case dwarf::DW_LLE_offset_pair:366  case dwarf::DW_LLE_start_end:367  case dwarf::DW_LLE_start_length:368    OS << format_hex(Entry.Value0, FieldSize) << ", "369       << format_hex(Entry.Value1, FieldSize);370    break;371  case dwarf::DW_LLE_base_addressx:372  case dwarf::DW_LLE_base_address:373    OS << format_hex(Entry.Value0, FieldSize);374    break;375  }376  OS << ')';377  switch (Entry.Kind) {378  case dwarf::DW_LLE_base_address:379  case dwarf::DW_LLE_start_end:380  case dwarf::DW_LLE_start_length:381    DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);382    break;383  default:384    break;385  }386}387 388void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,389                                   raw_ostream &OS, const DWARFObject &Obj,390                                   DIDumpOptions DumpOpts) {391  if (!Data.isValidOffsetForDataOfSize(StartOffset, Size))  {392    OS << "Invalid dump range\n";393    return;394  }395  uint64_t Offset = StartOffset;396  StringRef Separator;397  bool CanContinue = true;398  while (CanContinue && Offset < StartOffset + Size) {399    OS << Separator;400    Separator = "\n";401 402    CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,403                                   nullptr, DumpOpts, /*Indent=*/12);404    OS << '\n';405  }406}407 408void llvm::ResolverError::log(raw_ostream &OS) const {409  OS << format("unable to resolve indirect address %u for: %s", Index,410               dwarf::LocListEncodingString(Kind).data());411}412 413char llvm::ResolverError::ID;414