//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SymbolFileDWARF.h"

// Other libraries and framework includes
#include "llvm/Support/Casting.h"
#include "llvm/Support/Threading.h"

#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.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/StreamString.h"
#include "lldb/Utility/Timer.h"

#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"

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

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

#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.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/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"

#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"

#include "lldb/Target/Language.h"

#include "lldb/Host/TaskPool.h"

#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugLine.h"
#include "DWARFDebugMacro.h"
#include "DWARFDebugPubnames.h"
#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
#include "DWARFFormValue.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARFDebugMap.h"
#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDwp.h"

#include "llvm/Support/FileSystem.h"

#include <map>

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

PropertyDefinition g_properties[] = {
    {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr,
     nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic "
              "links will be resolved at DWARF parse time."},
    {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};

enum { ePropertySymLinkPaths };

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

  PluginProperties() {
    m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
    m_collection_sp->Initialize(g_properties);
  }

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

typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;

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

} // anonymous namespace end

static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
  if (!path_from_dwarf || !path_from_dwarf[0]) {
    return path_from_dwarf;
  }

  const char *colon_pos = strchr(path_from_dwarf, ':');
  if (nullptr == colon_pos) {
    return path_from_dwarf;
  }

  const char *slash_pos = strchr(path_from_dwarf, '/');
  if (slash_pos && (slash_pos < colon_pos)) {
    return path_from_dwarf;
  }

  // check whether we have a windows path, and so the first character
  // is a drive-letter not a hostname.
  if (colon_pos == path_from_dwarf + 1 && isalpha(*path_from_dwarf) &&
      strlen(path_from_dwarf) > 2 && '\\' == path_from_dwarf[2]) {
    return path_from_dwarf;
  }

  return colon_pos + 1;
}

static const char *resolveCompDir(const char *path_from_dwarf) {
  if (!path_from_dwarf)
    return nullptr;

  // DWARF2/3 suggests the form hostname:pathname for compilation directory.
  // Remove the host part if present.
  const char *local_path = removeHostnameFromPathname(path_from_dwarf);
  if (!local_path)
    return nullptr;

  bool is_symlink = false;
  FileSpec local_path_spec(local_path, false);
  const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
  for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
    is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
                                 local_path_spec, true);

  if (!is_symlink)
    return local_path;

  namespace fs = llvm::sys::fs;
  if (fs::get_file_type(local_path_spec.GetPath(), false) !=
      fs::file_type::symlink_file)
    return local_path;

  FileSpec resolved_local_path_spec;
  const auto error =
      FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
  if (error.Success())
    return resolved_local_path_spec.GetCString();

  return nullptr;
}

static inline bool IsSwiftLanguage(LanguageType language) {
  return language == eLanguageTypePLI || language == eLanguageTypeSwift ||
         ((uint32_t)language == (uint32_t)llvm::dwarf::DW_LANG_Swift);
}

DWARFCompileUnit *SymbolFileDWARF::GetBaseCompileUnit() {
  return nullptr;
}

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(ObjectFile *obj_file) {
  return new SymbolFileDWARF(obj_file);
}

TypeList *SymbolFileDWARF::GetTypeList() {
  SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
  if (debug_map_symfile)
    return debug_map_symfile->GetTypeList();
  else
    return m_obj_file->GetModule()->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,
                                 uint32_t type_mask, TypeList &type_list)

{
  TypeSet type_set;

  CompileUnit *comp_unit = NULL;
  DWARFCompileUnit *dwarf_cu = NULL;
  if (sc_scope)
    comp_unit = sc_scope->CalculateSymbolContextCompileUnit();

  if (comp_unit) {
    dwarf_cu = GetDWARFCompileUnit(comp_unit);
    if (dwarf_cu == 0)
      return 0;
    GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(),
             dwarf_cu->GetNextCompileUnitOffset(), type_mask, type_set);
  } else {
    DWARFDebugInfo *info = DebugInfo();
    if (info) {
      const size_t num_cus = info->GetNumCompileUnits();
      for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) {
        dwarf_cu = info->GetCompileUnitAtIndex(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_subprogram:
    case DW_TAG_inlined_subroutine:
    case DW_TAG_lexical_block:
      return die;
    }
  }
  return DWARFDIE();
}

SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
    : SymbolFile(objfile), UserID(0), // 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(NULL), m_data_debug_abbrev(),
      m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
      m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
      m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
      m_data_apple_types(), m_data_apple_exttypes(), m_data_apple_namespaces(),
      m_abbr(), m_info(), m_line(), m_apple_names_ap(), m_apple_types_ap(),
      m_apple_exttypes_ap(), m_apple_namespaces_ap(), m_apple_objc_ap(),
      m_function_basename_index(), m_function_fullname_index(),
      m_function_method_index(), m_function_selector_index(),
      m_objc_class_selectors_index(), m_global_index(), m_type_index(),
      m_namespace_index(), m_indexed(false), m_using_apple_tables(false),
      m_initialized_swift_modules(false), m_reported_missing_sdk(false),
      m_fetched_external_modules(false),
      m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
      m_unique_ast_type_map() {}

SymbolFileDWARF::~SymbolFileDWARF() {}

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

TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
  SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
  TypeSystem *type_system;
  if (debug_map_symfile) {
    type_system = debug_map_symfile->GetTypeSystemForLanguage(language);
  } else {
    type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
    if (type_system)
      type_system->SetSymbolFile(this);
  }
  return type_system;
}

void SymbolFileDWARF::InitializeObject() {
  ModuleSP module_sp(m_obj_file->GetModule());
  if (module_sp) {
    const SectionList *section_list = module_sp->GetSectionList();
    Section *section =
        section_list->FindSectionByName(GetDWARFMachOSegmentName()).get();

    if (section)
      m_obj_file->ReadSectionData(section, m_dwarf_data);
  }

  get_apple_names_data();
  if (m_data_apple_names.m_data.GetByteSize() > 0) {
    m_apple_names_ap.reset(new DWARFMappedHash::MemoryTable(
        m_data_apple_names.m_data, get_debug_str_data(), ".apple_names"));
    if (m_apple_names_ap->IsValid())
      m_using_apple_tables = true;
    else
      m_apple_names_ap.reset();
  }
  get_apple_types_data();
  if (m_data_apple_types.m_data.GetByteSize() > 0) {
    m_apple_types_ap.reset(new DWARFMappedHash::MemoryTable(
        m_data_apple_types.m_data, get_debug_str_data(), ".apple_types"));
    if (m_apple_types_ap->IsValid())
      m_using_apple_tables = true;
    else
      m_apple_types_ap.reset();
  }
  get_apple_exttypes_data();
  if (m_data_apple_exttypes.m_data.GetByteSize() > 0) {
    m_apple_exttypes_ap.reset(new DWARFMappedHash::MemoryTable(
        m_data_apple_exttypes.m_data, get_debug_str_data(), ".apple_exttypes"));
    if (m_apple_exttypes_ap->IsValid())
      m_using_apple_tables = true;
    else
      m_apple_exttypes_ap.reset();
  }

  get_apple_namespaces_data();
  if (m_data_apple_namespaces.m_data.GetByteSize() > 0) {
    m_apple_namespaces_ap.reset(new DWARFMappedHash::MemoryTable(
        m_data_apple_namespaces.m_data, get_debug_str_data(),
        ".apple_namespaces"));
    if (m_apple_namespaces_ap->IsValid())
      m_using_apple_tables = true;
    else
      m_apple_namespaces_ap.reset();
  }

  get_apple_objc_data();
  if (m_data_apple_objc.m_data.GetByteSize() > 0) {
    m_apple_objc_ap.reset(new DWARFMappedHash::MemoryTable(
        m_data_apple_objc.m_data, get_debug_str_data(), ".apple_objc"));
    if (m_apple_objc_ap->IsValid())
      m_using_apple_tables = true;
    else
      m_apple_objc_ap.reset();
  }
}

bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
  return version == 2 || version == 3 || version == 4;
}

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

    // On non Apple platforms we might have .debug_types debug info that
    // is created by using "-fdebug-types-section". LLDB currently will try
    // to load this debug info, but it causes crashes during debugging when
    // types are missing since it doesn't know how to parse the info in
    // the .debug_types type units. This causes all complex debug info
    // types to be unresolved. Because this causes LLDB to crash and since
    // it really doesn't provide a solid debuggiung experience, we should
    // disable trying to debug this kind of DWARF until support gets
    // added or deprecated.
    if (section_list->FindSectionByName(ConstString(".debug_types"))) {
      m_obj_file->GetModule()->ReportWarning(
        "lldb doesn’t support .debug_types debug info");
      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 != NULL) {
      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_obj_file->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_obj_file->GetFileSpec().GetDirectory().GetCString();
      if (symfile_dir_cstr) {
        if (strcasestr(symfile_dir_cstr, ".dsym")) {
          if (m_obj_file->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_obj_file->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_obj_file->GetModule());
  const SectionList *section_list = module_sp->GetSectionList();
  if (section_list) {
    SectionSP section_sp(section_list->FindSectionByType(sect_type, true));
    if (section_sp) {
      // See if we memory mapped the DWARF segment?
      if (m_dwarf_data.GetByteSize()) {
        data.SetData(m_dwarf_data, section_sp->GetOffset(),
                     section_sp->GetFileSize());
      } else {
        if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0)
          data.Clear();
      }
    }
  }
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_abbrev_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugAbbrev,
                              m_data_debug_abbrev);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_addr_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugAddr, m_data_debug_addr);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_aranges_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugAranges,
                              m_data_debug_aranges);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_frame_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugFrame, m_data_debug_frame);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugInfo, m_data_debug_info);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugLine, m_data_debug_line);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_macro_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugMacro, m_data_debug_macro);
}

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

const DWARFDataExtractor &SymbolFileDWARF::get_debug_ranges_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugRanges,
                              m_data_debug_ranges);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str);
}

const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_offsets_data() {
  return GetCachedSectionData(eSectionTypeDWARFDebugStrOffsets,
                              m_data_debug_str_offsets);
}

const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
  return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names);
}

const DWARFDataExtractor &SymbolFileDWARF::get_apple_types_data() {
  return GetCachedSectionData(eSectionTypeDWARFAppleTypes, m_data_apple_types);
}

const DWARFDataExtractor &SymbolFileDWARF::get_apple_exttypes_data() {
  return GetCachedSectionData(eSectionTypeDWARFAppleExternalTypes,
                              m_data_apple_exttypes);
}

const DWARFDataExtractor &SymbolFileDWARF::get_apple_namespaces_data() {
  return GetCachedSectionData(eSectionTypeDWARFAppleNamespaces,
                              m_data_apple_namespaces);
}

const DWARFDataExtractor &SymbolFileDWARF::get_apple_objc_data() {
  return GetCachedSectionData(eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}

DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
  if (m_abbr.get() == NULL) {
    const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
    if (debug_abbrev_data.GetByteSize() > 0) {
      m_abbr.reset(new DWARFDebugAbbrev());
      if (m_abbr.get())
        m_abbr->Parse(debug_abbrev_data);
    }
  }
  return m_abbr.get();
}

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

DWARFDebugInfo *SymbolFileDWARF::DebugInfo() {
  if (m_info.get() == NULL) {
    static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
    Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));
    if (get_debug_info_data().GetByteSize() > 0) {
      m_info.reset(new DWARFDebugInfo());
      if (m_info.get()) {
        m_info->SetDwarfData(this);
      }
    }
  }
  return m_info.get();
}

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

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

  DWARFDebugInfo *info = DebugInfo();
  if (info) {
    // Just a normal DWARF file whose user ID for the compile unit is
    // the DWARF offset itself

    DWARFCompileUnit *dwarf_cu =
        info->GetCompileUnit((dw_offset_t)comp_unit->GetID());
    if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
      dwarf_cu->SetUserData(comp_unit);
    return dwarf_cu;
  }
  return NULL;
}

DWARFDebugRanges *SymbolFileDWARF::DebugRanges() {
  if (m_ranges.get() == NULL) {
    static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
    Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
                       static_cast<void *>(this));
    if (get_debug_ranges_data().GetByteSize() > 0) {
      m_ranges.reset(new DWARFDebugRanges());
      if (m_ranges.get())
        m_ranges->Extract(this);
    }
  }
  return m_ranges.get();
}

const DWARFDebugRanges *SymbolFileDWARF::DebugRanges() const {
  return m_ranges.get();
}

lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
                                                   uint32_t cu_idx) {
  CompUnitSP cu_sp;
  if (dwarf_cu) {
    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,
                                                                cu_idx);
      } 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_obj_file->GetModule());
        if (module_sp) {
          const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
          if (cu_die) {
            FileSpec cu_file_spec{cu_die.GetName(), false};
            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.
              if (cu_file_spec.IsRelative()) {
                const char *cu_comp_dir{
                    cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)};
                cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir));
              }

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

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

            bool is_optimized = dwarf_cu->GetIsOptimized();
            cu_sp.reset(new CompileUnit(
                module_sp, dwarf_cu, cu_file_spec, dwarf_cu->GetID(),
                cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo));
            if (cu_sp) {
              // If we just created a compile unit with an invalid file spec,
              // try and get the
              // first entry in the supports files from the line table as that
              // should be the
              // compile unit.
              if (!cu_file_spec) {
                cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1);
                if (cu_file_spec) {
                  (FileSpec &)(*cu_sp) = cu_file_spec;
                  // Also fix the invalid file spec which was copied from the
                  // compile unit.
                  cu_sp->GetSupportFiles().Replace(0, cu_file_spec);
                }
              }

              dwarf_cu->SetUserData(cu_sp.get());

              // Figure out the compile unit index if we weren't given one
              if (cu_idx == UINT32_MAX)
                DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);

              m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(
                  cu_idx, cu_sp);
            }
          }
        }
      }
    }
  }
  return cu_sp;
}

uint32_t SymbolFileDWARF::GetNumCompileUnits() {
  DWARFDebugInfo *info = DebugInfo();
  if (info)
    return info->GetNumCompileUnits();
  return 0;
}

CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
  CompUnitSP cu_sp;
  DWARFDebugInfo *info = DebugInfo();
  if (info) {
    DWARFCompileUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
    if (dwarf_cu)
      cu_sp = ParseCompileUnit(dwarf_cu, cu_idx);
  }
  return cu_sp;
}

Function *SymbolFileDWARF::ParseCompileUnitFunction(const SymbolContext &sc,
                                                    const DWARFDIE &die) {
  if (die.IsValid()) {
    TypeSystem *type_system =
        GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());

    if (type_system) {
      DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
      if (dwarf_ast)
        return dwarf_ast->ParseFunctionFromDWARF(sc, die);
    }
  }
  return nullptr;
}

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::ParseCompileUnitLanguage(const SymbolContext &sc) {
  assert(sc.comp_unit);
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu)
    return dwarf_cu->GetLanguageType();
  else
    return eLanguageTypeUnknown;
}

size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
  assert(sc.comp_unit);
  size_t functions_added = 0;
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    DWARFDIECollection function_dies;
    const size_t num_functions =
        dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies);
    size_t func_idx;
    for (func_idx = 0; func_idx < num_functions; ++func_idx) {
      DWARFDIE die = function_dies.GetDIEAtIndex(func_idx);
      if (sc.comp_unit->FindFunctionByUID(die.GetID()).get() == NULL) {
        if (ParseCompileUnitFunction(sc, die))
          ++functions_added;
      }
    }
    // FixupTypes();
  }
  return functions_added;
}

bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
    const SymbolContext &sc, FileSpecList &support_files) {
  assert(sc.comp_unit);
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();

    if (cu_die) {
      const char *cu_comp_dir = resolveCompDir(
          cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
      const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(
          DW_AT_stmt_list, DW_INVALID_OFFSET);
      if (stmt_list != DW_INVALID_OFFSET) {
        // All file indexes in DWARF are one based and a file of index zero is
        // supposed to be the compile unit itself.
        support_files.Append(*sc.comp_unit);
        return DWARFDebugLine::ParseSupportFiles(
            sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir,
            stmt_list, support_files);
      }
    }
  }
  return false;
}

bool SymbolFileDWARF::ParseCompileUnitIsOptimized(
    const lldb_private::SymbolContext &sc) {
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu)
    return dwarf_cu->GetIsOptimized();
  return false;
}

