diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 7823 |
1 files changed, 3642 insertions, 4181 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 942a5d62d9b4..5c44ee03b02c 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -88,8 +88,8 @@ using namespace lldb; using namespace lldb_private; -//static inline bool -//child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag) +// static inline bool +// child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag) //{ // switch (tag) // { @@ -108,4713 +108,4174 @@ using namespace lldb_private; 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(); - } +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(); + } +}; - PluginProperties() - { - m_collection_sp.reset (new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } +typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP; - FileSpecList& - GetSymLinkPaths() - { - OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths); - assert(option_value); - return option_value->GetCurrentValue(); - } +static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() { + static const auto g_settings_sp(std::make_shared<PluginProperties>()); + return g_settings_sp; +} - }; +} // anonymous namespace end - typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP; +static const char *removeHostnameFromPathname(const char *path_from_dwarf) { + if (!path_from_dwarf || !path_from_dwarf[0]) { + return path_from_dwarf; + } - static const SymbolFileDWARFPropertiesSP& - GetGlobalPluginProperties() - { - static const auto g_settings_sp(std::make_shared<PluginProperties>()); - return g_settings_sp; - } + const char *colon_pos = strchr(path_from_dwarf, ':'); + if (nullptr == colon_pos) { + return path_from_dwarf; + } -} // anonymous namespace end + 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; + } -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; + return colon_pos + 1; } -static const char* -resolveCompDir(const char* path_from_dwarf) -{ - if (!path_from_dwarf) - return nullptr; +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; + // 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); + 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; + if (!is_symlink) + return local_path; - if (!local_path_spec.IsSymbolicLink()) - return local_path; + if (!local_path_spec.IsSymbolicLink()) + 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(); + 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; + return nullptr; } - -void -SymbolFileDWARF::Initialize() -{ - LogChannelDWARF::Initialize(); - PluginManager::RegisterPlugin (GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance, - DebuggerInitialize); +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::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::Initialize(); +void SymbolFileDWARF::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); + LogChannelDWARF::Initialize(); } - -lldb_private::ConstString -SymbolFileDWARF::GetPluginNameStatic() -{ - static ConstString g_name("dwarf"); - return g_name; +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."; +const char *SymbolFileDWARF::GetPluginDescriptionStatic() { + return "DWARF and DWARF3 debug symbol file reader."; } - -SymbolFile* -SymbolFileDWARF::CreateInstance (ObjectFile* obj_file) -{ - return new SymbolFileDWARF(obj_file); +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(); - +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); +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) +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); - } - } + 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; - } + } + + 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; + } + 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; - } +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(); + } + 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_namespaces (), - m_abbr(), - m_info(), - m_line(), - m_apple_names_ap (), - m_apple_types_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_fetched_external_modules (false), - m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate), - m_ranges(), - m_unique_ast_type_map () -{ +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_namespaces(), m_abbr(), m_info(), + m_line(), m_apple_names_ap(), m_apple_types_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_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; } -SymbolFileDWARF::~SymbolFileDWARF() -{ +UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() { + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) + return debug_map_symfile->GetUniqueDWARFASTTypeMap(); + else + return m_unique_ast_type_map; } -static const ConstString & -GetDWARFMachOSegmentName () -{ - static ConstString g_dwarf_section_name ("__DWARF"); - return g_dwarf_section_name; +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; } -UniqueDWARFASTTypeMap & -SymbolFileDWARF::GetUniqueDWARFASTTypeMap () -{ - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) - return debug_map_symfile->GetUniqueDWARFASTTypeMap (); +void SymbolFileDWARF::InitializeObject() { + ModuleSP module_sp(m_obj_file->GetModule()); + if (module_sp) { + const SectionList *section_list = module_sp->GetSectionList(); + const Section *section = + section_list->FindSectionByName(GetDWARFMachOSegmentName()).get(); + + // Memory map the DWARF mach-o segment so we have everything mmap'ed + // to keep our heap memory usage down. + if (section) + m_obj_file->MemoryMapSectionData(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 - 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); - } + 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 - { - 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(); - const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get(); - - // Memory map the DWARF mach-o segment so we have everything mmap'ed - // to keep our heap memory usage down. - if (section) - m_obj_file->MemoryMapSectionData(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_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(); - } + m_apple_types_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; +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; - - 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 = §ion->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(); - - 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."); - } - } - } +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; + + 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 = §ion->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(); + + 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_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; + if (debug_line_file_size > 0) + abilities |= LineTables; + } + return abilities; } -const DWARFDataExtractor& -SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment) -{ - std::call_once(data_segment.m_flag, - &SymbolFileDWARF::LoadSectionData, - this, - sect_type, - std::ref(data_segment.m_data)); - return data_segment.m_data; +const DWARFDataExtractor & +SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, + DWARFDataSegment &data_segment) { + std::call_once(data_segment.m_flag, &SymbolFileDWARF::LoadSectionData, this, + 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(); - } - } +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_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_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_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_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_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_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_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_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_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_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_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_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_types_data() { + return GetCachedSectionData(eSectionTypeDWARFAppleTypes, m_data_apple_types); } -const DWARFDataExtractor& -SymbolFileDWARF::get_apple_namespaces_data() -{ - return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces); +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); +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); - } +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(); + } + return m_abbr.get(); } -const DWARFDebugAbbrev* -SymbolFileDWARF::DebugAbbrev() const -{ - return m_abbr.get(); +const DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() const { + return m_abbr.get(); } - -DWARFDebugInfo* -SymbolFileDWARF::DebugInfo() -{ - if (m_info.get() == NULL) - { - Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", - __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); - } - } +DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { + if (m_info.get() == NULL) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%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(); + } + return m_info.get(); } -const DWARFDebugInfo* -SymbolFileDWARF::DebugInfo() const -{ - 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; -} +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) - { - Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", - __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); - } +DWARFDebugRanges *SymbolFileDWARF::DebugRanges() { + if (m_ranges.get() == NULL) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%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(); + } + return m_ranges.get(); } -const DWARFDebugRanges* -SymbolFileDWARF::DebugRanges() const -{ - 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()); +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); } - 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.GetCString(), 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); - } - } + 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; + } + return cu_sp; } -uint32_t -SymbolFileDWARF::GetNumCompileUnits() -{ - DWARFDebugInfo* info = DebugInfo(); - if (info) - return info->GetNumCompileUnits(); - return 0; +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; +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); - } +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; + } + 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; +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; +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(); +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; + } } - return 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); - } - } +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; + } + 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::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())) - { - 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); +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())) { + 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; + } + return false; } -struct ParseDWARFLineTableCallbackInfo -{ - LineTable* line_table; - std::unique_ptr<LineSequence> sequence_ap; - lldb::addr_t addr_mask; +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 +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()); } - 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(); - } + 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; - } +bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) { + assert(sc.comp_unit); + if (sc.comp_unit->GetLineTable() != NULL) + return true; - 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; - } - } - } + 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; + } + 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; +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(); + 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; + 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); + 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; + return debug_macros_sp; } -bool -SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc) -{ - assert (sc.comp_unit); +bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) { + assert(sc.comp_unit); - DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); - if (dwarf_cu == nullptr) - return false; + 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; + const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); + if (!dwarf_cu_die) + return false; - lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET); - if (sect_offset == DW_INVALID_OFFSET) - sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET); - if (sect_offset == DW_INVALID_OFFSET) - return false; + lldb::offset_t sect_offset = + dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, + DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + return false; - sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); + sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); - return true; + 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)); +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); + } + } - block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get()); - } + 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; + ++blocks_added; - if (die.HasChildren()) - { - blocks_added += ParseFunctionBlocks (sc, - block, - die.GetFirstChild(), - subprogram_low_pc, - depth + 1); - } - } - } - break; - default: - break; + if (die.HasChildren()) { + blocks_added += ParseFunctionBlocks(sc, block, die.GetFirstChild(), + subprogram_low_pc, depth + 1); } - - // 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(); + } + } break; + default: + break; } - return blocks_added; + + // 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; - } - } +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; + } + 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); +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); + 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; +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(); +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(); +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(); +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(); +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(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 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 - // withing 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; +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; - } - } + default: + break; } - return ResolveType (die); + } } - return NULL; + 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(); +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); + 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; +} -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; - } +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(); - 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; -} + if (assert_not_being_parsed) { + if (type != DIE_IS_BEING_PARSED) + return type; -Type* -SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context) -{ - if (die) - { - Type *type = GetTypeForDIE (die, resolve_function_context).get(); - - if (assert_not_being_parsed) - { - if (type != DIE_IS_BEING_PARSED) - return type; - - GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s", - die.GetOffset(), - die.GetTagAsCString(), - die.GetName()); + 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; + } 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(); +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(); +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); +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); + 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; - } + 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; + } + + 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(); +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(); +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 -gmodule 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; - - 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); - } +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 -gmodule support uses the same DWO machanism to specify full debug + // info files for modules. + if (GetDebugMapSymfile()) + return nullptr; - if (!dwo_file.Exists()) - return nullptr; + const char *dwo_name = cu_die.GetAttributeValueAsString( + this, &dwarf_cu, DW_AT_GNU_dwo_name, nullptr); + if (!dwo_name) + 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; + 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; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, &dwarf_cu); -} + dwo_file.SetFile(comp_dir, true); + dwo_file.AppendPathComponent(dwo_name); + } -void -SymbolFileDWARF::UpdateExternalModuleListIfNeeded() -{ - if (m_fetched_external_modules) - return; - m_fetched_external_modules = true; - - DWARFDebugInfo * debug_info = DebugInfo(); + if (!dwo_file.Exists()) + return nullptr; - 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(); - //printf ("Loading dwo = '%s'\n", dwo_path); - Error 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; - } + 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(); + // printf ("Loading dwo = '%s'\n", dwo_path); + Error 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; - Error error; - if (location.Evaluate(nullptr, nullptr, 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())); - } - } - } - } - } +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; + Error error; + if (location.Evaluate(nullptr, nullptr, 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; + m_global_aranges_ap->Sort(); + } + return *m_global_aranges_ap; } - -uint32_t -SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) -{ - Timer scoped_timer(__PRETTY_FUNCTION__, - "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(); - } +uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, + uint32_t resolve_scope, + SymbolContext &sc) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "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; } + } } - 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); - } + + 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; + } + 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) { + 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; + } - -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) - { - 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 (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 (sc.function != NULL) { + Block &block = sc.function->GetBlock(true); - if (!check_inlines) - break; + 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; + } + return sc_list.GetSize() - prev_size; } -void -SymbolFileDWARF::Index () -{ - if (m_indexed) - return; - m_indexed = true; - Timer scoped_timer (__PRETTY_FUNCTION__, - "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> clear_cu_dies(num_compile_units, false); - auto parser_fn = [this, - debug_info, - &function_basename_index, - &function_fullname_index, - &function_method_index, - &function_selector_index, - &objc_class_selectors_index, - &global_index, - &type_index, - &namespace_index](uint32_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]); - } - return cu_idx; - }; - - auto extract_fn = [this, - debug_info, - num_compile_units](uint32_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. - return std::make_pair(cu_idx, dwarf_cu->ExtractDIEsIfNeeded(false) > 1); - } - return std::make_pair(cu_idx, false); - }; - - // Create a task runner that extracts dies for each DWARF compile unit in a separate thread - TaskRunner<std::pair<uint32_t, bool>> task_runner_extract; - for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) - task_runner_extract.AddTask(extract_fn, cu_idx); - - //---------------------------------------------------------------------- - // 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. - //---------------------------------------------------------------------- - while (true) - { - auto f = task_runner_extract.WaitForNextCompletedTask(); - if (!f.valid()) - break; - unsigned cu_idx; - bool clear; - std::tie(cu_idx, clear) = f.get(); - clear_cu_dies[cu_idx] = clear; - } +void SymbolFileDWARF::Index() { + if (m_indexed) + return; + m_indexed = true; + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, "SymbolFileDWARF::Index (%s)", + GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>")); - // Now create a task runner that can index each DWARF compile unit in a separate - // thread so we can index quickly. + 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> clear_cu_dies(num_compile_units, false); + auto parser_fn = [this, debug_info, &function_basename_index, + &function_fullname_index, &function_method_index, + &function_selector_index, &objc_class_selectors_index, + &global_index, &type_index, + &namespace_index](uint32_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]); + } + return cu_idx; + }; - TaskRunner<uint32_t> task_runner; - for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) - task_runner.AddTask(parser_fn, cu_idx); + auto extract_fn = [this, debug_info, num_compile_units](uint32_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. + return std::make_pair(cu_idx, dwarf_cu->ExtractDIEsIfNeeded(false) > 1); + } + return std::make_pair(cu_idx, false); + }; - while (true) - { - std::future<uint32_t> f = task_runner.WaitForNextCompletedTask(); - if (!f.valid()) - break; - uint32_t cu_idx = f.get(); - - m_function_basename_index.Append(function_basename_index[cu_idx]); - m_function_fullname_index.Append(function_fullname_index[cu_idx]); - m_function_method_index.Append(function_method_index[cu_idx]); - m_function_selector_index.Append(function_selector_index[cu_idx]); - m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]); - m_global_index.Append(global_index[cu_idx]); - m_type_index.Append(type_index[cu_idx]); - m_namespace_index.Append(namespace_index[cu_idx]); - } + // Create a task runner that extracts dies for each DWARF compile unit in a + // separate thread + TaskRunner<std::pair<uint32_t, bool>> task_runner_extract; + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + task_runner_extract.AddTask(extract_fn, cu_idx); + + //---------------------------------------------------------------------- + // 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. + //---------------------------------------------------------------------- + while (true) { + auto f = task_runner_extract.WaitForNextCompletedTask(); + if (!f.valid()) + break; + unsigned cu_idx; + bool clear; + std::tie(cu_idx, clear) = f.get(); + clear_cu_dies[cu_idx] = clear; + } - TaskPool::RunTasks( - [&]() { m_function_basename_index.Finalize(); }, - [&]() { m_function_fullname_index.Finalize(); }, - [&]() { m_function_method_index.Finalize(); }, - [&]() { m_function_selector_index.Finalize(); }, - [&]() { m_objc_class_selectors_index.Finalize(); }, - [&]() { m_global_index.Finalize(); }, - [&]() { m_type_index.Finalize(); }, - [&]() { m_namespace_index.Finalize(); }); - - //---------------------------------------------------------------------- - // 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); - } + // Now create a task runner that can index each DWARF compile unit in a + // separate + // thread so we can index quickly. -#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 + TaskRunner<uint32_t> task_runner; + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + task_runner.AddTask(parser_fn, cu_idx); + + while (true) { + std::future<uint32_t> f = task_runner.WaitForNextCompletedTask(); + if (!f.valid()) + break; + uint32_t cu_idx = f.get(); + + m_function_basename_index.Append(function_basename_index[cu_idx]); + m_function_fullname_index.Append(function_fullname_index[cu_idx]); + m_function_method_index.Append(function_method_index[cu_idx]); + m_function_selector_index.Append(function_selector_index[cu_idx]); + m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]); + m_global_index.Append(global_index[cu_idx]); + m_type_index.Append(type_index[cu_idx]); + m_namespace_index.Append(namespace_index[cu_idx]); } -} -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; + TaskPool::RunTasks([&]() { m_function_basename_index.Finalize(); }, + [&]() { m_function_fullname_index.Finalize(); }, + [&]() { m_function_method_index.Finalize(); }, + [&]() { m_function_selector_index.Finalize(); }, + [&]() { m_objc_class_selectors_index.Finalize(); }, + [&]() { m_global_index.Finalize(); }, + [&]() { m_type_index.Finalize(); }, + [&]() { m_namespace_index.Finalize(); }); + + //---------------------------------------------------------------------- + // 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); } - 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 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 + } +} - if (log) - GetObjectFile()->GetModule()->LogMessage(log, "Valid namespace does not match symbol file"); - - return false; +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; } -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)); +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 (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; + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + return 0; - DWARFDebugInfo* info = DebugInfo(); - if (info == NULL) - 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(); + // 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(); + // 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; + 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 (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; + if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename)) + basename = name_cstr; - m_apple_names_ap->FindByName (basename.data(), die_offsets); - } + m_apple_names_ap->FindByName(basename.data(), die_offsets); } - else - { - // Index the DWARF if we haven't already - if (!m_indexed) - Index (); + } else { + // Index the DWARF if we haven't already + if (!m_indexed) + Index(); - m_global_index.Find (name, die_offsets); - } + 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()); - } + 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; } - } - } + } - // 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); + 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 num_matches; + } + + // Return the number of variable that were appended to the list + const uint32_t num_matches = variables.GetSize() - original_size; + if (log && num_matches > 0) { + GetObjectFile()->GetModule()->LogMessage( + log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", " + "parent_decl_ctx=%p, 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)); +uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, + 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(), append, - max_matches); - } + 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; + 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(); + // 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(); + // 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; + 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); + 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(); - 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()); - } - } + 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; + // 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 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; +bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, + bool include_inlines, + SymbolContextList &sc_list) { + SymbolContext sc; - if (!orig_die) - return false; + 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; + // 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(); - } + DWARFDIE die = orig_die; + DWARFDIE inlined_die; + if (die.Tag() == DW_TAG_inlined_subroutine) { + inlined_die = die; - if (addr.IsValid()) - { - sc_list.Append(sc); - return true; - } + 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(); } - - 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); + if (addr.IsValid()) { + sc_list.Append(sc); + return true; } -} + } + return false; +} -void -SymbolFileDWARF::FindFunctions (const RegularExpression ®ex, - 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 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 ®ex, + 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 ®ex, - 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::FindFunctions( + const RegularExpression ®ex, + 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); - } +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; - } +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; + } + 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) -{ - Timer scoped_timer (__PRETTY_FUNCTION__, - "SymbolFileDWARF::FindFunctions (name = '%s')", - name.AsCString()); - - // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup() - 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); - } +SymbolFileDWARF::FindFunctions(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, bool include_inlines, + bool append, SymbolContextList &sc_list) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "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 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; + // 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. + // 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 char *name_cstr = name.GetCString(); - const uint32_t original_size = sc_list.GetSize(); - - DWARFDebugInfo* info = DebugInfo(); - if (info == NULL) - return 0; + const uint32_t original_size = sc_list.GetSize(); - 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); - } - } - } + DWARFDebugInfo *info = DebugInfo(); + if (info == NULL) + return 0; - 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(); + 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()); } - - 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 { + 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); + } } - } - 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().isOSFreeBSD() || arch.GetTriple().isOSLinux() || - arch.GetMachine() == llvm::Triple::hexagon)) - { - 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); - } + 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); + } } - 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(); + } + } + } 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); + } } - 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(); + } + } + 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 & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid())) - { - FindFunctions (name, m_function_selector_index, include_inlines, sc_list); + 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(); } - // 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); + if ((name_type_mask & eFunctionNameTypeSelector) && + (!parent_decl_ctx || !parent_decl_ctx->IsValid())) { + FindFunctions(name, m_function_selector_index, include_inlines, sc_list); } - return num_matches; + } + + // 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) -{ - Timer scoped_timer (__PRETTY_FUNCTION__, - "SymbolFileDWARF::FindFunctions (regex = '%s')", - regex.GetText()); - - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); - - if (log) - { - GetObjectFile()->GetModule()->LogMessage (log, - "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", - regex.GetText(), - 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; +uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "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())); - } +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); -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(); + DWARFDebugInfo *info = DebugInfo(); + if (info == NULL) + return 0; - // Make sure we haven't already searched this SymbolFile before... - if (searched_symbol_files.count(this)) - 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 - searched_symbol_files.insert(this); + 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); + } - DWARFDebugInfo* info = DebugInfo(); - if (info == NULL) - return 0; + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + return 0; - Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); + DIEArray die_offsets; - 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 (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); } - - 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()); } + } } - else - { - if (!m_indexed) - Index (); - - m_type_index.Find (name, die_offsets); + 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(); - 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; - } - } + 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; + return 0; } +size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, + bool append, TypeMap &types) { + if (!append) + types.Clear(); -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; + if (context.empty()) + return 0; - ConstString name = context.back().name; + DIEArray die_offsets; - if (!name) - return 0; + ConstString name = context.back().name; - 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 (); + if (!name) + return 0; - m_type_index.Find (name, 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); } - - 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()); - } - } - + } 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; + 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; +SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name, + const CompilerDeclContext *parent_decl_ctx) { + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return namespace_decl_ctx; + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", + name.GetCString()); + } + CompilerDeclContext namespace_decl_ctx; - DWARFDebugInfo* info = DebugInfo(); - if (info) - { - DIEArray die_offsets; + if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + return namespace_decl_ctx; - // 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 (); + DWARFDebugInfo *info = DebugInfo(); + if (info) { + DIEArray die_offsets; - 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()); - } - } + // 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; + } + 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(); - } - +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; + } + 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; - - 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; - } +SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { + if (orig_die) { + DWARFDIE die = orig_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; - } + 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; - die = die.GetParent(); + 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(); + } + 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); - } +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; + } + 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 +// 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; - } - } +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; + 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); +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); } - - 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_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()); - } - } - + } + } + } 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; + } + 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 +// 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 +// 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. +// 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; - } +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); + // 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; - } + // 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; + } + // 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)); +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, - "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s')", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName()); + 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; + } } - - 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); - } + + 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_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()); - } - } - - } + } 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; + } + 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)); - } - } - } - } +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; -} + } -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; - } + return type_sp; +} - 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); - } +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_siblings) - die = die.GetSibling(); - else - die.Clear(); + 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); } - return types_added; -} + 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); - } +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; + 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); - } - } +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; + 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; +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); } - 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); - } - } - } - } + 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 vars_added; } - return 0; + } + 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 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; + 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 (form_value.BlockData()) - { - 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(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; - } + 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); } + } } - - 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; - - 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(); - } + 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()); + } } - - // DWARF doesn't specify if a DW_TAG_variable is a local, global - // or static variable, so we have to do a little digging by - // looking at the location of a variable to see if it contains - // a DW_OP_addr opcode _somewhere_ in the definition. I say - // somewhere because clang likes to combine small global variables - // into the same symbol and have locations like: - // DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus - // So if we don't have a DW_TAG_formal_parameter, we can look at - // the location to see if it contains a DW_OP_addr opcode, and - // then we can correctly classify our variables. - if (tag == DW_TAG_formal_parameter) - scope = eValueTypeVariableArgument; - else - { - bool op_error = false; - // 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) - { - 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.GetString().c_str()); - } - } - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - - if (location_DW_OP_addr != LLDB_INVALID_ADDRESS) - { - if (is_external) - scope = eValueTypeVariableGlobal; - else - scope = eValueTypeVariableStatic; - - if (debug_map_symfile) - { - // When leaving the DWARF in the .o files on darwin, - // when we have a global variable that wasn't initialized, - // the .o file might not have allocated a virtual - // address for the global variable. In this case it will - // have created a symbol for the global variable - // that is undefined/data and external and the value will - // be the byte size of the variable. When we do the - // address map in SymbolFileDWARFDebugMap we rely on - // having an address, we need to do some magic here - // so we can get the correct address for our global - // variable. The address for all of these entries - // will be zero, and there will be an undefined symbol - // in this object file, and the executable will have - // a matching symbol with a good address. So here we - // dig up the correct address and replace it in the - // location for the variable, and set the variable's - // symbol context scope to be that of the main executable - // so the file address will resolve correctly. - bool linked_oso_file_addr = false; - if (is_external && location_DW_OP_addr == 0) - { - // we have a possible uninitialized extern global - ConstString const_name(mangled ? mangled : name); - ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile(); - if (debug_map_objfile) - { - Symtab *debug_map_symtab = debug_map_objfile->GetSymtab(); - if (debug_map_symtab) - { - Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name, - eSymbolTypeData, - Symtab::eDebugYes, - Symtab::eVisibilityExtern); - if (exe_symbol) - { - if (exe_symbol->ValueIsAddress()) - { - const addr_t exe_file_addr = exe_symbol->GetAddressRef().GetFileAddress(); - if (exe_file_addr != LLDB_INVALID_ADDRESS) - { - if (location.Update_DW_OP_addr (exe_file_addr)) - { - linked_oso_file_addr = true; - symbol_context_scope = exe_symbol; - } - } - } - } - } - } - } - - if (!linked_oso_file_addr) - { - // The DW_OP_addr is not zero, but it contains a .o file address which - // needs to be linked up correctly. - const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr); - if (exe_file_addr != LLDB_INVALID_ADDRESS) - { - // Update the file address for this variable - location.Update_DW_OP_addr (exe_file_addr); - } - else - { - // Variable didn't make it into the final executable - return var_sp; - } - } - } - } - else - { - if (location_is_const_value_data) - scope = eValueTypeVariableStatic; - else - { - scope = eValueTypeVariableLocal; - if (debug_map_symfile) - { - // We need to check for TLS addresses that we need to fixup - if (location.ContainsThreadLocalStorage()) - { - location.LinkThreadLocalStorage( - debug_map_symfile->GetObjectFile()->GetModule(), - [this, debug_map_symfile](lldb::addr_t unlinked_file_addr) -> lldb::addr_t { - return debug_map_symfile->LinkOSOFileAddress(this, unlinked_file_addr); - }); - scope = eValueTypeVariableThreadLocal; - } - } - } - } + } 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()); } - 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; + 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; + } + } + } + + 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; + } + } } - break; - - default: - symbol_context_scope = sc.comp_unit; - break; + } } + } } - if (symbol_context_scope) - { - SymbolFileTypeSP type_sp(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 + if (!linked_oso_file_addr) { + // The DW_OP_addr is not zero, but it contains a .o file address + // which + // needs to be linked up correctly. + const lldb::addr_t exe_file_addr = + debug_map_symfile->LinkOSOFileAddress(this, + location_DW_OP_addr); + if (exe_file_addr != LLDB_INVALID_ADDRESS) { + // Update the file address for this variable + location.Update_DW_OP_addr(exe_file_addr); + } else { + // Variable didn't make it into the final executable return var_sp; + } + } + } + } else { + if (location_is_const_value_data) + scope = eValueTypeVariableStatic; + else { + scope = eValueTypeVariableLocal; + if (debug_map_symfile) { + // We need to check for TLS addresses that we need to fixup + if (location.ContainsThreadLocalStorage()) { + location.LinkThreadLocalStorage( + debug_map_symfile->GetObjectFile()->GetModule(), + [this, debug_map_symfile]( + lldb::addr_t unlinked_file_addr) -> lldb::addr_t { + return debug_map_symfile->LinkOSOFileAddress( + this, unlinked_file_addr); + }); + scope = eValueTypeVariableThreadLocal; + } } + } + } + } + + if (symbol_context_scope == 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; } - // 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; + } + + if (symbol_context_scope) { + SymbolFileTypeSP type_sp( + 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; + } } - 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 DIERef& func_die_ref, - dw_offset_t spec_block_die_offset) -{ - // Give the concrete function die specified by "func_die_offset", find the +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" - return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), 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; -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; + 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; - if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset) - return die; + 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; - } - // 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; + 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; + } } - } - - 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 (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); + cc_variable_list->AddVariableIfUnique(var_sp); + ++vars_added; + } } - 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); - } + bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); - if (parse_siblings) - die = die.GetSibling(); - else - die.Clear(); + if (!skip_children && parse_children && die.HasChildren()) { + vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, + true, cc_variable_list); } - return vars_added; + + if (parse_siblings) + die = die.GetSibling(); + else + die.Clear(); + } + return vars_added; } //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ -ConstString -SymbolFileDWARF::GetPluginName() -{ - return GetPluginNameStatic(); +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); } -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(); - } +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; + } + return m_debug_map_symfile; } DWARFExpression::LocationListFormat -SymbolFileDWARF::GetLocationListFormat() const -{ - return DWARFExpression::RegularLocationList; +SymbolFileDWARF::GetLocationListFormat() const { + return DWARFExpression::RegularLocationList; } |