[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