bool SymbolFileDWARF::ParseImportedModules(
    const lldb_private::SymbolContext &sc,
    std::vector<lldb_private::ConstString> &imported_modules) {
  assert(sc.comp_unit);
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    if (ClangModulesDeclVendor::LanguageSupportsClangModules(
            sc.comp_unit->GetLanguage())) {
      const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
      bool found_one = false;

      if (cu_die) {
        for (DWARFDIE child_die = cu_die.GetFirstChild(); child_die.IsValid();
             child_die = child_die.GetSibling()) {
          if (child_die.Tag() == DW_TAG_module) {
            const char *modulename = child_die.GetName();

            if (modulename) {
              found_one = true;
              imported_modules.push_back(ConstString(modulename));
            }
          }
        }

        return found_one;
      }
    } else if (IsSwiftLanguage(sc.comp_unit->GetLanguage())) {
      const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
      bool found_one = false;

      if (cu_die) {
        for (DWARFDIE child_die = cu_die.GetFirstChild(); child_die.IsValid();
             child_die = child_die.GetSibling()) {
          if (child_die.Tag() == DW_TAG_imported_module) {
            dw_offset_t die_offset = child_die.GetAttributeValueAsReference(
                DW_AT_import, DW_INVALID_OFFSET);

            if (die_offset != DW_INVALID_OFFSET) {
              const DWARFDIE import_die = dwarf_cu->GetDIE(die_offset);

              if (import_die) {
                const char *modulename = import_die.GetName();

                if (modulename) {
                  found_one = true;
                  // Now we have to see if this imported_module tag is embedded
                  // in a DW_TAG_MODULE,
                  // that is how sub-module importation is expressed:
                  std::string module_string(modulename);

                  for (DWARFDIE parent_die = import_die.GetParent();
                       parent_die.IsValid() &&
                       parent_die.Tag() == DW_TAG_module;
                       parent_die = parent_die.GetParent()) {
                    const char *parent_name = parent_die.GetName();
                    if (parent_name) {
                      module_string.insert(0, ".");
                      module_string.insert(0, parent_name);
                    }
                  }

                  imported_modules.push_back(
                      ConstString(module_string.c_str()));
                }
              }
            }
          }
        }

        return found_one;
      }
    }
  } else {
    if (ClangModulesDeclVendor::LanguageSupportsClangModules(
            sc.comp_unit->GetLanguage())) {
      UpdateExternalModuleListIfNeeded();

      if (sc.comp_unit) {
        const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();

        if (die) {
          for (DWARFDIE child_die = die.GetFirstChild(); child_die;
               child_die = child_die.GetSibling()) {
            if (child_die.Tag() == DW_TAG_imported_declaration) {
              if (DWARFDIE module_die =
                      child_die.GetReferencedDIE(DW_AT_import)) {
                if (module_die.Tag() == DW_TAG_module) {
                  if (const char *name = module_die.GetAttributeValueAsString(
                          DW_AT_name, nullptr)) {
                    ConstString const_name(name);
                    imported_modules.push_back(const_name);
                  }
                }
              }
            }
          }
        }
      } else {
        for (const auto &pair : m_external_type_modules) {
          imported_modules.push_back(pair.first);
        }
      }
    }
  }
  return false;
}

struct ParseDWARFLineTableCallbackInfo {
  LineTable *line_table;
  std::unique_ptr<LineSequence> sequence_ap;
  lldb::addr_t addr_mask;
};

//----------------------------------------------------------------------
// ParseStatementTableCallback
//----------------------------------------------------------------------
static void ParseDWARFLineTableCallback(dw_offset_t offset,
                                        const DWARFDebugLine::State &state,
                                        void *userData) {
  if (state.row == DWARFDebugLine::State::StartParsingLineTable) {
    // Just started parsing the line table
  } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) {
    // Done parsing line table, nothing to do for the cleanup
  } else {
    ParseDWARFLineTableCallbackInfo *info =
        (ParseDWARFLineTableCallbackInfo *)userData;
    LineTable *line_table = info->line_table;

    // If this is our first time here, we need to create a
    // sequence container.
    if (!info->sequence_ap.get()) {
      info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
      assert(info->sequence_ap.get());
    }
    line_table->AppendLineEntryToSequence(
        info->sequence_ap.get(), state.address & info->addr_mask, state.line,
        state.column, state.file, state.is_stmt, state.basic_block,
        state.prologue_end, state.epilogue_begin, state.end_sequence);
    if (state.end_sequence) {
      // First, put the current sequence into the line table.
      line_table->InsertSequence(info->sequence_ap.get());
      // Then, empty it to prepare for the next sequence.
      info->sequence_ap->Clear();
    }
  }
}

bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
  assert(sc.comp_unit);
  if (sc.comp_unit->GetLineTable() != NULL)
    return true;

  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
    if (dwarf_cu_die) {
      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) {
        std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
        if (line_table_ap.get()) {
          ParseDWARFLineTableCallbackInfo info;
          info.line_table = line_table_ap.get();

          /*
           * MIPS:
           * The SymbolContext may not have a valid target, thus we may not be
           * able
           * to call Address::GetOpcodeLoadAddress() which would clear the bit
           * #0
           * for MIPS. Use ArchSpec to clear the bit #0.
          */
          ArchSpec arch;
          GetObjectFile()->GetArchitecture(arch);
          switch (arch.GetMachine()) {
          case llvm::Triple::mips:
          case llvm::Triple::mipsel:
          case llvm::Triple::mips64:
          case llvm::Triple::mips64el:
            info.addr_mask = ~((lldb::addr_t)1);
            break;
          default:
            info.addr_mask = ~((lldb::addr_t)0);
            break;
          }

          lldb::offset_t offset = cu_line_offset;
          DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset,
                                              ParseDWARFLineTableCallback,
                                              &info);
          SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
          if (debug_map_symfile) {
            // 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.
            sc.comp_unit->SetLineTable(
                debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get()));
          } else {
            sc.comp_unit->SetLineTable(line_table_ap.release());
            return true;
          }
        }
      }
    }
  }
  return false;
}

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 = get_debug_macro_data();
  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, get_debug_str_data(),
                                         header.OffsetIs64Bit(), offset, this,
                                         debug_macros_sp);

  return debug_macros_sp;
}

bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
  assert(sc.comp_unit);

  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu == nullptr)
    return false;

  const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
  if (!dwarf_cu_die)
    return false;

#if TODO_REQUIRES_LLVM_ORG_SYNC
// Uncomment out the DW_AT_*macros and remove constants once GitHub llvm
// contains a refersh from llvm.org llvm
#endif
  lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(
      0x79 /* DW_AT_macros */, DW_INVALID_OFFSET);
  if (sect_offset == DW_INVALID_OFFSET)
    sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(
        0x2119 /* DW_AT_GNU_macros */, DW_INVALID_OFFSET);
  if (sect_offset == DW_INVALID_OFFSET)
    return false;

  sc.comp_unit->SetDebugMacros(ParseDebugMacros(&sect_offset));

  return true;
}

size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
                                            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 = NULL;
      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 = NULL;
      const char *mangled_name = NULL;

      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 != NULL || mangled_name != NULL)) {
          std::unique_ptr<Declaration> decl_ap;
          if (decl_file != 0 || decl_line != 0 || decl_column != 0)
            decl_ap.reset(new Declaration(
                sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
                decl_line, decl_column));

          std::unique_ptr<Declaration> call_ap;
          if (call_file != 0 || call_line != 0 || call_column != 0)
            call_ap.reset(new Declaration(
                sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file),
                call_line, call_column));

          block->SetInlinedFunctionInfo(name, mangled_name, decl_ap.get(),
                                        call_ap.get());
        }

        ++blocks_added;

        if (die.HasChildren()) {
          blocks_added += ParseFunctionBlocks(sc, 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) {
  TypeSystem *type_system = decl_ctx.GetTypeSystem();
  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);
}

SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
  // 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.
  SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile();
  if (debug_map)
    return debug_map->GetSymbolFileByOSOIndex(
        debug_map->GetOSOIndexFromUserID(uid));
  return this;
}

DWARFDIE
SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
  // 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.
  SymbolFileDWARF *dwarf = GetDWARFForUID(uid);
  if (dwarf)
    return dwarf->GetDIE(DIERef(uid, dwarf));
  return DWARFDIE();
}

CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
  // Anytime we have a lldb::user_id_t, we must get the DIE by
  // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
  // the SymbolFileDWARF::GetDIEFromUID() for details.
  DWARFDIE die = GetDIEFromUID(type_uid);
  if (die)
    return die.GetDecl();
  return CompilerDecl();
}

CompilerDeclContext
SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
  // Anytime we have a lldb::user_id_t, we must get the DIE by
  // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
  // the SymbolFileDWARF::GetDIEFromUID() for details.
  DWARFDIE die = GetDIEFromUID(type_uid);
  if (die)
    return die.GetDeclContext();
  return CompilerDeclContext();
}

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

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

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

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

  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,
                                             uint32_t cu_idx) {
  // Check if the symbol vendor already knows about this compile unit?
  if (dwarf_cu->GetUserData() == NULL) {
    // 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, cu_idx).get();
  }
  return (CompileUnit *)dwarf_cu->GetUserData();
}

