//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===//
//
// 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/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/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 "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangUtil.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 "SymbolFileDWARFDwp.h"

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

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

#include <ctype.h>
#include <string.h>

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

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

using namespace lldb;
using namespace lldb_private;

// static inline bool
// child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
//{
//    switch (tag)
//    {
//    default:
//        break;
//    case DW_TAG_subprogram:
//    case DW_TAG_inlined_subroutine:
//    case DW_TAG_class_type:
//    case DW_TAG_structure_type:
//    case DW_TAG_union_type:
//        return true;
//    }
//    return false;
//}
//

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

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

  FileSpecList GetSymLinkPaths() {
    const OptionValueFileSpecList *option_value =
        m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(
            nullptr, true, ePropertySymLinkPaths);
    assert(option_value);
    return option_value->GetCurrentValue();
  }

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

typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;

static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() {
  static const auto g_settings_sp(std::make_shared<PluginProperties>());
  return g_settings_sp;
}

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

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

static FileSpecList
ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
                              const llvm::DWARFDebugLine::Prologue &prologue,
                              llvm::StringRef compile_dir = {},
                              FileSpec first_file = {}) {
  FileSpecList support_files;
  support_files.Append(first_file);

  llvm::Optional<FileSpec::Style> compile_dir_style =
      FileSpec::GuessPathStyle(compile_dir);
  const size_t number_of_files = prologue.FileNames.size();
  for (size_t idx = 1; idx <= number_of_files; ++idx) {
    std::string original_file;
    if (!prologue.getFileNameByIndex(
            idx, compile_dir,
            llvm::DILineInfoSpecifier::FileLineInfoKind::Default,
            original_file)) {
      // Always add an entry so the indexes remain correct.
      support_files.EmplaceBack();
      continue;
    }

    FileSpec::Style style = FileSpec::Style::native;
    if (compile_dir_style) {
      style = *compile_dir_style;
    } else if (llvm::Optional<FileSpec::Style> file_style =
                   FileSpec::GuessPathStyle(original_file)) {
      style = *file_style;
    }

    std::string remapped_file;
    if (!prologue.getFileNameByIndex(
            idx, compile_dir,
            llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
            remapped_file)) {
      // Always add an entry so the indexes remain correct.
      support_files.EmplaceBack(original_file, style);
      continue;
    }

    module->RemapSourceFile(llvm::StringRef(original_file), remapped_file);
    support_files.EmplaceBack(remapped_file, style);
  }

  return support_files;
}

FileSpecList SymbolFileDWARF::GetSymlinkPaths() {
  return GetGlobalPluginProperties()->GetSymLinkPaths();
}

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

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() {
  PluginManager::UnregisterPlugin(CreateInstance);
  LogChannelDWARF::Terminate();
}

lldb_private::ConstString SymbolFileDWARF::GetPluginNameStatic() {
  static ConstString g_name("dwarf");
  return g_name;
}

const char *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;
      }

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

    for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
         child_die = child_die.GetSibling()) {
      GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set);
    }
  }
}

size_t 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;
  DWARFUnit *dwarf_cu = nullptr;
  if (sc_scope)
    comp_unit = sc_scope->CalculateSymbolContextCompileUnit();

  if (comp_unit) {
    dwarf_cu = GetDWARFCompileUnit(comp_unit);
    if (dwarf_cu == nullptr)
      return 0;
    GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(),
             dwarf_cu->GetNextUnitOffset(), type_mask, type_set);
  } else {
    DWARFDebugInfo *info = DebugInfo();
    if (info) {
      const size_t num_cus = info->GetNumUnits();
      for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) {
        dwarf_cu = info->GetUnitAtIndex(cu_idx);
        if (dwarf_cu) {
          GetTypes(dwarf_cu->DIE(), 0, UINT32_MAX, type_mask, type_set);
        }
      }
    }
  }

  std::set<CompilerType> compiler_type_set;
  size_t num_types_added = 0;
  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());
      ++num_types_added;
    }
  }
  return num_types_added;
}

// 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;
    }
  }
  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_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false),
      m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate),
      m_unique_ast_type_map() {}

SymbolFileDWARF::~SymbolFileDWARF() {}

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

  if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
    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);

    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) {
      llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
          DebugNamesDWARFIndex::Create(
              *GetObjectFile()->GetModule(), debug_names,
              m_context.getOrLoadStrData(), DebugInfo());
      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 = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(),
                                                DebugInfo());
}

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

const DWARFDataExtractor &
SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type,
                                      DWARFDataSegment &data_segment) {
  llvm::call_once(data_segment.m_flag, [this, sect_type, &data_segment] {
    this->LoadSectionData(sect_type, std::ref(data_segment.m_data));
  });
  return data_segment.m_data;
}

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

const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() {
  const DWARFDataExtractor &debugLocData = get_debug_loc_data();
  if (debugLocData.GetByteSize() > 0)
    return debugLocData;
  return get_debug_loclists_data();
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugLocLists,
                              m_data_debug_loclists);
}

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

const DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() const {
  return m_abbr.get();
}

DWARFDebugInfo *SymbolFileDWARF::DebugInfo() {
  if (m_info == nullptr) {
    static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
    Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));
    if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0)
      m_info = llvm::make_unique<DWARFDebugInfo>(*this, m_context);
  }
  return m_info.get();
}

const DWARFDebugInfo *SymbolFileDWARF::DebugInfo() const {
  return m_info.get();
}

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

  DWARFDebugInfo *info = DebugInfo();
  if (info) {
    // The compile unit ID is the index of the DWARF unit.
    DWARFUnit *dwarf_cu = info->GetUnitAtIndex(comp_unit->GetID());
    if (dwarf_cu && dwarf_cu->GetUserData() == nullptr)
      dwarf_cu->SetUserData(comp_unit);
    return dwarf_cu;
  }
  return nullptr;
}

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

    if (m_context.getOrLoadRangesData().GetByteSize() > 0)
      m_ranges.reset(new DWARFDebugRanges());

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

DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() {
  if (!m_rnglists) {
    static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
    Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));

    if (m_context.getOrLoadRngListsData().GetByteSize() > 0)
      m_rnglists.reset(new DWARFDebugRngLists());

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

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.GetSymbolFileDWARF() != this) {
      return dwarf_cu.GetSymbolFileDWARF().ParseCompileUnit(dwarf_cu);
    } 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) {
        const DWARFDIE cu_die = dwarf_cu.DIE();
        if (cu_die) {
          FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
          if (cu_file_spec) {
            // 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.
            cu_file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory());

            std::string remapped_file;
            if (module_sp->RemapSourceFile(cu_file_spec.GetPath(),
                                           remapped_file))
              cu_file_spec.SetFile(remapped_file, FileSpec::Style::native);
          }

          LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
              cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));

          bool is_optimized = dwarf_cu.GetIsOptimized();
          BuildCuTranslationTable();
          cu_sp = std::make_shared<CompileUnit>(
              module_sp, &dwarf_cu, cu_file_spec,
              *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
              is_optimized ? eLazyBoolYes : eLazyBoolNo);

          dwarf_cu.SetUserData(cu_sp.get());

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

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

  DWARFDebugInfo *info = DebugInfo();
  if (!info)
    return;

  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() {
  DWARFDebugInfo *info = DebugInfo();
  if (!info)
    return 0;
  BuildCuTranslationTable();
  return m_lldb_cu_to_dwarf_unit.empty() ? info->GetNumUnits()
                                         : m_lldb_cu_to_dwarf_unit.size();
}

CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
  ASSERT_MODULE_LOCK(this);
  DWARFDebugInfo *info = DebugInfo();
  if (!info)
    return {};

  if (llvm::Optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) {
    if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>(
            info->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(die.GetCU()->GetLanguageType());
  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;

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

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 dwarf_cu->GetLanguageType();
  else
    return eLanguageTypeUnknown;
}

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

  size_t functions_added = 0;
  std::vector<DWARFDIE> function_dies;
  dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies);
  for (const DWARFDIE &die : function_dies) {
    if (comp_unit.FindFunctionByUID(die.GetID()))
      continue;
    if (ParseFunction(comp_unit, die))
      ++functions_added;
  }
  // FixupTypes();
  return functions_added;
}

bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
                                        FileSpecList &support_files) {
  if (!comp_unit.GetLineTable())
    ParseLineTable(comp_unit);
  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;
    llvm::Error error = prologue.parse(data, &line_table_offset, ctx);
    if (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");
    } else {
      list =
          ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), prologue);
    }
  }
  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->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.GetFirstChild(); child_die;
       child_die = child_die.GetSibling()) {
    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))
        module.search_path = ConstString(include_path);
      if (const char *sysroot = module_die.GetAttributeValueAsString(
              DW_AT_LLVM_isysroot, 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;

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

  const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(
      DW_AT_stmt_list, DW_INVALID_OFFSET);
  if (cu_line_offset == DW_INVALID_OFFSET)
    return false;

  llvm::DWARFDebugLine line;
  const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable(
      m_context, line, cu_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::unique_ptr<LineTable> line_table_up =
      llvm::make_unique<LineTable>(&comp_unit);
  LineSequence *sequence = line_table_up->CreateLineSequenceContainer();
  for (auto &row : line_table->Rows) {
    line_table_up->AppendLineEntryToSequence(
        sequence, row.Address.Address, row.Line, row.Column, row.File,
        row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
        row.EndSequence);
    if (row.EndSequence) {
      line_table_up->InsertSequence(sequence);
      sequence = line_table_up->CreateLineSequenceContainer();
    }
  }

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

  comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
      comp_unit.GetModule(), line_table->Prologue,
      dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit)));

  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;

  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.reset(new 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.reset(new 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.GetFirstChild(); die;
         die = die.GetSibling()) {
      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)
    return;
  DWARFASTParser *ast_parser = type_system->GetDWARFParser();
  std::vector<DWARFDIE> decl_ctx_die_list =
      ast_parser->GetDIEForDeclContext(decl_ctx);

  for (DWARFDIE decl_ctx_die : decl_ctx_die_list)
    for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl;
         decl = decl.GetSibling())
      ast_parser->GetDeclForUIDFromDWARF(decl);
}

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

  return user_id_t(GetDwoNum().getValueOr(0x7fffffff)) << 32 |
         ref.die_offset() |
         (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 = uid >> 32 & 0x7fffffff;
  if (*dwo_num == 0x7fffffff)
    dwo_num = llvm::None;

  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 die.GetDecl();
  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 die.GetDeclContext();
  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 die.GetContainingDeclContext();
  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();

  ClangASTContext *clang_type_system =
      llvm::dyn_cast_or_null<ClangASTContext>(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());

  ClangASTContext *clang_type_system =
      llvm::dyn_cast_or_null<ClangASTContext>(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);
    DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser();
    if (dwarf_ast)
      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) {
  // 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 (CompileUnit *)dwarf_cu.GetUserData();
}

