[Lldb-commits] [lldb] r115983 - in /lldb/trunk/test: lldbutil.py threads/Makefile threads/TestPrintStackTraces.py threads/main.cpp

Johnny Chen johnny.chen at apple.com
Thu Oct 7 14:38:28 PDT 2010


Author: johnny
Date: Thu Oct  7 16:38:28 2010
New Revision: 115983

URL: http://llvm.org/viewvc/llvm-project?rev=115983&view=rev
Log:
Add a test case which uses the SBProcess and SBThread APIs to iterate through
the threads and print their stack traces when stopped on a breakpoint.

Add a PrintStackTraces(process) utility function into the lldbutil.py module.

Added:
    lldb/trunk/test/threads/TestPrintStackTraces.py
Modified:
    lldb/trunk/test/lldbutil.py
    lldb/trunk/test/threads/Makefile
    lldb/trunk/test/threads/main.cpp

Modified: lldb/trunk/test/lldbutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbutil.py?rev=115983&r1=115982&r2=115983&view=diff
==============================================================================
--- lldb/trunk/test/lldbutil.py (original)
+++ lldb/trunk/test/lldbutil.py Thu Oct  7 16:38:28 2010
@@ -1,5 +1,5 @@
 """
-LLDB modules which contains miscellaneous utilities.
+This LLDB module contains miscellaneous utilities.
 """
 
 import lldb
@@ -16,6 +16,26 @@
     return map(GetFuncName, range(thread.GetNumFrames()))
 
 
