diff options
Diffstat (limited to 'lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp')
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp | 64 |
1 files changed, 45 insertions, 19 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 859b693477a9..bdd5c29db848 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -1,5 +1,4 @@ -//===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++ -//-*-===// +//===-- AppleObjCClassDescriptorV2.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,7 +16,7 @@ using namespace lldb_private; bool ClassDescriptorV2::Read_objc_class( Process *process, std::unique_ptr<objc_class_t> &objc_class) const { - objc_class.reset(new objc_class_t); + objc_class = std::make_unique<objc_class_t>(); bool ret = objc_class->Read(process, m_objc_class_ptr); @@ -198,14 +197,14 @@ bool ClassDescriptorV2::Read_class_row( return false; if (class_row_t_flags & RW_REALIZED) { - class_rw.reset(new class_rw_t); + class_rw = std::make_unique<class_rw_t>(); if (!class_rw->Read(process, objc_class.m_data_ptr)) { class_rw.reset(); return false; } - class_ro.reset(new class_ro_t); + class_ro = std::make_unique<class_ro_t>(); if (!class_ro->Read(process, class_rw->m_ro_ptr)) { class_rw.reset(); @@ -213,7 +212,7 @@ bool ClassDescriptorV2::Read_class_row( return false; } } else { - class_ro.reset(new class_ro_t); + class_ro = std::make_unique<class_ro_t>(); if (!class_ro->Read(process, objc_class.m_data_ptr)) { class_ro.reset(); @@ -242,15 +241,20 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process, lldb::offset_t cursor = 0; - m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3; + uint32_t entsize = extractor.GetU32_unchecked(&cursor); + m_is_small = (entsize & 0x80000000) != 0; + m_has_direct_selector = (entsize & 0x40000000) != 0; + m_entsize = entsize & 0xfffc; m_count = extractor.GetU32_unchecked(&cursor); m_first_ptr = addr + cursor; return true; } -bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) { - size_t size = GetSize(process); +bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, + bool is_small, bool has_direct_sel) { + size_t ptr_size = process->GetAddressByteSize(); + size_t size = GetSize(process, is_small); DataBufferHeap buffer(size, '\0'); Status error; @@ -261,13 +265,30 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) { } DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), - process->GetAddressByteSize()); - + ptr_size); lldb::offset_t cursor = 0; - m_name_ptr = extractor.GetAddress_unchecked(&cursor); - m_types_ptr = extractor.GetAddress_unchecked(&cursor); - m_imp_ptr = extractor.GetAddress_unchecked(&cursor); + if (is_small) { + uint32_t nameref_offset = extractor.GetU32_unchecked(&cursor); + uint32_t types_offset = extractor.GetU32_unchecked(&cursor); + uint32_t imp_offset = extractor.GetU32_unchecked(&cursor); + + m_name_ptr = addr + nameref_offset; + + if (!has_direct_sel) { + // The SEL offset points to a SELRef. We need to dereference twice. + m_name_ptr = process->ReadUnsignedIntegerFromMemory(m_name_ptr, ptr_size, + 0, error); + if (!error.Success()) + return false; + } + m_types_ptr = addr + 4 + types_offset; + m_imp_ptr = addr + 8 + imp_offset; + } else { + m_name_ptr = extractor.GetAddress_unchecked(&cursor); + m_types_ptr = extractor.GetAddress_unchecked(&cursor); + m_imp_ptr = extractor.GetAddress_unchecked(&cursor); + } process->ReadCStringFromMemory(m_name_ptr, m_name, error); if (error.Fail()) { @@ -358,19 +379,24 @@ bool ClassDescriptorV2::Describe( if (instance_method_func) { std::unique_ptr<method_list_t> base_method_list; - base_method_list.reset(new method_list_t); + base_method_list = std::make_unique<method_list_t>(); if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr)) return false; - if (base_method_list->m_entsize != method_t::GetSize(process)) + bool is_small = base_method_list->m_is_small; + bool has_direct_selector = base_method_list->m_has_direct_selector; + + if (base_method_list->m_entsize != method_t::GetSize(process, is_small)) return false; std::unique_ptr<method_t> method; - method.reset(new method_t); + method = std::make_unique<method_t>(); for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) { - method->Read(process, base_method_list->m_first_ptr + - (i * base_method_list->m_entsize)); + method->Read(process, + base_method_list->m_first_ptr + + (i * base_method_list->m_entsize), + is_small, has_direct_selector); if (instance_method_func(method->m_name.c_str(), method->m_types.c_str())) break; |