forked from OSchip/llvm-project
Part 1 of a series of fixes meant to improve reliability and increase ease of bug fixing for data formatter issues.
We are introducing a new Logger class on the Python side. This has the same purpose, but is unrelated, to the C++ logging facility The Pythonic logging can be enabled by using the following scripting commands: (lldb) script Logger._lldb_formatters_debug_level = {0,1,2,...} 0 = no logging 1 = do log 2 = flush after logging each line - slower but safer 3 or more = each time a Logger is constructed, log the function that has created it more log levels may be added, each one being more log-active than the previous by default, the log output will come out on your screen, to direct it to a file: (lldb) script Logger._lldb_formatters_debug_filename = 'filename' that will make the output go to the file - set to None to disable the file output and get screen logging back Logging has been enabled for the C++ STL formatters and for Cocoa class NSData - more logging will follow synthetic children providers for classes list and map (both libstdcpp and libcxx) now have internal capping for safety reasons this will fix crashers where a malformed list or map would not ever meet our termination conditions to set the cap to a different value: (lldb) script {gnu_libstdcpp|libcxx}.{map|list}_capping_size = new_cap (by default, it is 255) you can optionally disable the loop detection algorithm for lists (lldb) script {gnu_libstdcpp|libcxx}.list_uses_loop_detector = False llvm-svn: 153676
This commit is contained in:
parent
751aac610a
commit
d50f18b1a0
|
@ -0,0 +1,122 @@
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import os.path
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
class NopLogger:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def write(self,data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class StdoutLogger:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def write(self,data):
|
||||||
|
print(data)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class FileLogger:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.file = None
|
||||||
|
try:
|
||||||
|
name = os.path.abspath(name)
|
||||||
|
self.file = open(name,'a')
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
self.file = open('formatters.log','a')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def write(self,data):
|
||||||
|
if self.file != None:
|
||||||
|
print(data,file=self.file)
|
||||||
|
else:
|
||||||
|
print(data)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
if self.file != None:
|
||||||
|
self.file.flush()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self.file != None:
|
||||||
|
self.file.close()
|
||||||
|
self.file = None
|
||||||
|
|
||||||
|
# to enable logging:
|
||||||
|
# define Logger._lldb_formatters_debug_level to any number greater than 0
|
||||||
|
# if you define it to any value greater than 1, the log will be automatically flushed after each write (slower but should make sure most of the stuff makes it to the log even if we crash)
|
||||||
|
# if you define it to any value greater than 2, the calling function's details will automatically be logged (even slower, but provides additional details)
|
||||||
|
# if you need the log to go to a file instead of on screen, define Logger._lldb_formatters_debug_filename to a valid filename
|
||||||
|
class Logger:
|
||||||
|
def __init__(self,autoflush=False,logcaller=False):
|
||||||
|
global _lldb_formatters_debug_level
|
||||||
|
global _lldb_formatters_debug_filename
|
||||||
|
self.autoflush = autoflush
|
||||||
|
want_log = False
|
||||||
|
try:
|
||||||
|
want_log = (_lldb_formatters_debug_level > 0)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if not (want_log):
|
||||||
|
self.impl = NopLogger()
|
||||||
|
return
|
||||||
|
want_file = False
|
||||||
|
try:
|
||||||
|
want_file = (_lldb_formatters_debug_filename != None and _lldb_formatters_debug_filename != '' and _lldb_formatters_debug_filename != 0)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if want_file:
|
||||||
|
self.impl = FileLogger(_lldb_formatters_debug_filename)
|
||||||
|
else:
|
||||||
|
self.impl = StdoutLogger()
|
||||||
|
try:
|
||||||
|
self.autoflush = (_lldb_formatters_debug_level > 1)
|
||||||
|
except:
|
||||||
|
self.autoflush = autoflush
|
||||||
|
want_caller_info = False
|
||||||
|
try:
|
||||||
|
want_caller_info = (_lldb_formatters_debug_level > 2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if want_caller_info:
|
||||||
|
self._log_caller()
|
||||||
|
|
||||||
|
def _log_caller(self):
|
||||||
|
caller = inspect.stack()[2]
|
||||||
|
try:
|
||||||
|
if caller != None and len(caller) > 3:
|
||||||
|
self.write('Logging from function ' + str(caller))
|
||||||
|
else:
|
||||||
|
self.write('Caller info not available - Required caller logging not possible')
|
||||||
|
finally:
|
||||||
|
del caller # needed per Python docs to avoid keeping objects alive longer than we care
|
||||||
|
|
||||||
|
def write(self,data):
|
||||||
|
self.impl.write(data)
|
||||||
|
if self.autoflush:
|
||||||
|
self.flush()
|
||||||
|
|
||||||
|
def __rshift__(self,data):
|
||||||
|
self.write(data)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
self.impl.flush()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.impl.close()
|
||||||
|
|
|
@ -10,6 +10,7 @@ import lldb
|
||||||
import ctypes
|
import ctypes
|
||||||
import objc_runtime
|
import objc_runtime
|
||||||
import metrics
|
import metrics
|
||||||
|
import Logger
|
||||||
|
|
||||||
statistics = metrics.Metrics()
|
statistics = metrics.Metrics()
|
||||||
statistics.add_metric('invalid_isa')
|
statistics.add_metric('invalid_isa')
|
||||||
|
@ -25,6 +26,8 @@ class NSConcreteData_SummaryProvider:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self, valobj, params):
|
def __init__(self, valobj, params):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSConcreteData_SummaryProvider __init__"
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
self.sys_params = params
|
self.sys_params = params
|
||||||
if not(self.sys_params.types_cache.NSUInteger):
|
if not(self.sys_params.types_cache.NSUInteger):
|
||||||
|
@ -46,9 +49,13 @@ class NSConcreteData_SummaryProvider:
|
||||||
return 2 * self.sys_params.pointer_size
|
return 2 * self.sys_params.pointer_size
|
||||||
|
|
||||||
def length(self):
|
def length(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSConcreteData_SummaryProvider length"
|
||||||
size = self.valobj.CreateChildAtOffset("count",
|
size = self.valobj.CreateChildAtOffset("count",
|
||||||
self.offset(),
|
self.offset(),
|
||||||
self.sys_params.types_cache.NSUInteger)
|
self.sys_params.types_cache.NSUInteger)
|
||||||
|
logger >> str(size)
|
||||||
|
logger >> str(size.GetValueAsUnsigned(0))
|
||||||
return size.GetValueAsUnsigned(0)
|
return size.GetValueAsUnsigned(0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,6 +64,8 @@ class NSDataUnknown_SummaryProvider:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self, valobj, params):
|
def __init__(self, valobj, params):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSDataUnknown_SummaryProvider __init__"
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
self.sys_params = params
|
self.sys_params = params
|
||||||
self.update();
|
self.update();
|
||||||
|
@ -65,21 +74,31 @@ class NSDataUnknown_SummaryProvider:
|
||||||
self.adjust_for_architecture();
|
self.adjust_for_architecture();
|
||||||
|
|
||||||
def length(self):
|
def length(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSDataUnknown_SummaryProvider length"
|
||||||
stream = lldb.SBStream()
|
stream = lldb.SBStream()
|
||||||
self.valobj.GetExpressionPath(stream)
|
self.valobj.GetExpressionPath(stream)
|
||||||
|
logger >> stream.GetData()
|
||||||
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " length]");
|
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " length]");
|
||||||
|
logger >> "still in after expression: " + str(num_children_vo)
|
||||||
if num_children_vo.IsValid():
|
if num_children_vo.IsValid():
|
||||||
|
logger >> "wow - expr output is valid: " + str(num_children_vo.GetValueAsUnsigned())
|
||||||
return num_children_vo.GetValueAsUnsigned(0)
|
return num_children_vo.GetValueAsUnsigned(0)
|
||||||
|
logger >> "invalid expr output - too bad"
|
||||||
return '<variable is not NSData>'
|
return '<variable is not NSData>'
|
||||||
|
|
||||||
|
|
||||||
def GetSummary_Impl(valobj):
|
def GetSummary_Impl(valobj):
|
||||||
global statistics
|
global statistics
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSData GetSummary_Impl"
|
||||||
class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
|
class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
|
||||||
if wrapper:
|
if wrapper:
|
||||||
|
logger >> "got a wrapper summary - using it"
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
name_string = class_data.class_name()
|
name_string = class_data.class_name()
|
||||||
|
logger >> "class name: " + name_string
|
||||||
if name_string == 'NSConcreteData' or \
|
if name_string == 'NSConcreteData' or \
|
||||||
name_string == 'NSConcreteMutableData' or \
|
name_string == 'NSConcreteMutableData' or \
|
||||||
name_string == '__NSCFData':
|
name_string == '__NSCFData':
|
||||||
|
@ -91,12 +110,16 @@ def GetSummary_Impl(valobj):
|
||||||
return wrapper;
|
return wrapper;
|
||||||
|
|
||||||
def NSData_SummaryProvider (valobj,dict):
|
def NSData_SummaryProvider (valobj,dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSData_SummaryProvider"
|
||||||
provider = GetSummary_Impl(valobj);
|
provider = GetSummary_Impl(valobj);
|
||||||
|
logger >> "found a summary provider, it is: " + str(provider)
|
||||||
if provider != None:
|
if provider != None:
|
||||||
try:
|
try:
|
||||||
summary = provider.length();
|
summary = provider.length();
|
||||||
except:
|
except:
|
||||||
summary = None
|
summary = None
|
||||||
|
logger >> "got a summary: it is " + str(summary)
|
||||||
if summary == None:
|
if summary == None:
|
||||||
summary = '<variable is not NSData>'
|
summary = '<variable is not NSData>'
|
||||||
elif isinstance(summary,basestring):
|
elif isinstance(summary,basestring):
|
||||||
|
@ -110,7 +133,10 @@ def NSData_SummaryProvider (valobj,dict):
|
||||||
return 'Summary Unavailable'
|
return 'Summary Unavailable'
|
||||||
|
|
||||||
def NSData_SummaryProvider2 (valobj,dict):
|
def NSData_SummaryProvider2 (valobj,dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "NSData_SummaryProvider2"
|
||||||
provider = GetSummary_Impl(valobj);
|
provider = GetSummary_Impl(valobj);
|
||||||
|
logger >> "found a summary provider, it is: " + str(provider)
|
||||||
if provider != None:
|
if provider != None:
|
||||||
if isinstance(provider,objc_runtime.SpecialSituation_Description):
|
if isinstance(provider,objc_runtime.SpecialSituation_Description):
|
||||||
return provider.message()
|
return provider.message()
|
||||||
|
@ -118,6 +144,7 @@ def NSData_SummaryProvider2 (valobj,dict):
|
||||||
summary = provider.length();
|
summary = provider.length();
|
||||||
except:
|
except:
|
||||||
summary = None
|
summary = None
|
||||||
|
logger >> "got a summary: it is " + str(summary)
|
||||||
if summary == None:
|
if summary == None:
|
||||||
summary = '<variable is not CFData>'
|
summary = '<variable is not CFData>'
|
||||||
elif isinstance(summary,basestring):
|
elif isinstance(summary,basestring):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import re
|
import re
|
||||||
|
import Logger
|
||||||
|
|
||||||
# C++ STL formatters for LLDB
|
# C++ STL formatters for LLDB
|
||||||
# These formatters are based upon the version of the GNU libstdc++
|
# These formatters are based upon the version of the GNU libstdc++
|
||||||
|
@ -9,20 +10,29 @@ import re
|
||||||
class StdListSynthProvider:
|
class StdListSynthProvider:
|
||||||
|
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj
|
self.valobj = valobj
|
||||||
|
|
||||||
def next_node(self,node):
|
def next_node(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetChildMemberWithName('_M_next')
|
return node.GetChildMemberWithName('_M_next')
|
||||||
|
|
||||||
def is_valid(self,node):
|
def is_valid(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.value(self.next_node(node)) != self.node_address
|
return self.value(self.next_node(node)) != self.node_address
|
||||||
|
|
||||||
def value(self,node):
|
def value(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetValueAsUnsigned()
|
return node.GetValueAsUnsigned()
|
||||||
|
|
||||||
# Floyd's cyle-finding algorithm
|
# Floyd's cyle-finding algorithm
|
||||||
# try to detect if this list has a loop
|
# try to detect if this list has a loop
|
||||||
def has_loop(self):
|
def has_loop(self):
|
||||||
|
global _list_uses_loop_detector
|
||||||
|
logger = Logger.Logger()
|
||||||
|
if _list_uses_loop_detector == False:
|
||||||
|
logger >> "Asked not to use loop detection"
|
||||||
|
return False
|
||||||
slow = self.next
|
slow = self.next
|
||||||
fast1 = self.next
|
fast1 = self.next
|
||||||
fast2 = self.next
|
fast2 = self.next
|
||||||
|
@ -36,11 +46,17 @@ class StdListSynthProvider:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
global _list_capping_size
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.count == None:
|
if self.count == None:
|
||||||
self.count = self.num_children_impl()
|
self.count = self.num_children_impl()
|
||||||
|
if self.count > _list_capping_size:
|
||||||
|
self.count = _list_capping_size
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
def num_children_impl(self):
|
def num_children_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
global _list_capping_size
|
||||||
try:
|
try:
|
||||||
next_val = self.next.GetValueAsUnsigned(0)
|
next_val = self.next.GetValueAsUnsigned(0)
|
||||||
prev_val = self.prev.GetValueAsUnsigned(0)
|
prev_val = self.prev.GetValueAsUnsigned(0)
|
||||||
|
@ -58,17 +74,21 @@ class StdListSynthProvider:
|
||||||
while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
|
while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
|
||||||
size = size + 1
|
size = size + 1
|
||||||
current = current.GetChildMemberWithName('_M_next')
|
current = current.GetChildMemberWithName('_M_next')
|
||||||
|
if size > _list_capping_size:
|
||||||
|
return _list_capping_size
|
||||||
return (size - 1)
|
return (size - 1)
|
||||||
except:
|
except:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None;
|
return None;
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
|
@ -84,6 +104,7 @@ class StdListSynthProvider:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def extract_type(self):
|
def extract_type(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
list_type = self.valobj.GetType().GetUnqualifiedType()
|
list_type = self.valobj.GetType().GetUnqualifiedType()
|
||||||
if list_type.IsReferenceType():
|
if list_type.IsReferenceType():
|
||||||
list_type = list_type.GetDereferencedType()
|
list_type = list_type.GetDereferencedType()
|
||||||
|
@ -94,6 +115,7 @@ class StdListSynthProvider:
|
||||||
return data_type
|
return data_type
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||||
node = impl.GetChildMemberWithName('_M_node')
|
node = impl.GetChildMemberWithName('_M_node')
|
||||||
|
@ -109,19 +131,23 @@ class StdListSynthProvider:
|
||||||
class StdVectorSynthProvider:
|
class StdVectorSynthProvider:
|
||||||
|
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.count == None:
|
if self.count == None:
|
||||||
self.count = self.num_children_impl()
|
self.count = self.num_children_impl()
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
def is_valid_pointer(ptr,process):
|
def is_valid_pointer(ptr,process):
|
||||||
|
logger = Logger.Logger()
|
||||||
error = lldb.SBError()
|
error = lldb.SBError()
|
||||||
process.ReadMemory(ptr,1,error)
|
process.ReadMemory(ptr,1,error)
|
||||||
return False if error.Fail() else True
|
return False if error.Fail() else True
|
||||||
|
|
||||||
def num_children_impl(self):
|
def num_children_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
start_val = self.start.GetValueAsUnsigned(0)
|
start_val = self.start.GetValueAsUnsigned(0)
|
||||||
finish_val = self.finish.GetValueAsUnsigned(0)
|
finish_val = self.finish.GetValueAsUnsigned(0)
|
||||||
|
@ -156,12 +182,14 @@ class StdVectorSynthProvider:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None;
|
return None;
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
|
@ -173,6 +201,7 @@ class StdVectorSynthProvider:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||||
self.start = impl.GetChildMemberWithName('_M_start')
|
self.start = impl.GetChildMemberWithName('_M_start')
|
||||||
|
@ -192,7 +221,9 @@ class StdVectorSynthProvider:
|
||||||
class StdMapSynthProvider:
|
class StdMapSynthProvider:
|
||||||
|
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
|
logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
|
||||||
|
|
||||||
# we need this function as a temporary workaround for rdar://problem/10801549
|
# we need this function as a temporary workaround for rdar://problem/10801549
|
||||||
# which prevents us from extracting the std::pair<K,V> SBType out of the template
|
# which prevents us from extracting the std::pair<K,V> SBType out of the template
|
||||||
|
@ -202,6 +233,7 @@ class StdMapSynthProvider:
|
||||||
# to replace the longer versions of std::string with the shorter one in order to be able
|
# to replace the longer versions of std::string with the shorter one in order to be able
|
||||||
# to find the type name
|
# to find the type name
|
||||||
def fixup_class_name(self, class_name):
|
def fixup_class_name(self, class_name):
|
||||||
|
logger = Logger.Logger()
|
||||||
if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||||
return 'std::basic_string<char>',True
|
return 'std::basic_string<char>',True
|
||||||
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||||
|
@ -213,7 +245,12 @@ class StdMapSynthProvider:
|
||||||
return class_name,False
|
return class_name,False
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
|
self.count = None
|
||||||
|
# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
|
||||||
|
# if this gets set to True, then we will merrily return None for any child from that moment on
|
||||||
|
self.garbage = False
|
||||||
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
|
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
|
||||||
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
|
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
|
||||||
self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
|
self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
|
||||||
|
@ -254,25 +291,43 @@ class StdMapSynthProvider:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
global _map_capping_size
|
||||||
|
logger = Logger.Logger()
|
||||||
|
if self.count == None:
|
||||||
|
self.count = self.num_children_impl()
|
||||||
|
if self.count > _map_capping_size:
|
||||||
|
self.count = _map_capping_size
|
||||||
|
return self.count
|
||||||
|
|
||||||
|
def num_children_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
root_ptr_val = self.node_ptr_value(self.Mroot)
|
root_ptr_val = self.node_ptr_value(self.Mroot)
|
||||||
if root_ptr_val == 0:
|
if root_ptr_val == 0:
|
||||||
return 0;
|
return 0;
|
||||||
return self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0)
|
count = self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0)
|
||||||
|
logger >> "I have " + str(count) + " children available"
|
||||||
|
return count
|
||||||
except:
|
except:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
logger >> "Being asked to fetch child[" + str(index) + "]"
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None
|
return None
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
return None;
|
return None;
|
||||||
|
if self.garbage:
|
||||||
|
logger >> "Returning None since we are a garbage tree"
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
offset = index
|
offset = index
|
||||||
current = self.left(self.Mheader);
|
current = self.left(self.Mheader);
|
||||||
|
@ -286,31 +341,53 @@ class StdMapSynthProvider:
|
||||||
|
|
||||||
# utility functions
|
# utility functions
|
||||||
def node_ptr_value(self,node):
|
def node_ptr_value(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetValueAsUnsigned(0)
|
return node.GetValueAsUnsigned(0)
|
||||||
|
|
||||||
def right(self,node):
|
def right(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetChildMemberWithName("_M_right");
|
return node.GetChildMemberWithName("_M_right");
|
||||||
|
|
||||||
def left(self,node):
|
def left(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetChildMemberWithName("_M_left");
|
return node.GetChildMemberWithName("_M_left");
|
||||||
|
|
||||||
def parent(self,node):
|
def parent(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetChildMemberWithName("_M_parent");
|
return node.GetChildMemberWithName("_M_parent");
|
||||||
|
|
||||||
# from libstdc++ implementation of iterator for rbtree
|
# from libstdc++ implementation of iterator for rbtree
|
||||||
def increment_node(self,node):
|
def increment_node(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
max_steps = self.num_children()
|
||||||
if self.node_ptr_value(self.right(node)) != 0:
|
if self.node_ptr_value(self.right(node)) != 0:
|
||||||
x = self.right(node);
|
x = self.right(node);
|
||||||
|
max_steps -= 1
|
||||||
while self.node_ptr_value(self.left(x)) != 0:
|
while self.node_ptr_value(self.left(x)) != 0:
|
||||||
x = self.left(x);
|
x = self.left(x);
|
||||||
|
max_steps -= 1
|
||||||
|
logger >> str(max_steps) + " more to go before giving up"
|
||||||
|
if max_steps <= 0:
|
||||||
|
self.garbage = True
|
||||||
|
return None
|
||||||
return x;
|
return x;
|
||||||
else:
|
else:
|
||||||
x = node;
|
x = node;
|
||||||
y = self.parent(x)
|
y = self.parent(x)
|
||||||
|
max_steps -= 1
|
||||||
while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
|
while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
|
||||||
x = y;
|
x = y;
|
||||||
y = self.parent(y);
|
y = self.parent(y);
|
||||||
|
max_steps -= 1
|
||||||
|
logger >> str(max_steps) + " more to go before giving up"
|
||||||
|
if max_steps <= 0:
|
||||||
|
self.garbage = True
|
||||||
|
return None
|
||||||
if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
|
if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
|
||||||
x = y;
|
x = y;
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
|
|
||||||
|
_map_capping_size = 255
|
||||||
|
_list_capping_size = 255
|
||||||
|
_list_uses_loop_detector = True
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import lldb
|
import lldb
|
||||||
|
import Logger
|
||||||
|
|
||||||
# libcxx STL formatters for LLDB
|
# libcxx STL formatters for LLDB
|
||||||
# These formatters are based upon the implementation of libc++ that
|
# These formatters are based upon the implementation of libc++ that
|
||||||
|
@ -27,6 +28,7 @@ def extract_short_size(value):
|
||||||
# no external significance - we access them by index since this saves a name lookup that would add
|
# no external significance - we access them by index since this saves a name lookup that would add
|
||||||
# no information for readers of the code, but when possible try to use meaningful variable names
|
# no information for readers of the code, but when possible try to use meaningful variable names
|
||||||
def stdstring_SummaryProvider(valobj,dict):
|
def stdstring_SummaryProvider(valobj,dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
r = valobj.GetChildAtIndex(0)
|
r = valobj.GetChildAtIndex(0)
|
||||||
B = r.GetChildAtIndex(0)
|
B = r.GetChildAtIndex(0)
|
||||||
first = B.GetChildAtIndex(0)
|
first = B.GetChildAtIndex(0)
|
||||||
|
@ -55,9 +57,11 @@ def stdstring_SummaryProvider(valobj,dict):
|
||||||
class stdvector_SynthProvider:
|
class stdvector_SynthProvider:
|
||||||
|
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
start_val = self.start.GetValueAsUnsigned(0)
|
start_val = self.start.GetValueAsUnsigned(0)
|
||||||
finish_val = self.finish.GetValueAsUnsigned(0)
|
finish_val = self.finish.GetValueAsUnsigned(0)
|
||||||
|
@ -85,12 +89,14 @@ class stdvector_SynthProvider:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None;
|
return None;
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
|
@ -102,6 +108,7 @@ class stdvector_SynthProvider:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
self.start = self.valobj.GetChildMemberWithName('__begin_')
|
self.start = self.valobj.GetChildMemberWithName('__begin_')
|
||||||
self.finish = self.valobj.GetChildMemberWithName('__end_')
|
self.finish = self.valobj.GetChildMemberWithName('__end_')
|
||||||
|
@ -121,21 +128,27 @@ def stdvector_SummaryProvider(valobj,dict):
|
||||||
class stdlist_entry:
|
class stdlist_entry:
|
||||||
|
|
||||||
def __init__(self,entry):
|
def __init__(self,entry):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
|
|
||||||
def _next_impl(self):
|
def _next_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return stdlist_entry(self.entry.GetChildMemberWithName('__next_'))
|
return stdlist_entry(self.entry.GetChildMemberWithName('__next_'))
|
||||||
|
|
||||||
def _prev_impl(self):
|
def _prev_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return stdlist_entry(self.entry.GetChildMemberWithName('__prev_'))
|
return stdlist_entry(self.entry.GetChildMemberWithName('__prev_'))
|
||||||
|
|
||||||
def _value_impl(self):
|
def _value_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.entry.GetValueAsUnsigned(0)
|
return self.entry.GetValueAsUnsigned(0)
|
||||||
|
|
||||||
def _isnull_impl(self):
|
def _isnull_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self._value_impl() == 0
|
return self._value_impl() == 0
|
||||||
|
|
||||||
def _sbvalue_impl(self):
|
def _sbvalue_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.entry
|
return self.entry
|
||||||
|
|
||||||
next = property(_next_impl,None)
|
next = property(_next_impl,None)
|
||||||
|
@ -146,17 +159,21 @@ class stdlist_entry:
|
||||||
class stdlist_iterator:
|
class stdlist_iterator:
|
||||||
|
|
||||||
def increment_node(self,node):
|
def increment_node(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
if node.is_null:
|
if node.is_null:
|
||||||
return None
|
return None
|
||||||
return node.next
|
return node.next
|
||||||
|
|
||||||
def __init__(self,node):
|
def __init__(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry
|
self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry
|
||||||
|
|
||||||
def value(self):
|
def value(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.node.sbvalue # and return the SBValue back on exit
|
return self.node.sbvalue # and return the SBValue back on exit
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
node = self.increment_node(self.node)
|
node = self.increment_node(self.node)
|
||||||
if node != None and node.sbvalue.IsValid() and not(node.is_null):
|
if node != None and node.sbvalue.IsValid() and not(node.is_null):
|
||||||
self.node = node
|
self.node = node
|
||||||
|
@ -165,6 +182,7 @@ class stdlist_iterator:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def advance(self,N):
|
def advance(self,N):
|
||||||
|
logger = Logger.Logger()
|
||||||
if N < 0:
|
if N < 0:
|
||||||
return None
|
return None
|
||||||
if N == 0:
|
if N == 0:
|
||||||
|
@ -179,17 +197,25 @@ class stdlist_iterator:
|
||||||
|
|
||||||
class stdlist_SynthProvider:
|
class stdlist_SynthProvider:
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj
|
self.valobj = valobj
|
||||||
|
|
||||||
def next_node(self,node):
|
def next_node(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetChildMemberWithName('__next_')
|
return node.GetChildMemberWithName('__next_')
|
||||||
|
|
||||||
def value(self,node):
|
def value(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
return node.GetValueAsUnsigned()
|
return node.GetValueAsUnsigned()
|
||||||
|
|
||||||
# Floyd's cyle-finding algorithm
|
# Floyd's cyle-finding algorithm
|
||||||
# try to detect if this list has a loop
|
# try to detect if this list has a loop
|
||||||
def has_loop(self):
|
def has_loop(self):
|
||||||
|
global _list_uses_loop_detector
|
||||||
|
logger = Logger.Logger()
|
||||||
|
if _list_uses_loop_detector == False:
|
||||||
|
logger >> "Asked not to use loop detection"
|
||||||
|
return False
|
||||||
slow = stdlist_entry(self.head)
|
slow = stdlist_entry(self.head)
|
||||||
fast1 = stdlist_entry(self.head)
|
fast1 = stdlist_entry(self.head)
|
||||||
fast2 = stdlist_entry(self.head)
|
fast2 = stdlist_entry(self.head)
|
||||||
|
@ -203,11 +229,17 @@ class stdlist_SynthProvider:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
global _list_capping_size
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.count == None:
|
if self.count == None:
|
||||||
self.count = self.num_children_impl()
|
self.count = self.num_children_impl()
|
||||||
|
if self.count > _list_capping_size:
|
||||||
|
self.count = _list_capping_size
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
def num_children_impl(self):
|
def num_children_impl(self):
|
||||||
|
global _list_capping_size
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
next_val = self.head.GetValueAsUnsigned(0)
|
next_val = self.head.GetValueAsUnsigned(0)
|
||||||
prev_val = self.tail.GetValueAsUnsigned(0)
|
prev_val = self.tail.GetValueAsUnsigned(0)
|
||||||
|
@ -225,17 +257,21 @@ class stdlist_SynthProvider:
|
||||||
while current.next.value != self.node_address:
|
while current.next.value != self.node_address:
|
||||||
size = size + 1
|
size = size + 1
|
||||||
current = current.next
|
current = current.next
|
||||||
|
if size > _list_capping_size:
|
||||||
|
return _list_capping_size
|
||||||
return (size - 1)
|
return (size - 1)
|
||||||
except:
|
except:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None;
|
return None;
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
|
@ -252,6 +288,7 @@ class stdlist_SynthProvider:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def extract_type(self):
|
def extract_type(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
list_type = self.valobj.GetType().GetUnqualifiedType()
|
list_type = self.valobj.GetType().GetUnqualifiedType()
|
||||||
if list_type.IsReferenceType():
|
if list_type.IsReferenceType():
|
||||||
list_type = list_type.GetDereferencedType()
|
list_type = list_type.GetDereferencedType()
|
||||||
|
@ -262,6 +299,7 @@ class stdlist_SynthProvider:
|
||||||
return data_type
|
return data_type
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
impl = self.valobj.GetChildMemberWithName('__end_')
|
impl = self.valobj.GetChildMemberWithName('__end_')
|
||||||
self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
|
self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
|
||||||
|
@ -281,24 +319,31 @@ def stdlist_SummaryProvider(valobj,dict):
|
||||||
# a tree node - this class makes the syntax in the actual iterator nicer to read and maintain
|
# a tree node - this class makes the syntax in the actual iterator nicer to read and maintain
|
||||||
class stdmap_iterator_node:
|
class stdmap_iterator_node:
|
||||||
def _left_impl(self):
|
def _left_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_"))
|
return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_"))
|
||||||
|
|
||||||
def _right_impl(self):
|
def _right_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_"))
|
return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_"))
|
||||||
|
|
||||||
def _parent_impl(self):
|
def _parent_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_"))
|
return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_"))
|
||||||
|
|
||||||
def _value_impl(self):
|
def _value_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.node.GetValueAsUnsigned(0)
|
return self.node.GetValueAsUnsigned(0)
|
||||||
|
|
||||||
def _sbvalue_impl(self):
|
def _sbvalue_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.node
|
return self.node
|
||||||
|
|
||||||
def _null_impl(self):
|
def _null_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.value == 0
|
return self.value == 0
|
||||||
|
|
||||||
def __init__(self,node):
|
def __init__(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.node = node
|
self.node = node
|
||||||
|
|
||||||
left = property(_left_impl,None)
|
left = property(_left_impl,None)
|
||||||
|
@ -312,13 +357,20 @@ class stdmap_iterator_node:
|
||||||
class stdmap_iterator:
|
class stdmap_iterator:
|
||||||
|
|
||||||
def tree_min(self,x):
|
def tree_min(self,x):
|
||||||
|
logger = Logger.Logger()
|
||||||
|
steps = 0
|
||||||
if x.is_null:
|
if x.is_null:
|
||||||
return None
|
return None
|
||||||
while (not x.left.is_null):
|
while (not x.left.is_null):
|
||||||
x = x.left
|
x = x.left
|
||||||
|
steps += 1
|
||||||
|
if steps > self.max_count:
|
||||||
|
logger >> "Returning None - we overflowed"
|
||||||
|
return None
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def tree_max(self,x):
|
def tree_max(self,x):
|
||||||
|
logger = Logger.Logger()
|
||||||
if x.is_null:
|
if x.is_null:
|
||||||
return None
|
return None
|
||||||
while (not x.right.is_null):
|
while (not x.right.is_null):
|
||||||
|
@ -326,26 +378,37 @@ class stdmap_iterator:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def tree_is_left_child(self,x):
|
def tree_is_left_child(self,x):
|
||||||
|
logger = Logger.Logger()
|
||||||
if x.is_null:
|
if x.is_null:
|
||||||
return None
|
return None
|
||||||
return True if x.value == x.parent.left.value else False
|
return True if x.value == x.parent.left.value else False
|
||||||
|
|
||||||
def increment_node(self,node):
|
def increment_node(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
if node.is_null:
|
if node.is_null:
|
||||||
return None
|
return None
|
||||||
if not node.right.is_null:
|
if not node.right.is_null:
|
||||||
return self.tree_min(node.right)
|
return self.tree_min(node.right)
|
||||||
|
steps = 0
|
||||||
while (not self.tree_is_left_child(node)):
|
while (not self.tree_is_left_child(node)):
|
||||||
|
steps += 1
|
||||||
|
if steps > self.max_count:
|
||||||
|
logger >> "Returning None - we overflowed"
|
||||||
|
return None
|
||||||
node = node.parent
|
node = node.parent
|
||||||
return node.parent
|
return node.parent
|
||||||
|
|
||||||
def __init__(self,node):
|
def __init__(self,node,max_count=0):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.node = stdmap_iterator_node(node) # we convert the SBValue to an internal node object on entry
|
self.node = stdmap_iterator_node(node) # we convert the SBValue to an internal node object on entry
|
||||||
|
self.max_count = max_count
|
||||||
|
|
||||||
def value(self):
|
def value(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
return self.node.sbvalue # and return the SBValue back on exit
|
return self.node.sbvalue # and return the SBValue back on exit
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
node = self.increment_node(self.node)
|
node = self.increment_node(self.node)
|
||||||
if node != None and node.sbvalue.IsValid() and not(node.is_null):
|
if node != None and node.sbvalue.IsValid() and not(node.is_null):
|
||||||
self.node = node
|
self.node = node
|
||||||
|
@ -354,6 +417,7 @@ class stdmap_iterator:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def advance(self,N):
|
def advance(self,N):
|
||||||
|
logger = Logger.Logger()
|
||||||
if N < 0:
|
if N < 0:
|
||||||
return None
|
return None
|
||||||
if N == 0:
|
if N == 0:
|
||||||
|
@ -361,18 +425,24 @@ class stdmap_iterator:
|
||||||
if N == 1:
|
if N == 1:
|
||||||
return self.next()
|
return self.next()
|
||||||
while N > 0:
|
while N > 0:
|
||||||
self.next()
|
if self.next() == None:
|
||||||
|
return None
|
||||||
N = N - 1
|
N = N - 1
|
||||||
return self.value()
|
return self.value()
|
||||||
|
|
||||||
class stdmap_SynthProvider:
|
class stdmap_SynthProvider:
|
||||||
|
|
||||||
def __init__(self, valobj, dict):
|
def __init__(self, valobj, dict):
|
||||||
|
logger = Logger.Logger()
|
||||||
self.valobj = valobj;
|
self.valobj = valobj;
|
||||||
self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
|
self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
|
# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
|
||||||
|
# if this gets set to True, then we will merrily return None for any child from that moment on
|
||||||
|
self.garbage = False
|
||||||
self.tree = self.valobj.GetChildMemberWithName('__tree_')
|
self.tree = self.valobj.GetChildMemberWithName('__tree_')
|
||||||
self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
|
self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
|
||||||
# this data is either lazily-calculated, or cannot be inferred at this moment
|
# this data is either lazily-calculated, or cannot be inferred at this moment
|
||||||
|
@ -385,17 +455,23 @@ class stdmap_SynthProvider:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def num_children(self):
|
def num_children(self):
|
||||||
|
global _map_capping_size
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.count == None:
|
if self.count == None:
|
||||||
self.count = self.num_children_impl()
|
self.count = self.num_children_impl()
|
||||||
|
if self.count > _map_capping_size:
|
||||||
|
self.count = _map_capping_size
|
||||||
return self.count
|
return self.count
|
||||||
|
|
||||||
def num_children_impl(self):
|
def num_children_impl(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
|
return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
|
||||||
except:
|
except:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
def get_data_type(self):
|
def get_data_type(self):
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.data_type == None or self.data_size == None:
|
if self.data_type == None or self.data_size == None:
|
||||||
if self.num_children() == 0:
|
if self.num_children() == 0:
|
||||||
return False
|
return False
|
||||||
|
@ -413,6 +489,7 @@ class stdmap_SynthProvider:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_value_offset(self,node):
|
def get_value_offset(self,node):
|
||||||
|
logger = Logger.Logger()
|
||||||
if self.skip_size == None:
|
if self.skip_size == None:
|
||||||
node_type = node.GetType()
|
node_type = node.GetType()
|
||||||
fields_count = node_type.GetNumberOfFields()
|
fields_count = node_type.GetNumberOfFields()
|
||||||
|
@ -424,24 +501,31 @@ class stdmap_SynthProvider:
|
||||||
return (self.skip_size != None)
|
return (self.skip_size != None)
|
||||||
|
|
||||||
def get_child_index(self,name):
|
def get_child_index(self,name):
|
||||||
|
logger = Logger.Logger()
|
||||||
try:
|
try:
|
||||||
return int(name.lstrip('[').rstrip(']'))
|
return int(name.lstrip('[').rstrip(']'))
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_child_at_index(self,index):
|
def get_child_at_index(self,index):
|
||||||
|
logger = Logger.Logger()
|
||||||
if index < 0:
|
if index < 0:
|
||||||
return None
|
return None
|
||||||
if index >= self.num_children():
|
if index >= self.num_children():
|
||||||
return None;
|
return None;
|
||||||
|
if self.garbage:
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
iterator = stdmap_iterator(self.root_node)
|
iterator = stdmap_iterator(self.root_node,max_count=self.num_children())
|
||||||
# the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
|
# the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
|
||||||
# out of which we can grab the information we need - every other node has a less informative
|
# out of which we can grab the information we need - every other node has a less informative
|
||||||
# type which omits all value information and only contains housekeeping information for the RB tree
|
# type which omits all value information and only contains housekeeping information for the RB tree
|
||||||
# hence, we need to know if we are at a node != 0, so that we can still get at the data
|
# hence, we need to know if we are at a node != 0, so that we can still get at the data
|
||||||
need_to_skip = (index > 0)
|
need_to_skip = (index > 0)
|
||||||
current = iterator.advance(index)
|
current = iterator.advance(index)
|
||||||
|
if current == None:
|
||||||
|
self.garbage = True
|
||||||
|
return None
|
||||||
if self.get_data_type():
|
if self.get_data_type():
|
||||||
if not(need_to_skip):
|
if not(need_to_skip):
|
||||||
current = current.Dereference()
|
current = current.Dereference()
|
||||||
|
@ -481,3 +565,7 @@ def __lldb_init_module(debugger,dict):
|
||||||
debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
|
debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
|
||||||
debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
|
debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
|
||||||
debugger.HandleCommand("type category enable libcxx")
|
debugger.HandleCommand("type category enable libcxx")
|
||||||
|
|
||||||
|
_map_capping_size = 255
|
||||||
|
_list_capping_size = 255
|
||||||
|
_list_uses_loop_detector = True
|
||||||
|
|
|
@ -508,6 +508,20 @@ else
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -f "${SRC_ROOT}/examples/summaries/cocoa/Logger.py" ]
|
||||||
|
then
|
||||||
|
if [ $Debug == 1 ]
|
||||||
|
then
|
||||||
|
echo "Copying Logger.py to ${framework_python_dir}"
|
||||||
|
fi
|
||||||
|
cp "${SRC_ROOT}/examples/summaries/cocoa/Logger.py" "${framework_python_dir}"
|
||||||
|
else
|
||||||
|
if [ $Debug == 1 ]
|
||||||
|
then
|
||||||
|
echo "Unable to find ${SRC_ROOT}/examples/summaries/cocoa/Logger.py"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f "${SRC_ROOT}/examples/summaries/cocoa/objc_lldb.py" ]
|
if [ -f "${SRC_ROOT}/examples/summaries/cocoa/objc_lldb.py" ]
|
||||||
then
|
then
|
||||||
if [ $Debug == 1 ]
|
if [ $Debug == 1 ]
|
||||||
|
|
|
@ -296,8 +296,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
|
||||||
|
|
||||||
int old_count = Debugger::TestDebuggerRefCount();
|
int old_count = Debugger::TestDebuggerRefCount();
|
||||||
|
|
||||||
|
run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, libcxx, objc, Logger')", m_dictionary_name.c_str());
|
||||||
run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, libcxx, objc')", m_dictionary_name.c_str());
|
|
||||||
PyRun_SimpleString (run_string.GetData());
|
PyRun_SimpleString (run_string.GetData());
|
||||||
|
|
||||||
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
|
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
|
||||||
|
|
Loading…
Reference in New Issue