//===-- SymbolFileDWARF.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
//
//===----------------------------------------------------------------------===//

#include "SymbolFileDWARF.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Threading.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/Timer.h"

#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"

#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"

#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"

#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileWasm.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"

#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"

#include "AppleDWARFIndex.h"
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugMacro.h"
#include "DWARFDeclContext.h"
#include "DWARFFormValue.h"
#include "DWARFTypeUnit.h"
#include "DWARFUnit.h"
#include "DebugNamesDWARFIndex.h"
#include "LogChannelDWARF.h"
#include "ManualDWARFIndex.h"
#include "SymbolFileDWARFDebugMap.h"
#include "SymbolFileDWARFDwo.h"
#include "lldb/lldb-private-enumerations.h"

#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"

#include <algorithm>
#include <map>
#include <memory>
#include <optional>

#include <cctype>
#include <cstring>

//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN

#ifdef ENABLE_DEBUG_PRINTF
#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::plugin::dwarf;
using namespace llvm::dwarf;

LLDB_PLUGIN_DEFINE(SymbolFileDWARF)

char SymbolFileDWARF::ID;

namespace {

#define LLDB_PROPERTIES_symbolfiledwarf
#include "SymbolFileDWARFProperties.inc"

enum {
#define LLDB_PROPERTIES_symbolfiledwarf
#include "SymbolFileDWARFPropertiesEnum.inc"
};

class PluginProperties : public Properties {
public:
  static llvm::StringRef GetSettingName() {
    return SymbolFileDWARF::GetPluginNameStatic();
  }

  PluginProperties() {
    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
    m_collection_sp->Initialize(g_symbolfiledwarf_properties_def);
  }

  bool IgnoreFileIndexes() const {
    return GetPropertyAtIndexAs<bool>(ePropertyIgnoreIndexes, false);
  }
};

} // namespace

bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
  return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
         Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
}

static PluginProperties &GetGlobalPluginProperties() {
  static PluginProperties g_settings;
  return g_settings;
}

static const llvm::DWARFDebugLine::LineTable *
ParseLLVMLineTable(DWARFContext &context, llvm::DWARFDebugLine &line,
                   dw_offset_t line_offset, dw_offset_t unit_offset) {
  Log *log = GetLog(DWARFLog::DebugInfo);

  llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVMDWARF();
  llvm::DWARFContext &ctx = context.GetAsLLVM();
  llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table =
      line.getOrParseLineTable(
          data, line_offset, ctx, nullptr, [&](llvm::Error e) {
            LLDB_LOG_ERROR(
                log, std::move(e),
                "SymbolFileDWARF::ParseLineTable failed to parse: {0}");
          });

  if (!line_table) {
    LLDB_LOG_ERROR(log, line_table.takeError(),
                   "SymbolFileDWARF::ParseLineTable failed to parse: {0}");
    return nullptr;
  }
  return *line_table;
}

static bool ParseLLVMLineTablePrologue(DWARFContext &context,
                                       llvm::DWARFDebugLine::Prologue &prologue,
                                       dw_offset_t line_offset,
                                       dw_offset_t unit_offset) {
  Log *log = GetLog(DWARFLog::DebugInfo);
  bool success = true;
  llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVMDWARF();
  llvm::DWARFContext &ctx = context.GetAsLLVM();
  uint64_t offset = line_offset;
  llvm::Error error = prologue.parse(
      data, &offset,
      [&](llvm::Error e) {
        success = false;
        LLDB_LOG_ERROR(log, std::move(e),
                       "SymbolFileDWARF::ParseSupportFiles failed to parse "
                       "line table prologue: {0}");
      },
      ctx, nullptr);
  if (error) {
    LLDB_LOG_ERROR(log, std::move(error),
                   "SymbolFileDWARF::ParseSupportFiles failed to parse line "
                   "table prologue: {0}");
    return false;
  }
  return success;
}

static std::optional<std::string>
GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,
               llvm::StringRef compile_dir, FileSpec::Style style) {
  // Try to get an absolute path first.
  std::string abs_path;
  auto absolute = llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
  if (prologue.getFileNameByIndex(idx, compile_dir, absolute, abs_path, style))
    return std::move(abs_path);

  // Otherwise ask for a relative path.
  std::string rel_path;
  auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::RawValue;
  if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style))
    return {};
  return std::move(rel_path);
}

static void ParseSupportFilesFromPrologue(
    SupportFileList &support_files, const lldb::ModuleSP &module,
    const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style,
    llvm::StringRef compile_dir = {}) {
  // Handle the case where there are no files first to avoid having to special
  // case this later.
  if (prologue.FileNames.empty())
    return;

  // Before DWARF v5, the line table indexes were one based.
  const bool is_one_based = prologue.getVersion() < 5;
  const size_t file_names = prologue.FileNames.size();
  const size_t first_file_idx = is_one_based ? 1 : 0;
  const size_t last_file_idx = is_one_based ? file_names : file_names - 1;

  // Add a dummy entry to ensure the support file list indices match those we
  // get from the debug info and line tables.
  if (is_one_based)
    support_files.Append(FileSpec());

  for (size_t idx = first_file_idx; idx <= last_file_idx; ++idx) {
    std::string remapped_file;
    if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) {
      auto entry = prologue.getFileNameEntry(idx);
      auto source = entry.Source.getAsCString();
      if (!source)
        consumeError(source.takeError());
      else {
        llvm::StringRef source_ref(*source);
        if (!source_ref.empty()) {
          /// Wrap a path for an in-DWARF source file. Lazily write it
          /// to disk when Materialize() is called.
          struct LazyDWARFSourceFile : public SupportFile {
            LazyDWARFSourceFile(const FileSpec &fs, llvm::StringRef source,
                                FileSpec::Style style)
                : SupportFile(fs), source(source), style(style) {}
            FileSpec tmp_file;
            /// The file contents buffer.
            llvm::StringRef source;
            /// Deletes the temporary file at the end.
            std::unique_ptr<llvm::FileRemover> remover;
            FileSpec::Style style;

            /// Write the file contents to a temporary file.
            const FileSpec &Materialize() override {
              if (tmp_file)
                return tmp_file;
              llvm::SmallString<0> name;
              int fd;
              auto orig_name = m_file_spec.GetFilename().GetStringRef();
              auto ec = llvm::sys::fs::createTemporaryFile(
                  "", llvm::sys::path::filename(orig_name, style), fd, name);
              if (ec || fd <= 0) {
                LLDB_LOG(GetLog(DWARFLog::DebugInfo),
                         "Could not create temporary file");
                return tmp_file;
              }
              remover = std::make_unique<llvm::FileRemover>(name);
              NativeFile file(fd, File::eOpenOptionWriteOnly, true);
              size_t num_bytes = source.size();
              file.Write(source.data(), num_bytes);
              tmp_file.SetPath(name);
              return tmp_file;
            }
          };
          support_files.Append(std::make_unique<LazyDWARFSourceFile>(
              FileSpec(*file_path), *source, style));
          continue;
        }
      }
      if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path)))
        remapped_file = *remapped;
      else
        remapped_file = std::move(*file_path);
    }

    Checksum checksum;
    if (prologue.ContentTypes.HasMD5) {
      const llvm::DWARFDebugLine::FileNameEntry &file_name_entry =
          prologue.getFileNameEntry(idx);
      checksum = file_name_entry.Checksum;
    }

    // Unconditionally add an entry, so the indices match up.
    support_files.EmplaceBack(FileSpec(remapped_file, style), checksum);
  }
}

void SymbolFileDWARF::Initialize() {
  LogChannelDWARF::Initialize();
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInitialize);
  SymbolFileDWARFDebugMap::Initialize();
}

void SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) {
  if (!PluginManager::GetSettingForSymbolFilePlugin(
          debugger, PluginProperties::GetSettingName())) {
    const bool is_global_setting = true;
    PluginManager::CreateSettingForSymbolFilePlugin(
        debugger, GetGlobalPluginProperties().GetValueProperties(),
        "Properties for the dwarf symbol-file plug-in.", is_global_setting);
  }
}

void SymbolFileDWARF::Terminate() {
  SymbolFileDWARFDebugMap::Terminate();
  PluginManager::UnregisterPlugin(CreateInstance);
  LogChannelDWARF::Terminate();
}

llvm::StringRef SymbolFileDWARF::GetPluginDescriptionStatic() {
  return "DWARF and DWARF3 debug symbol file reader.";
}

SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) {
  if (objfile_sp->GetArchitecture().GetTriple().isWasm())
    return new SymbolFileWasm(std::move(objfile_sp),
                              /*dwo_section_list*/ nullptr);
  return new SymbolFileDWARF(std::move(objfile_sp),
                             /*dwo_section_list*/ nullptr);
}

TypeList &SymbolFileDWARF::GetTypeList() {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
    return debug_map_symfile->GetTypeList();
  return SymbolFileCommon::GetTypeList();
}
void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
                               dw_offset_t max_die_offset, uint32_t type_mask,
                               TypeSet &type_set) {
  if (die) {
    const dw_offset_t die_offset = die.GetOffset();

    if (die_offset >= max_die_offset)
      return;

    if (die_offset >= min_die_offset) {
      const dw_tag_t tag = die.Tag();

      bool add_type = false;

      switch (tag) {
      case DW_TAG_array_type:
        add_type = (type_mask & eTypeClassArray) != 0;
        break;
      case DW_TAG_unspecified_type:
      case DW_TAG_base_type:
        add_type = (type_mask & eTypeClassBuiltin) != 0;
        break;
      case DW_TAG_class_type:
        add_type = (type_mask & eTypeClassClass) != 0;
        break;
      case DW_TAG_structure_type:
        add_type = (type_mask & eTypeClassStruct) != 0;
        break;
      case DW_TAG_union_type:
        add_type = (type_mask & eTypeClassUnion) != 0;
        break;
      case DW_TAG_enumeration_type:
        add_type = (type_mask & eTypeClassEnumeration) != 0;
        break;
      case DW_TAG_subroutine_type:
      case DW_TAG_subprogram:
      case DW_TAG_inlined_subroutine:
        add_type = (type_mask & eTypeClassFunction) != 0;
        break;
      case DW_TAG_pointer_type:
        add_type = (type_mask & eTypeClassPointer) != 0;
        break;
      case DW_TAG_rvalue_reference_type:
      case DW_TAG_reference_type:
        add_type = (type_mask & eTypeClassReference) != 0;
        break;
      case DW_TAG_typedef:
        add_type = (type_mask & eTypeClassTypedef) != 0;
        break;
      case DW_TAG_ptr_to_member_type:
        add_type = (type_mask & eTypeClassMemberPointer) != 0;
        break;
      default:
        break;
      }

      if (add_type) {
        const bool assert_not_being_parsed = true;
        Type *type = ResolveTypeUID(die, assert_not_being_parsed);
        if (type)
          type_set.insert(type);
      }
    }

    for (DWARFDIE child_die : die.children()) {
      GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set);
    }
  }
}

void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope,
                               TypeClass type_mask, TypeList &type_list)

{
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  TypeSet type_set;

  CompileUnit *comp_unit = nullptr;
  if (sc_scope)
    comp_unit = sc_scope->CalculateSymbolContextCompileUnit();

  const auto &get = [&](DWARFUnit *unit) {
    if (!unit)
      return;
    unit = &unit->GetNonSkeletonUnit();
    GetTypes(unit->DIE(), unit->GetOffset(), unit->GetNextUnitOffset(),
             type_mask, type_set);
  };
  if (comp_unit) {
    get(GetDWARFCompileUnit(comp_unit));
  } else {
    DWARFDebugInfo &info = DebugInfo();
    const size_t num_cus = info.GetNumUnits();
    for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx)
      get(info.GetUnitAtIndex(cu_idx));
  }

  std::set<CompilerType> compiler_type_set;
  for (Type *type : type_set) {
    CompilerType compiler_type = type->GetForwardCompilerType();
    if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) {
      compiler_type_set.insert(compiler_type);
      type_list.Insert(type->shared_from_this());
    }
  }
}

// Gets the first parent that is a lexical block, function or inlined
// subroutine, or compile unit.
DWARFDIE
SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
  DWARFDIE die;
  for (die = child_die.GetParent(); die; die = die.GetParent()) {
    dw_tag_t tag = die.Tag();

    switch (tag) {
    case DW_TAG_compile_unit:
    case DW_TAG_partial_unit:
    case DW_TAG_subprogram:
    case DW_TAG_inlined_subroutine:
    case DW_TAG_lexical_block:
      return die;
    default:
      break;
    }
  }
  return DWARFDIE();
}

SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp,
                                 SectionList *dwo_section_list)
    : SymbolFileCommon(std::move(objfile_sp)), m_debug_map_module_wp(),
      m_debug_map_symfile(nullptr),
      m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list),
      m_fetched_external_modules(false) {}

SymbolFileDWARF::~SymbolFileDWARF() = default;

static ConstString GetDWARFMachOSegmentName() {
  static ConstString g_dwarf_section_name("__DWARF");
  return g_dwarf_section_name;
}

llvm::DenseMap<const DWARFDebugInfoEntry *, Type *> &
SymbolFileDWARF::GetDIEToType() {
  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
    return debug_map_symfile->GetDIEToType();
  return m_die_to_type;
}

llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> &
SymbolFileDWARF::GetForwardDeclCompilerTypeToDIE() {
  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
    return debug_map_symfile->GetForwardDeclCompilerTypeToDIE();
  return m_forward_decl_compiler_type_to_die;
}

UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() {
  SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
  if (debug_map_symfile)
    return debug_map_symfile->GetUniqueDWARFASTTypeMap();
  else
    return m_unique_ast_type_map;
}

llvm::Expected<lldb::TypeSystemSP>
SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
    return debug_map_symfile->GetTypeSystemForLanguage(language);

  return SymbolFileCommon::GetTypeSystemForLanguage(language);
}

void SymbolFileDWARF::InitializeObject() {
  Log *log = GetLog(DWARFLog::DebugInfo);

  InitializeFirstCodeAddress();

  if (!GetGlobalPluginProperties().IgnoreFileIndexes()) {
    StreamString module_desc;
    GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
                                                 lldb::eDescriptionLevelBrief);
    DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
    LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
    LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
    LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
    LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);

    if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
        apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
      m_index = AppleDWARFIndex::Create(
          *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
          apple_types, apple_objc, m_context.getOrLoadStrData());

      if (m_index)
        return;
    }

    DWARFDataExtractor debug_names;
    LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
    if (debug_names.GetByteSize() > 0) {
      Progress progress("Loading DWARF5 index", module_desc.GetData());
      llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
          DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
                                       debug_names,
                                       m_context.getOrLoadStrData(), *this);
      if (index_or) {
        m_index = std::move(*index_or);
        return;
      }
      LLDB_LOG_ERROR(log, index_or.takeError(),
                     "Unable to read .debug_names data: {0}");
    }
  }

  m_index =
      std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), *this);
}

void SymbolFileDWARF::InitializeFirstCodeAddress() {
  InitializeFirstCodeAddressRecursive(
      *m_objfile_sp->GetModule()->GetSectionList());
  if (m_first_code_address == LLDB_INVALID_ADDRESS)
    m_first_code_address = 0;
}

void SymbolFileDWARF::InitializeFirstCodeAddressRecursive(
    const lldb_private::SectionList &section_list) {
  for (SectionSP section_sp : section_list) {
    if (section_sp->GetChildren().GetSize() > 0) {
      InitializeFirstCodeAddressRecursive(section_sp->GetChildren());
    } else if (section_sp->GetType() == eSectionTypeCode) {
      m_first_code_address =
          std::min(m_first_code_address, section_sp->GetFileAddress());
    }
  }
}

bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
  return version >= 2 && version <= 5;
}

static std::set<dw_form_t>
GetUnsupportedForms(llvm::DWARFDebugAbbrev *debug_abbrev) {
  if (!debug_abbrev)
    return {};

  std::set<dw_form_t> unsupported_forms;
  for (const auto &[_, decl_set] : *debug_abbrev)
    for (const auto &decl : decl_set)
      for (const auto &attr : decl.attributes())
        if (!DWARFFormValue::FormIsSupported(attr.Form))
          unsupported_forms.insert(attr.Form);

  return unsupported_forms;
}

uint32_t SymbolFileDWARF::CalculateAbilities() {
  uint32_t abilities = 0;
  if (m_objfile_sp != nullptr) {
    const Section *section = nullptr;
    const SectionList *section_list = m_objfile_sp->GetSectionList();
    if (section_list == nullptr)
      return 0;

    uint64_t debug_abbrev_file_size = 0;
    uint64_t debug_info_file_size = 0;
    uint64_t debug_line_file_size = 0;

    section = section_list->FindSectionByName(GetDWARFMachOSegmentName()).get();

    if (section)
      section_list = &section->GetChildren();

    section =
        section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true).get();
    if (section != nullptr) {
      debug_info_file_size = section->GetFileSize();

      section =
          section_list->FindSectionByType(eSectionTypeDWARFDebugAbbrev, true)
              .get();
      if (section)
        debug_abbrev_file_size = section->GetFileSize();

      llvm::DWARFDebugAbbrev *abbrev = DebugAbbrev();
      std::set<dw_form_t> unsupported_forms = GetUnsupportedForms(abbrev);
      if (!unsupported_forms.empty()) {
        StreamString error;
        error.Printf("unsupported DW_FORM value%s:",
                     unsupported_forms.size() > 1 ? "s" : "");
        for (auto form : unsupported_forms)
          error.Printf(" %#x", form);
        m_objfile_sp->GetModule()->ReportWarning("{0}", error.GetString());
        return 0;
      }

      section =
          section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true)
              .get();
      if (section)
        debug_line_file_size = section->GetFileSize();
    } else {
      llvm::StringRef symfile_dir =
          m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef();
      if (symfile_dir.contains_insensitive(".dsym")) {
        if (m_objfile_sp->GetType() == ObjectFile::eTypeDebugInfo) {
          // We have a dSYM file that didn't have a any debug info. If the
          // string table has a size of 1, then it was made from an
          // executable with no debug info, or from an executable that was
          // stripped.
          section =
              section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true)
                  .get();
          if (section && section->GetFileSize() == 1) {
            m_objfile_sp->GetModule()->ReportWarning(
                "empty dSYM file detected, dSYM was created with an "
                "executable with no debug info");
          }
        }
      }
    }

    constexpr uint64_t MaxDebugInfoSize = (1ull) << DW_DIE_OFFSET_MAX_BITSIZE;
    if (debug_info_file_size >= MaxDebugInfoSize) {
      m_objfile_sp->GetModule()->ReportWarning(
          "SymbolFileDWARF can't load this DWARF. It's larger then {0:x+16}",
          MaxDebugInfoSize);
      return 0;
    }

    if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
      abilities |= CompileUnits | Functions | Blocks | GlobalVariables |
                   LocalVariables | VariableTypes;

    if (debug_line_file_size > 0)
      abilities |= LineTables;
  }
  return abilities;
}

