diff options
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 227 | ||||
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp | 6 |
2 files changed, 164 insertions, 69 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 326a34cdc8e..78ccc1425ad 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -991,6 +991,9 @@ public: virtual ConstString GetClassName () { + if (!m_valid) + return ConstString(); + return m_name; } @@ -999,10 +1002,11 @@ public: { if (!m_valid) return ObjCLanguageRuntime::ClassDescriptorSP(); + ProcessSP process_sp = m_process_wp.lock(); if (!process_sp) return ObjCLanguageRuntime::ClassDescriptorSP(); - return AppleObjCRuntime::ClassDescriptorSP(new ClassDescriptorV2(m_parent_isa,process_sp)); + return AppleObjCRuntime::ClassDescriptorSP(new ClassDescriptorV2(m_objc_class.m_superclass,process_sp)); } virtual bool @@ -1020,30 +1024,43 @@ public: virtual uint64_t GetInstanceSize () { + if (!m_valid) + return 0; + return m_instance_size; } virtual ObjCLanguageRuntime::ObjCISA GetISA () { - return m_isa; + if (!m_valid) + return 0; + + return m_objc_class_la; } virtual bool CompleteInterface (clang::ObjCInterfaceDecl *interface_decl) { + if (!m_valid) + return false; + return false; } virtual bool IsRealized () { + if (!m_valid) + return false; + return m_realized; } virtual ~ClassDescriptorV2 () - {} + { + } protected: virtual bool @@ -1056,107 +1073,136 @@ protected: } void - Initialize (ObjCLanguageRuntime::ObjCISA isa, lldb::ProcessSP process_sp) + Initialize (ObjCLanguageRuntime::ObjCISA pointer_to_isa, lldb::ProcessSP process_sp) { - if (!isa || !process_sp) + m_valid = true; + + if (!pointer_to_isa || !process_sp) { m_valid = false; return; } - m_valid = true; - + size_t ptr_size = process_sp->GetAddressByteSize(); Error error; - m_isa = process_sp->ReadPointerFromMemory(isa, error); - + m_objc_class_la = process_sp->ReadPointerFromMemory(pointer_to_isa, error); + if (error.Fail()) { m_valid = false; return; } - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - if (!IsPointerValid(m_isa,ptr_size,false,false,true)) - { - m_valid = false; - return; - } - - lldb::addr_t data_ptr = process_sp->ReadPointerFromMemory(m_isa + 4 * ptr_size, error); - - if (error.Fail()) + const bool allow_NULLs = false; + const bool allow_tagged = false; + const bool check_version_specific = true; + + if (!IsPointerValid(m_objc_class_la, ptr_size, allow_NULLs, allow_tagged, check_version_specific)) { 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 (!IsPointerValid(data_ptr,ptr_size,false,false,true)) { - m_valid = false; - return; + 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_parent_isa = process_sp->ReadPointerFromMemory(isa + ptr_size,error); - - if (error.Fail()) + + // Now we just want to grab the instance size and the name. + // Since we find out whether the class is realized on the way, we'll remember that too. + + // The flags for class_r[ow]_t always are the first uint32_t. So just read that. + if (!IsPointerValid(m_objc_class.m_data_la, ptr_size, allow_NULLs, allow_tagged, check_version_specific)) { m_valid = false; return; } - // sanity checks - lldb::addr_t cache_ptr = process_sp->ReadPointerFromMemory(m_isa + 2*ptr_size, error); + uint32_t class_row_t_flags = process_sp->ReadUnsignedIntegerFromMemory(m_objc_class.m_data_la, sizeof(uint32_t), 0, error); if (error.Fail()) { m_valid = false; return; } - if (!IsPointerValid(cache_ptr,ptr_size,true,false,true)) - { - m_valid = false; - return; - } - lldb::addr_t rot_pointer; + m_realized = class_row_t_flags & RW_REALIZED; - // now construct the data object + lldb::addr_t class_ro_t_la = NULL; - uint32_t flags; - process_sp->ReadMemory(data_ptr, &flags, 4, error); - if (error.Fail()) + if (m_realized) { - m_valid = false; - return; - } - - if (flags & RW_REALIZED) - { - m_realized = true; - rot_pointer = process_sp->ReadPointerFromMemory(data_ptr + 8, error); + lldb::addr_t class_rw_t_la = m_objc_class.m_data_la; + + class_ro_t_la = process_sp->ReadPointerFromMemory(class_rw_t_la + + sizeof(uint32_t) // uint32_t flags + + sizeof(uint32_t), // uint32_t version + error); + + if (error.Fail()) + { + m_valid = false; + return; + } } else { - m_realized = false; - rot_pointer = data_ptr; + class_ro_t_la = m_objc_class.m_data_la; } - if (error.Fail()) + if (!IsPointerValid(class_ro_t_la, ptr_size)) { m_valid = false; return; } - if (!IsPointerValid(rot_pointer,ptr_size)) + // Now that we have a handle on class_ro_t_la, read the desired data out + + m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(class_ro_t_la + + sizeof(uint32_t) // uint32_t flags + + sizeof(uint32_t), // uint32_t instanceStart + sizeof(uint32_t), + 0, + error); + + if (error.Fail()) { m_valid = false; return; } - // now read from the rot - - lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(rot_pointer + (ptr_size == 8 ? 24 : 16) ,error); + lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(class_ro_t_la + + 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 + error); if (error.Fail()) { @@ -1164,9 +1210,10 @@ protected: return; } - lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); + const size_t buffer_size = 1024; - size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error); + DataBufferHeap buffer(buffer_size, 0); + size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer.GetBytes(), buffer_size, error); if (error.Fail()) { @@ -1175,24 +1222,72 @@ protected: } if (count) - m_name = ConstString((char*)buffer_sp->GetBytes()); + m_name = ConstString((char*)buffer.GetBytes()); else m_name = ConstString(); - - m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(rot_pointer + 8, ptr_size, 0, error); - + m_process_wp = lldb::ProcessWP(process_sp); } private: static const uint32_t RW_REALIZED = (1 << 31); - ConstString m_name; - ObjCLanguageRuntime::ObjCISA m_isa; - ObjCLanguageRuntime::ObjCISA m_parent_isa; - bool m_valid; + + bool m_valid; // Gates whether we trust anything here at all. + lldb::addr_t m_objc_class_la; // The address of the objc_class_t. + + struct objc_class_t { + ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass. + ObjCLanguageRuntime::ObjCISA m_superclass; + lldb::addr_t m_cache_la; + lldb::addr_t m_vtable_la; + lldb::addr_t m_data_la; + uint8_t m_flags; + }; + + objc_class_t m_objc_class; + + // cached information from the class_r[ow]_t + ConstString m_name; + uint32_t m_instance_size; + bool m_realized; + + struct class_ro_t { + uint32_t m_flags; + uint32_t m_instanceStart; + uint32_t m_instanceSize; + uint32_t m_reserved; + + lldb::addr_t m_ivarLayout_la; + lldb::addr_t m_name_la; + lldb::addr_t m_baseMethods_la; + lldb::addr_t m_baseProtocols_la; + lldb::addr_t m_ivars_la; + + lldb::addr_t m_weakIvarLayout_la; + lldb::addr_t m_baseProperties_la; + }; + + std::auto_ptr<class_ro_t> m_class_ro; + + struct class_rw_t { + uint32_t m_flags; + uint32_t m_version; + + lldb::addr_t m_ro_la; + union { + lldb::addr_t m_method_list_la; + lldb::addr_t m_method_lists_la; + }; + lldb::addr_t m_properties_la; + lldb::addr_t m_protocols_la; + + ObjCLanguageRuntime::ObjCISA m_firstSubclass; + ObjCLanguageRuntime::ObjCISA m_nextSiblingClass; + }; + + std::auto_ptr<class_rw_t> m_class_rw; + lldb::ProcessWP m_process_wp; - uint64_t m_instance_size; - bool m_realized; }; class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp index ced2026d4d3..ac293946bf3 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp @@ -71,10 +71,10 @@ public: break; if (descriptor->CompleteInterface(non_const_interface_decl)) - non_const_interface_decl->setHasExternalLexicalStorage(false); + non_const_interface_decl->setHasExternalVisibleStorage(false); } - if (non_const_interface_decl->hasExternalLexicalStorage()) // hasExternalLexicalStorage() is cleared during completion + if (non_const_interface_decl->hasExternalVisibleStorage()) break; return non_const_interface_decl->lookup(name); @@ -253,7 +253,7 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name, // 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. + // TODO Remove this break once testing is complete. break; ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); |