+def GetSymbolNames(thread):
+    """
+    Returns a sequence of symbols for this thread.
+    """
+    def GetSymbol(i):
+        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
+
+    return map(GetSymbol, range(thread.GetNumFrames()))
+
+
+def GetPCAddresses(thread):
+    """
+    Returns a sequence of pc addresses for this thread.
+    """
+    def GetPCAddress(i):
+        return thread.GetFrameAtIndex(i).GetPCAddress()
+
+    return map(GetPCAddress, range(thread.GetNumFrames()))
+
+
 def GetFilenames(thread):
     """
     Returns a sequence of file names from the stack frames of this thread.
@@ -59,23 +79,47 @@
 def PrintStackTrace(thread, string_buffer = False):
     """Prints a simple stack trace of this thread."""
 
+    output = StringIO.StringIO() if string_buffer else sys.stdout
+    target = thread.GetProcess().GetTarget()
+
     depth = thread.GetNumFrames()
 
     mods = GetModuleNames(thread)
     funcs = GetFunctionNames(thread)
+    symbols = GetSymbolNames(thread)
     files = GetFilenames(thread)
     lines = GetLineNumbers(thread)
-
-    output = StringIO.StringIO() if string_buffer else sys.stdout
+    addrs = GetPCAddresses(thread)
 
     print >> output, "Stack trace for thread id={0:#x} name={1} queue={2}:".format(
         thread.GetThreadID(), thread.GetName(), thread.GetQueueName())
 
-    for i in range(depth - 1):
-        print >> output, "  frame #{num}: {mod}`{func} at {file}:{line}".format(
-            num=i, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
+    for i in range(depth):
+        frame = thread.GetFrameAtIndex(i)
+        function = frame.GetFunction()
+
+        load_addr = addrs[i].GetLoadAddress(target)
+        if not function.IsValid():
+            file_addr = addrs[i].GetFileAddress()
+            print >> output, "  frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
+                num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
+        else:
+            print >> output, "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
+                num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
+
+    if string_buffer:
+        return output.getvalue()
+
+
+def PrintStackTraces(process, string_buffer = False):
+    """Prints the stack traces of all the threads."""
+
+    output = StringIO.StringIO() if string_buffer else sys.stdout
+
+    print >> output, "Stack traces for " + repr(process)
 
-    print >> output, "  frame #{num}: {mod}`start".format(num=depth-1, mod=mods[depth-1])
+    for i in range(process.GetNumThreads()):
+        print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
 
     if string_buffer:
         return output.getvalue()

Modified: lldb/trunk/test/threads/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/threads/Makefile?rev=115983&r1=115982&r2=115983&view=diff
==============================================================================
--- lldb/trunk/test/threads/Makefile (original)
+++ lldb/trunk/test/threads/Makefile Thu Oct  7 16:38:28 2010
@@ -1,125 +1,6 @@
-#----------------------------------------------------------------------
-# Fill in the source files to build
-#----------------------------------------------------------------------
-C_SOURCES :=
-CXX_SOURCES :=main.cpp
-OBJC_SOURCES :=
-OBJCXX_SOURCES :=
-
-# Uncomment line below for debugging shell commands
-# SHELL = /bin/sh -x
-
-#----------------------------------------------------------------------
-# Change any build/tool options needed
-#----------------------------------------------------------------------
-DS := /usr/bin/dsymutil
-DSFLAGS =
-CFLAGS ?=-arch x86_64 -gdwarf-2 -O0
-CPLUSPLUSFLAGS +=$(CFLAGS)
-CPPFLAGS +=$(CFLAGS)
-LD = gcc
-LDFLAGS = $(CFLAGS)
-OBJECTS =
-EXE=a.out
-DSYM=$(EXE).dSYM
-
-#----------------------------------------------------------------------
-# Check if we have any C source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(C_SOURCES))" ""
-	OBJECTS +=$(strip $(C_SOURCES:.c=.o))
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any C++ source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(CXX_SOURCES))" ""
-	OBJECTS +=$(strip $(CXX_SOURCES:.cpp=.o))
-	LD = g++
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any ObjC source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(OBJC_SOURCES))" ""
-	OBJECTS +=$(strip $(OBJC_SOURCES:.m=.o))
-	LDFLAGS +=-lobjc
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any ObjC++ source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(OBJCXX_SOURCES))" ""
-	OBJECTS +=$(strip $(OBJCXX_SOURCES:.mm=.o))
-	LD = g++
-	ifeq $(findstring lobjc,$(LDFLAGS)) ""
-		LDFLAGS +=-lobjc
-	endif
-endif
-
-
-#----------------------------------------------------------------------
-# Make the dSYM file from the executable
-#----------------------------------------------------------------------
-$(DSYM) : $(EXE)
-	$(DS) $(DSFLAGS) -o "$(DSYM)" "$(EXE)"
-
-#----------------------------------------------------------------------
-# Compile the executable from all the objects (default rule) with no
-# dsym file.
-#----------------------------------------------------------------------
-$(EXE) : $(OBJECTS)
-	$(LD) $(LDFLAGS) $(OBJECTS) -o "$(EXE)"
-
-
-#----------------------------------------------------------------------
-# Automatic variables based on items already entered. Below we create
-# an objects lists from the list of sources by replacing all entries
-# that end with .c with .o, and we also create a list of prerequisite
-# files by replacing all .c files with .d.
-#----------------------------------------------------------------------
-PREREQS := $(OBJECTS:.o=.d)
-
-#----------------------------------------------------------------------
-# Rule for Generating Prerequisites Automatically using .d files and
-# the compiler -MM option. The -M option will list all system headers,
-# and the -MM option will list all non-system dependencies.
-#----------------------------------------------------------------------
-%.d: %.c
-	@set -e; rm -f $@; \
-	$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
-	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-	rm -f $@.$$$$
-
-%.d: %.cpp
-	@set -e; rm -f $@; \
-	$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
-	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-	rm -f $@.$$$$
-
-%.d: %.m
-	@set -e; rm -f $@; \
-	$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
-	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-	rm -f $@.$$$$
-
-%.d: %.mm
-	@set -e; rm -f $@; \
-	$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
-	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-	rm -f $@.$$$$
-
-#----------------------------------------------------------------------
-# Include all of the makefiles for each source file so we don't have
-# to manually track all of the prerequisites for each source file.
-#----------------------------------------------------------------------
-sinclude $(PREREQS)
-
-.PHONY: clean
-dsym:	$(DSYM)
-all:	$(EXE) $(DSYM)
-clean:
-	rm -rf "$(EXE)" "$(DSYM)" $(OBJECTS) $(PREREQS)
-
+LEVEL = ../make
 
+CXX_SOURCES := main.cpp
+MAKE_DSYM :=NO
 
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/threads/TestPrintStackTraces.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/threads/TestPrintStackTraces.py?rev=115983&view=auto
==============================================================================
--- lldb/trunk/test/threads/TestPrintStackTraces.py (added)
+++ lldb/trunk/test/threads/TestPrintStackTraces.py Thu Oct  7 16:38:28 2010
@@ -0,0 +1,50 @@
+"""
+Test SBprocess and SBThread APIs with printing of the stack traces.
+"""
+
+import os, time
+import re
+import unittest2
+import lldb
+from lldbtest import *
+
+class ThreadsStackTracesTestCase(TestBase):
+
+    mydir = "threads"
+
+    def test_stack_traces(self):
+        """Test SBprocess and SBThread APIs with printing of the stack traces."""
+        self.buildDefault()
+        self.break_and_print_stacktraces()
+
+    def break_and_print_stacktraces(self):
+        """Break at main.cpp:68 and do a threads dump"""
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target.IsValid(), VALID_TARGET)
+
+        breakpoint = target.BreakpointCreateByLocation("main.cpp", 68)
+        self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        rc = lldb.SBError()
+        self.process = target.Launch([''], [''], os.ctermid(), 0, False, rc)
+
+        if not rc.Success() or not self.process.IsValid():
+            self.fail("SBTarget.LaunchProcess() failed")
+
+        if self.process.GetState() != lldb.eStateStopped:
+            self.fail("Process should be in the 'Stopped' state, "
+                      "instead the actual state is: '%s'" %
+                      StateTypeString(self.process.GetState()))
+
+        import lldbutil
+        lldbutil.PrintStackTraces(self.process)
+
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Modified: lldb/trunk/test/threads/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/threads/main.cpp?rev=115983&r1=115982&r2=115983&view=diff
==============================================================================
--- lldb/trunk/test/threads/main.cpp (original)
+++ lldb/trunk/test/threads/main.cpp Thu Oct  7 16:38:28 2010
@@ -65,6 +65,7 @@
         long usec = ::random() % 3000000;
         printf ("%s (thread = %u) doing a usleep (%li)...\n", __FUNCTION__, thread_index, usec);
         ::usleep (usec);
+        printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index);
     }
     printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
 
@@ -126,4 +127,4 @@
     err = ::pthread_join (g_thread_3, &thread_result);
 
     return 0;
-}
\ No newline at end of file
+}





More information about the lldb-commits mailing list