diff options
Diffstat (limited to 'lldb/examples/python/diagnose_nsstring.py')
-rw-r--r-- | lldb/examples/python/diagnose_nsstring.py | 250 |
1 files changed, 131 insertions, 119 deletions
diff --git a/lldb/examples/python/diagnose_nsstring.py b/lldb/examples/python/diagnose_nsstring.py index aca5c7f220f..0404f714f74 100644 --- a/lldb/examples/python/diagnose_nsstring.py +++ b/lldb/examples/python/diagnose_nsstring.py @@ -1,64 +1,67 @@ # This implements the "diagnose-nsstring" command, usually installed in the debug session like # command script import lldb.diagnose # it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the -# decisions it did and providing some useful context information that can be used for improving the formatter +# decisions it did and providing some useful context information that can +# be used for improving the formatter import lldb -def read_memory(process,location,size): - data = "" - error = lldb.SBError() - for x in range(0,size-1): - byte = process.ReadUnsignedFromMemory(x+location,1,error) - if error.fail: - data = data + "err%s" % "" if x == size-2 else ":" - else: - try: - data = data + "0x%x" % byte - if byte == 0: - data = data + "(\\0)" - elif byte == 0xa: - data = data + "(\\a)" - elif byte == 0xb: - data = data + "(\\b)" - elif byte == 0xc: - data = data + "(\\c)" - elif byte == '\n': - data = data + "(\\n)" - else: - data = data + "(%s)" % chr(byte) - if x < size-2: - data = data + ":" - except Exception as e: - print e - return data -def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict): - """ - A command to diagnose the LLDB NSString data formatter - invoke as - (lldb) diagnose-nsstring <expr returning NSString> - e.g. - (lldb) diagnose-nsstring @"Hello world" - """ - target = debugger.GetSelectedTarget() - process = target.GetProcess() - thread = process.GetSelectedThread() - frame = thread.GetSelectedFrame() - if not target.IsValid() or not process.IsValid(): - return "unable to get target/process - cannot proceed" - options = lldb.SBExpressionOptions() - options.SetFetchDynamicValue() - error = lldb.SBError() - if frame.IsValid(): - nsstring = frame.EvaluateExpression(command,options) - else: - nsstring = target.EvaluateExpression(command,options) - print >>result,str(nsstring) - nsstring_address = nsstring.GetValueAsUnsigned(0) - if nsstring_address == 0: - return "unable to obtain the string - cannot proceed" - expression = "\ +def read_memory(process, location, size): + data = "" + error = lldb.SBError() + for x in range(0, size - 1): + byte = process.ReadUnsignedFromMemory(x + location, 1, error) + if error.fail: + data = data + "err%s" % "" if x == size - 2 else ":" + else: + try: + data = data + "0x%x" % byte + if byte == 0: + data = data + "(\\0)" + elif byte == 0xa: + data = data + "(\\a)" + elif byte == 0xb: + data = data + "(\\b)" + elif byte == 0xc: + data = data + "(\\c)" + elif byte == '\n': + data = data + "(\\n)" + else: + data = data + "(%s)" % chr(byte) + if x < size - 2: + data = data + ":" + except Exception as e: + print e + return data + + +def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict): + """ + A command to diagnose the LLDB NSString data formatter + invoke as + (lldb) diagnose-nsstring <expr returning NSString> + e.g. + (lldb) diagnose-nsstring @"Hello world" + """ + target = debugger.GetSelectedTarget() + process = target.GetProcess() + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + if not target.IsValid() or not process.IsValid(): + return "unable to get target/process - cannot proceed" + options = lldb.SBExpressionOptions() + options.SetFetchDynamicValue() + error = lldb.SBError() + if frame.IsValid(): + nsstring = frame.EvaluateExpression(command, options) + else: + nsstring = target.EvaluateExpression(command, options) + print >>result, str(nsstring) + nsstring_address = nsstring.GetValueAsUnsigned(0) + if nsstring_address == 0: + return "unable to obtain the string - cannot proceed" + expression = "\ struct $__lldb__notInlineMutable {\ char* buffer;\ signed long length;\ @@ -97,75 +100,84 @@ struct $__lldb__CFString {\ };\ " - expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address - # print expression - dumped = target.EvaluateExpression(expression,options) - print >>result, str(dumped) - - little_endian = (target.byte_order == lldb.eByteOrderLittle) - ptr_size = target.addr_size - - info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0) - is_mutable = (info_bits & 1) == 1 - is_inline = (info_bits & 0x60) == 0 - has_explicit_length = (info_bits & (1 | 4)) != 4 - is_unicode = (info_bits & 0x10) == 0x10 - is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2") - has_null = (info_bits & 8) == 8 - - print >>result,"\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \ - (info_bits, "yes" if is_mutable else "no","yes" if is_inline else "no","yes" if has_explicit_length else "no","yes" if is_unicode else "no","yes" if is_special else "no","yes" if has_null else "no") + expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address + # print expression + dumped = target.EvaluateExpression(expression, options) + print >>result, str(dumped) + + little_endian = (target.byte_order == lldb.eByteOrderLittle) + ptr_size = target.addr_size + + info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex( + 0 if little_endian else 3).GetValueAsUnsigned(0) + is_mutable = (info_bits & 1) == 1 + is_inline = (info_bits & 0x60) == 0 + has_explicit_length = (info_bits & (1 | 4)) != 4 + is_unicode = (info_bits & 0x10) == 0x10 + is_special = ( + nsstring.GetDynamicValue( + lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2") + has_null = (info_bits & 8) == 8 + + print >>result, "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \ + (info_bits, "yes" if is_mutable else "no", "yes" if is_inline else "no", "yes" if has_explicit_length else "no", "yes" if is_unicode else "no", "yes" if is_special else "no", "yes" if has_null else "no") + explicit_length_offset = 0 + if not has_null and has_explicit_length and not is_special: + explicit_length_offset = 2 * ptr_size + if is_mutable and not is_inline: + explicit_length_offset = explicit_length_offset + ptr_size + elif is_inline: + pass + elif not is_inline and not is_mutable: + explicit_length_offset = explicit_length_offset + ptr_size + else: + explicit_length_offset = 0 - explicit_length_offset = 0 - if not has_null and has_explicit_length and not is_special: - explicit_length_offset = 2*ptr_size - if is_mutable and not is_inline: - explicit_length_offset = explicit_length_offset + ptr_size - elif is_inline: - pass - elif not is_inline and not is_mutable: - explicit_length_offset = explicit_length_offset + ptr_size - else: - explicit_length_offset = 0 + if explicit_length_offset == 0: + print >>result, "There is no explicit length marker - skipping this step\n" + else: + explicit_length_offset = nsstring_address + explicit_length_offset + explicit_length = process.ReadUnsignedFromMemory( + explicit_length_offset, 4, error) + print >>result, "Explicit length location is at 0x%x - read value is %d\n" % ( + explicit_length_offset, explicit_length) - if explicit_length_offset == 0: - print >>result,"There is no explicit length marker - skipping this step\n" - else: - explicit_length_offset = nsstring_address + explicit_length_offset - explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error) - print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length) + if is_mutable: + location = 2 * ptr_size + nsstring_address + location = process.ReadPointerFromMemory(location, error) + elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable: + location = 3 * ptr_size + nsstring_address + elif is_unicode: + location = 2 * ptr_size + nsstring_address + if is_inline: + if not has_explicit_length: + print >>result, "Unicode & Inline & !Explicit is a new combo - no formula for it" + else: + location += ptr_size + else: + location = process.ReadPointerFromMemory(location, error) + elif is_special: + location = nsstring_address + ptr_size + 4 + elif is_inline: + location = 2 * ptr_size + nsstring_address + if not has_explicit_length: + location += 1 + else: + location = 2 * ptr_size + nsstring_address + location = process.ReadPointerFromMemory(location, error) + print >>result, "Expected data location: 0x%x\n" % (location) + print >>result, "1K of data around location: %s\n" % read_memory( + process, location, 1024) + print >>result, "5K of data around string pointer: %s\n" % read_memory( + process, nsstring_address, 1024 * 5) - if is_mutable: - location = 2 * ptr_size + nsstring_address - location = process.ReadPointerFromMemory(location,error) - elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable: - location = 3 * ptr_size + nsstring_address - elif is_unicode: - location = 2 * ptr_size + nsstring_address - if is_inline: - if not has_explicit_length: - print >>result,"Unicode & Inline & !Explicit is a new combo - no formula for it" - else: - location += ptr_size - else: - location = process.ReadPointerFromMemory(location,error) - elif is_special: - location = nsstring_address + ptr_size + 4 - elif is_inline: - location = 2 * ptr_size + nsstring_address - if not has_explicit_length: - location += 1 - else: - location = 2 * ptr_size + nsstring_address - location = process.ReadPointerFromMemory(location,error) - print >>result,"Expected data location: 0x%x\n" % (location) - print >>result,"1K of data around location: %s\n" % read_memory(process,location,1024) - print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5) def __lldb_init_module(debugger, internal_dict): - debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__) - print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.' + debugger.HandleCommand( + "command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % + __name__) + print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.' -__lldb_init_module(lldb.debugger,None) -__lldb_init_module = None
\ No newline at end of file +__lldb_init_module(lldb.debugger, None) +__lldb_init_module = None |