//===-- LVDWARFReader.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the LVDWARFReader class.
// It supports ELF, Mach-O and Wasm binary formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/FormatVariadic.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::logicalview;

#define DEBUG_TYPE "DWARFReader"

void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
                                        LVOffset *OffsetPtr,
                                        const AttributeSpec &AttrSpec) {
  uint64_t OffsetOnEntry = *OffsetPtr;
  DWARFUnit *U = Die.getDwarfUnit();
  const DWARFFormValue &FormValue =
      DWARFFormValue::createFromUnit(AttrSpec.Form, U, OffsetPtr);

  // We are processing .debug_info section, implicit_const attribute
  // values are not really stored here, but in .debug_abbrev section.
  auto GetAsUnsignedConstant = [&]() -> int64_t {
    if (AttrSpec.isImplicitConst())
      return AttrSpec.getImplicitConstValue();
    if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
      return *Val;
    return 0;
  };

  auto GetFlag = [](const DWARFFormValue &FormValue) -> bool {
    return FormValue.isFormClass(DWARFFormValue::FC_Flag);
  };

  auto GetBoundValue = [&AttrSpec](const DWARFFormValue &FormValue) -> int64_t {
    switch (FormValue.getForm()) {
    case dwarf::DW_FORM_ref_addr:
    case dwarf::DW_FORM_ref1:
    case dwarf::DW_FORM_ref2:
    case dwarf::DW_FORM_ref4:
    case dwarf::DW_FORM_ref8:
    case dwarf::DW_FORM_ref_udata:
    case dwarf::DW_FORM_ref_sig8:
      return *FormValue.getAsReferenceUVal();
    case dwarf::DW_FORM_data1:
    case dwarf::DW_FORM_flag:
    case dwarf::DW_FORM_data2:
    case dwarf::DW_FORM_data4:
    case dwarf::DW_FORM_data8:
    case dwarf::DW_FORM_udata:
    case dwarf::DW_FORM_ref_sup4:
    case dwarf::DW_FORM_ref_sup8:
      return *FormValue.getAsUnsignedConstant();
    case dwarf::DW_FORM_sdata:
      return *FormValue.getAsSignedConstant();
    case dwarf::DW_FORM_implicit_const:
      return AttrSpec.getImplicitConstValue();
    default:
      return 0;
    }
  };

  LLVM_DEBUG({
    dbgs() << "     " << hexValue(OffsetOnEntry)
           << formatv(" {0}", AttrSpec.Attr) << "\n";
  });

  switch (AttrSpec.Attr) {
  case dwarf::DW_AT_accessibility:
    CurrentElement->setAccessibilityCode(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_artificial:
    CurrentElement->setIsArtificial();
    break;
  case dwarf::DW_AT_bit_size:
    CurrentElement->setBitSize(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_byte_size:
    CurrentElement->setBitSize(GetAsUnsignedConstant() * DWARF_CHAR_BIT);
    break;
  case dwarf::DW_AT_call_file:
    CurrentElement->setCallFilenameIndex(IncrementFileIndex
                                             ? GetAsUnsignedConstant() + 1
                                             : GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_call_line:
    CurrentElement->setCallLineNumber(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_comp_dir:
    CompileUnit->setCompilationDirectory(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_const_value:
    if (FormValue.isFormClass(DWARFFormValue::FC_Block)) {
      ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
      // Store the expression as a hexadecimal string.
      CurrentElement->setValue(
          llvm::toHex(llvm::toStringRef(Expr), /*LowerCase=*/true));
    } else if (FormValue.isFormClass(DWARFFormValue::FC_Constant)) {
      // In the case of negative values, generate the string representation
      // for a positive value prefixed with the negative sign.
      if (FormValue.getForm() == dwarf::DW_FORM_sdata) {
        std::stringstream Stream;
        int64_t Value = *FormValue.getAsSignedConstant();
        if (Value < 0) {
          Stream << "-";
          Value = std::abs(Value);
        }
        Stream << hexString(Value, 2);
        CurrentElement->setValue(Stream.str());
      } else
        CurrentElement->setValue(hexString(GetAsUnsignedConstant(), 2));
    } else
      CurrentElement->setValue(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_count:
    CurrentElement->setCount(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_decl_line:
    CurrentElement->setLineNumber(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_decl_file:
    CurrentElement->setFilenameIndex(IncrementFileIndex
                                         ? GetAsUnsignedConstant() + 1
                                         : GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_enum_class:
    if (GetFlag(FormValue))
      CurrentElement->setIsEnumClass();
    break;
  case dwarf::DW_AT_external:
    if (GetFlag(FormValue))
      CurrentElement->setIsExternal();
    break;
  case dwarf::DW_AT_GNU_discriminator:
    CurrentElement->setDiscriminator(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_inline:
    CurrentElement->setInlineCode(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_lower_bound:
    CurrentElement->setLowerBound(GetBoundValue(FormValue));
    break;
  case dwarf::DW_AT_name:
    CurrentElement->setName(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_GNU_template_name:
    CurrentElement->setValue(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_linkage_name:
  case dwarf::DW_AT_MIPS_linkage_name:
    CurrentElement->setLinkageName(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_producer:
    if (options().getAttributeProducer())
      CurrentElement->setProducer(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_language:
    if (options().getAttributeLanguage())
      CurrentElement->setSourceLanguage(LVSourceLanguage{
          static_cast<llvm::dwarf::SourceLanguage>(GetAsUnsignedConstant())});
    break;
  case dwarf::DW_AT_upper_bound:
    CurrentElement->setUpperBound(GetBoundValue(FormValue));
    break;
  case dwarf::DW_AT_virtuality:
    CurrentElement->setVirtualityCode(GetAsUnsignedConstant());
    break;

  case dwarf::DW_AT_abstract_origin:
  case dwarf::DW_AT_call_origin:
  case dwarf::DW_AT_extension:
  case dwarf::DW_AT_import:
  case dwarf::DW_AT_specification:
  case dwarf::DW_AT_type:
    updateReference(AttrSpec.Attr, FormValue);
    break;

  case dwarf::DW_AT_low_pc:
    if (options().getGeneralCollectRanges()) {
      FoundLowPC = true;
      // For toolchains that support the removal of unused code, the linker
      // marks functions that have been removed, by setting the value for the
      // low_pc to the max address.
      if (std::optional<uint64_t> Value = FormValue.getAsAddress()) {
        CurrentLowPC = *Value;
      } else {
        uint64_t UValue = FormValue.getRawUValue();
        if (U->getAddrOffsetSectionItem(UValue)) {
          CurrentLowPC = *FormValue.getAsAddress();
        } else {
          FoundLowPC = false;
          // We are dealing with an index into the .debug_addr section.
          LLVM_DEBUG({
            dbgs() << format("indexed (%8.8x) address = ", (uint32_t)UValue);
          });
        }
      }
      if (FoundLowPC) {
        if (CurrentLowPC == getTombstoneAddress())
          CurrentElement->setIsDiscarded();
        else
          // Consider the case of WebAssembly.
          CurrentLowPC += WasmCodeSectionOffset;
        if (CurrentElement->isCompileUnit())
          setCUBaseAddress(CurrentLowPC);
      }
    }
    break;

  case dwarf::DW_AT_high_pc:
    if (options().getGeneralCollectRanges()) {
      FoundHighPC = true;
      if (std::optional<uint64_t> Address = FormValue.getAsAddress())
        // High PC is an address.
        CurrentHighPC = *Address;
      if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant())
        // High PC is an offset from LowPC.
        // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as
        // the CurrentLowPC has already that offset added. Basically, use the
        // original DW_AT_loc_pc value.
        CurrentHighPC =
            (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) +
            *Offset;
      // Store the real upper limit for the address range.
      if (UpdateHighAddress && CurrentHighPC > 0)
        --CurrentHighPC;
      // Consider the case of WebAssembly.
      CurrentHighPC += WasmCodeSectionOffset;
      if (CurrentElement->isCompileUnit())
        setCUHighAddress(CurrentHighPC);
    }
    break;

  case dwarf::DW_AT_ranges:
    if (RangesDataAvailable && options().getGeneralCollectRanges()) {
      auto GetRanges = [](const DWARFFormValue &FormValue,
                          DWARFUnit *U) -> Expected<DWARFAddressRangesVector> {
        if (FormValue.getForm() == dwarf::DW_FORM_rnglistx)
          return U->findRnglistFromIndex(*FormValue.getAsSectionOffset());
        return U->findRnglistFromOffset(*FormValue.getAsSectionOffset());
      };
      Expected<DWARFAddressRangesVector> RangesOrError =
          GetRanges(FormValue, U);
      if (!RangesOrError) {
        LLVM_DEBUG({
          std::string TheError(toString(RangesOrError.takeError()));
          dbgs() << format("error decoding address ranges = ",
                           TheError.c_str());
        });
        consumeError(RangesOrError.takeError());
        break;
      }
      // The address ranges are absolute. There is no need to add any addend.
      DWARFAddressRangesVector Ranges = RangesOrError.get();
      for (DWARFAddressRange &Range : Ranges) {
        // This seems to be a tombstone for empty ranges.
        if ((Range.LowPC == Range.HighPC) ||
            (Range.LowPC == getTombstoneAddress()))
          continue;
        // Store the real upper limit for the address range.
        if (UpdateHighAddress && Range.HighPC > 0)
          --Range.HighPC;
        // Consider the case of WebAssembly.
        Range.LowPC += WasmCodeSectionOffset;
        Range.HighPC += WasmCodeSectionOffset;
        // Add the pair of addresses.
        CurrentScope->addObject(Range.LowPC, Range.HighPC);
        // If the scope is the CU, do not update the ranges set.
        if (!CurrentElement->isCompileUnit())
          CurrentRanges.emplace_back(Range.LowPC, Range.HighPC);
      }
    }
    break;

  // Get the location list for the symbol.
  case dwarf::DW_AT_data_member_location:
    if (options().getAttributeAnyLocation())
      processLocationMember(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);
    break;

  // Get the location list for the symbol.
  case dwarf::DW_AT_location:
  case dwarf::DW_AT_string_length:
  case dwarf::DW_AT_use_location:
    if (options().getAttributeAnyLocation() && CurrentSymbol)
      processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);
    break;

  case dwarf::DW_AT_call_data_value:
  case dwarf::DW_AT_call_value:
  case dwarf::DW_AT_GNU_call_site_data_value:
  case dwarf::DW_AT_GNU_call_site_value:
    if (options().getAttributeAnyLocation() && CurrentSymbol)
      processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry,
                          /*CallSiteLocation=*/true);
    break;

  default:
    break;
  }
}

LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent,
                                      DWARFDie &SkeletonDie) {
  // If the input DIE corresponds to the compile unit, it can be:
  // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty).
  // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE
  //    for the skeleton DWARF. Process both DIEs.
  const DWARFDie &DIE = SkeletonDie.isValid() ? SkeletonDie : InputDIE;
  DWARFDataExtractor DebugInfoData =
      DIE.getDwarfUnit()->getDebugInfoExtractor();
  LVOffset Offset = DIE.getOffset();

  // Reset values for the current DIE.
  CurrentLowPC = 0;
  CurrentHighPC = 0;
  CurrentOffset = Offset;
  CurrentEndOffset = 0;
  FoundLowPC = false;
  FoundHighPC = false;

  // Process supported attributes.
  if (DebugInfoData.isValidOffset(Offset)) {

    LLVM_DEBUG({
      dbgs() << "DIE: " << hexValue(Offset) << formatv(" {0}", DIE.getTag())
             << "\n";
    });

    // Create the logical view element for the current DIE.
    dwarf::Tag Tag = DIE.getTag();
    CurrentElement = createElement(Tag);
    if (!CurrentElement)
      return CurrentScope;

    CurrentElement->setTag(Tag);
    CurrentElement->setOffset(Offset);

    if (options().getAttributeAnySource() && CurrentElement->isCompileUnit())
      addCompileUnitOffset(Offset,
                           static_cast<LVScopeCompileUnit *>(CurrentElement));

    // Insert the newly created element into the element symbol table. If the
    // element is in the list, it means there are previously created elements
    // referencing this element.
    auto [It, Inserted] = ElementTable.try_emplace(Offset, CurrentElement);
    if (!Inserted) {
      // There are previous references to this element. We need to update the
      // element and all the references pointing to this element.
      LVElementEntry &Reference = ElementTable[Offset];
      Reference.Element = CurrentElement;
      // Traverse the element set and update the elements (backtracking).
      for (LVElement *Target : Reference.References)
        Target->setReference(CurrentElement);
      for (LVElement *Target : Reference.Types)
        Target->setType(CurrentElement);
      // Clear the pending elements.
      Reference.References.clear();
      Reference.Types.clear();
    }

    // Add the current element to its parent as there are attributes
    // (locations) that require the scope level.
    if (CurrentScope)
      Parent->addElement(CurrentScope);
    else if (CurrentSymbol)
      Parent->addElement(CurrentSymbol);
    else if (CurrentType)
      Parent->addElement(CurrentType);

    // Process the attributes for the given DIE.
    auto ProcessAttributes = [&](const DWARFDie &TheDIE,
                                 DWARFDataExtractor &DebugData) {
      CurrentEndOffset = Offset;
      uint32_t abbrCode = DebugData.getULEB128(&CurrentEndOffset);
      if (abbrCode) {
        if (const DWARFAbbreviationDeclaration *AbbrevDecl =
                TheDIE.getAbbreviationDeclarationPtr())
          for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
               AbbrevDecl->attributes())
            processOneAttribute(TheDIE, &CurrentEndOffset, AttrSpec);
      }
    };

    ProcessAttributes(DIE, DebugInfoData);

    // If the input DIE is for a compile unit, process its attributes in
    // the case of split DWARF, to override any common attribute values.
    if (SkeletonDie.isValid()) {
      DWARFDataExtractor DebugInfoData =
          InputDIE.getDwarfUnit()->getDebugInfoExtractor();
      LVOffset Offset = InputDIE.getOffset();
      if (DebugInfoData.isValidOffset(Offset))
        ProcessAttributes(InputDIE, DebugInfoData);
    }
  }

  if (CurrentScope) {
    if (CurrentScope->getCanHaveRanges()) {
      // If the scope has ranges, they are already added to the scope.
      // Add any collected LowPC/HighPC values.
      bool IsCompileUnit = CurrentScope->getIsCompileUnit();
      if (FoundLowPC && FoundHighPC) {
        CurrentScope->addObject(CurrentLowPC, CurrentHighPC);
        if (!IsCompileUnit) {
          // If the scope is a function, add it to the public names.
          if ((options().getAttributePublics() ||
               options().getPrintAnyLine()) &&
              CurrentScope->getIsFunction() &&
              !CurrentScope->getIsInlinedFunction())
            CompileUnit->addPublicName(CurrentScope, CurrentLowPC,
                                       CurrentHighPC);
        }
      }

      // Look for scopes with ranges and no linkage name information that
      // are referencing another scopes via DW_AT_specification. They are
      // possible candidates for a comdat scope.
      if (CurrentScope->getHasRanges() &&
          !CurrentScope->getLinkageNameIndex() &&
          CurrentScope->getHasReferenceSpecification()) {
        // Get the linkage name in order to search for a possible comdat.
        std::optional<DWARFFormValue> LinkageDIE =
            DIE.findRecursively(dwarf::DW_AT_linkage_name);
        if (LinkageDIE.has_value()) {
          StringRef Name(dwarf::toStringRef(LinkageDIE));
          if (!Name.empty())
            CurrentScope->setLinkageName(Name);
        }
      }

      // If the current scope is in the 'LinkageNames' table, update its
      // logical scope. For other scopes, always we will assume the default
      // ".text" section index.
      LVSectionIndex SectionIndex = updateSymbolTable(CurrentScope);
      if (CurrentScope->getIsComdat())
        CompileUnit->setHasComdatScopes();

      // Update section index contained ranges.
      if (SectionIndex) {
        if (!CurrentRanges.empty()) {
          for (LVAddressRange &Range : CurrentRanges)
            addSectionRange(SectionIndex, CurrentScope, Range.first,
                            Range.second > Range.first
                                ? Range.second - 1 // Make hi-pc exclusive
                                : Range.second);
          CurrentRanges.clear();
        }
        // If the scope is the CU, do not update the ranges set.
        if (FoundLowPC && FoundHighPC && !IsCompileUnit) {
          addSectionRange(SectionIndex, CurrentScope, CurrentLowPC,
                          CurrentHighPC > CurrentLowPC
                              ? CurrentHighPC - 1 // Make hi-pc exclusive
                              : CurrentHighPC);
        }
      }
    }
    // Mark member functions.
    if (Parent->getIsAggregate())
      CurrentScope->setIsMember();
  }

  // Keep track of symbols with locations.
  if (options().getAttributeAnyLocation() && CurrentSymbol &&
      CurrentSymbol->getHasLocation())
    SymbolsWithLocations.push_back(CurrentSymbol);

  // If we have template parameters, mark the parent as template.
  if (CurrentType && CurrentType->getIsTemplateParam())
    Parent->setIsTemplate();

  return CurrentScope;
}

void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent,
                                           DWARFDie &SkeletonDie) {
  // Process the current DIE.
  LVScope *Scope = processOneDie(DIE, Parent, SkeletonDie);
  if (Scope) {
    LVOffset Lower = DIE.getOffset();
    LVOffset Upper = CurrentEndOffset;
    DWARFDie DummyDie;
    // Traverse the children chain.
    DWARFDie Child = DIE.getFirstChild();
    while (Child) {
      traverseDieAndChildren(Child, Scope, DummyDie);
      Upper = Child.getOffset();
      Child = Child.getSibling();
    }
    // Calculate contributions to the debug info section.
    if (options().getPrintSizes() && Upper)
      CompileUnit->addSize(Scope, Lower, Upper);
  }
}

void LVDWARFReader::processLocationGaps() {
  if (options().getAttributeAnyLocation())
    for (LVSymbol *Symbol : SymbolsWithLocations)
      Symbol->fillLocationGaps();
}

void LVDWARFReader::createLineAndFileRecords(
    const DWARFDebugLine::LineTable *Lines) {
  if (!Lines)
    return;

  // Get the source filenames.
  if (!Lines->Prologue.FileNames.empty())
    for (const DWARFDebugLine::FileNameEntry &Entry :
         Lines->Prologue.FileNames) {
      std::string Directory;
      if (Lines->getDirectoryForEntry(Entry, Directory))
        Directory = transformPath(Directory);
      if (Directory.empty())
        Directory = std::string(CompileUnit->getCompilationDirectory());
      std::string File = transformPath(dwarf::toStringRef(Entry.Name));
      std::string String;
      raw_string_ostream(String) << Directory << "/" << File;
      CompileUnit->addFilename(String);
    }

  // In DWARF5 the file indexes start at 0;
  bool IncrementIndex = Lines->Prologue.getVersion() >= 5;

  // Get the source lines if requested by command line option.
  if (options().getPrintLines() && Lines->Rows.size())
    for (const DWARFDebugLine::Row &Row : Lines->Rows) {
      // Here we collect logical debug lines in CULines. Later on,
      // the 'processLines()' function will move each created logical line
      // to its enclosing logical scope, using the debug ranges information
      // and they will be released when its scope parent is deleted.
      LVLineDebug *Line = createLineDebug();
      CULines.push_back(Line);
      // Consider the case of WebAssembly.
      Line->setAddress(Row.Address.Address + WasmCodeSectionOffset);
      Line->setFilename(
          CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));
      Line->setLineNumber(Row.Line);
      if (Row.Discriminator)
        Line->setDiscriminator(Row.Discriminator);
      if (Row.IsStmt)
        Line->setIsNewStatement();
      if (Row.BasicBlock)
        Line->setIsBasicBlock();
      if (Row.EndSequence)
        Line->setIsEndSequence();
      if (Row.EpilogueBegin)
        Line->setIsEpilogueBegin();
      if (Row.PrologueEnd)
        Line->setIsPrologueEnd();
      LLVM_DEBUG({
        dbgs() << "Address: " << hexValue(Line->getAddress())
               << " Line: " << Line->lineNumberAsString(/*ShowZero=*/true)
               << "\n";
      });
    }
}

std::string LVDWARFReader::getRegisterName(LVSmall Opcode,
                                           ArrayRef<uint64_t> Operands) {
  // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support
  // DW_OP_regval_type. At this point we are operating on a logical view
  // item, with no access to the underlying DWARF data used by LLVM.
  // We do not support DW_OP_regval_type here.
  if (Opcode == dwarf::DW_OP_regval_type)
    return {};

  std::string string;
  raw_string_ostream Stream(string);
  DIDumpOptions DumpOpts;
  auto *MCRegInfo = MRI.get();
  auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
    if (!MCRegInfo)
      return {};
    if (std::optional<MCRegister> LLVMRegNum =
            MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
      if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))
        return StringRef(RegName);
    return {};
  };
  DumpOpts.GetNameForDWARFReg = GetRegName;
  prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, Opcode, Operands);
  return Stream.str();
}

Error LVDWARFReader::createScopes() {
  LLVM_DEBUG({
    W.startLine() << "\n";
    W.printString("File", Obj.getFileName().str());
    W.printString("Format", FileFormatName);
  });

  if (Error Err = LVReader::createScopes())
    return Err;

  // As the DwarfContext object is valid only during the scopes creation,
  // we need to create our own Target information, to be used during the
  // logical view printing, in the case of instructions being requested.
  std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(Obj);
  if (!DwarfContext)
    return createStringError(errc::invalid_argument,
                             "Could not create DWARF information: %s",
                             getFilename().str().c_str());

  if (Error Err = loadTargetInfo(Obj))
    return Err;

  // Create a mapping for virtual addresses.
  mapVirtualAddress(Obj);

  // Select the correct compile unit range, depending if we are dealing with
  // a standard or split DWARF object.
  DWARFContext::compile_unit_range CompileUnits =
      DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units()
                                         : DwarfContext->dwo_compile_units();
  for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {

    // Take into account the address byte size for a correct 'tombstone'
    // value identification.
    setTombstoneAddress(
        dwarf::computeTombstoneAddress(CU->getAddressByteSize()));

    // Deduction of index used for the line records.
    //
    // For the following test case: test.cpp
    //  void foo(void ParamPtr) { }

    // Both GCC and Clang generate DWARF-5 .debug_line layout.

    // * GCC (GNU C++17 11.3.0) - All DW_AT_decl_file use index 1.
    //
    //   .debug_info:
    //     format = DWARF32, version = 0x0005
    //     DW_TAG_compile_unit
    //       DW_AT_name	("test.cpp")
    //       DW_TAG_subprogram ("foo")
    //         DW_AT_decl_file (1)
    //         DW_TAG_formal_parameter ("ParamPtr")
    //           DW_AT_decl_file (1)
    //   .debug_line:
    //     Line table prologue: format (DWARF32), version (5)
    //     include_directories[0] = "..."
    //     file_names[0]: name ("test.cpp"), dir_index (0)
    //     file_names[1]: name ("test.cpp"), dir_index (0)

    // * Clang (14.0.6) - All DW_AT_decl_file use index 0.
    //
    //   .debug_info:
    //     format = DWARF32, version = 0x0005
    //     DW_AT_producer	("clang version 14.0.6")
    //     DW_AT_name	("test.cpp")
    //
    //     DW_TAG_subprogram ("foo")
    //       DW_AT_decl_file (0)
    //       DW_TAG_formal_parameter ("ParamPtr")
    //         DW_AT_decl_file (0)
    //   .debug_line:
    //     Line table prologue: format (DWARF32), version (5)
    //     include_directories[0] = "..."
    //     file_names[0]: name ("test.cpp"), dir_index (0)

    // From DWARFDebugLine::getFileNameByIndex documentation:
    //   In Dwarf 4, the files are 1-indexed.
    //   In Dwarf 5, the files are 0-indexed.
    // Additional discussions here:
    // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html

    // The DWARF reader is expecting the files are 1-indexed, so using
    // the .debug_line header information decide if the indexed require
    // an internal adjustment.

    // For the case of GCC (DWARF5), if the entries[0] and [1] are the
    // same, do not perform any adjustment.
    auto DeduceIncrementFileIndex = [&]() -> bool {
      if (CU->getVersion() < 5)
        // DWARF-4 or earlier -> Don't increment index.
        return false;

      if (const DWARFDebugLine::LineTable *LT =
              CU->getContext().getLineTableForUnit(CU.get())) {
        // Check if there are at least 2 entries and if they are the same.
        if (LT->hasFileAtIndex(0) && LT->hasFileAtIndex(1)) {
          const DWARFDebugLine::FileNameEntry &EntryZero =
              LT->Prologue.getFileNameEntry(0);
          const DWARFDebugLine::FileNameEntry &EntryOne =
              LT->Prologue.getFileNameEntry(1);
          // Check directory indexes.
          if (EntryZero.DirIdx != EntryOne.DirIdx)
            // DWARF-5 -> Increment index.
            return true;
          // Check filename.
          std::string FileZero;
          std::string FileOne;
          StringRef None;
          LT->getFileNameByIndex(
              0, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,
              FileZero);
          LT->getFileNameByIndex(
              1, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,
              FileOne);
          return FileZero != FileOne;
        }
      }

      // DWARF-5 -> Increment index.
      return true;
    };
    // The DWARF reader expects the indexes as 1-indexed.
    IncrementFileIndex = DeduceIncrementFileIndex();

    DWARFDie UnitDie = CU->getUnitDIE();
    SmallString<16> DWOAlternativeLocation;
    if (UnitDie) {
      std::optional<const char *> DWOFileName =
          CU->getVersion() >= 5
              ? dwarf::toString(UnitDie.find(dwarf::DW_AT_dwo_name))
              : dwarf::toString(UnitDie.find(dwarf::DW_AT_GNU_dwo_name));
      StringRef From(DWOFileName.value_or(""));
      DWOAlternativeLocation = createAlternativePath(From);
    }

    // The current CU can be a normal compile unit (standard) or a skeleton
    // compile unit (split). For both cases, the returned die, will be used
    // to create the logical scopes.
    DWARFDie CUDie = CU->getNonSkeletonUnitDIE(
        /*ExtractUnitDIEOnly=*/false,
        /*DWOAlternativeLocation=*/DWOAlternativeLocation);
    if (!CUDie.isValid())
      continue;

    // The current unit corresponds to the .dwo file. We need to get the
    // skeleton unit and query for any ranges that will enclose any ranges
    // in the non-skeleton unit.
    DWARFDie DummyDie;
    DWARFDie SkeletonDie =
        CUDie.getDwarfUnit()->isDWOUnit() ? CU->getUnitDIE(false) : DummyDie;
    // Disable the ranges processing if we have just a single .dwo object,
    // as any DW_AT_ranges will access not available range information.
    RangesDataAvailable =
        (!CUDie.getDwarfUnit()->isDWOUnit() ||
         (SkeletonDie.isValid() ? !SkeletonDie.getDwarfUnit()->isDWOUnit()
                                : true));

    traverseDieAndChildren(CUDie, Root, SkeletonDie);

    createLineAndFileRecords(DwarfContext->getLineTableForUnit(CU.get()));
    if (Error Err = createInstructions())
      return Err;

    // Process the compilation unit, as there are cases where enclosed
    // functions have the same ranges values. Insert the compilation unit
    // ranges at the end, to allow enclosing ranges to be first in the list.
    LVSectionIndex SectionIndex = getSectionIndex(CompileUnit);
    addSectionRange(SectionIndex, CompileUnit);
    LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
    ScopesWithRanges->sort();

    processLines(&CULines, SectionIndex);
    processLocationGaps();

    // These are per compile unit.
    ScopesWithRanges->clear();
    SymbolsWithLocations.clear();
    CULines.clear();
  }

  return Error::success();
}

// Get the location information for the associated attribute.
void LVDWARFReader::processLocationList(dwarf::Attribute Attr,
                                        const DWARFFormValue &FormValue,
                                        const DWARFDie &Die,
                                        uint64_t OffsetOnEntry,
                                        bool CallSiteLocation) {

  auto ProcessLocationExpression = [&](const DWARFExpression &Expression) {
    for (const DWARFExpression::Operation &Op : Expression)
      CurrentSymbol->addLocationOperands(Op.getCode(), Op.getRawOperands());
  };

  DWARFUnit *U = Die.getDwarfUnit();
  DWARFContext &DwarfContext = U->getContext();
  bool IsLittleEndian = DwarfContext.isLittleEndian();
  if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
      (DWARFAttribute::mayHaveLocationExpr(Attr) &&
       FormValue.isFormClass(DWARFFormValue::FC_Exprloc))) {
    ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
    DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
                       IsLittleEndian, 0);
    DWARFExpression Expression(Data, U->getAddressByteSize(),
                               U->getFormParams().Format);

    // Add location and operation entries.
    CurrentSymbol->addLocation(Attr, /*LowPC=*/0, /*HighPC=*/-1,
                               /*SectionOffset=*/0, OffsetOnEntry,
                               CallSiteLocation);
    ProcessLocationExpression(Expression);
    return;
  }

  if (DWARFAttribute::mayHaveLocationList(Attr) &&
      FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
    uint64_t Offset = *FormValue.getAsSectionOffset();
    if (FormValue.getForm() == dwarf::DW_FORM_loclistx) {
      std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(Offset);
      if (!LoclistOffset)
        return;
      Offset = *LoclistOffset;
    }
    uint64_t BaseAddr = 0;
    if (std::optional<SectionedAddress> BA = U->getBaseAddress())
      BaseAddr = BA->Address;
    LVAddress LowPC = 0;
    LVAddress HighPC = 0;

    auto ProcessLocationEntry = [&](const DWARFLocationEntry &Entry) {
      if (Entry.Kind == dwarf::DW_LLE_base_address) {
        BaseAddr = Entry.Value0;
        return;
      }
      if (Entry.Kind == dwarf::DW_LLE_offset_pair) {
        LowPC = BaseAddr + Entry.Value0;
        HighPC = BaseAddr + Entry.Value1;
        DWARFAddressRange Range{LowPC, HighPC, Entry.SectionIndex};
        if (Range.SectionIndex == SectionedAddress::UndefSection)
          Range.SectionIndex = Entry.SectionIndex;
        DWARFLocationExpression Loc{Range, Entry.Loc};
        DWARFDataExtractor Data(Loc.Expr, IsLittleEndian,
                                U->getAddressByteSize());
        DWARFExpression Expression(Data, U->getAddressByteSize());

        // Store the real upper limit for the address range.
        if (UpdateHighAddress && HighPC > 0)
          --HighPC;
        // Add location and operation entries.
        CurrentSymbol->addLocation(Attr, LowPC, HighPC, Offset, OffsetOnEntry,
                                   CallSiteLocation);
        ProcessLocationExpression(Expression);
      }
    };
    Error E = U->getLocationTable().visitLocationList(
        &Offset, [&](const DWARFLocationEntry &E) {
          ProcessLocationEntry(E);
          return true;
        });
    if (E)
      consumeError(std::move(E));
  }
}

void LVDWARFReader::processLocationMember(dwarf::Attribute Attr,
                                          const DWARFFormValue &FormValue,
                                          const DWARFDie &Die,
                                          uint64_t OffsetOnEntry) {
  // Check if the value is an integer constant.
  if (FormValue.isFormClass(DWARFFormValue::FC_Constant))
    // Add a record to hold a constant as location.
    CurrentSymbol->addLocationConstant(Attr, *FormValue.getAsUnsignedConstant(),
                                       OffsetOnEntry);
  else
    // This is a location description, or a reference to one.
    processLocationList(Attr, FormValue, Die, OffsetOnEntry);
}

// Update the current element with the reference.
void LVDWARFReader::updateReference(dwarf::Attribute Attr,
                                    const DWARFFormValue &FormValue) {
  // FIXME: We are assuming that at most one Reference (DW_AT_specification,
  // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type)
  // appear in any single DIE, but this may not be true.
  uint64_t Offset;
  if (std::optional<uint64_t> Off = FormValue.getAsRelativeReference())
    Offset = FormValue.getUnit()->getOffset() + *Off;
  else if (Off = FormValue.getAsDebugInfoReference(); Off)
    Offset = *Off;
  else
    llvm_unreachable("Unsupported reference type");

  // Get target for the given reference, if already created.
  LVElement *Target = getElementForOffset(
      Offset, CurrentElement,
      /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type);
  // Check if we are dealing with cross CU references.
  if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) {
    if (Target) {
      // The global reference is ready. Mark it as global.
      Target->setIsGlobalReference();
      // Remove global reference from the unseen list.
      removeGlobalOffset(Offset);
    } else
      // Record the unseen cross CU reference.
      addGlobalOffset(Offset);
  }

  // At this point, 'Target' can be null, in the case of the target element
  // not being seen. But the correct bit is set, to indicate that the target
  // is being referenced by (abstract_origin, extension, specification) or
  // (import, type).
  // We must differentiate between the kind of reference. This is needed to
  // complete inlined function instances with dropped abstract references,
  // in order to facilitate a logical comparison.
  switch (Attr) {
  case dwarf::DW_AT_abstract_origin:
  case dwarf::DW_AT_call_origin:
    CurrentElement->setReference(Target);
    CurrentElement->setHasReferenceAbstract();
    break;
  case dwarf::DW_AT_extension:
    CurrentElement->setReference(Target);
    CurrentElement->setHasReferenceExtension();
    break;
  case dwarf::DW_AT_specification:
    CurrentElement->setReference(Target);
    CurrentElement->setHasReferenceSpecification();
    break;
  case dwarf::DW_AT_import:
  case dwarf::DW_AT_type:
    CurrentElement->setType(Target);
    break;
  default:
    break;
  }
}

// Get an element given the DIE offset.
LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset,
                                              LVElement *Element, bool IsType) {
  // Update the element and all the references pointing to this element.
  LVElementEntry &Entry = ElementTable[Offset];
  if (!Entry.Element) {
    if (IsType)
      Entry.Types.insert(Element);
    else
      Entry.References.insert(Element);
  }
  return Entry.Element;
}

Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) {
  // Detect the architecture from the object file. We usually don't need OS
  // info to lookup a target and create register info.
  Triple TT = Obj.makeTriple();

  // Features to be passed to target/subtarget
  Expected<SubtargetFeatures> Features = Obj.getFeatures();
  SubtargetFeatures FeaturesValue;
  if (!Features) {
    consumeError(Features.takeError());
    FeaturesValue = SubtargetFeatures();
  }
  FeaturesValue = *Features;

  StringRef CPU;
  if (auto OptCPU = Obj.tryGetCPUName())
    CPU = *OptCPU;

  return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU);
}

