[Lldb-commits] [lldb] r182972 - Adding a diagnose-nsstring command

Enrico Granata egranata at apple.com
Thu May 30 16:36:47 PDT 2013


Author: enrico
Date: Thu May 30 18:36:47 2013
New Revision: 182972

URL: http://llvm.org/viewvc/llvm-project?rev=182972&view=rev
Log:
Adding a diagnose-nsstring command
This should help us figure out issues with the NSString data formatter


Added:
    lldb/trunk/examples/python/diagnose_nsstring.py
Modified:
    lldb/trunk/examples/python/diagnose_unwind.py
    lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh

Added: lldb/trunk/examples/python/diagnose_nsstring.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/diagnose_nsstring.py?rev=182972&view=auto
==============================================================================
--- lldb/trunk/examples/python/diagnose_nsstring.py (added)
+++ lldb/trunk/examples/python/diagnose_nsstring.py Thu May 30 18:36:47 2013
@@ -0,0 +1,171 @@
+# 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
+
+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 = "\
+struct $__lldb__notInlineMutable {\
+    char* buffer;\
+    signed long length;\
+    signed long capacity;\
+    unsigned int hasGap:1;\
+    unsigned int isFixedCapacity:1;\
+    unsigned int isExternalMutable:1;\
+    unsigned int capacityProvidedExternally:1;\n\
+#if __LP64__\n\
+    unsigned long desiredCapacity:60;\n\
+#else\n\
+    unsigned long desiredCapacity:28;\n\
+#endif\n\
+    void* contentsAllocator;\
+};\
+\
+struct $__lldb__CFString {\
+    void* _cfisa;\
+    uint8_t _cfinfo[4];\
+    uint32_t _rc;\
+    union {\
+        struct __inline1 {\
+            signed long length;\
+        } inline1;\
+        struct __notInlineImmutable1 {\
+            char* buffer;\
+            signed long length;\
+            void* contentsDeallocator;\
+        } notInlineImmutable1;\
+        struct __notInlineImmutable2 {\
+            char* buffer;\
+            void* contentsDeallocator;\
+        } notInlineImmutable2;\
+        struct $__lldb__notInlineMutable notInlineMutable;\
+    } variants;\
+};\
+"
+
+	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
+
+	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)
+
+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.'
+
+__lldb_init_module(lldb.debugger,None)
+__lldb_init_module = None
\ No newline at end of file

Modified: lldb/trunk/examples/python/diagnose_unwind.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/diagnose_unwind.py?rev=182972&r1=182971&r2=182972&view=diff
==============================================================================
--- lldb/trunk/examples/python/diagnose_unwind.py (original)
+++ lldb/trunk/examples/python/diagnose_unwind.py Thu May 30 18:36:47 2013
@@ -1,5 +1,5 @@
 # This implements the "diagnose-unwind" command, usually installed in the debug session like
-#   script import lldb.macosx
+#   command script import lldb.diagnose
 # it is used when lldb's backtrace fails -- it collects and prints information about the stack frames,
 # and tries an alternate unwind algorithm, that will help to understand why lldb's unwind algorithm did
 # not succeed.

Modified: lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh?rev=182972&r1=182971&r2=182972&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh (original)
+++ lldb/trunk/scripts/Python/finish-swig-Python-LLDB.sh Thu May 30 18:36:47 2013
@@ -248,7 +248,8 @@ then
     create_python_package "/macosx" "${package_files}"
 
     # lldb/diagnose
-    package_files="${SRC_ROOT}/examples/python/diagnose_unwind.py"
+    package_files="${SRC_ROOT}/examples/python/diagnose_unwind.py
+    ${SRC_ROOT}/examples/python/diagnose_nsstring.py"
     create_python_package "/diagnose" "${package_files}"
 
     # Copy files needed by lldb/macosx/heap.py to build libheap.dylib





More information about the lldb-commits mailing list