diff options
6 files changed, 222 insertions, 84 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index eb1870d4d49..185a5cc7532 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -42,7 +42,8 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : m_offset (DW_INVALID_OFFSET), m_length (0), m_version (0), - m_addr_size (DWARFCompileUnit::GetDefaultAddressSize()) + m_addr_size (DWARFCompileUnit::GetDefaultAddressSize()), + m_producer (eProducerInvalid) { } @@ -58,6 +59,7 @@ DWARFCompileUnit::Clear() m_die_array.clear(); m_func_aranges_ap.reset(); m_user_data = NULL; + m_producer = eProducerInvalid; } bool @@ -876,4 +878,47 @@ DWARFCompileUnit::Index (const uint32_t cu_idx, } } +bool +DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type () +{ + if (GetProducer() == eProcucerLLVMGCC) + return false; + return true; +} + +bool +DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() +{ + // llvm-gcc makes completely invalid decl file attributes and won't ever + // be fixed, so we need to know to ignore these. + return GetProducer() == eProcucerLLVMGCC; +} + +DWARFCompileUnit::Producer +DWARFCompileUnit::GetProducer () +{ + if (m_producer == eProducerInvalid) + { + const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); + if (die) + { + const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL); + if (producer_cstr) + { + RegularExpression g_llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$"); + if (g_llvm_gcc_regex.Execute (producer_cstr)) + m_producer = eProcucerLLVMGCC; + else if (strstr(producer_cstr, "clang")) + m_producer = eProducerClang; + else if (strstr(producer_cstr, "GNU")) + m_producer = eProducerGCC; + } + } + if (m_producer == eProducerInvalid) + m_producer = eProcucerOther; + } + return m_producer; +} + + diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 9591110d15f..28591a93ffd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -18,6 +18,15 @@ class NameToDIE; class DWARFCompileUnit { public: + enum Producer + { + eProducerInvalid = 0, + eProducerClang, + eProducerGCC, + eProcucerLLVMGCC, + eProcucerOther + }; + DWARFCompileUnit(SymbolFileDWARF* dwarf2Data); bool Extract(const lldb_private::DataExtractor &debug_info, uint32_t* offset_ptr); @@ -129,6 +138,11 @@ public: m_user_data = d; } + bool + Supports_DW_AT_APPLE_objc_complete_type (); + + bool + DW_AT_decl_file_attributes_are_invalid(); // void // AddGlobalDIEByIndex (uint32_t die_idx); @@ -155,6 +169,10 @@ public: { return m_dwarf2Data; } + + Producer + GetProducer (); + protected: SymbolFileDWARF* m_dwarf2Data; @@ -167,6 +185,7 @@ protected: uint32_t m_length; uint16_t m_version; uint8_t m_addr_size; + Producer m_producer; private: DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit); }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 32791c1ce54..e7dfa92a193 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -202,6 +202,7 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) : m_indexed (false), m_is_external_ast_source (false), m_using_apple_tables (false), + m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate), m_ranges(), m_unique_ast_type_map () { @@ -3852,18 +3853,50 @@ SymbolFileDWARF::GetObjCClassSymbol (const ConstString &objc_class_name) return objc_class_symbol; } +// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If they don't +// then we can end up looking through all class types for a complete type and never find +// the full definition. We need to know if this attribute is supported, so we determine +// this here and cache th result. We also need to worry about the debug map DWARF file +// if we are doing darwin DWARF in .o file debugging. +bool +SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu) +{ + if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) + { + m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; + if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) + m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; + else + { + DWARFDebugInfo* debug_info = DebugInfo(); + const uint32_t num_compile_units = GetNumCompileUnits(); + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + { + DWARFCompileUnit* curr_cu = debug_info->GetCompileUnitAtIndex(cu_idx); + if (curr_cu != cu && curr_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 && m_debug_map_symfile) + 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 (DWARFCompileUnit* cu, - const DWARFDebugInfoEntry *die, - const ConstString &type_name) +SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, + const ConstString &type_name, + bool must_be_implementation) { TypeSP type_sp; - if (cu == NULL || die == NULL || !type_name || !GetObjCClassSymbol (type_name)) + if (!type_name || (must_be_implementation && !GetObjCClassSymbol (type_name))) return type_sp; DIEArray die_offsets; @@ -3886,8 +3919,6 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (DWARFCompileUnit* cu, const size_t num_matches = die_offsets.size(); - const dw_tag_t die_tag = die->Tag(); - DWARFCompileUnit* type_cu = NULL; const DWARFDebugInfoEntry* type_die = NULL; if (num_matches) @@ -3905,40 +3936,21 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (DWARFCompileUnit* cu, // Don't try and resolve the DIE we are looking for with the DIE itself! if (type_die != die) { - const dw_tag_t type_die_tag = type_die->Tag(); - // Make sure the tags match - if (type_die_tag == die_tag) + switch (type_die->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_die_tag) - { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo { ... };" - try_resolving_type = (die_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 = (die_tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve - // using this type whose name matches.... - break; - } + case DW_TAG_class_type: + case DW_TAG_structure_type: + try_resolving_type = true; + break; + default: + break; } } if (try_resolving_type) { - try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0); + if (type_cu->Supports_DW_AT_APPLE_objc_complete_type()) + try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0); if (try_resolving_type) { @@ -3952,7 +3964,8 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (DWARFCompileUnit* cu, MakeUserID(type_die->GetOffset()), MakeUserID(type_cu->GetOffset())); - m_die_to_type[die] = resolved_type; + if (die) + m_die_to_type[die] = resolved_type; type_sp = resolved_type; break; } @@ -4232,28 +4245,52 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break; } - if (type_name_cstr != NULL && sc.comp_unit != NULL && - (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus)) + if (clang_type == NULL && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID)) { - static ConstString g_objc_type_name_id("id"); - static ConstString g_objc_type_name_Class("Class"); - static ConstString g_objc_type_name_selector("SEL"); - - if (type_name_const_str == g_objc_type_name_id) + if (type_name_cstr != NULL && sc.comp_unit != NULL && + (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus)) { - clang_type = ast.GetBuiltInType_objc_id(); - resolve_state = Type::eResolveStateFull; + static ConstString g_objc_type_name_id("id"); + static ConstString g_objc_type_name_Class("Class"); + static ConstString g_objc_type_name_selector("SEL"); + + if (type_name_const_str == g_objc_type_name_id) + { + if (log) + GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, dwarf_cu)); + clang_type = ast.GetBuiltInType_objc_id(); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; - } - else if (type_name_const_str == g_objc_type_name_Class) - { - clang_type = ast.GetBuiltInType_objc_Class(); - resolve_state = Type::eResolveStateFull; - } - else if (type_name_const_str == g_objc_type_name_selector) - { - clang_type = ast.GetBuiltInType_objc_selector(); - resolve_state = Type::eResolveStateFull; + } + else if (type_name_const_str == g_objc_type_name_Class) + { + if (log) + GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, dwarf_cu)); + clang_type = ast.GetBuiltInType_objc_Class(); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + } + else if (type_name_const_str == g_objc_type_name_selector) + { + if (log) + GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, dwarf_cu)); + clang_type = ast.GetBuiltInType_objc_selector(); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid = LLDB_INVALID_UID; + resolve_state = Type::eResolveStateFull; + } } } @@ -4304,7 +4341,15 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, switch (attr) { case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); + if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid()) + { + // llvm-gcc outputs invalid DW_AT_decl_file attributes that always + // point to the compile unit file, so we clear this invalid value + // so that we can still unique types efficiently. + decl.SetFile(FileSpec ("<invalid>", false)); + } + else + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; case DW_AT_decl_line: @@ -4420,21 +4465,21 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, if (class_language == eLanguageTypeObjC) { - if (!is_complete_objc_class) + if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu)) { // We have a valid eSymbolTypeObjCClass class symbol whose // name matches the current objective C class that we // are trying to find and this DIE isn't the complete // definition (we checked is_complete_objc_class above and // know it is false), so the real definition is in here somewhere - type_sp = FindCompleteObjCDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); + type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); if (!type_sp && m_debug_map_symfile) { // We weren't able to find a full declaration in // this DWARF, see if we have a declaration anywhere // else... - type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); + type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); } if (type_sp) @@ -4865,19 +4910,16 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, { ConstString class_name (class_name_start, class_name_end - class_name_start); TypeList types; - const uint32_t match_count = FindTypes (empty_sc, class_name, NULL, true, UINT32_MAX, types); - if (match_count > 0) + + TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, true)); + if (!complete_objc_class_type_sp) + complete_objc_class_type_sp = FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false); + + if (complete_objc_class_type_sp) { - for (uint32_t i=0; i<match_count; ++i) - { - Type *type = types.GetTypeAtIndex (i).get(); - clang_type_t type_clang_forward_type = type->GetClangForwardType(); - if (ClangASTContext::IsObjCClassType (type_clang_forward_type)) - { - class_opaque_type = type_clang_forward_type; - break; - } - } + clang_type_t type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType(); + if (ClangASTContext::IsObjCClassType (type_clang_forward_type)) + class_opaque_type = type_clang_forward_type; } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 886fce59c5e..df3b269c958 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -22,6 +22,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "lldb/lldb-private.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/dwarf.h" @@ -375,9 +376,14 @@ protected: const lldb_private::ConstString &type_name); lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE ( - DWARFCompileUnit* cu, const DWARFDebugInfoEntry *die, - const lldb_private::ConstString &type_name); + const lldb_private::ConstString &type_name, + bool must_be_implementation); + + bool Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); + + lldb::TypeSP FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name, + bool header_definition_ok); lldb_private::Symbol * GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name); @@ -498,9 +504,10 @@ protected: NameToDIE m_global_index; // Global and static variables NameToDIE m_type_index; // All type DIE offsets NameToDIE m_namespace_index; // All type DIE offsets - bool m_indexed:1, - m_is_external_ast_source:1, - m_using_apple_tables:1; + bool m_indexed:1, + m_is_external_ast_source:1, + m_using_apple_tables:1; + lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; std::auto_ptr<DWARFDebugRanges> m_ranges; UniqueDWARFASTTypeMap m_unique_ast_type_map; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 4e9fd4f9dc4..596ee5c77cd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -65,7 +65,8 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) : m_flags(), m_compile_unit_infos(), m_func_indexes(), - m_glob_indexes() + m_glob_indexes(), + m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate) { } @@ -952,16 +953,36 @@ SymbolFileDWARFDebugMap::FindDefinitionTypeForDIE (DWARFCompileUnit* cu, } + +bool +SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso) +{ + if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) + { + m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; + SymbolFileDWARF *oso_dwarf; + for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx) + { + if (skip_dwarf_oso != oso_dwarf && oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(NULL)) + { + m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; + break; + } + } + } + return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes; +} + TypeSP -SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (DWARFCompileUnit* cu, - const DWARFDebugInfoEntry *die, - const ConstString &type_name) +SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, + const ConstString &type_name, + bool must_be_implementation) { TypeSP type_sp; SymbolFileDWARF *oso_dwarf; for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx) { - type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (cu, die, type_name); + type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name, must_be_implementation); if (type_sp) break; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 5d271c22e64..544795b5a9c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -216,10 +216,13 @@ protected: const DWARFDebugInfoEntry *die, const lldb_private::ConstString &type_name); + bool + Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso); + lldb::TypeSP - FindCompleteObjCDefinitionTypeForDIE (DWARFCompileUnit* cu, - const DWARFDebugInfoEntry *die, - const lldb_private::ConstString &type_name); + FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, + const lldb_private::ConstString &type_name, + bool must_be_implementation); UniqueDWARFASTTypeMap & @@ -235,6 +238,7 @@ protected: std::vector<uint32_t> m_func_indexes; // Sorted by address std::vector<uint32_t> m_glob_indexes; UniqueDWARFASTTypeMap m_unique_ast_type_map; + lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; }; #endif // #ifndef SymbolFileDWARF_SymbolFileDWARFDebugMap_h_ |