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
|
# Copyright (C) 2020-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 for PR tui/25126.
#
# The bug is about a regression that makes GDB not reload its source
# code cache when the inferior's symbols are reloaded, which leads to
# wrong backtraces/listings.
#
# This bug is reproducible even without using the TUI.
standard_testfile
# Only run on native boards.
if { [use_gdb_stub] || [target_info gdb_protocol] == "extended-remote" } {
return -1
}
# Because we need to modify the source file later, it's better if we
# just copy it to our output directory (instead of messing with the
# user's source directory).
set newsrc [standard_output_file $testfile].c
file copy -force -- $srcdir/$subdir/$srcfile $newsrc
set srcfile $newsrc
if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
return -1
}
# Get the line number for the line with the "break-here" marker.
set bp_line [gdb_get_line_number "break-here" $srcfile]
gdb_assert { [runto "$srcfile:$bp_line"] } \
"run to break-here marker"
# Do a "list" and check that the printed line matches the line of the
# original source file.
gdb_test_no_output "set listsize 1"
gdb_test "list" "$bp_line\[ \t\]+printf \\(\"hello\\\\n\"\\); /\\* break-here \\*/" \
"check the first version of the source file"
# Modify the original source file, and add an extra line into it.
# This only works locally because of the TCL commands.
set bkpsrc [standard_output_file $testfile].c.bkp
set bkpsrcfd [open $bkpsrc w]
set srcfd [open $srcfile r]
while { [gets $srcfd line] != -1 } {
if { [string first "break-here" $line] != -1 } {
# Put a "printf" line before the "break-here" line.
puts $bkpsrcfd " printf (\"foo\\n\"); /* new-marker */"
}
puts $bkpsrcfd $line
}
close $bkpsrcfd
close $srcfd
file rename -force -- $bkpsrc $srcfile
# We have to wait 1 second because of the way GDB checks whether the
# binary has changed or not. GDB uses stat(2) and currently checks
# 'st_mtime', whose precision is measured in seconds. Since the copy,
# rename, and rebuild can take less than 1 second, GDB might mistakenly
# assume that the binary is unchanged.
sleep 1
# Recompile the modified source. We use "gdb_compile" here instead of
# "prepare_for_testing" because we don't want to call "clean_restart".
if { [gdb_compile "${srcfile}" "${binfile}" executable {debug}] != "" } {
return -1
}
# Rerun the program. This should not only force GDB to reload the
# source cache, but also to break at BP_LINE again, which now has
# different contents.
set q \
[multi_line \
"The program being debugged has been started already\\." \
"Start it from the beginning\\? \\(y or n\\) "]
set binregex [string_to_regexp $binfile]
set re \
[multi_line \
"\\`$binregex\\' has changed; re-reading symbols\\.(" \
"Expanding full symbols from $binfile\\.\\.\\.)?" \
"Starting program: ${binregex}.*"]
gdb_test "run" $re "rerun program" $q y
# Again, perform the listing and check that the line indeed has
# changed for GDB.
gdb_test "list" "${bp_line}\[ \t\]+printf \\(\"foo\\\\n\"\\); /\\\* new-marker \\\*/.*" \
"verify that the source code is properly reloaded"
# Modify the source file again. As before, this only works locally
# because of the TCL commands.
set bkpsrc [standard_output_file $testfile].c.bkp
set bkpsrcfd [open $bkpsrc w]
set srcfd [open $srcfile r]
while { [gets $srcfd line] != -1 } {
if { [string first "new-marker" $line] != -1 } {
# Modify the printf line that we added previously.
puts $bkpsrcfd " printf (\"foo\\n\"); /* new-marker updated */"
} else {
puts $bkpsrcfd $line
}
}
close $bkpsrcfd
close $srcfd
file rename -force -- $bkpsrc $srcfile
# As before, delay so that at least one second has passed. GDB still
# will not spot that the source file has changed, as GDB doesn't do a
# time check unless the binary has also changed, this delay just
# allows us to confirm this behaviour.
sleep 1
# List the printf line again, we should not see the file changes yet
# as the binary is unchanged, so the cached contents will still be
# used.
gdb_test "list ${bp_line}" "${bp_line}\[ \t\]+printf \\(\"foo\\\\n\"\\); /\\\* new-marker \\\*/.*" \
"verify that the source code change is not seen yet"
gdb_test "maint flush source-cache" "Source cache flushed\\."
# List the printf line again. After the cache flush GDB will re-read
# the source file and we should now see the changes.
gdb_test "list ${bp_line}" "${bp_line}\[ \t\]+printf \\(\"foo\\\\n\"\\); /\\\* new-marker updated \\\*/.*" \
"verify that the updated source code change is not seen"
|