brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.5 KiB · 3ba5061 Raw
1063 lines · cpp
1//===-- LVDWARFReader.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// This implements the LVDWARFReader class.10// It supports ELF, Mach-O and Wasm binary formats.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h"15#include "llvm/DebugInfo/DIContext.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"17#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"18#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"19#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"20#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"21#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"22#include "llvm/DebugInfo/LogicalView/Core/LVType.h"23#include "llvm/Object/MachO.h"24#include "llvm/Support/FormatVariadic.h"25 26using namespace llvm;27using namespace llvm::object;28using namespace llvm::logicalview;29 30#define DEBUG_TYPE "DWARFReader"31 32void LVDWARFReader::processOneAttribute(const DWARFDie &Die,33                                        LVOffset *OffsetPtr,34                                        const AttributeSpec &AttrSpec) {35  uint64_t OffsetOnEntry = *OffsetPtr;36  DWARFUnit *U = Die.getDwarfUnit();37  const DWARFFormValue &FormValue =38      DWARFFormValue::createFromUnit(AttrSpec.Form, U, OffsetPtr);39 40  // We are processing .debug_info section, implicit_const attribute41  // values are not really stored here, but in .debug_abbrev section.42  auto GetAsUnsignedConstant = [&]() -> int64_t {43    if (AttrSpec.isImplicitConst())44      return AttrSpec.getImplicitConstValue();45    if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())46      return *Val;47    return 0;48  };49 50  auto GetFlag = [](const DWARFFormValue &FormValue) -> bool {51    return FormValue.isFormClass(DWARFFormValue::FC_Flag);52  };53 54  auto GetBoundValue = [&AttrSpec](const DWARFFormValue &FormValue) -> int64_t {55    switch (FormValue.getForm()) {56    case dwarf::DW_FORM_ref_addr:57    case dwarf::DW_FORM_ref1:58    case dwarf::DW_FORM_ref2:59    case dwarf::DW_FORM_ref4:60    case dwarf::DW_FORM_ref8:61    case dwarf::DW_FORM_ref_udata:62    case dwarf::DW_FORM_ref_sig8:63      return *FormValue.getAsReferenceUVal();64    case dwarf::DW_FORM_data1:65    case dwarf::DW_FORM_flag:66    case dwarf::DW_FORM_data2:67    case dwarf::DW_FORM_data4:68    case dwarf::DW_FORM_data8:69    case dwarf::DW_FORM_udata:70    case dwarf::DW_FORM_ref_sup4:71    case dwarf::DW_FORM_ref_sup8:72      return *FormValue.getAsUnsignedConstant();73    case dwarf::DW_FORM_sdata:74      return *FormValue.getAsSignedConstant();75    case dwarf::DW_FORM_implicit_const:76      return AttrSpec.getImplicitConstValue();77    default:78      return 0;79    }80  };81 82  LLVM_DEBUG({83    dbgs() << "     " << hexValue(OffsetOnEntry)84           << formatv(" {0}", AttrSpec.Attr) << "\n";85  });86 87  switch (AttrSpec.Attr) {88  case dwarf::DW_AT_accessibility:89    CurrentElement->setAccessibilityCode(GetAsUnsignedConstant());90    break;91  case dwarf::DW_AT_artificial:92    CurrentElement->setIsArtificial();93    break;94  case dwarf::DW_AT_bit_size:95    CurrentElement->setBitSize(GetAsUnsignedConstant());96    break;97  case dwarf::DW_AT_byte_size:98    CurrentElement->setBitSize(GetAsUnsignedConstant() * DWARF_CHAR_BIT);99    break;100  case dwarf::DW_AT_call_file:101    CurrentElement->setCallFilenameIndex(IncrementFileIndex102                                             ? GetAsUnsignedConstant() + 1103                                             : GetAsUnsignedConstant());104    break;105  case dwarf::DW_AT_call_line:106    CurrentElement->setCallLineNumber(GetAsUnsignedConstant());107    break;108  case dwarf::DW_AT_comp_dir:109    CompileUnit->setCompilationDirectory(dwarf::toStringRef(FormValue));110    break;111  case dwarf::DW_AT_const_value:112    if (FormValue.isFormClass(DWARFFormValue::FC_Block)) {113      ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();114      // Store the expression as a hexadecimal string.115      CurrentElement->setValue(116          llvm::toHex(llvm::toStringRef(Expr), /*LowerCase=*/true));117    } else if (FormValue.isFormClass(DWARFFormValue::FC_Constant)) {118      // In the case of negative values, generate the string representation119      // for a positive value prefixed with the negative sign.120      if (FormValue.getForm() == dwarf::DW_FORM_sdata) {121        std::stringstream Stream;122        int64_t Value = *FormValue.getAsSignedConstant();123        if (Value < 0) {124          Stream << "-";125          Value = std::abs(Value);126        }127        Stream << hexString(Value, 2);128        CurrentElement->setValue(Stream.str());129      } else130        CurrentElement->setValue(hexString(GetAsUnsignedConstant(), 2));131    } else132      CurrentElement->setValue(dwarf::toStringRef(FormValue));133    break;134  case dwarf::DW_AT_count:135    CurrentElement->setCount(GetAsUnsignedConstant());136    break;137  case dwarf::DW_AT_decl_line:138    CurrentElement->setLineNumber(GetAsUnsignedConstant());139    break;140  case dwarf::DW_AT_decl_file:141    CurrentElement->setFilenameIndex(IncrementFileIndex142                                         ? GetAsUnsignedConstant() + 1143                                         : GetAsUnsignedConstant());144    break;145  case dwarf::DW_AT_enum_class:146    if (GetFlag(FormValue))147      CurrentElement->setIsEnumClass();148    break;149  case dwarf::DW_AT_external:150    if (GetFlag(FormValue))151      CurrentElement->setIsExternal();152    break;153  case dwarf::DW_AT_GNU_discriminator:154    CurrentElement->setDiscriminator(GetAsUnsignedConstant());155    break;156  case dwarf::DW_AT_inline:157    CurrentElement->setInlineCode(GetAsUnsignedConstant());158    break;159  case dwarf::DW_AT_lower_bound:160    CurrentElement->setLowerBound(GetBoundValue(FormValue));161    break;162  case dwarf::DW_AT_name:163    CurrentElement->setName(dwarf::toStringRef(FormValue));164    break;165  case dwarf::DW_AT_GNU_template_name:166    CurrentElement->setValue(dwarf::toStringRef(FormValue));167    break;168  case dwarf::DW_AT_linkage_name:169  case dwarf::DW_AT_MIPS_linkage_name:170    CurrentElement->setLinkageName(dwarf::toStringRef(FormValue));171    break;172  case dwarf::DW_AT_producer:173    if (options().getAttributeProducer())174      CurrentElement->setProducer(dwarf::toStringRef(FormValue));175    break;176  case dwarf::DW_AT_language:177    if (options().getAttributeLanguage())178      CurrentElement->setSourceLanguage(LVSourceLanguage{179          static_cast<llvm::dwarf::SourceLanguage>(GetAsUnsignedConstant())});180    break;181  case dwarf::DW_AT_upper_bound:182    CurrentElement->setUpperBound(GetBoundValue(FormValue));183    break;184  case dwarf::DW_AT_virtuality:185    CurrentElement->setVirtualityCode(GetAsUnsignedConstant());186    break;187 188  case dwarf::DW_AT_abstract_origin:189  case dwarf::DW_AT_call_origin:190  case dwarf::DW_AT_extension:191  case dwarf::DW_AT_import:192  case dwarf::DW_AT_specification:193  case dwarf::DW_AT_type:194    updateReference(AttrSpec.Attr, FormValue);195    break;196 197  case dwarf::DW_AT_low_pc:198    if (options().getGeneralCollectRanges()) {199      FoundLowPC = true;200      // For toolchains that support the removal of unused code, the linker201      // marks functions that have been removed, by setting the value for the202      // low_pc to the max address.203      if (std::optional<uint64_t> Value = FormValue.getAsAddress()) {204        CurrentLowPC = *Value;205      } else {206        uint64_t UValue = FormValue.getRawUValue();207        if (U->getAddrOffsetSectionItem(UValue)) {208          CurrentLowPC = *FormValue.getAsAddress();209        } else {210          FoundLowPC = false;211          // We are dealing with an index into the .debug_addr section.212          LLVM_DEBUG({213            dbgs() << format("indexed (%8.8x) address = ", (uint32_t)UValue);214          });215        }216      }217      if (FoundLowPC) {218        if (CurrentLowPC == getTombstoneAddress())219          CurrentElement->setIsDiscarded();220        else221          // Consider the case of WebAssembly.222          CurrentLowPC += WasmCodeSectionOffset;223        if (CurrentElement->isCompileUnit())224          setCUBaseAddress(CurrentLowPC);225      }226    }227    break;228 229  case dwarf::DW_AT_high_pc:230    if (options().getGeneralCollectRanges()) {231      FoundHighPC = true;232      if (std::optional<uint64_t> Address = FormValue.getAsAddress())233        // High PC is an address.234        CurrentHighPC = *Address;235      if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant())236        // High PC is an offset from LowPC.237        // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as238        // the CurrentLowPC has already that offset added. Basically, use the239        // original DW_AT_loc_pc value.240        CurrentHighPC =241            (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) +242            *Offset;243      // Store the real upper limit for the address range.244      if (UpdateHighAddress && CurrentHighPC > 0)245        --CurrentHighPC;246      // Consider the case of WebAssembly.247      CurrentHighPC += WasmCodeSectionOffset;248      if (CurrentElement->isCompileUnit())249        setCUHighAddress(CurrentHighPC);250    }251    break;252 253  case dwarf::DW_AT_ranges:254    if (RangesDataAvailable && options().getGeneralCollectRanges()) {255      auto GetRanges = [](const DWARFFormValue &FormValue,256                          DWARFUnit *U) -> Expected<DWARFAddressRangesVector> {257        if (FormValue.getForm() == dwarf::DW_FORM_rnglistx)258          return U->findRnglistFromIndex(*FormValue.getAsSectionOffset());259        return U->findRnglistFromOffset(*FormValue.getAsSectionOffset());260      };261      Expected<DWARFAddressRangesVector> RangesOrError =262          GetRanges(FormValue, U);263      if (!RangesOrError) {264        LLVM_DEBUG({265          std::string TheError(toString(RangesOrError.takeError()));266          dbgs() << format("error decoding address ranges = ",267                           TheError.c_str());268        });269        consumeError(RangesOrError.takeError());270        break;271      }272      // The address ranges are absolute. There is no need to add any addend.273      DWARFAddressRangesVector Ranges = RangesOrError.get();274      for (DWARFAddressRange &Range : Ranges) {275        // This seems to be a tombstone for empty ranges.276        if ((Range.LowPC == Range.HighPC) ||277            (Range.LowPC == getTombstoneAddress()))278          continue;279        // Store the real upper limit for the address range.280        if (UpdateHighAddress && Range.HighPC > 0)281          --Range.HighPC;282        // Consider the case of WebAssembly.283        Range.LowPC += WasmCodeSectionOffset;284        Range.HighPC += WasmCodeSectionOffset;285        // Add the pair of addresses.286        CurrentScope->addObject(Range.LowPC, Range.HighPC);287        // If the scope is the CU, do not update the ranges set.288        if (!CurrentElement->isCompileUnit())289          CurrentRanges.emplace_back(Range.LowPC, Range.HighPC);290      }291    }292    break;293 294  // Get the location list for the symbol.295  case dwarf::DW_AT_data_member_location:296    if (options().getAttributeAnyLocation())297      processLocationMember(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);298    break;299 300  // Get the location list for the symbol.301  case dwarf::DW_AT_location:302  case dwarf::DW_AT_string_length:303  case dwarf::DW_AT_use_location:304    if (options().getAttributeAnyLocation() && CurrentSymbol)305      processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);306    break;307 308  case dwarf::DW_AT_call_data_value:309  case dwarf::DW_AT_call_value:310  case dwarf::DW_AT_GNU_call_site_data_value:311  case dwarf::DW_AT_GNU_call_site_value:312    if (options().getAttributeAnyLocation() && CurrentSymbol)313      processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry,314                          /*CallSiteLocation=*/true);315    break;316 317  default:318    break;319  }320}321 322LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent,323                                      DWARFDie &SkeletonDie) {324  // If the input DIE corresponds to the compile unit, it can be:325  // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty).326  // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE327  //    for the skeleton DWARF. Process both DIEs.328  const DWARFDie &DIE = SkeletonDie.isValid() ? SkeletonDie : InputDIE;329  DWARFDataExtractor DebugInfoData =330      DIE.getDwarfUnit()->getDebugInfoExtractor();331  LVOffset Offset = DIE.getOffset();332 333  // Reset values for the current DIE.334  CurrentLowPC = 0;335  CurrentHighPC = 0;336  CurrentOffset = Offset;337  CurrentEndOffset = 0;338  FoundLowPC = false;339  FoundHighPC = false;340 341  // Process supported attributes.342  if (DebugInfoData.isValidOffset(Offset)) {343 344    LLVM_DEBUG({345      dbgs() << "DIE: " << hexValue(Offset) << formatv(" {0}", DIE.getTag())346             << "\n";347    });348 349    // Create the logical view element for the current DIE.350    dwarf::Tag Tag = DIE.getTag();351    CurrentElement = createElement(Tag);352    if (!CurrentElement)353      return CurrentScope;354 355    CurrentElement->setTag(Tag);356    CurrentElement->setOffset(Offset);357 358    if (options().getAttributeAnySource() && CurrentElement->isCompileUnit())359      addCompileUnitOffset(Offset,360                           static_cast<LVScopeCompileUnit *>(CurrentElement));361 362    // Insert the newly created element into the element symbol table. If the363    // element is in the list, it means there are previously created elements364    // referencing this element.365    auto [It, Inserted] = ElementTable.try_emplace(Offset, CurrentElement);366    if (!Inserted) {367      // There are previous references to this element. We need to update the368      // element and all the references pointing to this element.369      LVElementEntry &Reference = ElementTable[Offset];370      Reference.Element = CurrentElement;371      // Traverse the element set and update the elements (backtracking).372      for (LVElement *Target : Reference.References)373        Target->setReference(CurrentElement);374      for (LVElement *Target : Reference.Types)375        Target->setType(CurrentElement);376      // Clear the pending elements.377      Reference.References.clear();378      Reference.Types.clear();379    }380 381    // Add the current element to its parent as there are attributes382    // (locations) that require the scope level.383    if (CurrentScope)384      Parent->addElement(CurrentScope);385    else if (CurrentSymbol)386      Parent->addElement(CurrentSymbol);387    else if (CurrentType)388      Parent->addElement(CurrentType);389 390    // Process the attributes for the given DIE.391    auto ProcessAttributes = [&](const DWARFDie &TheDIE,392                                 DWARFDataExtractor &DebugData) {393      CurrentEndOffset = Offset;394      uint32_t abbrCode = DebugData.getULEB128(&CurrentEndOffset);395      if (abbrCode) {396        if (const DWARFAbbreviationDeclaration *AbbrevDecl =397                TheDIE.getAbbreviationDeclarationPtr())398          if (AbbrevDecl)399            for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :400                 AbbrevDecl->attributes())401              processOneAttribute(TheDIE, &CurrentEndOffset, AttrSpec);402      }403    };404 405    ProcessAttributes(DIE, DebugInfoData);406 407    // If the input DIE is for a compile unit, process its attributes in408    // the case of split DWARF, to override any common attribute values.409    if (SkeletonDie.isValid()) {410      DWARFDataExtractor DebugInfoData =411          InputDIE.getDwarfUnit()->getDebugInfoExtractor();412      LVOffset Offset = InputDIE.getOffset();413      if (DebugInfoData.isValidOffset(Offset))414        ProcessAttributes(InputDIE, DebugInfoData);415    }416  }417 418  if (CurrentScope) {419    if (CurrentScope->getCanHaveRanges()) {420      // If the scope has ranges, they are already added to the scope.421      // Add any collected LowPC/HighPC values.422      bool IsCompileUnit = CurrentScope->getIsCompileUnit();423      if (FoundLowPC && FoundHighPC) {424        CurrentScope->addObject(CurrentLowPC, CurrentHighPC);425        if (!IsCompileUnit) {426          // If the scope is a function, add it to the public names.427          if ((options().getAttributePublics() ||428               options().getPrintAnyLine()) &&429              CurrentScope->getIsFunction() &&430              !CurrentScope->getIsInlinedFunction())431            CompileUnit->addPublicName(CurrentScope, CurrentLowPC,432                                       CurrentHighPC);433        }434      }435 436      // Look for scopes with ranges and no linkage name information that437      // are referencing another scopes via DW_AT_specification. They are438      // possible candidates for a comdat scope.439      if (CurrentScope->getHasRanges() &&440          !CurrentScope->getLinkageNameIndex() &&441          CurrentScope->getHasReferenceSpecification()) {442        // Get the linkage name in order to search for a possible comdat.443        std::optional<DWARFFormValue> LinkageDIE =444            DIE.findRecursively(dwarf::DW_AT_linkage_name);445        if (LinkageDIE.has_value()) {446          StringRef Name(dwarf::toStringRef(LinkageDIE));447          if (!Name.empty())448            CurrentScope->setLinkageName(Name);449        }450      }451 452      // If the current scope is in the 'LinkageNames' table, update its453      // logical scope. For other scopes, always we will assume the default454      // ".text" section index.455      LVSectionIndex SectionIndex = updateSymbolTable(CurrentScope);456      if (CurrentScope->getIsComdat())457        CompileUnit->setHasComdatScopes();458 459      // Update section index contained ranges.460      if (SectionIndex) {461        if (!CurrentRanges.empty()) {462          for (LVAddressRange &Range : CurrentRanges)463            addSectionRange(SectionIndex, CurrentScope, Range.first,464                            Range.second > Range.first465                                ? Range.second - 1 // Make hi-pc exclusive466                                : Range.second);467          CurrentRanges.clear();468        }469        // If the scope is the CU, do not update the ranges set.470        if (FoundLowPC && FoundHighPC && !IsCompileUnit) {471          addSectionRange(SectionIndex, CurrentScope, CurrentLowPC,472                          CurrentHighPC > CurrentLowPC473                              ? CurrentHighPC - 1 // Make hi-pc exclusive474                              : CurrentHighPC);475        }476      }477    }478    // Mark member functions.479    if (Parent->getIsAggregate())480      CurrentScope->setIsMember();481  }482 483  // Keep track of symbols with locations.484  if (options().getAttributeAnyLocation() && CurrentSymbol &&485      CurrentSymbol->getHasLocation())486    SymbolsWithLocations.push_back(CurrentSymbol);487 488  // If we have template parameters, mark the parent as template.489  if (CurrentType && CurrentType->getIsTemplateParam())490    Parent->setIsTemplate();491 492  return CurrentScope;493}494 495void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent,496                                           DWARFDie &SkeletonDie) {497  // Process the current DIE.498  LVScope *Scope = processOneDie(DIE, Parent, SkeletonDie);499  if (Scope) {500    LVOffset Lower = DIE.getOffset();501    LVOffset Upper = CurrentEndOffset;502    DWARFDie DummyDie;503    // Traverse the children chain.504    DWARFDie Child = DIE.getFirstChild();505    while (Child) {506      traverseDieAndChildren(Child, Scope, DummyDie);507      Upper = Child.getOffset();508      Child = Child.getSibling();509    }510    // Calculate contributions to the debug info section.511    if (options().getPrintSizes() && Upper)512      CompileUnit->addSize(Scope, Lower, Upper);513  }514}515 516void LVDWARFReader::processLocationGaps() {517  if (options().getAttributeAnyLocation())518    for (LVSymbol *Symbol : SymbolsWithLocations)519      Symbol->fillLocationGaps();520}521 522void LVDWARFReader::createLineAndFileRecords(523    const DWARFDebugLine::LineTable *Lines) {524  if (!Lines)525    return;526 527  // Get the source filenames.528  if (!Lines->Prologue.FileNames.empty())529    for (const DWARFDebugLine::FileNameEntry &Entry :530         Lines->Prologue.FileNames) {531      std::string Directory;532      if (Lines->getDirectoryForEntry(Entry, Directory))533        Directory = transformPath(Directory);534      if (Directory.empty())535        Directory = std::string(CompileUnit->getCompilationDirectory());536      std::string File = transformPath(dwarf::toStringRef(Entry.Name));537      std::string String;538      raw_string_ostream(String) << Directory << "/" << File;539      CompileUnit->addFilename(String);540    }541 542  // In DWARF5 the file indexes start at 0;543  bool IncrementIndex = Lines->Prologue.getVersion() >= 5;544 545  // Get the source lines if requested by command line option.546  if (options().getPrintLines() && Lines->Rows.size())547    for (const DWARFDebugLine::Row &Row : Lines->Rows) {548      // Here we collect logical debug lines in CULines. Later on,549      // the 'processLines()' function will move each created logical line550      // to its enclosing logical scope, using the debug ranges information551      // and they will be released when its scope parent is deleted.552      LVLineDebug *Line = createLineDebug();553      CULines.push_back(Line);554      // Consider the case of WebAssembly.555      Line->setAddress(Row.Address.Address + WasmCodeSectionOffset);556      Line->setFilename(557          CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));558      Line->setLineNumber(Row.Line);559      if (Row.Discriminator)560        Line->setDiscriminator(Row.Discriminator);561      if (Row.IsStmt)562        Line->setIsNewStatement();563      if (Row.BasicBlock)564        Line->setIsBasicBlock();565      if (Row.EndSequence)566        Line->setIsEndSequence();567      if (Row.EpilogueBegin)568        Line->setIsEpilogueBegin();569      if (Row.PrologueEnd)570        Line->setIsPrologueEnd();571      LLVM_DEBUG({572        dbgs() << "Address: " << hexValue(Line->getAddress())573               << " Line: " << Line->lineNumberAsString(/*ShowZero=*/true)574               << "\n";575      });576    }577}578 579std::string LVDWARFReader::getRegisterName(LVSmall Opcode,580                                           ArrayRef<uint64_t> Operands) {581  // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support582  // DW_OP_regval_type. At this point we are operating on a logical view583  // item, with no access to the underlying DWARF data used by LLVM.584  // We do not support DW_OP_regval_type here.585  if (Opcode == dwarf::DW_OP_regval_type)586    return {};587 588  std::string string;589  raw_string_ostream Stream(string);590  DIDumpOptions DumpOpts;591  auto *MCRegInfo = MRI.get();592  auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {593    if (!MCRegInfo)594      return {};595    if (std::optional<MCRegister> LLVMRegNum =596            MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))597      if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))598        return StringRef(RegName);599    return {};600  };601  DumpOpts.GetNameForDWARFReg = GetRegName;602  prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, Opcode, Operands);603  return Stream.str();604}605 606Error LVDWARFReader::createScopes() {607  LLVM_DEBUG({608    W.startLine() << "\n";609    W.printString("File", Obj.getFileName().str());610    W.printString("Format", FileFormatName);611  });612 613  if (Error Err = LVReader::createScopes())614    return Err;615 616  // As the DwarfContext object is valid only during the scopes creation,617  // we need to create our own Target information, to be used during the618  // logical view printing, in the case of instructions being requested.619  std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(Obj);620  if (!DwarfContext)621    return createStringError(errc::invalid_argument,622                             "Could not create DWARF information: %s",623                             getFilename().str().c_str());624 625  if (Error Err = loadTargetInfo(Obj))626    return Err;627 628  // Create a mapping for virtual addresses.629  mapVirtualAddress(Obj);630 631  // Select the correct compile unit range, depending if we are dealing with632  // a standard or split DWARF object.633  DWARFContext::compile_unit_range CompileUnits =634      DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units()635                                         : DwarfContext->dwo_compile_units();636  for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {637 638    // Take into account the address byte size for a correct 'tombstone'639    // value identification.640    setTombstoneAddress(641        dwarf::computeTombstoneAddress(CU->getAddressByteSize()));642 643    // Deduction of index used for the line records.644    //645    // For the following test case: test.cpp646    //  void foo(void ParamPtr) { }647 648    // Both GCC and Clang generate DWARF-5 .debug_line layout.649 650    // * GCC (GNU C++17 11.3.0) - All DW_AT_decl_file use index 1.651    //652    //   .debug_info:653    //     format = DWARF32, version = 0x0005654    //     DW_TAG_compile_unit655    //       DW_AT_name	("test.cpp")656    //       DW_TAG_subprogram ("foo")657    //         DW_AT_decl_file (1)658    //         DW_TAG_formal_parameter ("ParamPtr")659    //           DW_AT_decl_file (1)660    //   .debug_line:661    //     Line table prologue: format (DWARF32), version (5)662    //     include_directories[0] = "..."663    //     file_names[0]: name ("test.cpp"), dir_index (0)664    //     file_names[1]: name ("test.cpp"), dir_index (0)665 666    // * Clang (14.0.6) - All DW_AT_decl_file use index 0.667    //668    //   .debug_info:669    //     format = DWARF32, version = 0x0005670    //     DW_AT_producer	("clang version 14.0.6")671    //     DW_AT_name	("test.cpp")672    //673    //     DW_TAG_subprogram ("foo")674    //       DW_AT_decl_file (0)675    //       DW_TAG_formal_parameter ("ParamPtr")676    //         DW_AT_decl_file (0)677    //   .debug_line:678    //     Line table prologue: format (DWARF32), version (5)679    //     include_directories[0] = "..."680    //     file_names[0]: name ("test.cpp"), dir_index (0)681 682    // From DWARFDebugLine::getFileNameByIndex documentation:683    //   In Dwarf 4, the files are 1-indexed.684    //   In Dwarf 5, the files are 0-indexed.685    // Additional discussions here:686    // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html687 688    // The DWARF reader is expecting the files are 1-indexed, so using689    // the .debug_line header information decide if the indexed require690    // an internal adjustment.691 692    // For the case of GCC (DWARF5), if the entries[0] and [1] are the693    // same, do not perform any adjustment.694    auto DeduceIncrementFileIndex = [&]() -> bool {695      if (CU->getVersion() < 5)696        // DWARF-4 or earlier -> Don't increment index.697        return false;698 699      if (const DWARFDebugLine::LineTable *LT =700              CU->getContext().getLineTableForUnit(CU.get())) {701        // Check if there are at least 2 entries and if they are the same.702        if (LT->hasFileAtIndex(0) && LT->hasFileAtIndex(1)) {703          const DWARFDebugLine::FileNameEntry &EntryZero =704              LT->Prologue.getFileNameEntry(0);705          const DWARFDebugLine::FileNameEntry &EntryOne =706              LT->Prologue.getFileNameEntry(1);707          // Check directory indexes.708          if (EntryZero.DirIdx != EntryOne.DirIdx)709            // DWARF-5 -> Increment index.710            return true;711          // Check filename.712          std::string FileZero;713          std::string FileOne;714          StringRef None;715          LT->getFileNameByIndex(716              0, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,717              FileZero);718          LT->getFileNameByIndex(719              1, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,720              FileOne);721          return FileZero != FileOne;722        }723      }724 725      // DWARF-5 -> Increment index.726      return true;727    };728    // The DWARF reader expects the indexes as 1-indexed.729    IncrementFileIndex = DeduceIncrementFileIndex();730 731    DWARFDie UnitDie = CU->getUnitDIE();732    SmallString<16> DWOAlternativeLocation;733    if (UnitDie) {734      std::optional<const char *> DWOFileName =735          CU->getVersion() >= 5736              ? dwarf::toString(UnitDie.find(dwarf::DW_AT_dwo_name))737              : dwarf::toString(UnitDie.find(dwarf::DW_AT_GNU_dwo_name));738      StringRef From(DWOFileName.value_or(""));739      DWOAlternativeLocation = createAlternativePath(From);740    }741 742    // The current CU can be a normal compile unit (standard) or a skeleton743    // compile unit (split). For both cases, the returned die, will be used744    // to create the logical scopes.745    DWARFDie CUDie = CU->getNonSkeletonUnitDIE(746        /*ExtractUnitDIEOnly=*/false,747        /*DWOAlternativeLocation=*/DWOAlternativeLocation);748    if (!CUDie.isValid())749      continue;750 751    // The current unit corresponds to the .dwo file. We need to get the752    // skeleton unit and query for any ranges that will enclose any ranges753    // in the non-skeleton unit.754    DWARFDie DummyDie;755    DWARFDie SkeletonDie =756        CUDie.getDwarfUnit()->isDWOUnit() ? CU->getUnitDIE(false) : DummyDie;757    // Disable the ranges processing if we have just a single .dwo object,758    // as any DW_AT_ranges will access not available range information.759    RangesDataAvailable =760        (!CUDie.getDwarfUnit()->isDWOUnit() ||761         (SkeletonDie.isValid() ? !SkeletonDie.getDwarfUnit()->isDWOUnit()762                                : true));763 764    traverseDieAndChildren(CUDie, Root, SkeletonDie);765 766    createLineAndFileRecords(DwarfContext->getLineTableForUnit(CU.get()));767    if (Error Err = createInstructions())768      return Err;769 770    // Process the compilation unit, as there are cases where enclosed771    // functions have the same ranges values. Insert the compilation unit772    // ranges at the end, to allow enclosing ranges to be first in the list.773    LVSectionIndex SectionIndex = getSectionIndex(CompileUnit);774    addSectionRange(SectionIndex, CompileUnit);775    LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);776    ScopesWithRanges->sort();777 778    processLines(&CULines, SectionIndex);779    processLocationGaps();780 781    // These are per compile unit.782    ScopesWithRanges->clear();783    SymbolsWithLocations.clear();784    CULines.clear();785  }786 787  return Error::success();788}789 790// Get the location information for the associated attribute.791void LVDWARFReader::processLocationList(dwarf::Attribute Attr,792                                        const DWARFFormValue &FormValue,793                                        const DWARFDie &Die,794                                        uint64_t OffsetOnEntry,795                                        bool CallSiteLocation) {796 797  auto ProcessLocationExpression = [&](const DWARFExpression &Expression) {798    for (const DWARFExpression::Operation &Op : Expression)799      CurrentSymbol->addLocationOperands(Op.getCode(), Op.getRawOperands());800  };801 802  DWARFUnit *U = Die.getDwarfUnit();803  DWARFContext &DwarfContext = U->getContext();804  bool IsLittleEndian = DwarfContext.isLittleEndian();805  if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||806      (DWARFAttribute::mayHaveLocationExpr(Attr) &&807       FormValue.isFormClass(DWARFFormValue::FC_Exprloc))) {808    ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();809    DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),810                       IsLittleEndian, 0);811    DWARFExpression Expression(Data, U->getAddressByteSize(),812                               U->getFormParams().Format);813 814    // Add location and operation entries.815    CurrentSymbol->addLocation(Attr, /*LowPC=*/0, /*HighPC=*/-1,816                               /*SectionOffset=*/0, OffsetOnEntry,817                               CallSiteLocation);818    ProcessLocationExpression(Expression);819    return;820  }821 822  if (DWARFAttribute::mayHaveLocationList(Attr) &&823      FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {824    uint64_t Offset = *FormValue.getAsSectionOffset();825    if (FormValue.getForm() == dwarf::DW_FORM_loclistx) {826      std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(Offset);827      if (!LoclistOffset)828        return;829      Offset = *LoclistOffset;830    }831    uint64_t BaseAddr = 0;832    if (std::optional<SectionedAddress> BA = U->getBaseAddress())833      BaseAddr = BA->Address;834    LVAddress LowPC = 0;835    LVAddress HighPC = 0;836 837    auto ProcessLocationEntry = [&](const DWARFLocationEntry &Entry) {838      if (Entry.Kind == dwarf::DW_LLE_base_address) {839        BaseAddr = Entry.Value0;840        return;841      }842      if (Entry.Kind == dwarf::DW_LLE_offset_pair) {843        LowPC = BaseAddr + Entry.Value0;844        HighPC = BaseAddr + Entry.Value1;845        DWARFAddressRange Range{LowPC, HighPC, Entry.SectionIndex};846        if (Range.SectionIndex == SectionedAddress::UndefSection)847          Range.SectionIndex = Entry.SectionIndex;848        DWARFLocationExpression Loc{Range, Entry.Loc};849        DWARFDataExtractor Data(Loc.Expr, IsLittleEndian,850                                U->getAddressByteSize());851        DWARFExpression Expression(Data, U->getAddressByteSize());852 853        // Store the real upper limit for the address range.854        if (UpdateHighAddress && HighPC > 0)855          --HighPC;856        // Add location and operation entries.857        CurrentSymbol->addLocation(Attr, LowPC, HighPC, Offset, OffsetOnEntry,858                                   CallSiteLocation);859        ProcessLocationExpression(Expression);860      }861    };862    Error E = U->getLocationTable().visitLocationList(863        &Offset, [&](const DWARFLocationEntry &E) {864          ProcessLocationEntry(E);865          return true;866        });867    if (E)868      consumeError(std::move(E));869  }870}871 872void LVDWARFReader::processLocationMember(dwarf::Attribute Attr,873                                          const DWARFFormValue &FormValue,874                                          const DWARFDie &Die,875                                          uint64_t OffsetOnEntry) {876  // Check if the value is an integer constant.877  if (FormValue.isFormClass(DWARFFormValue::FC_Constant))878    // Add a record to hold a constant as location.879    CurrentSymbol->addLocationConstant(Attr, *FormValue.getAsUnsignedConstant(),880                                       OffsetOnEntry);881  else882    // This is a location description, or a reference to one.883    processLocationList(Attr, FormValue, Die, OffsetOnEntry);884}885 886// Update the current element with the reference.887void LVDWARFReader::updateReference(dwarf::Attribute Attr,888                                    const DWARFFormValue &FormValue) {889  // FIXME: We are assuming that at most one Reference (DW_AT_specification,890  // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type)891  // appear in any single DIE, but this may not be true.892  uint64_t Offset;893  if (std::optional<uint64_t> Off = FormValue.getAsRelativeReference())894    Offset = FormValue.getUnit()->getOffset() + *Off;895  else if (Off = FormValue.getAsDebugInfoReference(); Off)896    Offset = *Off;897  else898    llvm_unreachable("Unsupported reference type");899 900  // Get target for the given reference, if already created.901  LVElement *Target = getElementForOffset(902      Offset, CurrentElement,903      /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type);904  // Check if we are dealing with cross CU references.905  if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) {906    if (Target) {907      // The global reference is ready. Mark it as global.908      Target->setIsGlobalReference();909      // Remove global reference from the unseen list.910      removeGlobalOffset(Offset);911    } else912      // Record the unseen cross CU reference.913      addGlobalOffset(Offset);914  }915 916  // At this point, 'Target' can be null, in the case of the target element917  // not being seen. But the correct bit is set, to indicate that the target918  // is being referenced by (abstract_origin, extension, specification) or919  // (import, type).920  // We must differentiate between the kind of reference. This is needed to921  // complete inlined function instances with dropped abstract references,922  // in order to facilitate a logical comparison.923  switch (Attr) {924  case dwarf::DW_AT_abstract_origin:925  case dwarf::DW_AT_call_origin:926    CurrentElement->setReference(Target);927    CurrentElement->setHasReferenceAbstract();928    break;929  case dwarf::DW_AT_extension:930    CurrentElement->setReference(Target);931    CurrentElement->setHasReferenceExtension();932    break;933  case dwarf::DW_AT_specification:934    CurrentElement->setReference(Target);935    CurrentElement->setHasReferenceSpecification();936    break;937  case dwarf::DW_AT_import:938  case dwarf::DW_AT_type:939    CurrentElement->setType(Target);940    break;941  default:942    break;943  }944}945 946// Get an element given the DIE offset.947LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset,948                                              LVElement *Element, bool IsType) {949  // Update the element and all the references pointing to this element.950  LVElementEntry &Entry = ElementTable[Offset];951  if (!Entry.Element) {952    if (IsType)953      Entry.Types.insert(Element);954    else955      Entry.References.insert(Element);956  }957  return Entry.Element;958}959 960Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) {961  // Detect the architecture from the object file. We usually don't need OS962  // info to lookup a target and create register info.963  Triple TT = Obj.makeTriple();964 965  // Features to be passed to target/subtarget966  Expected<SubtargetFeatures> Features = Obj.getFeatures();967  SubtargetFeatures FeaturesValue;968  if (!Features) {969    consumeError(Features.takeError());970    FeaturesValue = SubtargetFeatures();971  }972  FeaturesValue = *Features;973 974  StringRef CPU;975  if (auto OptCPU = Obj.tryGetCPUName())976    CPU = *OptCPU;977 978  return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU);979}980 981void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) {982  for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) {983    const SymbolRef &Symbol = *Iter;984 985    Expected<SymbolRef::Type> TypeOrErr = Symbol.getType();986    if (!TypeOrErr) {987      consumeError(TypeOrErr.takeError());988      continue;989    }990 991    // Process only symbols that represent a function.992    SymbolRef::Type Type = *TypeOrErr;993    if (Type != SymbolRef::ST_Function)994      continue;995 996    // In the case of a Mach-O STAB symbol, get its section only if997    // the STAB symbol's section field refers to a valid section index.998    // Otherwise the symbol may error trying to load a section that999    // does not exist.1000    const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);1001    bool IsSTAB = false;1002    if (MachO) {1003      DataRefImpl SymDRI = Symbol.getRawDataRefImpl();1004      uint8_t NType =1005          (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type1006                            : MachO->getSymbolTableEntry(SymDRI).n_type);1007      if (NType & MachO::N_STAB)1008        IsSTAB = true;1009    }1010 1011    Expected<section_iterator> IterOrErr = Symbol.getSection();1012    if (!IterOrErr) {1013      consumeError(IterOrErr.takeError());1014      continue;1015    }1016    section_iterator Section = IsSTAB ? Obj.section_end() : *IterOrErr;1017    if (Section == Obj.section_end())1018      continue;1019 1020    // Get the symbol value.1021    Expected<uint64_t> AddressOrErr = Symbol.getAddress();1022    if (!AddressOrErr) {1023      consumeError(AddressOrErr.takeError());1024      continue;1025    }1026    uint64_t Address = *AddressOrErr;1027 1028    // Get symbol name.1029    StringRef Name;1030    Expected<StringRef> NameOrErr = Symbol.getName();1031    if (!NameOrErr) {1032      consumeError(NameOrErr.takeError());1033      continue;1034    }1035    Name = *NameOrErr;1036 1037    // Check if the symbol is Comdat.1038    Expected<uint32_t> FlagsOrErr = Symbol.getFlags();1039    if (!FlagsOrErr) {1040      consumeError(FlagsOrErr.takeError());1041      continue;1042    }1043    uint32_t Flags = *FlagsOrErr;1044 1045    // Mark the symbol as 'comdat' in any of the following cases:1046    // - Symbol has the SF_Weak flag or1047    // - Symbol section index different from the DotTextSectionIndex.1048    LVSectionIndex SectionIndex = Section->getIndex();1049    bool IsComdat =1050        (Flags & SymbolRef::SF_Weak) || (SectionIndex != DotTextSectionIndex);1051 1052    // Record the symbol name (linkage) and its loading address.1053    addToSymbolTable(Name, Address, SectionIndex, IsComdat);1054  }1055}1056 1057void LVDWARFReader::sortScopes() { Root->sort(); }1058 1059void LVDWARFReader::print(raw_ostream &OS) const {1060  OS << "LVType\n";1061  LLVM_DEBUG(dbgs() << "CreateReaders\n");1062}1063