1 # Copyright 2019-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 # Based on break.exp, written by Rob Savoye. (rob@cygnus.com)
17 # Modified to test gdb's handling of separate debug info files.
18 # Modified to test gdb's handling of a debug-id retrieval.
20 # Build-id-related tests for core files.
22 standard_testfile .c -shlib-shr.c -shlib.c
24 # Create a corefile from PROGNAME. Return the name of the generated
25 # corefile, or the empty string if anything goes wrong.
27 # The generated corefile must contain a buildid for PROGNAME. If it
28 # doesn't then an empty string will be returned.
29 proc create_core_file { progname } {
30 # Generate a corefile.
31 set corefile [core_find $progname]
32 if {$corefile == ""} {
33 untested "could not generate core file"
36 verbose -log "corefile is $corefile"
38 # Check the corefile has a build-id for the executable.
39 if { [catch "exec [gdb_find_eu-unstrip] -n --core $corefile" output] == 0 } {
40 set line [lindex [split $output "\n"] 0]
41 set binfile_re (?:[string_to_regexp $progname]|\\\[(?:exe|pie)\\\])
42 if { ![regexp "^${::hex}\\+${::hex} \[a-f0-9\]+@${::hex}.*$binfile_re$" $line] } {
43 unsupported "no build-id for executable in corefile"
47 unsupported "eu-unstrip tool failed"
55 # Build a non-shared executable.
57 proc build_corefile_buildid_exec { progname } {
58 return [expr {[build_executable "build non-shared exec" $progname $::srcfile] != -1}]
61 # Build a shared executable.
63 proc build_corefile_buildid_shared { progname } {
65 set objdso [standard_output_file $::testfile-shlib-shr.so]
66 if {[build_executable "build dso" $objdso $::srcfile2 {debug shlib}] == -1} {
71 # Compile shared library.
72 set srclib $::srcfile3
73 set libname lib$::testfile.so
74 set objlib [standard_output_file $libname]
75 set dlopen_lib [shlib_target_file $objdso]
76 set opts [list debug shlib_load shlib \
77 additional_flags=-DSHLIB_NAME=\"$dlopen_lib\"]
78 if {[build_executable "build solib" $objlib $::srcfile3 $opts] == -1} {
82 # Compile main program.
83 set opts [list debug shlib=$objlib additional_flags=-DTEST_SHARED]
84 if {[build_executable "build shared exec" $progname $::srcfile $opts] == -1} {
91 # Append DEBUGDIR to the debug-file-directory path.
93 proc append_debug_dir {debugdir} {
97 gdb_test_multiple "show debug-file-directory" \
98 "get debug-file-directory" {
99 -re "The directory where separate debug symbols are searched for is \"(.*)\"\.\[\r\n\]+$gdb_prompt $" {
100 set orig_debugdir $expect_out(1,string)
101 pass "get debug-file-directory"
104 gdb_test_no_output "set debug-file-directory $debugdir:$orig_debugdir" \
105 "append debug directory"
108 # A convenience procedure to check if "info files" mentions the exec file
111 proc check_exec_file {file} {
113 send_log "expecting exec file \"$file\"\n"
115 # Get line with "Local exec file:".
117 gdb_test_multiple "info files" "" -lbl {
118 -re "\r\nLocal exec file:" {
119 set test_name $gdb_test_name
128 # Get subsequent line with $file.
130 gdb_test_multiple "" $test_name -lbl {
131 -re "\r\n\[\t\ \]+`[string_to_regexp $file]'\[^\r\n\]*" {
141 gdb_test_multiple "" $test_name -lbl {
142 -re "\r\n$gdb_prompt $" {
148 # Test whether gdb can find an exec file from a core file's build-id.
149 # The executable (and separate debuginfo if SEPDEBUG is true) is
150 # copied to the .build-id directory.
152 # SUFFIX is appended to the .builid-id parent directory name to
153 # keep all tests separate.
154 # SYMLINK specifies whether build-id files should be copied or symlinked.
155 # SHARED is a boolean indicating whether we are testing the shared
156 # library core dump test case.
158 proc locate_exec_from_core_build_id {corefile buildid \
160 sepdebug symlink shared} {
163 # Set up the build-id directory and symlink the binary there.
168 set d "${d}_not-shared"
176 set d "${d}_stripped"
178 set d "${d}_not-stripped"
181 set debugdir [standard_output_file $d]
183 "mkdir -p [file join $debugdir [file dirname $buildid]]"
186 lappend files_list [file join $dirname [file tail $progname]] \
189 lappend files_list [file join $dirname [file tail $progname]].debug \
193 foreach {target name} $files_list {
194 set t [file join $dirname [file tail $target]]
196 remote_exec build "ln -s $t [file join $debugdir $name]"
198 remote_exec build "cp $t [file join $debugdir $name]"
202 # Append the debugdir to the separate debug directory search path.
203 append_debug_dir $debugdir
205 gdb_test "core-file $corefile" "Program terminated with .*" \
208 set expected_file [file join $dirname [file tail $progname]]
210 set expected_file $buildid
212 check_exec_file [file join $debugdir $expected_file]
215 foreach_with_prefix mode { exec shared } {
216 # Build the executable.
217 set progname ${binfile}-$mode
218 set build_proc build_corefile_buildid_${mode}
219 if { ![$build_proc $progname] } {
223 # Generate a corefile.
224 set corefile [create_core_file $progname]
225 if { $corefile eq "" } {
229 # Get the build-id filename without ".debug" on the end. This
230 # will have the format: '.build-id/xx/xxxxx'
231 set buildid [build_id_debug_filename_get $progname ""]
232 if {$buildid == ""} {
233 untested "binary has no build-id"
236 verbose -log "build-id is $buildid"
238 # Create a directory for the non-stripped test.
239 set combined_dirname [standard_output_file ${mode}_non-stripped]
240 remote_exec build "mkdir -p $combined_dirname"
241 remote_exec build "cp $progname $combined_dirname"
243 # Create a directory for the stripped test.
244 if {[gdb_gnu_strip_debug [standard_output_file $progname] no-debuglink] != 0} {
245 untested "could not strip executable for [join $suffix \ ]"
248 set sepdebug_dirname [standard_output_file ${mode}_stripped]
249 remote_exec build "mkdir -p $sepdebug_dirname"
250 remote_exec build "mv $progname $sepdebug_dirname"
251 remote_exec build "mv ${progname}.debug $sepdebug_dirname"
253 # Now do the actual testing part. Fill out a debug directory with
254 # build-id related files (copies or symlinks) and then load the
255 # corefile. Check GDB finds the executable and debug information
256 # via the build-id related debug directory contents.
257 foreach_with_prefix sepdebug { false true } {
259 set dirname $sepdebug_dirname
261 set dirname $combined_dirname
264 foreach_with_prefix symlink { false true } {
265 locate_exec_from_core_build_id $corefile $buildid \
267 $sepdebug $symlink [expr {$mode eq "shared"}]