diff options
-rw-r--r-- | lldb/include/lldb/Symbol/TypeVendor.h | 56 | ||||
-rw-r--r-- | lldb/include/lldb/Target/LanguageRuntime.h | 6 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ObjCLanguageRuntime.h | 8 | ||||
-rw-r--r-- | lldb/source/Expression/ClangASTSource.cpp | 395 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 13 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h | 8 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp | 83 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp | 198 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h (renamed from lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h) | 26 | ||||
-rw-r--r-- | lldb/source/Target/ObjCLanguageRuntime.cpp | 10 |
10 files changed, 560 insertions, 243 deletions
diff --git a/lldb/include/lldb/Symbol/TypeVendor.h b/lldb/include/lldb/Symbol/TypeVendor.h new file mode 100644 index 00000000000..4ae82fd9522 --- /dev/null +++ b/lldb/include/lldb/Symbol/TypeVendor.h @@ -0,0 +1,56 @@ +//===-- TypeVendor.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_TypeVendor_h_ +#define liblldb_TypeVendor_h_ + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The type vendor class is intended as a generic interface to search +// for Clang types that are not necessarily backed by a specific symbol +// file. +//---------------------------------------------------------------------- +class TypeVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeVendor() + { + } + + virtual + ~TypeVendor() + { + } + + virtual uint32_t + FindTypes (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector <ClangASTType> &types) = 0; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from TypeVendor can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For TypeVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (TypeVendor); +}; + + +} // namespace lldb_private + +#endif diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index 4ca9f7419d2..5a4dc7ae7f6 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -83,6 +83,12 @@ public: static const char * GetNameForLanguageType (lldb::LanguageType language); + + Process * + GetProcess() + { + return m_process; + } protected: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h index 24891ed15c5..64aded76adf 100644 --- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h +++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h @@ -19,6 +19,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeVendor.h" #include "lldb/Target/LanguageRuntime.h" namespace lldb_private { @@ -222,14 +223,17 @@ public: virtual ObjCISA GetISA(ValueObject& valobj) = 0; + virtual ObjCISA + GetISA(const ConstString &name); + virtual ConstString GetActualTypeName(ObjCISA isa); virtual ObjCISA GetParentClass(ObjCISA isa); - virtual SymbolVendor * - GetSymbolVendor() + virtual TypeVendor * + GetTypeVendor() { return NULL; } diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index f94eb9c8e6c..80a9ea3dd6a 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -622,9 +622,11 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, name.GetCString(), (name_string ? name_string : "<anonymous>")); } - + + clang::ASTContext *type_ast = type_sp->GetClangAST(); + lldb::clang_type_t full_type = type_sp->GetClangFullType(); - void *copied_type = GuardedCopyType(m_ast_context, type_sp->GetClangAST(), type_sp->GetClangFullType()); + void *copied_type = GuardedCopyType(m_ast_context, type_ast, full_type); if (!copied_type) { @@ -641,6 +643,87 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, } while(0); } +static void +FindObjCMethodDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + ObjCInterfaceDecl *original_interface_decl, + clang::ASTContext *ast_context, + ClangASTImporter *ast_importer, + const char *log_info) +{ + const DeclarationName &decl_name(context.m_decl_name); + clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); + + Selector original_selector; + + if (decl_name.isObjCZeroArgSelector()) + { + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); + original_selector = original_ctx->Selectors.getSelector(0, &ident); + } + else if (decl_name.isObjCOneArgSelector()) + { + const std::string &decl_name_string = decl_name.getAsString(); + std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); + original_selector = original_ctx->Selectors.getSelector(1, &ident); + } + else + { + SmallVector<IdentifierInfo *, 4> idents; + + clang::Selector sel = decl_name.getObjCSelector(); + + int num_args = sel.getNumArgs(); + + for (unsigned i = 0; + i != num_args; + ++i) + { + idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); + } + + original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); + } + + DeclarationName original_decl_name(original_selector); + + ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name); + + if (result.first == result.second) + return; + + if (!*result.first) + return; + + ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(*result.first); + + if (!result_method) + return; + + Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); + + if (!copied_decl) + return; + + ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + + if (!copied_method_decl) + return; + + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); + + return; +} + void ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) { @@ -669,72 +752,12 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl); - Selector original_selector; - - if (decl_name.isObjCZeroArgSelector()) - { - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); - original_selector = original_ctx->Selectors.getSelector(0, &ident); - } - else if (decl_name.isObjCOneArgSelector()) - { - const std::string &decl_name_string = decl_name.getAsString(); - std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); - original_selector = original_ctx->Selectors.getSelector(1, &ident); - } - else - { - SmallVector<IdentifierInfo *, 4> idents; - - clang::Selector sel = decl_name.getObjCSelector(); - - int num_args = sel.getNumArgs(); - - for (unsigned i = 0; - i != num_args; - ++i) - { - idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); - } - - original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); - } - - DeclarationName original_decl_name(original_selector); - - ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name); - - if (result.first == result.second) - break; - - if (!*result.first) - break; - - ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(*result.first); - - if (!result_method) - break; - - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &result_method->getASTContext(), result_method); - - if (!copied_decl) - continue; - - ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); - - if (!copied_method_decl) - continue; - - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString()); - } - - context.AddNamedDecl(copied_method_decl); - - return; + FindObjCMethodDeclsWithOrigin(current_id, + context, + original_interface_decl, + m_ast_context, + m_ast_importer, + "in debug info"); } while (0); StreamString ss; @@ -845,53 +868,105 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) } while (0); - for (uint32_t i = 0, e = sc_list.GetSize(); - i != e; - ++i) + if (sc_list.GetSize()) { - SymbolContext sc; - - if (!sc_list.GetContextAtIndex(i, sc)) - continue; - - if (!sc.function) - continue; - - DeclContext *function_ctx = sc.function->GetClangDeclContext(); - - if (!function_ctx) - continue; - - ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx); - - if (!method_decl) - continue; - - ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); - - if (!found_interface_decl) - continue; + // We found a good function symbol. Use that. - if (found_interface_decl->getName() == interface_decl->getName()) + for (uint32_t i = 0, e = sc_list.GetSize(); + i != e; + ++i) { - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + SymbolContext sc; - if (!copied_decl) + if (!sc_list.GetContextAtIndex(i, sc)) continue; - ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + if (!sc.function) + continue; - if (!copied_method_decl) + DeclContext *function_ctx = sc.function->GetClangDeclContext(); + + if (!function_ctx) continue; - if (log) + ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx); + + if (!method_decl) + continue; + + ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); + + if (!found_interface_decl) + continue; + + if (found_interface_decl->getName() == interface_decl->getName()) { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString()); + Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + + if (!copied_decl) + continue; + + ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + + if (!copied_method_decl) + continue; + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); } + } + } + else + { + do + { + // We need to look at the runtime. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + TypeVendor *type_vendor = language_runtime->GetTypeVendor(); + + if (!type_vendor) + break; + + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector <ClangASTType> types; + + if (!type_vendor->FindTypes(interface_name, + append, + max_matches, + types)) + break; - context.AddNamedDecl(copied_method_decl); + const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); + + const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type); + + if (!runtime_interface_type) + break; + + ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl(); + + FindObjCMethodDeclsWithOrigin(current_id, + context, + runtime_interface_decl, + m_ast_context, + m_ast_importer, + "in runtime"); } + while(0); } } @@ -1055,41 +1130,89 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) if (!language_runtime) return; - lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); - - if (!complete_type_sp) - return; - - TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST()); - lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); - - if (!complete_opaque_type) - return; - - const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); - const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type); - - if (!complete_interface_type) - return; - - DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl()); - - if (complete_iface_decl.decl == origin_iface_decl.decl) - return; // already checked this one - - if (log) - log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - complete_iface_decl.decl, - &complete_iface_decl->getASTContext()); - + do + { + // First see if any other debug information has this property/ivar. + + lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + + if (!complete_type_sp) + break; + + TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST()); + lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + + if (!complete_opaque_type) + break; + + const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); + const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type); + + if (!complete_interface_type) + break; + + DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl()); + + if (complete_iface_decl.decl == origin_iface_decl.decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + complete_iface_decl.decl, + &complete_iface_decl->getASTContext()); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer, + complete_iface_decl)) + return; + } + while(0); - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, - complete_iface_decl)) - return; + do + { + // Now check the runtime. + + TypeVendor *type_vendor = language_runtime->GetTypeVendor(); + + if (!type_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector <ClangASTType> types; + + if (!type_vendor->FindTypes(class_name, + append, + max_matches, + types)) + break; + + const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr(); + + const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type); + + if (!runtime_interface_type) + break; + + DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(runtime_interface_type->getDecl()); + + if (log) + log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + runtime_iface_decl.decl, + &runtime_iface_decl->getASTContext()); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer, + runtime_iface_decl)) + return; + } + while(0); } typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 7945270e18a..e2deca56eef 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -32,6 +32,7 @@ #include "lldb/Expression/ClangUtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/TypeList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -39,7 +40,7 @@ #include "lldb/Target/Thread.h" #include "AppleObjCRuntimeV2.h" -#include "AppleObjCSymbolVendor.h" +#include "AppleObjCTypeVendor.h" #include "AppleObjCTrampolineHandler.h" #include <vector> @@ -700,13 +701,13 @@ AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) return descriptor->GetClassName(); } -SymbolVendor * -AppleObjCRuntimeV2::GetSymbolVendor() +TypeVendor * +AppleObjCRuntimeV2::GetTypeVendor() { - if (!m_symbol_vendor_ap.get()) - m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process)); + if (!m_type_vendor_ap.get()) + m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this)); - return m_symbol_vendor_ap.get(); + return m_type_vendor_ap.get(); } AppleObjCRuntimeV2::ClassDescriptorV2::ClassDescriptorV2 (ValueObject &isa_pointer) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index ff94b81dfac..90179cafbf4 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -244,7 +244,7 @@ public: static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1; virtual ObjCLanguageRuntime::ObjCISA - GetISA(ValueObject& valobj); + GetISA(ValueObject& valobj); virtual ConstString GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa); @@ -255,8 +255,8 @@ public: virtual ClassDescriptorSP GetClassDescriptor (ObjCISA isa); - virtual SymbolVendor * - GetSymbolVendor(); + virtual TypeVendor * + GetTypeVendor(); protected: virtual lldb::BreakpointResolverSP @@ -278,7 +278,7 @@ private: lldb::addr_t m_get_class_name_args; Mutex m_get_class_name_args_mutex; - std::auto_ptr<SymbolVendor> m_symbol_vendor_ap; + std::auto_ptr<TypeVendor> m_type_vendor_ap; static const char *g_find_class_name_function_name; static const char *g_find_class_name_function_body; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp deleted file mode 100644 index fba909b8701..00000000000 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//===-- 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/Core/Module.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(lldb::ModuleSP()), - m_process(process->shared_from_this()), - 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 &target_modules = m_process->GetTarget().GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); - - for (size_t image_index = 0, end_index = target_modules.GetSize(); - image_index < end_index; - ++image_index) - { - Module *image = target_modules.GetModulePointerAtIndexUnlocked(image_index); - - if (!image) - continue; - - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); - - if (!symbol_vendor) - continue; - - SymbolFile *symbol_file = image->GetSymbolVendor()->GetSymbolFile(); - - // Don't use a symbol file if it actually has types. We are specifically - // looking for something in runtime information, not from debug information, - // as the data in debug information will get parsed by the debug info - // symbol files. So we veto any symbol file that has actual variable - // type parsing abilities. - if (symbol_file == NULL || (symbol_file->GetAbilities() & SymbolFile::VariableTypes)) - 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/AppleObjCTypeVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp new file mode 100644 index 00000000000..e14e2e6f508 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp @@ -0,0 +1,198 @@ +//===-- 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 "AppleObjCTypeVendor.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Expression/ASTDumper.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" + +using namespace lldb_private; + +class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon +{ +public: + AppleObjCExternalASTSource (AppleObjCTypeVendor &type_vendor) : + m_type_vendor(type_vendor) + { + } + + clang::DeclContextLookupResult + FindExternalVisibleDeclsByName (const clang::DeclContext *DC, + clang::DeclarationName Name) + { + return clang::DeclContextLookupResult(); + } + + clang::ExternalLoadResult + FindExternalLexicalDecls (const clang::DeclContext *DC, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl<clang::Decl*> &Decls) + { + return clang::ELR_Success; + } + + void + CompleteType (clang::TagDecl *Tag) + { + return; + } + + void + CompleteType (clang::ObjCInterfaceDecl *Class) + { + return; + } + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) + { + return false; + } + + void StartTranslationUnit (clang::ASTConsumer *Consumer) + { + clang::TranslationUnitDecl *translation_unit_decl = m_type_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl(); + translation_unit_decl->setHasExternalVisibleStorage(); + translation_unit_decl->setHasExternalLexicalStorage(); + } +private: + AppleObjCTypeVendor &m_type_vendor; +}; + +AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) : + TypeVendor(), + m_runtime(runtime), + m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()) +{ + m_external_source = new AppleObjCExternalASTSource (*this); + llvm::OwningPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source); + m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr); +} + +uint32_t +AppleObjCTypeVendor::FindTypes (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector <ClangASTType> &types) +{ + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? + + if (log) + log->Printf("AppleObjCTypeVendor::FindTypes [%u] ('%s', %s, %u, )", + current_id, + (const char*)name.AsCString(), + append ? "true" : "false", + max_matches); + + if (!append) + types.clear(); + + uint32_t ret = 0; + + do + { + // See if the type is already in our ASTContext. + + clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext(); + + clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef()); + clang::DeclarationName decl_name = ast_ctx->DeclarationNames.getIdentifier(&identifier_info); + + clang::DeclContext::lookup_const_result lookup_result = ast_ctx->getTranslationUnitDecl()->lookup(decl_name); + + if (lookup_result.first != lookup_result.second) + { + if (const clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.first)) + { + clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl); + + if (log) + { + ASTDumper dumper(result_iface_type); + log->Printf("AOCTV::FT [%u] Found %s (isa 0x%llx) in the ASTContext", + current_id, + dumper.GetCString(), + m_external_source->GetMetadata((uintptr_t)result_iface_decl)); + } + + types.push_back(ClangASTType(ast_ctx, result_iface_type.getAsOpaquePtr())); + ret++; + break; + } + else + { + if (log) + log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but it's not something we know about", + current_id); + break; + } + } + else if(log) + { + log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext", + current_id, + name.AsCString()); + } + + // It's not. If it exists, we have to put it into our ASTContext. + + // TODO Actually do this. But we have to search the class list first. Until then we'll just give up. + break; + + ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); + + if (!isa) + { + if (log) + log->Printf("AOCTV::FT [%u] Couldn't find the isa", + current_id); + + break; + } + + clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx, + ast_ctx->getTranslationUnitDecl(), + clang::SourceLocation(), + &identifier_info, + NULL); + + m_external_source->SetMetadata((uintptr_t)new_iface_decl, (uint64_t)isa); + + new_iface_decl->setHasExternalVisibleStorage(); + + clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(new_iface_decl); + + if (log) + { + ASTDumper dumper(new_iface_type); + log->Printf("AOCTV::FT [%u] Created %s (isa 0x%llx)", + current_id, + dumper.GetCString(), + (uint64_t)isa); + } + } while (0); + + return ret; +} diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h index b426de5cf76..e06011662a9 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h @@ -16,30 +16,32 @@ #include <map> // 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" +#include "lldb/Symbol/TypeVendor.h" namespace lldb_private { + +class AppleObjCExternalASTSource; -class AppleObjCSymbolVendor : public SymbolVendor +class AppleObjCTypeVendor : public TypeVendor { public: - AppleObjCSymbolVendor(Process* process); + AppleObjCTypeVendor(ObjCLanguageRuntime &runtime); virtual uint32_t - FindTypes (const SymbolContext& sc, - const ConstString &name, - const ClangNamespaceDecl *namespace_decl, - bool append, - uint32_t max_matches, - TypeList& types); + FindTypes (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector <ClangASTType> &types); + friend class AppleObjCExternalASTSource; private: - lldb::ProcessSP m_process; - ClangASTContext m_ast_ctx; + ObjCLanguageRuntime &m_runtime; + ClangASTContext m_ast_ctx; + AppleObjCExternalASTSource *m_external_source; }; } // namespace lldb_private diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp index a404ce40c2d..df00c353c4a 100644 --- a/lldb/source/Target/ObjCLanguageRuntime.cpp +++ b/lldb/source/Target/ObjCLanguageRuntime.cpp @@ -281,6 +281,16 @@ ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value, } ObjCLanguageRuntime::ObjCISA +ObjCLanguageRuntime::GetISA(const ConstString &name) +{ + for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache) + if (val.second && val.second->GetClassName() == name) + return val.first; + + return 0; +} + +ObjCLanguageRuntime::ObjCISA ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) { if (!IsValidISA(isa)) |