mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-28 01:50:48 +00:00
Commits: commitaaad5a3254Author: Tom de Vries <tdevries@suse.de> Date: Fri Sep 5 15:36:23 2025 +0200 [gdb/testsuite] Fix clean_restart <absolute filename> in gdb.base, part 3 commit2e61486fceAuthor: Tom de Vries <tdevries@suse.de> Date: Fri Sep 5 15:36:23 2025 +0200 [gdb/testsuite] Fix clean_restart <absolute filename> in gdb.base, part 2 commit202beb3feeAuthor: Tom de Vries <tdevries@suse.de> Date: Fri Sep 5 15:36:23 2025 +0200 [gdb/testsuite] Fix clean_restart <absolute filename> in gdb.base, part 1 were made to work around the changes to clean_restart in commit: commitcba778b944Date: Sun Sep 7 11:53:30 2025 +0200 [gdb/testsuite] Error out on clean_restart <absolute filename> These commits added a lot of calls to gdb_load which can be removed in many cases by passing $testfile to clean_restart, or by switching to use prepare_for_testing to compile the test executable. In this commit I've gone through the gdb.base/ directory and removed as many of the gdb_load calls as possible. I was only looking for places where the gdb_load call immediately follows the call to clean_restart. And I did skip a few where it was not as simple as just passing $testfile. Where possible I've updated tests to use calls to prepare_for_testing, and simply removed the clean_restart call altogether (this is done as part of prepare_for_testing). This is, I think, the best solution. In other cases I've removed the gdb_load call, and passed $testfile to clean_restart. I've preferred $::testfile to adding a 'global' declaration, and in some cases switching to testfile has allowed me to remove the 'global binfile' as an additional cleanup. I ran the complete set of tests that I touched and I didn't see any regressions, so I don't believe I broke anything. I know that there are probably gdb_load calls that can be cleaned up in other testsuite sub-directories, if/when this patch is merged I'll take a look at those too. Reviewed-By: Tom de Vries <tdevries@suse.de>
300 lines
9.4 KiB
Plaintext
300 lines
9.4 KiB
Plaintext
# Copyright 2024-2025 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/>.
|
|
|
|
# Tests for GDB's handling of a shared library being unloaded via a
|
|
# call to dlclose. See the individual test_* procs for a description
|
|
# of each test.
|
|
|
|
standard_testfile .c -lib.c
|
|
|
|
# One of the tests uses this Python file. The test_* proc checks that
|
|
# GDB supports Python tests. Some of the other procs don't use this
|
|
# Python file.
|
|
set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
|
|
|
# Build the library and copy it to the target.
|
|
set libname ${testfile}-lib
|
|
set libfile [standard_output_file $libname]
|
|
if { [build_executable "build shlib" $libfile $srcfile2 {debug shlib}] == -1} {
|
|
return
|
|
}
|
|
set libfile_on_target [gdb_download_shlib $libfile]
|
|
|
|
# Build the executable.
|
|
set opts [list debug shlib_load additional_flags=-DSHLIB_NAME=\"${libname}\"]
|
|
if { [build_executable "build exec" $binfile $srcfile $opts] == -1} {
|
|
return
|
|
}
|
|
|
|
# The line number of the dlclose call.
|
|
set bp_line [gdb_get_line_number "Break here" $srcfile]
|
|
|
|
# If the target is remote, then the library name in the bp_disabled_re
|
|
# below will have a 'target:' prefix.
|
|
if {[is_remote target]} {
|
|
set target_prefix_re "target:"
|
|
} else {
|
|
set target_prefix_re ""
|
|
}
|
|
|
|
# The line emitted when GDB disables breakpoints after unloading a
|
|
# shared library.
|
|
set bp_disabled_re "warning: Temporarily disabling breakpoints for unloaded shared library \"$target_prefix_re[string_to_regexp $::libfile_on_target]\""
|
|
|
|
# The complete regexp for when GDB stops on the line after BP_LINE,
|
|
# assuming that GDB has disabled some breakpoints.
|
|
set stop_after_bp_re [multi_line \
|
|
"^$::bp_disabled_re" \
|
|
"[expr {$::bp_line + 1}]\\s+assert \\(res == 0\\);"]
|
|
|
|
# Checking that a breakpoint with multiple locations in a shared
|
|
# library only triggers a single breakpoint modified event from
|
|
# disable_breakpoints_in_unloaded_shlib when the shared library is
|
|
# unloaded.
|
|
proc_with_prefix test_bp_modified_events {} {
|
|
if { ![allow_python_tests] } {
|
|
unsupported "python support needed"
|
|
return
|
|
}
|
|
|
|
clean_restart $::testfile
|
|
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
|
|
# If the debug information doesn't allow GDB to identify inline
|
|
# functions then this test isn't going to work.
|
|
get_debug_format
|
|
if { [skip_inline_frame_tests] } {
|
|
unsupported "skipping inline frame tests"
|
|
return
|
|
}
|
|
|
|
gdb_breakpoint $::srcfile:$::bp_line
|
|
gdb_continue_to_breakpoint "stop before dlclose"
|
|
|
|
gdb_breakpoint inline_func
|
|
set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
|
|
"get b/p number"]
|
|
|
|
gdb_test_no_output "source $::pyfile" "import python scripts"
|
|
|
|
gdb_test "next" $::stop_after_bp_re
|
|
|
|
# The breakpoint should have been modified once when some of its
|
|
# locations are made pending after the shared library is unloaded.
|
|
gdb_test_multiple "python print(bp_modified_counts\[$bp_num\])" "" {
|
|
-re -wrap "^1" {
|
|
pass $gdb_test_name
|
|
}
|
|
-re -wrap "^2" {
|
|
# A second event occurs when the pending breakpoint is
|
|
# incorrectly deleted.
|
|
kfail gdb/32404 $gdb_test_name
|
|
}
|
|
-re -wrap "^$::decimal" {
|
|
fail $gdb_test_name
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check that GDB disables dprintf breakpoints within a shared library
|
|
# when the shared library is unloaded.
|
|
proc_with_prefix test_dprintf_after_unload {} {
|
|
clean_restart $::testfile
|
|
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
|
|
gdb_breakpoint $::srcfile:$::bp_line
|
|
gdb_continue_to_breakpoint "stop before dlclose"
|
|
|
|
# Setup a dprintf within the shared library.
|
|
gdb_test "dprintf foo,\"In foo\""
|
|
set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
|
|
"get b/p number"]
|
|
|
|
# Unload the shared library, GDB should disable our b/p.
|
|
gdb_test "next" $::stop_after_bp_re
|
|
|
|
# Check that our b/p is now showing as disabled.
|
|
gdb_test "info breakpoints $bp_num" \
|
|
[multi_line \
|
|
"^Num\\s+Type\\s+Disp\\s+Enb\\s+Address\\s+What" \
|
|
"$bp_num\\s+dprintf\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
|
|
"\\s+printf \"In foo\""]
|
|
}
|
|
|
|
# Create a dprintf breakpoint in a shared library. Restart the
|
|
# inferior. We should not get an error about re-setting the dprintf
|
|
# breakpoint.
|
|
proc_with_prefix test_dprintf_with_rerun {} {
|
|
clean_restart $::testfile
|
|
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
|
|
gdb_breakpoint $::srcfile:$::bp_line
|
|
gdb_continue_to_breakpoint "stop before dlclose"
|
|
|
|
# Setup a dprintf within the shared library.
|
|
gdb_test "dprintf foo,\"In foo\""
|
|
set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
|
|
"get b/p number"]
|
|
|
|
# Check that the dprintf b/p is initially not pending.
|
|
gdb_test "info breakpoints $bp_num" \
|
|
[multi_line \
|
|
"^Num\\s+Type\\s+Disp\\s+Enb\\s+Address\\s+What" \
|
|
"$bp_num\\s+dprintf\\s+keep\\s+y\\s+$::hex\\s+in foo at \[^\r\n\]+" \
|
|
"\\s+printf \"In foo\""] \
|
|
"dprintf is non-pending before restart"
|
|
|
|
# Restart the inferior.
|
|
gdb_run_cmd
|
|
|
|
# The inferior will stop at the initial 'main' breakpoint. This
|
|
# is at a location before any of the shlibs have been loaded.
|
|
set saw_bp_reset_error false
|
|
set saw_bp_disable_warning false
|
|
gdb_test_multiple "" "stop before shlib are reloaded" {
|
|
-re "warning: Temporarily disabling breakpoints for unloaded shared library \"\[^\r\n\]+/$::libname\"\r\n" {
|
|
set saw_bp_disable_warning true
|
|
exp_continue
|
|
}
|
|
|
|
-re "Error in re-setting breakpoint $bp_num: \[^\r\n\]+" {
|
|
set saw_bp_reset_error true
|
|
exp_continue
|
|
}
|
|
|
|
-re "Breakpoint $::decimal, main \\(\\) at \[^\r\n\]+\r\n$::decimal\\s+\[^\r\n\]+\r\n$::gdb_prompt $" {
|
|
gdb_assert { !$saw_bp_reset_error && !$saw_bp_disable_warning } $gdb_test_name
|
|
}
|
|
}
|
|
|
|
# Check that the dprintf b/p is still enabled, but marked pending
|
|
# before the shlib are loaded.
|
|
gdb_test "info breakpoints $bp_num" \
|
|
[multi_line \
|
|
"^Num\\s+Type\\s+Disp\\s+Enb\\s+Address\\s+What" \
|
|
"$bp_num\\s+dprintf\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
|
|
"\\s+printf \"In foo\""] \
|
|
"dprintf is pending before shlib reload"
|
|
|
|
set saw_in_foo_output false
|
|
gdb_test_multiple "continue" "stop after libraries are reloaded" {
|
|
-re "^continue\r\n" {
|
|
exp_continue
|
|
}
|
|
-re "^Continuing\\.\r\n" {
|
|
exp_continue
|
|
}
|
|
-re "^In foo\r\n" {
|
|
set saw_in_foo_output true
|
|
exp_continue
|
|
}
|
|
-re "^Breakpoint $::decimal, main \\(\\) at .* Break here\\. \\*/\r\n$::gdb_prompt $" {
|
|
gdb_assert { $saw_in_foo_output } $gdb_test_name
|
|
}
|
|
}
|
|
|
|
# Check that the dprintf b/p is still enabled, but is now, no
|
|
# longer pending.
|
|
gdb_test "info breakpoints $bp_num" \
|
|
[multi_line \
|
|
"^Num\\s+Type\\s+Disp\\s+Enb\\s+Address\\s+What" \
|
|
"$bp_num\\s+dprintf\\s+keep\\s+y\\s+$::hex\\s+in foo at \[^\r\n\]+" \
|
|
"\\s+breakpoint already hit 1 time" \
|
|
"\\s+printf \"In foo\""] \
|
|
"dprintf is non-pending after restart"
|
|
}
|
|
|
|
# Check that we see breakpoint modified events (where appropriate)
|
|
# when the 'nosharedlibrary' command is used to unload all shared
|
|
# libraries.
|
|
#
|
|
# Also check that the 'nosharedlibrary' doesn't trigger a warning
|
|
# about shared library breakpoints being disabled.
|
|
proc_with_prefix test_silent_nosharedlib {} {
|
|
if { ![allow_python_tests] } {
|
|
unsupported "python support needed"
|
|
return
|
|
}
|
|
|
|
foreach_with_prefix type { breakpoint dprintf } {
|
|
clean_restart $::testfile
|
|
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
|
|
gdb_breakpoint $::srcfile:$::bp_line
|
|
gdb_continue_to_breakpoint "stop before dlclose"
|
|
|
|
# Setup a dprintf or breakpoint in the shared library.
|
|
if { $type eq "breakpoint" } {
|
|
gdb_test "break foo"
|
|
} else {
|
|
gdb_test "dprintf foo,\"In foo\""
|
|
}
|
|
|
|
# Record the number of the b/p (or dprintf) we just inserted.
|
|
set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
|
|
"get b/p number"]
|
|
|
|
# Load Python library to track b/p modifications.
|
|
gdb_test_no_output "source $::pyfile" "import python scripts"
|
|
|
|
# Initialise the b/p modified hash. Currently dprintf style
|
|
# breakpoints are not visible from Python, so the modification
|
|
# count will remain unchanged in that case.
|
|
gdb_test_no_output "python bp_modified_counts\[$bp_num\] = 0"
|
|
|
|
# Discard symbols from all loaded shared libraries.
|
|
gdb_test_no_output "nosharedlibrary"
|
|
|
|
# Check that our b/p is now showing as disabled.
|
|
if { $type eq "breakpoint" } {
|
|
set re \
|
|
[list "$bp_num\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo"]
|
|
set count 1
|
|
} else {
|
|
set re \
|
|
[list \
|
|
"$bp_num\\s+dprintf\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
|
|
"\\s+printf \"In foo\""]
|
|
set count 0
|
|
}
|
|
|
|
gdb_test "info breakpoints $bp_num" \
|
|
[multi_line "^Num\\s+Type\\s+Disp\\s+Enb\\s+Address\\s+What" \
|
|
{*}$re]
|
|
|
|
# Check we've seen the expected number of breakpoint modified
|
|
# events. Currently dprintf breakpoints are not visible from
|
|
# Python, so we will not see an event in that case.
|
|
gdb_test "python print(bp_modified_counts\[$bp_num\])" "^$count"
|
|
}
|
|
}
|
|
|
|
test_bp_modified_events
|
|
test_dprintf_after_unload
|
|
test_dprintf_with_rerun
|
|
test_silent_nosharedlib
|