size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
                                                DIEArray &method_die_offsets) {
  method_die_offsets.clear();
  if (m_using_apple_tables) {
    if (m_apple_objc_ap.get())
      m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
  } else {
    if (!m_indexed)
      Index();

    m_objc_class_selectors_index.Find(class_name, method_die_offsets);
  }
  return method_die_offsets.size();
}

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

  if (die) {
    // Check if the symbol vendor already knows about this compile unit?
    sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);

    sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
    if (sc.function == NULL)
      sc.function = ParseCompileUnitFunction(sc, 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) {
  DWARFDebugInfo *debug_info = DebugInfo();
  if (debug_info)
    return debug_info->GetDIE(die_ref);
  else
    return DWARFDIE();
}

std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
    DWARFCompileUnit &dwarf_cu, 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;

  const char *dwo_name = cu_die.GetAttributeValueAsString(
      this, &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(this, &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, true);
  if (dwo_file.IsRelative()) {
    const char *comp_dir = cu_die.GetAttributeValueAsString(
        this, &dwarf_cu, DW_AT_comp_dir, nullptr);
    if (!comp_dir)
      return nullptr;

    dwo_file.SetFile(comp_dir, true);
    dwo_file.AppendPathComponent(dwo_name);
  }

  if (!dwo_file.Exists())
    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,
      dwo_file.GetByteSize(), 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) {
    DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);

    const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
    if (die && die.HasChildren() == false) {
      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, false);
            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, true);
                dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
              }
            }
            dwo_module_spec.GetArchitecture() =
                m_obj_file->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_obj_file->GetFileSpec()
                        .GetFileNameExtension()
                        .GetStringRef() == "dwo" &&
                llvm::StringRef(m_obj_file->GetFileSpec().GetPath())
                    .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
              continue;
            }

            Status error = ModuleList::GetSharedModule(
                dwo_module_spec, module_sp, NULL, NULL, NULL);
            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_ap) {
    m_global_aranges_ap.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();
                    m_global_aranges_ap->Append(GlobalVariableMap::Entry(
                        file_addr, byte_size, var_sp.get()));
                  }
                }
              }
            }
          }
        }
      }
    }
    m_global_aranges_ap->Sort();
  }
  return *m_global_aranges_ap;
}

uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
                                               uint32_t resolve_scope,
                                               SymbolContext &sc) {
  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) {
      const dw_offset_t cu_offset =
          debug_info->GetCompileUnitAranges().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;
        DWARFCompileUnit *dwarf_cu =
            debug_info->GetCompileUnit(cu_offset, &cu_idx);
        if (dwarf_cu) {
          sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
          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 == NULL)
                  sc.function = ParseCompileUnitFunction(sc, 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 != NULL) {
                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 != NULL) {
                // 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 = NULL;
              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,
                                               uint32_t resolve_scope,
                                               SymbolContextList &sc_list) {
  const uint32_t prev_size = sc_list.GetSize();
  if (resolve_scope & eSymbolContextCompUnit) {
    // See if the SymbolFile requires that we always check for inline entries
    if (check_inlines == false)
      check_inlines = ForceInlineSourceFileCheck();

    DWARFDebugInfo *debug_info = DebugInfo();
    if (debug_info) {
      uint32_t cu_idx;
      DWARFCompileUnit *dwarf_cu = NULL;

      for (cu_idx = 0;
           (dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL;
           ++cu_idx) {
        CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
        const bool full_match = (bool)file_spec.GetDirectory();
        bool file_spec_matches_cu_file_spec =
            dc_cu != NULL && FileSpec::Equal(file_spec, *dc_cu, full_match);
        if (check_inlines || file_spec_matches_cu_file_spec) {
          SymbolContext sc(m_obj_file->GetModule());
          sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
          if (sc.comp_unit) {
            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 != NULL && 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 = NULL;
                    sc.block = NULL;
                    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 =
                            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 == NULL)
                            sc.function =
                                ParseCompileUnitFunction(sc, function_die);

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

                        if (sc.function != NULL) {
                          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;
}

lldb::TypeSP
SymbolFileDWARF::ResolveTypeFromAttribute(const DWARFFormValue &type_attr) {
  if (type_attr) {
    const dw_form_t form = type_attr.Form();

    switch (form) {
    case DW_FORM_ref_sig8: {
      // TODO: Find type in .debug_types and return an appropriate
      // lldb_private::Type *
    } break;

    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref8:
    case DW_FORM_ref_udata:
    case DW_FORM_ref_addr: {
      Type *ref_type = ResolveTypeUID(type_attr.Reference());
      if (ref_type)
        return ref_type->shared_from_this();
    } break;
    }
  }
  return lldb::TypeSP();
}

void SymbolFileDWARF::PreloadSymbols() {
  std::lock_guard<std::recursive_mutex> guard(
      GetObjectFile()->GetModule()->GetMutex());
  Index();
}

void SymbolFileDWARF::Index() {
  if (m_indexed)
    return;
  m_indexed = true;
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(
      func_cat, "SymbolFileDWARF::Index (%s)",
      GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));

  DWARFDebugInfo *debug_info = DebugInfo();
  if (debug_info) {
    const uint32_t num_compile_units = GetNumCompileUnits();
    if (num_compile_units == 0)
      return;

    std::vector<NameToDIE> function_basename_index(num_compile_units);
    std::vector<NameToDIE> function_fullname_index(num_compile_units);
    std::vector<NameToDIE> function_method_index(num_compile_units);
    std::vector<NameToDIE> function_selector_index(num_compile_units);
    std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
    std::vector<NameToDIE> global_index(num_compile_units);
    std::vector<NameToDIE> type_index(num_compile_units);
    std::vector<NameToDIE> namespace_index(num_compile_units);

    // std::vector<bool> might be implemented using bit test-and-set, so use
    // uint8_t instead.
    std::vector<uint8_t> clear_cu_dies(num_compile_units, false);
    auto parser_fn = [debug_info, &function_basename_index,
                      &function_fullname_index, &function_method_index,
                      &function_selector_index, &objc_class_selectors_index,
                      &global_index, &type_index,
                      &namespace_index](size_t cu_idx) {
      DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
      if (dwarf_cu) {
        dwarf_cu->Index(
            function_basename_index[cu_idx], function_fullname_index[cu_idx],
            function_method_index[cu_idx], function_selector_index[cu_idx],
            objc_class_selectors_index[cu_idx], global_index[cu_idx],
            type_index[cu_idx], namespace_index[cu_idx]);
      }
    };

    auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) {
      DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
      if (dwarf_cu) {
        // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the
        // DIEs for a compile unit have already been parsed.
        if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1)
          clear_cu_dies[cu_idx] = true;
      }
    };

    // Create a task runner that extracts dies for each DWARF compile unit in a
    // separate thread
    //----------------------------------------------------------------------
    // First figure out which compile units didn't have their DIEs already
    // parsed and remember this.  If no DIEs were parsed prior to this index
    // function call, we are going to want to clear the CU dies after we
    // are done indexing to make sure we don't pull in all DWARF dies, but
    // we need to wait until all compile units have been indexed in case
    // a DIE in one compile unit refers to another and the indexes accesses
    // those DIEs.
    //----------------------------------------------------------------------
    TaskMapOverInt(0, num_compile_units, extract_fn);

    // Now create a task runner that can index each DWARF compile unit in a
    // separate
    // thread so we can index quickly.

    TaskMapOverInt(0, num_compile_units, parser_fn);

    auto finalize_fn = [](NameToDIE &index, std::vector<NameToDIE> &srcs) {
      for (auto &src : srcs)
        index.Append(src);
      index.Finalize();
    };

    TaskPool::RunTasks(
        [&]() {
          finalize_fn(m_function_basename_index, function_basename_index);
        },
        [&]() {
          finalize_fn(m_function_fullname_index, function_fullname_index);
        },
        [&]() { finalize_fn(m_function_method_index, function_method_index); },
        [&]() {
          finalize_fn(m_function_selector_index, function_selector_index);
        },
        [&]() {
          finalize_fn(m_objc_class_selectors_index, objc_class_selectors_index);
        },
        [&]() { finalize_fn(m_global_index, global_index); },
        [&]() { finalize_fn(m_type_index, type_index); },
        [&]() { finalize_fn(m_namespace_index, namespace_index); });

    //----------------------------------------------------------------------
    // Keep memory down by clearing DIEs for any compile units if indexing
    // caused us to load the compile unit's DIEs.
    //----------------------------------------------------------------------
    for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
      if (clear_cu_dies[cu_idx])
        debug_info->GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true);
    }

#if defined(ENABLE_DEBUG_PRINTF)
    StreamFile s(stdout, false);
    s.Printf("DWARF index for '%s':",
             GetObjectFile()->GetFileSpec().GetPath().c_str());
    s.Printf("\nFunction basenames:\n");
    m_function_basename_index.Dump(&s);
    s.Printf("\nFunction fullnames:\n");
    m_function_fullname_index.Dump(&s);
    s.Printf("\nFunction methods:\n");
    m_function_method_index.Dump(&s);
    s.Printf("\nFunction selectors:\n");
    m_function_selector_index.Dump(&s);
    s.Printf("\nObjective C class selectors:\n");
    m_objc_class_selectors_index.Dump(&s);
    s.Printf("\nGlobals and statics:\n");
    m_global_index.Dump(&s);
    s.Printf("\nTypes:\n");
    m_type_index.Dump(&s);
    s.Printf("\nNamespaces:\n");
    m_namespace_index.Dump(&s);
#endif
  }
}

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();
  TypeSystem *type_system = GetTypeSystemForLanguage(
      decl_ctx_type_system->GetMinimumLanguage(nullptr));
  if (decl_ctx_type_system == type_system)
    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;
}

ClangASTImporter &SymbolFileDWARF::GetClangASTImporter() {
  if (!m_clang_ast_importer_ap) {
    m_clang_ast_importer_ap.reset(new ClangASTImporter);
  }
  return *m_clang_ast_importer_ap;
}

uint32_t SymbolFileDWARF::FindGlobalVariables(
    const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
    bool append, uint32_t max_matches, VariableList &variables) {
  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

  if (log)
    GetObjectFile()->GetModule()->LogMessage(
        log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
             "parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",
        name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
        max_matches);

  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
    return 0;

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

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

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

  DIEArray die_offsets;

  if (m_using_apple_tables) {
    if (m_apple_names_ap.get()) {
      const char *name_cstr = name.GetCString();
      llvm::StringRef basename;
      llvm::StringRef context;

      if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
                                                          basename))
        basename = name_cstr;

      m_apple_names_ap->FindByName(basename.data(), die_offsets);
    }
  } else {
    // Index the DWARF if we haven't already
    if (!m_indexed)
      Index();

    m_global_index.Find(name, die_offsets);
  }

  const size_t num_die_matches = die_offsets.size();
  if (num_die_matches) {
    SymbolContext sc;
    sc.module_sp = m_obj_file->GetModule();
    assert(sc.module_sp);

    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: {
          sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);

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

          if (variables.GetSize() - original_size >= max_matches)
            done = true;
        } break;
        }
      } else {
        if (m_using_apple_tables) {
          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
              "the DWARF debug information has been modified (.apple_names "
              "accelerator table had bad die 0x%8.8x for '%s')\n",
              die_ref.die_offset, name.GetCString());
        }
      }
    }
  }

  // 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, append=%u, max_matches=%u, variables) => %u",
        name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
        max_matches, num_matches);
  }
  return num_matches;
}

uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
                                              bool append, uint32_t max_matches,
                                              VariableList &variables) {
  Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));

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

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

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

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

  DIEArray die_offsets;

  if (m_using_apple_tables) {
    if (m_apple_names_ap.get()) {
      DWARFMappedHash::DIEInfoArray hash_data_array;
      if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex(regex,
                                                           hash_data_array))
        DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
    }
  } else {
    // Index the DWARF if we haven't already
    if (!m_indexed)
      Index();

    m_global_index.Find(regex, die_offsets);
  }

  SymbolContext sc;
  sc.module_sp = m_obj_file->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) {
        sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);

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

        if (variables.GetSize() - original_size >= max_matches)
          break;
      } else {
        if (m_using_apple_tables) {
          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
              "the DWARF debug information has been modified (.apple_names "
              "accelerator table had bad die 0x%8.8x for regex '%s')\n",
              die_ref.die_offset, regex.GetText().str().c_str());
        }
      }
    }
  }

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

bool SymbolFileDWARF::ResolveFunction(const DIERef &die_ref,
                                      bool include_inlines,
                                      SymbolContextList &sc_list) {
  DWARFDIE die = DebugInfo()->GetDIE(die_ref);
  return ResolveFunction(die, include_inlines, sc_list);
}

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 (1) {
      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 == NULL)
        sc.block = function_block.FindBlockByID(inlined_die.GetOffset());
      if (sc.block == NULL || sc.block->GetStartAddress(addr) == false)
        addr.Clear();
    } else {
      sc.block = NULL;
      addr = sc.function->GetAddressRange().GetBaseAddress();
    }

    if (addr.IsValid()) {
      sc_list.Append(sc);
      return true;
    }
  }

  return false;
}

void SymbolFileDWARF::FindFunctions(const ConstString &name,
                                    const NameToDIE &name_to_die,
                                    bool include_inlines,
                                    SymbolContextList &sc_list) {
  DIEArray die_offsets;
  if (name_to_die.Find(name, die_offsets)) {
    ParseFunctions(die_offsets, include_inlines, sc_list);
  }
}

void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
                                    const NameToDIE &name_to_die,
                                    bool include_inlines,
                                    SymbolContextList &sc_list) {
  DIEArray die_offsets;
  if (name_to_die.Find(regex, die_offsets)) {
    ParseFunctions(die_offsets, include_inlines, sc_list);
  }
}

void SymbolFileDWARF::FindFunctions(
    const RegularExpression &regex,
    const DWARFMappedHash::MemoryTable &memory_table, bool include_inlines,
    SymbolContextList &sc_list) {
  DIEArray die_offsets;
  DWARFMappedHash::DIEInfoArray hash_data_array;
  if (memory_table.AppendAllDIEsThatMatchingRegex(regex, hash_data_array)) {
    DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
    ParseFunctions(die_offsets, include_inlines, sc_list);
  }
}

void SymbolFileDWARF::ParseFunctions(const DIEArray &die_offsets,
                                     bool include_inlines,
                                     SymbolContextList &sc_list) {
  const size_t num_matches = die_offsets.size();
  if (num_matches) {
    for (size_t i = 0; i < num_matches; ++i)
      ResolveFunction(die_offsets[i], include_inlines, sc_list);
  }
}

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 actual_decl_ctx == *decl_ctx;
    }
  }
  return false;
}

