# 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 . # Check GDB's ability to auto-load the executable based on the file # names extracted from the core file. # # Currently, only Linux supports reading full executable and arguments # from a core file. require {is_any_target "*-*-linux*" "*-*-freebsd*"} standard_testfile if {[build_executable $testfile.exp $testfile $srcfile {debug build-id}] == -1} { untested "failed to compile" return -1 } # Load the COREFILE and confirm that GDB auto-loads the executable. # The symbols should be read from SYMBOL_FILE and the core file should # be reported as generated by GEN_FROM_FILE. proc test_load { corefile symbol_file gen_from_file } { clean_restart set saw_generated_line false set saw_reading_symbols false gdb_test_multiple "core-file $corefile" "load core file" { -re "^Reading symbols from [string_to_regexp $symbol_file]\\.\\.\\.\r\n" { set saw_reading_symbols true exp_continue } -re "^Core was generated by `[string_to_regexp $gen_from_file]'\\.\r\n" { set saw_generated_line true exp_continue } -re "^$::gdb_prompt $" { gdb_assert { $saw_generated_line && $saw_reading_symbols} \ $gdb_test_name } -re "^\[^\r\n\]*\r\n" { exp_continue } } } with_test_prefix "absolute path" { # Generate a core file, this uses an absolute path to the # executable. with_test_prefix "to file" { set corefile [core_find $binfile] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_1 "$binfile.1.core" remote_exec build "mv $corefile $corefile_1" test_load $corefile_1 $binfile $binfile } # And create a symlink, and repeat the test using an absolute path # to the symlink. with_test_prefix "to symlink" { set symlink_name "symlink_1" set symlink [standard_output_file $symlink_name] with_cwd [standard_output_file ""] { remote_exec build "ln -s ${testfile} $symlink_name" } set corefile [core_find $symlink] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_2 "$binfile.2.core" remote_exec build "mv $corefile $corefile_2" test_load $corefile_2 $symlink $symlink } # Like the previous test, except this time, delete the symlink # after generating the core file. GDB should be smart enough to # figure out that we can use the underlying TESTFILE binary. with_test_prefix "to deleted symlink" { set symlink_name "symlink_2" set symlink [standard_output_file $symlink_name] with_cwd [standard_output_file ""] { remote_exec build "ln -s ${testfile} $symlink_name" } set corefile [core_find $symlink] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_3 "$binfile.3.core" remote_exec build "mv $corefile $corefile_3" remote_exec build "rm -f $symlink" # FreeBSD is unable to figure out the actual underlying mapped # file, so when the symlink is deleted, FeeeBSD is stuck. # # There is some argument that this shouldn't even be a # failure, the user ran the symlink, and if the symlink is # gone, should we really expect GDB to find the underlying # file? That we can on Linux is really just a quirk of how # the mapped file list works. setup_xfail "*-*-freebsd*" test_load $corefile_3 $binfile $symlink } # Generate the core file with an absolute path to the executable, # but move the core file and executable into a single directory # together so GDB can't use the absolute path to find the # executable. # # GDB should still find the executable though, but looking in the # same directory as the core file. with_test_prefix "in side directory" { set binfile_2 [standard_output_file ${testfile}_2] remote_exec build "cp $binfile $binfile_2" set corefile [core_find $binfile_2] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_4 "$binfile.4.core" remote_exec build "mv $corefile $corefile_4" set side_dir [standard_output_file side_dir] remote_exec build "mkdir -p $side_dir" remote_exec build "mv $binfile_2 $side_dir" remote_exec build "mv $corefile_4 $side_dir" set relocated_corefile_4 [file join $side_dir [file tail $corefile_4]] set relocated_binfile_2 [file join $side_dir [file tail $binfile_2]] test_load $relocated_corefile_4 $relocated_binfile_2 $binfile_2 } } with_test_prefix "relative path" { # Generate a core file using relative a path. We ned to work # around the core_find proc a little here. The core_find proc # creates a sub-directory using standard_output_file and runs the # test binary from inside that directory. # # Usually core_find is passed an absolute path, so thre's no # problem, but we want to pass a relative path. # # So setup a directory structure like this: # # corefile-find-exec/ # reldir/ # # workdir/ # # Place a copy of BINFILE in 'reldir/' and switch to workdir, use # core_find which will create a sibling directory of workdir, and # run the relative path from there. We then move the generated # core file back into 'workdir/', this leaves a tree like: # # corefile-find-exec/ # reldir/ # # workdir/ # # # Now we can ask GDB to open the core file, if all goes well GDB # should make use of the relative path encoded in the core file to # locate the executable in 'reldir/'. # # We also setup a symlink in 'reldir' that points to the # executable and repeat the test, but this time executing the # symlink. set reldir_name "reldir" set reldir [standard_output_file $reldir_name] remote_exec build "mkdir -p $reldir" set alt_testfile "alt_${testfile}" set binfile_3 "$reldir/${alt_testfile}" remote_exec build "cp $binfile $binfile_3" set symlink_2 "symlink_2" with_cwd $reldir { remote_exec build "ln -s ${alt_testfile} ${symlink_2}" } set work_dir [standard_output_file "workdir"] remote_exec build "mkdir -p $work_dir" set rel_path_to_file "../${reldir_name}/${alt_testfile}" set rel_path_to_symlink_2 "../${reldir_name}/${symlink_2}" with_cwd $work_dir { with_test_prefix "to file" { set corefile [core_find $rel_path_to_file] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_5 "${work_dir}/${testfile}.5.core" remote_exec build "mv $corefile $corefile_5" test_load $corefile_5 \ [file join $work_dir $rel_path_to_file] \ $rel_path_to_file } with_test_prefix "to symlink" { set corefile [core_find $rel_path_to_symlink_2] if {$corefile == ""} { untested "unable to create corefile" return 0 } set corefile_6 "${work_dir}/${testfile}.6.core" remote_exec build "mv $corefile $corefile_6" test_load $corefile_6 \ [file join $work_dir $rel_path_to_symlink_2] \ $rel_path_to_symlink_2 } # Move the core file. Now the relative path doesn't work so # we instead rely on GDB to use information about the mapped # files to help locate the executable. with_test_prefix "with moved corefile" { set corefile_7 [standard_output_file "${testfile}.7.core"] remote_exec build "cp $corefile_6 $corefile_7" test_load $corefile_7 $binfile_3 $rel_path_to_symlink_2 } } }