//===-- 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/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);
  }

  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);

  auto type_system_or_err =
      m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
  if (type_system_or_err)
    if (auto ts = *type_system_or_err)
      ts->SetSymbolFile(this);
  return type_system_or_err;
}

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().AsCString());
  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::createStringError(llvm::formatv(
              "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::createStringError(
          llvm::formatv("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::createStringError(
        llvm::formatv("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;
  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_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);
}

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;
}
