From 09ab4b777cdb7ec45e8a8e4181b1d2ab2de3909f Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Wed, 30 Nov 2011 22:11:59 +0000 Subject: [PATCH] Added support to the Objective-C language runtime to find Objective-C class types by looking in the symbol tables for the individual object files. I did this as follows: - I added code to SymbolFileSymtab that vends Clang types for symbols matching the pattern "_OBJC_CLASS_$_NSMyClassName," making them appear as Objective-C classes. This only occurs in modules that do not have debug information, since otherwise SymbolFileDWARF would be in charge of looking up types. - I made a new SymbolVendor subclass for the Apple Objective-C runtime that is in charge of making global lookups of Objective-C types. It currently just sends out type lookup requests to the appropriate SymbolFiles, but in the future we will probably extend it to query the runtime more completely. I also modified a testcase whose behavior is changed by the fact that we now actually return an Objective-C type for __NSCFString. llvm-svn: 145526 --- lldb/include/lldb/Symbol/ClangASTContext.h | 9 +++ lldb/include/lldb/Symbol/SymbolFile.h | 17 +++-- .../include/lldb/Target/ObjCLanguageRuntime.h | 6 ++ lldb/lldb.xcodeproj/project.pbxproj | 6 ++ lldb/source/Expression/ClangASTSource.cpp | 20 +++++ .../AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 10 ++- .../AppleObjCRuntime/AppleObjCRuntimeV2.h | 5 ++ .../AppleObjCSymbolVendor.cpp | 76 +++++++++++++++++++ .../AppleObjCRuntime/AppleObjCSymbolVendor.h | 47 ++++++++++++ .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 65 +++++++++++++++- .../SymbolFile/Symtab/SymbolFileSymtab.h | 7 ++ lldb/source/Symbol/ClangASTContext.cpp | 6 ++ .../TestDataFormatterObjC.py | 4 +- 13 files changed, 266 insertions(+), 12 deletions(-) create mode 100644 lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp create mode 100644 lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 522128a2a37d..095d1d347170 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -195,6 +195,15 @@ public: static lldb::clang_type_t GetVoidPtrType(clang::ASTContext *ast, bool is_const); + static clang::DeclContext * + GetTranslationUnitDecl (clang::ASTContext *ast); + + clang::DeclContext * + GetTranslationUnitDecl () + { + return GetTranslationUnitDecl (getASTContext()); + } + static lldb::clang_type_t CopyType(clang::ASTContext *dest_context, clang::ASTContext *source_context, diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 9b4f32b6073f..776cf3ab2005 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -30,14 +30,15 @@ public: TypeAcceleratorTable = (1 << 3), MacroInformation = (1 << 4), CallFrameInformation = (1 << 5), - CompileUnits = (1 << 6), - LineTables = (1 << 7), - LineColumns = (1 << 8), - Functions = (1 << 9), - Blocks = (1 << 10), - GlobalVariables = (1 << 11), - LocalVariables = (1 << 12), - VariableTypes = (1 << 13) + RuntimeTypes = (1 << 6), + CompileUnits = (1 << 7), + LineTables = (1 << 8), + LineColumns = (1 << 9), + Functions = (1 << 10), + Blocks = (1 << 11), + GlobalVariables = (1 << 12), + LocalVariables = (1 << 13), + VariableTypes = (1 << 14), }; static SymbolFile * diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h index 950740957956..793922168e5c 100644 --- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h +++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h @@ -87,6 +87,12 @@ public: virtual ObjCISA GetParentClass(ObjCISA isa) = 0; + virtual SymbolVendor * + GetSymbolVendor() + { + return NULL; + } + // Finds the byte offset of the child_type ivar in parent_type. If it can't find the // offset, returns LLDB_INVALID_IVAR_OFFSET. diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 2fc7b816494d..d2676f0cd067 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -393,6 +393,7 @@ 49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; }; 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; }; 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; }; + 49DA65031485C92A005FF180 /* AppleObjCSymbolVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCSymbolVendor.cpp */; }; 4CAA56131422D96A001FFA01 /* BreakpointResolverFileRegex.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */; }; 4CAA56151422D986001FFA01 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; }; 4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; }; @@ -1171,6 +1172,8 @@ 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTSource.cpp; path = source/Expression/ClangASTSource.cpp; sourceTree = ""; }; 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTImporter.cpp; path = source/Symbol/ClangASTImporter.cpp; sourceTree = ""; }; 49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = ""; }; + 49DA65021485C92A005FF180 /* AppleObjCSymbolVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCSymbolVendor.cpp; sourceTree = ""; }; + 49DA65041485C942005FF180 /* AppleObjCSymbolVendor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCSymbolVendor.h; sourceTree = ""; }; 49E45FA911F660DC008F7B28 /* ClangASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTType.h; path = include/lldb/Symbol/ClangASTType.h; sourceTree = ""; }; 49E45FAD11F660FE008F7B28 /* ClangASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTType.cpp; path = source/Symbol/ClangASTType.cpp; sourceTree = ""; }; 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = ""; }; @@ -2761,6 +2764,8 @@ 4CCA644513B40B82003BDF98 /* AppleObjCRuntimeV1.h */, 4CCA644613B40B82003BDF98 /* AppleObjCRuntimeV2.cpp */, 4CCA644713B40B82003BDF98 /* AppleObjCRuntimeV2.h */, + 49DA65041485C942005FF180 /* AppleObjCSymbolVendor.h */, + 49DA65021485C92A005FF180 /* AppleObjCSymbolVendor.cpp */, 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */, 4CCA644913B40B82003BDF98 /* AppleObjCTrampolineHandler.h */, 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */, @@ -3515,6 +3520,7 @@ B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */, 49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */, 494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */, + 49DA65031485C92A005FF180 /* AppleObjCSymbolVendor.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index 5f3c8b15b305..db08539b9776 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -17,6 +17,7 @@ #include "lldb/Expression/ClangExpression.h" #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Target.h" using namespace clang; @@ -460,11 +461,29 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, SymbolContext null_sc; if (module_sp && namespace_decl) + { module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types); + } else if(name != id_name && name != Class_name) + { m_target->GetImages().FindTypes (null_sc, name, true, 1, types); + + if (!types.GetSize()) + { + lldb::ProcessSP process = m_target->GetProcessSP(); + + if (process && process->GetObjCLanguageRuntime()) + { + SymbolVendor *objc_symbol_vendor = process->GetObjCLanguageRuntime()->GetSymbolVendor(); + + objc_symbol_vendor->FindTypes(null_sc, name, NULL, true, 1, types); + } + } + } else + { break; + } if (types.GetSize()) { @@ -484,6 +503,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, context.AddTypeDecl(copied_type); } + } while(0); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 1b72409e4770..d79eb7530155 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -38,9 +38,9 @@ #include "lldb/Target/Thread.h" #include "AppleObjCRuntimeV2.h" +#include "AppleObjCSymbolVendor.h" #include "AppleObjCTrampolineHandler.h" - #include using namespace lldb; @@ -769,3 +769,11 @@ AppleObjCRuntimeV2::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) return parent_isa; } +SymbolVendor * +AppleObjCRuntimeV2::GetSymbolVendor() +{ + if (!m_symbol_vendor_ap.get()) + m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process)); + + return m_symbol_vendor_ap.get(); +} diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 64ef4447d2a1..cf4bf3f641e2 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -96,6 +96,9 @@ public: virtual ObjCLanguageRuntime::ObjCISA GetParentClass(ObjCLanguageRuntime::ObjCISA isa); + virtual SymbolVendor * + GetSymbolVendor(); + protected: private: @@ -123,6 +126,8 @@ private: ISAToNameCache m_isa_to_name_cache; ISAToParentCache m_isa_to_parent_cache; + std::auto_ptr m_symbol_vendor_ap; + static const char *g_find_class_name_function_name; static const char *g_find_class_name_function_body; static const char *g_objc_class_symbol_prefix; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp new file mode 100644 index 000000000000..b7c7a1d1ad09 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp @@ -0,0 +1,76 @@ +//===-- AppleObjCSymbolVendor.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AppleObjCSymbolVendor.h" + +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "clang/AST/ASTContext.h" + +using namespace lldb_private; + +AppleObjCSymbolVendor::AppleObjCSymbolVendor(Process *process) : + SymbolVendor(NULL), + m_process(process->GetSP()), + m_ast_ctx(process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()) +{ +} + +uint32_t +AppleObjCSymbolVendor::FindTypes (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + uint32_t max_matches, + TypeList& types) +{ + lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); // FIXME - a more appropriate log channel? + + if (log) + log->Printf("ObjC SymbolVendor asked for '%s'", + name.AsCString()); + + if (!append) + types.Clear(); + + uint32_t ret = 0; + + ModuleList &images = m_process->GetTarget().GetImages(); + + for (size_t image_index = 0, end_index = images.GetSize(); + image_index < end_index; + ++image_index) + { + Module *image = images.GetModulePointerAtIndex(image_index); + + if (!image) + continue; + + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolFile *symbol_file = image->GetSymbolVendor()->GetSymbolFile(); + + if (!symbol_file || !(symbol_file->GetAbilities() & SymbolFile::RuntimeTypes)) + continue; + + const bool inferior_append = true; + + ret += symbol_file->FindTypes (sc, name, namespace_decl, inferior_append, max_matches - ret, types); + + if (ret >= max_matches) + break; + } + + return ret; +} diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h new file mode 100644 index 000000000000..b426de5cf76d --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h @@ -0,0 +1,47 @@ +//===-- AppleObjCSymbolVendor.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AppleObjCSymbolVendor_h_ +#define liblldb_AppleObjCSymbolVendor_h_ + +// C Includes +// C++ Includes + +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" + +namespace lldb_private { + +class AppleObjCSymbolVendor : public SymbolVendor +{ +public: + AppleObjCSymbolVendor(Process* process); + + virtual uint32_t + FindTypes (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + uint32_t max_matches, + TypeList& types); + +private: + lldb::ProcessSP m_process; + ClangASTContext m_ast_ctx; +}; + +} // namespace lldb_private + +#endif // liblldb_AppleObjCSymbolVendor_h_ diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index c3e02d7573ff..a824267487d6 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -63,7 +63,8 @@ SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) : m_func_indexes(), m_code_indexes(), m_data_indexes(), - m_addr_indexes() + m_addr_indexes(), + m_has_objc_symbols(eLazyBoolCalculate) { } @@ -71,6 +72,27 @@ SymbolFileSymtab::~SymbolFileSymtab() { } +ClangASTContext & +SymbolFileSymtab::GetClangASTContext () +{ + ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); + + return ast; +} + +bool +SymbolFileSymtab::HasObjCSymbols () +{ + if (m_has_objc_symbols == eLazyBoolCalculate) + { + if (m_obj_file->GetSectionList()->FindSectionByName(ConstString("__objc_data"))) + m_has_objc_symbols = eLazyBoolYes; + else + m_has_objc_symbols = eLazyBoolNo; + } + + return m_has_objc_symbols == eLazyBoolYes; +} uint32_t SymbolFileSymtab::GetAbilities () @@ -113,6 +135,11 @@ SymbolFileSymtab::GetAbilities () symtab->SortSymbolIndexesByValue(m_data_indexes, true); abilities |= GlobalVariables; } + + if (HasObjCSymbols()) + { + abilities |= RuntimeTypes; + } } } return abilities; @@ -352,6 +379,42 @@ SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc, const lldb_p { if (!append) types.Clear(); + + if (HasObjCSymbols()) + { + std::string symbol_name("OBJC_CLASS_$_"); + symbol_name.append(name.AsCString()); + ConstString symbol_const_string(symbol_name.c_str()); + + std::vector indices; + + if (m_obj_file->GetSymtab()->FindAllSymbolsWithNameAndType(symbol_const_string, lldb::eSymbolTypeRuntime, indices) == 0) + return 0; + + const bool isForwardDecl = false; + const bool isInternal = true; + + ClangASTContext &clang_ast_ctx = GetClangASTContext(); + + lldb::clang_type_t objc_object_type = clang_ast_ctx.CreateObjCClass(name.AsCString(), clang_ast_ctx.GetTranslationUnitDecl(), isForwardDecl, isInternal); + + Declaration decl; + + lldb::TypeSP type(new Type (indices[0], + this, + name, + 0 /*byte_size*/, + NULL /*SymbolContextScope*/, + 0 /*encoding_uid*/, + Type::eEncodingInvalid, + decl, + objc_object_type, + Type::eResolveStateForward)); + + types.Insert(type); + + return 1; + } return 0; } diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index ba43a30424ea..d7e58af1182b 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -119,12 +119,19 @@ public: GetPluginVersion(); protected: + lldb_private::LazyBool m_has_objc_symbols; std::vector m_source_indexes; std::vector m_func_indexes; std::vector m_code_indexes; std::vector m_data_indexes; std::vector m_addr_indexes; // Anything that needs to go into an search by address + bool + HasObjCSymbols (); + + lldb_private::ClangASTContext & + GetClangASTContext (); + private: DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab); }; diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index fda35d978a46..8acf79d98ea0 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -980,6 +980,12 @@ ClangASTContext::GetVoidPtrType (ASTContext *ast, bool is_const) return void_ptr_type.getAsOpaquePtr(); } +clang::DeclContext * +ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast) +{ + return ast->getTranslationUnitDecl(); +} + clang_type_t ClangASTContext::CopyType (ASTContext *dst_ast, ASTContext *src_ast, diff --git a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py index b34c83c33ffa..10034fa516bd 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py @@ -233,10 +233,10 @@ class ObjCDataFormatterTestCase(TestBase): self.expect('frame variable dyn_test', matching=False, substrs = ['Process Name: a.out Process Id:']) self.expect('frame variable dyn_test -d run-target -T', - substrs = ['(id, dynamic type:', + substrs = ['(__NSCFString *, dynamic type:', 'Process Name: a.out Process Id:']) self.expect('frame variable dyn_test -d run-target', - substrs = ['(id)', + substrs = ['(__NSCFString *)', 'Process Name: a.out Process Id:'])