diff --git a/lldb/examples/summaries/cocoa/Logger.py b/lldb/examples/summaries/cocoa/Logger.py new file mode 100644 index 000000000000..8044416e5ba0 --- /dev/null +++ b/lldb/examples/summaries/cocoa/Logger.py @@ -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() + diff --git a/lldb/examples/summaries/cocoa/NSData.py b/lldb/examples/summaries/cocoa/NSData.py index 94da6057f5ca..36f213393a5e 100644 --- a/lldb/examples/summaries/cocoa/NSData.py +++ b/lldb/examples/summaries/cocoa/NSData.py @@ -10,6 +10,7 @@ import lldb import ctypes import objc_runtime import metrics +import Logger statistics = metrics.Metrics() statistics.add_metric('invalid_isa') @@ -25,6 +26,8 @@ class NSConcreteData_SummaryProvider: pass def __init__(self, valobj, params): + logger = Logger.Logger() + logger >> "NSConcreteData_SummaryProvider __init__" self.valobj = valobj; self.sys_params = params if not(self.sys_params.types_cache.NSUInteger): @@ -46,9 +49,13 @@ class NSConcreteData_SummaryProvider: return 2 * self.sys_params.pointer_size def length(self): + logger = Logger.Logger() + logger >> "NSConcreteData_SummaryProvider length" size = self.valobj.CreateChildAtOffset("count", self.offset(), self.sys_params.types_cache.NSUInteger) + logger >> str(size) + logger >> str(size.GetValueAsUnsigned(0)) return size.GetValueAsUnsigned(0) @@ -57,6 +64,8 @@ class NSDataUnknown_SummaryProvider: pass def __init__(self, valobj, params): + logger = Logger.Logger() + logger >> "NSDataUnknown_SummaryProvider __init__" self.valobj = valobj; self.sys_params = params self.update(); @@ -65,21 +74,31 @@ class NSDataUnknown_SummaryProvider: self.adjust_for_architecture(); def length(self): + logger = Logger.Logger() + logger >> "NSDataUnknown_SummaryProvider length" stream = lldb.SBStream() self.valobj.GetExpressionPath(stream) + logger >> stream.GetData() 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(): + logger >> "wow - expr output is valid: " + str(num_children_vo.GetValueAsUnsigned()) return num_children_vo.GetValueAsUnsigned(0) + logger >> "invalid expr output - too bad" return '' def GetSummary_Impl(valobj): global statistics + logger = Logger.Logger() + logger >> "NSData GetSummary_Impl" class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(valobj,statistics) if wrapper: + logger >> "got a wrapper summary - using it" return wrapper name_string = class_data.class_name() + logger >> "class name: " + name_string if name_string == 'NSConcreteData' or \ name_string == 'NSConcreteMutableData' or \ name_string == '__NSCFData': @@ -91,12 +110,16 @@ def GetSummary_Impl(valobj): return wrapper; def NSData_SummaryProvider (valobj,dict): + logger = Logger.Logger() + logger >> "NSData_SummaryProvider" provider = GetSummary_Impl(valobj); + logger >> "found a summary provider, it is: " + str(provider) if provider != None: try: summary = provider.length(); except: summary = None + logger >> "got a summary: it is " + str(summary) if summary == None: summary = '' elif isinstance(summary,basestring): @@ -110,7 +133,10 @@ def NSData_SummaryProvider (valobj,dict): return 'Summary Unavailable' def NSData_SummaryProvider2 (valobj,dict): + logger = Logger.Logger() + logger >> "NSData_SummaryProvider2" provider = GetSummary_Impl(valobj); + logger >> "found a summary provider, it is: " + str(provider) if provider != None: if isinstance(provider,objc_runtime.SpecialSituation_Description): return provider.message() @@ -118,6 +144,7 @@ def NSData_SummaryProvider2 (valobj,dict): summary = provider.length(); except: summary = None + logger >> "got a summary: it is " + str(summary) if summary == None: summary = '' elif isinstance(summary,basestring): diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py index fb970e8bc43e..07e25c321a9f 100644 --- a/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/lldb/examples/synthetic/gnu_libstdcpp.py @@ -1,4 +1,5 @@ import re +import Logger # C++ STL formatters for LLDB # These formatters are based upon the version of the GNU libstdc++ @@ -9,20 +10,29 @@ import re class StdListSynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() self.valobj = valobj def next_node(self,node): + logger = Logger.Logger() return node.GetChildMemberWithName('_M_next') def is_valid(self,node): + logger = Logger.Logger() return self.value(self.next_node(node)) != self.node_address def value(self,node): + logger = Logger.Logger() return node.GetValueAsUnsigned() # Floyd's cyle-finding algorithm # try to detect if this list has a loop 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 fast1 = self.next fast2 = self.next @@ -36,11 +46,17 @@ class StdListSynthProvider: return False def num_children(self): + global _list_capping_size + logger = Logger.Logger() if self.count == None: self.count = self.num_children_impl() + if self.count > _list_capping_size: + self.count = _list_capping_size return self.count def num_children_impl(self): + logger = Logger.Logger() + global _list_capping_size try: next_val = self.next.GetValueAsUnsigned(0) prev_val = self.prev.GetValueAsUnsigned(0) @@ -58,17 +74,21 @@ class StdListSynthProvider: while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address: size = size + 1 current = current.GetChildMemberWithName('_M_next') + if size > _list_capping_size: + return _list_capping_size return (size - 1) except: return 0; def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() if index < 0: return None; if index >= self.num_children(): @@ -84,6 +104,7 @@ class StdListSynthProvider: return None def extract_type(self): + logger = Logger.Logger() list_type = self.valobj.GetType().GetUnqualifiedType() if list_type.IsReferenceType(): list_type = list_type.GetDereferencedType() @@ -94,6 +115,7 @@ class StdListSynthProvider: return data_type def update(self): + logger = Logger.Logger() try: impl = self.valobj.GetChildMemberWithName('_M_impl') node = impl.GetChildMemberWithName('_M_node') @@ -109,19 +131,23 @@ class StdListSynthProvider: class StdVectorSynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() self.valobj = valobj; def num_children(self): + logger = Logger.Logger() if self.count == None: self.count = self.num_children_impl() return self.count def is_valid_pointer(ptr,process): + logger = Logger.Logger() error = lldb.SBError() process.ReadMemory(ptr,1,error) return False if error.Fail() else True def num_children_impl(self): + logger = Logger.Logger() try: start_val = self.start.GetValueAsUnsigned(0) finish_val = self.finish.GetValueAsUnsigned(0) @@ -156,12 +182,14 @@ class StdVectorSynthProvider: return 0; def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() if index < 0: return None; if index >= self.num_children(): @@ -173,6 +201,7 @@ class StdVectorSynthProvider: return None def update(self): + logger = Logger.Logger() try: impl = self.valobj.GetChildMemberWithName('_M_impl') self.start = impl.GetChildMemberWithName('_M_start') @@ -192,7 +221,9 @@ class StdVectorSynthProvider: class StdMapSynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() 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 # which prevents us from extracting the std::pair 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 find the type name def fixup_class_name(self, class_name): + logger = Logger.Logger() if class_name == 'std::basic_string, std::allocator >': return 'std::basic_string',True if class_name == 'basic_string, std::allocator >': @@ -213,7 +245,12 @@ class StdMapSynthProvider: return class_name,False def update(self): + logger = Logger.Logger() 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.Mimpl = self.Mt.GetChildMemberWithName('_M_impl') self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header') @@ -254,25 +291,43 @@ class StdMapSynthProvider: pass 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: root_ptr_val = self.node_ptr_value(self.Mroot) if root_ptr_val == 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: return 0; def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() + logger >> "Being asked to fetch child[" + str(index) + "]" if index < 0: return None if index >= self.num_children(): return None; + if self.garbage: + logger >> "Returning None since we are a garbage tree" + return None try: offset = index current = self.left(self.Mheader); @@ -286,31 +341,53 @@ class StdMapSynthProvider: # utility functions def node_ptr_value(self,node): + logger = Logger.Logger() return node.GetValueAsUnsigned(0) def right(self,node): + logger = Logger.Logger() return node.GetChildMemberWithName("_M_right"); def left(self,node): + logger = Logger.Logger() return node.GetChildMemberWithName("_M_left"); def parent(self,node): + logger = Logger.Logger() return node.GetChildMemberWithName("_M_parent"); # from libstdc++ implementation of iterator for rbtree def increment_node(self,node): + logger = Logger.Logger() + max_steps = self.num_children() if self.node_ptr_value(self.right(node)) != 0: x = self.right(node); + max_steps -= 1 while self.node_ptr_value(self.left(x)) != 0: 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; else: x = node; y = self.parent(x) + max_steps -= 1 while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))): x = 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): x = y; return x; + +_map_capping_size = 255 +_list_capping_size = 255 +_list_uses_loop_detector = True diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py index fb43b10ef104..30128f6d32d8 100644 --- a/lldb/examples/synthetic/libcxx.py +++ b/lldb/examples/synthetic/libcxx.py @@ -1,4 +1,5 @@ import lldb +import Logger # libcxx STL formatters for LLDB # 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 information for readers of the code, but when possible try to use meaningful variable names def stdstring_SummaryProvider(valobj,dict): + logger = Logger.Logger() r = valobj.GetChildAtIndex(0) B = r.GetChildAtIndex(0) first = B.GetChildAtIndex(0) @@ -55,9 +57,11 @@ def stdstring_SummaryProvider(valobj,dict): class stdvector_SynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() self.valobj = valobj; def num_children(self): + logger = Logger.Logger() try: start_val = self.start.GetValueAsUnsigned(0) finish_val = self.finish.GetValueAsUnsigned(0) @@ -85,12 +89,14 @@ class stdvector_SynthProvider: return 0; def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() if index < 0: return None; if index >= self.num_children(): @@ -102,6 +108,7 @@ class stdvector_SynthProvider: return None def update(self): + logger = Logger.Logger() try: self.start = self.valobj.GetChildMemberWithName('__begin_') self.finish = self.valobj.GetChildMemberWithName('__end_') @@ -121,21 +128,27 @@ def stdvector_SummaryProvider(valobj,dict): class stdlist_entry: def __init__(self,entry): + logger = Logger.Logger() self.entry = entry def _next_impl(self): + logger = Logger.Logger() return stdlist_entry(self.entry.GetChildMemberWithName('__next_')) def _prev_impl(self): + logger = Logger.Logger() return stdlist_entry(self.entry.GetChildMemberWithName('__prev_')) def _value_impl(self): + logger = Logger.Logger() return self.entry.GetValueAsUnsigned(0) def _isnull_impl(self): + logger = Logger.Logger() return self._value_impl() == 0 def _sbvalue_impl(self): + logger = Logger.Logger() return self.entry next = property(_next_impl,None) @@ -146,17 +159,21 @@ class stdlist_entry: class stdlist_iterator: def increment_node(self,node): + logger = Logger.Logger() if node.is_null: return None return node.next def __init__(self,node): + logger = Logger.Logger() self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry def value(self): + logger = Logger.Logger() return self.node.sbvalue # and return the SBValue back on exit def next(self): + logger = Logger.Logger() node = self.increment_node(self.node) if node != None and node.sbvalue.IsValid() and not(node.is_null): self.node = node @@ -165,6 +182,7 @@ class stdlist_iterator: return None def advance(self,N): + logger = Logger.Logger() if N < 0: return None if N == 0: @@ -179,17 +197,25 @@ class stdlist_iterator: class stdlist_SynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() self.valobj = valobj def next_node(self,node): + logger = Logger.Logger() return node.GetChildMemberWithName('__next_') def value(self,node): + logger = Logger.Logger() return node.GetValueAsUnsigned() # Floyd's cyle-finding algorithm # try to detect if this list has a loop 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) fast1 = stdlist_entry(self.head) fast2 = stdlist_entry(self.head) @@ -203,11 +229,17 @@ class stdlist_SynthProvider: return False def num_children(self): + global _list_capping_size + logger = Logger.Logger() if self.count == None: self.count = self.num_children_impl() + if self.count > _list_capping_size: + self.count = _list_capping_size return self.count def num_children_impl(self): + global _list_capping_size + logger = Logger.Logger() try: next_val = self.head.GetValueAsUnsigned(0) prev_val = self.tail.GetValueAsUnsigned(0) @@ -225,17 +257,21 @@ class stdlist_SynthProvider: while current.next.value != self.node_address: size = size + 1 current = current.next + if size > _list_capping_size: + return _list_capping_size return (size - 1) except: return 0; def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() if index < 0: return None; if index >= self.num_children(): @@ -252,6 +288,7 @@ class stdlist_SynthProvider: return None def extract_type(self): + logger = Logger.Logger() list_type = self.valobj.GetType().GetUnqualifiedType() if list_type.IsReferenceType(): list_type = list_type.GetDereferencedType() @@ -262,6 +299,7 @@ class stdlist_SynthProvider: return data_type def update(self): + logger = Logger.Logger() try: impl = self.valobj.GetChildMemberWithName('__end_') 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 class stdmap_iterator_node: def _left_impl(self): + logger = Logger.Logger() return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_")) def _right_impl(self): + logger = Logger.Logger() return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_")) def _parent_impl(self): + logger = Logger.Logger() return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_")) def _value_impl(self): + logger = Logger.Logger() return self.node.GetValueAsUnsigned(0) def _sbvalue_impl(self): + logger = Logger.Logger() return self.node def _null_impl(self): + logger = Logger.Logger() return self.value == 0 def __init__(self,node): + logger = Logger.Logger() self.node = node left = property(_left_impl,None) @@ -312,13 +357,20 @@ class stdmap_iterator_node: class stdmap_iterator: def tree_min(self,x): + logger = Logger.Logger() + steps = 0 if x.is_null: return None while (not x.left.is_null): x = x.left + steps += 1 + if steps > self.max_count: + logger >> "Returning None - we overflowed" + return None return x def tree_max(self,x): + logger = Logger.Logger() if x.is_null: return None while (not x.right.is_null): @@ -326,26 +378,37 @@ class stdmap_iterator: return x def tree_is_left_child(self,x): + logger = Logger.Logger() if x.is_null: return None return True if x.value == x.parent.left.value else False def increment_node(self,node): + logger = Logger.Logger() if node.is_null: return None if not node.right.is_null: return self.tree_min(node.right) + steps = 0 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 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.max_count = max_count def value(self): + logger = Logger.Logger() return self.node.sbvalue # and return the SBValue back on exit def next(self): + logger = Logger.Logger() node = self.increment_node(self.node) if node != None and node.sbvalue.IsValid() and not(node.is_null): self.node = node @@ -354,6 +417,7 @@ class stdmap_iterator: return None def advance(self,N): + logger = Logger.Logger() if N < 0: return None if N == 0: @@ -361,18 +425,24 @@ class stdmap_iterator: if N == 1: return self.next() while N > 0: - self.next() + if self.next() == None: + return None N = N - 1 return self.value() class stdmap_SynthProvider: def __init__(self, valobj, dict): + logger = Logger.Logger() self.valobj = valobj; self.pointer_size = self.valobj.GetProcess().GetAddressByteSize() def update(self): + logger = Logger.Logger() 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.root_node = self.tree.GetChildMemberWithName('__begin_node_') # this data is either lazily-calculated, or cannot be inferred at this moment @@ -385,17 +455,23 @@ class stdmap_SynthProvider: pass 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: return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned() except: return 0; def get_data_type(self): + logger = Logger.Logger() if self.data_type == None or self.data_size == None: if self.num_children() == 0: return False @@ -413,6 +489,7 @@ class stdmap_SynthProvider: return True def get_value_offset(self,node): + logger = Logger.Logger() if self.skip_size == None: node_type = node.GetType() fields_count = node_type.GetNumberOfFields() @@ -424,24 +501,31 @@ class stdmap_SynthProvider: return (self.skip_size != None) def get_child_index(self,name): + logger = Logger.Logger() try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): + logger = Logger.Logger() if index < 0: return None if index >= self.num_children(): return None; + if self.garbage: + return None 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 # 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 # 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) current = iterator.advance(index) + if current == None: + self.garbage = True + return None if self.get_data_type(): if not(need_to_skip): 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 summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx') debugger.HandleCommand("type category enable libcxx") + +_map_capping_size = 255 +_list_capping_size = 255 +_list_uses_loop_detector = True diff --git a/lldb/scripts/Python/finish-swig-Python-LLDB.sh b/lldb/scripts/Python/finish-swig-Python-LLDB.sh index c3d54691ba54..13194f4567ab 100755 --- a/lldb/scripts/Python/finish-swig-Python-LLDB.sh +++ b/lldb/scripts/Python/finish-swig-Python-LLDB.sh @@ -508,6 +508,20 @@ else 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" ] then if [ $Debug == 1 ] diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 42053bbf16c5..afde01fbebda 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -296,8 +296,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete int old_count = Debugger::TestDebuggerRefCount(); - - run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, libcxx, objc')", m_dictionary_name.c_str()); + run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb, gnu_libstdcpp, libcxx, objc, Logger')", m_dictionary_name.c_str()); 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