summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_gdb.py19
-rw-r--r--Misc/NEWS3
-rw-r--r--Tools/gdb/libpython.py41
3 files changed, 61 insertions, 2 deletions
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 17b44ea..d288d79 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -611,12 +611,29 @@ $''')
$''')
class PyBtTests(DebuggerTests):
- def test_basic_command(self):
+ def test_bt(self):
'Verify that the "py-bt" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-bt'])
self.assertMultilineMatches(bt,
r'''^.*
+Traceback \(most recent call first\):
+ File ".*gdb_sample.py", line 10, in baz
+ id\(42\)
+ File ".*gdb_sample.py", line 7, in bar
+ baz\(a, b, c\)
+ File ".*gdb_sample.py", line 4, in foo
+ bar\(a, b, c\)
+ File ".*gdb_sample.py", line 12, in <module>
+ foo\(1, 2, 3\)
+''')
+
+ def test_bt_full(self):
+ 'Verify that the "py-bt-full" command works'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+ cmds_after_breakpoint=['py-bt-full'])
+ self.assertMultilineMatches(bt,
+ r'''^.*
#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
baz\(a, b, c\)
#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\)
diff --git a/Misc/NEWS b/Misc/NEWS
index dfde0b2..5b01426 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -359,6 +359,9 @@ IDLE
Tools/Demos
-----------
+- Issue #11996: libpython (gdb), replace "py-bt" command by "py-bt-full" and
+ add a smarter "py-bt" command printing a classic Python traceback.
+
- Issue #11179: Make ccbench work under Python 3.1 and 2.7 again.
Extension Modules
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index 93b0528..f3cb1b0 100644
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -931,6 +931,15 @@ class PyFrameObjectPtr(PyObjectPtr):
out.write(')')
+ def print_traceback(self):
+ if self.is_optimized_out():
+ sys.stdout.write(' (frame information optimized out)\n')
+ visited = set()
+ sys.stdout.write(' File "%s", line %i, in %s\n'
+ % (self.co_filename.proxyval(visited),
+ self.current_line_num(),
+ self.co_name.proxyval(visited)))
+
class PySetObjectPtr(PyObjectPtr):
_typename = 'PySetObject'
@@ -1427,6 +1436,17 @@ class Frame(object):
else:
sys.stdout.write('#%i\n' % self.get_index())
+ def print_traceback(self):
+ if self.is_evalframeex():
+ pyop = self.get_pyop()
+ if pyop:
+ pyop.print_traceback()
+ sys.stdout.write(' %s\n' % pyop.current_line().strip())
+ else:
+ sys.stdout.write(' (unable to read python frame information)\n')
+ else:
+ sys.stdout.write(' (not a python frame)\n')
+
class PyList(gdb.Command):
'''List the current Python source code, if any
@@ -1551,6 +1571,24 @@ if hasattr(gdb.Frame, 'select'):
PyUp()
PyDown()
+class PyBacktraceFull(gdb.Command):
+ 'Display the current python frame and all the frames within its call stack (if any)'
+ def __init__(self):
+ gdb.Command.__init__ (self,
+ "py-bt-full",
+ gdb.COMMAND_STACK,
+ gdb.COMPLETE_NONE)
+
+
+ def invoke(self, args, from_tty):
+ frame = Frame.get_selected_python_frame()
+ while frame:
+ if frame.is_evalframeex():
+ frame.print_summary()
+ frame = frame.older()
+
+PyBacktraceFull()
+
class PyBacktrace(gdb.Command):
'Display the current python frame and all the frames within its call stack (if any)'
def __init__(self):
@@ -1561,10 +1599,11 @@ class PyBacktrace(gdb.Command):
def invoke(self, args, from_tty):
+ sys.stdout.write('Traceback (most recent call first):\n')
frame = Frame.get_selected_python_frame()
while frame:
if frame.is_evalframeex():
- frame.print_summary()
+ frame.print_traceback()
frame = frame.older()
PyBacktrace()