diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/NEWS | 6 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/python.texi | 9 | ||||
-rw-r--r-- | gdb/python/py-frame.c | 23 | ||||
-rw-r--r-- | gdb/python/py-unwind.c | 19 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-frame.exp | 11 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-pending-frame-level.c | 49 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-pending-frame-level.exp | 65 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-pending-frame-level.py | 55 |
11 files changed, 258 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 24aeaa4..0501a56 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2021-06-21 Andrew Burgess <andrew.burgess@embecosm.com> + * NEWS: Mention the two new methods. + * python/py-frame.c (frapy_level): New function. + (frame_object_methods): Register 'level' method. + * python/py-unwind.c (pending_framepy_level): New function. + (pending_frame_object_methods): Register 'level' method. + +2021-06-21 Andrew Burgess <andrew.burgess@embecosm.com> + * python/py-inferior.c (infpy_get_connection_num): Call gdb_py_object_from_longest instead of PyLong_FromLong directly. @@ -220,6 +220,12 @@ QMemTags gives the connection number as seen in 'info connections' and 'info inferiors'. + ** New method gdb.Frame.level() which returns the stack level of the + frame object. + + ** New method gdb.PendingFrame.level() which returns the stack level + of the frame object. + *** Changes in GDB 10 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core" diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 0fa355c..9595c21 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2021-06-21 Andrew Burgess <andrew.burgess@embecosm.com> + + * python.texi (Unwinding Frames in Python): Mention + PendingFrame.level. + (Frames In Python): Mention Frame.level. + 2021-06-16 Felix Willgerodt <felix.willgerodt@intel.com> * gdb.texinfo (Process Record and Replay): Stop mentioning lines diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index ab934a8..01a2e8b 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -2605,6 +2605,11 @@ for this @code{gdb.PendingFrame}. This represents the architecture of the particular frame being unwound. @end defun +@defun PendingFrame.level () +Return an integer, the stack frame level for this frame. +@xref{Frames, ,Stack Frames}. +@end defun + @subheading Unwinder Output: UnwindInfo Use @code{PendingFrame.create_unwind_info} method described above to @@ -4813,6 +4818,10 @@ Set this frame to be the selected frame. @xref{Stack, ,Examining the Stack}. @end defun +@defun Frame.level () +Return an integer, the stack frame level for this frame. @xref{Frames, ,Stack Frames}. +@end defun + @node Blocks In Python @subsubsection Accessing blocks from Python diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index c8eab52..ee57eb1 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -577,6 +577,27 @@ frapy_select (PyObject *self, PyObject *args) Py_RETURN_NONE; } +/* The stack frame level for this frame. */ + +static PyObject * +frapy_level (PyObject *self, PyObject *args) +{ + struct frame_info *fi; + + try + { + FRAPY_REQUIRE_VALID (self, fi); + + return gdb_py_object_from_longest (frame_relative_level (fi)).release (); + } + catch (const gdb_exception &except) + { + GDB_PY_HANDLE_EXCEPTION (except); + } + + Py_RETURN_NONE; +} + /* Implementation of gdb.newest_frame () -> gdb.Frame. Returns the newest frame object. */ @@ -748,6 +769,8 @@ Return the frame's symtab and line." }, Return the value of the variable in this frame." }, { "select", frapy_select, METH_NOARGS, "Select this frame as the user's current frame." }, + { "level", frapy_level, METH_NOARGS, + "The stack level of this frame." }, {NULL} /* Sentinel */ }; diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index d6e2f85..d3ef191 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -463,6 +463,23 @@ pending_framepy_architecture (PyObject *self, PyObject *args) return gdbarch_to_arch_object (pending_frame->gdbarch); } +/* Implementation of PendingFrame.level (self) -> Integer. */ + +static PyObject * +pending_framepy_level (PyObject *self, PyObject *args) +{ + pending_frame_object *pending_frame = (pending_frame_object *) self; + + if (pending_frame->frame_info == NULL) + { + PyErr_SetString (PyExc_ValueError, + "Attempting to read stack level from stale PendingFrame"); + return NULL; + } + int level = frame_relative_level (pending_frame->frame_info); + return gdb_py_object_from_longest (level).release (); +} + /* frame_unwind.this_id method. */ static void @@ -704,6 +721,8 @@ static PyMethodDef pending_frame_object_methods[] = pending_framepy_architecture, METH_NOARGS, "architecture () -> gdb.Architecture\n" "The architecture for this PendingFrame." }, + { "level", pending_framepy_level, METH_NOARGS, + "The stack level of this frame." }, {NULL} /* Sentinel */ }; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ddd8b13..0f5c152 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2021-06-21 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.python/py-frame.exp: Add Frame.level tests. + * gdb.python/py-pending-frame-level.c: New file. + * gdb.python/py-pending-frame-level.exp: New file. + * gdb.python/py-pending-frame-level.py: New file. + +2021-06-21 Andrew Burgess <andrew.burgess@embecosm.com> + * gdb.python/py-unwind-user-regs.c: New file. * gdb.python/py-unwind-user-regs.exp: New file. * gdb.python/py-unwind-user-regs.py: New file. diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp index a6a5c0d..05c7fb0 100644 --- a/gdb/testsuite/gdb.python/py-frame.exp +++ b/gdb/testsuite/gdb.python/py-frame.exp @@ -70,6 +70,17 @@ gdb_test "up" ".*" "" gdb_py_test_silent_cmd "python f1 = gdb.selected_frame ()" "get second frame" 0 gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0 +gdb_py_test_silent_cmd "python f2 = f1.older ()" "get last frame" 0 + +# Check the Frame.level method. +gdb_test "python print ('bframe.level = %d' % bframe.level ())" \ + "bframe\\.level = 0" +gdb_test "python print ('f0.level = %d' % f0.level ())" \ + "f0\\.level = 0" +gdb_test "python print ('f1.level = %d' % f1.level ())" \ + "f1\\.level = 1" +gdb_test "python print ('f2.level = %d' % f2.level ())" \ + "f2\\.level = 2" gdb_test "python print (f1 == gdb.newest_frame())" False \ "selected frame -vs- newest frame" diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.c b/gdb/testsuite/gdb.python/py-pending-frame-level.c new file mode 100644 index 0000000..5e5495c --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.c @@ -0,0 +1,49 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +volatile int global_var; + +void __attribute__ ((noinline)) +f0 (void) +{ + ++global_var; /* Break here. */ +} + +void __attribute__ ((noinline)) +f1 (void) +{ + f0 (); +} + +void __attribute__ ((noinline)) +f2 (void) +{ + f1 (); +} + +void __attribute__ ((noinline)) +f3 (void) +{ + f2 (); +} + +int +main (void) +{ + f3 (); + return 0; +} diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.exp b/gdb/testsuite/gdb.python/py-pending-frame-level.exp new file mode 100644 index 0000000..1aadcae --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.exp @@ -0,0 +1,65 @@ +# Copyright (C) 2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test gdb.PendingFrame.level method. + +load_lib gdb-python.exp + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +if ![runto_main] then { + fail "can't run to main" + return 0 +} + +set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py] + +gdb_breakpoint [gdb_get_line_number "Break here"] +gdb_continue_to_breakpoint "stop at test breakpoint" + +# An initial look at the stack to ensure it is correct. +gdb_test_sequence "bt" "Initial backtrace" { + "\\r\\n#0 \[^\r\n\]* f0 \\(\\) at " + "\\r\\n#1 \[^\r\n\]* f1 \\(\\) at " + "\\r\\n#2 \[^\r\n\]* f2 \\(\\) at " + "\\r\\n#3 \[^\r\n\]* f3 \\(\\) at " + "\\r\\n#4 \[^\r\n\]* main \\(\\) at " +} + +# Load the script containing the unwinder. +gdb_test_no_output "source ${pyfile}"\ + "import python scripts" + +# Now look at the stack again, we should see output from the Python +# unwinder mixed in. +gdb_test_sequence "bt" "Backtrace with extra Python output" { + "Func f0, Level 0" + "Func f1, Level 1" + "\\r\\n#0 \[^\r\n\]* f0 \\(\\) at " + "\\r\\n#1 \[^\r\n\]* f1 \\(\\) at " + "Func f2, Level 2" + "\\r\\n#2 \[^\r\n\]* f2 \\(\\) at " + "Func f3, Level 3" + "\\r\\n#3 \[^\r\n\]* f3 \\(\\) at " + "Func main, Level 4" + "\\r\\n#4 \[^\r\n\]* main \\(\\) at " +} diff --git a/gdb/testsuite/gdb.python/py-pending-frame-level.py b/gdb/testsuite/gdb.python/py-pending-frame-level.py new file mode 100644 index 0000000..87b226c --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pending-frame-level.py @@ -0,0 +1,55 @@ +# Copyright (C) 2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import gdb +from gdb.unwinder import Unwinder + + +class FrameId(object): + def __init__(self, sp, pc): + self._sp = sp + self._pc = pc + + @property + def sp(self): + return self._sp + + @property + def pc(self): + return self._pc + + +class TestUnwinder(Unwinder): + def __init__(self): + Unwinder.__init__(self, "show level") + + def __call__(self, pending_frame): + pc_desc = pending_frame.architecture().registers().find("pc") + pc = pending_frame.read_register(pc_desc) + + block = gdb.block_for_pc(int(pc)) + if block is None: + return None + func = block.function + if func is None: + return None + + print("Func %s, Level %d" % (str(func), pending_frame.level())) + + # This unwinder never claims any frames. + return None + + +gdb.unwinder.register_unwinder(None, TestUnwinder(), True) |