aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.mi/mi-nsmoribund.exp
blob: a0ef91ce6dad06f0e2eacb2dc2b392cb3043969a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Copyright 2008-2016 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/>.

if { ![support_displaced_stepping] } { 
    unsupported "displaced stepping"
    return -1
}

load_lib mi-support.exp
set MIFLAGS "-i=mi"

gdb_exit
if {[mi_gdb_start]} {
    continue
}

#
# Start here
#
standard_testfile nsmoribund.c

set options [list debug]
if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } {
    return -1
}

mi_gdb_reinitialize_dir $srcdir/$subdir
mi_gdb_load $binfile

mi_gdb_test "-gdb-set non-stop 1" ".*"
mi_gdb_test "-gdb-set mi-async 1" ".*"
mi_detect_async

if { [mi_run_to_main] < 0 } {
    continue
}

# Keep this in sync with THREADS in the $srcfile.
set nthreads 10

# Set a breakpoint and let all threads hit it (except the main
# thread).

set bkpt_line [gdb_get_line_number "set breakpoint here"]

mi_create_breakpoint "$srcfile:$bkpt_line" \
    "breakpoint at thread_function" \
    -number 2 -function thread_function

mi_send_resuming_command "exec-continue --all" "resume all"
for {set i 0} {$i < $nthreads} {incr i} {
    mi_expect_stop "breakpoint-hit" "thread_function" "\[^\n\]*" "$srcfile" \
	"\[0-9\]*" {"" "disp=\"keep\""} "stop $i"
}

# All but the main thread should have hit it.

mi_check_thread_states \
    {"running" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped"} \
    "thread state: all stopped except the main thread"

# Select a stopped thread to make sure we're able to delete
# breakpoints
mi_gdb_test "-thread-select 5" "\\^done.*" "select thread 5"

# Now that we know about all the threads, we can get rid of
# breakpoint.
mi_delete_breakpoints

# Recreate the same breakpoint, but this time, specific to thread 5.
mi_gdb_test "234-break-insert -p 5 $srcfile:$bkpt_line" \
    "234\\^done,bkpt=\{number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\".*\",func=\"thread_function\",file=\".*\",fullname=\".*\",line=\".*\",thread-groups=\\\[\".*\"\\\],thread=\"5\",thread=\"5\",times=\"0\",original-location=\".*\"\}" \
    "thread specific breakpoint at thread_function" 

# Resume all threads.  Only thread 5 should report a stop.

set running_re ""
for {set i $nthreads} {$i > 1} {incr i -1} {
    set running_re "$running_re\\*running,thread-id=\"$decimal\"\r\n"
}
# Don't append \r\n after last line.
set running_re "$running_re\\*running,thread-id=\"$decimal\""

mi_gdb_test "-exec-continue --all" "\[^\n\]*\r\n$running_re" \
    "resume all, thread specific breakpoint"

mi_expect_stop "breakpoint-hit" "thread_function" "\[^\n\]*" "$srcfile" \
    "\[0-9\]*" {"" "disp=\"keep\""} "hit thread specific breakpoint"

# All threads except both thread 5 (and the main thread) should now be
# repeatedly hitting the thread specific breakpoint and stepping over
# it transparently.  These are internal events, so the frontend should
# see those threads as running.

mi_check_thread_states \
    {"running" "running" "running" "running" "stopped" "running" "running" "running" "running"} \
    "thread state: all running except the breakpoint thread"

# Get rid of the breakpoint while the other threads are stepping over
# it, and tell all threads to exit.  The program should exit
# gracefully shortly.  Send all commands in a row, since if something
# goes wrong with moribund locations support or displaced stepping (or
# a target bug if it can step over breakpoints itself), a spurious
# SIGTRAP/SIGSEGV can come at any time after deleting the breakpoint.
# Note that this causes multiple prompts to appear before the output
# we are interested in, so we can't use mi_gdb_test or
# gdb_test_multiple (or an MI equivalent)

mi_gdb_test "102-break-delete" "102\\^done.*"
mi_gdb_test "print done = 1" { = 1"}
mi_gdb_test "103-exec-continue --all" "\[^\n\]*\r\n$running_re"

gdb_expect {
    -re "\\*stopped,reason=\"exited-normally\"" {
       pass "resume all, program exited normally"
    }
    timeout {
       fail "resume all, waiting for program exit (timeout)"
    }
}

mi_gdb_exit