aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp')
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp711
1 files changed, 345 insertions, 366 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 805fca7a31b9..13bd245a33b4 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -1,4 +1,5 @@
-//===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++ -*-===//
+//===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,8 +9,8 @@
//===----------------------------------------------------------------------===//
#include "AppleObjCRuntimeV1.h"
-#include "AppleObjCTrampolineHandler.h"
#include "AppleObjCDeclVendor.h"
+#include "AppleObjCTrampolineHandler.h"
#include "clang/AST/Type.h"
@@ -36,425 +37,403 @@
using namespace lldb;
using namespace lldb_private;
-AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process) :
- AppleObjCRuntime (process),
- m_hash_signature (),
- m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS)
-{
-}
+AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process)
+ : AppleObjCRuntime(process), m_hash_signature(),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {}
-// for V1 runtime we just try to return a class name as that is the minimum level of support
+// for V1 runtime we just try to return a class name as that is the minimum
+// level of support
// required for the data formatters to work
-bool
-AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type)
-{
- class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
- if (CouldHaveDynamicValue(in_value))
- {
- auto class_descriptor(GetClassDescriptor(in_value));
- if (class_descriptor && class_descriptor->IsValid() && class_descriptor->GetClassName())
- {
- const addr_t object_ptr = in_value.GetPointerValue();
- address.SetRawAddress(object_ptr);
- class_type_or_name.SetName(class_descriptor->GetClassName());
- }
+bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+ if (CouldHaveDynamicValue(in_value)) {
+ auto class_descriptor(GetClassDescriptor(in_value));
+ if (class_descriptor && class_descriptor->IsValid() &&
+ class_descriptor->GetClassName()) {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+ class_type_or_name.SetName(class_descriptor->GetClassName());
}
- return class_type_or_name.IsEmpty() == false;
+ }
+ return class_type_or_name.IsEmpty() == false;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
lldb_private::LanguageRuntime *
-AppleObjCRuntimeV1::CreateInstance (Process *process, lldb::LanguageType language)
-{
- // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
- // sure we aren't using the V1 runtime.
- if (language == eLanguageTypeObjC)
- {
- ModuleSP objc_module_sp;
-
- if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V1)
- return new AppleObjCRuntimeV1 (process);
- else
- return NULL;
- }
+AppleObjCRuntimeV1::CreateInstance(Process *process,
+ lldb::LanguageType language) {
+ // FIXME: This should be a MacOS or iOS process, and we need to look for the
+ // OBJC section to make
+ // sure we aren't using the V1 runtime.
+ if (language == eLanguageTypeObjC) {
+ ModuleSP objc_module_sp;
+
+ if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
+ ObjCRuntimeVersions::eAppleObjC_V1)
+ return new AppleObjCRuntimeV1(process);
else
- return NULL;
+ return NULL;
+ } else
+ return NULL;
}
-
-void
-AppleObjCRuntimeV1::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Apple Objective C Language Runtime - Version 1",
- CreateInstance);
+void AppleObjCRuntimeV1::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 1",
+ CreateInstance);
}
-void
-AppleObjCRuntimeV1::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void AppleObjCRuntimeV1::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-AppleObjCRuntimeV1::GetPluginNameStatic()
-{
- static ConstString g_name("apple-objc-v1");
- return g_name;
+lldb_private::ConstString AppleObjCRuntimeV1::GetPluginNameStatic() {
+ static ConstString g_name("apple-objc-v1");
+ return g_name;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-ConstString
-AppleObjCRuntimeV1::GetPluginName()
-{
- return GetPluginNameStatic();
+ConstString AppleObjCRuntimeV1::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-AppleObjCRuntimeV1::GetPluginVersion()
-{
- return 1;
-}
+uint32_t AppleObjCRuntimeV1::GetPluginVersion() { return 1; }
BreakpointResolverSP
-AppleObjCRuntimeV1::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
-{
- BreakpointResolverSP resolver_sp;
-
- if (throw_bp)
- resolver_sp.reset (new BreakpointResolverName (bkpt,
- "objc_exception_throw",
- eFunctionNameTypeBase,
- eLanguageTypeUnknown,
- Breakpoint::Exact,
- 0,
- eLazyBoolNo));
- // FIXME: don't do catch yet.
- return resolver_sp;
+AppleObjCRuntimeV1::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
+ bool throw_bp) {
+ BreakpointResolverSP resolver_sp;
+
+ if (throw_bp)
+ resolver_sp.reset(new BreakpointResolverName(
+ bkpt, "objc_exception_throw", eFunctionNameTypeBase,
+ eLanguageTypeUnknown, Breakpoint::Exact, 0, eLazyBoolNo));
+ // FIXME: don't do catch yet.
+ return resolver_sp;
}
struct BufStruct {
- char contents[2048];
+ char contents[2048];
};
-UtilityFunction *
-AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
-{
- std::unique_ptr<BufStruct> buf(new BufStruct);
-
- assert(snprintf(&buf->contents[0], sizeof(buf->contents),
- "struct __objc_class \n"
- "{ \n"
- " struct __objc_class *isa; \n"
- " struct __objc_class *super_class; \n"
- " const char *name; \n"
- " // rest of struct elided because unused \n"
- "}; \n"
- " \n"
- "struct __objc_object \n"
- "{ \n"
- " struct __objc_class *isa; \n"
- "}; \n"
- " \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " struct __objc_object *obj = (struct __objc_object*)$__lldb_arg_obj; \n"
- " (int)strlen(obj->isa->name); \n"
- "} \n",
- name) < (int)sizeof(buf->contents));
-
- Error error;
- return GetTargetRef().GetUtilityFunctionForLanguage(buf->contents, eLanguageTypeObjC, name, error);
+UtilityFunction *AppleObjCRuntimeV1::CreateObjectChecker(const char *name) {
+ std::unique_ptr<BufStruct> buf(new BufStruct);
+
+ assert(snprintf(&buf->contents[0], sizeof(buf->contents),
+ "struct __objc_class "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_class *isa; "
+ " \n"
+ " struct __objc_class *super_class; "
+ " \n"
+ " const char *name; "
+ " \n"
+ " // rest of struct elided because unused "
+ " \n"
+ "}; "
+ " \n"
+ " "
+ " \n"
+ "struct __objc_object "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_class *isa; "
+ " \n"
+ "}; "
+ " \n"
+ " "
+ " \n"
+ "extern \"C\" void "
+ " \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_object *obj = (struct "
+ "__objc_object*)$__lldb_arg_obj; \n"
+ " if ($__lldb_arg_obj == (void *)0) "
+ " \n"
+ " return; // nil is ok "
+ " (int)strlen(obj->isa->name); "
+ " \n"
+ "} "
+ " \n",
+ name) < (int)sizeof(buf->contents));
+
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(
+ buf->contents, eLanguageTypeObjC, name, error);
}
-AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
-{
- Initialize (isa_pointer.GetValueAsUnsigned(0),
- isa_pointer.GetProcessSP());
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
+ ValueObject &isa_pointer) {
+ Initialize(isa_pointer.GetValueAsUnsigned(0), isa_pointer.GetProcessSP());
}
-AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp)
-{
- Initialize (isa, process_sp);
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
+ ObjCISA isa, lldb::ProcessSP process_sp) {
+ Initialize(isa, process_sp);
}
-void
-AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
-{
- if (!isa || !process_sp)
- {
- m_valid = false;
- return;
- }
-
- m_valid = true;
-
- Error error;
-
- m_isa = process_sp->ReadPointerFromMemory(isa, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- uint32_t ptr_size = process_sp->GetAddressByteSize();
-
- if (!IsPointerValid(m_isa,ptr_size))
- {
- m_valid = false;
- return;
- }
+void AppleObjCRuntimeV1::ClassDescriptorV1::Initialize(
+ ObjCISA isa, lldb::ProcessSP process_sp) {
+ if (!isa || !process_sp) {
+ m_valid = false;
+ return;
+ }
- m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- if (!IsPointerValid(m_parent_isa,ptr_size,true))
- {
- m_valid = false;
- return;
- }
-
- lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
-
- size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- if (count)
- m_name = ConstString((char*)buffer_sp->GetBytes());
- else
- m_name = ConstString();
-
- m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- m_process_wp = lldb::ProcessWP(process_sp);
+ m_valid = true;
+
+ Error error;
+
+ m_isa = process_sp->ReadPointerFromMemory(isa, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ if (!IsPointerValid(m_isa, ptr_size)) {
+ m_valid = false;
+ return;
+ }
+
+ m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ if (!IsPointerValid(m_parent_isa, ptr_size, true)) {
+ m_valid = false;
+ return;
+ }
+
+ lldb::addr_t name_ptr =
+ process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+
+ size_t count = process_sp->ReadCStringFromMemory(
+ name_ptr, (char *)buffer_sp->GetBytes(), 1024, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ if (count)
+ m_name = ConstString((char *)buffer_sp->GetBytes());
+ else
+ m_name = ConstString();
+
+ m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(
+ m_isa + 5 * ptr_size, ptr_size, 0, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ m_process_wp = lldb::ProcessWP(process_sp);
}
AppleObjCRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
-{
- if (!m_valid)
- return AppleObjCRuntime::ClassDescriptorSP();
- ProcessSP process_sp = m_process_wp.lock();
- if (!process_sp)
- return AppleObjCRuntime::ClassDescriptorSP();
- return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
+AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass() {
+ if (!m_valid)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ ProcessSP process_sp = m_process_wp.lock();
+ if (!process_sp)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ return ObjCLanguageRuntime::ClassDescriptorSP(
+ new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa, process_sp));
}
AppleObjCRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass () const
-{
- return ClassDescriptorSP();
+AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass() const {
+ return ClassDescriptorSP();
}
-bool
-AppleObjCRuntimeV1::ClassDescriptorV1::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
- std::function <bool (const char *, const char *)> const &instance_method_func,
- std::function <bool (const char *, const char *)> const &class_method_func,
- std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
-{
- return false;
+bool AppleObjCRuntimeV1::ClassDescriptorV1::Describe(
+ std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function<bool(const char *, const char *)> const &instance_method_func,
+ std::function<bool(const char *, const char *)> const &class_method_func,
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)> const &ivar_func) const {
+ return false;
}
-lldb::addr_t
-AppleObjCRuntimeV1::GetISAHashTablePointer ()
-{
- if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
- {
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (!objc_module_sp)
- return LLDB_INVALID_ADDRESS;
-
- static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
-
- const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData);
- if (symbol && symbol->ValueIsAddress())
- {
- Process *process = GetProcess();
- if (process)
- {
-
- lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
-
- if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
- {
- Error error;
- lldb::addr_t objc_debug_class_hash_ptr = process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
- if (objc_debug_class_hash_ptr != 0 &&
- objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
- {
- m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
- }
- }
- }
+lldb::addr_t AppleObjCRuntimeV1::GetISAHashTablePointer() {
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_objc_debug_class_hash, lldb::eSymbolTypeData);
+ if (symbol && symbol->ValueIsAddress()) {
+ Process *process = GetProcess();
+ if (process) {
+
+ lldb::addr_t objc_debug_class_hash_addr =
+ symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+
+ if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS) {
+ Error error;
+ lldb::addr_t objc_debug_class_hash_ptr =
+ process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+ if (objc_debug_class_hash_ptr != 0 &&
+ objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS) {
+ m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
+ }
}
+ }
}
- return m_isa_hash_table_ptr;
+ }
+ return m_isa_hash_table_ptr;
}
-void
-AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
-{
- // TODO: implement HashTableSignature...
- Process *process = GetProcess();
-
- if (process)
- {
- // Update the process stop ID that indicates the last time we updated the
- // map, whether it was successful or not.
- m_isa_to_descriptor_stop_id = process->GetStopID();
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- ProcessSP process_sp = process->shared_from_this();
-
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (!objc_module_sp)
- return;
-
- uint32_t isa_count = 0;
-
- lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
- if (hash_table_ptr != LLDB_INVALID_ADDRESS)
- {
- // Read the NXHashTable struct:
- //
- // typedef struct {
- // const NXHashTablePrototype *prototype;
- // unsigned count;
- // unsigned nbBuckets;
- // void *buckets;
- // const void *info;
- // } NXHashTable;
-
- Error error;
- DataBufferHeap buffer(1024, 0);
- if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
- {
- const uint32_t addr_size = m_process->GetAddressByteSize();
- const ByteOrder byte_order = m_process->GetByteOrder();
- DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
- lldb::offset_t offset = addr_size; // Skip prototype
- const uint32_t count = data.GetU32(&offset);
- const uint32_t num_buckets = data.GetU32(&offset);
- const addr_t buckets_ptr = data.GetPointer(&offset);
- if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
- {
- m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);
-
- const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
- buffer.SetByteSize(data_size);
-
- if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
- {
- data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
- offset = 0;
- for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
- {
- const uint32_t bucket_isa_count = data.GetU32 (&offset);
- const lldb::addr_t bucket_data = data.GetU32 (&offset);
-
-
- if (bucket_isa_count == 0)
- continue;
-
- isa_count += bucket_isa_count;
-
- ObjCISA isa;
- if (bucket_isa_count == 1)
- {
- // When we only have one entry in the bucket, the bucket data is the "isa"
- isa = bucket_data;
- if (isa)
- {
- if (!ISAIsCached(isa))
- {
- ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
-
- AddClass (isa, descriptor_sp);
- }
- }
- }
- else
- {
- // When we have more than one entry in the bucket, the bucket data is a pointer
- // to an array of "isa" values
- addr_t isa_addr = bucket_data;
- for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
- {
- isa = m_process->ReadPointerFromMemory(isa_addr, error);
-
- if (isa && isa != LLDB_INVALID_ADDRESS)
- {
- if (!ISAIsCached(isa))
- {
- ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
-
- AddClass (isa, descriptor_sp);
- }
- }
- }
- }
- }
+void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
+ // TODO: implement HashTableSignature...
+ Process *process = GetProcess();
+
+ if (process) {
+ // Update the process stop ID that indicates the last time we updated the
+ // map, whether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ProcessSP process_sp = process->shared_from_this();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return;
+
+ uint32_t isa_count = 0;
+
+ lldb::addr_t hash_table_ptr = GetISAHashTablePointer();
+ if (hash_table_ptr != LLDB_INVALID_ADDRESS) {
+ // Read the NXHashTable struct:
+ //
+ // typedef struct {
+ // const NXHashTablePrototype *prototype;
+ // unsigned count;
+ // unsigned nbBuckets;
+ // void *buckets;
+ // const void *info;
+ // } NXHashTable;
+
+ Error error;
+ DataBufferHeap buffer(1024, 0);
+ if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) ==
+ 20) {
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), byte_order,
+ addr_size);
+ lldb::offset_t offset = addr_size; // Skip prototype
+ const uint32_t count = data.GetU32(&offset);
+ const uint32_t num_buckets = data.GetU32(&offset);
+ const addr_t buckets_ptr = data.GetPointer(&offset);
+ if (m_hash_signature.NeedsUpdate(count, num_buckets, buckets_ptr)) {
+ m_hash_signature.UpdateSignature(count, num_buckets, buckets_ptr);
+
+ const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+ buffer.SetByteSize(data_size);
+
+ if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size,
+ error) == data_size) {
+ data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
+ offset = 0;
+ for (uint32_t bucket_idx = 0; bucket_idx < num_buckets;
+ ++bucket_idx) {
+ const uint32_t bucket_isa_count = data.GetU32(&offset);
+ const lldb::addr_t bucket_data = data.GetU32(&offset);
+
+ if (bucket_isa_count == 0)
+ continue;
+
+ isa_count += bucket_isa_count;
+
+ ObjCISA isa;
+ if (bucket_isa_count == 1) {
+ // When we only have one entry in the bucket, the bucket data is
+ // the "isa"
+ isa = bucket_data;
+ if (isa) {
+ if (!ISAIsCached(isa)) {
+ ClassDescriptorSP descriptor_sp(
+ new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
+ " from _objc_debug_class_hash to "
+ "isa->descriptor cache",
+ isa);
+
+ AddClass(isa, descriptor_sp);
+ }
+ }
+ } else {
+ // When we have more than one entry in the bucket, the bucket
+ // data is a pointer
+ // to an array of "isa" values
+ addr_t isa_addr = bucket_data;
+ for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count;
+ ++isa_idx, isa_addr += addr_size) {
+ isa = m_process->ReadPointerFromMemory(isa_addr, error);
+
+ if (isa && isa != LLDB_INVALID_ADDRESS) {
+ if (!ISAIsCached(isa)) {
+ ClassDescriptorSP descriptor_sp(
+ new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf(
+ "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
+ " from _objc_debug_class_hash to isa->descriptor "
+ "cache",
+ isa);
+
+ AddClass(isa, descriptor_sp);
}
+ }
}
+ }
}
- }
- }
- else
- {
- m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
+ }
+ }
}
+ } else {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
}
-DeclVendor *
-AppleObjCRuntimeV1::GetDeclVendor()
-{
- if (!m_decl_vendor_ap.get())
- m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
-
- return m_decl_vendor_ap.get();
+DeclVendor *AppleObjCRuntimeV1::GetDeclVendor() {
+ return nullptr;
}