size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
                                                DIEArray &method_die_offsets) {
  method_die_offsets.clear();
  m_index->GetObjCMethods(class_name, method_die_offsets);
  return method_die_offsets.size();
}

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::GetDWOModule(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()) {
    return DebugInfo()
        ->GetUnitAtIndex(*die_ref.dwo_num())
        ->GetDwoSymbolFile()
        ->GetDIE(die_ref);
  }

  DWARFDebugInfo *debug_info = DebugInfo();
  if (debug_info)
    return debug_info->GetDIE(die_ref);
  else
    return DWARFDIE();
}

std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
    DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
  // If we are using a dSYM file, we never want the standard DWO files since
  // the -gmodules support uses the same DWO machanism to specify full debug
  // info files for modules.
  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 =
      cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
  if (!dwo_name)
    return nullptr;

  SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile();
  if (dwp_symfile) {
    uint64_t dwo_id =
        cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0);
    std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile =
        dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id);
    if (dwo_symfile)
      return dwo_symfile;
  }

  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);
    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 llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu);
}

void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
  if (m_fetched_external_modules)
    return;
  m_fetched_external_modules = true;

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

    const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
    if (die && !die.HasChildren()) {
      const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);

      if (name) {
        ConstString const_name(name);
        if (m_external_type_modules.find(const_name) ==
            m_external_type_modules.end()) {
          ModuleSP module_sp;
          const char *dwo_path =
              die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
          if (dwo_path) {
            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_GNU_dwo_name. However, when the already created module
            // (corresponding to .dwo itself) is being processed, it will see
            // the presence of DW_AT_GNU_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_GNU_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 your project will regenerate the needed "
                  "module files.",
                  die.GetOffset(),
                  dwo_module_spec.GetFileSpec().GetPath().c_str(),
                  error.AsCString("unknown error"));
            }
          }
          m_external_type_modules[const_name] = module_sp;
        }
      }
    }
  }
}

SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
  if (!m_global_aranges_up) {
    m_global_aranges_up.reset(new 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::eValueTypeFileAddress) {
                    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().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;
}

uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
                                               SymbolContextItem resolve_scope,
                                               SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat,
                     "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();
    if (debug_info) {
      llvm::Expected<DWARFDebugAranges &> aranges =
          debug_info->GetCompileUnitAranges();
      if (!aranges) {
        Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
        LLDB_LOG_ERROR(log, aranges.takeError(),
                       "SymbolFileDWARF::ResolveSymbolContext failed to get cu "
                       "aranges.  {0}");
        return 0;
      }

      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)) {
              DWARFDIE function_die = dwarf_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 && (resolve_scope & eSymbolContextBlock))
                  block_die = function_die.LookupDeepestBlock(file_vm_addr);
              } 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.function != nullptr) {
                resolved |= eSymbolContextFunction;

                if (resolve_scope & eSymbolContextBlock) {
                  Block &block = sc.function->GetBlock(true);

                  if (block_die)
                    sc.block = block.FindBlockByID(block_die.GetID());
                  else
                    sc.block = block.FindBlockByID(function_die.GetID());
                  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 FileSpec &file_spec,
                                               uint32_t line,
                                               bool check_inlines,
                                               SymbolContextItem resolve_scope,
                                               SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  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;

      const bool full_match = (bool)file_spec.GetDirectory();
      bool file_spec_matches_cu_file_spec =
          FileSpec::Equal(file_spec, *dc_cu, full_match);
      if (check_inlines || file_spec_matches_cu_file_spec) {
        SymbolContext sc(m_objfile_sp->GetModule());
        sc.comp_unit = dc_cu;
        uint32_t file_idx = UINT32_MAX;

        // If we are looking for inline functions only and we don't find it
        // in the support files, we are done.
        if (check_inlines) {
          file_idx =
              sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true);
          if (file_idx == UINT32_MAX)
            continue;
        }

        if (line != 0) {
          LineTable *line_table = sc.comp_unit->GetLineTable();

          if (line_table != nullptr && line != 0) {
            // We will have already looked up the file index if we are
            // searching for inline entries.
            if (!check_inlines)
              file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
                  1, file_spec, true);

            if (file_idx != UINT32_MAX) {
              uint32_t found_line;
              uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex(
                  0, file_idx, line, false, &sc.line_entry);
              found_line = sc.line_entry.line;

              while (line_idx != UINT32_MAX) {
                sc.function = nullptr;
                sc.block = nullptr;
                if (resolve_scope &
                    (eSymbolContextFunction | eSymbolContextBlock)) {
                  const lldb::addr_t file_vm_addr =
                      sc.line_entry.range.GetBaseAddress().GetFileAddress();
                  if (file_vm_addr != LLDB_INVALID_ADDRESS) {
                    DWARFDIE function_die =
                        GetDWARFCompileUnit(dc_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 && (resolve_scope & eSymbolContextBlock))
                        block_die =
                            function_die.LookupDeepestBlock(file_vm_addr);
                    }

                    if (sc.function != nullptr) {
                      Block &block = sc.function->GetBlock(true);

                      if (block_die)
                        sc.block = block.FindBlockByID(block_die.GetID());
                      else if (function_die)
                        sc.block = block.FindBlockByID(function_die.GetID());
                    }
                  }
                }

                sc_list.Append(sc);
                line_idx = line_table->FindLineEntryIndexByFileIndex(
                    line_idx + 1, file_idx, found_line, true, &sc.line_entry);
              }
            }
          } else if (file_spec_matches_cu_file_spec && !check_inlines) {
            // only append the context if we aren't looking for inline call
            // sites by file and line and if the file spec matches that of
            // the compile unit
            sc_list.Append(sc);
          }
        } else if (file_spec_matches_cu_file_spec && !check_inlines) {
          // only append the context if we aren't looking for inline call
          // sites by file and line and if the file spec matches that of
          // the compile unit
          sc_list.Append(sc);
        }

        if (!check_inlines)
          break;
      }
    }
  }
  return sc_list.GetSize() - prev_size;
}

void SymbolFileDWARF::PreloadSymbols() {
  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 == nullptr || !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;
}

uint32_t 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 0;

  DWARFDebugInfo *info = DebugInfo();
  if (info == nullptr)
    return 0;

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

  DIEArray die_offsets;
  m_index->GetGlobalVariables(ConstString(basename), die_offsets);
  const size_t num_die_matches = die_offsets.size();
  if (num_die_matches) {
    SymbolContext sc;
    sc.module_sp = m_objfile_sp->GetModule();
    assert(sc.module_sp);

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

    bool done = false;
    for (size_t i = 0; i < num_die_matches && !done; ++i) {
      const DIERef &die_ref = die_offsets[i];
      DWARFDIE die = GetDIE(die_ref);

      if (die) {
        switch (die.Tag()) {
        default:
        case DW_TAG_subprogram:
        case DW_TAG_inlined_subroutine:
        case DW_TAG_try_block:
        case DW_TAG_catch_block:
          break;

        case DW_TAG_variable: {
          auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
          if (!dwarf_cu)
            continue;
          sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);

          if (parent_decl_ctx) {
            DWARFASTParser *dwarf_ast = die.GetDWARFParser();
            if (dwarf_ast) {
              CompilerDeclContext actual_parent_decl_ctx =
                  dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
              if (!actual_parent_decl_ctx ||
                  actual_parent_decl_ctx != *parent_decl_ctx)
                continue;
            }
          }

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

          if (variables.GetSize() - original_size >= max_matches)
            done = true;
        } break;
        }
      } else {
        m_index->ReportInvalidDIERef(die_ref, name.GetStringRef());
      }
    }
  }

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

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

  DWARFDebugInfo *info = DebugInfo();
  if (info == nullptr)
    return 0;

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

  DIEArray die_offsets;
  m_index->GetGlobalVariables(regex, die_offsets);

  SymbolContext sc;
  sc.module_sp = m_objfile_sp->GetModule();
  assert(sc.module_sp);

  const size_t num_matches = die_offsets.size();
  if (num_matches) {
    for (size_t i = 0; i < num_matches; ++i) {
      const DIERef &die_ref = die_offsets[i];
      DWARFDIE die = GetDIE(die_ref);

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

        ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);

        if (variables.GetSize() - original_size >= max_matches)
          break;
      } else
        m_index->ReportInvalidDIERef(die_ref, regex.GetText());
    }
  }

  // Return the number of variable that were appended to the list
  return variables.GetSize() - original_size;
}

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

    if (addr.IsValid()) {
      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 == nullptr || !decl_ctx->IsValid())
    return true;

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

