"""
LLDB AppKit formatters
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
import ctypes
import lldb.runtime.objc.objc_runtime
import lldb.formatters.metrics
import CFBag
import lldb.formatters.Logger
statistics = lldb.formatters.metrics.Metrics()
statistics.add_metric('invalid_isa')
statistics.add_metric('invalid_pointer')
statistics.add_metric('unknown_class')
statistics.add_metric('code_notrun')
class NSCFSet_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
def offset(self):
logger = lldb.formatters.Logger.Logger()
if self.sys_params.is_64_bit:
return 20
else:
return 12
def count(self):
logger = lldb.formatters.Logger.Logger()
vcount = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
return vcount.GetValueAsUnsigned(0)
class NSSetUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.sys_params = params
self.update();
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
def count(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(int)[" + stream.GetData() + " count]"
num_children_vo = self.valobj.CreateValueFromExpression("count",expr)
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not NSSet>'
class NSSetI_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
def offset(self):
logger = lldb.formatters.Logger.Logger()
return self.sys_params.pointer_size
def count(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
value = num_children_vo.GetValueAsUnsigned(0)
if value != None:
if self.sys_params.is_64_bit:
value = value & ~0xFF00000000000000
else:
value = value & ~0xFF000000
return value
class NSSetM_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
def offset(self):
logger = lldb.formatters.Logger.Logger()
return self.sys_params.pointer_size
def count(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
return num_children_vo.GetValueAsUnsigned(0)
class NSCountedSet_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.sys_params = params
if not (self.sys_params.types_cache.voidptr):
self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
self.update();
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
def offset(self):
logger = lldb.formatters.Logger.Logger()
return self.sys_params.pointer_size
def count(self):
logger = lldb.formatters.Logger.Logger()
cfbag_vo = self.valobj.CreateChildAtOffset("bag_impl",
self.offset(),
self.sys_params.types_cache.voidptr)
return CFBag.CFBagRef_SummaryProvider(cfbag_vo,self.sys_params).length()
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
if wrapper:
return wrapper
name_string = class_data.class_name()
logger >> "class name is: " + str(name_string)
if name_string == '__NSCFSet':
wrapper = NSCFSet_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
elif name_string == '__NSSetI':
wrapper = NSSetI_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
elif name_string == '__NSSetM':
wrapper = NSSetM_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
elif name_string == 'NSCountedSet':
wrapper = NSCountedSet_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
else:
wrapper = NSSetUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
def NSSet_SummaryProvider (valobj,dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
try:
summary = provider.count();
except:
summary = None
if summary == None:
summary = '<variable is not NSSet>'
if isinstance(summary, basestring):
return summary
else:
summary = str(summary) + (' objects' if summary != 1 else ' object')
return summary
return 'Summary Unavailable'
def NSSet_SummaryProvider2 (valobj,dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.count();
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
summary = '<variable is not CFSet>'
if isinstance(summary, basestring):
return summary
else:
if provider.sys_params.is_64_bit:
summary = summary & ~0x1fff000000000000
summary = '@"' + str(summary) + (' values"' if summary != 1 else ' value"')
return summary
return 'Summary Unavailable'
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")