void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) {
  for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) {
    const SymbolRef &Symbol = *Iter;

    Expected<SymbolRef::Type> TypeOrErr = Symbol.getType();
    if (!TypeOrErr) {
      consumeError(TypeOrErr.takeError());
      continue;
    }

    // Process only symbols that represent a function.
    SymbolRef::Type Type = *TypeOrErr;
    if (Type != SymbolRef::ST_Function)
      continue;

    // In the case of a Mach-O STAB symbol, get its section only if
    // the STAB symbol's section field refers to a valid section index.
    // Otherwise the symbol may error trying to load a section that
    // does not exist.
    const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);
    bool IsSTAB = false;
    if (MachO) {
      DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
      uint8_t NType =
          (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
                            : MachO->getSymbolTableEntry(SymDRI).n_type);
      if (NType & MachO::N_STAB)
        IsSTAB = true;
    }

    Expected<section_iterator> IterOrErr = Symbol.getSection();
    if (!IterOrErr) {
      consumeError(IterOrErr.takeError());
      continue;
    }
    section_iterator Section = IsSTAB ? Obj.section_end() : *IterOrErr;
    if (Section == Obj.section_end())
      continue;

    // Get the symbol value.
    Expected<uint64_t> AddressOrErr = Symbol.getAddress();
    if (!AddressOrErr) {
      consumeError(AddressOrErr.takeError());
      continue;
    }
    uint64_t Address = *AddressOrErr;

    // Get symbol name.
    StringRef Name;
    Expected<StringRef> NameOrErr = Symbol.getName();
    if (!NameOrErr) {
      consumeError(NameOrErr.takeError());
      continue;
    }
    Name = *NameOrErr;

    // Check if the symbol is Comdat.
    Expected<uint32_t> FlagsOrErr = Symbol.getFlags();
    if (!FlagsOrErr) {
      consumeError(FlagsOrErr.takeError());
      continue;
    }
    uint32_t Flags = *FlagsOrErr;

    // Mark the symbol as 'comdat' in any of the following cases:
    // - Symbol has the SF_Weak flag or
    // - Symbol section index different from the DotTextSectionIndex.
    LVSectionIndex SectionIndex = Section->getIndex();
    bool IsComdat =
        (Flags & SymbolRef::SF_Weak) || (SectionIndex != DotTextSectionIndex);

    // Record the symbol name (linkage) and its loading address.
    addToSymbolTable(Name, Address, SectionIndex, IsComdat);
  }
}

void LVDWARFReader::sortScopes() { Root->sort(); }

void LVDWARFReader::print(raw_ostream &OS) const {
  OS << "LVType\n";
  LLVM_DEBUG(dbgs() << "CreateReaders\n");
}
