From bc63aaccf7df033abd1f1060c681fe4853433383 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 25 Feb 2015 22:41:34 +0000 Subject: [PATCH] Optimize finding the Complete Definition of an ObjC class for debug with .o files with lots of .o files. When we have a debug map we have an executable with a bunch of STAB symbols and each source file has a N_SO symbol which scopes a bunch of symbols inside of it. We can use this to our advantage here when looking for the complete definition of an objective C class by looking for a symbol whose name matches the class name and whose type is eSymbolTypeObjCClass. If we find one, that symbol will be contained within a N_SO symbol. This symbol gets turned into a symbol whose type is eSymbolTypeSourceFile and that symbol will contain the eSymbolTypeObjCClass which helps us to locate the correct .o file and allows us to only look in that file. To further accelerate things, if we are looking for the implementation, we can avoid looking at all .o files if we don't find a matching symbol because we have a debug map, which means the objective C symbol for the class can't have been stripped, so we can safely not search all remaining .o files. This will save us lots of time when trying to look for "NSObject" and any other AppKit and Foundation classes that we never have implementation definitions for. llvm-svn: 230562 --- lldb/include/lldb/Symbol/Symtab.h | 8 +++ .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 62 +++++++++++++++++++--- lldb/source/Symbol/Symbol.cpp | 2 +- lldb/source/Symbol/Symtab.cpp | 27 ++++++++-- 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h index dc08333..cf28c7e 100644 --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -58,6 +58,14 @@ public: Symbol * SymbolAtIndex (size_t idx); const Symbol * SymbolAtIndex (size_t idx) const; Symbol * FindSymbolWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t &start_idx); + //---------------------------------------------------------------------- + /// Get the parent symbol for the given symbol. + /// + /// Many symbols in symbol tables are scoped by other symbols that + /// contain one or more symbol. This function will look for such a + /// containing symbol and return it if there is one. + //---------------------------------------------------------------------- + const Symbol * GetParent (Symbol *symbol) const; uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, std::vector& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; uint32_t AppendSymbolIndexesWithTypeAndFlagsValue (lldb::SymbolType symbol_type, uint32_t flags_value, std::vector& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector& matches, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index af16c03..e7c6859 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -416,7 +416,7 @@ SymbolFileDWARFDebugMap::InitOSO() m_compile_unit_infos[i].oso_mod_time = oso_mod_time; uint32_t sibling_idx = so_symbol->GetSiblingIndex(); // The sibling index can't be less that or equal to the current index "i" - if (sibling_idx <= i) + if (sibling_idx == UINT32_MAX) { m_obj_file->GetModule()->ReportError ("N_SO in symbol with UID %u has invalid sibling in debug map, please file a bug and attach the binary listed in this error", so_symbol->GetID()); } @@ -1219,15 +1219,63 @@ SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugI const ConstString &type_name, bool must_be_implementation) { + // If we have a debug map, we will have an Objective C symbol whose name is + // the type name and whose type is eSymbolTypeObjCClass. If we can find that + // symbol and find its containing parent, we can locate the .o file that will + // contain the implementation definition since it will be scoped inside the N_SO + // and we can then locate the SymbolFileDWARF that corresponds to that N_SO. + SymbolFileDWARF *oso_dwarf = NULL; TypeSP type_sp; - SymbolFileDWARF *oso_dwarf; - for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx) + ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); + if (module_objfile) { - type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name, must_be_implementation); - if (type_sp) - break; + Symtab *symtab = module_objfile->GetSymtab(); + if (symtab) + { + Symbol *objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(type_name, eSymbolTypeObjCClass, Symtab::eDebugAny, Symtab::eVisibilityAny); + if (objc_class_symbol) + { + // Get the N_SO symbol that contains the objective C class symbol as this + // should be the .o file that contains the real definition... + const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol); + + if (source_file_symbol && source_file_symbol->GetType() == eSymbolTypeSourceFile) + { + const uint32_t source_file_symbol_idx = symtab->GetIndexForSymbol(source_file_symbol); + if (source_file_symbol_idx != UINT32_MAX) + { + CompileUnitInfo *compile_unit_info = GetCompileUnitInfoForSymbolWithIndex (source_file_symbol_idx, NULL); + if (compile_unit_info) + { + oso_dwarf = GetSymbolFileByCompUnitInfo (compile_unit_info); + if (oso_dwarf) + { + TypeSP type_sp (oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name, must_be_implementation)); + if (type_sp) + { + return type_sp; + } + } + } + } + } + } + } } - return type_sp; + + // Only search all .o files for the definition if we don't need the implementation + // because otherwise, with a valid debug map we should have the ObjC class symbol and + // the code above should have found it. + if (must_be_implementation == false) + { + for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx) + { + TypeSP type_sp (oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name, must_be_implementation)); + if (type_sp) + return type_sp; + } + } + return TypeSP(); } uint32_t diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index c1d032c..da22084 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -235,7 +235,7 @@ Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) uint32_t Symbol::GetSiblingIndex() const { - return m_size_is_sibling ? m_addr_range.GetByteSize() : 0; + return m_size_is_sibling ? m_addr_range.GetByteSize() : UINT32_MAX; } bool diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index 1f4afdf..e2bf984 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/Timer.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Target/CPPLanguageRuntime.h" @@ -546,9 +547,12 @@ Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, Debug symbol_debug_ uint32_t Symtab::GetIndexForSymbol (const Symbol *symbol) const { - const Symbol *first_symbol = &m_symbols[0]; - if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) - return symbol - first_symbol; + if (!m_symbols.empty()) + { + const Symbol *first_symbol = &m_symbols[0]; + if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) + return symbol - first_symbol; + } return UINT32_MAX; } @@ -1178,3 +1182,20 @@ Symtab::FindFunctionSymbols (const ConstString &name, return count; } + +const Symbol * +Symtab::GetParent (Symbol *child_symbol) const +{ + uint32_t child_idx = GetIndexForSymbol(child_symbol); + if (child_idx != UINT32_MAX && child_idx > 0) + { + for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) + { + const Symbol *symbol = SymbolAtIndex (idx); + const uint32_t sibling_idx = symbol->GetSiblingIndex(); + if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) + return symbol; + } + } + return NULL; +} -- 2.7.4