diff options
| author | Enrico Granata <egranata@apple.com> | 2012-02-23 23:10:27 +0000 |
|---|---|---|
| committer | Enrico Granata <egranata@apple.com> | 2012-02-23 23:10:27 +0000 |
| commit | eb4a47988162d54ffeb48e1ff07686e96aee74cb (patch) | |
| tree | 442d21e1d2b966d53fac7c8ee734754601c80961 /lldb/examples/summaries/cocoa/objc_lldb.py | |
| parent | d3d444f81144d95501b2db82cf7f5f69385a8ab2 (diff) | |
| download | bcm5719-llvm-eb4a47988162d54ffeb48e1ff07686e96aee74cb.tar.gz bcm5719-llvm-eb4a47988162d54ffeb48e1ff07686e96aee74cb.zip | |
This patch provides a set of formatters for most of the commonly used Cocoa classes.
The formatter for NSString is an improved version of the one previously shipped as an example, the others are new in design and implementation.
A more robust and OO-compliant Objective-C runtime wrapper is provided for runtime versions 1 and 2 on 32 and 64 bit.
The formatters are contained in a category named "AppKit", which is not enabled at startup.
llvm-svn: 151300
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 |