uint32_t SymbolFileDWARF::FindFunctions(
    ConstString name, const CompilerDeclContext *parent_decl_ctx,
    FunctionNameType name_type_mask, bool include_inlines, bool append,
    SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, "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, append=%u, sc_list)",
        name.GetCString(), name_type_mask, append);
  }

  // If we aren't appending the results to this list, then clear the list
  if (!append)
    sc_list.Clear();

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return 0;

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

  // 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;
  DIEArray offsets;
  CompilerDeclContext empty_decl_ctx;
  if (!parent_decl_ctx)
    parent_decl_ctx = &empty_decl_ctx;

  std::vector<DWARFDIE> dies;
  m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies);
  for (const DWARFDIE &die : dies) {
    if (resolved_dies.insert(die.GetDIE()).second)
      ResolveFunction(die, include_inlines, sc_list);
  }

  // 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, append=%u, sc_list) => "
        "%u",
        name.GetCString(), name_type_mask, include_inlines, append,
        num_matches);
  }
  return num_matches;
}

uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
                                        bool include_inlines, bool append,
                                        SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, "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\", append=%u, sc_list)",
        regex.GetText().str().c_str(), append);
  }

  // If we aren't appending the results to this list, then clear the list
  if (!append)
    sc_list.Clear();

  DWARFDebugInfo *info = DebugInfo();
  if (!info)
    return 0;

  // Remember how many sc_list are in the list before we search in case we are
  // appending the results to a variable list.
  uint32_t original_size = sc_list.GetSize();

  DIEArray offsets;
  m_index->GetFunctions(regex, offsets);

  llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
  for (DIERef ref : offsets) {
    DWARFDIE die = info->GetDIE(ref);
    if (!die) {
      m_index->ReportInvalidDIERef(ref, regex.GetText());
      continue;
    }
    if (resolved_dies.insert(die.GetDIE()).second)
      ResolveFunction(die, include_inlines, sc_list);
  }

  // Return the number of variable that were appended to the list
  return sc_list.GetSize() - original_size;
}

void SymbolFileDWARF::GetMangledNamesForFunction(
    const std::string &scope_qualified_name,
    std::vector<ConstString> &mangled_names) {
  DWARFDebugInfo *info = DebugInfo();
  uint32_t num_comp_units = 0;
  if (info)
    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 (lldb::user_id_t uid :
       m_function_scope_qualified_name_map.lookup(scope_qualified_name)) {
    DWARFDIE die = GetDIE(uid);
    mangled_names.push_back(ConstString(die.GetMangledName()));
  }
}

