diff options
Diffstat (limited to 'lldb/examples/summaries/cocoa/objc_lldb.py')
-rw-r--r-- | lldb/examples/summaries/cocoa/objc_lldb.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lldb/examples/summaries/cocoa/objc_lldb.py b/lldb/examples/summaries/cocoa/objc_lldb.py new file mode 100644 index 00000000000..a81be013159 --- /dev/null +++ b/lldb/examples/summaries/cocoa/objc_lldb.py @@ -0,0 +1,132 @@ +""" +Objective-C runtime wrapper - Replicates the behavior of AppleObjCRuntimeV2.cpp in Python code +for the benefit of synthetic children providers and Python summaries + +part of The LLVM Compiler Infrastructure +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. +""" +import lldb + +class ObjCRuntime: + + def __init__(self,valobj = None): + self.valobj = valobj; + self.adjust_for_architecture() + + def adjust_for_architecture(self): + self.lp64 = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8) + self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle) + self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize() + self.addr_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) + self.addr_ptr_type = self.addr_type.GetPointerType() + + def is_tagged(self): + if valobj is None: + return None + ptr_value = self.valobj.GetPointerValue() + if (ptr_value % 2) == 1: + return True + else: + return False + + def read_ascii(self, pointer): + process = self.valobj.GetTarget().GetProcess() + error = lldb.SBError() + pystr = '' + # cannot do the read at once because there is no length byte + while True: + content = process.ReadMemory(pointer, 1, error) + new_bytes = bytearray(content) + b0 = new_bytes[0] + pointer = pointer + 1 + if b0 == 0: + break + pystr = pystr + chr(b0) + return pystr + + def read_isa(self): + # read ISA pointer + isa_pointer = self.valobj.CreateChildAtOffset("cfisa", + 0, + self.addr_ptr_type) + if isa_pointer == None or isa_pointer.IsValid() == False: + return None; + if isa_pointer.GetValue() == None: + return None; + isa = int(isa_pointer.GetValue(), 0) + if isa == 0 or isa == None: + return None; + return isa + + + def get_parent_class(self, isa = None): + if isa is None: + isa = self.read_isa() + if isa is None: + return None + # read superclass pointer + rw_pointer = isa + self.pointer_size + rw_object = self.valobj.CreateValueFromAddress("parent_isa", + rw_pointer, + self.addr_type) + if rw_object == None or rw_object.IsValid() == False: + return None; + if rw_object.GetValue() == None: + return None; + rw = int(rw_object.GetValue(), 0) + if rw == 0 or rw == None: + return None; + return rw + + def get_class_name(self, isa = None): + if isa is None: + isa = self.read_isa() + if isa is None: + return None + # read rw pointer + rw_pointer = isa + 4 * self.pointer_size + rw_object = self.valobj.CreateValueFromAddress("rw", + rw_pointer, + self.addr_type) + if rw_object == None or rw_object.IsValid() == False: + return None; + if rw_object.GetValue() == None: + return None; + rw = int(rw_object.GetValue(), 0) + if rw == 0 or rw == None: + return None; + + # read data pointer + data_pointer = rw + 8 + data_object = self.valobj.CreateValueFromAddress("data", + data_pointer, + self.addr_type) + if data_object == None or data_object.IsValid() == False: + return None; + if data_object.GetValue() == None: + return None; + data = int(data_object.GetValue(), 0) + if data == 0 or data == None: + return None; + + # read ro pointer + ro_pointer = data + 12 + self.pointer_size + if self.lp64: + ro_pointer += 4 + ro_object = self.valobj.CreateValueFromAddress("ro", + ro_pointer, + self.addr_type) + if ro_object == None or ro_object.IsValid() == False: + return None; + if ro_object.GetValue() == None: + return None; + name_pointer = int(ro_object.GetValue(), 0) + if name_pointer == 0 or name_pointer == None: + return None; + + # now read the actual name and compare it to known stuff + name_string = self.read_ascii(name_pointer) + if (name_string.startswith("NSKVONotify")): + return self.get_class_name(self.get_parent_class()) + return name_string |