[Lldb-commits] [lldb] r151300 - in /lldb/trunk/examples/summaries/cocoa: ./ CFArray.py CFBag.py CFBinaryHeap.py CFDictionary.py CFString.py NSBundle.py NSData.py NSException.py NSMachPort.py NSNotification.py NSNumber.py NSSet.py NSURL.py cache.py metrics.py objc_lldb.py objc_runtime.py

Enrico Granata egranata at apple.com
Thu Feb 23 15:10:27 PST 2012


Author: enrico
Date: Thu Feb 23 17:10:27 2012
New Revision: 151300

URL: http://llvm.org/viewvc/llvm-project?rev=151300&view=rev
Log:
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.

Added:
    lldb/trunk/examples/summaries/cocoa/
    lldb/trunk/examples/summaries/cocoa/CFArray.py
    lldb/trunk/examples/summaries/cocoa/CFBag.py
    lldb/trunk/examples/summaries/cocoa/CFBinaryHeap.py
    lldb/trunk/examples/summaries/cocoa/CFDictionary.py
    lldb/trunk/examples/summaries/cocoa/CFString.py
    lldb/trunk/examples/summaries/cocoa/NSBundle.py
    lldb/trunk/examples/summaries/cocoa/NSData.py
    lldb/trunk/examples/summaries/cocoa/NSException.py
    lldb/trunk/examples/summaries/cocoa/NSMachPort.py
    lldb/trunk/examples/summaries/cocoa/NSNotification.py
    lldb/trunk/examples/summaries/cocoa/NSNumber.py
    lldb/trunk/examples/summaries/cocoa/NSSet.py
    lldb/trunk/examples/summaries/cocoa/NSURL.py
    lldb/trunk/examples/summaries/cocoa/cache.py
    lldb/trunk/examples/summaries/cocoa/metrics.py
    lldb/trunk/examples/summaries/cocoa/objc_lldb.py
    lldb/trunk/examples/summaries/cocoa/objc_runtime.py

Added: lldb/trunk/examples/summaries/cocoa/CFArray.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFArray.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFArray.py (added)
+++ lldb/trunk/examples/summaries/cocoa/CFArray.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,321 @@
+# synthetic children provider for NSArray
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# much less functional than the other two cases below
+# just runs code to get to the count and then returns
+# no children
+class NSArrayKVC_SynthProvider:
+
+	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()
+
+	def __init__(self, valobj, dict):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def num_children(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+	def get_child_index(self,name):
+		if name == "len":
+			return self.num_children();
+		else:
+			return None
+
+	def get_child_at_index(self, index):
+		return None
+
+
+
+# much less functional than the other two cases below
+# just runs code to get to the count and then returns
+# no children
+class NSArrayCF_SynthProvider:
+
+	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.cfruntime_size = self.size_of_cfruntime_base()
+
+	# CFRuntimeBase is defined as having an additional
+	# 4 bytes (padding?) on LP64 architectures
+	# to get its size we add up sizeof(pointer)+4
+	# and then add 4 more bytes if we are on a 64bit system
+	def size_of_cfruntime_base(self):
+		if self.lp64 == True:
+			return 8+4+4;
+		else:
+			return 4+4;
+
+	def __init__(self, valobj, dict):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def num_children(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.cfruntime_size,
+							self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong))
+		return num_children_vo.GetValueAsUnsigned(0)
+
+	def get_child_index(self,name):
+		if name == "len":
+			return self.num_children();
+		else:
+			return None
+
+	def get_child_at_index(self, index):
+		return None
+
+
+class NSArrayI_SynthProvider:
+
+	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()
+
+	def __init__(self, valobj, dict):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	# skip the isa pointer and get at the size
+	def num_children(self):
+		offset = self.pointer_size;
+		datatype = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
+		count = self.valobj.CreateChildAtOffset("count",
+				offset,
+				datatype);
+		return int(count.GetValue(), 0)
+
+	def get_child_index(self,name):
+		if name == "len":
+			return self.num_children();
+		else:
+			return int(name.lstrip('[').rstrip(']'), 0)
+
+	def get_child_at_index(self, index):
+		if index == self.num_children():
+			return self.valobj.CreateValueFromExpression("len",
+				str(index))
+		offset = 2 * self.pointer_size + self.id_type.GetByteSize()*index
+		return self.valobj.CreateChildAtOffset('[' + str(index) + ']',
+				offset,
+				self.id_type)
+
+
+class NSArrayM_SynthProvider:
+
+	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()
+
+	def __init__(self, valobj, dict):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	# skip the isa pointer and get at the size
+	def num_children(self):
+		offset = self.pointer_size;
+		datatype = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
+		count = self.valobj.CreateChildAtOffset("count",
+				offset,
+				datatype);
+		return int(count.GetValue(), 0)
+
+	def get_child_index(self,name):
+		if name == "len":
+			return self.num_children();
+		else:
+			return int(name.lstrip('[').rstrip(']'), 0)
+
+	def data_offset(self):
+		offset = self.pointer_size; # isa
+		offset += self.pointer_size; # _used
+		offset += self.pointer_size; # _doHardRetain, _doWeakAccess, _size
+		offset += self.pointer_size; # _hasObjects, _hasStrongReferences, _offset
+		offset += self.pointer_size; # _mutations
+		return offset;
+
+	# the _offset field is used to calculate the actual offset
+	# when reading a value out of the array. we need to read it
+	# to do so we read a whole pointer_size of data from the
+	# right spot, and then zero out the two LSB
+	def read_offset_field(self):
+		disp = self.pointer_size;  # isa
+		disp += self.pointer_size; # _used
+		disp += self.pointer_size; # _doHardRetain, _doWeakAccess, _size
+		offset = self.valobj.CreateChildAtOffset("offset",
+					disp,
+					self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong))
+		offset_value = int(offset.GetValue(), 0)
+		offset_value = ctypes.c_uint32((offset_value & 0xFFFFFFFC) >> 2).value
+		return offset_value
+
+	# the _used field tells how many items are in the array
+	# but since this is a mutable array, it allocates more space
+	# for performance reasons. we need to get the real _size of
+	# the array to calculate the actual offset of each element
+	# in get_child_at_index() (see NSArray.m for details)
+	def read_size_field(self):
+		disp = self.pointer_size;  # isa
+		disp += self.pointer_size; # _used
+		size = self.valobj.CreateChildAtOffset("size",
+					disp,
+					self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong))
+		size_value = int(size.GetValue(), 0)
+		size_value = ctypes.c_uint32((size_value & 0xFFFFFFFA) >> 2).value
+		return size_value
+
+	def get_child_at_index(self, index):
+		if index == self.num_children():
+			return self.valobj.CreateValueFromExpression("len",
+				str(index))
+		size = self.read_size_field()
+		offset = self.read_offset_field()
+		phys_idx = offset + index
+		if size <= phys_idx:
+			phys_idx -=size;
+		# we still need to multiply by element size to do a correct pointer read
+		phys_idx *= self.id_type.GetByteSize()
+		list_ptr = self.valobj.CreateChildAtOffset("_list",
+            self.data_offset(),
+            self.id_type.GetBasicType(lldb.eBasicTypeUnsignedLongLong))
+		list_addr = int(list_ptr.GetValue(), 0)
+		return self.valobj.CreateValueFromAddress('[' + str(index) + ']',
+				list_addr + phys_idx,
+				self.id_type)
+
+# this is the actual synth provider, but is just a wrapper that checks
+# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
+# appropriate backend layer to do the computations 
+class NSArray_SynthProvider:
+
+	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.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def __init__(self, valobj, dict):
+		self.valobj = valobj;
+		self.adjust_for_architecture()
+		self.wrapper = self.make_wrapper(valobj,dict)
+		self.invalid = (self.wrapper == None)
+
+	def get_child_at_index(self, index):
+		if self.wrapper == None:
+			return None;
+		return self.wrapper.get_child_at_index(index)
+
+	def get_child_index(self,name):
+		if self.wrapper == None:
+			return None;
+		return self.wrapper.get_child_index(name)
+
+	def num_children(self):
+		if self.wrapper == None:
+			return 0;
+		return self.wrapper.num_children()
+
+	def update(self):
+		if self.wrapper == None:
+			return None;
+		return self.wrapper.update()
+
+	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
+
+	# this code acts as our defense against NULL and unitialized
+	# NSArray pointers, which makes it much longer than it would be otherwise
+	def make_wrapper(self,valobj,dict):
+		global statistics
+		class_data = objc_runtime.ObjCRuntime(valobj)
+		if class_data.is_valid() == False:
+			statistics.metric_hit('invalid_pointer',valobj)
+			wrapper = None
+			return
+		class_data = class_data.read_class_data()
+		if class_data.is_valid() == False:
+			statistics.metric_hit('invalid_isa',valobj)
+			wrapper = None
+			return
+		if class_data.is_kvo():
+			class_data = class_data.get_superclass()
+		if class_data.is_valid() == False:
+			statistics.metric_hit('invalid_isa',valobj)
+			wrapper = None
+			return
+		
+		name_string = class_data.class_name()
+		if name_string == '__NSArrayI':
+			wrapper = NSArrayI_SynthProvider(valobj, dict)
+			statistics.metric_hit('code_notrun',valobj)
+		elif name_string == '__NSArrayM':
+			wrapper = NSArrayM_SynthProvider(valobj, dict)
+			statistics.metric_hit('code_notrun',valobj)
+		elif name_string == '__NSCFArray':
+			wrapper = NSArrayCF_SynthProvider(valobj, dict)
+			statistics.metric_hit('code_notrun',valobj)
+		else:
+			wrapper = NSArrayKVC_SynthProvider(valobj, dict)
+			statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+		return wrapper;
+
+def CFArray_SummaryProvider (valobj,dict):
+	provider = NSArray_SynthProvider(valobj,dict);
+	if provider.invalid == False:
+	    try:
+	        summary = str(provider.num_children());
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid array here'
+	    return 'size='+summary
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")

