//===-- LVELFReader.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 LVELFReader class.
// It supports ELF and Mach-O formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/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/Error.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 "ElfReader"

LVElement *LVELFReader::createElement(dwarf::Tag Tag) {
  CurrentScope = nullptr;
  CurrentSymbol = nullptr;
  CurrentType = nullptr;
  CurrentRanges.clear();

  if (!options().getPrintSymbols()) {
    switch (Tag) {
    // As the command line options did not specify a request to print
    // logical symbols (--print=symbols or --print=all or --print=elements),
    // skip its creation.
    case dwarf::DW_TAG_formal_parameter:
    case dwarf::DW_TAG_unspecified_parameters:
    case dwarf::DW_TAG_member:
    case dwarf::DW_TAG_variable:
    case dwarf::DW_TAG_inheritance:
    case dwarf::DW_TAG_constant:
    case dwarf::DW_TAG_call_site_parameter:
    case dwarf::DW_TAG_GNU_call_site_parameter:
      return nullptr;
    default:
      break;
    }
  }

  switch (Tag) {
  // Types.
  case dwarf::DW_TAG_base_type:
    CurrentType = new LVType();
    CurrentType->setIsBase();
    if (options().getAttributeBase())
      CurrentType->setIncludeInPrint();
    return CurrentType;
  case dwarf::DW_TAG_const_type:
    CurrentType = new LVType();
    CurrentType->setIsConst();
    CurrentType->setName("const");
    return CurrentType;
  case dwarf::DW_TAG_enumerator:
    CurrentType = new LVTypeEnumerator();
    return CurrentType;
  case dwarf::DW_TAG_imported_declaration:
    CurrentType = new LVTypeImport();
    CurrentType->setIsImportDeclaration();
    return CurrentType;
  case dwarf::DW_TAG_imported_module:
    CurrentType = new LVTypeImport();
    CurrentType->setIsImportModule();
    return CurrentType;
  case dwarf::DW_TAG_pointer_type:
    CurrentType = new LVType();
    CurrentType->setIsPointer();
    CurrentType->setName("*");
    return CurrentType;
  case dwarf::DW_TAG_ptr_to_member_type:
    CurrentType = new LVType();
    CurrentType->setIsPointerMember();
    CurrentType->setName("*");
    return CurrentType;
  case dwarf::DW_TAG_reference_type:
    CurrentType = new LVType();
    CurrentType->setIsReference();
    CurrentType->setName("&");
    return CurrentType;
  case dwarf::DW_TAG_restrict_type:
    CurrentType = new LVType();
    CurrentType->setIsRestrict();
    CurrentType->setName("restrict");
    return CurrentType;
  case dwarf::DW_TAG_rvalue_reference_type:
    CurrentType = new LVType();
    CurrentType->setIsRvalueReference();
    CurrentType->setName("&&");
    return CurrentType;
  case dwarf::DW_TAG_subrange_type:
    CurrentType = new LVTypeSubrange();
    return CurrentType;
  case dwarf::DW_TAG_template_value_parameter:
    CurrentType = new LVTypeParam();
    CurrentType->setIsTemplateValueParam();
    return CurrentType;
  case dwarf::DW_TAG_template_type_parameter:
    CurrentType = new LVTypeParam();
    CurrentType->setIsTemplateTypeParam();
    return CurrentType;
  case dwarf::DW_TAG_GNU_template_template_param:
    CurrentType = new LVTypeParam();
    CurrentType->setIsTemplateTemplateParam();
    return CurrentType;
  case dwarf::DW_TAG_typedef:
    CurrentType = new LVTypeDefinition();
    return CurrentType;
  case dwarf::DW_TAG_unspecified_type:
    CurrentType = new LVType();
    CurrentType->setIsUnspecified();
    return CurrentType;
  case dwarf::DW_TAG_volatile_type:
    CurrentType = new LVType();
    CurrentType->setIsVolatile();
    CurrentType->setName("volatile");
    return CurrentType;

  // Symbols.
  case dwarf::DW_TAG_formal_parameter:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsParameter();
    return CurrentSymbol;
  case dwarf::DW_TAG_unspecified_parameters:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsUnspecified();
    CurrentSymbol->setName("...");
    return CurrentSymbol;
  case dwarf::DW_TAG_member:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsMember();
    return CurrentSymbol;
  case dwarf::DW_TAG_variable:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsVariable();
    return CurrentSymbol;
  case dwarf::DW_TAG_inheritance:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsInheritance();
    return CurrentSymbol;
  case dwarf::DW_TAG_call_site_parameter:
  case dwarf::DW_TAG_GNU_call_site_parameter:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsCallSiteParameter();
    return CurrentSymbol;
  case dwarf::DW_TAG_constant:
    CurrentSymbol = new LVSymbol();
    CurrentSymbol->setIsConstant();
    return CurrentSymbol;

  // Scopes.
  case dwarf::DW_TAG_catch_block:
    CurrentScope = new LVScope();
    CurrentScope->setIsCatchBlock();
    return CurrentScope;
  case dwarf::DW_TAG_lexical_block:
    CurrentScope = new LVScope();
    CurrentScope->setIsLexicalBlock();
    return CurrentScope;
  case dwarf::DW_TAG_try_block:
    CurrentScope = new LVScope();
    CurrentScope->setIsTryBlock();
    return CurrentScope;
  case dwarf::DW_TAG_compile_unit:
  case dwarf::DW_TAG_skeleton_unit:
    CurrentScope = new LVScopeCompileUnit();
    CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope);
    return CurrentScope;
  case dwarf::DW_TAG_inlined_subroutine:
    CurrentScope = new LVScopeFunctionInlined();
    return CurrentScope;
  case dwarf::DW_TAG_namespace:
    CurrentScope = new LVScopeNamespace();
    return CurrentScope;
  case dwarf::DW_TAG_template_alias:
    CurrentScope = new LVScopeAlias();
    return CurrentScope;
  case dwarf::DW_TAG_array_type:
    CurrentScope = new LVScopeArray();
    return CurrentScope;
  case dwarf::DW_TAG_call_site:
  case dwarf::DW_TAG_GNU_call_site:
    CurrentScope = new LVScopeFunction();
    CurrentScope->setIsCallSite();
    return CurrentScope;
  case dwarf::DW_TAG_entry_point:
    CurrentScope = new LVScopeFunction();
    CurrentScope->setIsEntryPoint();
    return CurrentScope;
  case dwarf::DW_TAG_subprogram:
    CurrentScope = new LVScopeFunction();
    CurrentScope->setIsSubprogram();
    return CurrentScope;
  case dwarf::DW_TAG_subroutine_type:
    CurrentScope = new LVScopeFunctionType();
    return CurrentScope;
  case dwarf::DW_TAG_label:
    CurrentScope = new LVScopeFunction();
    CurrentScope->setIsLabel();
    return CurrentScope;
  case dwarf::DW_TAG_class_type:
    CurrentScope = new LVScopeAggregate();
    CurrentScope->setIsClass();
    return CurrentScope;
  case dwarf::DW_TAG_structure_type:
    CurrentScope = new LVScopeAggregate();
    CurrentScope->setIsStructure();
    return CurrentScope;
  case dwarf::DW_TAG_union_type:
    CurrentScope = new LVScopeAggregate();
    CurrentScope->setIsUnion();
    return CurrentScope;
  case dwarf::DW_TAG_enumeration_type:
    CurrentScope = new LVScopeEnumeration();
    return CurrentScope;
  case dwarf::DW_TAG_GNU_formal_parameter_pack:
    CurrentScope = new LVScopeFormalPack();
    return CurrentScope;
  case dwarf::DW_TAG_GNU_template_parameter_pack:
    CurrentScope = new LVScopeTemplatePack();
    return CurrentScope;
  default:
    // Collect TAGs not implemented.
    if (options().getInternalTag() && Tag)
      CompileUnit->addDebugTag(Tag, CurrentOffset);
    break;
  }
  return nullptr;
}

