[Lldb-commits] [lldb] r180199 - Changes to the ObjC runtime
Enrico Granata
egranata at apple.com
Wed Apr 24 10:49:09 PDT 2013
Author: enrico
Date: Wed Apr 24 12:49:08 2013
New Revision: 180199
URL: http://llvm.org/viewvc/llvm-project?rev=180199&view=rev
Log:
Changes to the ObjC runtime
Modified:
lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
lldb/trunk/source/DataFormatters/Cocoa.cpp
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Wed Apr 24 12:49:08 2013
@@ -199,7 +199,8 @@ public:
virtual bool
GetTaggedPointerInfo (uint64_t* info_bits = NULL,
- uint64_t* value_bits = NULL) = 0;
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL) = 0;
virtual uint64_t
GetInstanceSize () = 0;
Modified: lldb/trunk/source/DataFormatters/Cocoa.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/Cocoa.cpp?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/Cocoa.cpp (original)
+++ lldb/trunk/source/DataFormatters/Cocoa.cpp Wed Apr 24 12:49:08 2013
@@ -330,17 +330,20 @@ lldb_private::formatters::NSNumberSummar
case 0:
stream.Printf("(char)%hhd",(char)value);
break;
+ case 1:
case 4:
stream.Printf("(short)%hd",(short)value);
break;
+ case 2:
case 8:
stream.Printf("(int)%d",(int)value);
break;
+ case 3:
case 12:
stream.Printf("(long)%" PRId64,value);
break;
default:
- stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64 ")",i_bits,value);
+ stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
break;
}
return true;
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Wed Apr 24 12:49:08 2013
@@ -49,7 +49,8 @@ public:
// v1 does not support tagged pointers
virtual bool
GetTaggedPointerInfo (uint64_t* info_bits = NULL,
- uint64_t* value_bits = NULL)
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
{
return false;
}
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Wed Apr 24 12:49:08 2013
@@ -27,12 +27,14 @@
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -286,6 +288,52 @@ __lldb_apple_objc_v2_get_shared_cache_cl
)";
+static uint64_t
+ExtractRuntimeGlobalSymbol (Process* process,
+ ConstString name,
+ const ModuleSP &module_sp,
+ Error& error,
+ bool read_value = true,
+ uint8_t byte_size = 0,
+ uint64_t default_value = LLDB_INVALID_ADDRESS,
+ SymbolType sym_type = lldb::eSymbolTypeData)
+{
+ if (!process)
+ {
+ error.SetErrorString("no process");
+ return default_value;
+ }
+ if (!module_sp)
+ {
+ error.SetErrorString("no module");
+ return default_value;
+ }
+ if (!byte_size)
+ byte_size = process->GetAddressByteSize();
+ const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
+ if (symbol)
+ {
+ lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
+ else
+ return symbol_load_addr;
+ }
+ else
+ {
+ error.SetErrorString("symbol address invalid");
+ return default_value;
+ }
+ }
+ else
+ {
+ error.SetErrorString("no symbol");
+ return default_value;
+ }
+
+}
AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
const ModuleSP &objc_module_sp) :
@@ -302,7 +350,9 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2 (
m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
m_hash_signature (),
m_has_object_getClass (false),
- m_loaded_objc_opt (false)
+ m_loaded_objc_opt (false),
+ m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
+ m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
{
static const ConstString g_gdb_object_getClass("gdb_object_getClass");
m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
@@ -313,7 +363,7 @@ AppleObjCRuntimeV2::~AppleObjCRuntimeV2(
}
bool
-AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
+AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
Address &address)
@@ -522,15 +572,16 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar
return ivar_offset;
}
-// tagged pointers are marked by having their least-significant bit
-// set. this makes them "invalid" as pointers because they violate
-// the alignment requirements. of course, this detection algorithm
-// is not accurate (it might become better by incorporating further
-// knowledge about the internals of tagged pointers)
+
+// tagged pointers are special not-a-real-pointer values that contain both type and value information
+// this routine attempts to check with as little computational effort as possible whether something
+// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
bool
AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
{
- return (ptr & 1);
+ if (!m_tagged_pointer_vendor_ap)
+ return false;
+ return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
}
class RemoteNXMapTable
@@ -860,7 +911,8 @@ public:
// a custom descriptor is used for tagged pointers
virtual bool
GetTaggedPointerInfo (uint64_t* info_bits = NULL,
- uint64_t* value_bits = NULL)
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
{
return false;
}
@@ -1414,88 +1466,43 @@ private:
ConstString m_name; // May be NULL
};
+// tagged pointer descriptor
class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
{
public:
- ClassDescriptorV2Tagged (ValueObject &isa_pointer)
+ ClassDescriptorV2Tagged (ConstString class_name,
+ uint64_t payload)
{
- m_valid = false;
- uint64_t value = isa_pointer.GetValueAsUnsigned(0);
- ProcessSP process_sp = isa_pointer.GetProcessSP();
- if (process_sp)
- m_pointer_size = process_sp->GetAddressByteSize();
- else
+ m_name = class_name;
+ if (!m_name)
{
- m_name = ConstString("");
- m_pointer_size = 0;
+ m_valid = false;
return;
}
-
m_valid = true;
- m_class_bits = (value & 0xE) >> 1;
- lldb::TargetSP target_sp = isa_pointer.GetTargetSP();
-
- uint32_t foundation_version = GetFoundationVersion(target_sp);
-
- // TODO: check for OSX version - for now assume Mtn Lion
- if (foundation_version == UINT32_MAX)
+ m_payload = payload;
+ m_info_bits = (m_payload & 0xF0ULL) >> 4;
+ m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+ }
+
+ ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+ uint64_t payload)
+ {
+ if (!actual_class_sp)
{
- // if we can't determine the matching table (e.g. we have no Foundation),
- // assume this is not a valid tagged pointer
m_valid = false;
+ return;
}
- else if (foundation_version >= 900)
- {
- switch (m_class_bits)
- {
- case 0:
- m_name = ConstString("NSAtom");
- break;
- case 3:
- m_name = ConstString("NSNumber");
- break;
- case 4:
- m_name = ConstString("NSDateTS");
- break;
- case 5:
- m_name = ConstString("NSManagedObject");
- break;
- case 6:
- m_name = ConstString("NSDate");
- break;
- default:
- m_valid = false;
- break;
- }
- }
- else
- {
- switch (m_class_bits)
- {
- case 1:
- m_name = ConstString("NSNumber");
- break;
- case 5:
- m_name = ConstString("NSManagedObject");
- break;
- case 6:
- m_name = ConstString("NSDate");
- break;
- case 7:
- m_name = ConstString("NSDateTS");
- break;
- default:
- m_valid = false;
- break;
- }
- }
- if (!m_valid)
- m_name = ConstString("");
- else
+ m_name = actual_class_sp->GetClassName();
+ if (!m_name)
{
- m_info_bits = (value & 0xF0ULL) >> 4;
- m_value_bits = (value & ~0x0000000000000000FFULL) >> 8;
+ m_valid = false;
+ return;
}
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0x0FULL);
+ m_value_bits = (m_payload & ~0x0FULL) >> 4;
}
virtual ConstString
@@ -1533,12 +1540,15 @@ public:
virtual bool
GetTaggedPointerInfo (uint64_t* info_bits = NULL,
- uint64_t* value_bits = NULL)
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
{
if (info_bits)
*info_bits = GetInfoBits();
if (value_bits)
*value_bits = GetValueBits();
+ if (payload)
+ *payload = GetPayload();
return true;
}
@@ -1554,12 +1564,6 @@ public:
return 0; // tagged pointers have no ISA
}
- virtual uint64_t
- GetClassBits ()
- {
- return (IsValid() ? m_class_bits : 0);
- }
-
// these calls are not part of any formal tagged pointers specification
virtual uint64_t
GetValueBits ()
@@ -1573,43 +1577,38 @@ public:
return (IsValid() ? m_info_bits : 0);
}
- virtual
- ~ClassDescriptorV2Tagged ()
- {}
-
-protected:
- // we use the version of Foundation to make assumptions about the ObjC runtime on a target
- uint32_t
- GetFoundationVersion (lldb::TargetSP &target_sp)
+ virtual uint64_t
+ GetPayload ()
{
- if (!target_sp)
- return eLazyBoolCalculate;
- const ModuleList& modules = target_sp->GetImages();
- uint32_t major = UINT32_MAX;
- for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
- {
- lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
- if (!module_sp)
- continue;
- if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
- {
- module_sp->GetVersion(&major,1);
- break;
- }
- }
- return major;
+ return (IsValid() ? m_payload : 0);
}
+ virtual
+ ~ClassDescriptorV2Tagged ()
+ {}
+
private:
ConstString m_name;
uint8_t m_pointer_size;
bool m_valid;
- uint64_t m_class_bits;
uint64_t m_info_bits;
uint64_t m_value_bits;
+ uint64_t m_payload;
+
};
ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
+{
+ ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
+ if (m_non_pointer_isa_cache_ap.get())
+ class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
+ if (!class_descriptor_sp)
+ class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
+ return class_descriptor_sp;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
{
ClassDescriptorSP objc_class_sp;
@@ -1623,13 +1622,7 @@ AppleObjCRuntimeV2::GetClassDescriptor (
// 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();
+ return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
}
else
{
@@ -2353,3 +2346,299 @@ AppleObjCRuntimeV2::LookupRuntimeSymbol
return ret;
}
+
+AppleObjCRuntimeV2::NonPointerISACache*
+AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
+
+ Error error;
+
+ auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_value"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_class_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
+
+ return new NonPointerISACache(runtime,
+ objc_debug_isa_class_mask,
+ objc_debug_isa_magic_mask,
+ objc_debug_isa_magic_value);
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendor*
+AppleObjCRuntimeV2::TaggedPointerVendor::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
+
+ Error error;
+
+ auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_shift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_mask"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_lshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_rshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_classes"),
+ objc_module_sp,
+ error,
+ false);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+
+ // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
+
+ return new TaggedPointerVendorRuntimeAssisted(runtime,
+ objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_slot_shift,
+ objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_classes);
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & 1);
+}
+
+// we use the version of Foundation to make assumptions about the ObjC runtime on a target
+uint32_t
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetFoundationVersion (Target &target)
+{
+ const ModuleList& modules = target.GetImages();
+ uint32_t major = UINT32_MAX;
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
+ if (!module_sp)
+ continue;
+ if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
+ {
+ module_sp->GetVersion(&major,1);
+ break;
+ }
+ }
+ return major;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
+{
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ Process* process(m_runtime.GetProcess());
+
+ if (m_Foundation_version == 0)
+ m_Foundation_version = GetFoundationVersion(process->GetTarget());
+
+ if (m_Foundation_version == UINT32_MAX)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uint64_t class_bits = (ptr & 0xE) >> 1;
+ ConstString name;
+
+ // TODO: make a table
+ if (m_Foundation_version >= 900)
+ {
+ switch (class_bits)
+ {
+ case 0:
+ name = ConstString("NSAtom");
+ break;
+ case 3:
+ name = ConstString("NSNumber");
+ break;
+ case 4:
+ name = ConstString("NSDateTS");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ else
+ {
+ switch (class_bits)
+ {
+ case 1:
+ name = ConstString("NSNumber");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ case 7:
+ name = ConstString("NSDateTS");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes) :
+TaggedPointerVendor(runtime),
+m_cache(),
+m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
+m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
+m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
+m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
+m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
+m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
+{
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & m_objc_debug_taggedpointer_mask) != 0;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
+{
+ ClassDescriptorSP actual_class_descriptor_sp;
+ uint64_t data_payload;
+
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
+
+ CacheIterator iterator = m_cache.find(slot),
+ end = m_cache.end();
+ if (iterator != end)
+ {
+ actual_class_descriptor_sp = iterator->second;
+ }
+ else
+ {
+ Process* process(m_runtime.GetProcess());
+ uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
+ return false;
+ actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_cache[slot] = actual_class_descriptor_sp;
+ }
+
+ data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
+
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+}
+
+AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value) :
+m_runtime(runtime),
+m_cache(),
+m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
+m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
+m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
+{
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
+{
+ ObjCISA real_isa = 0;
+ if (EvaluateNonPointerISA(isa, real_isa) == false)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ auto cache_iter = m_cache.find(real_isa);
+ if (cache_iter != m_cache.end())
+ return cache_iter->second;
+ auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
+ if (descriptor_sp) // cache only positive matches since the table might grow
+ m_cache[real_isa] = descriptor_sp;
+ return descriptor_sp;
+}
+
+bool
+AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
+{
+ if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
+ return false;
+ if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
+ {
+ ret_isa = isa & m_objc_debug_isa_class_mask;
+ return (ret_isa != 0); // this is a pointer so 0 is not a valid value
+ }
+ return false;
+}
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Wed Apr 24 12:49:08 2013
@@ -14,6 +14,7 @@
// C++ Includes
#include <map>
+#include <memory>
// Other libraries and framework includes
// Project includes
@@ -95,6 +96,9 @@ public:
virtual ClassDescriptorSP
GetClassDescriptor (ValueObject& in_value);
+ virtual ClassDescriptorSP
+ GetClassDescriptor (ObjCISA isa);
+
virtual TypeVendor *
GetTypeVendor();
@@ -125,6 +129,118 @@ private:
lldb::addr_t m_buckets_ptr;
};
+ class NonPointerISACache
+ {
+ public:
+ static NonPointerISACache*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (ObjCISA isa);
+ private:
+ NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value);
+
+ bool
+ EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa);
+
+ AppleObjCRuntimeV2& m_runtime;
+ std::map<ObjCISA,ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
+ uint64_t m_objc_debug_isa_class_mask;
+ uint64_t m_objc_debug_isa_magic_mask;
+ uint64_t m_objc_debug_isa_magic_value;
+
+ DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
+ };
+
+ class TaggedPointerVendor
+ {
+ public:
+ static TaggedPointerVendor*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr) = 0;
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr) = 0;
+
+ virtual
+ ~TaggedPointerVendor () { }
+ protected:
+ AppleObjCRuntimeV2& m_runtime;
+
+ TaggedPointerVendor (AppleObjCRuntimeV2& runtime) :
+ m_runtime(runtime)
+ {
+ }
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor);
+ };
+
+ class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendor
+ {
+ public:
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr);
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr);
+ protected:
+ TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes);
+
+ typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+ typedef Cache::iterator CacheIterator;
+ Cache m_cache;
+ uint64_t m_objc_debug_taggedpointer_mask;
+ uint32_t m_objc_debug_taggedpointer_slot_shift;
+ uint32_t m_objc_debug_taggedpointer_slot_mask;
+ uint32_t m_objc_debug_taggedpointer_payload_lshift;
+ uint32_t m_objc_debug_taggedpointer_payload_rshift;
+ lldb::addr_t m_objc_debug_taggedpointer_classes;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
+ };
+
+ class TaggedPointerVendorLegacy : public TaggedPointerVendor
+ {
+ public:
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr);
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr);
+ protected:
+ TaggedPointerVendorLegacy (AppleObjCRuntimeV2& runtime) :
+ TaggedPointerVendor (runtime),
+ m_Foundation_version(0)
+ {
+ }
+
+ static uint32_t
+ GetFoundationVersion (Target& target);
+
+ uint32_t m_Foundation_version;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
+ };
+
AppleObjCRuntimeV2 (Process *process,
const lldb::ModuleSP &objc_module_sp);
@@ -150,22 +266,23 @@ private:
lldb::addr_t
GetSharedCacheReadOnlyAddress();
- std::unique_ptr<ClangFunction> m_get_class_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_class_info_code;
- lldb::addr_t m_get_class_info_args;
- Mutex m_get_class_info_args_mutex;
-
- std::unique_ptr<ClangFunction> m_get_shared_cache_class_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code;
- lldb::addr_t m_get_shared_cache_class_info_args;
- Mutex m_get_shared_cache_class_info_args_mutex;
-
- std::unique_ptr<TypeVendor> m_type_vendor_ap;
- lldb::addr_t m_isa_hash_table_ptr;
- HashTableSignature m_hash_signature;
- bool m_has_object_getClass;
- bool m_loaded_objc_opt;
-
+ std::unique_ptr<ClangFunction> m_get_class_info_function;
+ std::unique_ptr<ClangUtilityFunction> m_get_class_info_code;
+ lldb::addr_t m_get_class_info_args;
+ Mutex m_get_class_info_args_mutex;
+
+ std::unique_ptr<ClangFunction> m_get_shared_cache_class_info_function;
+ std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code;
+ lldb::addr_t m_get_shared_cache_class_info_args;
+ Mutex m_get_shared_cache_class_info_args_mutex;
+
+ std::unique_ptr<TypeVendor> m_type_vendor_ap;
+ lldb::addr_t m_isa_hash_table_ptr;
+ HashTableSignature m_hash_signature;
+ bool m_has_object_getClass;
+ bool m_loaded_objc_opt;
+ std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
+ std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
};
} // namespace lldb_private
More information about the lldb-commits
mailing list