uint32_t
SymbolFileDWARF::FindFunctions(const ConstString &name,
                               const CompilerDeclContext *parent_decl_ctx,
                               uint32_t name_type_mask, bool include_inlines,
                               bool append, SymbolContextList &sc_list) {
  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 char *name_cstr = name.GetCString();

  const uint32_t original_size = sc_list.GetSize();

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

  std::set<const DWARFDebugInfoEntry *> resolved_dies;
  if (m_using_apple_tables) {
    if (m_apple_names_ap.get()) {

      DIEArray die_offsets;

      uint32_t num_matches = 0;

      if (name_type_mask & eFunctionNameTypeFull) {
        // If they asked for the full name, match what they typed.  At some
        // point we may
        // want to canonicalize this (strip double spaces, etc.  For now, we
        // just add all the
        // dies that we find by exact match.
        num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
        for (uint32_t i = 0; i < num_matches; i++) {
          const DIERef &die_ref = die_offsets[i];
          DWARFDIE die = info->GetDIE(die_ref);
          if (die) {
            if (!DIEInDeclContext(parent_decl_ctx, die))
              continue; // The containing decl contexts don't match

            if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
              if (ResolveFunction(die, include_inlines, sc_list))
                resolved_dies.insert(die.GetDIE());
            }
          } else {
            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
                "the DWARF debug information has been modified (.apple_names "
                "accelerator table had bad die 0x%8.8x for '%s')",
                die_ref.die_offset, name_cstr);
          }
        }
      }

      if (name_type_mask & eFunctionNameTypeSelector) {
        if (parent_decl_ctx && parent_decl_ctx->IsValid())
          return 0; // no selectors in namespaces

        num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
        // Now make sure these are actually ObjC methods.  In this case we can
        // simply look up the name,
        // and if it is an ObjC method name, we're good.

        for (uint32_t i = 0; i < num_matches; i++) {
          const DIERef &die_ref = die_offsets[i];
          DWARFDIE die = info->GetDIE(die_ref);
          if (die) {
            const char *die_name = die.GetName();
            if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) {
              if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
                if (ResolveFunction(die, include_inlines, sc_list))
                  resolved_dies.insert(die.GetDIE());
              }
            }
          } else {
            GetObjectFile()->GetModule()->ReportError(
                "the DWARF debug information has been modified (.apple_names "
                "accelerator table had bad die 0x%8.8x for '%s')",
                die_ref.die_offset, name_cstr);
          }
        }
        die_offsets.clear();
      }

      if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) ||
          name_type_mask & eFunctionNameTypeBase) {
        // The apple_names table stores just the "base name" of C++ methods in
        // the table.  So we have to
        // extract the base name, look that up, and if there is any other
        // information in the name we were
        // passed in we have to post-filter based on that.

        // FIXME: Arrange the logic above so that we don't calculate the base
        // name twice:
        num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);

        for (uint32_t i = 0; i < num_matches; i++) {
          const DIERef &die_ref = die_offsets[i];
          DWARFDIE die = info->GetDIE(die_ref);
          if (die) {
            if (!DIEInDeclContext(parent_decl_ctx, die))
              continue; // The containing decl contexts don't match

            // If we get to here, the die is good, and we should add it:
            if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() &&
                ResolveFunction(die, include_inlines, sc_list)) {
              bool keep_die = true;
              if ((name_type_mask &
                   (eFunctionNameTypeBase | eFunctionNameTypeMethod)) !=
                  (eFunctionNameTypeBase | eFunctionNameTypeMethod)) {
                // We are looking for either basenames or methods, so we need to
                // trim out the ones we won't want by looking at the type
                SymbolContext sc;
                if (sc_list.GetLastContext(sc)) {
                  if (sc.block) {
                    // We have an inlined function
                  } else if (sc.function) {
                    Type *type = sc.function->GetType();

                    if (type) {
                      CompilerDeclContext decl_ctx =
                          GetDeclContextContainingUID(type->GetID());
                      if (decl_ctx.IsStructUnionOrClass()) {
                        if (name_type_mask & eFunctionNameTypeBase) {
                          sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
                          keep_die = false;
                        }
                      } else {
                        if (name_type_mask & eFunctionNameTypeMethod) {
                          sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
                          keep_die = false;
                        }
                      }
                    } else {
                      GetObjectFile()->GetModule()->ReportWarning(
                          "function at die offset 0x%8.8x had no function type",
                          die_ref.die_offset);
                    }
                  }
                }
              }
              if (keep_die)
                resolved_dies.insert(die.GetDIE());
            }
          } else {
            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
                "the DWARF debug information has been modified (.apple_names "
                "accelerator table had bad die 0x%8.8x for '%s')",
                die_ref.die_offset, name_cstr);
          }
        }
        die_offsets.clear();
      }
    }
  } else {

    // Index the DWARF if we haven't already
    if (!m_indexed)
      Index();

    if (name_type_mask & eFunctionNameTypeFull) {
      FindFunctions(name, m_function_fullname_index, include_inlines, sc_list);

      // FIXME Temporary workaround for global/anonymous namespace
      // functions debugging FreeBSD and Linux binaries.
      // If we didn't find any functions in the global namespace try
      // looking in the basename index but ignore any returned
      // functions that have a namespace but keep functions which
      // have an anonymous namespace
      // TODO: The arch in the object file isn't correct for MSVC
      // binaries on windows, we should find a way to make it
      // correct and handle those symbols as well.
      if (sc_list.GetSize() == original_size) {
        ArchSpec arch;
        if (!parent_decl_ctx && GetObjectFile()->GetArchitecture(arch) &&
            arch.GetTriple().isOSBinFormatELF()) {
          SymbolContextList temp_sc_list;
          FindFunctions(name, m_function_basename_index, include_inlines,
                        temp_sc_list);
          SymbolContext sc;
          for (uint32_t i = 0; i < temp_sc_list.GetSize(); i++) {
            if (temp_sc_list.GetContextAtIndex(i, sc)) {
              ConstString mangled_name =
                  sc.GetFunctionName(Mangled::ePreferMangled);
              ConstString demangled_name =
                  sc.GetFunctionName(Mangled::ePreferDemangled);
              // Mangled names on Linux and FreeBSD are of the form:
              // _ZN18function_namespace13function_nameEv.
              if (strncmp(mangled_name.GetCString(), "_ZN", 3) ||
                  !strncmp(demangled_name.GetCString(), "(anonymous namespace)",
                           21)) {
                sc_list.Append(sc);
              }
            }
          }
        }
      }
    }
    DIEArray die_offsets;
    if (name_type_mask & eFunctionNameTypeBase) {
      uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
      for (uint32_t i = 0; i < num_base; i++) {
        DWARFDIE die = info->GetDIE(die_offsets[i]);
        if (die) {
          if (!DIEInDeclContext(parent_decl_ctx, die))
            continue; // The containing decl contexts don't match

          // If we get to here, the die is good, and we should add it:
          if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
            if (ResolveFunction(die, include_inlines, sc_list))
              resolved_dies.insert(die.GetDIE());
          }
        }
      }
      die_offsets.clear();
    }

    if (name_type_mask & eFunctionNameTypeMethod) {
      if (parent_decl_ctx && parent_decl_ctx->IsValid())
        return 0; // no methods in namespaces

      uint32_t num_base = m_function_method_index.Find(name, die_offsets);
      {
        for (uint32_t i = 0; i < num_base; i++) {
          DWARFDIE die = info->GetDIE(die_offsets[i]);
          if (die) {
            // If we get to here, the die is good, and we should add it:
            if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
              if (ResolveFunction(die, include_inlines, sc_list))
                resolved_dies.insert(die.GetDIE());
            }
          }
        }
      }
      die_offsets.clear();
    }

    if ((name_type_mask & eFunctionNameTypeSelector) &&
        (!parent_decl_ctx || !parent_decl_ctx->IsValid())) {
      FindFunctions(name, m_function_selector_index, 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) {
  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();

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

  if (m_using_apple_tables) {
    if (m_apple_names_ap.get())
      FindFunctions(regex, *m_apple_names_ap, include_inlines, sc_list);
  } else {
    // Index the DWARF if we haven't already
    if (!m_indexed)
      Index();

    FindFunctions(regex, m_function_basename_index, include_inlines, sc_list);

    FindFunctions(regex, m_function_fullname_index, 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->GetNumCompileUnits();

  for (uint32_t i = 0; i < num_comp_units; i++) {
    DWARFCompileUnit *cu = info->GetCompileUnitAtIndex(i);
    if (cu == nullptr)
      continue;

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

  NameToOffsetMap::iterator iter =
      m_function_scope_qualified_name_map.find(scope_qualified_name);
  if (iter == m_function_scope_qualified_name_map.end())
    return;

  DIERefSetSP set_sp = (*iter).second;
  std::set<DIERef>::iterator set_iter;
  for (set_iter = set_sp->begin(); set_iter != set_sp->end(); set_iter++) {
    DWARFDIE die = DebugInfo()->GetDIE(*set_iter);
    mangled_names.push_back(ConstString(die.GetMangledName()));
  }
}

uint32_t SymbolFileDWARF::FindTypes(
    const SymbolContext &sc, const ConstString &name,
    const CompilerDeclContext *parent_decl_ctx, bool append,
    uint32_t max_matches,
    llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
    TypeMap &types) {
  // 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 == NULL)
    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;

  if (m_using_apple_tables) {
    if (m_apple_types_ap.get()) {
      const char *name_cstr = name.GetCString();
      m_apple_types_ap->FindByName(name_cstr, die_offsets);
    }
  } else {
    if (!m_indexed)
      Index();

    m_type_index.Find(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 {
        if (m_using_apple_tables) {
          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
              "the DWARF debug information has been modified (.apple_types "
              "accelerator table had bad die 0x%8.8x for '%s')\n",
              die_ref.die_offset, name.GetCString());
        }
      }
    }
    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);
      }
    }
    return num_matches;
  } else {
    UpdateExternalModuleListIfNeeded();

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

  return 0;
}

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

  if (context.empty())
    return 0;

  DIEArray die_offsets;

  ConstString name = context.back().name;

  if (!name)
    return 0;

  if (m_using_apple_tables) {
    if (m_apple_types_ap.get()) {
      const char *name_cstr = name.GetCString();
      m_apple_types_ap->FindByName(name_cstr, die_offsets);
    }
  } else {
    if (!m_indexed)
      Index();

    m_type_index.Find(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.GetDWOContext(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 {
        if (m_using_apple_tables) {
          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
              "the DWARF debug information has been modified (.apple_types "
              "accelerator table had bad die 0x%8.8x for '%s')\n",
              die_ref.die_offset, name.GetCString());
        }
      }
    }
    return num_matches;
  }
  return 0;
}

