Changes to the ObjC runtime

llvm-svn: 180199
This commit is contained in:
Enrico Granata 2013-04-24 17:49:08 +00:00
parent eb3f1007d8
commit b636be79c0
5 changed files with 545 additions and 134 deletions

View File

@ -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;

View File

@ -330,17 +330,20 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
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;

View File

@ -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;
}

View File

@ -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_class_info (void *objc_opt_ro_ptr,
)";
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 (Process *process,
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 (ClangASTType &parent_ast_type, const c
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)
m_name = actual_class_sp->GetClassName();
if (!m_name)
{
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_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,42 +1577,37 @@ public:
return (IsValid() ? m_info_bits : 0);
}
virtual uint64_t
GetPayload ()
{
return (IsValid() ? m_payload : 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)
{
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;
}
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)
{
@ -1623,13 +1622,7 @@ AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
// 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 (const ConstString &name)
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;
}

View File

@ -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_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<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<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