void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type,
                                      DWARFDataExtractor &data) {
  ModuleSP module_sp(m_objfile_sp->GetModule());
  const SectionList *section_list = module_sp->GetSectionList();
  if (!section_list)
    return;

  SectionSP section_sp(section_list->FindSectionByType(sect_type, true));
  if (!section_sp)
    return;

  data.Clear();
  m_objfile_sp->ReadSectionData(section_sp.get(), data);
}

llvm::DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
  if (m_abbr)
    return m_abbr.get();

  const DWARFDataExtractor &debug_abbrev_data = m_context.getOrLoadAbbrevData();
  if (debug_abbrev_data.GetByteSize() == 0)
    return nullptr;

  ElapsedTime elapsed(m_parse_time);
  auto abbr =
      std::make_unique<llvm::DWARFDebugAbbrev>(debug_abbrev_data.GetAsLLVM());
  llvm::Error error = abbr->parse();
  if (error) {
    Log *log = GetLog(DWARFLog::DebugInfo);
    LLDB_LOG_ERROR(log, std::move(error),
                   "Unable to read .debug_abbrev section: {0}");
    return nullptr;
  }

  m_abbr = std::move(abbr);
  return m_abbr.get();
}

DWARFDebugInfo &SymbolFileDWARF::DebugInfo() {
  llvm::call_once(m_info_once_flag, [&] {
    LLDB_SCOPED_TIMER();

    m_info = std::make_unique<DWARFDebugInfo>(*this, m_context);
  });
  return *m_info;
}

DWARFCompileUnit *SymbolFileDWARF::GetDWARFCompileUnit(CompileUnit *comp_unit) {
  if (!comp_unit)
    return nullptr;

  // The compile unit ID is the index of the DWARF unit.
  DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(comp_unit->GetID());
  if (dwarf_cu && dwarf_cu->GetLLDBCompUnit() == nullptr)
    dwarf_cu->SetLLDBCompUnit(comp_unit);

  // It must be DWARFCompileUnit when it created a CompileUnit.
  return llvm::cast_or_null<DWARFCompileUnit>(dwarf_cu);
}

/// Make an absolute path out of \p file_spec and remap it using the
/// module's source remapping dictionary.
static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu,
                                 const ModuleSP &module_sp) {
  if (!file_spec)
    return;
  // If we have a full path to the compile unit, we don't need to
  // resolve the file.  This can be expensive e.g. when the source
  // files are NFS mounted.
  file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory());

  if (auto remapped_file = module_sp->RemapSourceFile(file_spec.GetPath()))
    file_spec.SetFile(*remapped_file, FileSpec::Style::native);
}

/// Return the DW_AT_(GNU_)dwo_name.
static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
                              const DWARFDebugInfoEntry &cu_die) {
  const char *dwo_name =
      cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
  if (!dwo_name)
    dwo_name =
        cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
  return dwo_name;
}

lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
  CompUnitSP cu_sp;
  CompileUnit *comp_unit = dwarf_cu.GetLLDBCompUnit();
  if (comp_unit) {
    // We already parsed this compile unit, had out a shared pointer to it
    cu_sp = comp_unit->shared_from_this();
  } else {
    if (GetDebugMapSymfile()) {
      // Let the debug map create the compile unit
      cu_sp = m_debug_map_symfile->GetCompileUnit(this, dwarf_cu);
      dwarf_cu.SetLLDBCompUnit(cu_sp.get());
    } else {
      ModuleSP module_sp(m_objfile_sp->GetModule());
      if (module_sp) {
        auto initialize_cu = [&](SupportFileNSP support_file_nsp,
                                 LanguageType cu_language,
                                 SupportFileList &&support_files = {}) {
          BuildCuTranslationTable();
          cu_sp = std::make_shared<CompileUnit>(
              module_sp, &dwarf_cu, support_file_nsp,
              *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
              eLazyBoolCalculate, std::move(support_files));

          dwarf_cu.SetLLDBCompUnit(cu_sp.get());

          SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
        };

        auto lazy_initialize_cu = [&]() {
          // If the version is < 5, we can't do lazy initialization.
          if (dwarf_cu.GetVersion() < 5)
            return false;

          // If there is no DWO, there is no reason to initialize
          // lazily; we will do eager initialization in that case.
          if (GetDebugMapSymfile())
            return false;
          const DWARFBaseDIE cu_die = dwarf_cu.GetUnitDIEOnly();
          if (!cu_die)
            return false;
          if (!GetDWOName(dwarf_cu, *cu_die.GetDIE()))
            return false;

          // With DWARFv5 we can assume that the first support
          // file is also the name of the compile unit. This
          // allows us to avoid loading the non-skeleton unit,
          // which may be in a separate DWO file.
          SupportFileList support_files;
          if (!ParseSupportFiles(dwarf_cu, module_sp, support_files))
            return false;
          if (support_files.GetSize() == 0)
            return false;
          initialize_cu(support_files.GetSupportFileAtIndex(0),
                        eLanguageTypeUnknown, std::move(support_files));
          return true;
        };

        if (!lazy_initialize_cu()) {
          // Eagerly initialize compile unit
          const DWARFBaseDIE cu_die =
              dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
          if (cu_die) {
            LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
                dwarf_cu.GetDWARFLanguageType());

            FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());

            // Path needs to be remapped in this case. In the support files
            // case ParseSupportFiles takes care of the remapping.
            MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);

            initialize_cu(std::make_shared<SupportFile>(cu_file_spec),
                          cu_language);
          }
        }
      }
    }
  }
  return cu_sp;
}

void SymbolFileDWARF::BuildCuTranslationTable() {
  if (!m_lldb_cu_to_dwarf_unit.empty())
    return;

  DWARFDebugInfo &info = DebugInfo();
  if (!info.ContainsTypeUnits()) {
    // We can use a 1-to-1 mapping. No need to build a translation table.
    return;
  }
  for (uint32_t i = 0, num = info.GetNumUnits(); i < num; ++i) {
    if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info.GetUnitAtIndex(i))) {
      cu->SetID(m_lldb_cu_to_dwarf_unit.size());
      m_lldb_cu_to_dwarf_unit.push_back(i);
    }
  }
}

std::optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) {
  BuildCuTranslationTable();
  if (m_lldb_cu_to_dwarf_unit.empty())
    return cu_idx;
  if (cu_idx >= m_lldb_cu_to_dwarf_unit.size())
    return std::nullopt;
  return m_lldb_cu_to_dwarf_unit[cu_idx];
}

uint32_t SymbolFileDWARF::CalculateNumCompileUnits() {
  BuildCuTranslationTable();
  return m_lldb_cu_to_dwarf_unit.empty() ? DebugInfo().GetNumUnits()
                                         : m_lldb_cu_to_dwarf_unit.size();
}

CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
  ASSERT_MODULE_LOCK(this);
  if (std::optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) {
    if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>(
            DebugInfo().GetUnitAtIndex(*dwarf_idx)))
      return ParseCompileUnit(*dwarf_cu);
  }
  return {};
}

Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit,
                                         const DWARFDIE &die) {
  ASSERT_MODULE_LOCK(this);
  Log *log = GetLog(LLDBLog::Symbols);
  if (!die.IsValid())
    return nullptr;

  auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(log, std::move(err), "Unable to parse function: {0}");
    return nullptr;
  }
  auto ts = *type_system_or_err;
  if (!ts)
    return nullptr;
  DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
  if (!dwarf_ast)
    return nullptr;

  AddressRanges ranges;
  ModuleSP module_sp(die.GetModule());
  if (llvm::Expected<llvm::DWARFAddressRangesVector> die_ranges =
          die.GetDIE()->GetAttributeAddressRanges(die.GetCU(),
                                                  /*check_hi_lo_pc=*/true)) {
    for (const auto &range : *die_ranges) {
      if (range.valid() && range.LowPC < m_first_code_address)
        continue;
      if (Address base_addr(range.LowPC, module_sp->GetSectionList());
          base_addr.IsValid() && FixupAddress(base_addr))
        ranges.emplace_back(std::move(base_addr), range.HighPC - range.LowPC);
    }
  } else {
    LLDB_LOG_ERROR(log, die_ranges.takeError(), "DIE({1:x}): {0}", die.GetID());
  }
  if (ranges.empty())
    return nullptr;

  return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, std::move(ranges));
}

ConstString
SymbolFileDWARF::ConstructFunctionDemangledName(const DWARFDIE &die) {
  ASSERT_MODULE_LOCK(this);
  if (!die.IsValid()) {
    return ConstString();
  }

  auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Unable to construct demangled name for function: {0}");
    return ConstString();
  }

  auto ts = *type_system_or_err;
  if (!ts) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "Type system no longer live");
    return ConstString();
  }
  DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
  if (!dwarf_ast)
    return ConstString();

  return dwarf_ast->ConstructDemangledNameFromDWARF(die);
}

lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) {
  SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
  if (debug_map_symfile)
    return debug_map_symfile->LinkOSOFileAddress(this, file_addr);
  return file_addr;
}

bool SymbolFileDWARF::FixupAddress(Address &addr) {
  SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
  if (debug_map_symfile) {
    return debug_map_symfile->LinkOSOAddress(addr);
  }
  // This is a normal DWARF file, no address fixups need to happen
  return true;
}
lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (dwarf_cu)
    return GetLanguage(dwarf_cu->GetNonSkeletonUnit());
  else
    return eLanguageTypeUnknown;
}

XcodeSDK SymbolFileDWARF::ParseXcodeSDK(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (!dwarf_cu)
    return {};
  const DWARFBaseDIE cu_die = dwarf_cu->GetNonSkeletonUnit().GetUnitDIEOnly();
  if (!cu_die)
    return {};
  const char *sdk = cu_die.GetAttributeValueAsString(DW_AT_APPLE_sdk, nullptr);
  if (!sdk)
    return {};
  llvm::StringRef sysroot =
      cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, "");

  // RegisterXcodeSDK calls into xcrun which is not aware of CLT, which is
  // expensive.
  if (!sysroot.starts_with("/Library/Developer/CommandLineTools/SDKs")) {
    // Register the sysroot path remapping with the module belonging to
    // the CU as well as the one belonging to the symbol file. The two
    // would be different if this is an OSO object and module is the
    // corresponding debug map, in which case both should be updated.
    ModuleSP module_sp = comp_unit.GetModule();
    if (module_sp)
      module_sp->RegisterXcodeSDK(sdk, sysroot);

    ModuleSP local_module_sp = m_objfile_sp->GetModule();
    if (local_module_sp && local_module_sp != module_sp)
      local_module_sp->RegisterXcodeSDK(sdk, sysroot);
  }

  return {sdk, FileSpec(sysroot)};
}

size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
  LLDB_SCOPED_TIMER();
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (!dwarf_cu)
    return 0;

  size_t functions_added = 0;
  dwarf_cu = &dwarf_cu->GetNonSkeletonUnit();
  for (DWARFDebugInfoEntry &entry : dwarf_cu->dies()) {
    if (entry.Tag() != DW_TAG_subprogram)
      continue;

    DWARFDIE die(dwarf_cu, &entry);
    if (comp_unit.FindFunctionByUID(die.GetID()))
      continue;
    if (ParseFunction(comp_unit, die))
      ++functions_added;
  }
  // FixupTypes();
  return functions_added;
}

bool SymbolFileDWARF::ForEachExternalModule(
    CompileUnit &comp_unit,
    llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
    llvm::function_ref<bool(Module &)> lambda) {
  // Only visit each symbol file once.
  if (!visited_symbol_files.insert(this).second)
    return false;

  UpdateExternalModuleListIfNeeded();
  for (auto &p : m_external_type_modules) {
    ModuleSP module = p.second;
    if (!module)
      continue;

    // Invoke the action and potentially early-exit.
    if (lambda(*module))
      return true;

    for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
      auto cu = module->GetCompileUnitAtIndex(i);
      bool early_exit = cu->ForEachExternalModule(visited_symbol_files, lambda);
      if (early_exit)
        return true;
    }
  }
  return false;
}

bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
                                        SupportFileList &support_files) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (!dwarf_cu)
    return false;

  if (!ParseSupportFiles(*dwarf_cu, comp_unit.GetModule(), support_files))
    return false;

  return true;
}

bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
                                        const ModuleSP &module,
                                        SupportFileList &support_files) {

  dw_offset_t offset = dwarf_cu.GetLineTableOffset();
  if (offset == DW_INVALID_OFFSET)
    return false;

  ElapsedTime elapsed(m_parse_time);
  llvm::DWARFDebugLine::Prologue prologue;
  if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
                                  dwarf_cu.GetOffset()))
    return false;

  std::string comp_dir = dwarf_cu.GetCompilationDirectory().GetPath();
  ParseSupportFilesFromPrologue(support_files, module, prologue,
                                dwarf_cu.GetPathStyle(), comp_dir);
  return true;
}

FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) {
  if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit)) {
    if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu))
      return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx);
    return FileSpec();
  }

  auto &tu = llvm::cast<DWARFTypeUnit>(unit);
  if (const SupportFileList *support_files = GetTypeUnitSupportFiles(tu))
    return support_files->GetFileSpecAtIndex(file_idx);
  return {};
}

const SupportFileList *
SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) {
  static SupportFileList empty_list;

  dw_offset_t offset = tu.GetLineTableOffset();
  if (offset == DW_INVALID_OFFSET ||
      offset == llvm::DenseMapInfo<dw_offset_t>::getEmptyKey() ||
      offset == llvm::DenseMapInfo<dw_offset_t>::getTombstoneKey())
    return nullptr;

  // Many type units can share a line table, so parse the support file list
  // once, and cache it based on the offset field.
  auto iter_bool = m_type_unit_support_files.try_emplace(offset);
  std::unique_ptr<SupportFileList> &list = iter_bool.first->second;
  if (iter_bool.second) {
    list = std::make_unique<SupportFileList>();
    uint64_t line_table_offset = offset;
    llvm::DWARFDataExtractor data =
        m_context.getOrLoadLineData().GetAsLLVMDWARF();
    llvm::DWARFContext &ctx = m_context.GetAsLLVM();
    llvm::DWARFDebugLine::Prologue prologue;
    auto report = [](llvm::Error error) {
      Log *log = GetLog(DWARFLog::DebugInfo);
      LLDB_LOG_ERROR(log, std::move(error),
                     "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
                     "the line table prologue: {0}");
    };
    ElapsedTime elapsed(m_parse_time);
    llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
    if (error)
      report(std::move(error));
    else
      ParseSupportFilesFromPrologue(*list, GetObjectFile()->GetModule(),
                                    prologue, tu.GetPathStyle());
  }
  return list.get();
}

bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (dwarf_cu)
    return dwarf_cu->GetNonSkeletonUnit().GetIsOptimized();
  return false;
}

bool SymbolFileDWARF::ParseImportedModules(
    const lldb_private::SymbolContext &sc,
    std::vector<SourceModule> &imported_modules) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  assert(sc.comp_unit);
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (!dwarf_cu)
    return false;
  if (!ClangModulesDeclVendor::LanguageSupportsClangModules(
          sc.comp_unit->GetLanguage()))
    return false;
  UpdateExternalModuleListIfNeeded();

  const DWARFDIE die = dwarf_cu->DIE();
  if (!die)
    return false;

  for (DWARFDIE child_die : die.children()) {
    if (child_die.Tag() != DW_TAG_imported_declaration)
      continue;

    DWARFDIE module_die = child_die.GetReferencedDIE(DW_AT_import);
    if (module_die.Tag() != DW_TAG_module)
      continue;

    if (const char *name =
            module_die.GetAttributeValueAsString(DW_AT_name, nullptr)) {
      SourceModule module;
      module.path.push_back(ConstString(name));

      const char *include_path = module_die.GetAttributeValueAsString(
          DW_AT_LLVM_include_path, nullptr);
      DWARFDIE parent_die = module_die;
      while ((parent_die = parent_die.GetParent())) {
        if (parent_die.Tag() != DW_TAG_module)
          break;
        if (const char *name =
                parent_die.GetAttributeValueAsString(DW_AT_name, nullptr))
          module.path.push_back(ConstString(name));

        // Inferred submodule declarations may not have a
        // DW_AT_LLVM_include_path. Pick the parent (aka umbrella) module's
        // include path instead.
        if (!include_path)
          include_path = parent_die.GetAttributeValueAsString(
              DW_AT_LLVM_include_path, nullptr);
      }
      std::reverse(module.path.begin(), module.path.end());
      if (include_path) {
        FileSpec include_spec(include_path, dwarf_cu->GetPathStyle());
        MakeAbsoluteAndRemap(include_spec, *dwarf_cu,
                             m_objfile_sp->GetModule());
        module.search_path = ConstString(include_spec.GetPath());
      }
      if (const char *sysroot = dwarf_cu->DIE().GetAttributeValueAsString(
              DW_AT_LLVM_sysroot, nullptr))
        module.sysroot = ConstString(sysroot);
      imported_modules.push_back(module);
    }
  }
  return true;
}

bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (comp_unit.GetLineTable() != nullptr)
    return true;

  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (!dwarf_cu)
    return false;

  dw_offset_t offset = dwarf_cu->GetLineTableOffset();
  if (offset == DW_INVALID_OFFSET)
    return false;

  ElapsedTime elapsed(m_parse_time);
  llvm::DWARFDebugLine line;
  const llvm::DWARFDebugLine::LineTable *line_table =
      ParseLLVMLineTable(m_context, line, offset, dwarf_cu->GetOffset());

  if (!line_table)
    return false;

  // FIXME: Rather than parsing the whole line table and then copying it over
  // into LLDB, we should explore using a callback to populate the line table
  // while we parse to reduce memory usage.
  std::vector<LineTable::Sequence> sequences;
  // The Sequences view contains only valid line sequences. Don't iterate over
  // the Rows directly.
  for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) {
    // Ignore line sequences that do not start after the first code address.
    // All addresses generated in a sequence are incremental so we only need
    // to check the first one of the sequence. Check the comment at the
    // m_first_code_address declaration for more details on this.
    if (seq.LowPC < m_first_code_address)
      continue;
    LineTable::Sequence sequence;
    for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
      const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx];
      LineTable::AppendLineEntryToSequence(
          sequence, row.Address.Address, row.Line, row.Column, row.File,
          row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
          row.EndSequence);
    }
    sequences.push_back(std::move(sequence));
  }

  std::unique_ptr<LineTable> line_table_up =
      std::make_unique<LineTable>(&comp_unit, std::move(sequences));

  if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) {
    // We have an object file that has a line table with addresses that are not
    // linked. We need to link the line table and convert the addresses that
    // are relative to the .o file into addresses for the main executable.
    comp_unit.SetLineTable(
        debug_map_symfile->LinkOSOLineTable(this, line_table_up.get()));
  } else {
    comp_unit.SetLineTable(line_table_up.release());
  }

  return true;
}

