//===-- 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 "llvm/ADT/Optional.h"
#include "llvm/Support/Casting.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/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.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/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/LocateSymbolFile.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 "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugMacro.h"
#include "DWARFDebugRanges.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 "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"

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

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

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 ConstString GetSettingName() {
    return ConstString(SymbolFileDWARF::GetPluginNameStatic());
  }

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

  bool IgnoreFileIndexes() const {
    return m_collection_sp->GetPropertyAtIndexAsBoolean(
        nullptr, ePropertyIgnoreIndexes, false);
  }
};

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

} // namespace

static const llvm::DWARFDebugLine::LineTable *
ParseLLVMLineTable(lldb_private::DWARFContext &context,
                   llvm::DWARFDebugLine &line, dw_offset_t line_offset,
                   dw_offset_t unit_offset) {
  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);

  llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM();
  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(lldb_private::DWARFContext &context,
                                       llvm::DWARFDebugLine::Prologue &prologue,
                                       dw_offset_t line_offset,
                                       dw_offset_t unit_offset) {
  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
  bool success = true;
  llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM();
  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 llvm::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 FileSpecList
ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
                              const llvm::DWARFDebugLine::Prologue &prologue,
                              FileSpec::Style style,
                              llvm::StringRef compile_dir = {}) {
  FileSpecList support_files;
  size_t first_file = 0;
  if (prologue.getVersion() <= 4) {
    // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure
    // support file list indices match those we get from the debug info and line
    // tables.
    support_files.Append(FileSpec());
    first_file = 1;
  }

  const size_t number_of_files = prologue.FileNames.size();
  for (size_t idx = first_file; idx <= number_of_files; ++idx) {
    std::string remapped_file;
    if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) {
      if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path)))
        remapped_file = *remapped;
      else
        remapped_file = std::move(*file_path);
    }

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

  return support_files;
}

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(),
        ConstString("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) {
  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 SymbolFile::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)
    : SymbolFile(std::move(objfile_sp)),
      UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to
                                  // when this class parses .o files to
                                  // contain the .o file index/ID
      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),
      m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}

SymbolFileDWARF::~SymbolFileDWARF() = default;

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

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<TypeSystem &>
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) {
    type_system_or_err->SetSymbolFile(this);
  }
  return type_system_or_err;
}

void SymbolFileDWARF::InitializeObject() {
  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);

  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) {
      Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
                                      module_desc.GetData()));
      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(
          llvm::formatv("Loading DWARF5 index for {0}", 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;
}

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

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

      section =
          section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true)
              .get();
      if (section)
        debug_line_file_size = section->GetFileSize();
    } else {
      const char *symfile_dir_cstr =
          m_objfile_sp->GetFileSpec().GetDirectory().GetCString();
      if (symfile_dir_cstr) {
        if (strcasestr(symfile_dir_cstr, ".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.");
            }
          }
        }
      }
    }

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

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;

  auto abbr = std::make_unique<DWARFDebugAbbrev>();
  llvm::Error error = abbr->parse(debug_abbrev_data);
  if (error) {
    Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
    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_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));
    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->GetUserData() == nullptr)
    dwarf_cu->SetUserData(comp_unit);

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

DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() {
  if (!m_ranges) {
    LLDB_SCOPED_TIMERF("%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));

    if (m_context.getOrLoadRangesData().GetByteSize() > 0)
      m_ranges = std::make_unique<DWARFDebugRanges>();

    if (m_ranges)
      m_ranges->Extract(m_context);
  }
  return m_ranges.get();
}

/// 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 = (CompileUnit *)dwarf_cu.GetUserData();
  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 (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) {
      // Let the debug map create the compile unit
      cu_sp = m_debug_map_symfile->GetCompileUnit(this);
      dwarf_cu.SetUserData(cu_sp.get());
    } else {
      ModuleSP module_sp(m_objfile_sp->GetModule());
      if (module_sp) {
        auto initialize_cu = [&](const FileSpec &file_spec,
                                 LanguageType cu_language) {
          BuildCuTranslationTable();
          cu_sp = std::make_shared<CompileUnit>(
              module_sp, &dwarf_cu, file_spec,
              *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
              eLazyBoolCalculate);

          dwarf_cu.SetUserData(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.
          FileSpecList support_files;
          if (!ParseSupportFiles(dwarf_cu, module_sp, support_files))
            return false;
          if (support_files.GetSize() == 0)
            return false;

          initialize_cu(support_files.GetFileSpecAtIndex(0),
                        eLanguageTypeUnknown);
          cu_sp->SetSupportFiles(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(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);
    }
  }
}

llvm::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 llvm::None;
  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 (llvm::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);
  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(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
                   std::move(err), "Unable to parse function");
    return nullptr;
  }
  DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser();
  if (!dwarf_ast)
    return nullptr;

  DWARFRangeList ranges;
  if (die.GetDIE()->GetAttributeAddressRanges(die.GetCU(), ranges,
                                              /*check_hi_lo_pc=*/true) == 0)
    return nullptr;

  // Union of all ranges in the function DIE (if the function is
  // discontiguous)
  lldb::addr_t lowest_func_addr = ranges.GetMinRangeBase(0);
  lldb::addr_t highest_func_addr = ranges.GetMaxRangeEnd(0);
  if (lowest_func_addr == LLDB_INVALID_ADDRESS ||
      lowest_func_addr >= highest_func_addr ||
      lowest_func_addr < m_first_code_address)
    return nullptr;

  ModuleSP module_sp(die.GetModule());
  AddressRange func_range;
  func_range.GetBaseAddress().ResolveAddressUsingFileSections(
      lowest_func_addr, module_sp->GetSectionList());
  if (!func_range.GetBaseAddress().IsValid())
    return nullptr;

  func_range.SetByteSize(highest_func_addr - lowest_func_addr);
  if (!FixupAddress(func_range.GetBaseAddress()))
    return nullptr;

  return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, func_range);
}

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 {};
  const char *sysroot =
      cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, "");
  // 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};
}

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,
                                        FileSpecList &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;

  comp_unit.SetSupportFiles(support_files);
  return true;
}

bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
                                        const ModuleSP &module,
                                        FileSpecList &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;

  support_files = ParseSupportFilesFromPrologue(
      module, prologue, dwarf_cu.GetPathStyle(),
      dwarf_cu.GetCompilationDirectory().GetCString());

  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);
  return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx);
}

const FileSpecList &
SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) {
  static FileSpecList 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 empty_list;

  // 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);
  FileSpecList &list = iter_bool.first->second;
  if (iter_bool.second) {
    uint64_t line_table_offset = offset;
    llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM();
    llvm::DWARFContext &ctx = m_context.GetAsLLVM();
    llvm::DWARFDebugLine::Prologue prologue;
    auto report = [](llvm::Error error) {
      Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
      LLDB_LOG_ERROR(log, std::move(error),
                     "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
                     "the line table prologue");
    };
    ElapsedTime elapsed(m_parse_time);
    llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
    if (error) {
      report(std::move(error));
    } else {
      list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(),
                                           prologue, tu.GetPathStyle());
    }
  }
  return list;
}

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

      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));
      }
      std::reverse(module.path.begin(), module.path.end());
      if (const char *include_path = module_die.GetAttributeValueAsString(
              DW_AT_LLVM_include_path, nullptr)) {
        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<std::unique_ptr<LineSequence>> 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;
    std::unique_ptr<LineSequence> sequence =
        LineTable::CreateLineSequenceContainer();
    for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
      const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx];
      LineTable::AppendLineEntryToSequence(
          sequence.get(), 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(
    lldb_private::CompileUnit &comp_unit, Block *parent_block,
    const DWARFDIE &orig_die, addr_t subprogram_low_pc, uint32_t depth) {
  size_t blocks_added = 0;
  DWARFDIE die = orig_die;
  while (die) {
    dw_tag_t tag = die.Tag();

    switch (tag) {
    case DW_TAG_inlined_subroutine:
    case DW_TAG_subprogram:
    case DW_TAG_lexical_block: {
      Block *block = nullptr;
      if (tag == DW_TAG_subprogram) {
        // Skip any DW_TAG_subprogram DIEs that are inside of a normal or
        // inlined functions. These will be parsed on their own as separate
        // entities.

        if (depth > 0)
          break;

        block = parent_block;
      } else {
        BlockSP block_sp(new Block(die.GetID()));
        parent_block->AddChild(block_sp);
        block = block_sp.get();
      }
      DWARFRangeList ranges;
      const char *name = nullptr;
      const char *mangled_name = nullptr;

      int decl_file = 0;
      int decl_line = 0;
      int decl_column = 0;
      int call_file = 0;
      int call_line = 0;
      int call_column = 0;
      if (die.GetDIENamesAndRanges(name, mangled_name, ranges, decl_file,
                                   decl_line, decl_column, call_file, call_line,
                                   call_column, nullptr)) {
        if (tag == DW_TAG_subprogram) {
          assert(subprogram_low_pc == LLDB_INVALID_ADDRESS);
          subprogram_low_pc = ranges.GetMinRangeBase(0);
        } else if (tag == DW_TAG_inlined_subroutine) {
          // We get called here for inlined subroutines in two ways. The first
          // time is when we are making the Function object for this inlined
          // concrete instance.  Since we're creating a top level block at
          // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS.  So we
          // need to adjust the containing address. The second time is when we
          // are parsing the blocks inside the function that contains the
          // inlined concrete instance.  Since these will be blocks inside the
          // containing "real" function the offset will be for that function.
          if (subprogram_low_pc == LLDB_INVALID_ADDRESS) {
            subprogram_low_pc = ranges.GetMinRangeBase(0);
          }
        }

        const size_t num_ranges = ranges.GetSize();
        for (size_t i = 0; i < num_ranges; ++i) {
          const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
          const addr_t range_base = range.GetRangeBase();
          if (range_base >= subprogram_low_pc)
            block->AddRange(Block::Range(range_base - subprogram_low_pc,
                                         range.GetByteSize()));
          else {
            GetObjectFile()->GetModule()->ReportError(
                "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64
                ") which has a base that is less than the function's low PC "
                "0x%" PRIx64 ". Please file a bug and attach the file at the "
                "start of this error message",
                block->GetID(), range_base, range.GetRangeEnd(),
                subprogram_low_pc);
          }
        }
        block->FinalizeRanges();

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

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

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

        ++blocks_added;

        if (die.HasChildren()) {
          blocks_added +=
              ParseBlocksRecursive(comp_unit, block, die.GetFirstChild(),
                                   subprogram_low_pc, depth + 1);
        }
      }
    } break;
    default:
      break;
    }

    // Only parse siblings of the block if we are not at depth zero. A depth of
    // zero indicates we are currently parsing the top level DW_TAG_subprogram
    // DIE

    if (depth == 0)
      die.Clear();
    else
      die = die.GetSibling();
  }
  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);
}