CompilerDeclContext
SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
                               const CompilerDeclContext *parent_decl_ctx) {
  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;

    // Index if we already haven't to make sure the compile units
    // get indexed and make their global DIE index list
    if (m_using_apple_tables) {
      if (m_apple_namespaces_ap.get()) {
        const char *name_cstr = name.GetCString();
        m_apple_namespaces_ap->FindByName(name_cstr, die_offsets);
      }
    } else {
      if (!m_indexed)
        Index();

      m_namespace_index.Find(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 {
          if (m_using_apple_tables) {
            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
                "the DWARF debug information has been modified "
                "(.apple_namespaces accelerator table had bad die 0x%8.8x for "
                "'%s')\n",
                die_ref.die_offset, name.GetCString());
          }
        }
      }
    }
  }
  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 == NULL) {
      CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());
      assert(lldb_cu);
      SymbolContext sc(lldb_cu);
      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, NULL);
    } 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_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(const ConstString &objc_class_name) {
  Symbol *objc_class_symbol = NULL;
  if (m_obj_file) {
    Symtab *symtab = m_obj_file->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(
    DWARFCompileUnit *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) {
        DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(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, const 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;

  if (m_using_apple_tables) {
    if (m_apple_types_ap.get()) {
      const char *name_cstr = type_name.GetCString();
      m_apple_types_ap->FindCompleteObjCClassByName(name_cstr, die_offsets,
                                                    must_be_implementation);
    }
  } else {
    if (!m_indexed)
      Index();

    m_type_index.Find(type_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 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_obj_file->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 {
        if (m_using_apple_tables) {
          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
              "the DWARF debug information has been modified (.apple_types "
              "accelerator table had bad die 0x%8.8x for '%s')\n",
              die_ref.die_offset, type_name.GetCString());
        }
      }
    }
  }
  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;

  DWARFDIECollection decl_ctx_1;
  DWARFDIECollection 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 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
  die1.GetDeclContextDIEs(decl_ctx_1);
  die2.GetDeclContextDIEs(decl_ctx_2);
  // 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.GetDIEAtIndex(i);
    decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(i);
    if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())
      return false;
  }
#if defined LLDB_CONFIGURATION_DEBUG

  // Make sure the top item in the decl context die array is always
  // DW_TAG_compile_unit. If it isn't then something went wrong in
  // the DWARFDIE::GetDeclContextDIEs() function...
  assert(decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag() == DW_TAG_compile_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.GetDIEAtIndex(i);
    decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(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;

      if (m_using_apple_tables) {
        if (m_apple_types_ap.get()) {
          const bool has_tag =
              m_apple_types_ap->GetHeader().header_data.ContainsAtom(
                  DWARFMappedHash::eAtomTypeTag);
          const bool has_qualified_name_hash =
              m_apple_types_ap->GetHeader().header_data.ContainsAtom(
                  DWARFMappedHash::eAtomTypeQualNameHash);
          if (has_tag && has_qualified_name_hash) {
            const char *qualified_name = dwarf_decl_ctx.GetQualifiedName();
            const uint32_t qualified_name_hash =
                MappedHash::HashStringUsingDJB(qualified_name);
            if (log)
              GetObjectFile()->GetModule()->LogMessage(
                  log, "FindByNameAndTagAndQualifiedNameHash()");
            m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash(
                type_name.GetCString(), tag, qualified_name_hash, die_offsets);
          } else if (has_tag) {
            if (log)
              GetObjectFile()->GetModule()->LogMessage(log,
                                                       "FindByNameAndTag()");
            m_apple_types_ap->FindByNameAndTag(type_name.GetCString(), tag,
                                               die_offsets);
          } else {
            m_apple_types_ap->FindByName(type_name.GetCString(), die_offsets);
          }
        }
      } else {
        if (!m_indexed)
          Index();

        m_type_index.Find(type_name, 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 = (language == eLanguageTypeUnknown)
                                    ? nullptr
                                    : GetTypeSystemForLanguage(language);

      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 {
            if (m_using_apple_tables) {
              GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
                  "the DWARF debug information has been modified (.apple_types "
                  "accelerator table had bad die 0x%8.8x for '%s')\n",
                  die_ref.die_offset, type_name.GetCString());
            }
          }
        }
      }
    }
  }
  return type_sp;
}

TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die,
                                  bool *type_is_new_ptr) {
  TypeSP type_sp;

  if (die) {
    TypeSystem *type_system =
        GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());

    if (type_system) {
      DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
      if (dwarf_ast) {
        Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
        type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr);
        if (type_sp) {
          TypeList *type_list = GetTypeList();
          if (type_list)
            type_list->Insert(type_sp);

          if (die.Tag() == DW_TAG_subprogram) {
            DIERef die_ref = die.GetDIERef();
            std::string scope_qualified_name(GetDeclContextForUID(die.GetID())
                                                 .GetScopeQualifiedName()
                                                 .AsCString(""));
            if (scope_qualified_name.size()) {
              NameToOffsetMap::iterator iter =
                  m_function_scope_qualified_name_map.find(
                      scope_qualified_name);
              if (iter != m_function_scope_qualified_name_map.end())
                (*iter).second->insert(die_ref);
              else {
                DIERefSetSP new_set(new std::set<DIERef>);
                new_set->insert(die_ref);
                m_function_scope_qualified_name_map.emplace(
                    std::make_pair(scope_qualified_name, new_set));
              }
            }
          }
        }
      }
    }
  }

  return type_sp;
}

bool SymbolFileDWARF::GetCompileOption(const char *option, std::string &value,
                                       CompileUnit *cu) {
  value.clear();

  DWARFDebugInfo *debug_info = DebugInfo();

  if (debug_info) {
    const uint32_t num_compile_units = GetNumCompileUnits();

    if (cu) {
      DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(cu);

      if (dwarf_cu) {
        const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
        if (die) {
          const char *flags =
              die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

          if (flags) {
            if (strstr(flags, option)) {
              Args compiler_args(flags);

              return compiler_args.GetOptionValueAsString(option, value);
            }
          }
        }
      }
    } else {
      for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
        DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);

        if (dwarf_cu) {
          const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
          if (die) {
            const char *flags =
                die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

            if (flags) {
              if (strstr(flags, option)) {
                Args compiler_args(flags);

                return compiler_args.GetOptionValueAsString(option, value);
              }
            }
          }
        }
      }
    }
  }

  return false;
}

int SymbolFileDWARF::GetCompileOptions(const char *option,
                                       std::vector<std::string> &values,
                                       CompileUnit *cu) {
  DWARFDebugInfo *debug_info = DebugInfo();

  if (debug_info) {
    if (cu) {
      DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(cu);

      if (dwarf_cu) {
        const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
        if (die) {
          const char *flags =
              die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

          if (flags) {
            if (strstr(flags, option)) {
              Args compiler_args(flags);

              return compiler_args.GetOptionValuesAsStrings(option, values);
            }
          }
        }
      }
    } else {
      const uint32_t num_compile_units = GetNumCompileUnits();

      for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
        DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);

        if (dwarf_cu) {
          const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
          if (die) {
            const char *flags =
                die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

            if (flags) {
              if (strstr(flags, option)) {
                Args compiler_args(flags);

                return compiler_args.GetOptionValuesAsStrings(option, values);
              }
            }
          }
        }
      }
    }
  }

  return 0;
}

void SymbolFileDWARF::GetLoadedModules(lldb::LanguageType language,
                                       lldb_private::FileSpecList &modules) {
  ModuleSP module_sp(m_obj_file->GetModule());

  if (IsSwiftLanguage(language)) {
    const uint32_t num_cus = module_sp->GetNumCompileUnits();
    for (uint32_t i = 0; i < num_cus; ++i) {
      CompileUnit *cu = module_sp->GetCompileUnitAtIndex(i).get();
      if (cu) {
        const FileSpecList &files = cu->GetSupportFiles();
        const size_t num_files = files.GetSize();
        static ConstString g_swift_module_extension("swiftmodule");
        for (uint32_t pass = 0; pass < 2; ++pass) {
          for (size_t file_idx = 0; file_idx < num_files; ++file_idx) {
            const FileSpec &file = files.GetFileSpecAtIndex(file_idx);
            if (file.GetFileNameExtension() == g_swift_module_extension)
              modules.AppendIfUnique(file);
          }
        }
      }
    }
  }
}

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::ParseFunctionBlocks(const SymbolContext &sc) {
  assert(sc.comp_unit && sc.function);
  size_t functions_added = 0;
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    const dw_offset_t function_die_offset = sc.function->GetID();
    DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset);
    if (function_die) {
      ParseFunctionBlocks(sc, &sc.function->GetBlock(false), function_die,
                          LLDB_INVALID_ADDRESS, 0);
    }
  }

  return functions_added;
}

size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) {
  // At least a compile unit must be valid
  assert(sc.comp_unit);
  size_t types_added = 0;
  DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
  if (dwarf_cu) {
    if (sc.function) {
      dw_offset_t function_die_offset = sc.function->GetID();
      DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset);
      if (func_die && func_die.HasChildren()) {
        types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true);
      }
    } else {
      DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
      if (dwarf_cu_die && dwarf_cu_die.HasChildren()) {
        types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
      }
    }
  }

  return types_added;
}

