xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.multi/attach-while-running.exp (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1# Copyright 2022-2023 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# This test was introduced to reproduce a specific bug in GDBserver, where
17# attaching an inferior while another one was running would trigger a segfault
18# in GDBserver.  Reproducing the bug required specific circumstances:
19#
20#  - The first process must be far enough to have loaded its libc or
21#    libpthread (whatever triggers the loading of libthread_db), such that
22#    its proc->priv->thread_db is not nullptr
23#
24#  - However, its lwp must still be in the `!lwp->thread_known` state,
25#    meaning GDBserver hasn't asked libthread_db to compute the thread
26#    handle yet.  That means, GDB must not have refreshed the thread list
27#    yet, since that would cause the thread handles to be computed.  That
28#    means, no stopping on a breakpoint, since that causes a thread list
29#    update.  That's why the first inferior needs to be started with "run
30#    &".
31#
32#  - Attaching the second process would segfault GDBserver.
33#
34# All of this to say, if modifying this test, please keep in mind the original
35# intent.
36
37standard_testfile
38
39if [use_gdb_stub] {
40    unsupported "test requires running"
41    return
42}
43
44if { [build_executable "failed to prepare" ${testfile} ${srcfile}] } {
45    return
46}
47
48proc do_test {} {
49    save_vars { $::GDBFLAGS } {
50	append ::GDBFLAGS " -ex \"maint set target-non-stop on\""
51	clean_restart $::binfile
52    }
53
54    gdb_test -no-prompt-anchor "run &"
55    gdb_test "add-inferior" "Added inferior 2 on connection 1 .*"
56    gdb_test "inferior 2" "Switching to inferior 2 .*"
57
58    set spawn_id [spawn_wait_for_attach $::binfile]
59    set pid [spawn_id_get_pid $spawn_id]
60
61    # This call would crash GDBserver.
62    gdb_attach $pid
63
64    # Read a variable from the inferior, just to make sure the attach worked
65    # fine.
66    gdb_test "print global_var" " = 123"
67}
68
69do_test
70