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 CFBinaryHeap
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 CFBinaryHeap, so they need not
# obey the interface specification for synthetic children providers
class CFBinaryHeapRef_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();
# 8 bytes on i386
# 16 bytes on x64
# most probably 2 pointers
def offset(self):
return 2 * self.sys_params.pointer_size
Enrico Granata
committed
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 CFBinaryHeapUnknown_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)CFBinaryHeapGetCount(" + stream.GetData() + " )");
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not CFBinaryHeap>'
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 = class_data.class_name()
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
if class_data.is_cftype():
Enrico Granata
committed
# 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():
valobj_type = valobj_type.GetPointeeType()
if valobj_type.IsValid():
actual_name = valobj_type.GetName()
if actual_name == '__CFBinaryHeap':
wrapper = CFBinaryHeapRef_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
return wrapper
wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granata
committed
return wrapper;
def CFBinaryHeap_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 CFBinaryHeap>'
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
return '@"1 item"'
Enrico Granata
committed
else:
Enrico Granata
committed
summary = '@"' + str(summary) + ' items"'
Enrico Granata
committed
return summary
return 'Summary Unavailable'
Enrico Granata
committed
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")