void LVELFReader::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 {
    return AttrSpec.isImplicitConst() ? AttrSpec.getImplicitConstValue()
                                      : *FormValue.getAsUnsignedConstant();
  };

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

  auto GetBoundValue = [](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();
    default:
      return 0;
    }
  };

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

  switch (AttrSpec.Attr) {
  case dwarf::DW_AT_accessibility:
    CurrentElement->setAccessibilityCode(*FormValue.getAsUnsignedConstant());
    break;
  case dwarf::DW_AT_artificial:
    CurrentElement->setIsArtificial();
    break;
  case dwarf::DW_AT_bit_size:
    CurrentElement->setBitSize(*FormValue.getAsUnsignedConstant());
    break;
  case dwarf::DW_AT_call_file:
    CurrentElement->setCallFilenameIndex(GetAsUnsignedConstant());
    break;
  case dwarf::DW_AT_call_line:
    CurrentElement->setCallLineNumber(IncrementFileIndex
                                          ? GetAsUnsignedConstant() + 1
                                          : 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(*FormValue.getAsUnsignedConstant(), 2));
    } else
      CurrentElement->setValue(dwarf::toStringRef(FormValue));
    break;
  case dwarf::DW_AT_count:
    CurrentElement->setCount(*FormValue.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(*FormValue.getAsUnsignedConstant());
    break;
  case dwarf::DW_AT_inline:
    CurrentElement->setInlineCode(*FormValue.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_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_upper_bound:
    CurrentElement->setUpperBound(GetBoundValue(FormValue));
    break;
  case dwarf::DW_AT_virtuality:
    CurrentElement->setVirtualityCode(*FormValue.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 == MaxAddress)
          CurrentElement->setIsDiscarded();
        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.
        CurrentHighPC = CurrentLowPC + *Offset;
      // Store the real upper limit for the address range.
      if (UpdateHighAddress && CurrentHighPC > 0)
        --CurrentHighPC;
      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)
          continue;
        // Store the real upper limit for the address range.
        if (UpdateHighAddress && Range.HighPC > 0)
          --Range.HighPC;
        // 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 *LVELFReader::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.
    if (ElementTable.find(Offset) == ElementTable.end()) {
      // No previous references to this offset.
      ElementTable.emplace(
          std::piecewise_construct, std::forward_as_tuple(Offset),
          std::forward_as_tuple(CurrentElement, LVElementSet()));
    } else {
      // 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.first = CurrentElement;
      // Traverse the element set and update the elements (backtracking).
      // Using the bit associated with 'type' or 'reference' allows us to set
      // the correct target.
      for (LVElement *Target : Reference.second)
        Target->getHasReference() ? Target->setReference(CurrentElement)
                                  : Target->setType(CurrentElement);
      // Clear the pending elements.
      Reference.second.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())
          if (AbbrevDecl)
            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);
          CurrentRanges.clear();
        }
        // If the scope is the CU, do not update the ranges set.
        if (FoundLowPC && FoundHighPC && !IsCompileUnit) {
          addSectionRange(SectionIndex, CurrentScope, CurrentLowPC,
                          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 LVELFReader::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 LVELFReader::processLocationGaps() {
  if (options().getAttributeAnyLocation())
    for (LVSymbol *Symbol : SymbolsWithLocations)
      Symbol->fillLocationGaps();
}

void LVELFReader::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 = new LVLineDebug();
      CULines.push_back(Line);
      Line->setAddress(Row.Address.Address);
      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 LVELFReader::getRegisterName(LVSmall Opcode, uint64_t Operands[2]) {
  // 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<unsigned> LLVMRegNum =
            MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
      if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))
        return StringRef(RegName);
    return {};
  };
  DumpOpts.GetNameForDWARFReg = GetRegName;
  DWARFExpression::prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts,
                                         Opcode, Operands);
  return Stream.str();
}

