--- /dev/null
+# Copyright 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/>.
+
+# Test that when loading a core file, if the current executable
+# doesn't match the expected executable for this core file, then GDB
+# should give a warning.
+#
+# We only check the build-id based verification as the name only based
+# verification relies on the name held in the PRPSINFO note, which is
+# only 80 characters long, as a result, when running the testsuite,
+# this string usually only holds the path to the testsuite build
+# directory, which might be the same for every core file created.
+#
+# In addition, as the check is in a similar area of GDB, we check that
+# if the executable is newer than the core file, GDB gives a warning.
+
+# The core file management in this script only works if the host
+# machine is local.
+require {!is_remote host}
+
+standard_testfile .c
+
+# Build an executable with a build id.
+if { [build_executable "build" $testfile $srcfile \
+ { debug build-id additional_flags=-DGEN_CORE } ] } {
+ return
+}
+
+# Build an alternative executable. This is different than
+# TESTFILE, and so has a different build-id.
+set alt_testfile "alt-with-build-id"
+set alt_binfile [standard_output_file $alt_testfile]
+if { [build_executable "build" $alt_testfile $srcfile \
+ { debug build-id } ] } {
+ return
+}
+
+# Do we expect the build-id for BINFILE to appear in a core file
+# generated from BINFILE? If not then this test isn't going to
+# work.
+if { ![expect_build_id_in_core_file $binfile] } {
+ unsupported "build-id will not appear in core file"
+ return
+}
+
+# Create a core file by running BINFILE.
+set corefile [core_find $binfile {}]
+if {$corefile == ""} {
+ untested "unable to create corefile"
+ return
+}
+
+# Start GDB using a completely different executable (than was used
+# to generate the core file); this has a different filename and
+# build-id.
+clean_restart $alt_testfile
+
+# Load the core file. GDB should warn because the build-id of the
+# executable doesn't match the expected build-id pulled from the
+# core file.
+set saw_mismatch_warning false
+gdb_test_multiple "core $corefile" "load core file, different exec name" {
+ -re "^core \[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ -re "^warning: core file may not match specified executable file\\.\r\n" {
+ set saw_mismatch_warning true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_mismatch_warning } $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+# Cleanup before the next test.
+unset saw_mismatch_warning
+gdb_exit
+
+# Touch TESTFILE (via its full filename) so that it is newer than
+# the core file.
+sleep 1
+remote_exec host "touch ${binfile}"
+
+# Start GDB using the correct executable, but this file is newer than
+# the core file, we expect GDB to warn about this.
+clean_restart $testfile
+
+# Load the core file. GDB should warn that the executable is
+# newer than the core file.
+#
+# NOTE: In this case the build-ids match, so maybe GDB should
+# ignore the fact that the core file is older than the executable?
+# If we every make that change to GDB, and this test starts to
+# fail, then the test should be updated to build executables
+# without build-ids so that this warning is still tested.
+#
+# The reason I didn't do this initially is that, if there are any
+# build-ids in the core file, from any shared library at all, then
+# GDB will use this as "the" build-id for the core file, and
+# compare this to the build-id of the executable. I say GDB here,
+# but some of this logic is in BFD. Anyway, if GDB thinks that
+# the core file has a build-id, but the executable doesn't, then
+# GDB gives the generic "core file may not match specified
+# executable file" warning instead of the "exec file is newer than
+# core file" warning, which is what we want.
+#
+# For now then, I just check for the age based warning when we
+# also have full build-ids.
+set saw_age_warning false
+gdb_test_multiple "core $corefile" "load core file, exec is newer" {
+ -re "^core \[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ -re "^warning: exec file is newer than core file\\.\r\n" {
+ set saw_age_warning true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_age_warning } $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+# Cleanup before the next test.
+unset saw_age_warning
+gdb_exit
+
+# Replace BINFILE with ALT_BINFILE, a file with a different
+# build-id.
+remote_exec host "mv $binfile ${binfile}-hidden"
+remote_exec host "cp $alt_binfile $binfile"
+
+# Ensure COREFILE is newer than BINFILE.
+sleep 1
+remote_exec host "touch ${corefile}"
+
+# Start GDB using the filename that now points to the replacement
+# file.
+clean_restart $testfile
+
+# Load the core file. GDB should use the build-id to warn the
+# user that the executable doesn't match the core file. We'll
+# also get a warning that the build-id of the executable doesn't
+# match while processing the mapped file information in the core
+# file.
+set saw_mismatch_warning false
+set saw_build_id_warning false
+gdb_test_multiple "core $corefile" "load core file, same exec name" {
+ -re "^core \[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ -re "^warning: File [string_to_regexp $binfile] doesn't match build-id from core-file during file-backed mapping processing" {
+ set saw_build_id_warning true
+ exp_continue
+ }
+ -re "^warning: core file may not match specified executable file\\.\r\n" {
+ set saw_mismatch_warning true
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_mismatch_warning \
+ && $saw_build_id_warning } $gdb_test_name
+ }
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+unset saw_mismatch_warning
+unset saw_build_id_warning
+gdb_exit