1 # Copyright 2024 Free Software Foundation, Inc.
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.
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.
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/>.
16 # Test that the condition for a catchpoint is correctly reset after
17 # shared libraries are unloaded, as happens when an inferior is
20 # If this is not done then, when the catchpoint is hit on the second
21 # run, we'll evaluate the parsed expression from the first run, which
22 # might include references to types owned by the now deleted objfile
23 # (for the shared library loaded in the first run).
25 # This scripts tests a number of different catchpoint types. Inside
26 # GDB these are all sub-classes of the 'catchpoint' type, which is
27 # where the fix for the above issue resides, so all catchpoint types
28 # should work correctly.
30 standard_testfile .c -lib.c
32 set libfile $binfile-lib.so
34 set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
36 if {[build_executable "build shared library" $libfile $srcfile2 \
37 {debug shlib}] == -1} {
41 # Depending on whether or not libc debug info is installed, when we
42 # hit a syscall catchpoint inside libc there might be a source line
43 # included in the output.
45 # This regexp will match an optional line and can be added to the
46 # expected catchpoint output to ignore the (possibly missing) source
48 set libc_src_line_re "(?:\r\n\[^\r\n\]+)?"
50 # Check the Python bp_modified_list and then reset the list back to
51 # empty. TESTNAME is just a string. BP_NUM is a list of breakpoint
52 # numbers that are expected to appear (in the given order) in the
55 proc check_modified_bp_list { testname bp_num } {
56 if { [allow_python_tests] } {
57 set expected [join $bp_num ", "]
59 gdb_test "python print(bp_modified_list)" "\\\[$expected\\\]" \
61 gdb_test_no_output -nopass "python bp_modified_list=\[\]" \
62 "reset bp_modified_list after $testname"
66 # Build an executable and run tests on 'catch MODE'.
68 proc run_test { mode } {
69 set exec_name ${::binfile}-${mode}
71 set macro TEST_[string toupper $mode]
73 if {[build_executable "build test executable" $exec_name $::srcfile \
74 [list debug shlib=$::libfile additional_flags=-D${macro}]] == -1} {
78 clean_restart $exec_name
79 gdb_load_shlib $::libfile
85 if { $mode eq "syscall" } {
86 gdb_test "catch syscall write" \
87 "Catchpoint $::decimal \\(syscall 'write' \[^)\]+\\)"
88 set catch_re "call to syscall write"
89 } elseif { $mode eq "signal" } {
90 gdb_test "catch signal SIGUSR1" \
91 "Catchpoint $::decimal \\(signal SIGUSR1\\)"
92 set catch_re "signal SIGUSR1"
93 } elseif { $mode eq "fork" } {
94 gdb_test "catch fork" \
95 "Catchpoint $::decimal \\(fork\\)"
96 set catch_re "forked process $::decimal"
98 error "unknown mode $mode"
100 set cp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*"]
102 gdb_breakpoint "breakpt_before_exit"
104 gdb_test "continue" \
105 "Catchpoint ${cp_num} \[^\r\n\]+$::libc_src_line_re"
107 if { [allow_python_tests] } {
108 gdb_test_no_output "source $::pyfile" "import python scripts"
109 check_modified_bp_list \
110 "check b/p modified observer has not yet triggered" {}
113 with_test_prefix "with false condition" {
114 gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) != 0" \
115 "set catchpoint condition"
117 check_modified_bp_list \
118 "catchpoint modified once by setting condition" \
122 gdb_test "" [multi_line \
123 "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
124 "$::decimal\\s+\[^\r\n\]+"]
126 check_modified_bp_list "catchpoint modified twice at startup" \
127 [list $cp_num $cp_num "$::decimal"]
129 gdb_test "continue" \
131 "Breakpoint $::decimal, breakpt_before_exit \\(\\) at \[^\r\n\]+" \
132 "$::decimal\\s+\[^\r\n\]+"] \
133 "continue to breakpt_before_exit"
136 # Check the bp_modified_list against '.*'. We don't care at this
137 # point what's in the list (nothing relevant has happened since we
138 # last checked), but this has the side effect of clearing the list.
139 check_modified_bp_list "clear bp modified list" { .* }
141 with_test_prefix "with true condition" {
142 gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) == 0" \
143 "set catchpoint condition"
145 check_modified_bp_list \
146 "catchpoint modified once by setting condition" \
150 gdb_test "" [multi_line \
151 "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
152 "$::decimal\\s+\[^\r\n\]+"]
154 check_modified_bp_list "catchpoint modified twice at startup" \
155 [list $cp_num $cp_num "$::decimal"]
157 gdb_test "continue" \
158 "Catchpoint $cp_num \\($catch_re\\), \[^\r\n\]+$::libc_src_line_re" \
159 "continue until catchpoint hit"
161 check_modified_bp_list "catchpoint modified again when hit" \
167 foreach_with_prefix mode { syscall signal fork } {
168 if { $mode == "syscall"
169 && ( ![allow_xml_test] || ![supports_catch_syscall] ) } {