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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# Copyright 2012-2023 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 case for forgotten hw-watchpoints after fork()-off of a process.
# The allow_hw_watchpoint_tests checks if watchpoints are supported by the
# processor. On PowerPC, the check runs a small test program under gdb
# to determine if the Power processor supports HW watchpoints. The check
# must be done before starting the test so as to not disrupt the execution
# of the actual test.
set allow_hw_watchpoint_tests_p [allow_hw_watchpoint_tests]
set testfile watchpoint-fork
# Set DEBUG to 0 or 1 in sources
set debug 0
proc test {type symbol} {
global allow_hw_watchpoint_tests_p
global debug
with_test_prefix "$type" {
global testfile subdir srcdir gdb_prompt
set srcfile_type ${srcdir}/${subdir}/${testfile}-${type}.c
# no threads
with_test_prefix "singlethreaded" {
set executable ${testfile}-${type}-st
set srcfile_main ${testfile}-st.c
if {[build_executable $testfile.exp $executable \
[list $srcfile_main ${testfile}-${type}.c] \
[list debug additional_flags=-D$symbol \
additional_flags=-DDEBUG=$debug]] == -1} {
return -1
}
clean_restart $executable
if {!$allow_hw_watchpoint_tests_p} {
# The software watchpoint functionality is in GDB an unrelated test.
gdb_test_no_output "set can-use-hw-watchpoints 0"
# Software watchpoints can be quite slow on remote targets
# on this test because it ends up single-stepping through
# code to initialize dynamic libraries, etc.
set factor 20
} else {
set factor 1
}
gdb_test "show detach-on-fork" "Whether gdb will detach the child of a fork is on\\."
gdb_test_no_output "set follow-fork-mode $type"
gdb_test "show follow-fork-mode" "Debugger response to a program call of fork or vfork is \"$type\"\\."
# Testcase uses it for the `follow-fork-mode child' type.
gdb_test "handle SIGUSR1 nostop noprint pass" "No\[ \t\]+No\[ \t\]+Yes.*"
if ![runto_main] {
return
}
gdb_test "watch var" "atchpoint \[0-9\]+: var" "set the watchpoint"
# It is never hit but it should not be left over in the fork()ed-off child.
if {![allow_hw_breakpoint_tests]} {
set hbreak "break"
} else {
set hbreak "hbreak"
}
gdb_test "$hbreak marker"
gdb_breakpoint "mark_exit"
with_timeout_factor $factor {
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "hardware breakpoints work"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work"
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "breakpoint after the first fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork"
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "breakpoint after the second fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 2.*New value = 3.*mark_exit \\(\\);" "watchpoint after the second fork"
gdb_test "continue" "Continuing\\..*\r\n(Thread .* hit )?Breakpoint \[0-9\]+, mark_exit .*" "finish"
}
}
# threads
if {!$allow_hw_watchpoint_tests_p} {
# Watchpoint hits would get detected in unexpected threads.
return
}
with_test_prefix "multithreaded" {
set executable ${testfile}-${type}-mt
set srcfile_main ${srcdir}/${subdir}/${testfile}-mt.c
if { [gdb_compile_pthreads "${srcfile_main} ${srcfile_type}" \
[standard_output_file ${executable}] executable \
[list debug "additional_flags=-D$symbol" \
"additional_flags=-DDEBUG=$debug" \
"-DTHREAD"]] != "" } {
untested "failed to compile"
return
}
clean_restart $executable
gdb_test_no_output "set follow-fork-mode $type"
# Testcase uses it for the `follow-fork-mode child' type.
gdb_test "handle SIGUSR1 nostop noprint pass" "No\[ \t\]+No\[ \t\]+Yes.*"
if ![runto_main] {
return
}
gdb_test "watch var" "atchpoint \[0-9\]+: var" "set the watchpoint"
# It should not be left over in the fork()ed-off child.
gdb_test "$hbreak marker" {reakpoint [0-9]+.*}
gdb_breakpoint "mark_exit"
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "hardware breakpoints work"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B"
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "breakpoint (A) after the first fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork"
gdb_test "continue" \
"reakpoint \[0-9\]+, marker.*" "breakpoint (A) after the second fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork"
gdb_test "continue" \
"atchpoint \[0-9\]+: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork"
gdb_test "continue" "Continuing\\..*\r\nThread .* hit Breakpoint \[0-9\]+, mark_exit .*" "finish"
}
}
}
test parent FOLLOW_PARENT
# Only GNU/Linux is known to support `set follow-fork-mode child'.
if [istarget "*-*-linux*"] {
test child FOLLOW_CHILD
} else {
untested "${testfile}: child"
}
|