1# to activate the AOO-LLDB helper script type the line below into LLDB 2# command script import path-to-script/lldb4aoo.py 3# or activate it automatically by adding the line to ~/.lldbinit 4 5def __lldb_init_module( dbg, dict): 6 # the list of AOO specific types 7 aoo_types = ['rtl_String', 'rtl_uString', '_ByteStringData', '_UniStringData'] 8 pimpl_types = ['rtl::OString', 'rtl::OUString', 'ByteString', 'UniString'] 9 # register a helper function for each non-trivial type 10 for t in aoo_types: 11 f = 'getinfo_for_' + t.replace( '::', '_') 12 if f in globals(): 13 dbg.HandleCommand( 'type summary add %s -v -C yes -F %s.%s' % (t,__name__,f)) 14 else: 15 print( 'AOO-LLDB helper function "%s" is not yet defined: ' 16 '"%s" types cannot be displayed properly!' % (f,t)) 17 # register a generic helper function for pimpl types 18 dbg.HandleCommand( 'type summary add -F %s.%s -v -C yes -n PIMPL %s' % ( __name__,'get_pimpl_info', ' '.join(pimpl_types))) 19 20 # add info about specific helper methods 21 # assume functions with docstrings are available for general consumption 22 helper_funcs = [v for (k,v) in globals().iteritems() if( not k.startswith('_') and callable(v) and v.__doc__)] 23 if helper_funcs: 24 print( 'Available AOO-specific helper functions:') 25 for hfunc in helper_funcs: 26 shortdesc = hfunc.__doc__.splitlines()[0] 27 print( '\t%s\t# "%s"' %(hfunc.__name__, shortdesc)) 28 print( 'Run them with:') 29 for hfunc in helper_funcs[:4]: 30 print( '\tscript %s.%s()' %(__name__, hfunc.__name__)) 31 32# some helpers for use from interactive LLDB sessions 33 34import lldb 35 36def add_breakpoints(): 37 'Setup breakpoints useful for AOO debugging' 38 dbg = lldb.debugger 39 if dbg.GetNumTargets() == 0: 40 return 41 # the list of interesting function breakpoints 42 aoo_breakfn = ['main', '__cxa_call_unexpected', 'objc_exception_throw'] 43 aoo_breakfn += ['__cxa_throw'] 44 # register breakpoints for function basenames 45 for b in aoo_breakfn: 46 dbg.HandleCommand( 'breakpoint set -b ' + b) 47 48 49# local functions for use by the AOO-type summary providers 50 51def walk_ptrchain( v): 52 info = '' 53 while v.TypeIsPointerType(): 54 n = v.GetValueAsUnsigned() 55 if n == 0: 56 info += 'NULL' 57 return (None, info) 58 info += '0x%04X-> ' % (n) 59 v = v.Dereference() 60 return (v, info) 61 62def ret_strdata_info( v, refvar, lenvar, aryvar): 63 (v, info) = walk_ptrchain( v) 64 if not v: 65 return info 66 r = v.GetChildMemberWithName( refvar).GetValueAsSigned() 67 l = v.GetChildMemberWithName( lenvar).GetValueAsSigned() 68 c = v.GetChildMemberWithName( aryvar) 69 if (r < 0) or (l < 0): 70 info += 'CORRUPT_STR={refs=%d, len=%d}' % (r,l) 71 return info 72 L = min(l,128) 73 d = c.AddressOf().GetPointeeData( 0, L) 74 if c.GetByteSize() == 1: # assume UTF-8 75 s = ''.join([chr(x) for x in d.uint8s]) 76 else: # assume UTF-16 77 s = (u''.join([unichr(x) for x in d.uint16s])).encode('utf-8') 78 info += ('{refs=%d, len=%d, str="%s"%s}' % (r, l, s.encode('string_escape'), '...'if(l!=L)else'')) 79 return info 80 81# definitions for our individual LLDB type summary providers 82 83def get_pimpl_info( valobj, dict): 84 (v, info) = walk_ptrchain( valobj) 85 p = v.GetChildAtIndex(0) 86 pname = p.GetName() 87 n = p.GetValueAsUnsigned() 88 if n == 0: 89 return '%s(%s==NULL)' % (info, pname) 90 info = '%s(%s=0x%04X)-> ' % (info, pname, n) 91 return info + p.Dereference().GetSummary() 92 93 94def getinfo_for_rtl_String( valobj, dict): 95 return ret_strdata_info( valobj, 'refCount', 'length', 'buffer') 96 97def getinfo_for_rtl_uString( valobj, dict): 98 return ret_strdata_info( valobj, 'refCount', 'length', 'buffer') 99 100def getinfo_for__ByteStringData( valobj, dict): 101 return ret_strdata_info( valobj, 'mnRefCount', 'mnLen', 'maStr') 102 103def getinfo_for__UniStringData( valobj, dict): 104 return ret_strdata_info( valobj, 'mnRefCount', 'mnLen', 'maStr') 105 106