aboutsummaryrefslogtreecommitdiff
path: root/gdb/unittests
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@polymtl.ca>2022-12-13 22:34:39 -0500
committerSimon Marchi <simon.marchi@efficios.com>2023-01-20 14:48:57 -0500
commit836a8d3710462596bb4184617999a9507adc3629 (patch)
treeda76674260e0c55130bfe6931918cfd6a6b8e643 /gdb/unittests
parentbc2cbe815bdbac3bd027bf4acc94c554c29b0189 (diff)
downloadgdb-836a8d3710462596bb4184617999a9507adc3629.zip
gdb-836a8d3710462596bb4184617999a9507adc3629.tar.gz
gdb-836a8d3710462596bb4184617999a9507adc3629.tar.bz2
gdb: make user-created frames reinflatable
This patch teaches frame_info_ptr to reinflate user-created frames (frames created through create_new_frame, with the "select-frame view" command). Before this patch, frame_info_ptr doesn't support reinflating user-created frames, because it currently reinflates by getting the current target frame (for frame 0) or frame_find_by_id (for other frames). To reinflate a user-created frame, we need to call create_new_frame, to make it lookup an existing user-created frame, or otherwise create one. So, in prepare_reinflate, get the frame id even if the frame has level 0, if it is user-created. In reinflate, if the saved frame id is user create it, call create_new_frame. In order to test this, I initially enhanced the gdb.base/frame-view.exp test added by the previous patch by setting a pretty-printer for the type of the function parameters, in which we do an inferior call. This causes print_frame_args to not reinflate its frame (which is a user-created one) properly. On one machine (my Arch Linux one), it properly catches the bug, as the frame is not correctly restored after printing the first parameter, so it messes up the second parameter: frame #0 baz (z1=hahaha, z2=<error reading variable: frame address is not available.>) at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:40 40 return z1.m + z2.n; (gdb) FAIL: gdb.base/frame-view.exp: with_pretty_printer=true: frame frame #0 baz (z1=hahaha, z2=<error reading variable: frame address is not available.>) at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:40 40 return z1.m + z2.n; (gdb) FAIL: gdb.base/frame-view.exp: with_pretty_printer=true: frame again However, on another machine (my Ubuntu 22.04 one), it just passes fine, without the appropriate fix. I then thought about writing a selftest for that, it's more reliable. I left the gdb.base/frame-view.exp pretty printer test there, it's already written, and we never know, it might catch some unrelated issue some day. Change-Id: I5849baf77991fc67a15bfce4b5e865a97265b386 Reviewed-By: Bruno Larsen <blarsen@redhat.com>
Diffstat (limited to 'gdb/unittests')
-rw-r--r--gdb/unittests/frame_info_ptr-selftests.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/gdb/unittests/frame_info_ptr-selftests.c b/gdb/unittests/frame_info_ptr-selftests.c
new file mode 100644
index 0000000..edf1b9f
--- /dev/null
+++ b/gdb/unittests/frame_info_ptr-selftests.c
@@ -0,0 +1,80 @@
+/* Self tests for frame_info_ptr.
+
+ Copyright (C) 2022 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#include "defs.h"
+
+#include "frame.h"
+#include "gdbsupport/selftest.h"
+#include "scoped-mock-context.h"
+#include "test-target.h"
+
+namespace selftests {
+
+static void
+validate_user_created_frame (frame_id id)
+{
+ SELF_CHECK (id.stack_status == FID_STACK_VALID);
+ SELF_CHECK (id.stack_addr == 0x1234);
+ SELF_CHECK (id.code_addr_p);
+ SELF_CHECK (id.code_addr == 0x5678);
+}
+
+static frame_info_ptr
+user_created_frame_callee (frame_info_ptr frame)
+{
+ validate_user_created_frame (get_frame_id (frame));
+
+ frame.prepare_reinflate ();
+ reinit_frame_cache ();
+ frame.reinflate ();
+
+ validate_user_created_frame (get_frame_id (frame));
+
+ return frame;
+}
+
+static void
+test_user_created_frame ()
+{
+ scoped_mock_context<test_target_ops> mock_context
+ (current_inferior ()->gdbarch);
+ frame_info_ptr frame = create_new_frame (0x1234, 0x5678);
+
+ validate_user_created_frame (get_frame_id (frame));
+
+ /* Pass the frame to a callee, which calls reinit_frame_cache. This lets us
+ validate that the reinflation in both the callee and caller restore the
+ same frame_info object. */
+ frame.prepare_reinflate ();
+ frame_info_ptr callees_frame_info = user_created_frame_callee (frame);
+ frame.reinflate ();
+
+ validate_user_created_frame (get_frame_id (frame));
+ SELF_CHECK (frame.get () == callees_frame_info.get ());
+}
+
+} /* namespace selftests */
+
+void _initialize_frame_info_ptr_selftests ();
+void
+_initialize_frame_info_ptr_selftests ()
+{
+ selftests::register_test ("frame_info_ptr_user",
+ selftests::test_user_created_frame);
+}