uint32_t SymbolFileDWARF::FindTypes(
    ConstString name, const CompilerDeclContext *parent_decl_ctx, bool append,
    uint32_t max_matches,
    llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
    TypeMap &types) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // If we aren't appending the results to this list, then clear the list
  if (!append)
    types.Clear();

  // Make sure we haven't already searched this SymbolFile before...
  if (searched_symbol_files.count(this))
    return 0;
  else
    searched_symbol_files.insert(this);

  DWARFDebugInfo *info = DebugInfo();
  if (info == nullptr)
    return 0;

  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\"), append=%u, max_matches=%u, type_list)",
          name.GetCString(), static_cast<const void *>(parent_decl_ctx),
          parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches);
    else
      GetObjectFile()->GetModule()->LogMessage(
          log,
          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = "
          "NULL, append=%u, max_matches=%u, type_list)",
          name.GetCString(), append, max_matches);
  }

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return 0;

  DIEArray die_offsets;
  m_index->GetTypes(name, die_offsets);
  const size_t num_die_matches = die_offsets.size();

  if (num_die_matches) {
    const uint32_t initial_types_size = types.GetSize();
    for (size_t i = 0; i < num_die_matches; ++i) {
      const DIERef &die_ref = die_offsets[i];
      DWARFDIE die = GetDIE(die_ref);

      if (die) {
        if (!DIEInDeclContext(parent_decl_ctx, die))
          continue; // The containing decl contexts don't match

        Type *matching_type = ResolveType(die, true, true);
        if (matching_type) {
          // We found a type pointer, now find the shared pointer form our type
          // list
          types.InsertUnique(matching_type->shared_from_this());
          if (types.GetSize() >= max_matches)
            break;
        }
      } else {
        m_index->ReportInvalidDIERef(die_ref, name.GetStringRef());
      }
    }
    const uint32_t num_matches = types.GetSize() - initial_types_size;
    if (log && num_matches) {
      if (parent_decl_ctx) {
        GetObjectFile()->GetModule()->LogMessage(
            log,
            "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
            "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",
            name.GetCString(), static_cast<const void *>(parent_decl_ctx),
            parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches,
            num_matches);
      } else {
        GetObjectFile()->GetModule()->LogMessage(
            log,
            "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx "
            "= NULL, append=%u, max_matches=%u, type_list) => %u",
            name.GetCString(), append, max_matches, num_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 (num_die_matches < max_matches) {
    UpdateExternalModuleListIfNeeded();

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

  return num_die_matches;
}

size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
                                  bool append, TypeMap &types) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (!append)
    types.Clear();

  if (context.empty())
    return 0;

  ConstString name = context.back().name;

  if (!name)
    return 0;

  DIEArray die_offsets;
  m_index->GetTypes(name, die_offsets);
  const size_t num_die_matches = die_offsets.size();

  if (num_die_matches) {
    size_t num_matches = 0;
    for (size_t i = 0; i < num_die_matches; ++i) {
      const DIERef &die_ref = die_offsets[i];
      DWARFDIE die = GetDIE(die_ref);

      if (die) {
        std::vector<CompilerContext> die_context;
        die.GetDeclContext(die_context);
        if (die_context != context)
          continue;

        Type *matching_type = ResolveType(die, true, true);
        if (matching_type) {
          // We found a type pointer, now find the shared pointer form our type
          // list
          types.InsertUnique(matching_type->shared_from_this());
          ++num_matches;
        }
      } else {
        m_index->ReportInvalidDIERef(die_ref, name.GetStringRef());
      }
    }
    return num_matches;
  }
  return 0;
}

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;

  DWARFDebugInfo *info = DebugInfo();
  if (info) {
    DIEArray die_offsets;
    m_index->GetNamespaces(name, die_offsets);
    const size_t num_matches = die_offsets.size();
    if (num_matches) {
      for (size_t i = 0; i < num_matches; ++i) {
        const DIERef &die_ref = die_offsets[i];
        DWARFDIE die = GetDIE(die_ref);

        if (die) {
          if (!DIEInDeclContext(parent_decl_ctx, die))
            continue; // The containing decl contexts don't match

          DWARFASTParser *dwarf_ast = die.GetDWARFParser();
          if (dwarf_ast) {
            namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die);
            if (namespace_decl_ctx)
              break;
          }
        } else {
          m_index->ReportInvalidDIERef(die_ref, name.GetStringRef());
        }
      }
    }
  }
  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) {
      // Grab the existing type from the master types lists
      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;

  DIEArray die_offsets;
  m_index->GetCompleteObjCClass(type_name, must_be_implementation, die_offsets);

  const size_t num_matches = die_offsets.size();

  if (num_matches) {
    for (size_t i = 0; i < num_matches; ++i) {
      const DIERef &die_ref = die_offsets[i];
      DWARFDIE type_die = GetDIE(die_ref);

      if (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) {
          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) {
            Type *resolved_type = ResolveType(type_die, false, true);
            if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) {
              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();
              break;
            }
          }
        }
      } else {
        m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef());
      }
    }
  }
  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());
      }

      DIEArray die_offsets;
      m_index->GetTypes(dwarf_decl_ctx, die_offsets);
      const size_t num_matches = die_offsets.size();

      // 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();
        }
      }
      if (num_matches) {
        for (size_t i = 0; i < num_matches; ++i) {
          const DIERef &die_ref = die_offsets[i];
          DWARFDIE type_die = GetDIE(die_ref);

          if (type_die) {
            // Make sure type_die's langauge 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(type_die.GetLanguage()))
              continue;
            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) {
              DWARFDeclContext type_dwarf_decl_ctx;
              type_die.GetDWARFDeclContext(type_dwarf_decl_ctx);

              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) {
                Type *resolved_type = ResolveType(type_die, false);
                if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) {
                  type_sp = resolved_type->shared_from_this();
                  break;
                }
              }
            } else {
              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());
              }
            }
          } else {
            m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef());
          }
        }
      }
    }
  }
  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(die.GetCU()->GetLanguageType());
  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 {};

  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
  TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, 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.GetID());
      }
    }
  }

  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) {
    bool type_is_new = false;
    if (ParseType(sc, die, &type_is_new).get()) {
      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->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) {
    DWARFDebugInfo *info = DebugInfo();
    if (info == nullptr)
      return 0;

    if (sc.function) {
      DWARFDIE function_die = GetDIE(sc.function->GetID());

      const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress(
          DW_AT_low_pc, LLDB_INVALID_ADDRESS);
      if (func_lo_pc != LLDB_INVALID_ADDRESS) {
        const size_t num_variables = ParseVariables(
            sc, function_die.GetFirstChild(), func_lo_pc, true, true);

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

        DIEArray die_offsets;
        m_index->GetGlobalVariables(dwarf_cu->GetNonSkeletonUnit(),
                                    die_offsets);
        const size_t num_matches = die_offsets.size();
        if (num_matches) {
          for (size_t i = 0; i < num_matches; ++i) {
            const DIERef &die_ref = die_offsets[i];
            DWARFDIE die = GetDIE(die_ref);
            if (die) {
              VariableSP var_sp(
                  ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS));
              if (var_sp) {
                variables->AddVariableIfUnique(var_sp);
                ++vars_added;
              }
            } else
              m_index->ReportInvalidDIERef(die_ref, "");
          }
        }
      }
      return vars_added;
    }
  }
  return 0;
}

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

  VariableSP var_sp;
  if (!die)
    return var_sp;

  var_sp = GetDIEToVariable()[die.GetDIE()];
  if (var_sp)
    return var_sp; // Already been parsed!

  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)) {
    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    DWARFDIE spec_die;
    if (num_attributes > 0) {
      const char *name = nullptr;
      const char *mangled = nullptr;
      Declaration decl;
      uint32_t i;
      DWARFFormValue type_die_form;
      DWARFExpression location;
      bool is_external = false;
      bool is_artificial = false;
      bool location_is_const_value_data = false;
      bool has_explicit_location = false;
      DWARFFormValue const_value;
      Variable::RangeList scope_ranges;
      // AccessType accessibility = eAccessNone;

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

        if (attributes.ExtractFormValueAtIndex(i, form_value)) {
          switch (attr) {
          case DW_AT_decl_file:
            decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
                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:
            // If we have already found a DW_AT_location attribute, ignore this
            // attribute.
            if (!has_explicit_location) {
              location_is_const_value_data = true;
              // The constant value will be either a block, a data value or a
              // string.
              auto debug_info_data = die.GetData();
              if (DWARFFormValue::IsBlockForm(form_value.Form())) {
                // Retrieve the value as a block expression.
                uint32_t block_offset =
                    form_value.BlockData() - debug_info_data.GetDataStart();
                uint32_t block_length = form_value.Unsigned();
                location = DWARFExpression(module, debug_info_data, die.GetCU(),
                                           block_offset, block_length);
              } else if (DWARFFormValue::IsDataForm(form_value.Form())) {
                // Retrieve the value as a data expression.
                uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
                if (auto data_length = form_value.GetFixedSize())
                  location =
                      DWARFExpression(module, debug_info_data, die.GetCU(),
                                      data_offset, *data_length);
                else {
                  const uint8_t *data_pointer = form_value.BlockData();
                  if (data_pointer) {
                    form_value.Unsigned();
                  } else if (DWARFFormValue::IsDataForm(form_value.Form())) {
                    // we need to get the byte size of the type later after we
                    // create the variable
                    const_value = form_value;
                  }
                }
              } else {
                // Retrieve the value as a string expression.
                if (form_value.Form() == DW_FORM_strp) {
                  uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
                  if (auto data_length = form_value.GetFixedSize())
                    location =
                        DWARFExpression(module, debug_info_data, die.GetCU(),
                                        data_offset, *data_length);
                } else {
                  const char *str = form_value.AsCString();
                  uint32_t string_offset =
                      str - (const char *)debug_info_data.GetDataStart();
                  uint32_t string_length = strlen(str) + 1;
                  location =
                      DWARFExpression(module, debug_info_data, die.GetCU(),
                                      string_offset, string_length);
                }
              }
            }
            break;
          case DW_AT_location: {
            location_is_const_value_data = false;
            has_explicit_location = true;
            if (DWARFFormValue::IsBlockForm(form_value.Form())) {
              auto data = die.GetData();

              uint32_t block_offset =
                  form_value.BlockData() - data.GetDataStart();
              uint32_t block_length = form_value.Unsigned();
              location = DWARFExpression(module, data, die.GetCU(),
                                         block_offset, block_length);
            } else {
              const DWARFDataExtractor &debug_loc_data = DebugLocData();
              const dw_offset_t debug_loc_offset = form_value.Unsigned();

              size_t loc_list_length = DWARFExpression::LocationListSize(
                  die.GetCU(), debug_loc_data, debug_loc_offset);
              if (loc_list_length > 0) {
                location = DWARFExpression(module, debug_loc_data, die.GetCU(),
                                           debug_loc_offset, loc_list_length);
                assert(func_low_pc != LLDB_INVALID_ADDRESS);
                location.SetLocationListSlide(
                    func_low_pc -
                    attributes.CompileUnitAtIndex(i)->GetBaseAddress());
              }
            }
          } break;
          case DW_AT_specification:
            spec_die = form_value.Reference();
            break;
          case DW_AT_start_scope:
            // TODO: Implement this.
            break;
          case DW_AT_artificial:
            is_artificial = form_value.Boolean();
            break;
          case DW_AT_accessibility:
            break; // accessibility =
                   // DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
          case DW_AT_declaration:
          case DW_AT_description:
          case DW_AT_endianity:
          case DW_AT_segment:
          case DW_AT_visibility:
          default:
          case DW_AT_abstract_origin:
          case DW_AT_sibling:
            break;
          }
        }
      }

      const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
      const dw_tag_t parent_tag = die.GetParent().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;

      const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
      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(die.GetLanguage())) {
          DWARFDeclContext decl_ctx;

          die.GetDWARFDeclContext(decl_ctx);
          mangled = decl_ctx.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 oject 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 var_sp;
              }
            }
          }
        } else {
          if (location_is_const_value_data)
            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) {
        SymbolFileTypeSP type_sp(
            new SymbolFileType(*this, GetUID(type_die_form.Reference())));

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

        var_sp = std::make_shared<Variable>(
            die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
            scope_ranges, &decl, location, is_external, is_artificial,
            is_static_member);

        var_sp->SetLocationIsConstantValueData(location_is_const_value_data);
      } else {
        // 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 var_sp;
      }
    }
    // Cache var_sp even if NULL (the variable was just a specification or was
    // missing vital information to be able to be displayed in the debugger
    // (missing location due to optimization, etc)) so we don't re-parse this
    // DIE over and over later...
    GetDIEToVariable()[die.GetDIE()] = var_sp;
    if (spec_die)
      GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
  }
  return var_sp;
}

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

    // 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.GetFirstChild(); child_die;
         child_die = child_die.GetSibling()) {
      DWARFDIE result_die =
          FindBlockContainingSpecification(child_die, spec_block_die_offset);
      if (result_die)
        return result_die;
    }
  }

  return DWARFDIE();
}