lldb_private::DebugMacrosSP
SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
  auto iter = m_debug_macros_map.find(*offset);
  if (iter != m_debug_macros_map.end())
    return iter->second;

  ElapsedTime elapsed(m_parse_time);
  const DWARFDataExtractor &debug_macro_data = m_context.getOrLoadMacroData();
  if (debug_macro_data.GetByteSize() == 0)
    return DebugMacrosSP();

  lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros());
  m_debug_macros_map[*offset] = debug_macros_sp;

  const DWARFDebugMacroHeader &header =
      DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset);
  DWARFDebugMacroEntry::ReadMacroEntries(
      debug_macro_data, m_context.getOrLoadStrData(), header.OffsetIs64Bit(),
      offset, this, debug_macros_sp);

  return debug_macros_sp;
}

bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());

  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (dwarf_cu == nullptr)
    return false;

  const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
  if (!dwarf_cu_die)
    return false;

  lldb::offset_t sect_offset =
      dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET);
  if (sect_offset == DW_INVALID_OFFSET)
    sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros,
                                                           DW_INVALID_OFFSET);
  if (sect_offset == DW_INVALID_OFFSET)
    return false;

  comp_unit.SetDebugMacros(ParseDebugMacros(&sect_offset));

  return true;
}

size_t SymbolFileDWARF::ParseBlocksRecursive(CompileUnit &comp_unit,
                                             Block *parent_block, DWARFDIE die,
                                             addr_t function_file_addr) {
  size_t blocks_added = 0;
  for (; die; die = die.GetSibling()) {
    dw_tag_t tag = die.Tag();

    if (tag != DW_TAG_inlined_subroutine && tag != DW_TAG_lexical_block)
      continue;

    Block *block = parent_block->CreateChild(die.GetID()).get();
    llvm::DWARFAddressRangesVector ranges;
    const char *name = nullptr;
    const char *mangled_name = nullptr;

    std::optional<int> decl_file;
    std::optional<int> decl_line;
    std::optional<int> decl_column;
    std::optional<int> call_file;
    std::optional<int> call_line;
    std::optional<int> call_column;
    if (die.GetDIENamesAndRanges(name, mangled_name, ranges, decl_file,
                                 decl_line, decl_column, call_file, call_line,
                                 call_column, nullptr)) {
      for (const llvm::DWARFAddressRange &range : ranges) {
        if (range.valid() && range.LowPC >= m_first_code_address)
          block->AddRange(Block::Range(range.LowPC - function_file_addr,
                                       range.HighPC - range.LowPC));
      }
      block->FinalizeRanges();

      if (tag != DW_TAG_subprogram &&
          (name != nullptr || mangled_name != nullptr)) {
        std::unique_ptr<Declaration> decl_up;
        if (decl_file || decl_line || decl_column)
          decl_up = std::make_unique<Declaration>(
              comp_unit.GetSupportFiles().GetFileSpecAtIndex(
                  decl_file.value_or(0)),
              decl_line.value_or(0), decl_column.value_or(0));

        std::unique_ptr<Declaration> call_up;
        if (call_file || call_line || call_column)
          call_up = std::make_unique<Declaration>(
              comp_unit.GetSupportFiles().GetFileSpecAtIndex(
                  call_file.value_or(0)),
              call_line.value_or(0), call_column.value_or(0));

        block->SetInlinedFunctionInfo(name, mangled_name, decl_up.get(),
                                      call_up.get());
      }

      ++blocks_added;

      if (die.HasChildren()) {
        blocks_added += ParseBlocksRecursive(
            comp_unit, block, die.GetFirstChild(), function_file_addr);
      }
    }
  }
  return blocks_added;
}

bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) {
  if (parent_die) {
    for (DWARFDIE die : parent_die.children()) {
      dw_tag_t tag = die.Tag();
      bool check_virtuality = false;
      switch (tag) {
      case DW_TAG_inheritance:
      case DW_TAG_subprogram:
        check_virtuality = true;
        break;
      default:
        break;
      }
      if (check_virtuality) {
        if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0)
          return true;
      }
    }
  }
  return false;
}

void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
  auto *type_system = decl_ctx.GetTypeSystem();
  if (type_system != nullptr)
    type_system->GetDWARFParser()->EnsureAllDIEsInDeclContextHaveBeenParsed(
        decl_ctx);
}

DWARFDIE
SymbolFileDWARF::GetDIE(lldb::user_id_t uid) { return GetDIE(DIERef(uid)); }

CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
  // This method can be called without going through the symbol vendor so we
  // need to lock the module.
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
  // SymbolFileDWARF::GetDIE(). See comments inside the
  // SymbolFileDWARF::GetDIE() for details.
  if (DWARFDIE die = GetDIE(type_uid))
    return GetDecl(die);
  return CompilerDecl();
}

CompilerDeclContext
SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
  // This method can be called without going through the symbol vendor so we
  // need to lock the module.
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
  // SymbolFileDWARF::GetDIE(). See comments inside the
  // SymbolFileDWARF::GetDIE() for details.
  if (DWARFDIE die = GetDIE(type_uid))
    return GetDeclContext(die);
  return CompilerDeclContext();
}

CompilerDeclContext
SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
  // SymbolFileDWARF::GetDIE(). See comments inside the
  // SymbolFileDWARF::GetDIE() for details.
  if (DWARFDIE die = GetDIE(type_uid))
    return GetContainingDeclContext(die);
  return CompilerDeclContext();
}

std::vector<CompilerContext>
SymbolFileDWARF::GetCompilerContextForUID(lldb::user_id_t type_uid) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
  // SymbolFileDWARF::GetDIE(). See comments inside the
  // SymbolFileDWARF::GetDIE() for details.
  if (DWARFDIE die = GetDIE(type_uid))
    return die.GetDeclContext();
  return {};
}

Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Anytime we have a lldb::user_id_t, we must get the DIE by calling
  // SymbolFileDWARF::GetDIE(). See comments inside the
  // SymbolFileDWARF::GetDIE() for details.
  if (DWARFDIE type_die = GetDIE(type_uid))
    return type_die.ResolveType();
  else
    return nullptr;
}

std::optional<SymbolFile::ArrayInfo> SymbolFileDWARF::GetDynamicArrayInfoForUID(
    lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (DWARFDIE type_die = GetDIE(type_uid))
    return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx);
  else
    return std::nullopt;
}

Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) {
  return ResolveType(GetDIE(die_ref), true);
}

Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
                                      bool assert_not_being_parsed) {
  if (die) {
    Log *log = GetLog(DWARFLog::DebugInfo);
    if (log)
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) {1} ({2}) '{3}'",
          die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),
          die.GetName());

    // We might be coming in in the middle of a type tree (a class within a
    // class, an enum within a class), so parse any needed parent DIEs before
    // we get to this one...
    DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(die);
    if (decl_ctx_die) {
      if (log) {
        switch (decl_ctx_die.Tag()) {
        case DW_TAG_structure_type:
        case DW_TAG_union_type:
        case DW_TAG_class_type: {
          // Get the type, which could be a forward declaration
          if (log)
            GetObjectFile()->GetModule()->LogMessage(
                log,
                "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) {1} ({2}) "
                "'{3}' resolve parent forward type for {4:x16})",
                die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),
                die.GetName(), decl_ctx_die.GetOffset());
        } break;

        default:
          break;
        }
      }
    }
    return ResolveType(die);
  }
  return nullptr;
}

// This function is used when SymbolFileDWARFDebugMap owns a bunch of
// SymbolFileDWARF objects to detect if this DWARF file is the one that can
// resolve a compiler_type.
bool SymbolFileDWARF::HasForwardDeclForCompilerType(
    const CompilerType &compiler_type) {
  CompilerType compiler_type_no_qualifiers =
      ClangUtil::RemoveFastQualifiers(compiler_type);
  if (GetForwardDeclCompilerTypeToDIE().count(
          compiler_type_no_qualifiers.GetOpaqueQualType())) {
    return true;
  }
  auto clang_type_system = compiler_type.GetTypeSystem<TypeSystemClang>();
  if (!clang_type_system)
    return false;
  auto *ast_parser =
      llvm::cast<DWARFASTParserClang>(clang_type_system->GetDWARFParser());
  return ast_parser->GetClangASTImporter().CanImport(compiler_type);
}

bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  auto clang_type_system = compiler_type.GetTypeSystem<TypeSystemClang>();
  if (clang_type_system) {
    auto *ast_parser =
        llvm::cast<DWARFASTParserClang>(clang_type_system->GetDWARFParser());
    if (ast_parser &&
        ast_parser->GetClangASTImporter().CanImport(compiler_type))
      return ast_parser->GetClangASTImporter().CompleteType(compiler_type);
  }

  // We have a struct/union/class/enum that needs to be fully resolved.
  CompilerType compiler_type_no_qualifiers =
      ClangUtil::RemoveFastQualifiers(compiler_type);
  auto die_it = GetForwardDeclCompilerTypeToDIE().find(
      compiler_type_no_qualifiers.GetOpaqueQualType());
  if (die_it == GetForwardDeclCompilerTypeToDIE().end()) {
    // We have already resolved this type...
    return true;
  }

  DWARFDIE decl_die = GetDIE(die_it->getSecond());
  // Once we start resolving this type, remove it from the forward
  // declaration map in case anyone's child members or other types require this
  // type to get resolved.
  GetForwardDeclCompilerTypeToDIE().erase(die_it);
  DWARFDIE def_die = FindDefinitionDIE(decl_die);
  if (!def_die) {
    SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
    if (debug_map_symfile) {
      // We weren't able to find a full declaration in this DWARF, see
      // if we have a declaration anywhere else...
      def_die = debug_map_symfile->FindDefinitionDIE(decl_die);
    }
  }
  if (!def_die) {
    // If we don't have definition DIE, CompleteTypeFromDWARF will forcefully
    // complete this type.
    def_die = decl_die;
  }

  DWARFASTParser *dwarf_ast = GetDWARFParser(*def_die.GetCU());
  if (!dwarf_ast)
    return false;
  Type *type = GetDIEToType().lookup(decl_die.GetDIE());
  assert(type);

  if (decl_die != def_die) {
    GetDIEToType()[def_die.GetDIE()] = type;
    auto *ast_parser = llvm::cast<DWARFASTParserClang>(dwarf_ast);
    ast_parser->MapDeclDIEToDefDIE(decl_die, def_die);
  }

  Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
  if (log)
    GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
        log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
        def_die.GetID(), DW_TAG_value_to_name(def_die.Tag()), def_die.Tag(),
        type->GetName().GetStringRef());
  assert(compiler_type);
  return dwarf_ast->CompleteTypeFromDWARF(def_die, type, compiler_type);
}

Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
                                   bool assert_not_being_parsed,
                                   bool resolve_function_context) {
  if (die) {
    Type *type = GetTypeForDIE(die, resolve_function_context).get();

    if (assert_not_being_parsed) {
      if (type != DIE_IS_BEING_PARSED)
        return type;

      GetObjectFile()->GetModule()->ReportError(
          "Parsing a die that is being parsed die: {0:x16}: {1} ({2}) {3}",
          die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),
          die.GetName());

    } else
      return type;
  }
  return nullptr;
}

CompileUnit *
SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) {

  if (dwarf_cu.IsDWOUnit()) {
    DWARFCompileUnit *non_dwo_cu = dwarf_cu.GetSkeletonUnit();
    assert(non_dwo_cu);
    return non_dwo_cu->GetSymbolFileDWARF().GetCompUnitForDWARFCompUnit(
        *non_dwo_cu);
  }
  // Check if the symbol vendor already knows about this compile unit?
  CompileUnit *lldb_cu = dwarf_cu.GetLLDBCompUnit();
  if (lldb_cu)
    return lldb_cu;
  // The symbol vendor doesn't know about this compile unit, we need to parse
  // and add it to the symbol vendor object.
  return ParseCompileUnit(dwarf_cu).get();
}

void SymbolFileDWARF::GetObjCMethods(
    ConstString class_name,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  m_index->GetObjCMethods(class_name, callback);
}

bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
  sc.Clear(false);

  if (die && llvm::isa<DWARFCompileUnit>(die.GetCU())) {
    // Check if the symbol vendor already knows about this compile unit?
    sc.comp_unit =
        GetCompUnitForDWARFCompUnit(llvm::cast<DWARFCompileUnit>(*die.GetCU()));

    sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
    if (sc.function == nullptr)
      sc.function = ParseFunction(*sc.comp_unit, die);

    if (sc.function) {
      sc.module_sp = sc.function->CalculateSymbolContextModule();
      return true;
    }
  }

  return false;
}

lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) {
  UpdateExternalModuleListIfNeeded();
  const auto &pos = m_external_type_modules.find(name);
  if (pos == m_external_type_modules.end())
    return lldb::ModuleSP();
  return pos->second;
}

SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) {
  // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
  // must make sure we use the correct DWARF file when resolving things. On
  // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
  // SymbolFileDWARF classes, one for each .o file. We can often end up with
  // references to other DWARF objects and we must be ready to receive a
  // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
  // instance.

  std::optional<uint32_t> file_index = die_ref.file_index();

  // If the file index matches, then we have the right SymbolFileDWARF already.
  // This will work for both .dwo file and DWARF in .o files for mac. Also if
  // both the file indexes are invalid, then we have a match.
  if (GetFileIndex() == file_index)
    return this;

  if (file_index) {
      // We have a SymbolFileDWARFDebugMap, so let it find the right file
    if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile())
      return debug_map->GetSymbolFileByOSOIndex(*file_index);

    // Handle the .dwp file case correctly
    if (*file_index == DIERef::k_file_index_mask)
      return GetDwpSymbolFile().get(); // DWP case

    // Handle the .dwo file case correctly
    return DebugInfo().GetUnitAtIndex(*die_ref.file_index())
        ->GetDwoSymbolFile(); // DWO case
  }
  return this;
}

DWARFDIE
SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
  if (die_ref.die_offset() == DW_INVALID_OFFSET)
    return DWARFDIE();

  // This method can be called without going through the symbol vendor so we
  // need to lock the module.
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  SymbolFileDWARF *symbol_file = GetDIERefSymbolFile(die_ref);
  if (symbol_file)
    return symbol_file->DebugInfo().GetDIE(die_ref.section(),
                                           die_ref.die_offset());
  return DWARFDIE();
}

/// Return the DW_AT_(GNU_)dwo_id.
static std::optional<uint64_t> GetDWOId(DWARFCompileUnit &dwarf_cu,
                                        const DWARFDebugInfoEntry &cu_die) {
  std::optional<uint64_t> dwo_id =
      cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id);
  if (dwo_id)
    return dwo_id;
  return cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_dwo_id);
}

std::optional<uint64_t> SymbolFileDWARF::GetDWOId() {
  if (GetNumCompileUnits() == 1) {
    if (auto comp_unit = GetCompileUnitAtIndex(0))
      if (DWARFCompileUnit *cu = GetDWARFCompileUnit(comp_unit.get()))
        if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
          return ::GetDWOId(*cu, *cu_die);
  }
  return {};
}

DWARFUnit *SymbolFileDWARF::GetSkeletonUnit(DWARFUnit *dwo_unit) {
  return DebugInfo().GetSkeletonUnit(dwo_unit);
}