Added: lldb/trunk/examples/summaries/cocoa/CFBag.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFBag.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFBag.py (added)
+++ lldb/trunk/examples/summaries/cocoa/CFBag.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,131 @@
+# summary provider for CFBag
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the length for an CFBag, so they need not
+# obey the interface specification for synthetic children providers
+class CFBagRef_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# 12 bytes on i386
+	# 20 bytes on x64
+	# most probably 2 pointers and 4 bytes of data
+	def offset(self):
+		if self.lp64:
+			return 20
+		else:
+			return 12
+
+	def length(self):
+		size = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return size.GetValueAsUnsigned(0)
+
+
+class CFBagUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def length(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	actual_name = name_string
+	if name_string == '__NSCFType':
+		# CFBag does not expose an actual NSWrapper type, so we have to check that this is
+		# an NSCFType and then check we are a pointer-to __CFBag
+		valobj_type = valobj.GetType()
+		if valobj_type.IsValid() and valobj_type.IsPointerType():
+			pointee_type = valobj_type.GetPointeeType()
+			actual_name = pointee_type.GetName()
+			if actual_name == '__CFBag' or \
+			   actual_name == 'const struct __CFBag':
+				wrapper = CFBagRef_SummaryProvider(valobj)
+				statistics.metric_hit('code_notrun',valobj)
+				return wrapper
+	wrapper = CFBagUnknown_SummaryProvider(valobj)
+	statistics.metric_hit('unknown_class',str(valobj) + " seen as " + actual_name)
+	return wrapper;
+
+def CFBag_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+		try:
+			summary = provider.length();
+		except:
+			summary = None
+		# for some reason, one needs to clear some bits for the count
+		# to be correct when using CF(Mutable)BagRef on x64
+		# the bit mask was derived through experimentation
+		# (if counts start looking weird, then most probably
+		#  the mask needs to be changed)
+		if summary == None:
+			summary = 'no valid set here'
+		else:
+			if provider.lp64:
+				summary = summary & ~0x1fff000000000000
+		if summary == 1:
+			return '1 item'
+		return str(summary) + " items"
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")

Added: lldb/trunk/examples/summaries/cocoa/CFBinaryHeap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFBinaryHeap.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFBinaryHeap.py (added)
+++ lldb/trunk/examples/summaries/cocoa/CFBinaryHeap.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,128 @@
+# summary provider for CFBinaryHeap
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the length for an CFBinaryHeap, so they need not
+# obey the interface specification for synthetic children providers
+class CFBinaryHeapRef_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# 8 bytes on i386
+	# 16 bytes on x64
+	# most probably 2 pointers
+	def offset(self):
+		if self.lp64:
+			return 16
+		else:
+			return 8
+
+	def length(self):
+		size = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return size.GetValueAsUnsigned(0)
+
+
+class CFBinaryHeapUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def length(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBinaryHeapGetCount(" + stream.GetData() + " )");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == '__NSCFType':
+		# CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
+		# an NSCFType and then check we are a pointer-to CFBinaryHeap
+		valobj_type = valobj.GetType()
+		if valobj_type.IsValid() and valobj_type.IsPointerType():
+			pointee_type = valobj_type.GetPointeeType()
+			if pointee_type.GetName() == '__CFBinaryHeap':
+				wrapper = CFBinaryHeapRef_SummaryProvider(valobj)
+				statistics.metric_hit('code_notrun',valobj)
+				return wrapper
+	wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj)
+	statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def CFBinaryHeap_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+		try:
+			summary = provider.length();
+		except:
+			summary = None
+		# for some reason, one needs to clear some bits for the count
+		# to be correct when using CF(Mutable)BagRef on x64
+		# the bit mask was derived through experimentation
+		# (if counts start looking weird, then most probably
+		#  the mask needs to be changed)
+		if summary == None:
+			summary = 'no valid set here'
+		else:
+			if provider.lp64:
+				summary = summary & ~0x1fff000000000000
+		if summary == 1:
+			return '1 item'
+		return str(summary) + " items"
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")

Added: lldb/trunk/examples/summaries/cocoa/CFDictionary.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFDictionary.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFDictionary.py (added)
+++ lldb/trunk/examples/summaries/cocoa/CFDictionary.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,208 @@
+# summary provider for NSDictionary
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the count for an NSDictionary, so they need not
+# obey the interface specification for synthetic children providers
+class NSCFDictionary_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# empirically determined on both 32 and 64bit desktop Mac OS X
+	# probably boils down to 2 pointers and 4 bytes of data, but
+	# the description of __CFDictionary is not readily available so most
+	# of this is guesswork, plain and simple
+	def offset(self):
+		if self.lp64:
+			return 20
+		else:
+			return 12
+
+	def num_children(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+class NSDictionaryI_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# we just need to skip the ISA and the count immediately follows
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def num_children(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		value = num_children_vo.GetValueAsUnsigned(0)
+		if value != None:
+			# the MSB on immutable dictionaries seems to be taken by the LSB of capacity
+			# not sure if it is a bug or some weird sort of feature, but masking it out
+			# gets the count right (unless, of course, someone's dictionaries grow
+			#                       too large - but I have not tested this)
+			if self.lp64:
+				value = value & ~0xFF00000000000000
+			else:
+				value = value & ~0xFF000000
+		return value
+
+class NSDictionaryM_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# we just need to skip the ISA and the count immediately follows
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def num_children(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+class NSDictionaryUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def num_children(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == '__NSCFDictionary':
+		wrapper = NSCFDictionary_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	elif name_string == '__NSDictionaryI':
+		wrapper = NSDictionaryI_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	elif name_string == '__NSDictionaryM':
+		wrapper = NSDictionaryM_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSDictionaryUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def CFDictionary_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = str(provider.num_children());
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid dictionary here'
+	    return summary + " key/value pairs"
+	return ''
+
+def CFDictionary_SummaryProvider2 (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+		try:
+			summary = (provider.num_children());
+		except:
+			summary = None
+		if summary == None:
+			summary = 'no valid dictionary here'
+		# needed on OSX Mountain Lion
+		elif provider.lp64:
+			summary = int(summary) & ~0x0f1f000000000000
+		return str(summary) + " key/value pairs"
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
+	debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")

Added: lldb/trunk/examples/summaries/cocoa/CFString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFString.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFString.py (added)
+++ lldb/trunk/examples/summaries/cocoa/CFString.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,302 @@
+# synthetic children and summary provider for CFString
+# (and related NSString class)
+import lldb
+
+def CFString_SummaryProvider (valobj,dict):
+	provider = CFStringSynthProvider(valobj,dict);
+	if provider.invalid == False:
+	    try:
+	        summary = provider.get_child_at_index(provider.get_child_index("content")).GetSummary();
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid string here'
+	    return '@'+summary
+	return ''
+
+def CFAttributedString_SummaryProvider (valobj,dict):
+	offset = valobj.GetTarget().GetProcess().GetAddressByteSize()
+	pointee = valobj.GetValueAsUnsigned(0)
+	summary = 'no valid string here'
+	if pointee != None and pointee != 0:
+		pointee = pointee + offset
+		child_ptr = valobj.CreateValueFromAddress("string_ptr",pointee,valobj.GetType())
+		child = child_ptr.CreateValueFromAddress("string_data",child_ptr.GetValueAsUnsigned(),valobj.GetType()).AddressOf()
+		provider = CFStringSynthProvider(child,dict);
+		if provider.invalid == False:
+			try:
+				summary = provider.get_child_at_index(provider.get_child_index("content")).GetSummary();
+			except:
+				summary = 'no valid string here'
+	if summary == None:
+		summary = 'no valid string here'
+	return '@'+summary
+
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F CFString.CFString_SummaryProvider NSString CFStringRef CFMutableStringRef")
+	debugger.HandleCommand("type summary add -F CFString.CFAttributedString_SummaryProvider NSAttributedString")
+
+class CFStringSynthProvider:
+	def __init__(self,valobj,dict):
+		self.valobj = valobj;
+		self.update()
+
+	# children other than "content" are for debugging only and must not be used in production code
+	def num_children(self):
+		if self.invalid:
+			return 0;
+		return 6;
+
+	def read_unicode(self, pointer):
+		process = self.valobj.GetTarget().GetProcess()
+		error = lldb.SBError()
+		pystr = u''
+		# cannot do the read at once because the length value has
+		# a weird encoding. better play it safe here
+		while True:
+			content = process.ReadMemory(pointer, 2, error)
+			new_bytes = bytearray(content)
+			b0 = new_bytes[0]
+			b1 = new_bytes[1]
+			pointer = pointer + 2
+			if b0 == 0 and b1 == 0:
+				break
+			# rearrange bytes depending on endianness
+			# (do we really need this or is Cocoa going to
+			#  use Windows-compatible little-endian even
+			#  if the target is big endian?)
+			if self.is_little:
+				value = b1 * 256 + b0
+			else:
+				value = b0 * 256 + b1
+			pystr = pystr + unichr(value)
+		return pystr
+
+	# handle the special case strings
+	# only use the custom code for the tested LP64 case
+	def handle_special(self):
+		if self.lp64 == False:
+			# for 32bit targets, use safe ObjC code
+			return self.handle_unicode_string_safe()
+		offset = 12
+		pointer = self.valobj.GetValueAsUnsigned(0) + offset
+		pystr = self.read_unicode(pointer)
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+
+	# last resort call, use ObjC code to read; the final aim is to
+	# be able to strip this call away entirely and only do the read
+	# ourselves
+	def handle_unicode_string_safe(self):
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + self.valobj.GetObjectDescription() + "\"");
+
+	def handle_unicode_string(self):
+		# step 1: find offset
+		if self.inline:
+			pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
+			if self.explicit == False:
+				# untested, use the safe code path
+				return self.handle_unicode_string_safe();
+			else:
+				# not sure why 8 bytes are skipped here
+				# (lldb) mem read -c 50 0x00000001001154f0
+				# 0x1001154f0: 98 1a 85 71 ff 7f 00 00 90 07 00 00 01 00 00 00  ...q?...........
+				# 0x100115500: 03 00 00 00 00 00 00 00 *c3 03 78 00 78 00 00 00  ........?.x.x...
+				# 0x100115510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+				# 0x100115520: 00 00                                            ..
+				# content begins at * (i.e. 8 bytes into variants, skipping void* buffer in
+				# __notInlineImmutable1 entirely, while the length byte is correctly located
+				# for an inline string)
+				pointer = pointer + 8;
+		else:
+			pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
+			# read 8 bytes here and make an address out of them
+			try:
+			    vopointer = self.valobj.CreateChildAtOffset("dummy",
+				pointer,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+			    pointer = vopointer.GetValueAsUnsigned(0)
+			except:
+			    return self.valobj.CreateValueFromExpression("content",
+                                                             '(char*)"@\"invalid NSString\""')
+		# step 2: read Unicode data at pointer
+		pystr = self.read_unicode(pointer)
+		# step 3: return it
+		return self.valobj.CreateValueFromExpression("content",
+			"(char*)\"" + pystr.encode('utf-8') + "\"")
+
+	def handle_inline_explicit(self):
+		if self.lp64:
+			offset = 24
+		else:
+			offset = 12
+		offset = offset + self.valobj.GetValueAsUnsigned(0)
+		return self.valobj.CreateValueFromExpression("content",
+				"(char*)(" + str(offset) + ")")
+
+	def handle_mutable_string(self):
+		if self.lp64:
+			offset = 16
+		else:
+			offset = 8
+		data = self.valobj.CreateChildAtOffset("content",
+			offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+		data_value = data.GetValueAsUnsigned(0)
+		data_value = data_value + 1
+		return self.valobj.CreateValueFromExpression("content", "(char*)(" + str(data_value) + ")")
+
+	def handle_UTF8_inline(self):
+		offset = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
+		if self.explicit == False:
+			offset = offset + 1;
+		return self.valobj.CreateValueFromAddress("content",
+				offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)).AddressOf();
+
+	def handle_UTF8_not_inline(self):
+		offset = self.size_of_cfruntime_base();
+		return self.valobj.CreateChildAtOffset("content",
+				offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
+
+	def get_child_at_index(self,index):
+		if index == 0:
+			return self.valobj.CreateValueFromExpression("mutable",
+				str(int(self.mutable)));
+		if index == 1:
+			return self.valobj.CreateValueFromExpression("inline",
+				str(int(self.inline)));
+		if index == 2:
+			return self.valobj.CreateValueFromExpression("explicit",
+				str(int(self.explicit)));
+		if index == 3:
+			return self.valobj.CreateValueFromExpression("unicode",
+				str(int(self.unicode)));
+		if index == 4:
+			return self.valobj.CreateValueFromExpression("special",
+				str(int(self.special)));
+		if index == 5:
+			# we are handling the several possible combinations of flags.
+			# for each known combination we have a function that knows how to
+			# go fetch the data from memory instead of running code. if a string is not
+			# correctly displayed, one should start by finding a combination of flags that
+			# makes it different from these known cases, and provide a new reader function
+			# if this is not possible, a new flag might have to be made up (like the "special" flag
+			# below, which is not a real flag in CFString), or alternatively one might need to use
+			# the ObjC runtime helper to detect the new class and deal with it accordingly
+			if self.mutable == True:
+				return self.handle_mutable_string()
+			elif self.inline == True and self.explicit == True and \
+			   self.unicode == False and self.special == False and \
+			   self.mutable == False:
+				return self.handle_inline_explicit()
+			elif self.unicode == True:
+				return self.handle_unicode_string();
+			elif self.special == True:
+				return self.handle_special();
+			elif self.inline == True:
+				return self.handle_UTF8_inline();
+			else:
+				return self.handle_UTF8_not_inline();
+
+	def get_child_index(self,name):
+		if name == "content":
+			return self.num_children() - 1;
+		if name == "mutable":
+			return 0;
+		if name == "inline":
+			return 1;
+		if name == "explicit":
+			return 2;
+		if name == "unicode":
+			return 3;
+		if name == "special":
+			return 4;
+
+	def is_64bit(self):
+		return self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8
+
+	def is_little_endian(self):
+		return self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle
+
+	# CFRuntimeBase is defined as having an additional
+	# 4 bytes (padding?) on LP64 architectures
+	# to get its size we add up sizeof(pointer)+4
+	# and then add 4 more bytes if we are on a 64bit system
+	def size_of_cfruntime_base(self):
+		if self.lp64 == True:
+			return 8+4+4;
+		else:
+			return 4+4;
+
+	# the info bits are part of the CFRuntimeBase structure
+	# to get at them we have to skip a uintptr_t and then get
+	# at the least-significant byte of a 4 byte array. If we are
+	# on big-endian this means going to byte 3, if we are on
+	# little endian (OSX & iOS), this means reading byte 0
+	def offset_of_info_bits(self):
+		if self.lp64 == True:
+			offset = 8;
+		else:
+			offset = 4;
+		if self.is_little == False:
+			offset = offset + 3;
+		return offset;
+
+	def read_info_bits(self):
+		cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
+					self.offset_of_info_bits(),
+					self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
+		cfinfo.SetFormat(11)
+		info = cfinfo.GetValue();
+		if info != None:
+			self.invalid = False;
+			return int(info,0);
+		else:
+			self.invalid = True;
+			return None;
+
+	# calculating internal flag bits of the CFString object
+	# this stuff is defined and discussed in CFString.c
+	def is_mutable(self):
+		return (self.info_bits & 1) == 1;
+
+	def is_inline(self):
+		return (self.info_bits & 0x60) == 0;
+
+	# this flag's name is ambiguous, it turns out
+	# we must skip a length byte to get at the data
+	# when this flag is False
+	def has_explicit_length(self):
+		return (self.info_bits & (1 | 4)) != 4;
+
+	# probably a subclass of NSString. obtained this from [str pathExtension]
+	# here info_bits = 0 and Unicode data at the start of the padding word
+	# in the long run using the isa value might be safer as a way to identify this
+	# instead of reading the info_bits
+	def is_special_case(self):
+		return self.info_bits == 0;
+
+	def is_unicode(self):
+		return (self.info_bits & 0x10) == 0x10;
+
+	# preparing ourselves to read into memory
+	# by adjusting architecture-specific info
+	def adjust_for_architecture(self):
+		self.lp64 = self.is_64bit();
+		self.is_little = self.is_little_endian();
+
+	# reading info bits out of the CFString and computing
+	# useful values to get at the real data
+	def compute_flags(self):
+		self.info_bits = self.read_info_bits();
+		if self.info_bits == None:
+			return;
+		self.mutable = self.is_mutable();
+		self.inline = self.is_inline();
+		self.explicit = self.has_explicit_length();
+		self.unicode = self.is_unicode();
+		self.special = self.is_special_case();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.compute_flags();
\ No newline at end of file

Added: lldb/trunk/examples/summaries/cocoa/NSBundle.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSBundle.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSBundle.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSBundle.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,125 @@
+# summary provider for NSBundle
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+import NSURL
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but a summary for an NSURL, so they need not
+# obey the interface specification for synthetic children providers
+class NSBundleKnown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+			self.pointer_size = 8
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+			self.pointer_size = 4
+		self.NSString = self.valobj.GetTarget().FindFirstType('NSString')
+		self.NSURL = self.valobj.GetTarget().FindFirstType('NSURL')
+
+	# we need to skip the ISA, plus four other values
+	# that are luckily each a pointer in size
+	# which makes our computation trivial :-)
+	def offset(self):
+		return 5 * self.pointer_size
+
+	def url_text(self):
+		global statistics
+		text = self.valobj.CreateChildAtOffset("text",
+							self.offset(),
+							self.NSString.GetPointerType())
+		my_string = text.GetSummary()
+		if (my_string == None) or (my_string == ''):
+			statistics.metric_hit('unknown_class',str(self.valobj) + " triggered unkown pointer location")
+			return NSBundleUnknown_SummaryProvider(self.valobj).url_text()
+		else:
+			statistics.metric_hit('code_notrun',self.valobj)
+			return my_string
+
+
+class NSBundleUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def url_text(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
+		url_text_vo = self.valobj.CreateValueFromExpression("path",expr);
+		return url_text_vo.GetSummary()
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSBundle':
+		wrapper = NSBundleKnown_SummaryProvider(valobj)
+		# [NSBundle mainBundle] does return an object that is
+		# not correctly filled out for our purposes, so we still
+		# end up having to run code in that case
+		#statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSBundleUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSBundle_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.url_text();
+	    except:
+	        summary = None
+	    if summary == None or summary == '':
+	        summary = 'no valid NSBundle here'
+	    return summary
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")

Added: lldb/trunk/examples/summaries/cocoa/NSData.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSData.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSData.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSData.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,118 @@
+# summary provider for NSData
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the length for an NSData, so they need not
+# obey the interface specification for synthetic children providers
+class NSConcreteData_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# one pointer is the ISA
+	# then there are 32 bit worth of flags and other data
+	# however, on 64bit systems these are padded to be a full
+	# machine word long, which means we actually have two pointers
+	# worth of data to skip
+	def offset(self):
+		if self.lp64:
+			return 16
+		else:
+			return 8
+
+	def length(self):
+		size = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return size.GetValueAsUnsigned(0)
+
+
+class NSDataUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def length(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " length]");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSConcreteData' or \
+	   name_string == 'NSConcreteMutableData' or \
+	   name_string == '__NSCFData':
+		wrapper = NSConcreteData_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSDataUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSData_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.length();
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid data here'
+	    if summary == 1:
+	        return '1 byte'
+	    return str(summary) + " bytes"
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSData.NSData_SummaryProvider NSData CFDataRef CFMutableDataRef")

Added: lldb/trunk/examples/summaries/cocoa/NSException.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSException.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSException.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSException.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,108 @@
+# summary provider for class NSException
+import objc_runtime
+import metrics
+import CFString
+import lldb
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+class NSKnownException_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+
+	# skip the ISA and go to the name pointer
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def description(self):
+		name_ptr = self.valobj.CreateChildAtOffset("name",
+							self.offset(),
+							self.id_type)
+		reason_ptr = self.valobj.CreateChildAtOffset("reason",
+							2*self.offset(),
+							self.id_type)
+		return CFString.CFString_SummaryProvider(name_ptr,None) + " " + CFString.CFString_SummaryProvider(reason_ptr,None)
+
+
+class NSUnknownException_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def description(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		name_vo = self.valobj.CreateValueFromExpression("name","(NSString*)[" + stream.GetData() + " name]");
+		reason_vo = self.valobj.CreateValueFromExpression("reason","(NSString*)[" + stream.GetData() + " reason]");
+		return CFString.CFString_SummaryProvider(name_vo,None) + ' ' + CFString.CFString_SummaryProvider(reason_vo,None)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSException':
+		wrapper = NSKnownException_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSUnknownException_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSException_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.description();
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid exception here'
+	    return str(summary)
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSException.NSException_SummaryProvider NSException")

Added: lldb/trunk/examples/summaries/cocoa/NSMachPort.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSMachPort.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSMachPort.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSMachPort.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,109 @@
+# summary provider for NSData
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the port number of an NSMachPort, so they need not
+# obey the interface specification for synthetic children providers
+class NSMachPortKnown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+
+	# one pointer is the ISA
+	# then we have one other internal pointer, plus
+	# 4 bytes worth of flags. hence, these values
+	def offset(self):
+		if self.lp64:
+			return 20
+		else:
+			return 12
+
+	def port(self):
+		vport = self.valobj.CreateChildAtOffset("port",
+							self.offset(),
+							self.NSUInteger)
+		return vport.GetValueAsUnsigned(0)
+
+
+class NSMachPortUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def port(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		num_children_vo = self.valobj.CreateValueFromExpression("port","(int)[" + stream.GetData() + " machPort]");
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSMachPort':
+		wrapper = NSMachPortKnown_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSMachPortUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSMachPort_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.port();
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid mach port here'
+	    return 'mach port: ' + str(summary)
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSMachPort.NSMachPort_SummaryProvider NSMachPort")

Added: lldb/trunk/examples/summaries/cocoa/NSNotification.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSNotification.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSNotification.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSNotification.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,104 @@
+# summary provider for class NSNotification
+import objc_runtime
+import metrics
+import CFString
+import lldb
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+class NSConcreteNotification_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+
+	# skip the ISA and go to the name pointer
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def name(self):
+		string_ptr = self.valobj.CreateChildAtOffset("name",
+							self.offset(),
+							self.id_type)
+		return CFString.CFString_SummaryProvider(string_ptr,None)
+
+
+class NSNotificationUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def name(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		name_vo = self.valobj.CreateValueFromExpression("name","(NSString*)[" + stream.GetData() + " name]");
+		return CFString.CFString_SummaryProvider(name_vo,None)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSConcreteNotification':
+		wrapper = NSConcreteNotification_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSNotificationUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSNotification_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.name();
+	    except:
+	        summary = None
+	    if summary == None:
+	        summary = 'no valid notification here'
+	    return str(summary)
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSNotification.NSNotification_SummaryProvider NSNotification")

Added: lldb/trunk/examples/summaries/cocoa/NSNumber.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSNumber.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSNumber.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSNumber.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,217 @@
+# summary provider for NSNumber
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+import struct
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the port number of an NSNumber, so they need not
+# obey the interface specification for synthetic children providers
+class NSTaggedNumber_SummaryProvider:
+	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()
+
+	def __init__(self, valobj, info_bits, data):
+		self.valobj = valobj;
+		self.update();
+		self.info_bits = info_bits
+		self.data = data
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+		self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
+		self.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
+		self.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
+		self.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
+		self.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
+		self.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		self.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
+		self.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
+		self.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
+		self.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
+
+	def value(self):
+		# in spite of the plenty of types made available by the public NSNumber API
+		# only a bunch of these are actually used in the internal implementation
+		# unfortunately, the original type information appears to be lost
+		# so we try to at least recover the proper magnitude of the data
+		if self.info_bits == 0:
+			return '(char)' + str(self.data % 256)
+		if self.info_bits == 4:
+			return '(short)' + str(self.data % (256*256))
+		if self.info_bits == 8:
+			return '(int)' + str(self.data % (256*256*256*256))
+		if self.info_bits == 12:
+			return '(long)' + str(self.data)
+		else:
+			return 'absurd value:(info=' + str(self.info_bits) + ", value = " + str(self.data) + ')'
+
+
+class NSUntaggedNumber_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+		self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
+		self.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
+		self.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
+		self.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
+		self.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
+		self.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		self.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
+		self.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
+		self.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
+		self.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
+
+	def value(self):
+		global statistics
+		# we need to skip the ISA, then the next byte tells us what to read
+		# we then skip one other full pointer worth of data and then fetch the contents
+		# if we are fetching an int64 value, one more pointer must be skipped to get at our data
+		data_type_vo = self.valobj.CreateChildAtOffset("dt",
+							self.pointer_size,
+							self.char)
+		data_type = ((data_type_vo.GetValueAsUnsigned(0) % 256) & 0x1F)
+		data_offset = 2 * self.pointer_size
+		if data_type == 0B00001:
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.char)
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(char)' + str(data_vo.GetValueAsUnsigned(0))
+		elif data_type == 0B0010:
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.short)
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(short)' + str(data_vo.GetValueAsUnsigned(0) % (256*256))
+		# IF tagged pointers are possible on 32bit+v2 runtime
+		# (of which the only existing instance should be iOS)
+		# then values of this type might be tagged
+		elif data_type == 0B0011:
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.int)
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(int)' + str(data_vo.GetValueAsUnsigned(0) % (256*256*256*256))
+		# apparently, on lp64 architectures, these are the only values that will ever
+		# be represented by a non tagged pointers
+		elif data_type == 0B10001 or data_type == 0B0100:
+			data_offset = data_offset + self.pointer_size
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.longlong)
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(long)' + str(data_vo.GetValueAsUnsigned(0))
+		elif data_type == 0B0101:
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.longlong)
+			data_plain = int(str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
+			packed = struct.pack('I', data_plain)
+			data_float = struct.unpack('f', packed)[0]
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(float)' + str(data_float)
+		elif data_type == 0B0110:
+			data_vo = self.valobj.CreateChildAtOffset("data",
+								data_offset,
+								self.longlong)
+			data_plain = data_vo.GetValueAsUnsigned(0)
+			data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
+			statistics.metric_hit('code_notrun',self.valobj)
+			return '(double)' + str(data_double)
+		statistics.metric_hit('unknown_class',str(self.valobj) + " had unknown data_type " + str(data_type))
+		return 'absurd: dt = ' + str(data_type)
+
+
+class NSUnknownNumber_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def value(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		expr = "(NSString*)[" + stream.GetData() + " stringValue]"
+		num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
+		return num_children_vo.GetSummary()
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSNumber' or name_string == '__NSCFNumber':
+		if class_data.is_tagged():
+			wrapper = NSTaggedNumber_SummaryProvider(valobj,class_data.info_bits(),class_data.value())
+			statistics.metric_hit('code_notrun',valobj)
+		else:
+			# the wrapper might be unable to decipher what is into the NSNumber
+			# and then have to run code on it
+			wrapper = NSUntaggedNumber_SummaryProvider(valobj)
+	else:
+		wrapper = NSUnknownNumber_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+
+def NSNumber_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    #try:
+	    summary = provider.value();
+	    #except:
+	    #    summary = None
+	    if summary == None:
+	        summary = 'no valid number here'
+	    return str(summary)
+	return ''
+
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber")
+

Added: lldb/trunk/examples/summaries/cocoa/NSSet.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSSet.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSSet.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSSet.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,211 @@
+# summary provider for NSSet
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but the port number of an NSMachPort, so they need not
+# obey the interface specification for synthetic children providers
+class NSCFSet_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+
+	# one pointer is the ISA
+	# then we have one other internal pointer, plus
+	# 4 bytes worth of flags. hence, these values
+	def offset(self):
+		if self.lp64:
+			return 20
+		else:
+			return 12
+
+	def count(self):
+		vcount = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return vcount.GetValueAsUnsigned(0)
+
+
+class NSSetUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def count(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		expr = "(int)[" + stream.GetData() + " count]"
+		num_children_vo = self.valobj.CreateValueFromExpression("count",expr);
+		return num_children_vo.GetValueAsUnsigned(0)
+
+class NSSetI_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# we just need to skip the ISA and the count immediately follows
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def count(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		value = num_children_vo.GetValueAsUnsigned(0)
+		if value != None:
+			# the MSB on immutable sets seems to be taken by some other data
+			# not sure if it is a bug or some weird sort of feature, but masking it out
+			# gets the count right (unless, of course, someone's dictionaries grow
+			#                       too large - but I have not tested this)
+			if self.lp64:
+				value = value & ~0xFF00000000000000
+			else:
+				value = value & ~0xFF000000
+		return value
+
+class NSSetM_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+
+	# we just need to skip the ISA and the count immediately follows
+	def offset(self):
+		if self.lp64:
+			return 8
+		else:
+			return 4
+
+	def count(self):
+		num_children_vo = self.valobj.CreateChildAtOffset("count",
+							self.offset(),
+							self.NSUInteger)
+		return num_children_vo.GetValueAsUnsigned(0)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == '__NSCFSet':
+		wrapper = NSCFSet_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	elif name_string == '__NSSetI':
+		wrapper = NSSetI_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	elif name_string == '__NSSetM':
+		wrapper = NSSetM_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSSetUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+
+def NSSet_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    #try:
+	    summary = provider.count();
+	    #except:
+	    #    summary = None
+	    if summary == None:
+	        summary = 'no valid set here'
+	    return str(summary) + ' objects'
+	return ''
+
+def NSSet_SummaryProvider2 (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+		try:
+			summary = provider.count();
+		except:
+			summary = None
+		# for some reason, one needs to clear some bits for the count returned
+		# to be correct when using directly CF*SetRef as compared to NS*Set
+		# this only happens on 64bit, and the bit mask was derived through
+		# experimentation (if counts start looking weird, then most probably
+		#                  the mask needs to be changed)
+		if summary == None:
+			summary = 'no valid set here'
+		else:
+			if provider.lp64:
+				summary = int(summary) & ~0x1fff000000000000
+		return str(summary) + ' objects'
+	return ''
+
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSSet.NSSet_SummaryProvider NSSet")
+	debugger.HandleCommand("type summary add -F NSSet.NSSet_SummaryProvider2 CFSetRef CFMutableSetRef")

Added: lldb/trunk/examples/summaries/cocoa/NSURL.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSURL.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSURL.py (added)
+++ lldb/trunk/examples/summaries/cocoa/NSURL.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,124 @@
+# summary provider for NSURL
+import lldb
+import ctypes
+import objc_runtime
+import metrics
+import CFString
+
+statistics = metrics.Metrics()
+statistics.add_metric('invalid_isa')
+statistics.add_metric('invalid_pointer')
+statistics.add_metric('unknown_class')
+statistics.add_metric('code_notrun')
+
+# despite the similary to synthetic children providers, these classes are not
+# trying to provide anything but a summary for an NSURL, so they need not
+# obey the interface specification for synthetic children providers
+class NSURLKnown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update();
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+		if self.lp64:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+			self.pointer_size = 8
+		else:
+			self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+			self.pointer_size = 4
+		self.NSString = self.valobj.GetTarget().FindFirstType('NSString')
+		self.NSURL = self.valobj.GetTarget().FindFirstType('NSURL')
+
+	# one pointer is the ISA
+	# then there is one more pointer and 8 bytes of plain data
+	# (which are also present on a 32-bit system)
+	# plus another pointer, and then the real data
+	def offset(self):
+		if self.lp64:
+			return 24
+		else:
+			return 16
+
+	def url_text(self):
+		text = self.valobj.CreateChildAtOffset("text",
+							self.offset(),
+							self.NSString.GetPointerType())
+		base = self.valobj.CreateChildAtOffset("base",
+							self.offset()+self.pointer_size,
+							self.NSURL.GetPointerType())
+		my_string = CFString.CFString_SummaryProvider(text,None)
+		if base.GetValueAsUnsigned(0) != 0:
+			my_string = my_string + " (base path: " + NSURL_SummaryProvider(base,None) + ")"
+		return my_string
+
+
+class NSURLUnknown_SummaryProvider:
+	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()
+
+	def __init__(self, valobj):
+		self.valobj = valobj;
+		self.update()
+
+	def update(self):
+		self.adjust_for_architecture();
+		self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+
+	def url_text(self):
+		stream = lldb.SBStream()
+		self.valobj.GetExpressionPath(stream)
+		url_text_vo = self.valobj.CreateValueFromExpression("url","(NSString*)[" + stream.GetData() + " description]");
+		return CFString.CFString_SummaryProvider(url_text_vo,None)
+
+
+def GetSummary_Impl(valobj):
+	global statistics
+	class_data = objc_runtime.ObjCRuntime(valobj)
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_pointer',valobj)
+		wrapper = None
+		return
+	class_data = class_data.read_class_data()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	if class_data.is_kvo():
+		class_data = class_data.get_superclass()
+	if class_data.is_valid() == False:
+		statistics.metric_hit('invalid_isa',valobj)
+		wrapper = None
+		return
+	
+	name_string = class_data.class_name()
+	if name_string == 'NSURL':
+		wrapper = NSURLKnown_SummaryProvider(valobj)
+		statistics.metric_hit('code_notrun',valobj)
+	else:
+		wrapper = NSURLUnknown_SummaryProvider(valobj)
+		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
+	return wrapper;
+
+def NSURL_SummaryProvider (valobj,dict):
+	provider = GetSummary_Impl(valobj);
+	if provider != None:
+	    try:
+	        summary = provider.url_text();
+	    except:
+	        summary = None
+	    if summary == None or summary == '':
+	        summary = 'no valid NSURL here'
+	    return summary
+	return ''
+
+def __lldb_init_module(debugger,dict):
+	debugger.HandleCommand("type summary add -F NSURL.NSURL_SummaryProvider NSURL CFURLRef")

Added: lldb/trunk/examples/summaries/cocoa/cache.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/cache.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/cache.py (added)
+++ lldb/trunk/examples/summaries/cocoa/cache.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,28 @@
+import metrics
+
+class Cache:
+	def __init__(self):
+		self.data = {}
+		self.statistics = metrics.Metrics()
+		self.statistics.add_metric('hit')
+		self.statistics.add_metric('miss')
+
+	def look_for_key(self,key):
+		if key in self.data:
+			return True
+		return False
+
+	def add_item(self,key,value,ok_to_replace=True):
+		if not(ok_to_replace) and self.look_for_key(key):
+			return False
+		self.data[key] = value
+		return True
+
+	def get_value(self,key,default=None):
+		if self.look_for_key(key):
+			self.statistics.metric_hit('hit',key)
+			return self.data[key]
+		else:
+			self.statistics.metric_hit('miss',key)
+			return default
+

Added: lldb/trunk/examples/summaries/cocoa/metrics.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/metrics.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/metrics.py (added)
+++ lldb/trunk/examples/summaries/cocoa/metrics.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,62 @@
+import lldb
+
+class Counter:
+	def __init__(self):
+		self.count = 0
+		self.list = []
+	def update(self,name):
+		self.count = self.count + 1
+		self.list.append(str(name))
+	def __str__(self):
+		return str(self.count) + " times, for items [" + str(self.list) + "]"
+
+class MetricsPrinter_Verbose:
+	def __init__(self,metrics):
+		self.metrics = metrics
+	def __str__(self):
+		string = ""
+		for key,value in self.metrics.metrics.items():
+			string = string + "metric " + str(key) + ": " + str(value) + "\n"
+		return string
+
+class MetricsPrinter_Compact:
+	def __init__(self,metrics):
+		self.metrics = metrics
+	def __str__(self):
+		string = ""
+		for key,value in self.metrics.metrics.items():
+			string = string + "metric " + str(key) + " was hit " + str(value.count) + " times\n"
+		return string
+
+class Metrics:
+	def __init__(self):
+		self.metrics = {}
+
+	def add_metric(self,name):
+		self.metrics[name] = Counter()
+
+	def metric_hit(self,metric,trigger):
+		self.metrics[metric].update(trigger)
+
+	def __getitem__(self,key):
+		return self.metrics[key]
+
+	def __getattr__(self,name):
+		if name == 'compact':
+			return MetricsPrinter_Compact(self)
+		if name == 'verbose':
+			return MetricsPrinter_Verbose(self)
+		raise AttributeError("%r object has no attribute %r" %
+			                         (type(self).__name__, name))
+
+	def __str__(self):
+		return str(self.verbose)
+
+	def metric_success(self,metric):
+		total_count = 0
+		metric_count = self[metric].count
+		for key,value in self.metrics.items():
+			total_count = total_count + value.count
+		if total_count > 0:
+			return metric_count / float(total_count)
+		return 0

Added: lldb/trunk/examples/summaries/cocoa/objc_lldb.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_lldb.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/objc_lldb.py (added)
+++ lldb/trunk/examples/summaries/cocoa/objc_lldb.py Thu Feb 23 17:10:27 2012
@@ -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

Added: lldb/trunk/examples/summaries/cocoa/objc_runtime.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py?rev=151300&view=auto
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/objc_runtime.py (added)
+++ lldb/trunk/examples/summaries/cocoa/objc_runtime.py Thu Feb 23 17:10:27 2012
@@ -0,0 +1,500 @@
+# a wrapper for the Objective-C runtime for use by LLDB
+import lldb
+import cache
+
+class Utilities:
+	@staticmethod
+	def read_ascii(process, pointer,max_len=128,when_over_return_none=True):
+		error = lldb.SBError()
+		pystr = ''
+		count = 0
+		# there is not any length byte to tell us how much to read
+		# however, there are most probably ways to optimize this
+		# in order to avoid doing the read byte-by-byte (caching is
+		# still occurring, but we could just fetch a larger chunk
+		# of memory instead of going one byte at a time)
+		while True:
+			content = process.ReadMemory(pointer, 1, error)
+			new_bytes = bytearray(content)
+			if new_bytes == None or len(new_bytes) == 0:
+				break
+			b0 = new_bytes[0]
+			pointer = pointer + 1
+			if b0 == 0:
+				break
+			count = count + 1
+			if count > max_len:
+				if when_over_return_none:
+					return None
+				else:
+					return pystr
+			pystr = pystr + chr(b0)
+		return pystr
+
+	@staticmethod
+	def is_valid_pointer(pointer, pointer_size, allow_tagged):
+		if pointer == None:
+			return False
+		if pointer == 0:
+			return False
+		if allow_tagged:
+			if (pointer % 2) == 1:
+				return True
+		return ((pointer % pointer_size) == 0)
+
+	# Objective-C runtime has a rule that pointers in a class_t will only have bits 0 thru 46 set
+	# so if any pointer has bits 47 thru 63 high we know that this is not a valid isa
+	@staticmethod
+	def is_allowed_pointer(pointer):
+		if pointer == None:
+			return False
+		mask = 0xFFFF800000000000
+		if (pointer & mask) != 0:
+			return False
+		return True
+
+	@staticmethod
+	def read_child_of(valobj,offset,type):
+		child = valobj.CreateChildAtOffset("childUNK",offset,type)
+		if child == None or child.IsValid() == False:
+			return None;
+		return child.GetValueAsUnsigned()
+
+	@staticmethod
+	def is_valid_identifier(name):
+		if name is None:
+			return None
+		if len(name) == 0:
+			return None
+		return True
+		# the rules below make perfect sense for compile-time class names, but the runtime is free
+		# to create classes with arbitrary names to implement functionality (e.g -poseAsClass)
+		# hence, we cannot really outlaw anything appearing in an identifier
+		#ok_first = dict.fromkeys("$ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_")
+		#ok_others = dict.fromkeys("$ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_1234567890")
+		#if name[0] not in ok_first:
+		#	return False
+		#return all(c in ok_others for c in name[1:])
+
+class RoT_Data:
+	def __init__(self,rot_pointer,params):
+		if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
+			self.sys_params = params
+			self.valobj = rot_pointer
+			self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
+			self.instanceStart = Utilities.read_child_of(self.valobj,4,self.sys_params.uint32_t)
+			self.instanceSize = Utilities.read_child_of(self.valobj,8,self.sys_params.uint32_t)
+			if self.sys_params.lp64:
+				self.reserved = Utilities.read_child_of(self.valobj,12,self.sys_params.uint32_t)
+				offset = 16
+			else:
+				self.reserved = 0
+				offset = 12
+			self.ivarLayoutPtr = Utilities.read_child_of(self.valobj,offset,self.sys_params.addr_ptr_type)
+			offset = offset + self.sys_params.pointer_size
+			self.namePointer = Utilities.read_child_of(self.valobj,offset,self.sys_params.addr_ptr_type)
+			self.check_valid()
+		else:
+			self.valid = False
+		if self.valid:
+			self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
+			if not(Utilities.is_valid_identifier(self.name)):
+				self.valid = False
+
+	# perform sanity checks on the contents of this class_rw_t
+	def check_valid(self):
+		self.valid = True
+		# misaligned pointers seem to be possible for this field
+		#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=False)):
+		#	self.valid = False
+		#	pass
+
+	def __str__(self):
+		return 'flags = ' + str(self.flags) + "\n" + \
+		 "instanceStart = " + hex(self.instanceStart) + "\n" + \
+		 "instanceSize = " + hex(self.instanceSize) + "\n" + \
+		 "reserved = " + hex(self.reserved) + "\n" + \
+		 "ivarLayoutPtr = " + hex(self.ivarLayoutPtr) + "\n" + \
+		 "namePointer = " + hex(self.namePointer) + " --> " + self.name
+
+	def is_valid(self):
+		return self.valid
+
+
+class RwT_Data:
+	def __init__(self,rwt_pointer,params):
+		if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
+			self.sys_params = params
+			self.valobj = rwt_pointer
+			self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
+			self.version = Utilities.read_child_of(self.valobj,4,self.sys_params.uint32_t)
+			self.roPointer = Utilities.read_child_of(self.valobj,8,self.sys_params.addr_ptr_type)
+			self.check_valid()
+		else:
+			self.valid = False
+		if self.valid:
+			self.rot = self.valobj.CreateValueFromAddress("rot",self.roPointer,self.sys_params.addr_ptr_type).AddressOf()
+			self.data = RoT_Data(self.rot,self.sys_params)
+
+	# perform sanity checks on the contents of this class_rw_t
+	def check_valid(self):
+		self.valid = True
+		if not(Utilities.is_valid_pointer(self.roPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+
+	def __str__(self):
+		return 'flags = ' + str(self.flags) + "\n" + \
+		 "version = " + hex(self.version) + "\n" + \
+		 "roPointer = " + hex(self.roPointer)
+
+	def is_valid(self):
+		if self.valid:
+			return self.data.is_valid()
+		return False
+
+class Class_Data_V2:
+	def __init__(self,isa_pointer,params):
+		if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
+			self.sys_params = params
+			self.valobj = isa_pointer
+			self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.addr_ptr_type)
+			self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.cachePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.vtablePointer = Utilities.read_child_of(self.valobj,3*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.dataPointer = Utilities.read_child_of(self.valobj,4*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.check_valid()
+		else:
+			self.valid = False
+		if self.valid:
+			self.rwt = self.valobj.CreateValueFromAddress("rwt",self.dataPointer,self.sys_params.addr_ptr_type).AddressOf()
+			self.data = RwT_Data(self.rwt,self.sys_params)
+
+	# perform sanity checks on the contents of this class_t
+	def check_valid(self):
+		self.valid = True
+		if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+			return
+		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			# NULL is a valid value for superclass (it means we have reached NSObject)
+			if self.superclassIsaPointer != 0:
+				self.valid = False
+				return
+		if not(Utilities.is_valid_pointer(self.cachePointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+			return
+		if not(Utilities.is_valid_pointer(self.vtablePointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+			return
+		if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+			return
+		if not(Utilities.is_allowed_pointer(self.isaPointer)):
+			self.valid = False
+			return
+		if not(Utilities.is_allowed_pointer(self.superclassIsaPointer)):
+			# NULL is a valid value for superclass (it means we have reached NSObject)
+			if self.superclassIsaPointer != 0:
+				self.valid = False
+				return
+		if not(Utilities.is_allowed_pointer(self.cachePointer)):
+			self.valid = False
+			return
+		if not(Utilities.is_allowed_pointer(self.vtablePointer)):
+			self.valid = False
+			return
+		if not(Utilities.is_allowed_pointer(self.dataPointer)):
+			self.valid = False
+			return
+
+	def is_kvo(self):
+		if self.is_valid():
+			if self.data.data.name.startswith("NSKVONotify"):
+				return True
+		else:
+			return None
+
+	def get_superclass(self):
+		if self.is_valid():
+			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
+				self.sys_params.pointer_size,
+				self.sys_params.addr_ptr_type)
+			return Class_Data_V2(parent_isa_pointer,self.sys_params)
+		else:
+			return None
+
+	def class_name(self):
+		if self.is_valid():
+			return self.data.data.name
+		else:
+			return None
+
+	def is_valid(self):
+		if self.valid:
+			return self.data.is_valid()
+		return False
+
+	def __str__(self):
+		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
+		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
+		 "cachePointer = " + hex(self.cachePointer) + "\n" + \
+		 "vtablePointer = " + hex(self.vtablePointer) + "\n" + \
+		 "data = " + hex(self.dataPointer)
+
+	def is_tagged(self):
+		return False
+
+# runtime v1 is much less intricate than v2 and stores relevant information directly in the class_t object
+# idea for improvement: read additional information just to check for faulty pointers (not too worried about it
+# since v1 is only used for 32bit desktop development)
+class Class_Data_V1:
+	def __init__(self,isa_pointer,params):
+		if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
+			self.sys_params = params
+			self.valobj = isa_pointer
+			self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.addr_ptr_type)
+			self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.namePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.addr_ptr_type)
+			self.check_valid()
+		else:
+			self.valid = False
+		if self.valid:
+			self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
+			if not(Utilities.is_valid_identifier(self.name)):
+				self.valid = False
+
+	# perform sanity checks on the contents of this class_t
+	def check_valid(self):
+		self.valid = True
+		if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			self.valid = False
+			return
+		if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=False)):
+			# NULL is a valid value for superclass (it means we have reached NSObject)
+			if self.superclassIsaPointer != 0:
+				self.valid = False
+				return
+		#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=False)):
+		#	self.valid = False
+		#	return
+
+	def is_kvo(self):
+		if self.is_valid():
+			if self.name.startswith("NSKVONotify"):
+				return True
+		else:
+			return None
+
+	def get_superclass(self):
+		if self.is_valid():
+			parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
+				self.sys_params.pointer_size,
+				self.sys_params.addr_ptr_type)
+			return Class_Data_V1(parent_isa_pointer,self.sys_params)
+		else:
+			return None
+
+	def class_name(self):
+		if self.is_valid():
+			return self.name
+		else:
+			return None
+
+	def is_valid(self):
+		return self.valid
+
+	def __str__(self):
+		return 'isaPointer = ' + hex(self.isaPointer) + "\n" + \
+		 "superclassIsaPointer = " + hex(self.superclassIsaPointer) + "\n" + \
+		 "namePointer = " + hex(self.namePointer) + " --> " + self.name
+
+	def is_tagged(self):
+		return False
+
+class TaggedClass_Data:
+	def __init__(self,pointer,params):
+		self.valid = True
+		self.name = None
+		self.sys_params = params
+		self.valobj = pointer
+		self.val = (pointer & ~0x0000000000000000FF) >> 8
+		self.class_bits = (pointer & 0xE) >> 1
+		self.i_bits = (pointer & 0xF0) >> 4
+		# ignoring the LSB, NSNumber gets marked
+		# as 3 on Zin and as 1 on Lion - I can either make
+		# a difference or accept false positives
+		# ToT LLDB + some knowledge of framework versioning
+		# would let me do the right thing - for now I just
+		# act dumb and accept false positives
+		if self.class_bits == 0 or \
+		   self.class_bits == 5 or \
+		   self.class_bits == 7 or \
+		   self.class_bits == 9:
+			self.valid = False
+			return
+		elif self.class_bits == 3 or self.class_bits == 1:
+			self.name = 'NSNumber'
+		elif self.class_bits == 11:
+			self.name = 'NSManagedObject'
+		elif self.class_bits == 13:
+			self.name = 'NSDate'
+		elif self.class_bits == 15:
+			self.name = 'NSDateTS' # not sure what this is
+		else:
+			self.valid = False
+
+	def is_valid(self):
+		return self.valid
+
+	def class_name(self):
+		if self.is_valid():
+			return self.name
+		else:
+			return None
+
+	def value(self):
+		return self.val if self.is_valid() else None
+
+	def info_bits(self):
+		return self.i_bits if self.is_valid() else None
+
+	def is_kvo(self):
+		return False
+
+	# we would need to go around looking for the superclass or ask the runtime
+	# for now, we seem not to require support for this operation so we will merrily
+	# pretend to be at a root point in the hierarchy
+	def get_superclass(self):
+		return None
+
+	# anything that is handled here is tagged
+	def is_tagged(self):
+		return True
+
+class InvalidClass_Data:
+	def __init__(self):
+		pass
+	def is_valid(self):
+		return False
+
+runtime_version = cache.Cache()
+
+class SystemParameters:
+	def __init__(self,valobj):
+		self.adjust_for_architecture(valobj)
+
+	def adjust_for_architecture(self,valobj):
+		self.process = valobj.GetTarget().GetProcess()
+		self.lp64 = (self.process.GetAddressByteSize() == 8)
+		self.is_little = (self.process.GetByteOrder() == lldb.eByteOrderLittle)
+		self.pointer_size = self.process.GetAddressByteSize()
+		self.addr_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+		self.addr_ptr_type = self.addr_type.GetPointerType()
+		self.uint32_t = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
+		global runtime_version
+		pid = self.process.GetProcessID()
+		if runtime_version.look_for_key(pid) == None:
+			self.runtime_version = runtime_version.get_value(pid)
+		else:
+			self.runtime_version = ObjCRuntime.runtime_version(self.process)
+			runtime_version.add_item(pid,self.runtime_version)
+
+isa_cache = cache.Cache()
+
+class ObjCRuntime:
+
+	# the ObjC runtime has no explicit "version" field that we can use
+	# instead, we discriminate v1 from v2 by looking for the presence
+	# of a well-known section only present in v1
+	@staticmethod
+	def runtime_version(process):
+		if process.IsValid() == False:
+			return None
+		target = process.GetTarget()
+		num_modules = target.GetNumModules()
+		module_objc = None
+		for idx in range(num_modules):
+			module = target.GetModuleAtIndex(idx)
+			if module.GetFileSpec().GetFilename() == 'libobjc.A.dylib':
+				module_objc = module
+				break
+		if module_objc == None or module_objc.IsValid() == False:
+			return None
+		num_sections = module.GetNumSections()
+		section_objc = None
+		for idx in range(num_sections):
+			section = module.GetSectionAtIndex(idx)
+			if section.GetName() == '__OBJC':
+				section_objc = section
+				break
+		if section_objc != None and section_objc.IsValid():
+			return 1
+		return 2
+
+	def __init__(self,valobj):
+		self.valobj = valobj
+		self.adjust_for_architecture()
+		self.sys_params = SystemParameters(self.valobj)
+
+	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()
+
+# an ObjC pointer can either be tagged or must be aligned
+	def is_tagged(self):
+		if self.valobj is None:
+			return False
+		return (Utilities.is_valid_pointer(self.valobj.GetValueAsUnsigned(),self.pointer_size, allow_tagged=True) and not(Utilities.is_valid_pointer(self.valobj.GetValueAsUnsigned(),self.pointer_size, allow_tagged=False)))
+
+	def is_valid(self):
+		if self.valobj is None:
+			return False
+		if self.valobj.IsInScope() == False:
+			return False
+		return Utilities.is_valid_pointer(self.valobj.GetValueAsUnsigned(),self.pointer_size, allow_tagged=True)
+
+	def read_isa(self):
+		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.GetValueAsUnsigned(1) == 1:
+			return None;
+		return isa_pointer
+
+	def read_class_data(self):
+		global isa_cache
+		if self.is_tagged():
+			# tagged pointers only exist in ObjC v2
+			if self.sys_params.runtime_version == 2:
+				# not every odd-valued pointer is actually tagged. most are just plain wrong
+				# we could try and predetect this before even creating a TaggedClass_Data object
+				# but unless performance requires it, this seems a cleaner way to tackle the task
+				tentative_tagged = TaggedClass_Data(self.valobj.GetValueAsUnsigned(0),self.sys_params)
+				return tentative_tagged if tentative_tagged.is_valid() else InvalidClass_Data()
+			else:
+				return InvalidClass_Data()
+		if self.is_valid() == False:
+			return InvalidClass_Data()
+		isa = self.read_isa()
+		if isa == None:
+			return InvalidClass_Data()
+		isa_value = isa.GetValueAsUnsigned(1)
+		if isa_value == 1:
+			return InvalidClass_Data()
+		data = isa_cache.get_value(isa_value,default=None)
+		if data != None:
+			return data
+		if self.sys_params.runtime_version == 2:
+			data = Class_Data_V2(isa,self.sys_params)
+		else:
+			data = Class_Data_V1(isa,self.sys_params)
+		if data == None:
+			return InvalidClass_Data()
+		if data.is_valid():
+			isa_cache.add_item(isa_value,data,ok_to_replace=True)
+		return data





More information about the lldb-commits mailing list