Error LVELFReader::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) {

    // 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 ELF 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.compare(FileOne);
        }
      }

      // DWARF-5 -> Increment index.
      return true;
    };
    // The ELF 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 LVELFReader::processLocationList(dwarf::Attribute Attr,
                                      const DWARFFormValue &FormValue,
                                      const DWARFDie &Die,
                                      uint64_t OffsetOnEntry,
                                      bool CallSiteLocation) {

  auto ProcessLocationExpression = [&](const DWARFExpression &Expression) {
    // DW_OP_const_type is variable-length and has 3
    // operands. DWARFExpression thus far only supports 2.
    uint64_t Operands[2] = {0};
    for (const DWARFExpression::Operation &Op : Expression) {
      DWARFExpression::Operation::Description Description = Op.getDescription();
      for (unsigned Operand = 0; Operand < 2; ++Operand) {
        if (Description.Op[Operand] == DWARFExpression::Operation::SizeNA)
          break;
        Operands[Operand] = Op.getRawOperand(Operand);
      }
      CurrentSymbol->addLocationOperands(Op.getCode(), Operands[0],
                                         Operands[1]);
    }
  };

  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 LVELFReader::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 a location description, or a reference to one.
    processLocationList(Attr, FormValue, Die, OffsetOnEntry);
}

// Update the current element with the reference.
void LVELFReader::updateReference(dwarf::Attribute Attr,
                                  const DWARFFormValue &FormValue) {
  // We are assuming that DW_AT_specification, DW_AT_abstract_origin,
  // DW_AT_type and DW_AT_extension do not appear at the same time
  // in the same DIE.
  uint64_t Reference = *FormValue.getAsReference();
  // Get target for the given reference, if already created.
  LVElement *Target = getElementForOffset(Reference, CurrentElement);
  // 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(Reference);
    } else
      // Record the unseen cross CU reference.
      addGlobalOffset(Reference);
  }

  // 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 *LVELFReader::getElementForOffset(LVOffset Offset,
                                            LVElement *Element) {
  LVElement *Target = nullptr;
  // Search offset in the cross references.
  LVElementReference::iterator Iter = ElementTable.find(Offset);
  if (Iter == ElementTable.end())
    // Reference to an unseen element.
    ElementTable.emplace(std::piecewise_construct,
                         std::forward_as_tuple(Offset),
                         std::forward_as_tuple(nullptr, LVElementSet{Element}));
  else {
    // There are previous references to this element. We need to update the
    // element and all the references pointing to this element.
    LVElementEntry &Reference = Iter->second;
    Target = Reference.first;
    if (!Target)
      // Add the element to the set.
      Reference.second.insert(Element);
  }
  return Target;
}

Error LVELFReader::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;
  TT.setArch(Triple::ArchType(Obj.getArch()));
  TT.setVendor(Triple::UnknownVendor);
  TT.setOS(Triple::UnknownOS);

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

void LVELFReader::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 LVELFReader::sortScopes() { Root->sort(); }

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