diff options
| author | Sean Callanan <scallanan@apple.com> | 2012-09-20 17:01:52 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2012-09-20 17:01:52 +0000 |
| commit | d0dcae08e56b059a7fd012dd941d544dd6b0dad8 (patch) | |
| tree | 66b0f7708b09869293d6e46c7c335e49b21b9763 | |
| parent | c727bacb38208be6af9c4701f12f0cd3008a7f22 (diff) | |
| download | bcm5719-llvm-d0dcae08e56b059a7fd012dd941d544dd6b0dad8.tar.gz bcm5719-llvm-d0dcae08e56b059a7fd012dd941d544dd6b0dad8.zip | |
More work for reading the Objective-C runtime.
We can now read the relevant data structures for
the method list, and use a callback mechanism to
report their details to the AppleObjCTypeVendor,
which constructs appropriate Clang types.
llvm-svn: 164310
4 files changed, 347 insertions, 68 deletions
diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h index 1d263c44ed1..d812554d0f2 100644 --- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h +++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include <functional> #include <map> // Other libraries and framework includes @@ -115,7 +116,8 @@ public: // This should return true iff the interface could be completed virtual bool - CompleteInterface (clang::ObjCInterfaceDecl *interface_decl) + Describe (std::function <void (ObjCISA)> const &superclass_func, + std::function <void (const char*, const char*)> const &method_func) { return false; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index ca2b6966d02..30e8ff01070 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -1039,12 +1039,56 @@ public: } virtual bool - CompleteInterface (clang::ObjCInterfaceDecl *interface_decl) + Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func, + std::function <void (const char *, const char *)> const &method_func) { if (!m_valid) return false; - return false; + std::auto_ptr <class_ro_t> ro; + std::auto_ptr <class_rw_t> rw; + + ProcessSP process_sp = m_process_wp.lock(); + + if (!process_sp) + return false; + + if (IsRealized()) + { + rw.reset(new class_rw_t); + if (!rw->Read(process_sp, m_objc_class.m_data_la)) + return false; + + ro.reset(new class_ro_t); + if (!ro->Read(process_sp, rw->m_ro_la)) + return false; + } + else + { + ro.reset(new class_ro_t); + if (!ro->Read(process_sp, m_objc_class.m_data_la)) + return false; + } + + superclass_func(m_objc_class.m_superclass); + + std::auto_ptr <method_list_t> base_method_list; + + base_method_list.reset(new method_list_t); + if (!base_method_list->Read(process_sp, ro->m_baseMethods_la)) + return false; + + std::auto_ptr <method_t> method; + method.reset(new method_t); + + for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) + { + method->Read(process_sp, base_method_list->m_first_la + (i * base_method_list->m_entsize)); + + method_func(method->m_name.c_str(), method->m_types.c_str()); + } + + return true; } virtual bool @@ -1102,35 +1146,11 @@ protected: m_valid = false; return; } - - size_t objc_class_size = ptr_size // uintptr_t isa; - + ptr_size // Class superclass; - + ptr_size // void *cache; - + ptr_size // IMP *vtable; - + ptr_size; // uintptr_t data_NEVER_USE; + if (!m_objc_class.Read(process_sp, m_objc_class_la)) { - DataBufferHeap objc_class_buf (objc_class_size, '\0'); - - process_sp->ReadMemory(m_objc_class_la, objc_class_buf.GetBytes(), objc_class_size, error); - if (error.Fail()) - { - m_valid = false; - return; - } - - DataExtractor objc_class_extractor(objc_class_buf.GetBytes(), objc_class_size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); - - uint32_t cursor = 0; - - m_objc_class.m_isa = objc_class_extractor.GetAddress_unchecked(&cursor); // uintptr_t isa; - m_objc_class.m_superclass = objc_class_extractor.GetAddress_unchecked(&cursor); // Class superclass; - m_objc_class.m_cache_la = objc_class_extractor.GetAddress_unchecked(&cursor); // void *cache; - m_objc_class.m_vtable_la = objc_class_extractor.GetAddress_unchecked(&cursor); // IMP *vtable; - lldb::addr_t data_NEVER_USE = objc_class_extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE; - - m_objc_class.m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3); - m_objc_class.m_data_la = data_NEVER_USE & ~(lldb::addr_t)3; + m_valid = false; + return; } // Now we just want to grab the instance size and the name. @@ -1227,7 +1247,7 @@ protected: m_process_wp = lldb::ProcessWP(process_sp); } - + private: static const uint32_t RW_REALIZED = (1 << 31); @@ -1241,6 +1261,41 @@ private: lldb::addr_t m_vtable_la; lldb::addr_t m_data_la; uint8_t m_flags; + + bool Read(ProcessSP &process_sp, lldb::addr_t addr) + { + size_t ptr_size = process_sp->GetAddressByteSize(); + + size_t objc_class_size = ptr_size // uintptr_t isa; + + ptr_size // Class superclass; + + ptr_size // void *cache; + + ptr_size // IMP *vtable; + + ptr_size; // uintptr_t data_NEVER_USE; + + DataBufferHeap objc_class_buf (objc_class_size, '\0'); + Error error; + + process_sp->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error); + if (error.Fail()) + { + return false; + } + + DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + uint32_t cursor = 0; + + m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa; + m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass; + m_cache_la = extractor.GetAddress_unchecked(&cursor); // void *cache; + m_vtable_la = extractor.GetAddress_unchecked(&cursor); // IMP *vtable; + lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE; + + m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3); + m_data_la = data_NEVER_USE & ~(lldb::addr_t)3; + + return true; + } }; objc_class_t m_objc_class; @@ -1264,10 +1319,55 @@ private: lldb::addr_t m_weakIvarLayout_la; lldb::addr_t m_baseProperties_la; + + bool Read(ProcessSP &process_sp, lldb::addr_t addr) + { + size_t ptr_size = process_sp->GetAddressByteSize(); + + size_t size = sizeof(uint32_t) // uint32_t flags; + + sizeof(uint32_t) // uint32_t instanceStart; + + sizeof(uint32_t) // uint32_t instanceSize; + + (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only + + ptr_size // const uint8_t *ivarLayout; + + ptr_size // const char *name; + + ptr_size // const method_list_t *baseMethods; + + ptr_size // const protocol_list_t *baseProtocols; + + ptr_size // const ivar_list_t *ivars; + + ptr_size // const uint8_t *weakIvarLayout; + + ptr_size; // const property_list_t *baseProperties; + + DataBufferHeap buffer (size, '\0'); + Error error; + + process_sp->ReadMemory(addr, buffer.GetBytes(), size, error); + if (error.Fail()) + { + return false; + } + + DataExtractor extractor(buffer.GetBytes(), size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + uint32_t cursor = 0; + + m_flags = extractor.GetU32_unchecked(&cursor); + m_instanceStart = extractor.GetU32_unchecked(&cursor); + m_instanceSize = extractor.GetU32_unchecked(&cursor); + if (ptr_size == 8) + m_reserved = extractor.GetU32_unchecked(&cursor); + else + m_reserved = 0; + m_ivarLayout_la = extractor.GetAddress_unchecked(&cursor); + m_name_la = extractor.GetAddress_unchecked(&cursor); + m_baseMethods_la = extractor.GetAddress_unchecked(&cursor); + m_baseProtocols_la = extractor.GetAddress_unchecked(&cursor); + m_ivars_la = extractor.GetAddress_unchecked(&cursor); + m_weakIvarLayout_la = extractor.GetAddress_unchecked(&cursor); + m_baseProperties_la = extractor.GetAddress_unchecked(&cursor); + + return true; + } }; - std::auto_ptr<class_ro_t> m_class_ro; - struct class_rw_t { uint32_t m_flags; uint32_t m_version; @@ -1282,9 +1382,122 @@ private: ObjCLanguageRuntime::ObjCISA m_firstSubclass; ObjCLanguageRuntime::ObjCISA m_nextSiblingClass; + + bool Read(ProcessSP &process_sp, lldb::addr_t addr) + { + size_t ptr_size = process_sp->GetAddressByteSize(); + + size_t size = sizeof(uint32_t) // uint32_t flags; + + sizeof(uint32_t) // uint32_t version; + + ptr_size // const class_ro_t *ro; + + ptr_size // union { method_list_t **method_lists; method_list_t *method_list; }; + + ptr_size // struct chained_property_list *properties; + + ptr_size // const protocol_list_t **protocols; + + ptr_size // Class firstSubclass; + + ptr_size; // Class nextSiblingClass; + + DataBufferHeap buffer (size, '\0'); + Error error; + + process_sp->ReadMemory(addr, buffer.GetBytes(), size, error); + if (error.Fail()) + { + return false; + } + + DataExtractor extractor(buffer.GetBytes(), size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + uint32_t cursor = 0; + + m_flags = extractor.GetU32_unchecked(&cursor); + m_version = extractor.GetU32_unchecked(&cursor); + m_ro_la = extractor.GetAddress_unchecked(&cursor); + m_method_list_la = extractor.GetAddress_unchecked(&cursor); + m_properties_la = extractor.GetAddress_unchecked(&cursor); + m_firstSubclass = extractor.GetAddress_unchecked(&cursor); + m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor); + + return true; + } }; - std::auto_ptr<class_rw_t> m_class_rw; + struct method_list_t + { + uint32_t m_entsize; + uint32_t m_count; + lldb::addr_t m_first_la; + + bool Read(ProcessSP &process_sp, lldb::addr_t addr) + { + size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE; + + sizeof(uint32_t); // uint32_t count; + + DataBufferHeap buffer (size, '\0'); + Error error; + + process_sp->ReadMemory(addr, buffer.GetBytes(), size, error); + if (error.Fail()) + { + return false; + } + + DataExtractor extractor(buffer.GetBytes(), size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + uint32_t cursor = 0; + + m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3; + m_count = extractor.GetU32_unchecked(&cursor); + m_first_la = addr + cursor; + + return true; + } + }; + + struct method_t + { + lldb::addr_t m_name_la; + lldb::addr_t m_types_la; + lldb::addr_t m_imp_la; + + std::string m_name; + std::string m_types; + + bool Read(ProcessSP &process_sp, lldb::addr_t addr) + { + size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE; + + sizeof(uint32_t); // uint32_t count; + + DataBufferHeap buffer (size, '\0'); + Error error; + + process_sp->ReadMemory(addr, buffer.GetBytes(), size, error); + if (error.Fail()) + { + return false; + } + + DataExtractor extractor(buffer.GetBytes(), size, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + uint32_t cursor = 0; + + m_name_la = extractor.GetAddress_unchecked(&cursor); + m_types_la = extractor.GetAddress_unchecked(&cursor); + m_imp_la = extractor.GetAddress_unchecked(&cursor); + + const size_t buffer_size = 1024; + size_t count; + + DataBufferHeap string_buf(buffer_size, 0); + + count = process_sp->ReadCStringFromMemory(m_name_la, (char*)string_buf.GetBytes(), buffer_size, error); + m_name.assign((char*)string_buf.GetBytes(), count); + + count = process_sp->ReadCStringFromMemory(m_types_la, (char*)string_buf.GetBytes(), buffer_size, error); + m_types.assign((char*)string_buf.GetBytes(), count); + + return true; + } + }; lldb::ProcessWP m_process_wp; }; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp index ac293946bf3..78ff9d40bcd 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp @@ -55,28 +55,12 @@ public: if (!interface_decl) break; - - ObjCLanguageRuntime::ObjCISA objc_isa = (ObjCLanguageRuntime::ObjCISA)GetMetadata((uintptr_t)interface_decl); - - if (!objc_isa) - break; clang::ObjCInterfaceDecl *non_const_interface_decl = const_cast<clang::ObjCInterfaceDecl*>(interface_decl); - - if (non_const_interface_decl->hasExternalVisibleStorage()) - { - ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_type_vendor.m_runtime.GetClassDescriptor(objc_isa); - - if (!descriptor) - break; - - if (descriptor->CompleteInterface(non_const_interface_decl)) - non_const_interface_decl->setHasExternalVisibleStorage(false); - } - if (non_const_interface_decl->hasExternalVisibleStorage()) + if (!m_type_vendor.FinishDecl(non_const_interface_decl)) break; - + return non_const_interface_decl->lookup(name); } while(0); @@ -183,6 +167,78 @@ AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) : m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr); } +clang::ObjCInterfaceDecl* +AppleObjCTypeVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) +{ + ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa); + + if (iter != m_isa_to_interface.end()) + return iter->second; + + clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext(); + + ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptor(isa); + + if (!descriptor) + return NULL; + + const ConstString &name(descriptor->GetClassName()); + + clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef()); + + 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(); + ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl); + + m_isa_to_interface[isa] = new_iface_decl; + + return new_iface_decl; +} + +bool +AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) +{ + ObjCLanguageRuntime::ObjCISA objc_isa = (ObjCLanguageRuntime::ObjCISA)m_external_source->GetMetadata((uintptr_t)interface_decl); + + if (!objc_isa) + return false; + + if (!interface_decl->hasExternalVisibleStorage()) + return true; + + interface_decl->startDefinition(); + + ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptor(objc_isa); + + if (!descriptor) + return false; + + auto superclass_func = [interface_decl, this](ObjCLanguageRuntime::ObjCISA isa) + { + clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa); + if (!superclass_decl) + return; + interface_decl->setSuperClass(superclass_decl); + }; + + auto method_func = [interface_decl, this](const char *name, const char *types) + { + + }; + + if (!descriptor->Describe(superclass_func, method_func)) + return false; + + interface_decl->setHasExternalVisibleStorage(false); + return true; +} + uint32_t AppleObjCTypeVendor::FindTypes (const ConstString &name, bool append, @@ -206,6 +262,9 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name, uint32_t ret = 0; + // TODO Remove this return once testing is complete. + return ret; + do { // See if the type is already in our ASTContext. @@ -252,10 +311,7 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name, } // It's not. If it exists, we have to put it into our ASTContext. - - // TODO Remove this break once testing is complete. - break; - + ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); if (!isa) @@ -267,17 +323,17 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name, break; } - clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx, - ast_ctx->getTranslationUnitDecl(), - clang::SourceLocation(), - &identifier_info, - NULL); + clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); - m_external_source->SetMetadata((uintptr_t)new_iface_decl, (uint64_t)isa); - new_iface_decl->setHasExternalVisibleStorage(); - ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl); + if (!iface_decl) + { + if (log) + log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for isa 0x%llx", + current_id, + (uint64_t)isa); + } - clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(new_iface_decl); + clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl); if (log) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h index e06011662a9..bb1dc30832d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h @@ -21,6 +21,7 @@ #include "lldb/lldb-private.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/TypeVendor.h" +#include "lldb/Target/ObjCLanguageRuntime.h" namespace lldb_private { @@ -39,9 +40,16 @@ public: friend class AppleObjCExternalASTSource; private: - ObjCLanguageRuntime &m_runtime; - ClangASTContext m_ast_ctx; - AppleObjCExternalASTSource *m_external_source; + clang::ObjCInterfaceDecl *GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa); + bool FinishDecl(clang::ObjCInterfaceDecl *decl); + + ObjCLanguageRuntime &m_runtime; + ClangASTContext m_ast_ctx; + AppleObjCExternalASTSource *m_external_source; + + typedef llvm::DenseMap<ObjCLanguageRuntime::ObjCISA, clang::ObjCInterfaceDecl *> ISAToInterfaceMap; + + ISAToInterfaceMap m_isa_to_interface; }; } // namespace lldb_private |