std::shared_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
    DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
  // If this is a Darwin-style debug map (non-.dSYM) symbol file,
  // never attempt to load ELF-style DWO files since the -gmodules
  // support uses the same DWO mechanism to specify full debug info
  // files for modules. This is handled in
  // UpdateExternalModuleListIfNeeded().
  if (GetDebugMapSymfile())
    return nullptr;

  DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit);
  // Only compile units can be split into two parts and we should only
  // look for a DWO file if there is a valid DWO ID.
  if (!dwarf_cu || !dwarf_cu->GetDWOId().has_value())
    return nullptr;

  const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
  if (!dwo_name) {
    unit.SetDwoError(Status::FromErrorStringWithFormatv(
        "missing DWO name in skeleton DIE {0:x16}", cu_die.GetOffset()));
    return nullptr;
  }

  if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile())
    return dwp_sp;

  FileSpec dwo_file(dwo_name);
  FileSystem::Instance().Resolve(dwo_file);
  bool found = false;

  const FileSpecList &debug_file_search_paths =
      Target::GetDefaultDebugFileSearchPaths();
  size_t num_search_paths = debug_file_search_paths.GetSize();

  // It's relative, e.g. "foo.dwo", but we just to happen to be right next to
  // it. Or it's absolute.
  found = FileSystem::Instance().Exists(dwo_file);

  const char *comp_dir =
      cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr);
  if (!found) {
    // It could be a relative path that also uses DW_AT_COMP_DIR.
    if (comp_dir) {
      dwo_file.SetFile(comp_dir, FileSpec::Style::native);
      if (!dwo_file.IsRelative()) {
        FileSystem::Instance().Resolve(dwo_file);
        dwo_file.AppendPathComponent(dwo_name);
        found = FileSystem::Instance().Exists(dwo_file);
      } else {
        FileSpecList dwo_paths;

        // if DW_AT_comp_dir is relative, it should be relative to the location
        // of the executable, not to the location from which the debugger was
        // launched.
        FileSpec relative_to_binary = dwo_file;
        relative_to_binary.PrependPathComponent(
            m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
        FileSystem::Instance().Resolve(relative_to_binary);
        relative_to_binary.AppendPathComponent(dwo_name);
        dwo_paths.Append(relative_to_binary);

        // Or it's relative to one of the user specified debug directories.
        for (size_t idx = 0; idx < num_search_paths; ++idx) {
          FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
          dirspec.AppendPathComponent(comp_dir);
          FileSystem::Instance().Resolve(dirspec);
          if (!FileSystem::Instance().IsDirectory(dirspec))
            continue;

          dirspec.AppendPathComponent(dwo_name);
          dwo_paths.Append(dirspec);
        }

        size_t num_possible = dwo_paths.GetSize();
        for (size_t idx = 0; idx < num_possible && !found; ++idx) {
          FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
          if (FileSystem::Instance().Exists(dwo_spec)) {
            dwo_file = dwo_spec;
            found = true;
          }
        }
      }
    } else {
      Log *log = GetLog(LLDBLog::Symbols);
      LLDB_LOGF(log,
                "unable to locate relative .dwo debug file \"%s\" for "
                "skeleton DIE 0x%016" PRIx64 " without valid DW_AT_comp_dir "
                "attribute",
                dwo_name, cu_die.GetOffset());
    }
  }

  if (!found) {
    // Try adding the DW_AT_dwo_name ( e.g. "c/d/main-main.dwo"), and just the
    // filename ("main-main.dwo") to binary dir and search paths.
    FileSpecList dwo_paths;
    FileSpec dwo_name_spec(dwo_name);
    llvm::StringRef filename_only = dwo_name_spec.GetFilename();

    FileSpec binary_directory(
        m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
    FileSystem::Instance().Resolve(binary_directory);

    if (dwo_name_spec.IsRelative()) {
      FileSpec dwo_name_binary_directory(binary_directory);
      dwo_name_binary_directory.AppendPathComponent(dwo_name);
      dwo_paths.Append(dwo_name_binary_directory);
    }

    FileSpec filename_binary_directory(binary_directory);
    filename_binary_directory.AppendPathComponent(filename_only);
    dwo_paths.Append(filename_binary_directory);

    for (size_t idx = 0; idx < num_search_paths; ++idx) {
      FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
      FileSystem::Instance().Resolve(dirspec);
      if (!FileSystem::Instance().IsDirectory(dirspec))
        continue;

      FileSpec dwo_name_dirspec(dirspec);
      dwo_name_dirspec.AppendPathComponent(dwo_name);
      dwo_paths.Append(dwo_name_dirspec);

      FileSpec filename_dirspec(dirspec);
      filename_dirspec.AppendPathComponent(filename_only);
      dwo_paths.Append(filename_dirspec);
    }

    size_t num_possible = dwo_paths.GetSize();
    for (size_t idx = 0; idx < num_possible && !found; ++idx) {
      FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
      if (FileSystem::Instance().Exists(dwo_spec)) {
        dwo_file = dwo_spec;
        found = true;
      }
    }
  }

  if (!found) {
    FileSpec error_dwo_path(dwo_name);
    FileSystem::Instance().Resolve(error_dwo_path);
    if (error_dwo_path.IsRelative() && comp_dir != nullptr) {
      error_dwo_path.PrependPathComponent(comp_dir);
      FileSystem::Instance().Resolve(error_dwo_path);
    }
    unit.SetDwoError(Status::FromErrorStringWithFormatv(
        "unable to locate .dwo debug file \"{0}\" for skeleton DIE "
        "{1:x16}",
        error_dwo_path.GetPath().c_str(), cu_die.GetOffset()));

    if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) {
      GetObjectFile()->GetModule()->ReportWarning(
          "unable to locate separate debug file (dwo, dwp). Debugging will be "
          "degraded");
    }
    return nullptr;
  }

  const lldb::offset_t file_offset = 0;
  DataExtractorSP dwo_file_extractor_sp;
  lldb::offset_t dwo_file_data_offset = 0;
  ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(
      GetObjectFile()->GetModule(), &dwo_file, file_offset,
      FileSystem::Instance().GetByteSize(dwo_file), dwo_file_extractor_sp,
      dwo_file_data_offset);
  if (dwo_obj_file == nullptr) {
    unit.SetDwoError(Status::FromErrorStringWithFormatv(
        "unable to load object file for .dwo debug file \"{0}\" for "
        "unit DIE {1:x16}",
        dwo_name, cu_die.GetOffset()));
    return nullptr;
  }

  return std::make_shared<SymbolFileDWARFDwo>(*this, dwo_obj_file,
                                              dwarf_cu->GetID());
}

void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
  if (m_fetched_external_modules)
    return;
  m_fetched_external_modules = true;
  DWARFDebugInfo &debug_info = DebugInfo();

  // Follow DWO skeleton unit breadcrumbs.
  const uint32_t num_compile_units = GetNumCompileUnits();
  for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
    auto *dwarf_cu =
        llvm::dyn_cast<DWARFCompileUnit>(debug_info.GetUnitAtIndex(cu_idx));
    if (!dwarf_cu)
      continue;

    const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
    if (!die || die.HasChildren() || !die.GetDIE())
      continue;

    const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
    if (!name)
      continue;

    ConstString const_name(name);
    ModuleSP &module_sp = m_external_type_modules[const_name];
    if (module_sp)
      continue;

    const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
    if (!dwo_path)
      continue;

    ModuleSpec dwo_module_spec;
    dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native);
    if (dwo_module_spec.GetFileSpec().IsRelative()) {
      const char *comp_dir =
          die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
      if (comp_dir) {
        dwo_module_spec.GetFileSpec().SetFile(comp_dir,
                                              FileSpec::Style::native);
        FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
        dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
      }
    }
    dwo_module_spec.GetArchitecture() =
        m_objfile_sp->GetModule()->GetArchitecture();

    // When LLDB loads "external" modules it looks at the presence of
    // DW_AT_dwo_name. However, when the already created module
    // (corresponding to .dwo itself) is being processed, it will see
    // the presence of DW_AT_dwo_name (which contains the name of dwo
    // file) and will try to call ModuleList::GetSharedModule
    // again. In some cases (i.e., for empty files) Clang 4.0
    // generates a *.dwo file which has DW_AT_dwo_name, but no
    // DW_AT_comp_dir. In this case the method
    // ModuleList::GetSharedModule will fail and the warning will be
    // printed. However, as one can notice in this case we don't
    // actually need to try to load the already loaded module
    // (corresponding to .dwo) so we simply skip it.
    if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
        llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
            .ends_with(dwo_module_spec.GetFileSpec().GetPath())) {
      continue;
    }

    Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
                                               nullptr, nullptr);
    if (!module_sp) {
      // ReportWarning also rate-limits based on the warning string,
      // but in a -gmodules build, each object file has a similar DAG
      // of module dependencies that would all be listed here.
      GetObjectFile()->GetModule()->ReportWarning(
          "{0}", error.AsCString("unknown error"));
      GetObjectFile()->GetModule()->ReportWarning(
          "unable to locate module needed for external types.\n"
          "Debugging will be degraded due to missing types. Rebuilding the "
          "project will regenerate the needed module files");
      continue;
    }

    // Verify the DWO hash.
    // FIXME: Technically "0" is a valid hash.
    std::optional<uint64_t> dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE());
    if (!dwo_id)
      continue;

    auto *dwo_symfile =
        llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile());
    if (!dwo_symfile)
      continue;
    std::optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
    if (!dwo_dwo_id)
      continue;

    if (dwo_id != dwo_dwo_id) {
      GetObjectFile()->GetModule()->ReportWarning(
          "module {0} is out-of-date (hash mismatch).\n"
          "Type information from this module may be incomplete or inconsistent "
          "with the rest of the program. Rebuilding the project will "
          "regenerate the needed module files",
          dwo_module_spec.GetFileSpec().GetPath());
    }
  }
}

SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
  if (!m_global_aranges_up) {
    m_global_aranges_up = std::make_unique<GlobalVariableMap>();

    ModuleSP module_sp = GetObjectFile()->GetModule();
    if (module_sp) {
      const size_t num_cus = module_sp->GetNumCompileUnits();
      for (size_t i = 0; i < num_cus; ++i) {
        CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i);
        if (cu_sp) {
          VariableListSP globals_sp = cu_sp->GetVariableList(true);
          if (globals_sp) {
            const size_t num_globals = globals_sp->GetSize();
            for (size_t g = 0; g < num_globals; ++g) {
              VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
              if (var_sp && !var_sp->GetLocationIsConstantValueData()) {
                const DWARFExpressionList &location =
                    var_sp->LocationExpressionList();
                ExecutionContext exe_ctx;
                llvm::Expected<Value> location_result = location.Evaluate(
                    &exe_ctx, nullptr, LLDB_INVALID_ADDRESS, nullptr, nullptr);
                if (location_result) {
                  if (location_result->GetValueType() ==
                      Value::ValueType::FileAddress) {
                    lldb::addr_t file_addr =
                        location_result->GetScalar().ULongLong();
                    lldb::addr_t byte_size = 1;
                    if (var_sp->GetType())
                      byte_size = llvm::expectedToOptional(
                                      var_sp->GetType()->GetByteSize(nullptr))
                                      .value_or(0);
                    m_global_aranges_up->Append(GlobalVariableMap::Entry(
                        file_addr, byte_size, var_sp.get()));
                  }
                } else {
                  LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols),
                                 location_result.takeError(),
                                 "location expression failed to execute: {0}");
                }
              }
            }
          }
        }
      }
    }
    m_global_aranges_up->Sort();
  }
  return *m_global_aranges_up;
}

void SymbolFileDWARF::ResolveFunctionAndBlock(lldb::addr_t file_vm_addr,
                                              bool lookup_block,
                                              SymbolContext &sc) {
  assert(sc.comp_unit);
  DWARFCompileUnit &cu =
      GetDWARFCompileUnit(sc.comp_unit)->GetNonSkeletonUnit();
  DWARFDIE function_die = cu.LookupAddress(file_vm_addr);
  DWARFDIE block_die;
  if (function_die) {
    sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get();
    if (sc.function == nullptr)
      sc.function = ParseFunction(*sc.comp_unit, function_die);

    if (sc.function && lookup_block)
      block_die = function_die.LookupDeepestBlock(file_vm_addr);
  }

  if (!sc.function || !lookup_block)
    return;

  Block &block = sc.function->GetBlock(true);
  if (block_die)
    sc.block = block.FindBlockByID(block_die.GetID());
  else
    sc.block = block.FindBlockByID(function_die.GetID());
}

uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
                                               SymbolContextItem resolve_scope,
                                               SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  LLDB_SCOPED_TIMERF("SymbolFileDWARF::"
                     "ResolveSymbolContext (so_addr = { "
                     "section = %p, offset = 0x%" PRIx64
                     " }, resolve_scope = 0x%8.8x)",
                     static_cast<void *>(so_addr.GetSection().get()),
                     so_addr.GetOffset(), resolve_scope);
  uint32_t resolved = 0;
  if (resolve_scope &
      (eSymbolContextCompUnit | eSymbolContextFunction | eSymbolContextBlock |
       eSymbolContextLineEntry | eSymbolContextVariable)) {
    lldb::addr_t file_vm_addr = so_addr.GetFileAddress();

    DWARFDebugInfo &debug_info = DebugInfo();
    const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges();
    const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr);
    if (cu_offset == DW_INVALID_OFFSET) {
      // Global variables are not in the compile unit address ranges. The only
      // way to currently find global variables is to iterate over the
      // .debug_pubnames or the __apple_names table and find all items in there
      // that point to DW_TAG_variable DIEs and then find the address that
      // matches.
      if (resolve_scope & eSymbolContextVariable) {
        GlobalVariableMap &map = GetGlobalAranges();
        const GlobalVariableMap::Entry *entry =
            map.FindEntryThatContains(file_vm_addr);
        if (entry && entry->data) {
          Variable *variable = entry->data;
          SymbolContextScope *scc = variable->GetSymbolContextScope();
          if (scc) {
            scc->CalculateSymbolContext(&sc);
            sc.variable = variable;
          }
          return sc.GetResolvedMask();
        }
      }
    } else {
      uint32_t cu_idx = DW_INVALID_INDEX;
      if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
              debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, cu_offset,
                                         &cu_idx))) {
        sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
        if (sc.comp_unit) {
          resolved |= eSymbolContextCompUnit;

          bool force_check_line_table = false;
          if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
            ResolveFunctionAndBlock(file_vm_addr,
                                    resolve_scope & eSymbolContextBlock, sc);
            if (sc.function)
              resolved |= eSymbolContextFunction;
            else {
              // We might have had a compile unit that had discontiguous address
              // ranges where the gaps are symbols that don't have any debug
              // info. Discontiguous compile unit address ranges should only
              // happen when there aren't other functions from other compile
              // units in these gaps. This helps keep the size of the aranges
              // down.
              force_check_line_table = true;
            }
            if (sc.block)
              resolved |= eSymbolContextBlock;
          }

          if ((resolve_scope & eSymbolContextLineEntry) ||
              force_check_line_table) {
            LineTable *line_table = sc.comp_unit->GetLineTable();
            if (line_table != nullptr) {
              // And address that makes it into this function should be in terms
              // of this debug file if there is no debug map, or it will be an
              // address in the .o file which needs to be fixed up to be in
              // terms of the debug map executable. Either way, calling
              // FixupAddress() will work for us.
              Address exe_so_addr(so_addr);
              if (FixupAddress(exe_so_addr)) {
                if (line_table->FindLineEntryByAddress(exe_so_addr,
                                                       sc.line_entry)) {
                  resolved |= eSymbolContextLineEntry;
                }
              }
            }
          }

          if (force_check_line_table && !(resolved & eSymbolContextLineEntry)) {
            // We might have had a compile unit that had discontiguous address
            // ranges where the gaps are symbols that don't have any debug info.
            // Discontiguous compile unit address ranges should only happen when
            // there aren't other functions from other compile units in these
            // gaps. This helps keep the size of the aranges down.
            sc.comp_unit = nullptr;
            resolved &= ~eSymbolContextCompUnit;
          }
        } else {
          GetObjectFile()->GetModule()->ReportWarning(
              "{0:x16}: compile unit {1} failed to create a valid "
              "lldb_private::CompileUnit class",
              cu_offset, cu_idx);
        }
      }
    }
  }
  return resolved;
}

uint32_t SymbolFileDWARF::ResolveSymbolContext(
    const SourceLocationSpec &src_location_spec,
    SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  const bool check_inlines = src_location_spec.GetCheckInlines();
  const uint32_t prev_size = sc_list.GetSize();
  if (resolve_scope & eSymbolContextCompUnit) {
    for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
         ++cu_idx) {
      CompileUnit *dc_cu = ParseCompileUnitAtIndex(cu_idx).get();
      if (!dc_cu)
        continue;

      bool file_spec_matches_cu_file_spec = FileSpec::Match(
          src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile());
      if (check_inlines || file_spec_matches_cu_file_spec) {
        dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
        if (!check_inlines)
          break;
      }
    }
  }
  return sc_list.GetSize() - prev_size;
}

void SymbolFileDWARF::PreloadSymbols() {
  // Get the symbol table for the symbol file prior to taking the module lock
  // so that it is available without needing to take the module lock. The DWARF
  // indexing might end up needing to relocate items when DWARF sections are
  // loaded as they might end up getting the section contents which can call
  // ObjectFileELF::RelocateSection() which in turn will ask for the symbol
  // table and can cause deadlocks.
  GetSymtab();
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  m_index->Preload();
}

std::recursive_mutex &SymbolFileDWARF::GetModuleMutex() const {
  lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
  if (module_sp)
    return module_sp->GetMutex();
  return GetObjectFile()->GetModule()->GetMutex();
}

bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
    const lldb_private::CompilerDeclContext &decl_ctx) {
  if (!decl_ctx.IsValid()) {
    // Invalid namespace decl which means we aren't matching only things in
    // this symbol file, so return true to indicate it matches this symbol
    // file.
    return true;
  }

  TypeSystem *decl_ctx_type_system = decl_ctx.GetTypeSystem();
  auto type_system_or_err = GetTypeSystemForLanguage(
      decl_ctx_type_system->GetMinimumLanguage(nullptr));
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Unable to match namespace decl using TypeSystem: {0}");
    return false;
  }

  if (decl_ctx_type_system == type_system_or_err->get())
    return true; // The type systems match, return true

  // The namespace AST was valid, and it does not match...
  Log *log = GetLog(DWARFLog::Lookups);

  if (log)
    GetObjectFile()->GetModule()->LogMessage(
        log, "Valid namespace does not match symbol file");

  return false;
}

void SymbolFileDWARF::FindGlobalVariables(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    uint32_t max_matches, VariableList &variables) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  Log *log = GetLog(DWARFLog::Lookups);

  if (log)
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", "
        "parent_decl_ctx={1:p}, max_matches={2}, variables)",
        name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
        max_matches);

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return;

  // Remember how many variables are in the list before we search.
  const uint32_t original_size = variables.GetSize();

  llvm::StringRef basename;
  llvm::StringRef context;
  bool name_is_mangled = Mangled::GetManglingScheme(name.GetStringRef()) !=
                         Mangled::eManglingSchemeNone;

  if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetStringRef(),
                                                      context, basename))
    basename = name.GetStringRef();

  // Loop invariant: Variables up to this index have been checked for context
  // matches.
  uint32_t pruned_idx = original_size;

  SymbolContext sc;
  m_index->GetGlobalVariables(ConstString(basename), [&](DWARFDIE die) {
    if (!sc.module_sp)
      sc.module_sp = m_objfile_sp->GetModule();
    assert(sc.module_sp);

    if (die.Tag() != DW_TAG_variable && die.Tag() != DW_TAG_member)
      return IterationAction::Continue;

    auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
    if (!dwarf_cu)
      return IterationAction::Continue;
    sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);

    if (parent_decl_ctx) {
      if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) {
        CompilerDeclContext actual_parent_decl_ctx =
            dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);

        /// If the actual namespace is inline (i.e., had a DW_AT_export_symbols)
        /// and a child (possibly through other layers of inline namespaces)
        /// of the namespace referred to by 'basename', allow the lookup to
        /// succeed.
        if (!actual_parent_decl_ctx ||
            (actual_parent_decl_ctx != parent_decl_ctx &&
             !parent_decl_ctx.IsContainedInLookup(actual_parent_decl_ctx)))
          return IterationAction::Continue;
      }
    }

    ParseAndAppendGlobalVariable(sc, die, variables);
    while (pruned_idx < variables.GetSize()) {
      VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx);
      if (name_is_mangled ||
          var_sp->GetName().GetStringRef().contains(name.GetStringRef()))
        ++pruned_idx;
      else
        variables.RemoveVariableAtIndex(pruned_idx);
    }

    if (variables.GetSize() - original_size < max_matches)
      return IterationAction::Continue;

    return IterationAction::Stop;
  });

  // Return the number of variable that were appended to the list
  const uint32_t num_matches = variables.GetSize() - original_size;
  if (log && num_matches > 0) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", "
        "parent_decl_ctx={1:p}, max_matches={2}, variables) => {3}",
        name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
        max_matches, num_matches);
  }
}

void SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
                                          uint32_t max_matches,
                                          VariableList &variables) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  Log *log = GetLog(DWARFLog::Lookups);

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindGlobalVariables (regex=\"{0}\", "
        "max_matches={1}, variables)",
        regex.GetText().str().c_str(), max_matches);
  }

  // Remember how many variables are in the list before we search.
  const uint32_t original_size = variables.GetSize();

  SymbolContext sc;
  m_index->GetGlobalVariables(regex, [&](DWARFDIE die) {
    if (!sc.module_sp)
      sc.module_sp = m_objfile_sp->GetModule();
    assert(sc.module_sp);

    DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
    if (!dwarf_cu)
      return IterationAction::Continue;
    sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);

    ParseAndAppendGlobalVariable(sc, die, variables);

    if (variables.GetSize() - original_size < max_matches)
      return IterationAction::Continue;

    return IterationAction::Stop;
  });
}

bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
                                      bool include_inlines,
                                      SymbolContextList &sc_list) {
  SymbolContext sc;

  if (!orig_die)
    return false;

  // If we were passed a die that is not a function, just return false...
  if (!(orig_die.Tag() == DW_TAG_subprogram ||
        (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine)))
    return false;

  DWARFDIE die = orig_die;
  DWARFDIE inlined_die;
  if (die.Tag() == DW_TAG_inlined_subroutine) {
    inlined_die = die;

    while (true) {
      die = die.GetParent();

      if (die) {
        if (die.Tag() == DW_TAG_subprogram)
          break;
      } else
        break;
    }
  }
  assert(die && die.Tag() == DW_TAG_subprogram);
  if (GetFunction(die, sc)) {
    // Parse all blocks if needed
    if (inlined_die) {
      Block &function_block = sc.function->GetBlock(true);
      sc.block = function_block.FindBlockByID(inlined_die.GetID());
      if (sc.block == nullptr)
        sc.block = function_block.FindBlockByID(inlined_die.GetOffset());
    }

    sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/true);
    return true;
  }

  return false;
}

static llvm::StringRef ClangToItaniumCtorKind(clang::CXXCtorType kind) {
  switch (kind) {
  case clang::CXXCtorType::Ctor_Complete:
    return "C1";
  case clang::CXXCtorType::Ctor_Base:
    return "C2";
  case clang::CXXCtorType::Ctor_Unified:
    return "C4";
  case clang::CXXCtorType::Ctor_CopyingClosure:
  case clang::CXXCtorType::Ctor_DefaultClosure:
  case clang::CXXCtorType::Ctor_Comdat:
    llvm_unreachable("Unexpected constructor kind.");
  }
  llvm_unreachable("Fully covered switch above");
}

static llvm::StringRef ClangToItaniumDtorKind(clang::CXXDtorType kind) {
  switch (kind) {
  case clang::CXXDtorType::Dtor_Deleting:
    return "D0";
  case clang::CXXDtorType::Dtor_Complete:
    return "D1";
  case clang::CXXDtorType::Dtor_Base:
    return "D2";
  case clang::CXXDtorType::Dtor_Unified:
    return "D4";
  case clang::CXXDtorType::Dtor_Comdat:
  case clang::CXXDtorType::Dtor_VectorDeleting:
    llvm_unreachable("Unexpected destructor kind.");
  }
  llvm_unreachable("Fully covered switch above");
}

static llvm::StringRef
GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
  const bool is_ctor = discriminator.consume_front("C");
  if (!is_ctor && !discriminator.consume_front("D"))
    return {};

  uint64_t structor_kind;
  if (!llvm::to_integer(discriminator, structor_kind))
    return {};

  if (is_ctor) {
    if (structor_kind > clang::CXXCtorType::Ctor_Unified)
      return {};

    return ClangToItaniumCtorKind(
        static_cast<clang::CXXCtorType>(structor_kind));
  }

  if (structor_kind > clang::CXXDtorType::Dtor_Unified)
    return {};

  return ClangToItaniumDtorKind(static_cast<clang::CXXDtorType>(structor_kind));
}

llvm::Expected<DWARFDIE>
SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label,
                                        const DWARFDIE &declaration) {
  auto do_lookup = [this](llvm::StringRef lookup_name) -> DWARFDIE {
    DWARFDIE found;
    auto lookup_infos = Module::LookupInfo::MakeLookupInfos(
        ConstString(lookup_name), lldb::eFunctionNameTypeFull,
        lldb::eLanguageTypeUnknown);

    m_index->GetFunctions(lookup_infos, *this, {}, [&](DWARFDIE entry) {
      if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
        return IterationAction::Continue;

      found = entry;
      return IterationAction::Stop;
    });

    return found;
  };

  DWARFDIE definition = do_lookup(label.lookup_name);
  if (definition.IsValid())
    return definition;

  // This is not a structor lookup. Nothing else to be done here.
  if (label.discriminator.empty())
    return llvm::createStringError(
        "no definition DIE found in this SymbolFile");

  // We're doing a structor lookup. Maybe we didn't find the structor variant
  // because the complete object structor was aliased to the base object
  // structor. Try finding the alias instead.
  //
  // TODO: there are other reasons for why a subprogram definition might be
  // missing. Ideally DWARF would tell us more details about which structor
  // variant a DIE corresponds to and whether it's an alias.
  auto subst_or_err =
      CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle(
          label.lookup_name);
  if (!subst_or_err)
    return subst_or_err.takeError();

  definition = do_lookup(*subst_or_err);

  if (!definition.IsValid())
    return llvm::createStringError(
        "failed to find definition DIE for structor alias in fallback lookup");

  return definition;
}

llvm::Expected<SymbolContext>
SymbolFileDWARF::ResolveFunctionCallLabel(FunctionCallLabel &label) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());

  if (!label.discriminator.empty()) {
    llvm::StringRef from = label.discriminator[0] == 'C' ? "C4" : "D4";

    llvm::StringRef variant = GetItaniumCtorDtorVariant(label.discriminator);
    if (variant.empty())
      return llvm::createStringError(
          "failed to get Itanium variant for discriminator");

    if (from == variant)
      return llvm::createStringError(
          "tried substituting unified structor variant into label");

    // If we failed to substitute unified mangled name, don't try to do a lookup
    // using the unified name because there may be multiple definitions for it
    // in the index, and we wouldn't know which one to choose.
    auto subst_or_err = CPlusPlusLanguage::SubstituteStructor_ItaniumMangle(
        label.lookup_name, from, variant);
    if (!subst_or_err)
      return llvm::joinErrors(
          llvm::createStringErrorV(
              "failed to substitute {0} for {1} in mangled name {2}:", from,
              variant, label.lookup_name),
          subst_or_err.takeError());

    if (!*subst_or_err)
      return llvm::createStringErrorV(
          "got invalid substituted mangled named (substituted "
          "{0} for {1} in mangled name {2})",
          from, variant, label.lookup_name);

    label.lookup_name = subst_or_err->GetStringRef();
  }

  DWARFDIE die = GetDIE(label.symbol_id);
  if (!die.IsValid())
    return llvm::createStringErrorV("invalid DIE ID in {0}", label);

  // Label was created using a declaration DIE. Need to fetch the definition
  // to resolve the function call.
  if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) {
    auto die_or_err = FindFunctionDefinition(label, die);
    if (!die_or_err)
      return llvm::joinErrors(
          llvm::createStringError("failed to find definition DIE:"),
          die_or_err.takeError());

    die = std::move(*die_or_err);
  }

  SymbolContextList sc_list;
  if (!ResolveFunction(die, /*include_inlines=*/false, sc_list))
    return llvm::createStringError("failed to resolve function");

  if (sc_list.IsEmpty())
    return llvm::createStringError("failed to find function");

  assert(sc_list.GetSize() == 1);

  return sc_list[0];
}

bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
                                       const DWARFDIE &die,
                                       bool only_root_namespaces) {
  // If we have no parent decl context to match this DIE matches, and if the
  // parent decl context isn't valid, we aren't trying to look for any
  // particular decl context so any die matches.
  if (!decl_ctx.IsValid()) {
    // ...But if we are only checking root decl contexts, confirm that the
    // 'die' is a top-level context.
    if (only_root_namespaces)
      return die.GetParent().Tag() == llvm::dwarf::DW_TAG_compile_unit;

    return true;
  }

  if (die) {
    if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) {
      if (CompilerDeclContext actual_decl_ctx =
              dwarf_ast->GetDeclContextContainingUIDFromDWARF(die))
        return decl_ctx.IsContainedInLookup(actual_decl_ctx);
    }
  }
  return false;
}

void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
                                    const CompilerDeclContext &parent_decl_ctx,
                                    bool include_inlines,
                                    SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  ConstString name = lookup_info.GetLookupName();
  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();

  // eFunctionNameTypeAuto should be pre-resolved by a call to
  // Module::LookupInfo::LookupInfo()
  assert((name_type_mask & eFunctionNameTypeAuto) == 0);

  Log *log = GetLog(DWARFLog::Lookups);

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindFunctions (name=\"{0}\", name_type_mask={1:x}, "
        "sc_list)",
        name.GetCString(), name_type_mask);
  }

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return;

  // If name is empty then we won't find anything.
  if (name.IsEmpty())
    return;

  // Remember how many sc_list are in the list before we search in case we are
  // appending the results to a variable list.

  const uint32_t original_size = sc_list.GetSize();

  llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;

  m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
    if (resolved_dies.insert(die.GetDIE()).second)
      ResolveFunction(die, include_inlines, sc_list);
    return IterationAction::Continue;
  });
  // With -gsimple-template-names, a templated type's DW_AT_name will not
  // contain the template parameters. Try again stripping '<' and anything
  // after, filtering out entries with template parameters that don't match.
  {
    const llvm::StringRef name_ref = name.GetStringRef();
    auto it = name_ref.find('<');
    if (it != llvm::StringRef::npos) {
      const llvm::StringRef name_no_template_params = name_ref.slice(0, it);

      Module::LookupInfo no_tp_lookup_info(
          lookup_info, ConstString(name_no_template_params));
      m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx,
                            [&](DWARFDIE die) {
                              if (resolved_dies.insert(die.GetDIE()).second)
                                ResolveFunction(die, include_inlines, sc_list);
                              return IterationAction::Continue;
                            });
    }
  }

  // Return the number of variable that were appended to the list
  const uint32_t num_matches = sc_list.GetSize() - original_size;

  if (log && num_matches > 0) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindFunctions (name=\"{0}\", "
        "name_type_mask={1:x}, include_inlines={2:d}, sc_list) => {3}",
        name.GetCString(), name_type_mask, include_inlines, num_matches);
  }
}

void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
                                    bool include_inlines,
                                    SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  LLDB_SCOPED_TIMERF("SymbolFileDWARF::FindFunctions (regex = '%s')",
                     regex.GetText().str().c_str());

  Log *log = GetLog(DWARFLog::Lookups);

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log, "SymbolFileDWARF::FindFunctions (regex=\"{0}\", sc_list)",
        regex.GetText().str().c_str());
  }

  llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
  m_index->GetFunctions(regex, [&](DWARFDIE die) {
    if (resolved_dies.insert(die.GetDIE()).second)
      ResolveFunction(die, include_inlines, sc_list);
    return IterationAction::Continue;
  });
}

void SymbolFileDWARF::GetMangledNamesForFunction(
    const std::string &scope_qualified_name,
    std::vector<ConstString> &mangled_names) {
  DWARFDebugInfo &info = DebugInfo();
  uint32_t num_comp_units = info.GetNumUnits();
  for (uint32_t i = 0; i < num_comp_units; i++) {
    DWARFUnit *cu = info.GetUnitAtIndex(i);
    if (cu == nullptr)
      continue;

    SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
    if (dwo)
      dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names);
  }

  for (DIERef die_ref :
       m_function_scope_qualified_name_map.lookup(scope_qualified_name)) {
    DWARFDIE die = GetDIE(die_ref);
    mangled_names.push_back(ConstString(die.GetMangledName()));
  }
}

/// Split a name up into a basename and template parameters.
static bool SplitTemplateParams(llvm::StringRef fullname,
                                llvm::StringRef &basename,
                                llvm::StringRef &template_params) {
  auto it = fullname.find('<');
  if (it == llvm::StringRef::npos) {
    basename = fullname;
    template_params = llvm::StringRef();
    return false;
  }
  basename = fullname.slice(0, it);
  template_params = fullname.slice(it, fullname.size());
  return true;
}

static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) {
  // We need to find any names in the context that have template parameters
  // and strip them so the context can be matched when -gsimple-template-names
  // is being used. Returns true if any of the context items were updated.
  bool any_context_updated = false;
  for (auto &context : match.GetContextRef()) {
    llvm::StringRef basename, params;
    if (SplitTemplateParams(context.name.GetStringRef(), basename, params)) {
      context.name = ConstString(basename);
      any_context_updated = true;
    }
  }
  return any_context_updated;
}

uint64_t SymbolFileDWARF::GetDebugInfoSize(bool load_all_debug_info) {
  DWARFDebugInfo &info = DebugInfo();
  uint32_t num_comp_units = info.GetNumUnits();

  uint64_t debug_info_size = SymbolFileCommon::GetDebugInfoSize();
  // In dwp scenario, debug info == skeleton debug info + dwp debug info.
  if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile())
    return debug_info_size + dwp_sp->GetDebugInfoSize();

  // In dwo scenario, debug info == skeleton debug info + all dwo debug info.
  for (uint32_t i = 0; i < num_comp_units; i++) {
    DWARFUnit *cu = info.GetUnitAtIndex(i);
    if (cu == nullptr)
      continue;

    SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile(load_all_debug_info);
    if (dwo)
      debug_info_size += dwo->GetDebugInfoSize();
  }
  return debug_info_size;
}

void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {

  // Make sure we haven't already searched this SymbolFile before.
  if (results.AlreadySearched(this))
    return;

  auto type_basename = query.GetTypeBasename();

  Log *log = GetLog(DWARFLog::Lookups);
  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log, "SymbolFileDWARF::FindTypes(type_basename=\"{0}\")",
        type_basename);
  }

  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());

  TypeQuery query_full(query);
  bool have_index_match = false;
  m_index->GetTypesWithQuery(query_full, [&](DWARFDIE die) {
    if (Type *matching_type = ResolveType(die, true, true)) {
      if (!query.GetSearchByMangledName() && matching_type->IsTemplateType()) {
        // We have to watch out for case where we lookup a type by basename and
        // it matches a template with simple template names. Like looking up
        // "Foo" and if we have simple template names then we will match
        // "Foo<int>" and "Foo<double>" because all the DWARF has is "Foo" in
        // the accelerator tables. The main case we see this in is when the
        // expression parser is trying to parse "Foo<int>" and it will first do
        // a lookup on just "Foo". We verify the type basename matches before
        // inserting the type in the results.
        auto CompilerTypeBasename =
            matching_type->GetForwardCompilerType().GetTypeName(true);
        if (CompilerTypeBasename != query.GetTypeBasename())
          return IterationAction::Continue;
      }
      have_index_match = true;
      results.InsertUnique(matching_type->shared_from_this());
    }
    if (!results.Done(query))
      return IterationAction::Continue;

    return IterationAction::Stop;
  });

  if (results.Done(query)) {
    if (log) {
      GetObjectFile()->GetModule()->LogMessage(
          log, "SymbolFileDWARF::FindTypes(type_basename=\"{0}\") => {1}",
          type_basename, results.GetTypeMap().GetSize());
    }
    return;
  }

  // With -gsimple-template-names, a templated type's DW_AT_name will not
  // contain the template parameters. Try again stripping '<' and anything
  // after, filtering out entries with template parameters that don't match.
  if (!have_index_match && !query.GetSearchByMangledName()) {
    // Create a type matcher with a compiler context that is tuned for
    // -gsimple-template-names. We will use this for the index lookup and the
    // context matching, but will use the original "match" to insert matches
    // into if things match. The "match_simple" has a compiler context with
    // all template parameters removed to allow the names and context to match.
    // The UpdateCompilerContextForSimpleTemplateNames(...) will return true if
    // it trims any context items down by removing template parameter names.
    TypeQuery query_simple(query);
    if (UpdateCompilerContextForSimpleTemplateNames(query_simple)) {
      auto type_basename_simple = query_simple.GetTypeBasename();
      // Copy our match's context and update the basename we are looking for
      // so we can use this only to compare the context correctly.
      m_index->GetTypesWithQuery(query_simple, [&](DWARFDIE die) {
        std::vector<CompilerContext> qualified_context =
            query.GetModuleSearch()
                ? die.GetDeclContext(/*derive_template_names=*/true)
                : die.GetTypeLookupContext(/*derive_template_names=*/true);
        if (query.ContextMatches(qualified_context))
          if (Type *matching_type = ResolveType(die, true, true))
            results.InsertUnique(matching_type->shared_from_this());
        if (!results.Done(query))
          return IterationAction::Continue;

        return IterationAction::Stop;
      });
      if (results.Done(query)) {
        if (log) {
          GetObjectFile()->GetModule()->LogMessage(
              log,
              "SymbolFileDWARF::FindTypes(type_basename=\"{0}\") => {1} "
              "(simplified as \"{2}\")",
              type_basename, results.GetTypeMap().GetSize(),
              type_basename_simple);
        }
        return;
      }
    }
  }

  // Next search through the reachable Clang modules. This only applies for
  // DWARF objects compiled with -gmodules that haven't been processed by
  // dsymutil.
  UpdateExternalModuleListIfNeeded();

  for (const auto &pair : m_external_type_modules) {
    if (ModuleSP external_module_sp = pair.second) {
      external_module_sp->FindTypes(query, results);
      if (results.Done(query)) {
        // We don't log the results here as they are already logged in the
        // nested FindTypes call
        return;
      }
    }
  }
}

CompilerDeclContext
SymbolFileDWARF::FindNamespace(ConstString name,
                               const CompilerDeclContext &parent_decl_ctx,
                               bool only_root_namespaces) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  Log *log = GetLog(DWARFLog::Lookups);

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log, "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\")",
        name.GetCString());
  }

  CompilerDeclContext namespace_decl_ctx;

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return namespace_decl_ctx;

  m_index->GetNamespacesWithParents(name, parent_decl_ctx, [&](DWARFDIE die) {
    if (!DIEInDeclContext(parent_decl_ctx, die, only_root_namespaces))
      return IterationAction::Continue;

    DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU());
    if (!dwarf_ast)
      return IterationAction::Continue;

    namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die);
    if (namespace_decl_ctx.IsValid())
      return IterationAction::Stop;

    return IterationAction::Continue;
  });

  if (log && namespace_decl_ctx) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\") => "
        "CompilerDeclContext({1:p}/{2:p}) \"{3}\"",
        name.GetCString(),
        static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()),
        static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()),
        namespace_decl_ctx.GetName().AsCString("<NULL>"));
  }

  return namespace_decl_ctx;
}

TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die,
                                      bool resolve_function_context) {
  TypeSP type_sp;
  if (die) {
    Type *type_ptr = GetDIEToType().lookup(die.GetDIE());
    if (type_ptr == nullptr) {
      SymbolContextScope *scope;
      if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()))
        scope = GetCompUnitForDWARFCompUnit(*dwarf_cu);
      else
        scope = GetObjectFile()->GetModule().get();
      assert(scope);
      SymbolContext sc(scope);
      const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE();
      while (parent_die != nullptr) {
        if (parent_die->Tag() == DW_TAG_subprogram)
          break;
        parent_die = parent_die->GetParent();
      }
      SymbolContext sc_backup = sc;
      if (resolve_function_context && parent_die != nullptr &&
          !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc))
        sc = sc_backup;

      type_sp = ParseType(sc, die, nullptr);
    } else if (type_ptr != DIE_IS_BEING_PARSED) {
      // Get the original shared pointer for this type
      type_sp = type_ptr->shared_from_this();
    }
  }
  return type_sp;
}

DWARFDIE
SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) {
  if (orig_die) {
    DWARFDIE die = orig_die;

    while (die) {
      // If this is the original DIE that we are searching for a declaration
      // for, then don't look in the cache as we don't want our own decl
      // context to be our decl context...
      if (orig_die != die) {
        switch (die.Tag()) {
        case DW_TAG_compile_unit:
        case DW_TAG_partial_unit:
        case DW_TAG_namespace:
        case DW_TAG_structure_type:
        case DW_TAG_union_type:
        case DW_TAG_class_type:
        case DW_TAG_lexical_block:
        case DW_TAG_subprogram:
          return die;
        case DW_TAG_inlined_subroutine: {
          DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
          if (abs_die) {
            return abs_die;
          }
          break;
        }
        default:
          break;
        }
      }

      DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification);
      if (spec_die) {
        DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die);
        if (decl_ctx_die)
          return decl_ctx_die;
      }

      DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
      if (abs_die) {
        DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die);
        if (decl_ctx_die)
          return decl_ctx_die;
      }

      die = die.GetParent();
    }
  }
  return DWARFDIE();
}

Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) {
  Symbol *objc_class_symbol = nullptr;
  if (m_objfile_sp) {
    Symtab *symtab = m_objfile_sp->GetSymtab();
    if (symtab) {
      objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
          objc_class_name, eSymbolTypeObjCClass, Symtab::eDebugNo,
          Symtab::eVisibilityAny);
    }
  }
  return objc_class_symbol;
}

// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
    const DWARFDIE &die, ConstString type_name, bool must_be_implementation) {

  TypeSP type_sp;

  if (!type_name || (must_be_implementation && !GetObjCClassSymbol(type_name)))
    return type_sp;

  m_index->GetCompleteObjCClass(
      type_name, must_be_implementation, [&](DWARFDIE type_die) {
        // Don't try and resolve the DIE we are looking for with the DIE
        // itself!
        if (type_die == die || !IsStructOrClassTag(type_die.Tag()))
          return IterationAction::Continue;

        if (must_be_implementation) {
          const bool try_resolving_type = type_die.GetAttributeValueAsUnsigned(
              DW_AT_APPLE_objc_complete_type, 0);
          if (!try_resolving_type)
            return IterationAction::Continue;
        }

        Type *resolved_type = ResolveType(type_die, false, true);
        if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
          return IterationAction::Continue;

        DEBUG_PRINTF(
            "resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64
            " (cu 0x%8.8" PRIx64 ")\n",
            die.GetID(),
            m_objfile_sp->GetFileSpec().GetFilename().AsCString("<Unknown>"),
            type_die.GetID(), type_cu->GetID());

        if (die)
          GetDIEToType()[die.GetDIE()] = resolved_type;
        type_sp = resolved_type->shared_from_this();
        return IterationAction::Stop;
      });
  return type_sp;
}

DWARFDIE
SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
  const char *name = die.GetName();
  if (!name)
    return {};
  if (!die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
    return die;

  Progress progress(llvm::formatv(
      "Searching definition DIE in {0}: '{1}'",
      GetObjectFile()->GetFileSpec().GetFilename().GetString(), name));

  const dw_tag_t tag = die.Tag();

  Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindDefinitionDIE(tag={0} "
        "({1}), name='{2}')",
        DW_TAG_value_to_name(tag), tag, name);
  }

  // Get the type system that we are looking to find a type for. We will
  // use this to ensure any matches we find are in a language that this
  // type system supports
  const LanguageType language = GetLanguage(*die.GetCU());
  TypeSystemSP type_system = nullptr;
  if (language != eLanguageTypeUnknown) {
    auto type_system_or_err = GetTypeSystemForLanguage(language);
    if (auto err = type_system_or_err.takeError()) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Cannot get TypeSystem for language {1}: {0}",
                     Language::GetNameForLanguageType(language));
    } else {
      type_system = *type_system_or_err;
    }
  }

  // See comments below about -gsimple-template-names for why we attempt to
  // compute missing template parameter names.
  std::vector<std::string> template_params;
  DWARFDeclContext die_dwarf_decl_ctx;
  DWARFASTParser *dwarf_ast =
      type_system ? type_system->GetDWARFParser() : nullptr;
  for (DWARFDIE ctx_die = die; ctx_die && !isUnitType(ctx_die.Tag());
       ctx_die = ctx_die.GetParentDeclContextDIE()) {
    die_dwarf_decl_ctx.AppendDeclContext(ctx_die.Tag(), ctx_die.GetName());
    template_params.push_back(
        (ctx_die.IsStructUnionOrClass() && dwarf_ast)
            ? dwarf_ast->GetDIEClassTemplateParams(ctx_die)
            : "");
  }
  const bool any_template_params = llvm::any_of(
      template_params, [](llvm::StringRef p) { return !p.empty(); });

  auto die_matches = [&](DWARFDIE type_die) {
    // Resolve the type if both have the same tag or {class, struct} tags.
    const bool tag_matches =
        type_die.Tag() == tag ||
        (IsStructOrClassTag(type_die.Tag()) && IsStructOrClassTag(tag));
    if (!tag_matches)
      return false;
    if (any_template_params) {
      size_t pos = 0;
      for (DWARFDIE ctx_die = type_die; ctx_die && !isUnitType(ctx_die.Tag()) &&
                                        pos < template_params.size();
           ctx_die = ctx_die.GetParentDeclContextDIE(), ++pos) {
        if (template_params[pos].empty())
          continue;
        if (template_params[pos] !=
            dwarf_ast->GetDIEClassTemplateParams(ctx_die))
          return false;
      }
      if (pos != template_params.size())
        return false;
    }
    return true;
  };
  DWARFDIE result;
  m_index->GetFullyQualifiedType(die_dwarf_decl_ctx, [&](DWARFDIE type_die) {
    // Make sure type_die's language matches the type system we are
    // looking for. We don't want to find a "Foo" type from Java if we
    // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
    if (type_system &&
        !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU())))
      return IterationAction::Continue;

    if (!die_matches(type_die)) {
      if (log) {
        GetObjectFile()->GetModule()->LogMessage(
            log,
            "SymbolFileDWARF::FindDefinitionDIE(tag={0} ({1}), "
            "name='{2}') ignoring die={3:x16} ({4})",
            DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
            type_die.GetName());
      }
      return IterationAction::Continue;
    }

    if (log) {
      DWARFDeclContext type_dwarf_decl_ctx = type_die.GetDWARFDeclContext();
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindDefinitionTypeDIE(tag={0} ({1}), name='{2}') "
          "trying die={3:x16} ({4})",
          DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(),
          type_dwarf_decl_ctx.GetQualifiedName());
    }

    result = type_die;
    return IterationAction::Stop;
  });
  return result;
}

TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
                                  bool *type_is_new_ptr) {
  if (!die)
    return {};

  auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Unable to parse type: {0}");
    return {};
  }
  auto ts = *type_system_or_err;
  if (!ts)
    return {};

  DWARFASTParser *dwarf_ast = ts->GetDWARFParser();
  if (!dwarf_ast)
    return {};

  TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr);
  if (type_sp) {
    if (die.Tag() == DW_TAG_subprogram) {
      std::string scope_qualified_name(GetDeclContextForUID(die.GetID())
                                           .GetScopeQualifiedName()
                                           .AsCString(""));
      if (scope_qualified_name.size()) {
        m_function_scope_qualified_name_map[scope_qualified_name].insert(
            *die.GetDIERef());
      }
    }
  }

  return type_sp;
}

size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
                                   const DWARFDIE &orig_die,
                                   bool parse_siblings, bool parse_children) {
  size_t types_added = 0;
  DWARFDIE die = orig_die;

  while (die) {
    const dw_tag_t tag = die.Tag();
    bool type_is_new = false;

    Tag dwarf_tag = static_cast<Tag>(tag);

    // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...)
    // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or
    // not.
    if (isType(dwarf_tag) && tag != DW_TAG_subrange_type)
      ParseType(sc, die, &type_is_new);

    if (type_is_new)
      ++types_added;

    if (parse_children && die.HasChildren()) {
      if (die.Tag() == DW_TAG_subprogram) {
        SymbolContext child_sc(sc);
        child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
        types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true);
      } else
        types_added += ParseTypes(sc, die.GetFirstChild(), true, true);
    }

    if (parse_siblings)
      die = die.GetSibling();
    else
      die.Clear();
  }
  return types_added;
}

size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  CompileUnit *comp_unit = func.GetCompileUnit();
  lldbassert(comp_unit);

  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit);
  if (!dwarf_cu)
    return 0;

  size_t functions_added = 0;
  const dw_offset_t function_die_offset = DIERef(func.GetID()).die_offset();
  DWARFDIE function_die =
      dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset);
  if (function_die) {
    // We can't use the file address from the Function object as (in the OSO
    // case) it will already be remapped to the main module.
    if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
            function_die.GetDIE()->GetAttributeAddressRanges(
                function_die.GetCU(),
                /*check_hi_lo_pc=*/true)) {
      if (ranges->empty())
        return 0;
      dw_addr_t function_file_addr = ranges->begin()->LowPC;
      if (function_file_addr != LLDB_INVALID_ADDRESS)
        ParseBlocksRecursive(*comp_unit, &func.GetBlock(false),
                             function_die.GetFirstChild(), function_file_addr);
    } else {
      LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(),
                     "{1:x}: {0}", dwarf_cu->GetOffset());
    }
  }

  return functions_added;
}

size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  size_t types_added = 0;
  DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
  if (dwarf_cu) {
    DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
    if (dwarf_cu_die && dwarf_cu_die.HasChildren()) {
      SymbolContext sc;
      sc.comp_unit = &comp_unit;
      types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
    }
  }

  return types_added;
}

size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (sc.comp_unit != nullptr) {
    if (sc.function) {
      DWARFDIE function_die = GetDIE(sc.function->GetID());

      dw_addr_t func_lo_pc = LLDB_INVALID_ADDRESS;
      if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
              function_die.GetDIE()->GetAttributeAddressRanges(
                  function_die.GetCU(), /*check_hi_lo_pc=*/true)) {
        if (!ranges->empty())
          func_lo_pc = ranges->begin()->LowPC;
      } else {
        LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), ranges.takeError(),
                       "DIE({1:x}): {0}", function_die.GetID());
      }
      if (func_lo_pc != LLDB_INVALID_ADDRESS) {
        const size_t num_variables =
            ParseVariablesInFunctionContext(sc, function_die, func_lo_pc);

        // Let all blocks know they have parse all their variables
        sc.function->GetBlock(false).SetDidParseVariables(true, true);
        return num_variables;
      }
    } else if (sc.comp_unit) {
      DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(sc.comp_unit->GetID());

      if (dwarf_cu == nullptr)
        return 0;

      uint32_t vars_added = 0;
      VariableListSP variables(sc.comp_unit->GetVariableList(false));

      if (variables.get() == nullptr) {
        variables = std::make_shared<VariableList>();
        sc.comp_unit->SetVariableList(variables);

        m_index->GetGlobalVariables(*dwarf_cu, [&](DWARFDIE die) {
          VariableSP var_sp(ParseVariableDIECached(sc, die));
          if (var_sp) {
            variables->AddVariableIfUnique(var_sp);
            ++vars_added;
          }
          return IterationAction::Continue;
        });
      }
      return vars_added;
    }
  }
  return 0;
}

VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
                                                   const DWARFDIE &die) {
  if (!die)
    return nullptr;

  DIEToVariableSP &die_to_variable = die.GetDWARF()->GetDIEToVariable();

  VariableSP var_sp = die_to_variable[die.GetDIE()];
  if (var_sp)
    return var_sp;

  var_sp = ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS);
  if (var_sp) {
    die_to_variable[die.GetDIE()] = var_sp;
    if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification))
      die_to_variable[spec_die.GetDIE()] = var_sp;
  }
  return var_sp;
}

/// Creates a DWARFExpressionList from an DW_AT_location form_value.
static DWARFExpressionList GetExprListFromAtLocation(DWARFFormValue form_value,
                                                     ModuleSP module,
                                                     const DWARFDIE &die,
                                                     const addr_t func_low_pc) {
  if (DWARFFormValue::IsBlockForm(form_value.Form())) {
    const DWARFDataExtractor &data = die.GetData();

    uint64_t block_offset = form_value.BlockData() - data.GetDataStart();
    uint64_t block_length = form_value.Unsigned();
    return DWARFExpressionList(
        module, DataExtractor(data, block_offset, block_length), die.GetCU());
  }

  DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU());
  DataExtractor data = die.GetCU()->GetLocationData();
  dw_offset_t offset = form_value.Unsigned();
  if (form_value.Form() == DW_FORM_loclistx)
    offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1);
  if (data.ValidOffset(offset)) {
    data = DataExtractor(data, offset, data.GetByteSize() - offset);
    const DWARFUnit *dwarf_cu = form_value.GetUnit();
    if (dwarf_cu->ParseDWARFLocationList(data, location_list))
      location_list.SetFuncFileAddress(func_low_pc);
  }

  return location_list;
}

/// Creates a DWARFExpressionList from an DW_AT_const_value. This is either a
/// block form, or a string, or a data form. For data forms, this returns an
/// empty list, as we cannot initialize it properly without a SymbolFileType.
static DWARFExpressionList
GetExprListFromAtConstValue(DWARFFormValue form_value, ModuleSP module,
                            const DWARFDIE &die) {
  const DWARFDataExtractor &debug_info_data = die.GetData();
  if (DWARFFormValue::IsBlockForm(form_value.Form())) {
    // Retrieve the value as a block expression.
    uint64_t block_offset =
        form_value.BlockData() - debug_info_data.GetDataStart();
    uint64_t block_length = form_value.Unsigned();
    return DWARFExpressionList(
        module, DataExtractor(debug_info_data, block_offset, block_length),
        die.GetCU());
  }
  if (const char *str = form_value.AsCString())
    return DWARFExpressionList(module,
                               DataExtractor(str, strlen(str) + 1,
                                             die.GetCU()->GetByteOrder(),
                                             die.GetCU()->GetAddressByteSize()),
                               die.GetCU());
  return DWARFExpressionList(module, DWARFExpression(), die.GetCU());
}

/// Global variables that are not initialized may have their address set to
/// zero. Since multiple variables may have this address, we cannot apply the
/// OSO relink address approach we normally use.
/// However, the executable will have a matching symbol with a good address;
/// this function attempts to find the correct address by looking into the
/// executable's symbol table. If it succeeds, the expr_list is updated with
/// the new address and the executable's symbol is returned.
static Symbol *fixupExternalAddrZeroVariable(
    SymbolFileDWARFDebugMap &debug_map_symfile, llvm::StringRef name,
    DWARFExpressionList &expr_list, const DWARFDIE &die) {
  ObjectFile *debug_map_objfile = debug_map_symfile.GetObjectFile();
  if (!debug_map_objfile)
    return nullptr;

  Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
  if (!debug_map_symtab)
    return nullptr;
  Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType(
      ConstString(name), eSymbolTypeData, Symtab::eDebugYes,
      Symtab::eVisibilityExtern);
  if (!exe_symbol || !exe_symbol->ValueIsAddress())
    return nullptr;
  const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress();
  if (exe_file_addr == LLDB_INVALID_ADDRESS)
    return nullptr;

  DWARFExpression *location = expr_list.GetMutableExpressionAtAddress();
  if (location->Update_DW_OP_addr(die.GetCU(), exe_file_addr))
    return exe_symbol;
  return nullptr;
}

VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
                                             const DWARFDIE &die,
                                             const lldb::addr_t func_low_pc) {
  if (die.GetDWARF() != this)
    return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc);

  if (!die)
    return nullptr;

  const dw_tag_t tag = die.Tag();
  ModuleSP module = GetObjectFile()->GetModule();

  if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
      tag != DW_TAG_member && (tag != DW_TAG_formal_parameter || !sc.function))
    return nullptr;

  DWARFAttributes attributes = die.GetAttributes();
  const char *name = nullptr;
  const char *mangled = nullptr;
  Declaration decl;
  DWARFFormValue type_die_form;
  bool is_external = false;
  bool is_artificial = false;
  std::optional<uint64_t> tag_offset = std::nullopt;
  DWARFFormValue const_value_form, location_form;
  Variable::RangeList scope_ranges;

  for (size_t i = 0; i < attributes.Size(); ++i) {
    dw_attr_t attr = attributes.AttributeAtIndex(i);
    DWARFFormValue form_value;

    if (!attributes.ExtractFormValueAtIndex(i, form_value))
      continue;
    switch (attr) {
    case DW_AT_LLVM_tag_offset:
      tag_offset = form_value.Unsigned();
      break;
    case DW_AT_decl_file:
      decl.SetFile(
          attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
      break;
    case DW_AT_decl_line:
      decl.SetLine(form_value.Unsigned());
      break;
    case DW_AT_decl_column:
      decl.SetColumn(form_value.Unsigned());
      break;
    case DW_AT_name:
      name = form_value.AsCString();
      break;
    case DW_AT_linkage_name:
    case DW_AT_MIPS_linkage_name:
      mangled = form_value.AsCString();
      break;
    case DW_AT_type:
      // DW_AT_type on declaration may be less accurate than
      // that of definition, so don't overwrite it.
      if (!type_die_form.IsValid())
        type_die_form = form_value;
      break;
    case DW_AT_external:
      is_external = form_value.Boolean();
      break;
    case DW_AT_const_value:
      const_value_form = form_value;
      break;
    case DW_AT_location:
      location_form = form_value;
      break;
    case DW_AT_start_scope:
      // TODO: Implement this.
      break;
    case DW_AT_artificial:
      is_artificial = form_value.Boolean();
      break;
    case DW_AT_declaration:
    case DW_AT_description:
    case DW_AT_endianity:
    case DW_AT_segment:
    case DW_AT_specification:
    case DW_AT_visibility:
    default:
    case DW_AT_abstract_origin:
    case DW_AT_sibling:
      break;
    }
  }

  // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
  // for static constexpr member variables -- DW_AT_const_value and
  // DW_AT_location will both be present in the DIE defining the member.
  bool location_is_const_value_data =
      const_value_form.IsValid() && !location_form.IsValid();

  DWARFExpressionList location_list = [&] {
    if (location_form.IsValid())
      return GetExprListFromAtLocation(location_form, module, die, func_low_pc);
    if (const_value_form.IsValid())
      return GetExprListFromAtConstValue(const_value_form, module, die);
    return DWARFExpressionList(module, DWARFExpression(), die.GetCU());
  }();

  const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
  const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
  const dw_tag_t parent_tag = sc_parent_die.Tag();
  bool is_static_member = (parent_tag == DW_TAG_compile_unit ||
                           parent_tag == DW_TAG_partial_unit) &&
                          (parent_context_die.Tag() == DW_TAG_class_type ||
                           parent_context_die.Tag() == DW_TAG_structure_type);

  ValueType scope = eValueTypeInvalid;
  SymbolContextScope *symbol_context_scope = nullptr;

  bool has_explicit_mangled = mangled != nullptr;
  if (!mangled) {
    // LLDB relies on the mangled name (DW_TAG_linkage_name or
    // DW_AT_MIPS_linkage_name) to generate fully qualified names
    // of global variables with commands like "frame var j". For
    // example, if j were an int variable holding a value 4 and
    // declared in a namespace B which in turn is contained in a
    // namespace A, the command "frame var j" returns
    //   "(int) A::B::j = 4".
    // If the compiler does not emit a linkage name, we should be
    // able to generate a fully qualified name from the
    // declaration context.
    if ((parent_tag == DW_TAG_compile_unit ||
         parent_tag == DW_TAG_partial_unit) &&
        Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
      mangled = die.GetDWARFDeclContext()
                    .GetQualifiedNameAsConstString()
                    .GetCString();
  }

  if (tag == DW_TAG_formal_parameter)
    scope = eValueTypeVariableArgument;
  else {
    // DWARF doesn't specify if a DW_TAG_variable is a local, global
    // or static variable, so we have to do a little digging:
    // 1) DW_AT_linkage_name implies static lifetime (but may be missing)
    // 2) An empty DW_AT_location is an (optimized-out) static lifetime var.
    // 3) DW_AT_location containing a DW_OP_addr implies static lifetime.
    // Clang likes to combine small global variables into the same symbol
    // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
    // so we need to look through the whole expression.
    bool has_explicit_location = location_form.IsValid();
    bool is_static_lifetime =
        has_explicit_mangled ||
        (has_explicit_location && !location_list.IsValid());
    // Check if the location has a DW_OP_addr with any address value...
    lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
    if (!location_is_const_value_data) {
      if (const DWARFExpression *location =
              location_list.GetAlwaysValidExpr()) {
        if (auto maybe_location_DW_OP_addr =
                location->GetLocation_DW_OP_addr(location_form.GetUnit())) {
          location_DW_OP_addr = *maybe_location_DW_OP_addr;
        } else {
          StreamString strm;
          location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
          GetObjectFile()->GetModule()->ReportError(
              "{0:x16}: {1} ({2}) has an invalid location: {3}: {4}",
              die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),
              llvm::fmt_consume(maybe_location_DW_OP_addr.takeError()),
              strm.GetData());
        }
      }
      if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
        is_static_lifetime = true;
    }
    SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
    if (debug_map_symfile)
      // Set the module of the expression to the linked module
      // instead of the object file so the relocated address can be
      // found there.
      location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule());

    if (is_static_lifetime) {
      if (is_external)
        scope = eValueTypeVariableGlobal;
      else
        scope = eValueTypeVariableStatic;

      if (debug_map_symfile) {
        bool linked_oso_file_addr = false;

        if (is_external && location_DW_OP_addr == 0) {
          if (Symbol *exe_symbol = fixupExternalAddrZeroVariable(
                  *debug_map_symfile, mangled ? mangled : name, location_list,
                  die)) {
            linked_oso_file_addr = true;
            symbol_context_scope = exe_symbol;
          }
        }

        if (!linked_oso_file_addr) {
          // The DW_OP_addr is not zero, but it contains a .o file address
          // which needs to be linked up correctly.
          const lldb::addr_t exe_file_addr =
              debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
          if (exe_file_addr != LLDB_INVALID_ADDRESS) {
            // Update the file address for this variable
            DWARFExpression *location =
                location_list.GetMutableExpressionAtAddress();
            location->Update_DW_OP_addr(die.GetCU(), exe_file_addr);
          } else {
            // Variable didn't make it into the final executable
            return nullptr;
          }
        }
      }
    } else {
      if (location_is_const_value_data &&
          die.GetDIE()->IsGlobalOrStaticScopeVariable())
        scope = eValueTypeVariableStatic;
      else {
        scope = eValueTypeVariableLocal;
        if (debug_map_symfile) {
          // We need to check for TLS addresses that we need to fixup
          if (location_list.ContainsThreadLocalStorage()) {
            location_list.LinkThreadLocalStorage(
                debug_map_symfile->GetObjectFile()->GetModule(),
                [this, debug_map_symfile](
                    lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
                  return debug_map_symfile->LinkOSOFileAddress(
                      this, unlinked_file_addr);
                });
            scope = eValueTypeVariableThreadLocal;
          }
        }
      }
    }
  }

  if (symbol_context_scope == nullptr) {
    switch (parent_tag) {
    case DW_TAG_subprogram:
    case DW_TAG_inlined_subroutine:
    case DW_TAG_lexical_block:
      if (sc.function) {
        symbol_context_scope =
            sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
        if (symbol_context_scope == nullptr)
          symbol_context_scope = sc.function;
      }
      break;

    default:
      symbol_context_scope = sc.comp_unit;
      break;
    }
  }

  if (!symbol_context_scope) {
    // Not ready to parse this variable yet. It might be a global or static
    // variable that is in a function scope and the function in the symbol
    // context wasn't filled in yet
    return nullptr;
  }

  auto type_sp = std::make_shared<SymbolFileType>(
      *this, type_die_form.Reference().GetID());

  bool use_type_size_for_value =
      location_is_const_value_data &&
      DWARFFormValue::IsDataForm(const_value_form.Form());
  if (use_type_size_for_value && type_sp->GetType()) {
    DWARFExpression *location = location_list.GetMutableExpressionAtAddress();
    location->UpdateValue(
        const_value_form.Unsigned(),
        llvm::expectedToOptional(type_sp->GetType()->GetByteSize(nullptr))
            .value_or(0),
        die.GetCU()->GetAddressByteSize());
  }

  return std::make_shared<Variable>(
      die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
      scope_ranges, &decl, location_list, is_external, is_artificial,
      location_is_const_value_data, is_static_member, tag_offset);
}

DWARFDIE
SymbolFileDWARF::FindBlockContainingSpecification(
    const DIERef &func_die_ref, dw_offset_t spec_block_die_offset) {
  // Give the concrete function die specified by "func_die_offset", find the
  // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
  // to "spec_block_die_offset"
  return FindBlockContainingSpecification(GetDIE(func_die_ref),
                                          spec_block_die_offset);
}

DWARFDIE
SymbolFileDWARF::FindBlockContainingSpecification(
    const DWARFDIE &die, dw_offset_t spec_block_die_offset) {
  if (die) {
    switch (die.Tag()) {
    case DW_TAG_subprogram:
    case DW_TAG_inlined_subroutine:
    case DW_TAG_lexical_block: {
      if (die.GetReferencedDIE(DW_AT_specification).GetOffset() ==
          spec_block_die_offset)
        return die;

      if (die.GetReferencedDIE(DW_AT_abstract_origin).GetOffset() ==
          spec_block_die_offset)
        return die;
    } break;
    default:
      break;
    }

    // Give the concrete function die specified by "func_die_offset", find the
    // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
    // to "spec_block_die_offset"
    for (DWARFDIE child_die : die.children()) {
      DWARFDIE result_die =
          FindBlockContainingSpecification(child_die, spec_block_die_offset);
      if (result_die)
        return result_die;
    }
  }

  return DWARFDIE();
}

void SymbolFileDWARF::ParseAndAppendGlobalVariable(
    const SymbolContext &sc, const DWARFDIE &die,
    VariableList &cc_variable_list) {
  if (!die)
    return;

  dw_tag_t tag = die.Tag();
  if (tag != DW_TAG_variable && tag != DW_TAG_constant && tag != DW_TAG_member)
    return;

  // Check to see if we have already parsed this variable or constant?
  VariableSP var_sp = GetDIEToVariable()[die.GetDIE()];
  if (var_sp) {
    cc_variable_list.AddVariableIfUnique(var_sp);
    return;
  }

  // We haven't parsed the variable yet, lets do that now. Also, let us include
  // the variable in the relevant compilation unit's variable list, if it
  // exists.
  VariableListSP variable_list_sp;
  DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
  dw_tag_t parent_tag = sc_parent_die.Tag();
  switch (parent_tag) {
  case DW_TAG_compile_unit:
  case DW_TAG_partial_unit:
    if (sc.comp_unit != nullptr) {
      variable_list_sp = sc.comp_unit->GetVariableList(false);
    } else {
      GetObjectFile()->GetModule()->ReportError(
          "parent {0:x8} {1} ({2}) with no valid compile unit in "
          "symbol context for {3:x8} {4} ({5}).\n",
          sc_parent_die.GetID(), DW_TAG_value_to_name(sc_parent_die.Tag()),
          sc_parent_die.Tag(), die.GetID(), DW_TAG_value_to_name(die.Tag()),
          die.Tag());
      return;
    }
    break;

  default:
    LLDB_LOG(GetLog(DWARFLog::Lookups),
             "{0} '{1}' ({2:x8}) is not a global variable - ignoring", tag,
             die.GetName(), die.GetID());
    return;
  }

  var_sp = ParseVariableDIECached(sc, die);
  if (!var_sp)
    return;

  cc_variable_list.AddVariableIfUnique(var_sp);
  if (variable_list_sp)
    variable_list_sp->AddVariableIfUnique(var_sp);
}

DIEArray
SymbolFileDWARF::MergeBlockAbstractParameters(const DWARFDIE &block_die,
                                              DIEArray &&variable_dies) {
  // DW_TAG_inline_subroutine objects may omit DW_TAG_formal_parameter in
  // instances of the function when they are unused (i.e., the parameter's
  // location list would be empty). The current DW_TAG_inline_subroutine may
  // refer to another DW_TAG_subprogram that might actually have the definitions
  // of the parameters and we need to include these so they show up in the
  // variables for this function (for example, in a stack trace). Let us try to
  // find the abstract subprogram that might contain the parameter definitions
  // and merge with the concrete parameters.

  // Nothing to merge if the block is not an inlined function.
  if (block_die.Tag() != DW_TAG_inlined_subroutine) {
    return std::move(variable_dies);
  }

  // Nothing to merge if the block does not have abstract parameters.
  DWARFDIE abs_die = block_die.GetReferencedDIE(DW_AT_abstract_origin);
  if (!abs_die || abs_die.Tag() != DW_TAG_subprogram ||
      !abs_die.HasChildren()) {
    return std::move(variable_dies);
  }

  // For each abstract parameter, if we have its concrete counterpart, insert
  // it. Otherwise, insert the abstract parameter.
  DIEArray::iterator concrete_it = variable_dies.begin();
  DWARFDIE abstract_child = abs_die.GetFirstChild();
  DIEArray merged;
  bool did_merge_abstract = false;
  for (; abstract_child; abstract_child = abstract_child.GetSibling()) {
    if (abstract_child.Tag() == DW_TAG_formal_parameter) {
      if (concrete_it == variable_dies.end() ||
          GetDIE(*concrete_it).Tag() != DW_TAG_formal_parameter) {
        // We arrived at the end of the concrete parameter list, so all
        // the remaining abstract parameters must have been omitted.
        // Let us insert them to the merged list here.
        merged.push_back(*abstract_child.GetDIERef());
        did_merge_abstract = true;
        continue;
      }

      DWARFDIE origin_of_concrete =
          GetDIE(*concrete_it).GetReferencedDIE(DW_AT_abstract_origin);
      if (origin_of_concrete == abstract_child) {
        // The current abstract parameter is the origin of the current
        // concrete parameter, just push the concrete parameter.
        merged.push_back(*concrete_it);
        ++concrete_it;
      } else {
        // Otherwise, the parameter must have been omitted from the concrete
        // function, so insert the abstract one.
        merged.push_back(*abstract_child.GetDIERef());
        did_merge_abstract = true;
      }
    }
  }

  // Shortcut if no merging happened.
  if (!did_merge_abstract)
    return std::move(variable_dies);

  // We inserted all the abstract parameters (or their concrete counterparts).
  // Let us insert all the remaining concrete variables to the merged list.
  // During the insertion, let us check there are no remaining concrete
  // formal parameters. If that's the case, then just bailout from the merge -
  // the variable list is malformed.
  for (; concrete_it != variable_dies.end(); ++concrete_it) {
    if (GetDIE(*concrete_it).Tag() == DW_TAG_formal_parameter) {
      return std::move(variable_dies);
    }
    merged.push_back(*concrete_it);
  }
  return merged;
}

size_t SymbolFileDWARF::ParseVariablesInFunctionContext(
    const SymbolContext &sc, const DWARFDIE &die,
    const lldb::addr_t func_low_pc) {
  if (!die || !sc.function)
    return 0;

  DIEArray dummy_block_variables; // The recursive call should not add anything
                                  // to this vector because |die| should be a
                                  // subprogram, so all variables will be added
                                  // to the subprogram's list.
  return ParseVariablesInFunctionContextRecursive(sc, die, func_low_pc,
                                                  dummy_block_variables);
}

// This method parses all the variables in the blocks in the subtree of |die|,
// and inserts them to the variable list for all the nested blocks.
// The uninserted variables for the current block are accumulated in
// |accumulator|.
size_t SymbolFileDWARF::ParseVariablesInFunctionContextRecursive(
    const lldb_private::SymbolContext &sc, const DWARFDIE &die,
    lldb::addr_t func_low_pc, DIEArray &accumulator) {
  size_t vars_added = 0;
  dw_tag_t tag = die.Tag();

  if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
      (tag == DW_TAG_formal_parameter)) {
    accumulator.push_back(*die.GetDIERef());
  }

  switch (tag) {
  case DW_TAG_subprogram:
  case DW_TAG_inlined_subroutine:
  case DW_TAG_lexical_block: {
    // If we start a new block, compute a new block variable list and recurse.
    Block *block =
        sc.function->GetBlock(/*can_create=*/true).FindBlockByID(die.GetID());
    if (block == nullptr) {
      // This must be a specification or abstract origin with a
      // concrete block counterpart in the current function. We need
      // to find the concrete block so we can correctly add the
      // variable to it.
      const DWARFDIE concrete_block_die = FindBlockContainingSpecification(
          GetDIE(sc.function->GetID()), die.GetOffset());
      if (concrete_block_die)
        block = sc.function->GetBlock(/*can_create=*/true)
                    .FindBlockByID(concrete_block_die.GetID());
    }

    if (block == nullptr)
      return 0;

    const bool can_create = false;
    VariableListSP block_variable_list_sp =
        block->GetBlockVariableList(can_create);
    if (block_variable_list_sp.get() == nullptr) {
      block_variable_list_sp = std::make_shared<VariableList>();
      block->SetVariableList(block_variable_list_sp);
    }

    DIEArray block_variables;
    for (DWARFDIE child = die.GetFirstChild(); child;
         child = child.GetSibling()) {
      vars_added += ParseVariablesInFunctionContextRecursive(
          sc, child, func_low_pc, block_variables);
    }
    block_variables =
        MergeBlockAbstractParameters(die, std::move(block_variables));
    vars_added += PopulateBlockVariableList(*block_variable_list_sp, sc,
                                            block_variables, func_low_pc);
    break;
  }

  default:
    // Recurse to children with the same variable accumulator.
    for (DWARFDIE child = die.GetFirstChild(); child;
         child = child.GetSibling()) {
      vars_added += ParseVariablesInFunctionContextRecursive(
          sc, child, func_low_pc, accumulator);
    }
    break;
  }

  return vars_added;
}

size_t SymbolFileDWARF::PopulateBlockVariableList(
    VariableList &variable_list, const lldb_private::SymbolContext &sc,
    llvm::ArrayRef<DIERef> variable_dies, lldb::addr_t func_low_pc) {
  // Parse the variable DIEs and insert them to the list.
  for (auto &die : variable_dies) {
    if (VariableSP var_sp = ParseVariableDIE(sc, GetDIE(die), func_low_pc)) {
      variable_list.AddVariableIfUnique(var_sp);
    }
  }
  return variable_dies.size();
}

/// Collect call site parameters in a DW_TAG_call_site DIE.
static CallSiteParameterArray
CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
  CallSiteParameterArray parameters;
  for (DWARFDIE child : call_site_die.children()) {
    if (child.Tag() != DW_TAG_call_site_parameter &&
        child.Tag() != DW_TAG_GNU_call_site_parameter)
      continue;

    std::optional<DWARFExpressionList> LocationInCallee;
    std::optional<DWARFExpressionList> LocationInCaller;

    DWARFAttributes attributes = child.GetAttributes();

    // Parse the location at index \p attr_index within this call site parameter
    // DIE, or return std::nullopt on failure.
    auto parse_simple_location =
        [&](int attr_index) -> std::optional<DWARFExpressionList> {
      DWARFFormValue form_value;
      if (!attributes.ExtractFormValueAtIndex(attr_index, form_value))
        return {};
      if (!DWARFFormValue::IsBlockForm(form_value.Form()))
        return {};
      auto data = child.GetData();
      uint64_t block_offset = form_value.BlockData() - data.GetDataStart();
      uint64_t block_length = form_value.Unsigned();
      return DWARFExpressionList(
          module, DataExtractor(data, block_offset, block_length),
          child.GetCU());
    };

    for (size_t i = 0; i < attributes.Size(); ++i) {
      dw_attr_t attr = attributes.AttributeAtIndex(i);
      if (attr == DW_AT_location)
        LocationInCallee = parse_simple_location(i);
      if (attr == DW_AT_call_value || attr == DW_AT_GNU_call_site_value)
        LocationInCaller = parse_simple_location(i);
    }

    if (LocationInCallee && LocationInCaller) {
      CallSiteParameter param = {*LocationInCallee, *LocationInCaller};
      parameters.push_back(param);
    }
  }
  return parameters;
}