user_id_t SymbolFileDWARF::GetUID(DIERef ref) {
  if (GetDebugMapSymfile())
    return GetID() | ref.die_offset();

  lldbassert(GetDwoNum().getValueOr(0) <= 0x3fffffff);
  return user_id_t(GetDwoNum().getValueOr(0)) << 32 | ref.die_offset() |
         lldb::user_id_t(GetDwoNum().hasValue()) << 62 |
         lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63;
}

llvm::Optional<SymbolFileDWARF::DecodedUID>
SymbolFileDWARF::DecodeUID(lldb::user_id_t 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 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.
  if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) {
    SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex(
        debug_map->GetOSOIndexFromUserID(uid));
    return DecodedUID{
        *dwarf, {llvm::None, DIERef::Section::DebugInfo, dw_offset_t(uid)}};
  }
  dw_offset_t die_offset = uid;
  if (die_offset == DW_INVALID_OFFSET)
    return llvm::None;

  DIERef::Section section =
      uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo;

  llvm::Optional<uint32_t> dwo_num;
  bool dwo_valid = uid >> 62 & 1;
  if (dwo_valid)
    dwo_num = uid >> 32 & 0x3fffffff;

  return DecodedUID{*this, {dwo_num, section, die_offset}};
}

DWARFDIE
SymbolFileDWARF::GetDIE(lldb::user_id_t 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());

  llvm::Optional<DecodedUID> decoded = DecodeUID(uid);

  if (decoded)
    return decoded->dwarf.GetDIE(decoded->ref);

  return DWARFDIE();
}

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

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

llvm::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 llvm::None;
}

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(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
    if (log)
      GetObjectFile()->GetModule()->LogMessage(
          log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",
          die.GetOffset(), die.GetTagAsCString(), 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 = 0x%8.8x) %s '%s' "
                "resolve parent forward type for 0x%8.8x",
                die.GetOffset(), die.GetTagAsCString(), 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::HasForwardDeclForClangType(
    const CompilerType &compiler_type) {
  CompilerType compiler_type_no_qualifiers =
      ClangUtil::RemoveFastQualifiers(compiler_type);
  if (GetForwardDeclClangTypeToDie().count(
          compiler_type_no_qualifiers.GetOpaqueQualType())) {
    return true;
  }
  TypeSystem *type_system = compiler_type.GetTypeSystem();

  TypeSystemClang *clang_type_system =
      llvm::dyn_cast_or_null<TypeSystemClang>(type_system);
  if (!clang_type_system)
    return false;
  DWARFASTParserClang *ast_parser =
      static_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());

  TypeSystemClang *clang_type_system =
      llvm::dyn_cast_or_null<TypeSystemClang>(compiler_type.GetTypeSystem());
  if (clang_type_system) {
    DWARFASTParserClang *ast_parser =
        static_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 = GetForwardDeclClangTypeToDie().find(
      compiler_type_no_qualifiers.GetOpaqueQualType());
  if (die_it == GetForwardDeclClangTypeToDie().end()) {
    // We have already resolved this type...
    return true;
  }

  DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
  if (dwarf_die) {
    // Once we start resolving this type, remove it from the forward
    // declaration map in case anyone child members or other types require this
    // type to get resolved. The type will get resolved when all of the calls
    // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
    GetForwardDeclClangTypeToDie().erase(die_it);

    Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());

    Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO |
                                          DWARF_LOG_TYPE_COMPLETION));
    if (log)
      GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
          log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
          dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
          type->GetName().AsCString());
    assert(compiler_type);
    if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
      return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
  }
  return false;
}

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: 0x%8.8x: %s %s",
          die.GetOffset(), die.GetTagAsCString(), die.GetName());

    } else
      return type;
  }
  return nullptr;
}

CompileUnit *
SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) {
  if (dwarf_cu.IsDWOUnit()) {
    DWARFCompileUnit *non_dwo_cu =
        static_cast<DWARFCompileUnit *>(dwarf_cu.GetUserData());
    assert(non_dwo_cu);
    return non_dwo_cu->GetSymbolFileDWARF().GetCompUnitForDWARFCompUnit(
        *non_dwo_cu);
  }
  // Check if the symbol vendor already knows about this compile unit?
  if (dwarf_cu.GetUserData() == nullptr) {
    // 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();
  }
  return static_cast<CompileUnit *>(dwarf_cu.GetUserData());
}

