summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/FormatNavigator.h6
-rw-r--r--lldb/include/lldb/Target/ObjCLanguageRuntime.h33
-rw-r--r--lldb/source/Core/ValueObject.cpp9
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp40
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h18
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp182
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h13
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp303
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h15
-rw-r--r--lldb/source/Target/ObjCLanguageRuntime.cpp99
10 files changed, 379 insertions, 339 deletions
diff --git a/lldb/include/lldb/Core/FormatNavigator.h b/lldb/include/lldb/Core/FormatNavigator.h
index 4c0af74ff5c..cdabd6344c2 100644
--- a/lldb/include/lldb/Core/FormatNavigator.h
+++ b/lldb/include/lldb/Core/FormatNavigator.h
@@ -504,14 +504,14 @@ protected:
log->Printf("no valid ObjC runtime, skipping dynamic");
return false;
}
- ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(valobj);
- if (runtime->IsValidISA(isa) == false)
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
+ if (!objc_class_sp)
{
if (log)
log->Printf("invalid ISA, skipping dynamic");
return false;
}
- ConstString name = runtime->GetActualTypeName(isa);
+ ConstString name (objc_class_sp->GetClassName());
if (log)
log->Printf("dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
if (Get(name, entry))
diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index 97cefdc8df7..7be517b0853 100644
--- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -174,12 +174,18 @@ public:
virtual ClassDescriptorSP
GetClassDescriptor (ValueObject& in_value);
+ ClassDescriptorSP
+ GetNonKVOClassDescriptor (ValueObject& in_value);
+
+ virtual ClassDescriptorSP
+ GetClassDescriptor (const ConstString &class_name);
+
virtual ClassDescriptorSP
GetClassDescriptor (ObjCISA isa);
ClassDescriptorSP
GetNonKVOClassDescriptor (ObjCISA isa);
-
+
virtual
~ObjCLanguageRuntime();
@@ -200,10 +206,7 @@ public:
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
-
- virtual ClassDescriptorSP
- CreateClassDescriptor (ObjCISA isa) = 0;
-
+
lldb::addr_t
LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
@@ -231,17 +234,15 @@ public:
return eObjC_VersionUnknown;
}
- virtual bool
- IsValidISA(ObjCISA isa) = 0;
-
- virtual ObjCISA
- GetISA(ValueObject& valobj) = 0;
-
- virtual void
- UpdateISAToDescriptorMap_Impl()
+ bool
+ IsValidISA(ObjCISA isa)
{
- // to be implemented by runtimes if they support doing this
+ UpdateISAToDescriptorMap();
+ return m_isa_to_descriptor_cache.count(isa) > 0;
}
+
+ virtual bool
+ UpdateISAToDescriptorMap_Impl() = 0;
void
UpdateISAToDescriptorMap()
@@ -249,9 +250,7 @@ public:
if (m_isa_to_descriptor_cache_is_up_to_date)
return;
- m_isa_to_descriptor_cache_is_up_to_date = true;
-
- UpdateISAToDescriptorMap_Impl();
+ m_isa_to_descriptor_cache_is_up_to_date = UpdateISAToDescriptorMap_Impl();
}
virtual ObjCISA
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index fe34724e311..9debcc0318a 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -3223,12 +3223,11 @@ DumpValueObject_Impl (Stream &s,
s.Printf(", dynamic type: unknown) ");
else
{
- ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(*valobj);
- if (!runtime->IsValidISA(isa))
- s.Printf(", dynamic type: unknown) ");
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetNonKVOClassDescriptor(*valobj));
+ if (objc_class_sp)
+ s.Printf(", dynamic type: %s) ", objc_class_sp->GetClassName().GetCString());
else
- s.Printf(", dynamic type: %s) ",
- runtime->GetActualTypeName(isa).GetCString());
+ s.Printf(", dynamic type: unknown) ");
}
}
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 4d001d857dc..995a438ca89 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -168,6 +168,30 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon
return cstr_len > 0;
}
+lldb::ModuleSP
+AppleObjCRuntime::GetObjCModule ()
+{
+ ModuleSP module_sp (m_objc_module_wp.lock());
+ if (module_sp)
+ return module_sp;
+
+ Process *process = GetProcess();
+ if (process)
+ {
+ ModuleList& modules = process->GetTarget().GetImages();
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ module_sp = modules.GetModuleAtIndex(idx);
+ if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp))
+ {
+ m_objc_module_wp = module_sp;
+ return module_sp;
+ }
+ }
+ }
+ return ModuleSP();
+}
+
Address *
AppleObjCRuntime::GetPrintForDebuggerAddr()
{
@@ -211,15 +235,17 @@ AppleObjCRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
bool
AppleObjCRuntime::AppleIsModuleObjCLibrary (const ModuleSP &module_sp)
{
- const FileSpec &module_file_spec = module_sp->GetFileSpec();
- static ConstString ObjCName ("libobjc.A.dylib");
-
- if (module_file_spec)
+ if (module_sp)
{
- if (module_file_spec.GetFilename() == ObjCName)
- return true;
+ const FileSpec &module_file_spec = module_sp->GetFileSpec();
+ static ConstString ObjCName ("libobjc.A.dylib");
+
+ if (module_file_spec)
+ {
+ if (module_file_spec.GetFilename() == ObjCName)
+ return true;
+ }
}
-
return false;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
index e835a0c94af..e5d2c0f5e06 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -63,17 +63,10 @@ public:
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (Thread &thread, bool stop_others);
- virtual bool
- IsValidISA(ObjCISA isa)
- {
- return false;
- }
-
- virtual ObjCISA
- GetISA(ValueObject& valobj)
- {
- return 0;
- }
+ // Get the "libobjc.A.dylib" module from the current target if we can find
+ // it, also cache it once it is found to ensure quick lookups.
+ lldb::ModuleSP
+ GetObjCModule ();
//------------------------------------------------------------------
// Static Functions
@@ -111,8 +104,9 @@ protected:
bool m_read_objc_library;
std::auto_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
lldb::BreakpointSP m_objc_exception_bp_sp;
+ lldb::ModuleWP m_objc_module_wp;
- AppleObjCRuntime(Process *process) :
+ AppleObjCRuntime(Process *process) :
lldb_private::ObjCLanguageRuntime(process),
m_read_objc_library (false),
m_objc_trampoline_handler_ap(NULL)
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 3996476a87a..2624d5c289c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -24,6 +24,7 @@
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -155,35 +156,35 @@ AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
// this code relies on the assumption that an Objective-C object always starts
// with an ISA at offset 0.
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV1::GetISA(ValueObject& valobj)
-{
-// if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
+//ObjCLanguageRuntime::ObjCISA
+//AppleObjCRuntimeV1::GetISA(ValueObject& valobj)
+//{
+//// if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
+//// return 0;
+//
+// // if we get an invalid VO (which might still happen when playing around
+// // with pointers returned by the expression parser, don't consider this
+// // a valid ObjC object)
+// if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
// return 0;
-
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
- if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
- return 0;
-
- addr_t isa_pointer = valobj.GetPointerValue();
-
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- uint8_t pointer_size = process->GetAddressByteSize();
-
- Error error;
- return process->ReadUnsignedIntegerFromMemory (isa_pointer,
- pointer_size,
- 0,
- error);
- }
- return 0;
-}
+//
+// addr_t isa_pointer = valobj.GetPointerValue();
+//
+// ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+//
+// Process *process = exe_ctx.GetProcessPtr();
+// if (process)
+// {
+// uint8_t pointer_size = process->GetAddressByteSize();
+//
+// Error error;
+// return process->ReadUnsignedIntegerFromMemory (isa_pointer,
+// pointer_size,
+// 0,
+// error);
+// }
+// return 0;
+//}
AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
{
@@ -287,11 +288,124 @@ AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
}
-ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::CreateClassDescriptor (ObjCISA isa)
+bool
+AppleObjCRuntimeV1::UpdateISAToDescriptorMap_Impl()
{
- ClassDescriptorSP objc_class_sp;
- if (isa != 0)
- objc_class_sp.reset (new ClassDescriptorV1(isa,m_process->CalculateProcess()));
- return objc_class_sp;
+ lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Process *process_ptr = GetProcess();
+
+ if (!process_ptr)
+ return false;
+
+ ProcessSP process_sp = process_ptr->shared_from_this();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return false;
+
+ uint32_t isa_count = 0;
+
+ 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)
+ {
+ lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddress().GetLoadAddress(&process_sp->GetTarget());
+
+ if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
+ {
+ Error error;
+ lldb::addr_t objc_debug_class_hash_ptr = process_sp->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+ if (error.Success() && objc_debug_class_hash_ptr != 0 && objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
+ {
+ // Read the NXHashTable struct:
+ //
+ // typedef struct {
+ // const NXHashTablePrototype *prototype;
+ // unsigned count;
+ // unsigned nbBuckets;
+ // void *buckets;
+ // const void *info;
+ // } NXHashTable;
+
+ DataBufferHeap buffer(1024, 0);
+ if (process_sp->ReadMemory(objc_debug_class_hash_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);
+ uint32_t offset = addr_size + 4; // Skip prototype
+ const uint32_t num_buckets = data.GetU32(&offset);
+ const addr_t buckets_ptr = data.GetPointer(&offset);
+
+ const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+ buffer.SetByteSize(data_size);
+
+ if (process_sp->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 (m_isa_to_descriptor_cache.count(isa) == 0)
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%llx from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ m_isa_to_descriptor_cache[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 (m_isa_to_descriptor_cache.count(isa) == 0)
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%llx from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ m_isa_to_descriptor_cache[isa] = descriptor_sp;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return isa_count > 0;
}
+
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 579fdbcb9f1..d85350c1d11 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -124,17 +124,8 @@ public:
}
virtual bool
- IsValidISA(ObjCISA isa)
- {
- return (isa != 0) && ( (isa % 2) == 0);
- }
-
- virtual ObjCISA
- GetISA(ValueObject& valobj);
-
- virtual ClassDescriptorSP
- CreateClassDescriptor (ObjCISA isa);
-
+ UpdateISAToDescriptorMap_Impl();
+
protected:
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index f37102e52b6..786728147ba 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -585,7 +585,7 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const c
bool
AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
{
- return (ptr & 0x01);
+ return (ptr & 1);
}
class RemoteNXMapTable
@@ -597,7 +597,7 @@ public:
m_end_iterator(*this, -1),
m_load_addr(load_addr),
m_map_pair_size(m_process_sp->GetAddressByteSize() * 2),
- m_NXMAPNOTAKEY(m_process_sp->GetAddressByteSize() == 8 ? 0xffffffffffffffffull : 0xffffffffull)
+ m_NXMAPNOTAKEY(m_process_sp->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX)
{
lldb::addr_t cursor = load_addr;
@@ -1668,49 +1668,45 @@ private:
};
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::CreateClassDescriptor (ObjCISA isa)
-{
- UpdateISAToDescriptorMap();
-
- ISAToDescriptorMap::const_iterator di = m_isa_to_descriptor_cache.find(isa);
-
- if (di == m_isa_to_descriptor_cache.end())
- return ObjCLanguageRuntime::ClassDescriptorSP();
- else
- return di->second;
-}
-
-ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& in_value)
+AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
{
ClassDescriptorSP objc_class_sp;
- uint64_t ptr_value = in_value.GetValueAsUnsigned(0);
- if (ptr_value)
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
{
- if (ptr_value & 1)
- objc_class_sp = ClassDescriptorSP(new ClassDescriptorV2Tagged(in_value));
+ addr_t isa_pointer = valobj.GetPointerValue();
+
+ // tagged pointer
+ if (IsTaggedPointer(isa_pointer))
+ {
+ objc_class_sp.reset (new ClassDescriptorV2Tagged(valobj));
+
+ // probably an invalid tagged pointer - say it's wrong
+ if (objc_class_sp->IsValid())
+ return objc_class_sp;
+ else
+ objc_class_sp.reset();
+ }
else
- objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (in_value);
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+ if (isa != LLDB_INVALID_ADDRESS)
+ objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (isa);
+ }
+ }
}
return objc_class_sp;
}
-ModuleSP FindLibobjc (Target &target)
-{
- ModuleList& modules = target.GetImages();
- for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
- {
- lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
- if (!module_sp)
- continue;
- if (strncmp(module_sp->GetFileSpec().GetFilename().AsCString(""), "libobjc.", sizeof("libobjc.") - 1) == 0)
- return module_sp;
- }
-
- return ModuleSP();
-}
-
-void
+bool
AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
{
lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1718,193 +1714,105 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
Process *process_ptr = GetProcess();
if (!process_ptr)
- return;
-
- ProcessSP process_sp = process_ptr->shared_from_this();
+ return false;
- Target &target(process_sp->GetTarget());
+ ProcessSP process_sp (process_ptr->shared_from_this());
- ModuleSP objc_module_sp(FindLibobjc(target));
+ ModuleSP objc_module_sp(GetObjCModule());
if (!objc_module_sp)
- return;
-
- do
- {
- SymbolContextList sc_list;
-
- size_t num_symbols = objc_module_sp->FindSymbolsWithNameAndType(ConstString("gdb_objc_realized_classes"),
- lldb::eSymbolTypeData,
- sc_list);
-
- if (!num_symbols)
- break;
-
- SymbolContext gdb_objc_realized_classes_sc;
-
- if (!sc_list.GetContextAtIndex(0, gdb_objc_realized_classes_sc))
- break;
-
- AddressRange gdb_objc_realized_classes_addr_range;
-
- const uint32_t scope = eSymbolContextSymbol;
- const uint32_t range_idx = 0;
- bool use_inline_block_range = false;
+ return false;
- if (!gdb_objc_realized_classes_sc.GetAddressRange(scope,
- range_idx,
- use_inline_block_range,
- gdb_objc_realized_classes_addr_range))
- break;
-
- lldb::addr_t gdb_objc_realized_classes_ptr = gdb_objc_realized_classes_addr_range.GetBaseAddress().GetLoadAddress(&target);
-
- if (gdb_objc_realized_classes_ptr == LLDB_INVALID_ADDRESS)
- break;
-
- // <rdar://problem/10763513>
-
- lldb::addr_t gdb_objc_realized_classes_nxmaptable_ptr;
+ uint32_t num_map_table_isas = 0;
+ uint32_t num_objc_opt_ro_isas = 0;
+
+ static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeData);
+ if (symbol)
+ {
+ lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process_sp->GetTarget());
+ if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
{
+ // <rdar://problem/10763513>
+
+ lldb::addr_t gdb_objc_realized_classes_nxmaptable_ptr;
+
Error err;
gdb_objc_realized_classes_nxmaptable_ptr = process_sp->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, err);
- if (!err.Success())
- break;
- }
-
- RemoteNXMapTable gdb_objc_realized_classes(process_sp, gdb_objc_realized_classes_nxmaptable_ptr);
-
- for (RemoteNXMapTable::element elt : gdb_objc_realized_classes)
- {
- if (m_isa_to_descriptor_cache.count(elt.second))
- continue;
-
- ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+ if (err.Success())
+ {
+ RemoteNXMapTable gdb_objc_realized_classes(process_sp, gdb_objc_realized_classes_nxmaptable_ptr);
- m_isa_to_descriptor_cache[elt.second] = descriptor_sp;
+ for (RemoteNXMapTable::element elt : gdb_objc_realized_classes)
+ {
+ ++num_map_table_isas;
+
+ if (m_isa_to_descriptor_cache.count(elt.second))
+ continue;
+
+ ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+
+ m_isa_to_descriptor_cache[elt.second] = descriptor_sp;
+ }
+ }
}
}
- while(0);
- do
+ ObjectFile *objc_object = objc_module_sp->GetObjectFile();
+
+ if (objc_object)
{
- ObjectFile *objc_object = objc_module_sp->GetObjectFile();
-
- if (!objc_object)
- break;
-
SectionList *section_list = objc_object->GetSectionList();
-
- if (!section_list)
- break;
-
- SectionSP TEXT_section_sp = section_list->FindSectionByName(ConstString("__TEXT"));
-
- if (!TEXT_section_sp)
- break;
-
- SectionList &TEXT_children = TEXT_section_sp->GetChildren();
-
- SectionSP objc_opt_section_sp = TEXT_children.FindSectionByName(ConstString("__objc_opt_ro"));
-
- if (!objc_opt_section_sp)
- break;
-
- lldb::addr_t objc_opt_ptr = objc_opt_section_sp->GetLoadBaseAddress(&target);
-
- if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
- break;
-
- RemoteObjCOpt objc_opt(process_sp, objc_opt_ptr);
-
- for (ObjCLanguageRuntime::ObjCISA objc_isa : objc_opt)
+
+ if (section_list)
{
- if (m_isa_to_descriptor_cache.count(objc_isa))
- continue;
-
- ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, objc_isa));
+ SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from static table to isa->descriptor cache", objc_isa, descriptor_sp->GetClassName().AsCString());
-
- m_isa_to_descriptor_cache[objc_isa] = descriptor_sp;
+ if (text_segment_sp)
+ {
+ SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
+
+ if (objc_opt_section_sp)
+ {
+ lldb::addr_t objc_opt_ptr = objc_opt_section_sp->GetLoadBaseAddress(&process_sp->GetTarget());
+
+ if (objc_opt_ptr != LLDB_INVALID_ADDRESS)
+ {
+ RemoteObjCOpt objc_opt(process_sp, objc_opt_ptr);
+
+ for (ObjCLanguageRuntime::ObjCISA objc_isa : objc_opt)
+ {
+ ++num_objc_opt_ro_isas;
+ if (m_isa_to_descriptor_cache.count(objc_isa))
+ continue;
+
+ ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, objc_isa));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from static table to isa->descriptor cache", objc_isa, descriptor_sp->GetClassName().AsCString());
+
+ m_isa_to_descriptor_cache[objc_isa] = descriptor_sp;
+ }
+ }
+ }
+ }
}
}
- while (0);
-}
-
-// this code relies on the assumption that an Objective-C object always starts
-// with an ISA at offset 0. an ISA is effectively a pointer to an instance of
-// struct class_t in the ObjCv2 runtime
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
-{
-// if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
-// return 0;
-//
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
- if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
- return 0;
- addr_t isa_pointer = valobj.GetPointerValue();
-
- // tagged pointer
- if (IsTaggedPointer(isa_pointer))
- {
- ClassDescriptorV2Tagged descriptor(valobj);
-
- // probably an invalid tagged pointer - say it's wrong
- if (!descriptor.IsValid())
- return 0;
-
- static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
- static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
- static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
- static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
- static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
-
- ConstString class_name_const_string = descriptor.GetClassName();
-
- if (class_name_const_string == g_objc_tagged_isa_nsatom_name)
- return g_objc_Tagged_ISA_NSAtom;
- if (class_name_const_string == g_objc_tagged_isa_nsnumber_name)
- return g_objc_Tagged_ISA_NSNumber;
- if (class_name_const_string == g_objc_tagged_isa_nsdatets_name)
- return g_objc_Tagged_ISA_NSDateTS;
- if (class_name_const_string == g_objc_tagged_isa_nsmanagedobject_name)
- return g_objc_Tagged_ISA_NSManagedObject;
- if (class_name_const_string == g_objc_tagged_isa_nsdate_name)
- return g_objc_Tagged_ISA_NSDate;
- return g_objc_Tagged_ISA;
- }
-
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- Error error;
- ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
- if (isa != LLDB_INVALID_ADDRESS)
- return isa;
- }
- return 0; // For some reason zero is being used to indicate invalid ISA instead of LLDB_INVALID_ADDRESS
+ return num_objc_opt_ro_isas > 0 && num_map_table_isas > 0;
}
+
// TODO: should we have a transparent_kvo parameter here to say if we
// want to replace the KVO swizzled class with the actual user-level type?
ConstString
AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
{
- if (!IsValidISA(isa))
- return ConstString();
-
if (isa == g_objc_Tagged_ISA)
{
static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
@@ -1935,7 +1843,6 @@ AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
return g_objc_tagged_isa_nsdate_name;
}
-
return ObjCLanguageRuntime::GetActualTypeName(isa);
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 361ebcfa3ee..480b5969dab 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -73,14 +73,8 @@ public:
virtual size_t
GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
- virtual void
- UpdateISAToDescriptorMap_Impl();
-
virtual bool
- IsValidISA (ObjCLanguageRuntime::ObjCISA isa)
- {
- return (isa != 0);
- }
+ UpdateISAToDescriptorMap_Impl();
// none of these are valid ISAs - we use them to infer the type
// of tagged pointers - if we have something meaningful to say
@@ -94,19 +88,12 @@ public:
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 5;
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
-
- virtual ObjCLanguageRuntime::ObjCISA
- GetISA(ValueObject& valobj);
-
virtual ConstString
GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa);
virtual ClassDescriptorSP
GetClassDescriptor (ValueObject& in_value);
- virtual ClassDescriptorSP
- CreateClassDescriptor (ObjCISA isa);
-
virtual TypeVendor *
GetTypeVendor();
diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp
index 98bb0c44dad..4fb41c843e5 100644
--- a/lldb/source/Target/ObjCLanguageRuntime.cpp
+++ b/lldb/source/Target/ObjCLanguageRuntime.cpp
@@ -31,6 +31,7 @@ ObjCLanguageRuntime::~ObjCLanguageRuntime()
ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
LanguageRuntime (process),
m_has_new_literals_and_indexing (eLazyBoolCalculate),
+ m_isa_to_descriptor_cache(),
m_isa_to_descriptor_cache_is_up_to_date (false)
{
@@ -284,24 +285,10 @@ ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
ObjCLanguageRuntime::ObjCISA
ObjCLanguageRuntime::GetISA(const ConstString &name)
{
- // Try once regardless of whether the map has been brought up to date. We
- // might have encountered the relevant isa directly.
- for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
- if (val.second && val.second->GetClassName() == name)
- return val.first;
-
- // If the map is up to date and we didn't find the isa, give up.
- if (m_isa_to_descriptor_cache_is_up_to_date)
- return 0;
-
- // Try again after bringing the map up to date.
UpdateISAToDescriptorMap();
-
for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
if (val.second && val.second->GetClassName() == name)
return val.first;
-
- // Now we know for sure that the class isn't there. Give up.
return 0;
}
@@ -318,8 +305,6 @@ ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
return 0;
}
-// TODO: should we have a transparent_kvo parameter here to say if we
-// want to replace the KVO swizzled class with the actual user-level type?
ConstString
ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
{
@@ -330,34 +315,74 @@ ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
}
ObjCLanguageRuntime::ClassDescriptorSP
-ObjCLanguageRuntime::GetClassDescriptor (ValueObject& in_value)
+ObjCLanguageRuntime::GetClassDescriptor (const ConstString &class_name)
{
- ObjCISA isa = GetISA(in_value);
- if (isa)
- return GetClassDescriptor (isa);
+ UpdateISAToDescriptorMap();
+ for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
+ if (val.second && val.second->GetClassName() == class_name)
+ return val.second;
return ClassDescriptorSP();
+
}
ObjCLanguageRuntime::ClassDescriptorSP
-ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
+ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
{
ClassDescriptorSP objc_class_sp;
- if (isa)
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
{
- ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
- ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
-
- if (found != end && found->second)
- return found->second;
-
- objc_class_sp = CreateClassDescriptor(isa);
- if (objc_class_sp && objc_class_sp->IsValid())
- m_isa_to_descriptor_cache[isa] = objc_class_sp;
+ addr_t isa_pointer = valobj.GetPointerValue();
+ if (isa_pointer != LLDB_INVALID_ADDRESS)
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+ if (isa != LLDB_INVALID_ADDRESS)
+ objc_class_sp = GetClassDescriptor (isa);
+ }
+ }
}
return objc_class_sp;
}
ObjCLanguageRuntime::ClassDescriptorSP
+ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
+{
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
+ if (objc_class_sp)
+ {
+ if (!objc_class_sp->IsKVO())
+ return objc_class_sp;
+
+ ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
+ if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
+ return non_kvo_objc_class_sp;
+ }
+ return ClassDescriptorSP();
+}
+
+
+ObjCLanguageRuntime::ClassDescriptorSP
+ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
+{
+ if (isa)
+ {
+ UpdateISAToDescriptorMap();
+ ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor_cache.find(isa);
+ if (pos != m_isa_to_descriptor_cache.end())
+ return pos->second;
+ }
+ return ClassDescriptorSP();
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
{
if (isa)
@@ -365,14 +390,12 @@ ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
ClassDescriptorSP objc_class_sp = GetClassDescriptor (isa);
if (objc_class_sp && objc_class_sp->IsValid())
{
- if (objc_class_sp->IsKVO())
- {
- ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
- if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
- return non_kvo_objc_class_sp;
- }
- else
+ if (!objc_class_sp->IsKVO())
return objc_class_sp;
+
+ ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
+ if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
+ return non_kvo_objc_class_sp;
}
}
return ClassDescriptorSP();
OpenPOWER on IntegriCloud