Newer
Older
"""
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.
"""
Enrico Granata
committed
# summary provider for CFBag
import lldb
import ctypes
import objc_runtime
import metrics
Enrico Granata
committed
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):
pass
Enrico Granata
committed
def __init__(self, valobj, params):
Enrico Granata
committed
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)
Enrico Granata
committed
self.update();
def update(self):
Enrico Granata
committed
self.adjust_for_architecture();
# 12 bytes on i386
# 20 bytes on x64
# most probably 2 pointers and 4 bytes of data
def offset(self):
if self.sys_params.is_64_bit:
Enrico Granata
committed
return 20
else:
return 12
def length(self):
Enrico Granata
committed
size = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
Enrico Granata
committed
return size.GetValueAsUnsigned(0)
class CFBagUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
Enrico Granata
committed
def __init__(self, valobj, params):
Enrico Granata
committed
self.valobj = valobj;
self.sys_params = params
self.update();
Enrico Granata
committed
def update(self):
Enrico Granata
committed
self.adjust_for_architecture();
def length(self):
Enrico Granata
committed
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return "<variable is not CFBag>"
Enrico Granata
committed
def GetSummary_Impl(valobj):
Enrico Granata
committed
global statistics
class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
if wrapper:
return wrapper
Enrico Granata
committed
name_string = class_data.class_name()
actual_name = name_string
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
if class_data.is_cftype():
Enrico Granata
committed
# 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():
valobj_type = valobj_type.GetPointeeType()
if valobj_type.IsValid():
actual_name = valobj_type.GetName()
if actual_name == '__CFBag' or \
actual_name == 'const struct __CFBag':
wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
return wrapper
wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + actual_name)
Enrico Granata
committed
return wrapper;
def CFBag_SummaryProvider (valobj,dict):
Enrico Granata
committed
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,objc_runtime.SpecialSituation_Description):
return provider.message()
Enrico Granata
committed
try:
summary = provider.length();
except:
summary = None
logger >> "summary got from provider: " + str(summary)
Enrico Granata
committed
# 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 = '<variable is not CFBag>'
elif isinstance(summary,basestring):
pass
Enrico Granata
committed
else:
if provider.sys_params.is_64_bit:
Enrico Granata
committed
summary = summary & ~0x1fff000000000000
Enrico Granata
committed
if summary == 1:
Enrico Granata
committed
summary = '@"1 value"'
Enrico Granata
committed
else:
Enrico Granata
committed
summary = '@"' + str(summary) + ' values"'
Enrico Granata
committed
return summary
return 'Summary Unavailable'
Enrico Granata
committed
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")