aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/exec.c5
-rw-r--r--gdb/infrun.c16
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.multi/multi-re-run-1.c61
-rw-r--r--gdb/testsuite/gdb.multi/multi-re-run-2.c61
-rw-r--r--gdb/testsuite/gdb.multi/multi-re-run.exp115
-rw-r--r--gdb/thread.c5
8 files changed, 265 insertions, 18 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3d166f0..16d16ef 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2020-01-24 Pedro Alves <palves@redhat.com>
+
+ PR gdb/25410
+ * thread.c (scoped_restore_current_thread::restore): Use
+ switch_to_inferior_no_thread.
+ * exec.c: Include "progspace-and-thread.h".
+ (add_target_sections, remove_target_sections):
+ scoped_restore_current_pspace_and_thread instead of
+ scoped_restore_current_thread.
+ * infrun.c (handle_vfork_child_exec_or_exit): Assign the pspace
+ and aspace to the inferior before calling clone_program_space.
+ Remove stale comment.
+
2020-01-24 Christian Biesinger <cbiesinger@google.com>
* arm-nbsd-nat.c (arm_nbsd_nat_target::fetch_registers): Rename to...
diff --git a/gdb/exec.c b/gdb/exec.c
index eb07b51..2506e84 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -33,6 +33,7 @@
#include "arch-utils.h"
#include "gdbthread.h"
#include "progspace.h"
+#include "progspace-and-thread.h"
#include "gdb_bfd.h"
#include "gcore.h"
#include "source.h"
@@ -547,7 +548,7 @@ add_target_sections (void *owner,
table->sections[space + i].owner = owner;
}
- scoped_restore_current_thread restore_thread;
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
program_space *curr_pspace = current_program_space;
/* If these are the first file sections we can provide memory
@@ -645,7 +646,7 @@ remove_target_sections (void *owner)
inferior sharing the program space. */
if (old_count + (dest - src) == 0)
{
- scoped_restore_current_thread restore_thread;
+ scoped_restore_current_pspace_and_thread restore_pspace_thread;
program_space *curr_pspace = current_program_space;
for (inferior *inf : all_inferiors ())
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 9c4a07d..22de42c 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1020,8 +1020,6 @@ handle_vfork_child_exec_or_exit (int exec)
}
else
{
- struct program_space *pspace;
-
/* If this is a vfork child exiting, then the pspace and
aspaces were shared with the parent. Since we're
reporting the process exit, we'll be mourning all that is
@@ -1037,18 +1035,12 @@ handle_vfork_child_exec_or_exit (int exec)
scoped_restore restore_ptid
= make_scoped_restore (&inferior_ptid, null_ptid);
- /* This inferior is dead, so avoid giving the breakpoints
- module the option to write through to it (cloning a
- program space resets breakpoints). */
- inf->aspace = NULL;
- inf->pspace = NULL;
- pspace = new program_space (maybe_new_address_space ());
- set_current_program_space (pspace);
+ inf->pspace = new program_space (maybe_new_address_space ());
+ inf->aspace = inf->pspace->aspace;
+ set_current_program_space (inf->pspace);
inf->removable = 1;
inf->symfile_flags = SYMFILE_NO_READ;
- clone_program_space (pspace, vfork_parent->pspace);
- inf->pspace = pspace;
- inf->aspace = pspace->aspace;
+ clone_program_space (inf->pspace, vfork_parent->pspace);
resume_parent = vfork_parent->pid;
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 3a97848..81500c2 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2020-01-24 Pedro Alves <palves@redhat.com>
+
+ PR gdb/25410
+ * gdb.multi/multi-re-run-1.c: New.
+ * gdb.multi/multi-re-run-2.c: New.
+ * gdb.multi/multi-re-run.exp: New.
+
2020-01-24 Andrew Burgess <andrew.burgess@embecosm.com>
PR gdb/23718
diff --git a/gdb/testsuite/gdb.multi/multi-re-run-1.c b/gdb/testsuite/gdb.multi/multi-re-run-1.c
new file mode 100644
index 0000000..91b0dbc
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/multi-re-run-1.c
@@ -0,0 +1,61 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2020 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/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <pthread.h>
+
+int re_run_var_1 = 1;
+
+#define NUM_THREADS 1
+
+__thread int tls_var = 1;
+
+static pthread_barrier_t barrier;
+
+static void *
+thread_start (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+
+ while (1)
+ sleep (1);
+ return NULL;
+}
+
+static void
+all_started (void)
+{
+}
+
+int
+main (int argc, char ** argv)
+{
+ pthread_t thread;
+ int len;
+
+ pthread_barrier_init (&barrier, NULL, NUM_THREADS + 1);
+ pthread_create (&thread, NULL, thread_start, NULL);
+
+ pthread_barrier_wait (&barrier);
+ all_started ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/multi-re-run-2.c b/gdb/testsuite/gdb.multi/multi-re-run-2.c
new file mode 100644
index 0000000..6925e0c
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/multi-re-run-2.c
@@ -0,0 +1,61 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2020 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/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <pthread.h>
+
+int re_run_var_2 = 2;
+
+#define NUM_THREADS 1
+
+__thread int tls_var = 1;
+
+static pthread_barrier_t barrier;
+
+static void *
+thread_start (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+
+ while (1)
+ sleep (1);
+ return NULL;
+}
+
+static void
+all_started (void)
+{
+}
+
+int
+main (int argc, char ** argv)
+{
+ pthread_t thread;
+ int len;
+
+ pthread_barrier_init (&barrier, NULL, NUM_THREADS + 1);
+ pthread_create (&thread, NULL, thread_start, NULL);
+
+ pthread_barrier_wait (&barrier);
+ all_started ();
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/multi-re-run.exp b/gdb/testsuite/gdb.multi/multi-re-run.exp
new file mode 100644
index 0000000..93cd709
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/multi-re-run.exp
@@ -0,0 +1,115 @@
+# Copyright 2020 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 loading two inferiors into GDB, and running one of them twice
+# in a row. GDB used to have a bug that made it so that after an
+# inferior exit, the current program space was left pointing to the
+# wrong inferior's pspace, causing subsequent symbol lookups to
+# misbehave, including failing to load libthread_db.so. See PR
+# gdb/25410.
+
+# Build two executables, with different symbols.
+
+set exec1 "multi-re-run-1"
+set srcfile1 multi-re-run-1.c
+set binfile1 [standard_output_file ${exec1}]
+
+set exec2 "multi-re-run-2"
+set srcfile2 multi-re-run-2.c
+set binfile2 [standard_output_file ${exec2}]
+
+with_test_prefix "exec1" {
+ if { [prepare_for_testing "failed to prepare" ${exec1} "${srcfile1}" \
+ [list pthreads debug]] } {
+ return -1
+ }
+}
+
+with_test_prefix "exec2" {
+ if { [prepare_for_testing "failed to prepare" ${exec2} "${srcfile2}" \
+ [list pthreads debug]] } {
+ return -1
+ }
+}
+
+# Start two inferiors, leave one stopped, and run the other a couple
+# times. RE_RUN_INF is the inferior that is re-run.
+
+proc test_re_run {re_run_inf} {
+ global binfile1 binfile2
+ global inferior_exited_re
+ global gdb_prompt
+
+ clean_restart ${binfile1}
+
+ delete_breakpoints
+
+ # Start another inferior.
+ gdb_test "add-inferior" "Added inferior 2.*" \
+ "add empty inferior 2"
+ gdb_test "inferior 2" "Switching to inferior 2.*" \
+ "switch to inferior 2"
+ gdb_load ${binfile2}
+
+ if {$re_run_inf == 1} {
+ set steady_inf 2
+ } else {
+ set steady_inf 1
+ }
+
+ gdb_test "inferior $steady_inf" "Switching to inferior $steady_inf.*" \
+ "switch to steady inferior"
+
+ # Run the steady inferior to a breakpoint, and let it stay stopped
+ # there.
+ if ![runto all_started message] then {
+ untested "setup failed"
+ return 0
+ }
+
+ gdb_test "inferior $re_run_inf" "Switching to inferior $re_run_inf.*" \
+ "switch to re-run inferior"
+
+ # Now run the RE_RUN_INF inferior a couple times. GDB used to
+ # have a bug that caused the second run to fail to load
+ # libthread_db.so.
+ foreach_with_prefix iter {1 2} {
+ delete_breakpoints
+
+ if ![runto all_started message] {
+ return 0
+ }
+
+ # If a thread_stratum target fails to load, then TLS debugging
+ # fails too.
+ gdb_test "print tls_var" " = 1"
+
+ gdb_continue_to_end "" continue 1
+
+ # In the original bug, after an inferior exit, GDB would leave
+ # the current program space pointing to the wrong inferior's
+ # pspace, and thus the wrong symbols were visible.
+ if {$re_run_inf == 1} {
+ gdb_test "print re_run_var_1" " = 1"
+ } else {
+ gdb_test "print re_run_var_2" " = 2"
+ }
+ }
+}
+
+# For completeness, test re-running either inferior 1 or inferior 2.
+foreach_with_prefix re_run_inf {1 2} {
+ test_re_run $re_run_inf
+}
diff --git a/gdb/thread.c b/gdb/thread.c
index 001fdd4..302a49e 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1429,10 +1429,7 @@ scoped_restore_current_thread::restore ()
&& m_inf->pid != 0)
switch_to_thread (m_thread);
else
- {
- switch_to_no_thread ();
- set_current_inferior (m_inf);
- }
+ switch_to_inferior_no_thread (m_inf);
/* The running state of the originally selected thread may have
changed, so we have to recheck it here. */