Files
binutils-gdb/gdb/testsuite/gdb.base/shlib-unload.exp
Andrew Burgess 25902bd0ba gdb/testsuite: make more use of clean_restart's argument
Commits:

  commit aaad5a3254
  Author: 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

  commit 2e61486fce
  Author: 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

  commit 202beb3fee
  Author: 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:

  commit cba778b944
  Date:   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>
2025-12-01 14:00:47 +00:00

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