Changes to clean up the runtime and how the ISA caches are managed.

llvm-svn: 165516
This commit is contained in:
Greg Clayton 2012-10-09 17:51:53 +00:00
parent 7c0990ba35
commit 77fbc8176d
6 changed files with 402 additions and 386 deletions

View File

@ -108,7 +108,7 @@ public:
// use to implement version-specific additional constraints on pointers
virtual bool
CheckPointer (lldb::addr_t value,
uint32_t ptr_size)
uint32_t ptr_size) const
{
return true;
}
@ -135,7 +135,7 @@ public:
uint32_t ptr_size,
bool allow_NULLs = false,
bool allow_tagged = false,
bool check_version_specific = false);
bool check_version_specific = false) const;
private:
LazyBool m_is_kvo;
@ -167,8 +167,10 @@ public:
GetISA () { return 0; }
virtual bool
CheckPointer (lldb::addr_t value,
uint32_t ptr_size) { return false; }
CheckPointer (lldb::addr_t value, uint32_t ptr_size) const
{
return false;
}
virtual
~ClassDescriptor_Invalid ()
@ -177,17 +179,14 @@ public:
};
virtual ClassDescriptorSP
GetClassDescriptor (ValueObject& in_value)
{
return ClassDescriptorSP();
}
GetClassDescriptor (ValueObject& in_value);
virtual ClassDescriptorSP
GetClassDescriptor (ObjCISA isa)
{
return ClassDescriptorSP();
}
GetClassDescriptor (ObjCISA isa);
ClassDescriptorSP
GetNonKVOClassDescriptor (ObjCISA isa);
virtual
~ObjCLanguageRuntime();
@ -209,6 +208,9 @@ 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);

View File

@ -158,8 +158,8 @@ AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
ObjCLanguageRuntime::ObjCISA
AppleObjCRuntimeV1::GetISA(ValueObject& valobj)
{
if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
return 0;
// 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
@ -288,33 +288,10 @@ AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
}
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV1::GetClassDescriptor (ValueObject& in_value)
AppleObjCRuntimeV1::CreateClassDescriptor (ObjCISA isa)
{
ObjCISA isa = GetISA(in_value);
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;
ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(in_value));
if (descriptor && descriptor->IsValid())
m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
return descriptor;
}
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV1::GetClassDescriptor (ObjCISA isa)
{
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;
ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(isa,m_process->CalculateProcess()));
if (descriptor && descriptor->IsValid())
m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
return descriptor;
ClassDescriptorSP objc_class_sp;
if (isa != 0)
objc_class_sp.reset (new ClassDescriptorV1(isa,m_process->CalculateProcess()));
return objc_class_sp;
}

View File

@ -133,11 +133,8 @@ public:
GetISA(ValueObject& valobj);
virtual ClassDescriptorSP
GetClassDescriptor (ValueObject& in_value);
CreateClassDescriptor (ObjCISA isa);
virtual ClassDescriptorSP
GetClassDescriptor (ObjCISA isa);
protected:
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);

View File