size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
                                       const DWARFDIE &orig_die,
                                       const lldb::addr_t func_low_pc,
                                       bool parse_siblings, bool parse_children,
                                       VariableList *cc_variable_list) {
  if (!orig_die)
    return 0;

  VariableListSP variable_list_sp;

  size_t vars_added = 0;
  DWARFDIE die = orig_die;
  while (die) {
    dw_tag_t tag = die.Tag();

    // Check to see if we have already parsed this variable or constant?
    VariableSP var_sp = GetDIEToVariable()[die.GetDIE()];
    if (var_sp) {
      if (cc_variable_list)
        cc_variable_list->AddVariableIfUnique(var_sp);
    } else {
      // We haven't already parsed it, lets do that now.
      if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
          (tag == DW_TAG_formal_parameter && sc.function)) {
        if (variable_list_sp.get() == nullptr) {
          DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_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);
              if (variable_list_sp.get() == nullptr) {
                variable_list_sp = std::make_shared<VariableList>();
              }
            } 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(),
                  orig_die.GetID(), orig_die.GetTagAsCString());
            }
            break;

          case DW_TAG_subprogram:
          case DW_TAG_inlined_subroutine:
          case DW_TAG_lexical_block:
            if (sc.function != nullptr) {
              // Check to see if we already have parsed the variables for the
              // given scope

              Block *block = sc.function->GetBlock(true).FindBlockByID(
                  sc_parent_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()),
                        sc_parent_die.GetOffset());
                if (concrete_block_die)
                  block = sc.function->GetBlock(true).FindBlockByID(
                      concrete_block_die.GetID());
              }

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

          default:
            GetObjectFile()->GetModule()->ReportError(
                "didn't find appropriate parent DIE for variable list for "
                "0x%8.8" PRIx64 " %s.\n",
                orig_die.GetID(), orig_die.GetTagAsCString());
            break;
          }
        }

        if (variable_list_sp) {
          VariableSP var_sp(ParseVariableDIE(sc, die, func_low_pc));
          if (var_sp) {
            variable_list_sp->AddVariableIfUnique(var_sp);
            if (cc_variable_list)
              cc_variable_list->AddVariableIfUnique(var_sp);
            ++vars_added;
          }
        }
      }
    }

    bool skip_children = (sc.function == nullptr && tag == DW_TAG_subprogram);

    if (!skip_children && parse_children && die.HasChildren()) {
      vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true,
                                   true, cc_variable_list);
    }

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

