aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2021-05-26 22:01:59 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2021-06-21 16:20:08 +0100
commitd52b8007213eea4d1f33e3a604481f390d37b52a (patch)
tree07158fe01e4d4d0edc2bf3e043d13198cb21d96e /gdb/testsuite
parent8b9c48b287d42d1c816f441e4273dcb8c7af1876 (diff)
downloadgdb-d52b8007213eea4d1f33e3a604481f390d37b52a.zip
gdb-d52b8007213eea4d1f33e3a604481f390d37b52a.tar.gz
gdb-d52b8007213eea4d1f33e3a604481f390d37b52a.tar.bz2
gdb/python: add PendingFrame.level and Frame.level methods
Add new methods to the PendingFrame and Frame classes to obtain the stack frame level for each object. The use of 'level' as the method name is consistent with the existing attribute RecordFunctionSegment.level (though this is an attribute rather than a method). For Frame/PendingFrame I went with methods as these classes currently only use methods, including for simple data like architecture, so I want to be consistent with this interface. gdb/ChangeLog: * 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. gdb/doc/ChangeLog: * python.texi (Unwinding Frames in Python): Mention PendingFrame.level. (Frames In Python): Mention Frame.level. gdb/testsuite/ChangeLog: * 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.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.python/py-frame.exp11
-rw-r--r--gdb/testsuite/gdb.python/py-pending-frame-level.c49
-rw-r--r--gdb/testsuite/gdb.python/py-pending-frame-level.exp65
-rw-r--r--gdb/testsuite/gdb.python/py-pending-frame-level.py55
5 files changed, 187 insertions, 0 deletions
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)