@ -603,7 +603,7 @@ public:
Error err;
// const struct +NXMapTablePrototype *prototype;
m_prototype_la = m_process_sp->ReadPointerFromMemory(cursor, err);
m_prototype_ptr = m_process_sp->ReadPointerFromMemory(cursor, err);
cursor += m_process_sp->GetAddressByteSize();
// unsigned count;
@ -615,7 +615,7 @@ public:
cursor += sizeof(unsigned);
// void *buckets;
m_buckets_la = m_process_sp->ReadPointerFromMemory(cursor, err);
m_buckets_ptr = m_process_sp->ReadPointerFromMemory(cursor, err);
}
// const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
@ -672,16 +672,16 @@ public:
return element();
}
lldb::addr_t pairs_la = m_parent.m_buckets_la;
lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
size_t map_pair_size = m_parent.m_map_pair_size;
lldb::addr_t pair_la = pairs_la + (m_index * map_pair_size);
lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
Error err;
lldb::addr_t key = m_parent.m_process_sp->ReadPointerFromMemory(pair_la, err);
lldb::addr_t key = m_parent.m_process_sp->ReadPointerFromMemory(pair_ptr, err);
if (!err.Success())
return element();
lldb::addr_t value = m_parent.m_process_sp->ReadPointerFromMemory(pair_la + m_parent.m_process_sp->GetAddressByteSize(), err);
lldb::addr_t value = m_parent.m_process_sp->ReadPointerFromMemory(pair_ptr + m_parent.m_process_sp->GetAddressByteSize(), err);
if (!err.Success())
return element();
@ -699,15 +699,15 @@ public:
if (m_index == -1)
return;
lldb::addr_t pairs_la = m_parent.m_buckets_la;
lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
size_t map_pair_size = m_parent.m_map_pair_size;
lldb::addr_t NXMAPNOTAKEY = m_parent.m_NXMAPNOTAKEY;
Error err;
while (m_index--)
{
lldb::addr_t pair_la = pairs_la + (m_index * map_pair_size);
lldb::addr_t key = m_parent.m_process_sp->ReadPointerFromMemory(pair_la, err);
lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
lldb::addr_t key = m_parent.m_process_sp->ReadPointerFromMemory(pair_ptr, err);
if (!err.Success())
{
@ -735,10 +735,10 @@ public:
private:
// contents of _NXMapTable struct
lldb::addr_t m_prototype_la;
lldb::addr_t m_prototype_ptr;
uint32_t m_count;
uint32_t m_nbBucketsMinusOne;
lldb::addr_t m_buckets_la;
lldb::addr_t m_buckets_ptr;
lldb::ProcessSP m_process_sp;
const_iterator m_end_iterator;
@ -781,9 +781,9 @@ public:
if (m_version != 12)
return;
m_clsopt_la = load_addr + m_clsopt_offset;
m_clsopt_ptr = load_addr + m_clsopt_offset;
cursor = m_clsopt_la;
cursor = m_clsopt_ptr;
// uint32_t capacity;
m_capacity = m_process_sp->ReadUnsignedIntegerFromMemory(cursor, sizeof(uint32_t), 0, err);
@ -800,7 +800,7 @@ public:
cursor += sizeof(uint32_t);
// uint32_t zero;
m_zero_offset = cursor - m_clsopt_la;
m_zero_offset = cursor - m_clsopt_ptr;
cursor += sizeof(uint32_t);
// uint32_t unused;
@ -822,7 +822,7 @@ public:
cursor += sizeof(int32_t) * m_capacity;
// objc_classheader_t clsOffsets[capacity];
m_clsOffsets_la = cursor;
m_clsOffsets_ptr = cursor;
cursor += (m_classheader_size * m_capacity);
// uint32_t duplicateCount;
@ -830,7 +830,7 @@ public:
cursor += sizeof(uint32_t);
// objc_classheader_t duplicateOffsets[duplicateCount];
m_duplicateOffsets_la = cursor;
m_duplicateOffsets_ptr = cursor;
}
friend class const_iterator;
@ -888,23 +888,23 @@ public:
if (m_index >= m_parent.m_capacity + m_parent.m_duplicateCount)
return 0; // index out of range
lldb::addr_t classheader_la;
lldb::addr_t classheader_ptr;
if (m_index >= m_parent.m_capacity)
{
// index in the duplicate offsets
uint32_t index = (uint32_t)((uint64_t)m_index - (uint64_t)m_parent.m_capacity);
classheader_la = m_parent.m_duplicateOffsets_la + (index * m_parent.m_classheader_size);
classheader_ptr = m_parent.m_duplicateOffsets_ptr + (index * m_parent.m_classheader_size);
}
else
{
// index in the offsets
uint32_t index = (uint32_t)m_index;
classheader_la = m_parent.m_clsOffsets_la + (index * m_parent.m_classheader_size);
classheader_ptr = m_parent.m_clsOffsets_ptr + (index * m_parent.m_classheader_size);
}
Scalar clsOffset;
m_parent.m_process_sp->ReadScalarIntegerFromMemory(classheader_la, sizeof(int32_t), /*is_signed*/ true, clsOffset, err);
m_parent.m_process_sp->ReadScalarIntegerFromMemory(classheader_ptr, sizeof(int32_t), /*is_signed*/ true, clsOffset, err);
if (!err.Success())
return 0;
@ -915,7 +915,7 @@ public:
if (clsOffset_int == m_parent.m_zero_offset)
return 0; // == offsetof(objc_clsopt_t, zero)
return m_parent.m_clsopt_la + (int64_t)clsOffset_int;
return m_parent.m_clsopt_ptr + (int64_t)clsOffset_int;
}
void AdvanceToValidIndex ()
@ -954,14 +954,14 @@ private:
uint32_t m_version;
int32_t m_clsopt_offset;
lldb::addr_t m_clsopt_la;
lldb::addr_t m_clsopt_ptr;
// contents of objc_clsopt struct
uint32_t m_capacity;
uint32_t m_mask;
uint32_t m_duplicateCount;
lldb::addr_t m_clsOffsets_la;
lldb::addr_t m_duplicateOffsets_la;
lldb::addr_t m_clsOffsets_ptr;
lldb::addr_t m_duplicateOffsets_ptr;
int32_t m_zero_offset;
lldb::ProcessSP m_process_sp;
@ -974,23 +974,35 @@ class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
{
public:
ClassDescriptorV2 (ObjCLanguageRuntime &runtime, ValueObject &ptr_to_object) :
m_runtime(runtime)
m_runtime (runtime),
m_valid (false),
m_objc_class_ptr (0),
m_objc_class (),
m_name (),
m_instance_size (0),
m_realized (eLazyBoolCalculate),
m_process_wp ()
{
lldb::addr_t object_la = ptr_to_object.GetValueAsUnsigned(0);
lldb::addr_t object_ptr = ptr_to_object.GetValueAsUnsigned(0);
lldb::ProcessSP process_sp = ptr_to_object.GetProcessSP();
Error error;
ObjCLanguageRuntime::ObjCISA isa = process_sp->ReadPointerFromMemory(object_la,
ObjCLanguageRuntime::ObjCISA isa = process_sp->ReadPointerFromMemory(object_ptr,
error);
if (isa == LLDB_INVALID_ADDRESS)
m_valid = false;
else
if (isa != LLDB_INVALID_ADDRESS)
Initialize (isa, process_sp);
}
ClassDescriptorV2 (ObjCLanguageRuntime &runtime, ObjCLanguageRuntime::ObjCISA isa, lldb::ProcessSP process_sp) :
m_runtime(runtime)
m_runtime (runtime),
m_valid (false),
m_objc_class_ptr (0),
m_objc_class (),
m_name (),
m_instance_size (0),
m_realized (eLazyBoolCalculate),
m_process_wp ()
{
Initialize (isa, process_sp);
}
@ -998,9 +1010,49 @@ public:
virtual ConstString
GetClassName ()
{
if (!m_valid)
return ConstString();
if (m_valid && !m_name)
{
const lldb::addr_t class_ro_t_ptr = get_class_ro_t_ptr ();
ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
{
const size_t ptr_size = process_sp->GetAddressByteSize();
Error error;
lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory (class_ro_t_ptr
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t) // uint32_t instanceStart
+ sizeof(uint32_t) // uint32_t instanceSize
+ (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved (__LP64__ only)
+ ptr_size, // const uint8_t *ivarLayout
error);
if (error.Success())
{
char class_name_cstr[1024];
size_t count = process_sp->ReadCStringFromMemory(name_ptr, class_name_cstr, sizeof(class_name_cstr), error);
if (error.Fail())
{
m_valid = false;
}
else
{
if (count)
m_name.SetCString(class_name_cstr);
else
m_valid = false;
}
}
else
m_valid = false;
}
else
m_valid = false;
}
return m_name;
}
@ -1031,6 +1083,27 @@ public:
if (!m_valid)
return 0;
if (m_instance_size == 0)
{
const lldb::addr_t class_ro_t_ptr = get_class_ro_t_ptr ();
ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
{
Error error;
m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(class_ro_t_ptr
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t), // uint32_t instanceStart
sizeof(uint32_t),
0,
error);
if (error.Fail())
m_valid = false;
}
else
m_valid = false;
}
return m_instance_size;
}
@ -1040,7 +1113,7 @@ public:
if (!m_valid)
return 0;
return m_objc_class_la;
return m_objc_class_ptr;
}
virtual bool
@ -1062,17 +1135,17 @@ public:
if (IsRealized())
{
rw.reset(new class_rw_t);
if (!rw->Read(process_sp, m_objc_class.m_data_la))
if (!rw->Read(process_sp, m_objc_class.m_data_ptr))
return false;
ro.reset(new class_ro_t);
if (!ro->Read(process_sp, rw->m_ro_la))
if (!ro->Read(process_sp, rw->m_ro_ptr))
return false;
}
else
{
ro.reset(new class_ro_t);
if (!ro->Read(process_sp, m_objc_class.m_data_la))
if (!ro->Read(process_sp, m_objc_class.m_data_ptr))
return false;
}
@ -1086,7 +1159,7 @@ public:
std::auto_ptr <method_list_t> base_method_list;
base_method_list.reset(new method_list_t);
if (!base_method_list->Read(process_sp, ro->m_baseMethods_la))
if (!base_method_list->Read(process_sp, ro->m_baseMethods_ptr))
return false;
if (base_method_list->m_entsize != method_t::GetSize(process_sp))
@ -1097,7 +1170,7 @@ public:
for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
{
method->Read(process_sp, base_method_list->m_first_la + (i * base_method_list->m_entsize));
method->Read(process_sp, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
instance_method_func(method->m_name.c_str(), method->m_types.c_str());
}
@ -1125,7 +1198,14 @@ public:
if (!m_valid)
return false;
return m_realized;
if (m_realized == eLazyBoolCalculate)
{
if (class_row_t_flags() & RW_REALIZED)
m_realized = eLazyBoolYes;
else
m_realized = eLazyBoolNo;
}
return m_realized == eLazyBoolYes;
}
virtual
@ -1135,26 +1215,78 @@ public:
protected:
virtual bool
CheckPointer (lldb::addr_t value,
uint32_t ptr_size)
CheckPointer (lldb::addr_t value, uint32_t ptr_size) const
{
if (ptr_size != 8)
return true;
return ((value & 0xFFFF800000000000) == 0);
}
void
Initialize (ObjCLanguageRuntime::ObjCISA objc_class_la, lldb::ProcessSP process_sp)
uint32_t
class_row_t_flags ()
{
m_valid = true;
if (m_valid && m_objc_class.m_data_ptr)
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
Error error;
uint32_t class_row_t_flags = process_sp->ReadUnsignedIntegerFromMemory(m_objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
if (error.Success())
return class_row_t_flags;
else
m_valid = false;
}
}
return 0;
}
lldb::addr_t
get_class_ro_t_ptr ()
{
if (m_valid && m_objc_class.m_data_ptr)
{
if (IsRealized())
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
lldb::addr_t class_rw_t_ptr = m_objc_class.m_data_ptr;
Error error;
const lldb::addr_t class_ro_t_ptr = process_sp->ReadPointerFromMemory (class_rw_t_ptr
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t), // uint32_t version
error);
if (error.Success() && IsPointerValid(class_ro_t_ptr, process_sp->GetAddressByteSize()))
return class_ro_t_ptr;
else
m_valid = false;
}
else
m_valid = false;
}
else
{
return m_objc_class.m_data_ptr;
}
}
return 0;
}
if (!objc_class_la || !process_sp)
void
Initialize (ObjCLanguageRuntime::ObjCISA objc_class_ptr, lldb::ProcessSP process_sp)
{
if (!objc_class_ptr || !process_sp)
{
m_valid = false;
return;
}
m_valid = true;
m_objc_class_la = objc_class_la;
m_objc_class_ptr = objc_class_ptr;
size_t ptr_size = process_sp->GetAddressByteSize();
Error error;
@ -1163,13 +1295,13 @@ protected:
const bool allow_tagged = false;
const bool check_version_specific = true;
if (!IsPointerValid(m_objc_class_la, ptr_size, allow_NULLs, allow_tagged, check_version_specific))
if (!IsPointerValid(m_objc_class_ptr, ptr_size, allow_NULLs, allow_tagged, check_version_specific))
{
m_valid = false;
return;
}
if (!m_objc_class.Read(process_sp, m_objc_class_la))
if (!m_objc_class.Read(process_sp, m_objc_class_ptr))
{
m_valid = false;
return;
@ -1179,121 +1311,56 @@ protected:
// Since we find out whether the class is realized on the way, we'll remember that too.
// The flags for class_r[ow]_t always are the first uint32_t. So just read that.
if (!IsPointerValid(m_objc_class.m_data_la, ptr_size, allow_NULLs, allow_tagged, check_version_specific))
if (!IsPointerValid(m_objc_class.m_data_ptr, ptr_size, allow_NULLs, allow_tagged, check_version_specific))
{
m_valid = false;
return;
}
uint32_t class_row_t_flags = process_sp->ReadUnsignedIntegerFromMemory(m_objc_class.m_data_la, sizeof(uint32_t), 0, error);
if (error.Fail())
{
m_valid = false;
return;
}
m_realized = class_row_t_flags & RW_REALIZED;
lldb::addr_t class_ro_t_la = 0;
if (m_realized)
{
lldb::addr_t class_rw_t_la = m_objc_class.m_data_la;
class_ro_t_la = process_sp->ReadPointerFromMemory(class_rw_t_la
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t), // uint32_t version
error);
if (error.Fail())
{
m_valid = false;
return;
}
}
else
{
class_ro_t_la = m_objc_class.m_data_la;
}
if (!IsPointerValid(class_ro_t_la, ptr_size))
{
m_valid = false;
return;
}
// Now that we have a handle on class_ro_t_la, read the desired data out
m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(class_ro_t_la
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t), // uint32_t instanceStart
sizeof(uint32_t),
0,
error);
if (error.Fail())
{
m_valid = false;
return;
}
lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(class_ro_t_la
+ sizeof(uint32_t) // uint32_t flags
+ sizeof(uint32_t) // uint32_t instanceStart
+ sizeof(uint32_t) // uint32_t instanceSize
+ (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved (__LP64__ only)
+ ptr_size, // const uint8_t *ivarLayout
error);
if (error.Fail())
{
m_valid = false;
return;
}
const size_t buffer_size = 1024;
DataBufferHeap buffer(buffer_size, 0);
size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer.GetBytes(), buffer_size, error);
if (error.Fail())
{
m_valid = false;
return;
}
if (count)
m_name = ConstString((char*)buffer.GetBytes());
else
m_name = ConstString();
m_process_wp = lldb::ProcessWP(process_sp);
m_process_wp = process_sp;
}
private:
static const uint32_t RW_REALIZED = (1 << 31);
ObjCLanguageRuntime &m_runtime; // The runtime, so we can read our metaclass.
bool m_valid; // Gates whether we trust anything here at all.
lldb::addr_t m_objc_class_la; // The address of the objc_class_t.
struct objc_class_t {
ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
ObjCLanguageRuntime::ObjCISA m_superclass;
lldb::addr_t m_cache_la;
lldb::addr_t m_vtable_la;
lldb::addr_t m_data_la;
lldb::addr_t m_cache_ptr;
lldb::addr_t m_vtable_ptr;
lldb::addr_t m_data_ptr;
uint8_t m_flags;
objc_class_t () :
m_isa (0),
m_superclass (0),
m_cache_ptr (0),
m_vtable_ptr (0),
m_data_ptr (0),
m_flags (0)
{
}
void
Clear()
{
m_isa = 0;
m_superclass = 0;
m_cache_ptr = 0;
m_vtable_ptr = 0;
m_data_ptr = 0;
m_flags = 0;
}
bool Read(ProcessSP &process_sp, lldb::addr_t addr)
{
size_t ptr_size = process_sp->GetAddressByteSize();
size_t objc_class_size = ptr_size // uintptr_t isa;
+ ptr_size // Class superclass;
+ ptr_size // void *cache;
+ ptr_size // IMP *vtable;
+ ptr_size; // uintptr_t data_NEVER_USE;
+ ptr_size // Class superclass;
+ ptr_size // void *cache;
+ ptr_size // IMP *vtable;
+ ptr_size; // uintptr_t data_NEVER_USE;
DataBufferHeap objc_class_buf (objc_class_size, '\0');
Error error;
@ -1308,56 +1375,49 @@ private:
uint32_t cursor = 0;
m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
m_cache_la = extractor.GetAddress_unchecked(&cursor); // void *cache;
m_vtable_la = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
m_data_la = data_NEVER_USE & ~(lldb::addr_t)3;
m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
m_data_ptr = data_NEVER_USE & ~(lldb::addr_t)3;
return true;
}
};
objc_class_t m_objc_class;
// cached information from the class_r[ow]_t
ConstString m_name;
uint32_t m_instance_size;
bool m_realized;
struct class_ro_t {
uint32_t m_flags;
uint32_t m_instanceStart;
uint32_t m_instanceSize;
uint32_t m_reserved;
lldb::addr_t m_ivarLayout_la;
lldb::addr_t m_name_la;
lldb::addr_t m_baseMethods_la;
lldb::addr_t m_baseProtocols_la;
lldb::addr_t m_ivars_la;
lldb::addr_t m_ivarLayout_ptr;
lldb::addr_t m_name_ptr;
lldb::addr_t m_baseMethods_ptr;
lldb::addr_t m_baseProtocols_ptr;
lldb::addr_t m_ivars_ptr;
lldb::addr_t m_weakIvarLayout_la;
lldb::addr_t m_baseProperties_la;
lldb::addr_t m_weakIvarLayout_ptr;
lldb::addr_t m_baseProperties_ptr;
bool Read(ProcessSP &process_sp, lldb::addr_t addr)
{
size_t ptr_size = process_sp->GetAddressByteSize();
size_t size = sizeof(uint32_t) // uint32_t flags;
+ sizeof(uint32_t) // uint32_t instanceStart;
+ sizeof(uint32_t) // uint32_t instanceSize;
+ (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only
+ ptr_size // const uint8_t *ivarLayout;
+ ptr_size // const char *name;
+ ptr_size // const method_list_t *baseMethods;
+ ptr_size // const protocol_list_t *baseProtocols;
+ ptr_size // const ivar_list_t *ivars;
+ ptr_size // const uint8_t *weakIvarLayout;
+ ptr_size; // const property_list_t *baseProperties;
size_t size = sizeof(uint32_t) // uint32_t flags;
+ sizeof(uint32_t) // uint32_t instanceStart;
+ sizeof(uint32_t) // uint32_t instanceSize;
+ (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only
+ ptr_size // const uint8_t *ivarLayout;
+ ptr_size // const char *name;
+ ptr_size // const method_list_t *baseMethods;
+ ptr_size // const protocol_list_t *baseProtocols;
+ ptr_size // const ivar_list_t *ivars;
+ ptr_size // const uint8_t *weakIvarLayout;
+ ptr_size; // const property_list_t *baseProperties;
DataBufferHeap buffer (size, '\0');
Error error;
@ -1379,13 +1439,13 @@ private:
m_reserved = extractor.GetU32_unchecked(&cursor);
else
m_reserved = 0;
m_ivarLayout_la = extractor.GetAddress_unchecked(&cursor);
m_name_la = extractor.GetAddress_unchecked(&cursor);
m_baseMethods_la = extractor.GetAddress_unchecked(&cursor);
m_baseProtocols_la = extractor.GetAddress_unchecked(&cursor);
m_ivars_la = extractor.GetAddress_unchecked(&cursor);
m_weakIvarLayout_la = extractor.GetAddress_unchecked(&cursor);
m_baseProperties_la = extractor.GetAddress_unchecked(&cursor);
m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
m_name_ptr = extractor.GetAddress_unchecked(&cursor);
m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
return true;
}
@ -1395,13 +1455,13 @@ private:
uint32_t m_flags;
uint32_t m_version;
lldb::addr_t m_ro_la;
lldb::addr_t m_ro_ptr;
union {
lldb::addr_t m_method_list_la;
lldb::addr_t m_method_lists_la;
lldb::addr_t m_method_list_ptr;
lldb::addr_t m_method_lists_ptr;
};
lldb::addr_t m_properties_la;
lldb::addr_t m_protocols_la;
lldb::addr_t m_properties_ptr;
lldb::addr_t m_protocols_ptr;
ObjCLanguageRuntime::ObjCISA m_firstSubclass;
ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
@ -1411,13 +1471,13 @@ private:
size_t ptr_size = process_sp->GetAddressByteSize();
size_t size = sizeof(uint32_t) // uint32_t flags;
+ sizeof(uint32_t) // uint32_t version;
+ ptr_size // const class_ro_t *ro;
+ ptr_size // union { method_list_t **method_lists; method_list_t *method_list; };
+ ptr_size // struct chained_property_list *properties;
+ ptr_size // const protocol_list_t **protocols;
+ ptr_size // Class firstSubclass;
+ ptr_size; // Class nextSiblingClass;
+ sizeof(uint32_t) // uint32_t version;
+ ptr_size // const class_ro_t *ro;
+ ptr_size // union { method_list_t **method_lists; method_list_t *method_list; };
+ ptr_size // struct chained_property_list *properties;
+ ptr_size // const protocol_list_t **protocols;
+ ptr_size // Class firstSubclass;
+ ptr_size; // Class nextSiblingClass;
DataBufferHeap buffer (size, '\0');
Error error;
@ -1434,9 +1494,9 @@ private:
m_flags = extractor.GetU32_unchecked(&cursor);
m_version = extractor.GetU32_unchecked(&cursor);
m_ro_la = extractor.GetAddress_unchecked(&cursor);
m_method_list_la = extractor.GetAddress_unchecked(&cursor);
m_properties_la = extractor.GetAddress_unchecked(&cursor);
m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
@ -1448,12 +1508,12 @@ private:
{
uint32_t m_entsize;
uint32_t m_count;
lldb::addr_t m_first_la;
lldb::addr_t m_first_ptr;
bool Read(ProcessSP &process_sp, lldb::addr_t addr)
{
{
size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
+ sizeof(uint32_t); // uint32_t count;
+ sizeof(uint32_t); // uint32_t count;
DataBufferHeap buffer (size, '\0');
Error error;
@ -1470,7 +1530,7 @@ private:
m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
m_count = extractor.GetU32_unchecked(&cursor);
m_first_la = addr + cursor;
m_first_ptr = addr + cursor;
return true;
}
@ -1478,9 +1538,9 @@ private:
struct method_t
{
lldb::addr_t m_name_la;
lldb::addr_t m_types_la;
lldb::addr_t m_imp_la;
lldb::addr_t m_name_ptr;
lldb::addr_t m_types_ptr;
lldb::addr_t m_imp_ptr;
std::string m_name;
std::string m_types;
@ -1488,10 +1548,10 @@ private:
static size_t GetSize(ProcessSP &process_sp)
{
size_t ptr_size = process_sp->GetAddressByteSize();
return ptr_size // SEL name;
+ ptr_size // const char *types;
+ ptr_size; // IMP imp;
+ ptr_size // const char *types;
+ ptr_size; // IMP imp;
}
bool Read(ProcessSP &process_sp, lldb::addr_t addr)
@ -1511,26 +1571,35 @@ private:
uint32_t cursor = 0;
m_name_la = extractor.GetAddress_unchecked(&cursor);
m_types_la = extractor.GetAddress_unchecked(&cursor);
m_imp_la = extractor.GetAddress_unchecked(&cursor);
m_name_ptr = extractor.GetAddress_unchecked(&cursor);
m_types_ptr = extractor.GetAddress_unchecked(&cursor);
m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
const size_t buffer_size = 1024;
size_t count;
DataBufferHeap string_buf(buffer_size, 0);
count = process_sp->ReadCStringFromMemory(m_name_la, (char*)string_buf.GetBytes(), buffer_size, error);
count = process_sp->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
m_name.assign((char*)string_buf.GetBytes(), count);
count = process_sp->ReadCStringFromMemory(m_types_la, (char*)string_buf.GetBytes(), buffer_size, error);
count = process_sp->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
m_types.assign((char*)string_buf.GetBytes(), count);
return true;
}
};
lldb::ProcessWP m_process_wp;
ObjCLanguageRuntime &m_runtime; // The runtime, so we can read our metaclass.
bool m_valid; // Gates whether we trust anything here at all.
lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t.
objc_class_t m_objc_class;
// cached information from the class_r[ow]_t
ConstString m_name;
uint32_t m_instance_size;
LazyBool m_realized;
lldb::ProcessWP m_process_wp;
};
class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
@ -1727,44 +1796,27 @@ private:
};
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
AppleObjCRuntimeV2::CreateClassDescriptor (ObjCISA isa)
{
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;
ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV2(*this, isa, m_process->CalculateProcess()));
if (descriptor && descriptor->IsValid())
m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
return descriptor;
ClassDescriptorSP objc_class_sp;
if (isa != 0)
objc_class_sp.reset (new ClassDescriptorV2(*this, isa, m_process->CalculateProcess()));
return objc_class_sp;
}
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& in_value)
{
ClassDescriptorSP objc_class_sp;
uint64_t ptr_value = in_value.GetValueAsUnsigned(0);
if (ptr_value == 0)
return ObjCLanguageRuntime::ClassDescriptorSP();
ObjCISA isa = GetISA(in_value);
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;
ClassDescriptorSP descriptor;
if (ptr_value & 1)
return ClassDescriptorSP(new ClassDescriptorV2Tagged(in_value)); // do not save tagged pointers
descriptor = ClassDescriptorSP(new ClassDescriptorV2(*this, in_value));
if (descriptor && descriptor->IsValid())
m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
return descriptor;
if (ptr_value)
{
if (ptr_value & 1)
objc_class_sp = ClassDescriptorSP(new ClassDescriptorV2Tagged(in_value));
else
objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (in_value);
}
return objc_class_sp;
}
ModuleSP FindLibobjc (Target &target)
@ -1829,23 +1881,23 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
gdb_objc_realized_classes_addr_range))
break;
lldb::addr_t gdb_objc_realized_classes_la = gdb_objc_realized_classes_addr_range.GetBaseAddress().GetLoadAddress(&target);
lldb::addr_t gdb_objc_realized_classes_ptr = gdb_objc_realized_classes_addr_range.GetBaseAddress().GetLoadAddress(&target);
if (gdb_objc_realized_classes_la == LLDB_INVALID_ADDRESS)
if (gdb_objc_realized_classes_ptr == LLDB_INVALID_ADDRESS)
break;
// <rdar://problem/10763513>
lldb::addr_t gdb_objc_realized_classes_nxmaptable_la;
lldb::addr_t gdb_objc_realized_classes_nxmaptable_ptr;
{
Error err;
gdb_objc_realized_classes_nxmaptable_la = process_sp->ReadPointerFromMemory(gdb_objc_realized_classes_la, 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_la);
RemoteNXMapTable gdb_objc_realized_classes(process_sp, gdb_objc_realized_classes_nxmaptable_ptr);
for (RemoteNXMapTable::element elt : gdb_objc_realized_classes)
{
@ -1886,12 +1938,12 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
if (!objc_opt_section_sp)
break;
lldb::addr_t objc_opt_la = objc_opt_section_sp->GetLoadBaseAddress(&target);
lldb::addr_t objc_opt_ptr = objc_opt_section_sp->GetLoadBaseAddress(&target);
if (objc_opt_la == LLDB_INVALID_ADDRESS)
if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
break;
RemoteObjCOpt objc_opt(process_sp, objc_opt_la);
RemoteObjCOpt objc_opt(process_sp, objc_opt_ptr);
for (ObjCLanguageRuntime::ObjCISA objc_isa : objc_opt)
{
@ -1915,9 +1967,9 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
ObjCLanguageRuntime::ObjCISA
AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
{
if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
return 0;
// 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)
@ -1961,24 +2013,19 @@ AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
Process *process = exe_ctx.GetProcessPtr();
if (process)
{
uint8_t pointer_size = process->GetAddressByteSize();
Error error;
return process->ReadUnsignedIntegerFromMemory (isa_pointer,
pointer_size,
0,
error);
ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
if (isa != LLDB_INVALID_ADDRESS)
return isa;
}
return 0;
return 0; // For some reason zero is being used to indicate invalid ISA instead of LLDB_INVALID_ADDRESS
}
// TODO: should we have a transparent_kvo parameter here to say if we
// 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)
{
static const ConstString g_unknown ("unknown");
if (!IsValidISA(isa))
return ConstString();
@ -2012,26 +2059,8 @@ AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
return g_objc_tagged_isa_nsdate_name;
}
ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
if (found != end && found->second)
return found->second->GetClassName();
ClassDescriptorSP descriptor(GetClassDescriptor(isa));
if (!descriptor.get() || !descriptor->IsValid())
return ConstString();
ConstString class_name = descriptor->GetClassName();
if (descriptor->IsKVO())
{
ClassDescriptorSP superclass(descriptor->GetSuperclass());
if (!superclass.get() || !superclass->IsValid())
return ConstString();
descriptor = superclass;
}
m_isa_to_descriptor_cache[isa] = descriptor;
return descriptor->GetClassName();
return ObjCLanguageRuntime::GetActualTypeName(isa);
}
TypeVendor *

View File

@ -105,7 +105,7 @@ public:
GetClassDescriptor (ValueObject& in_value);
virtual ClassDescriptorSP
GetClassDescriptor (ObjCISA isa);
CreateClassDescriptor (ObjCISA isa);
virtual TypeVendor *
GetTypeVendor();

View File

@ -269,7 +269,7 @@ ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
uint32_t ptr_size,
bool allow_NULLs,
bool allow_tagged,
bool check_version_specific)
bool check_version_specific) const
{
if (!value)
return allow_NULLs;
@ -308,35 +308,14 @@ ObjCLanguageRuntime::GetISA(const ConstString &name)
ObjCLanguageRuntime::ObjCISA
ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
{
if (!IsValidISA(isa))
return 0;
ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
if (found != end && found->second)
ClassDescriptorSP objc_class_sp (GetClassDescriptor(isa));
if (objc_class_sp)
{
ClassDescriptorSP superclass = found->second->GetSuperclass();
if (!superclass || !superclass->IsValid())
return 0;
else
{
ObjCISA parent_isa = superclass->GetISA();
m_isa_to_descriptor_cache[parent_isa] = superclass;
return parent_isa;
}
ClassDescriptorSP objc_super_class_sp (objc_class_sp->GetSuperclass());
if (objc_super_class_sp)
return objc_super_class_sp->GetISA();
}
ClassDescriptorSP descriptor(GetClassDescriptor(isa));
if (!descriptor.get() || !descriptor->IsValid())
return 0;
m_isa_to_descriptor_cache[isa] = descriptor;
ClassDescriptorSP superclass(descriptor->GetSuperclass());
if (!superclass.get() || !superclass->IsValid())
return 0;
ObjCISA parent_isa = superclass->GetISA();
m_isa_to_descriptor_cache[parent_isa] = superclass;
return parent_isa;
return 0;
}
// TODO: should we have a transparent_kvo parameter here to say if we
@ -344,28 +323,60 @@ ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
ConstString
ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
{
static const ConstString g_unknown ("unknown");
if (!IsValidISA(isa))
return ConstString();
ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
if (found != end && found->second)
return found->second->GetClassName();
ClassDescriptorSP descriptor(GetClassDescriptor(isa));
if (!descriptor.get() || !descriptor->IsValid())
return ConstString();
ConstString class_name = descriptor->GetClassName();
if (descriptor->IsKVO())
{
ClassDescriptorSP superclass(descriptor->GetSuperclass());
if (!superclass.get() || !superclass->IsValid())
return ConstString();
descriptor = superclass;
}
m_isa_to_descriptor_cache[isa] = descriptor;
return descriptor->GetClassName();
ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor(isa));
if (objc_class_sp)
return objc_class_sp->GetClassName();
return ConstString();
}
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptor (ValueObject& in_value)
{
ObjCISA isa = GetISA(in_value);
if (isa)
return GetClassDescriptor (isa);
return ClassDescriptorSP();
}
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
{
ClassDescriptorSP objc_class_sp;
if (isa)
{
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;
}
return objc_class_sp;
}
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
{
if (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
return objc_class_sp;
}
}
return ClassDescriptorSP();
}