/// Collect call graph edges present in a function DIE.
std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
  // Check if the function has a supported call site-related attribute.
  // TODO: In the future it may be worthwhile to support call_all_source_calls.
  bool has_call_edges =
      function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0) ||
      function_die.GetAttributeValueAsUnsigned(DW_AT_GNU_all_call_sites, 0);
  if (!has_call_edges)
    return {};

  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOG(log, "CollectCallEdges: Found call site info in {0}",
           function_die.GetPubname());

  // Scan the DIE for TAG_call_site entries.
  // TODO: A recursive scan of all blocks in the subprogram is needed in order
  // to be DWARF5-compliant. This may need to be done lazily to be performant.
  // For now, assume that all entries are nested directly under the subprogram
  // (this is the kind of DWARF LLVM produces) and parse them eagerly.
  std::vector<std::unique_ptr<CallEdge>> call_edges;
  for (DWARFDIE child : function_die.children()) {
    if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site)
      continue;

    std::optional<DWARFDIE> call_origin;
    std::optional<DWARFExpressionList> call_target;
    addr_t return_pc = LLDB_INVALID_ADDRESS;
    addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
    addr_t low_pc = LLDB_INVALID_ADDRESS;
    bool tail_call = false;

    // Second DW_AT_low_pc may come from DW_TAG_subprogram referenced by
    // DW_TAG_GNU_call_site's DW_AT_abstract_origin overwriting our 'low_pc'.
    // So do not inherit attributes from DW_AT_abstract_origin.
    DWARFAttributes attributes = child.GetAttributes(DWARFDIE::Recurse::no);
    for (size_t i = 0; i < attributes.Size(); ++i) {
      DWARFFormValue form_value;
      if (!attributes.ExtractFormValueAtIndex(i, form_value)) {
        LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form");
        break;
      }

      dw_attr_t attr = attributes.AttributeAtIndex(i);

      if (attr == DW_AT_call_tail_call || attr == DW_AT_GNU_tail_call)
        tail_call = form_value.Boolean();

      // Extract DW_AT_call_origin (the call target's DIE).
      if (attr == DW_AT_call_origin || attr == DW_AT_abstract_origin) {
        call_origin = form_value.Reference();
        if (!call_origin->IsValid()) {
          LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
                   function_die.GetPubname());
          break;
        }
      }

      if (attr == DW_AT_low_pc)
        low_pc = form_value.Address();

      // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
      // available. It should only ever be unavailable for tail call edges, in
      // which case use LLDB_INVALID_ADDRESS.
      if (attr == DW_AT_call_return_pc)
        return_pc = form_value.Address();

      // Extract DW_AT_call_pc (the PC at the call/branch instruction). It
      // should only ever be unavailable for non-tail calls, in which case use
      // LLDB_INVALID_ADDRESS.
      if (attr == DW_AT_call_pc)
        call_inst_pc = form_value.Address();

      // Extract DW_AT_call_target (the location of the address of the indirect
      // call).
      if (attr == DW_AT_call_target || attr == DW_AT_GNU_call_site_target) {
        if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
          LLDB_LOG(log,
                   "CollectCallEdges: AT_call_target does not have block form");
          break;
        }

        auto data = child.GetData();
        uint64_t block_offset = form_value.BlockData() - data.GetDataStart();
        uint64_t block_length = form_value.Unsigned();
        call_target = DWARFExpressionList(
            module, DataExtractor(data, block_offset, block_length),
            child.GetCU());
      }
    }
    if (!call_origin && !call_target) {
      LLDB_LOG(log, "CollectCallEdges: call site without any call target");
      continue;
    }

    addr_t caller_address;
    CallEdge::AddrType caller_address_type;
    if (return_pc != LLDB_INVALID_ADDRESS) {
      caller_address = return_pc;
      caller_address_type = CallEdge::AddrType::AfterCall;
    } else if (low_pc != LLDB_INVALID_ADDRESS) {
      caller_address = low_pc;
      caller_address_type = CallEdge::AddrType::AfterCall;
    } else if (call_inst_pc != LLDB_INVALID_ADDRESS) {
      caller_address = call_inst_pc;
      caller_address_type = CallEdge::AddrType::Call;
    } else {
      LLDB_LOG(log, "CollectCallEdges: No caller address");
      continue;
    }
    // Adjust any PC forms. It needs to be fixed up if the main executable
    // contains a debug map (i.e. pointers to object files), because we need a
    // file address relative to the executable's text section.
    caller_address = FixupAddress(caller_address);

    // Extract call site parameters.
    CallSiteParameterArray parameters =
        CollectCallSiteParameters(module, child);

    std::unique_ptr<CallEdge> edge;
    if (call_origin) {
      LLDB_LOG(log,
               "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x}) "
               "(call-PC: {2:x})",
               call_origin->GetPubname(), return_pc, call_inst_pc);
      edge = std::make_unique<DirectCallEdge>(
          call_origin->GetMangledName(), caller_address_type, caller_address,
          tail_call, std::move(parameters));
    } else {
      if (log) {
        StreamString call_target_desc;
        call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
                                    nullptr);
        LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
                 call_target_desc.GetString());
      }
      edge = std::make_unique<IndirectCallEdge>(
          *call_target, caller_address_type, caller_address, tail_call,
          std::move(parameters));
    }

    if (log && parameters.size()) {
      for (const CallSiteParameter &param : parameters) {
        StreamString callee_loc_desc, caller_loc_desc;
        param.LocationInCallee.GetDescription(&callee_loc_desc,
                                              eDescriptionLevelBrief, nullptr);
        param.LocationInCaller.GetDescription(&caller_loc_desc,
                                              eDescriptionLevelBrief, nullptr);
        LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}",
                 callee_loc_desc.GetString(), caller_loc_desc.GetString());
      }
    }

    call_edges.push_back(std::move(edge));
  }
  return call_edges;
}

std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARF::ParseCallEdgesInFunction(lldb_private::UserID func_id) {
  // ParseCallEdgesInFunction must be called at the behest of an exclusively
  // locked lldb::Function instance. Storage for parsed call edges is owned by
  // the lldb::Function instance: locking at the SymbolFile level would be too
  // late, because the act of storing results from ParseCallEdgesInFunction
  // would be racy.
  DWARFDIE func_die = GetDIE(func_id.GetID());
  if (func_die.IsValid())
    return CollectCallEdges(GetObjectFile()->GetModule(), func_die);
  return {};
}

void SymbolFileDWARF::Dump(lldb_private::Stream &s) {
  SymbolFileCommon::Dump(s);
  m_index->Dump(s);
}

void SymbolFileDWARF::DumpClangAST(Stream &s, llvm::StringRef filter,
                                   bool show_color) {
  auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
  if (!ts_or_err)
    return;
  auto ts = *ts_or_err;
  TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
  if (!clang)
    return;
  clang->Dump(s.AsRawOstream(), filter, show_color);
}

bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d,
                                           bool errors_only,
                                           bool load_all_debug_info) {
  StructuredData::Array separate_debug_info_files;
  DWARFDebugInfo &info = DebugInfo();
  const size_t num_cus = info.GetNumUnits();
  for (size_t cu_idx = 0; cu_idx < num_cus; cu_idx++) {
    DWARFUnit *unit = info.GetUnitAtIndex(cu_idx);
    DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(unit);
    if (dwarf_cu == nullptr)
      continue;

    // Check if this is a DWO unit by checking if it has a DWO ID.
    // NOTE: it seems that `DWARFUnit::IsDWOUnit` is always false?
    if (!dwarf_cu->GetDWOId().has_value())
      continue;

    StructuredData::DictionarySP dwo_data =
        std::make_shared<StructuredData::Dictionary>();
    const uint64_t dwo_id = dwarf_cu->GetDWOId().value();
    dwo_data->AddIntegerItem("dwo_id", dwo_id);

    if (const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly()) {
      const char *dwo_name = GetDWOName(*dwarf_cu, *die.GetDIE());
      if (dwo_name) {
        dwo_data->AddStringItem("dwo_name", dwo_name);
      } else {
        dwo_data->AddStringItem("error", "missing dwo name");
      }

      const char *comp_dir = die.GetDIE()->GetAttributeValueAsString(
          dwarf_cu, DW_AT_comp_dir, nullptr);
      if (comp_dir) {
        dwo_data->AddStringItem("comp_dir", comp_dir);
      }
    } else {
      dwo_data->AddStringItem(
          "error",
          llvm::formatv("unable to get unit DIE for DWARFUnit at {0:x}",
                        dwarf_cu->GetOffset())
              .str());
    }

    // If we have a DWO symbol file, that means we were able to successfully
    // load it.
    SymbolFile *dwo_symfile = dwarf_cu->GetDwoSymbolFile(load_all_debug_info);
    if (dwo_symfile) {
      dwo_data->AddStringItem(
          "resolved_dwo_path",
          dwo_symfile->GetObjectFile()->GetFileSpec().GetPath());
    } else {
      dwo_data->AddStringItem("error",
                              dwarf_cu->GetDwoError().AsCString("unknown"));
    }
    dwo_data->AddBooleanItem("loaded", dwo_symfile != nullptr);
    if (!errors_only || dwo_data->HasKey("error"))
      separate_debug_info_files.AddItem(dwo_data);
  }

  d.AddStringItem("type", "dwo");
  d.AddStringItem("symfile", GetMainObjectFile()->GetFileSpec().GetPath());
  d.AddItem("separate-debug-info-files",
            std::make_shared<StructuredData::Array>(
                std::move(separate_debug_info_files)));
  return true;
}

SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
  if (m_debug_map_symfile == nullptr) {
    lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
    if (module_sp) {
      m_debug_map_symfile = llvm::cast<SymbolFileDWARFDebugMap>(
          module_sp->GetSymbolFile()->GetBackingSymbolFile());
    }
  }
  return m_debug_map_symfile;
}

const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
  llvm::call_once(m_dwp_symfile_once_flag, [this]() {
    if (m_objfile_sp->GetArchitecture().GetTriple().isAppleMachO())
      return;

    // Create a list of files to try and append .dwp to.
    FileSpecList symfiles;
    // Append the module's object file path.
    const FileSpec module_fspec = m_objfile_sp->GetModule()->GetFileSpec();
    symfiles.Append(module_fspec);
    // Append the object file for this SymbolFile only if it is different from
    // the module's file path. Our main module could be "a.out", our symbol file
    // could be "a.debug" and our ".dwp" file might be "a.debug.dwp" instead of
    // "a.out.dwp".
    const FileSpec symfile_fspec(m_objfile_sp->GetFileSpec());
    if (symfile_fspec != module_fspec) {
      symfiles.Append(symfile_fspec);
    } else {
      // If we don't have a separate debug info file, then try stripping the
      // extension. The main module could be "a.debug" and the .dwp file could
      // be "a.dwp" instead of "a.debug.dwp".
      ConstString filename_no_ext =
          module_fspec.GetFileNameStrippingExtension();
      if (filename_no_ext != module_fspec.GetFilename()) {
        FileSpec module_spec_no_ext(module_fspec);
        module_spec_no_ext.SetFilename(filename_no_ext);
        symfiles.Append(module_spec_no_ext);
      }
    }
    Log *log = GetLog(DWARFLog::SplitDwarf);
    FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
    ModuleSpec module_spec;
    module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec();
    FileSpec dwp_filespec;
    for (const auto &symfile : symfiles.files()) {
      module_spec.GetSymbolFileSpec() =
          FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle());
      LLDB_LOG(log, "Searching for DWP using: \"{0}\"",
               module_spec.GetSymbolFileSpec());
      dwp_filespec = PluginManager::LocateExecutableSymbolFile(
          module_spec, search_paths,
          m_objfile_sp->GetModule()->GetSymbolLocatorStatistics());
      if (FileSystem::Instance().Exists(dwp_filespec)) {
        break;
      }
    }
    if (!FileSystem::Instance().Exists(dwp_filespec)) {
      LLDB_LOG(log, "No DWP file found locally");
      // Fill in the UUID for the module we're trying to match for, so we can
      // find the correct DWP file, as the Debuginfod plugin uses *only* this
      // data to correctly match the DWP file with the binary.
      module_spec.GetUUID() = m_objfile_sp->GetUUID();
      dwp_filespec = PluginManager::LocateExecutableSymbolFile(
          module_spec, search_paths,
          m_objfile_sp->GetModule()->GetSymbolLocatorStatistics());
    }
    if (FileSystem::Instance().Exists(dwp_filespec)) {
      LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec);
      DataExtractorSP dwp_file_extractor_sp;
      lldb::offset_t dwp_file_data_offset = 0;
      ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
          GetObjectFile()->GetModule(), &dwp_filespec, 0,
          FileSystem::Instance().GetByteSize(dwp_filespec),
          dwp_file_extractor_sp, dwp_file_data_offset);
      if (dwp_obj_file) {
        m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>(
            *this, dwp_obj_file, DIERef::k_file_index_mask);
      }
    }
    if (!m_dwp_symfile) {
      LLDB_LOG(log, "Unable to locate for DWP file for: \"{0}\"",
               m_objfile_sp->GetModule()->GetFileSpec());
    }
  });
  return m_dwp_symfile;
}

llvm::Expected<lldb::TypeSystemSP>
SymbolFileDWARF::GetTypeSystem(DWARFUnit &unit) {
  return unit.GetSymbolFileDWARF().GetTypeSystemForLanguage(GetLanguage(unit));
}

DWARFASTParser *SymbolFileDWARF::GetDWARFParser(DWARFUnit &unit) {
  auto type_system_or_err = GetTypeSystem(unit);
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Unable to get DWARFASTParser: {0}");
    return nullptr;
  }
  if (auto ts = *type_system_or_err)
    return ts->GetDWARFParser();
  return nullptr;
}

CompilerDecl SymbolFileDWARF::GetDecl(const DWARFDIE &die) {
  if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
    return dwarf_ast->GetDeclForUIDFromDWARF(die);
  return CompilerDecl();
}

CompilerDeclContext SymbolFileDWARF::GetDeclContext(const DWARFDIE &die) {
  if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
    return dwarf_ast->GetDeclContextForUIDFromDWARF(die);
  return CompilerDeclContext();
}

CompilerDeclContext
SymbolFileDWARF::GetContainingDeclContext(const DWARFDIE &die) {
  if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()))
    return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
  return CompilerDeclContext();
}

LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) {
  if (val <= eLanguageTypeLastStandardLanguage)
    return static_cast<LanguageType>(val);

  // Note: user languages between lo_user and hi_user must be handled
  // explicitly here.
  switch (val) {
  case DW_LANG_Mips_Assembler:
    return eLanguageTypeMipsAssembler;
  default:
    return eLanguageTypeUnknown;
  }
}

LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
  return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
}

LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) {
  auto lang = (llvm::dwarf::SourceLanguage)unit.GetDWARFLanguageType();
  if (llvm::dwarf::isCPlusPlus(lang))
    lang = DW_LANG_C_plus_plus;
  return LanguageTypeFromDWARF(lang);
}

StatsDuration::Duration SymbolFileDWARF::GetDebugInfoIndexTime() {
  if (m_index)
    return m_index->GetIndexTime();
  return {};
}

void SymbolFileDWARF::ResetStatistics() {
  m_parse_time.reset();
  if (m_index)
    return m_index->ResetStatistics();
}

Status SymbolFileDWARF::CalculateFrameVariableError(StackFrame &frame) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  CompileUnit *cu = frame.GetSymbolContext(eSymbolContextCompUnit).comp_unit;
  if (!cu)
    return Status();

  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(cu);
  if (!dwarf_cu)
    return Status();

  // Check if we have a skeleton compile unit that had issues trying to load
  // its .dwo/.dwp file. First pares the Unit DIE to make sure we see any .dwo
  // related errors.
  dwarf_cu->ExtractUnitDIEIfNeeded();
  const Status &dwo_error = dwarf_cu->GetDwoError();
  if (dwo_error.Fail())
    return dwo_error.Clone();

  // Don't return an error for assembly files as they typically don't have
  // varaible information.
  if (dwarf_cu->GetDWARFLanguageType() == DW_LANG_Mips_Assembler)
    return Status();

  // Check if this compile unit has any variable DIEs. If it doesn't then there
  // is not variable information for the entire compile unit.
  if (dwarf_cu->HasAny({DW_TAG_variable, DW_TAG_formal_parameter}))
    return Status();

  return Status::FromErrorString(
      "no variable information is available in debug info for this "
      "compile unit");
}

void SymbolFileDWARF::GetCompileOptions(
    std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) {

  const uint32_t num_compile_units = GetNumCompileUnits();

  for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
    lldb::CompUnitSP comp_unit = GetCompileUnitAtIndex(cu_idx);
    if (!comp_unit)
      continue;

    DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit.get());
    if (!dwarf_cu)
      continue;

    const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
    if (!die)
      continue;

    const char *flags = die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

    if (!flags)
      continue;
    args.insert({comp_unit, Args(flags)});
  }
}

DWOStats SymbolFileDWARF::GetDwoStats() {
  DWOStats stats;

  DWARFDebugInfo &info = DebugInfo();
  const size_t num_cus = info.GetNumUnits();
  for (size_t cu_idx = 0; cu_idx < num_cus; cu_idx++) {
    DWARFUnit *dwarf_cu = info.GetUnitAtIndex(cu_idx);
    if (dwarf_cu == nullptr)
      continue;

    // Check if this is a DWO unit by checking if it has a DWO ID.
    if (!dwarf_cu->GetDWOId().has_value())
      continue;

    stats.dwo_file_count++;

    // If we have a DWO symbol file, that means we were able to successfully
    // load it.
    SymbolFile *dwo_symfile =
        dwarf_cu->GetDwoSymbolFile(/*load_all_debug_info=*/false);
    if (dwo_symfile) {
      stats.loaded_dwo_file_count++;
    }

    // Check if this unit has a DWO load error, false by default.
    const Status &dwo_error = dwarf_cu->GetDwoError();
    if (dwo_error.Fail())
      stats.dwo_error_count++;
  }

  return stats;
}