/// Collect call graph edges present in a function DIE.
static std::vector<lldb_private::CallEdge>
CollectCallEdges(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.
  uint64_t has_call_edges =
      function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 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<CallEdge> call_edges;
  for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
       child = child.GetSibling()) {
    if (child.Tag() != DW_TAG_call_site)
      continue;

    // Extract DW_AT_call_origin (the call target's DIE).
    DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin);
    if (!call_origin.IsValid()) {
      LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
               function_die.GetPubname());
      continue;
    }

    // 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.
    addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc,
                                                        LLDB_INVALID_ADDRESS);

    LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
             call_origin.GetPubname(), return_pc);
    call_edges.emplace_back(call_origin.GetMangledName(), return_pc);
  }
  return call_edges;
}

std::vector<lldb_private::CallEdge>
SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
  DWARFDIE func_die = GetDIE(func_id.GetID());
  if (func_die.IsValid())
    return CollectCallEdges(func_die);
  return {};
}

// PluginInterface protocol
ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); }

uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; }

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;
  ClangASTContext *clang =
      llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get());
  if (!clang)
    return;
  clang->Dump(s);
}

SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
  if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) {
    lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
    if (module_sp) {
      m_debug_map_symfile =
          (SymbolFileDWARFDebugMap *)module_sp->GetSymbolFile();
    }
  }
  return m_debug_map_symfile;
}

DWARFExpression::LocationListFormat
SymbolFileDWARF::GetLocationListFormat() const {
  if (m_data_debug_loclists.m_data.GetByteSize() > 0)
    return DWARFExpression::LocLists;
  return DWARFExpression::RegularLocationList;
}

SymbolFileDWARFDwp *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->GetFileSpec().GetPath() + ".dwp");

    FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
    FileSpec dwp_filespec =
        Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
    if (FileSystem::Instance().Exists(dwp_filespec)) {
      m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(),
                                                 dwp_filespec);
    }
  });
  return m_dwp_symfile.get();
}