size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
  if (sc.comp_unit != NULL) {
    DWARFDebugInfo *info = DebugInfo();
    if (info == NULL)
      return 0;

    if (sc.function) {
      DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID(), this));

      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) {
      DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());

      if (dwarf_cu == NULL)
        return 0;

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

      if (variables.get() == NULL) {
        variables.reset(new VariableList());
        sc.comp_unit->SetVariableList(variables);

        DIEArray die_offsets;
        if (m_using_apple_tables) {
          if (m_apple_names_ap.get()) {
            DWARFMappedHash::DIEInfoArray hash_data_array;
            if (m_apple_names_ap->AppendAllDIEsInRange(
                    dwarf_cu->GetOffset(), dwarf_cu->GetNextCompileUnitOffset(),
                    hash_data_array)) {
              DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
            }
          }
        } else {
          // Index if we already haven't to make sure the compile units
          // get indexed and make their global DIE index list
          if (!m_indexed)
            Index();

          m_global_index.FindAllEntriesForCompileUnit(dwarf_cu->GetOffset(),
                                                      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 {
              if (m_using_apple_tables) {
                GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
                    "the DWARF debug information has been modified "
                    "(.apple_names accelerator table had bad die 0x%8.8x)\n",
                    die_ref.die_offset);
              }
            }
          }
        }
      }
      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 = NULL;
      const char *mangled = NULL;
      Declaration decl;
      uint32_t i;
      DWARFFormValue type_die_form;
      DWARFExpression location(die.GetCU());
      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.
              const DWARFDataExtractor &debug_info_data = get_debug_info_data();
              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.CopyOpcodeData(module, debug_info_data, block_offset,
                                        block_length);
              } else if (DWARFFormValue::IsDataForm(form_value.Form())) {
                // Retrieve the value as a data expression.
                DWARFFormValue::FixedFormSizes fixed_form_sizes =
                    DWARFFormValue::GetFixedFormSizesForAddressSize(
                        attributes.CompileUnitAtIndex(i)->GetAddressByteSize(),
                        attributes.CompileUnitAtIndex(i)->IsDWARF64());
                uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
                uint32_t data_length =
                    fixed_form_sizes.GetSize(form_value.Form());
                if (data_length == 0) {
                  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
                  location.CopyOpcodeData(module, debug_info_data, data_offset,
                                          data_length);
              } else {
                // Retrieve the value as a string expression.
                if (form_value.Form() == DW_FORM_strp) {
                  DWARFFormValue::FixedFormSizes fixed_form_sizes =
                      DWARFFormValue::GetFixedFormSizesForAddressSize(
                          attributes.CompileUnitAtIndex(i)
                              ->GetAddressByteSize(),
                          attributes.CompileUnitAtIndex(i)->IsDWARF64());
                  uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
                  uint32_t data_length =
                      fixed_form_sizes.GetSize(form_value.Form());
                  location.CopyOpcodeData(module, debug_info_data, 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.CopyOpcodeData(module, debug_info_data,
                                          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())) {
              const DWARFDataExtractor &debug_info_data = get_debug_info_data();

              uint32_t block_offset =
                  form_value.BlockData() - debug_info_data.GetDataStart();
              uint32_t block_length = form_value.Unsigned();
              location.CopyOpcodeData(module, get_debug_info_data(),
                                      block_offset, block_length);
            } else {
              const DWARFDataExtractor &debug_loc_data = get_debug_loc_data();
              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.CopyOpcodeData(module, debug_loc_data,
                                        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 = GetDIE(DIERef(form_value));
            break;
          case DW_AT_start_scope: {
            if (form_value.Form() == DW_FORM_sec_offset) {
              DWARFRangeList dwarf_scope_ranges;
              const DWARFDebugRanges *debug_ranges = DebugRanges();
              debug_ranges->FindRanges(die.GetCU()->GetRangesBase(),
                                       form_value.Unsigned(),
                                       dwarf_scope_ranges);

              // All DW_AT_start_scope are relative to the base address of the
              // compile unit. We add the compile unit base address to make
              // sure all the addresses are properly fixed up.
              for (size_t i = 0, count = dwarf_scope_ranges.GetSize();
                   i < count; ++i) {
                const DWARFRangeList::Entry &range =
                    dwarf_scope_ranges.GetEntryRef(i);
                scope_ranges.Append(range.GetRangeBase() +
                                        die.GetCU()->GetBaseAddress(),
                                    range.GetByteSize());
              }
            } else {
              // TODO: Handle the case when DW_AT_start_scope have form
              // constant. The
              // dwarf spec is a bit ambiguous about what is the expected
              // behavior in
              // case the enclosing block have a non coninious address range and
              // the
              // DW_AT_start_scope entry have a form constant.
              GetObjectFile()->GetModule()->ReportWarning(
                  "0x%8.8" PRIx64
                  ": DW_AT_start_scope has unsupported form type (0x%x)\n",
                  die.GetID(), form_value.Form());
            }

            scope_ranges.Sort();
            scope_ranges.CombineConsecutiveRanges();
          } 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;
          }
        }
      }

      if (tag == DW_TAG_variable && mangled &&
          IsSwiftLanguage(sc.comp_unit->GetLanguage()))
        mangled = NULL;

      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_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 = NULL;

      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 &&
            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,
                                            NULL);
            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 (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 {
          // The heuristic for inferring static variables works for Clang's
          // behavior on C-like languages, which generally does not emit
          // AT_const_value for locals.
          //
          // However, the Swift compiler can and does emit AT_const_value for
          // locals, and function-level statics don't exist, so we flip the
          // heuristic here.
          if (location_is_const_value_data &&
              !IsSwiftLanguage(sc.comp_unit->GetLanguage()))
            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 == NULL) {
        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 == NULL)
              symbol_context_scope = sc.function;
          }
          break;

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

      if (symbol_context_scope) {
        SymbolFileTypeSP type_sp;
        if (type_die_form.Form() == DW_FORM_strp) {
          type_sp.reset(new SymbolFileType(
              *this, ResolveTypeFromAttribute(type_die_form)));
        } else {
          type_sp.reset(
              new SymbolFileType(*this, DIERef(type_die_form).GetUID(this)));
        }

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

        var_sp.reset(new 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.GetAttributeValueAsReference(
              DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
        return die;

      if (die.GetAttributeValueAsReference(DW_AT_abstract_origin,
                                           DW_INVALID_OFFSET) ==
          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() == NULL) {
          DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die);
          dw_tag_t parent_tag = sc_parent_die.Tag();
          switch (parent_tag) {
          case DW_TAG_compile_unit:
            if (sc.comp_unit != NULL) {
              variable_list_sp = sc.comp_unit->GetVariableList(false);
              if (variable_list_sp.get() == NULL) {
                variable_list_sp.reset(new VariableList());
                sc.comp_unit->SetVariableList(variable_list_sp);
              }
            } 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 != NULL) {
              // 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 == NULL) {
                // 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(
                        DIERef(sc.function->GetID(), this),
                        sc_parent_die.GetOffset());
                if (concrete_block_die)
                  block = sc.function->GetBlock(true).FindBlockByID(
                      concrete_block_die.GetID());
              }

              if (block != NULL) {
                const bool can_create = false;
                variable_list_sp = block->GetBlockVariableList(can_create);
                if (variable_list_sp.get() == NULL) {
                  variable_list_sp.reset(new 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 == NULL && 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;
}

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

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

void SymbolFileDWARF::DumpIndexes() {
  StreamFile s(stdout, false);

  s.Printf(
      "DWARF index for (%s) '%s':",
      GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(),
      GetObjectFile()->GetFileSpec().GetPath().c_str());
  s.Printf("\nFunction basenames:\n");
  m_function_basename_index.Dump(&s);
  s.Printf("\nFunction fullnames:\n");
  m_function_fullname_index.Dump(&s);
  s.Printf("\nFunction methods:\n");
  m_function_method_index.Dump(&s);
  s.Printf("\nFunction selectors:\n");
  m_function_selector_index.Dump(&s);
  s.Printf("\nObjective C class selectors:\n");
  m_objc_class_selectors_index.Dump(&s);
  s.Printf("\nGlobals and statics:\n");
  m_global_index.Dump(&s);
  s.Printf("\nTypes:\n");
  m_type_index.Dump(&s);
  s.Printf("\nNamespaces:\n");
  m_namespace_index.Dump(&s);
}

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

DWARFExpression::LocationListFormat
SymbolFileDWARF::GetLocationListFormat() const {
  return DWARFExpression::RegularLocationList;
}

SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() {
  llvm::call_once(m_dwp_symfile_once_flag, [this]() {
    ModuleSpec module_spec;
    module_spec.GetFileSpec() = m_obj_file->GetFileSpec();
    module_spec.GetSymbolFileSpec() =
        FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp", false);
    FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec);
    if (dwp_filespec.Exists()) {
      m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(),
                                                 dwp_filespec);
    }
  });
  return m_dwp_symfile.get();
}