void SymbolFileDWARF::GetObjCMethods(
    ConstString class_name, llvm::function_ref<bool(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 pos->second;
  else
    return lldb::ModuleSP();
}

DWARFDIE
SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
  if (die_ref.dwo_num()) {
    SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x3fffffff
                                 ? m_dwp_symfile.get()
                                 : this->DebugInfo()
                                       .GetUnitAtIndex(*die_ref.dwo_num())
                                       ->GetDwoSymbolFile();
    return dwarf->DebugInfo().GetDIE(die_ref);
  }

  return DebugInfo().GetDIE(die_ref);
}

/// Return the DW_AT_(GNU_)dwo_id.
/// FIXME: Technically 0 is a valid hash.
static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,
                         const DWARFDebugInfoEntry &cu_die) {
  uint64_t dwo_id =
      cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0);
  if (!dwo_id)
    dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0);
  return dwo_id;
}

llvm::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())
          if (uint64_t dwo_id = ::GetDWOId(*cu, *cu_die))
            return dwo_id;
  }
  return {};
}

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.
  if (!dwarf_cu)
    return nullptr;

  const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
  if (!dwo_name)
    return nullptr;

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

  FileSpec dwo_file(dwo_name);
  FileSystem::Instance().Resolve(dwo_file);
  if (dwo_file.IsRelative()) {
    const char *comp_dir =
        cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr);
    if (!comp_dir)
      return nullptr;

    dwo_file.SetFile(comp_dir, FileSpec::Style::native);
    if (dwo_file.IsRelative()) {
      // 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.
      dwo_file.PrependPathComponent(
          m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
    }
    FileSystem::Instance().Resolve(dwo_file);
    dwo_file.AppendPathComponent(dwo_name);
  }

  if (!FileSystem::Instance().Exists(dwo_file))
    return nullptr;

  const lldb::offset_t file_offset = 0;
  DataBufferSP dwo_file_data_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_data_sp,
      dwo_file_data_offset);
  if (dwo_obj_file == nullptr)
    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())
            .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
      continue;
    }

    Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
                                               nullptr, nullptr, nullptr);
    if (!module_sp) {
      GetObjectFile()->GetModule()->ReportWarning(
          "0x%8.8x: unable to locate module needed for external types: "
          "%s\nerror: %s\nDebugging will be degraded due to missing "
          "types. Rebuilding the project will regenerate the needed "
          "module files.",
          die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
          error.AsCString("unknown error"));
      continue;
    }

    // Verify the DWO hash.
    // FIXME: Technically "0" is a valid hash.
    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;
    llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
    if (!dwo_dwo_id)
      continue;

    if (dwo_id != dwo_dwo_id) {
      GetObjectFile()->GetModule()->ReportWarning(
          "0x%8.8x: Module %s is out-of-date (hash mismatch). 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.",
          die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
    }
  }
}

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 DWARFExpression &location = var_sp->LocationExpression();
                Value location_result;
                Status error;
                if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr,
                                      nullptr, location_result, &error)) {
                  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 =
                          var_sp->GetType()->GetByteSize(nullptr).getValueOr(0);
                    m_global_aranges_up->Append(GlobalVariableMap::Entry(
                        file_addr, byte_size, var_sp.get()));
                  }
                }
              }
            }
          }
        }
      }
    }
    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(
              "0x%8.8x: compile unit %u 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(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
                   std::move(err),
                   "Unable to match namespace decl using TypeSystem");
    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(LogChannelDWARF::GetLogIfAll(DWARF_LOG_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(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log)
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
        "parent_decl_ctx=%p, max_matches=%u, 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 = (bool)Mangled(name);

  if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(),
                                                      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)
      return true;

    auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
    if (!dwarf_cu)
      return true;
    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 (!actual_parent_decl_ctx ||
            actual_parent_decl_ctx != parent_decl_ctx)
          return true;
      }
    }

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

    return variables.GetSize() - original_size < max_matches;
  });

  // 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=\"%s\", "
        "parent_decl_ctx=%p, max_matches=%u, variables) => %u",
        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(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", "
        "max_matches=%u, 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 true;
    sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);

    ParseAndAppendGlobalVariable(sc, die, variables);

    return variables.GetSize() - original_size < max_matches;
  });
}

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)) {
    Address addr;
    // 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());
      if (sc.block == nullptr || !sc.block->GetStartAddress(addr))
        addr.Clear();
    } else {
      sc.block = nullptr;
      addr = sc.function->GetAddressRange().GetBaseAddress();
    }

    sc_list.Append(sc);
    return true;
  }

  return false;
}

bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
                                       const DWARFDIE &die) {
  // 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())
    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(ConstString name,
                                    const CompilerDeclContext &parent_decl_ctx,
                                    FunctionNameType name_type_mask,
                                    bool include_inlines,
                                    SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  LLDB_SCOPED_TIMERF("SymbolFileDWARF::FindFunctions (name = '%s')",
                     name.AsCString());

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

  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%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(name, *this, parent_decl_ctx, name_type_mask,
                        [&](DWARFDIE die) {
                          if (resolved_dies.insert(die.GetDIE()).second)
                            ResolveFunction(die, include_inlines, sc_list);
                          return true;
                        });

  // 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=\"%s\", "
        "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u",
        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(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log) {
    GetObjectFile()->GetModule()->LogMessage(
        log, "SymbolFileDWARF::FindFunctions (regex=\"%s\", 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 true;
  });
}

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

void SymbolFileDWARF::FindTypes(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    uint32_t max_matches,
    llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
    TypeMap &types) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Make sure we haven't already searched this SymbolFile before.
  if (!searched_symbol_files.insert(this).second)
    return;

  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log) {
    if (parent_decl_ctx)
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
          "%p (\"%s\"), max_matches=%u, type_list)",
          name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
          parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches);
    else
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
          "NULL, max_matches=%u, type_list)",
          name.GetCString(), max_matches);
  }

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return;

  m_index->GetTypes(name, [&](DWARFDIE die) {
    if (!DIEInDeclContext(parent_decl_ctx, die))
      return true; // The containing decl contexts don't match

    Type *matching_type = ResolveType(die, true, true);
    if (!matching_type)
      return true;

    // We found a type pointer, now find the shared pointer form our type
    // list
    types.InsertUnique(matching_type->shared_from_this());
    return types.GetSize() < max_matches;
  });

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

    for (const auto &pair : m_external_type_modules)
      if (ModuleSP external_module_sp = pair.second)
        if (SymbolFile *sym_file = external_module_sp->GetSymbolFile())
          sym_file->FindTypes(name, parent_decl_ctx, max_matches,
                              searched_symbol_files, types);
  }

  if (log && types.GetSize()) {
    if (parent_decl_ctx) {
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
          "= %p (\"%s\"), max_matches=%u, type_list) => %u",
          name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
          parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches,
          types.GetSize());
    } else {
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
          "= NULL, max_matches=%u, type_list) => %u",
          name.GetCString(), max_matches, types.GetSize());
    }
  }
}

void SymbolFileDWARF::FindTypes(
    llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
    llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
  // Make sure we haven't already searched this SymbolFile before.
  if (!searched_symbol_files.insert(this).second)
    return;

  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (pattern.empty())
    return;

  ConstString name = pattern.back().name;

  if (!name)
    return;

  m_index->GetTypes(name, [&](DWARFDIE die) {
    if (!languages[GetLanguageFamily(*die.GetCU())])
      return true;

    llvm::SmallVector<CompilerContext, 4> die_context;
    die.GetDeclContext(die_context);
    if (!contextMatches(die_context, pattern))
      return true;

    if (Type *matching_type = ResolveType(die, true, true)) {
      // We found a type pointer, now find the shared pointer form our type
      // list.
      types.InsertUnique(matching_type->shared_from_this());
    }
    return true;
  });

  // 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(pattern, languages, searched_symbol_files,
                                    types);
}

CompilerDeclContext
SymbolFileDWARF::FindNamespace(ConstString name,
                               const CompilerDeclContext &parent_decl_ctx) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

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

  CompilerDeclContext namespace_decl_ctx;

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return namespace_decl_ctx;

  m_index->GetNamespaces(name, [&](DWARFDIE die) {
    if (!DIEInDeclContext(parent_decl_ctx, die))
      return true; // The containing decl contexts don't match

    DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU());
    if (!dwarf_ast)
      return true;

    namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die);
    return !namespace_decl_ctx.IsValid();
  });

  if (log && namespace_decl_ctx) {
    GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => "
        "CompilerDeclContext(%p/%p) \"%s\"",
        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;
}

// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If
// they don't then we can end up looking through all class types for a complete
// type and never find the full definition. We need to know if this attribute
// is supported, so we determine this here and cache th result. We also need to
// worry about the debug map
// DWARF file
// if we are doing darwin DWARF in .o file debugging.
bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) {
  if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
    m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
    if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
      m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
    else {
      DWARFDebugInfo &debug_info = DebugInfo();
      const uint32_t num_compile_units = GetNumCompileUnits();
      for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
        DWARFUnit *dwarf_cu = debug_info.GetUnitAtIndex(cu_idx);
        if (dwarf_cu != cu &&
            dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) {
          m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
          break;
        }
      }
    }
    if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolNo &&
        GetDebugMapSymfile())
      return m_debug_map_symfile->Supports_DW_AT_APPLE_objc_complete_type(this);
  }
  return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
}

// 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) {
        bool try_resolving_type = false;

        // Don't try and resolve the DIE we are looking for with the DIE
        // itself!
        if (type_die != die) {
          switch (type_die.Tag()) {
          case DW_TAG_class_type:
          case DW_TAG_structure_type:
            try_resolving_type = true;
            break;
          default:
            break;
          }
        }
        if (!try_resolving_type)
          return true;

        if (must_be_implementation &&
            type_die.Supports_DW_AT_APPLE_objc_complete_type())
          try_resolving_type = type_die.GetAttributeValueAsUnsigned(
              DW_AT_APPLE_objc_complete_type, 0);
        if (!try_resolving_type)
          return true;

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

        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 false;
      });
  return type_sp;
}

