aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2025-07-08 16:54:44 -0400
committerSimon Marchi <simon.marchi@efficios.com>2025-09-02 13:50:21 -0400
commit3a0bf6d1926c61781d40ec7d948fd9a445f316a8 (patch)
tree28ef7ff1ab9b4b2670bd3748d5202b4ef26c05a5
parent0a2ec1daf9339d105e83d73ecabe65e73bb6f84a (diff)
downloadbinutils-3a0bf6d1926c61781d40ec7d948fd9a445f316a8.zip
binutils-3a0bf6d1926c61781d40ec7d948fd9a445f316a8.tar.gz
binutils-3a0bf6d1926c61781d40ec7d948fd9a445f316a8.tar.bz2
gdb/remote: use scoped_restore_current_program_space in remote_unpush_target
Since commit 3cb6bc13e328 ("gdb/progspace: add solib_ops pointer in program_space"), this fails with an internal error: $ make check TESTS="gdb.server/extended-remote-restart.exp" RUNTESTFLAGS="--target_board=native-extended-gdbserver" In gdb.log: (gdb) PASS: gdb.server/extended-remote-restart.exp: kill: 1, follow-child 0: disconnect target extended-remote localhost:2347 Remote debugging using localhost:2347 /home/smarchi/src/binutils-gdb/gdb/progspace.h:240: internal-error: set_solib_ops: Assertion `m_solib_ops == nullptr' failed. The issue is that remote_unpush_target uses scoped_restore_current_inferior to save the context, which only restores the current inferior on exit. But it then uses switch_to_inferior_no_thread, which switches the inferior and the program space. The program space is therefore left unrestored. This can leave the current inferior and current program space out of sync. With two inferiors, let's say we enter with current inferior == 1 and current program space == 1. When calling switch_to_inferior_no_thread for inferior 2, we set the current inferior to 2 and current program space to 2. On exit, only the original inferior is restored, so we end up with current inferior == 1 and current program space == 2. The problem can be observed manually by starting two remote inferiors and disconnecting while inferior 1 is selected: $ ./gdb -nx --data-directory=data-directory -q \ -ex 'set sysroot /' \ -ex 'target extended-remote | gdbserver --multi --once -' \ -ex 'file /home/smarchi/build/wt/amd/gdb/testsuite/outputs/gdb.server/extended-remote-restart/extended-remote-restart' \ -ex 'set remote exec-file /home/smarchi/build/wt/amd/gdb/testsuite/outputs/gdb.server/extended-remote-restart/extended-remote-restart' \ -ex 'b main' \ -ex r \ -ex 'add-inferior' \ -ex 'inferior 2' \ -ex 'file /home/smarchi/build/wt/amd/gdb/testsuite/outputs/gdb.server/extended-remote-restart/extended-remote-restart' \ -ex 'run' \ -ex 'inferior 1' \ -ex 'disconnect' Then, connecting top-gdb to that gdb, we see the inconsistency: (top-gdb) p current_inferior_.m_obj.num $1 = 1 (top-gdb) p current_program_space.num $2 = 2 When the test tries to connect to a remote target again, GDB maps the remote inferior to inferior 1, but tries to set the solib_ops of program space 2, which already has an solib_ops set, causing the internal error. Fix this by using scoped_restore_current_program_space in addition to scoped_restore_current_inferior. With this patch applied, we get: (top-gdb) p current_inferior_.m_obj.num $1 = 1 (top-gdb) p current_program_space.num $2 = 1 With this patch, we then hit another internal error, fixed by the following patch. Change-Id: If916f581a223d6611f7f23a9cbbf1825d2cdd0ba Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
-rw-r--r--gdb/remote.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index 7c9950c..7b954b7 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -6167,6 +6167,7 @@ remote_unpush_target (remote_target *target)
/* We have to unpush the target from all inferiors, even those that
aren't running. */
scoped_restore_current_inferior restore_current_inferior;
+ scoped_restore_current_program_space restore_program_space;
for (inferior *inf : all_inferiors (target))
{