// This function helps to ensure that the declaration contexts match for two
// different DIEs. Often times debug information will refer to a forward
// declaration of a type (the equivalent of "struct my_struct;". There will
// often be a declaration of that type elsewhere that has the full definition.
// When we go looking for the full type "my_struct", we will find one or more
// matches in the accelerator tables and we will then need to make sure the
// type was in the same declaration context as the original DIE. This function
// can efficiently compare two DIEs and will return true when the declaration
// context matches, and false when they don't.
bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
                                           const DWARFDIE &die2) {
  if (die1 == die2)
    return true;

  std::vector<DWARFDIE> decl_ctx_1;
  std::vector<DWARFDIE> decl_ctx_2;
  // The declaration DIE stack is a stack of the declaration context DIEs all
  // the way back to the compile unit. If a type "T" is declared inside a class
  // "B", and class "B" is declared inside a class "A" and class "A" is in a
  // namespace "lldb", and the namespace is in a compile unit, there will be a
  // stack of DIEs:
  //
  //   [0] DW_TAG_class_type for "B"
  //   [1] DW_TAG_class_type for "A"
  //   [2] DW_TAG_namespace  for "lldb"
  //   [3] DW_TAG_compile_unit or DW_TAG_partial_unit for the source file.
  //
  // We grab both contexts and make sure that everything matches all the way
  // back to the compiler unit.

  // First lets grab the decl contexts for both DIEs
  decl_ctx_1 = die1.GetDeclContextDIEs();
  decl_ctx_2 = die2.GetDeclContextDIEs();
  // Make sure the context arrays have the same size, otherwise we are done
  const size_t count1 = decl_ctx_1.size();
  const size_t count2 = decl_ctx_2.size();
  if (count1 != count2)
    return false;

  // Make sure the DW_TAG values match all the way back up the compile unit. If
  // they don't, then we are done.
  DWARFDIE decl_ctx_die1;
  DWARFDIE decl_ctx_die2;
  size_t i;
  for (i = 0; i < count1; i++) {
    decl_ctx_die1 = decl_ctx_1[i];
    decl_ctx_die2 = decl_ctx_2[i];
    if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())
      return false;
  }
#ifndef NDEBUG

  // Make sure the top item in the decl context die array is always
  // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then
  // something went wrong in the DWARFDIE::GetDeclContextDIEs()
  // function.
  dw_tag_t cu_tag = decl_ctx_1[count1 - 1].Tag();
  UNUSED_IF_ASSERT_DISABLED(cu_tag);
  assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit);

#endif
  // Always skip the compile unit when comparing by only iterating up to "count
  // - 1". Here we compare the names as we go.
  for (i = 0; i < count1 - 1; i++) {
    decl_ctx_die1 = decl_ctx_1[i];
    decl_ctx_die2 = decl_ctx_2[i];
    const char *name1 = decl_ctx_die1.GetName();
    const char *name2 = decl_ctx_die2.GetName();
    // If the string was from a DW_FORM_strp, then the pointer will often be
    // the same!
    if (name1 == name2)
      continue;

    // Name pointers are not equal, so only compare the strings if both are not
    // NULL.
    if (name1 && name2) {
      // If the strings don't compare, we are done...
      if (strcmp(name1, name2) != 0)
        return false;
    } else {
      // One name was NULL while the other wasn't
      return false;
    }
  }
  // We made it through all of the checks and the declaration contexts are
  // equal.
  return true;
}

TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
    const DWARFDeclContext &dwarf_decl_ctx) {
  TypeSP type_sp;

  const uint32_t dwarf_decl_ctx_count = dwarf_decl_ctx.GetSize();
  if (dwarf_decl_ctx_count > 0) {
    const ConstString type_name(dwarf_decl_ctx[0].name);
    const dw_tag_t tag = dwarf_decl_ctx[0].tag;

    if (type_name) {
      Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
                                            DWARF_LOG_LOOKUPS));
      if (log) {
        GetObjectFile()->GetModule()->LogMessage(
            log,
            "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%"
            "s, qualified-name='%s')",
            DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
            dwarf_decl_ctx.GetQualifiedName());
      }

      // 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 = dwarf_decl_ctx.GetLanguage();
      TypeSystem *type_system = nullptr;
      if (language != eLanguageTypeUnknown) {
        auto type_system_or_err = GetTypeSystemForLanguage(language);
        if (auto err = type_system_or_err.takeError()) {
          LLDB_LOG_ERROR(
              lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
              std::move(err), "Cannot get TypeSystem for language {}",
              Language::GetNameForLanguageType(language));
        } else {
          type_system = &type_system_or_err.get();
        }
      }

      m_index->GetTypes(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 true;
        bool try_resolving_type = false;

        // Don't try and resolve the DIE we are looking for with the DIE
        // itself!
        const dw_tag_t type_tag = type_die.Tag();
        // Make sure the tags match
        if (type_tag == tag) {
          // The tags match, lets try resolving this type
          try_resolving_type = true;
        } else {
          // The tags don't match, but we need to watch our for a forward
          // declaration for a struct and ("struct foo") ends up being a
          // class ("class foo { ... };") or vice versa.
          switch (type_tag) {
          case DW_TAG_class_type:
            // We had a "class foo", see if we ended up with a "struct foo
            // { ... };"
            try_resolving_type = (tag == DW_TAG_structure_type);
            break;
          case DW_TAG_structure_type:
            // We had a "struct foo", see if we ended up with a "class foo
            // { ... };"
            try_resolving_type = (tag == DW_TAG_class_type);
            break;
          default:
            // Tags don't match, don't event try to resolve using this type
            // whose name matches....
            break;
          }
        }

        if (!try_resolving_type) {
          if (log) {
            std::string qualified_name;
            type_die.GetQualifiedName(qualified_name);
            GetObjectFile()->GetModule()->LogMessage(
                log,
                "SymbolFileDWARF::"
                "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
                "qualified-name='%s') ignoring die=0x%8.8x (%s)",
                DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
                dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(),
                qualified_name.c_str());
          }
          return true;
        }

        DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);

        if (log) {
          GetObjectFile()->GetModule()->LogMessage(
              log,
              "SymbolFileDWARF::"
              "FindDefinitionTypeForDWARFDeclContext(tag=%s, "
              "qualified-name='%s') trying die=0x%8.8x (%s)",
              DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
              dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(),
              type_dwarf_decl_ctx.GetQualifiedName());
        }

        // Make sure the decl contexts match all the way up
        if (dwarf_decl_ctx != type_dwarf_decl_ctx)
          return true;

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

        type_sp = resolved_type->shared_from_this();
        return false;
      });
    }
  }
  return type_sp;
}

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(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
                   std::move(err), "Unable to parse type");
    return {};
  }

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

  TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr);
  if (type_sp) {
    GetTypeList().Insert(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 = func.GetID();
  DWARFDIE function_die =
      dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset);
  if (function_die) {
    ParseBlocksRecursive(*comp_unit, &func.GetBlock(false), function_die,
                         LLDB_INVALID_ADDRESS, 0);
  }

  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;
      DWARFRangeList ranges;
      if (function_die.GetDIE()->GetAttributeAddressRanges(
              function_die.GetCU(), ranges,
              /*check_hi_lo_pc=*/true))
        func_lo_pc = ranges.GetMinRangeBase(0);
      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 true;
        });
      }
      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;
}

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_formal_parameter || !sc.function))
    return nullptr;

  DWARFAttributes attributes;
  const size_t num_attributes = die.GetAttributes(attributes);
  const char *name = nullptr;
  const char *mangled = nullptr;
  Declaration decl;
  DWARFFormValue type_die_form;
  DWARFExpression location;
  bool is_external = false;
  bool is_artificial = false;
  DWARFFormValue const_value_form, location_form;
  Variable::RangeList scope_ranges;

  for (size_t i = 0; i < num_attributes; ++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:
      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 will be
  // present in the class declaration and DW_AT_location in the DIE defining
  // the member.
  bool location_is_const_value_data = false;
  bool has_explicit_location = false;
  bool use_type_size_for_value = false;
  if (location_form.IsValid()) {
    has_explicit_location = true;
    if (DWARFFormValue::IsBlockForm(location_form.Form())) {
      const DWARFDataExtractor &data = die.GetData();

      uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
      uint32_t block_length = location_form.Unsigned();
      location = DWARFExpression(
          module, DataExtractor(data, block_offset, block_length), die.GetCU());
    } else {
      DataExtractor data = die.GetCU()->GetLocationData();
      dw_offset_t offset = location_form.Unsigned();
      if (location_form.Form() == DW_FORM_loclistx)
        offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
      if (data.ValidOffset(offset)) {
        data = DataExtractor(data, offset, data.GetByteSize() - offset);
        location = DWARFExpression(module, data, die.GetCU());
        assert(func_low_pc != LLDB_INVALID_ADDRESS);
        location.SetLocationListAddresses(
            location_form.GetUnit()->GetBaseAddress(), func_low_pc);
      }
    }
  } else if (const_value_form.IsValid()) {
    location_is_const_value_data = true;
    // The constant value will be either a block, a data value or a
    // string.
    const DWARFDataExtractor &debug_info_data = die.GetData();
    if (DWARFFormValue::IsBlockForm(const_value_form.Form())) {
      // Retrieve the value as a block expression.
      uint32_t block_offset =
          const_value_form.BlockData() - debug_info_data.GetDataStart();
      uint32_t block_length = const_value_form.Unsigned();
      location = DWARFExpression(
          module, DataExtractor(debug_info_data, block_offset, block_length),
          die.GetCU());
    } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
      // Constant value size does not have to match the size of the
      // variable. We will fetch the size of the type after we create
      // it.
      use_type_size_for_value = true;
    } else if (const char *str = const_value_form.AsCString()) {
      uint32_t string_length = strlen(str) + 1;
      location = DWARFExpression(
          module,
          DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
                        die.GetCU()->GetAddressByteSize()),
          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 =
          GetDWARFDeclContext(die).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 is_static_lifetime =
        has_explicit_mangled || (has_explicit_location && !location.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) {
      bool op_error = false;
      location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error);
      if (op_error) {
        StreamString strm;
        location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0,
                                        nullptr);
        GetObjectFile()->GetModule()->ReportError(
            "0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
            die.GetTagAsCString(), 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.SetModule(debug_map_symfile->GetObjectFile()->GetModule());

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

      if (debug_map_symfile) {
        // When leaving the DWARF in the .o files on darwin, when we have a
        // global variable that wasn't initialized, the .o file might not
        // have allocated a virtual address for the global variable. In
        // this case it will have created a symbol for the global variable
        // that is undefined/data and external and the value will be the
        // byte size of the variable. When we do the address map in
        // SymbolFileDWARFDebugMap we rely on having an address, we need to
        // do some magic here so we can get the correct address for our
        // global variable. The address for all of these entries will be
        // zero, and there will be an undefined symbol in this object file,
        // and the executable will have a matching symbol with a good
        // address. So here we dig up the correct address and replace it in
        // the location for the variable, and set the variable's symbol
        // context scope to be that of the main executable so the file
        // address will resolve correctly.
        bool linked_oso_file_addr = false;
        if (is_external && location_DW_OP_addr == 0) {
          // we have a possible uninitialized extern global
          ConstString const_name(mangled ? mangled : name);
          ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
          if (debug_map_objfile) {
            Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
            if (debug_map_symtab) {
              Symbol *exe_symbol =
                  debug_map_symtab->FindFirstSymbolWithNameAndType(
                      const_name, eSymbolTypeData, Symtab::eDebugYes,
                      Symtab::eVisibilityExtern);
              if (exe_symbol) {
                if (exe_symbol->ValueIsAddress()) {
                  const addr_t exe_file_addr =
                      exe_symbol->GetAddressRef().GetFileAddress();
                  if (exe_file_addr != LLDB_INVALID_ADDRESS) {
                    if (location.Update_DW_OP_addr(exe_file_addr)) {
                      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
            location.Update_DW_OP_addr(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.ContainsThreadLocalStorage()) {
            location.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, GetUID(type_die_form.Reference()));

  if (use_type_size_for_value && type_sp->GetType())
    location.UpdateValue(const_value_form.Unsigned(),
                         type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
                         die.GetCU()->GetAddressByteSize());

  return std::make_shared<Variable>(
      die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
      scope_ranges, &decl, location, 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(DebugInfo().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)
    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 0x%8.8" PRIx64 " %s with no valid compile unit in "
          "symbol context for 0x%8.8" PRIx64 " %s.\n",
          sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), die.GetID(),
          die.GetTagAsCString());
      return;
    }
    break;

  default:
    GetObjectFile()->GetModule()->ReportError(
        "didn't find appropriate parent DIE for variable list for "
        "0x%8.8" PRIx64 " %s.\n",
        die.GetID(), die.GetTagAsCString());
    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;

    llvm::Optional<DWARFExpression> LocationInCallee;
    llvm::Optional<DWARFExpression> LocationInCaller;

    DWARFAttributes attributes;
    const size_t num_attributes = child.GetAttributes(attributes);

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

    for (size_t i = 0; i < num_attributes; ++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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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;

    llvm::Optional<DWARFDIE> call_origin;
    llvm::Optional<DWARFExpression> 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;
    const size_t num_attributes =
        child.GetAttributes(attributes, DWARFDIE::Recurse::no);
    for (size_t i = 0; i < num_attributes; ++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();
        uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
        uint32_t block_length = form_value.Unsigned();
        call_target = DWARFExpression(
            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,
                                    LLDB_INVALID_ADDRESS, 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,
                                              LLDB_INVALID_ADDRESS, nullptr);
        param.LocationInCaller.GetDescription(&caller_loc_desc,
                                              eDescriptionLevelBrief,
                                              LLDB_INVALID_ADDRESS, 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(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) {
  SymbolFile::Dump(s);
  m_index->Dump(s);
}

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

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 =
          static_cast<SymbolFileDWARFDebugMap *>(module_sp->GetSymbolFile());
    }
  }
  return m_debug_map_symfile;
}

const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
  llvm::call_once(m_dwp_symfile_once_flag, [this]() {
    ModuleSpec module_spec;
    module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec();
    module_spec.GetSymbolFileSpec() =
        FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp");

    FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
    FileSpec dwp_filespec =
        Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
    if (FileSystem::Instance().Exists(dwp_filespec)) {
      DataBufferSP dwp_file_data_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_data_sp,
          dwp_file_data_offset);
      if (!dwp_obj_file)
        return;
      m_dwp_symfile =
          std::make_shared<SymbolFileDWARFDwo>(*this, dwp_obj_file, 0x3fffffff);
    }
  });
  return m_dwp_symfile;
}

llvm::Expected<TypeSystem &> 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(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
                   std::move(err), "Unable to get DWARFASTParser");
    return nullptr;
  }
  return type_system_or_err->GetDWARFParser();
}

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

DWARFDeclContext SymbolFileDWARF::GetDWARFDeclContext(const DWARFDIE &die) {
  if (!die.IsValid())
    return {};
  DWARFDeclContext dwarf_decl_ctx =
      die.GetDIE()->GetDWARFDeclContext(die.GetCU());
  dwarf_decl_ctx.SetLanguage(GetLanguage(*die.GetCU()));
  return dwarf_decl_ctx;
}

LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) {
  // Note: user languages between lo_user and hi_user must be handled
  // explicitly here.
  switch (val) {
  case DW_LANG_Mips_Assembler:
    return eLanguageTypeMipsAssembler;
  case DW_LANG_GOOGLE_RenderScript:
    return eLanguageTypeExtRenderScript;
  default:
    return static_cast<LanguageType>(val);
  }
}

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 SymbolFileDWARF::GetDebugInfoIndexTime() {
  if (m_index)
    return m_index->GetIndexTime();
  return StatsDuration(0.0);
}
