1# Copyright 2019-2023 Free Software Foundation, Inc. 2 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. 7# 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. 12# 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/>. 15 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. 19 20# Build-id-related tests for core files. 21 22standard_testfile 23 24# Build a non-shared executable. 25 26proc build_corefile_buildid_exec {} { 27 global testfile srcfile binfile execdir 28 29 if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} { 30 untested "failed to compile" 31 return false 32 } 33 34 # Move executable to non-default path. 35 set builddir [standard_output_file $execdir] 36 remote_exec build "rm -rf $builddir" 37 remote_exec build "mkdir $builddir" 38 remote_exec build "mv $binfile [file join $builddir [file tail $binfile]]" 39 40 return true 41} 42 43# Build a shared executable. 44 45proc build_corefile_buildid_shared {} { 46 global srcdir subdir testfile binfile srcfile sharedir 47 48 set builddir [standard_output_file $sharedir] 49 50 # Compile DSO. 51 set srcdso [file join $srcdir $subdir $testfile-shlib-shr.c] 52 set objdso [standard_output_file $testfile-shlib-shr.so] 53 if {[gdb_compile_shlib $srcdso $objdso {debug}] != ""} { 54 untested "failed to compile dso" 55 return false 56 } 57 58 # Compile shared library. 59 set srclib [file join $srcdir $subdir $testfile-shlib.c] 60 set libname lib$testfile.so 61 set objlib [standard_output_file $libname] 62 set dlopen_lib [shlib_target_file \ 63 [file join $builddir [file tail $objdso]]] 64 set opts [list debug shlib_load \ 65 additional_flags=-DSHLIB_NAME=\"$dlopen_lib\"] 66 if {[gdb_compile_shlib $srclib $objlib $opts] != ""} { 67 untested "failed to compile shared library" 68 return false 69 } 70 71 # Compile main program. 72 set srcexec [file join $srcdir $subdir $srcfile] 73 set binfile [standard_output_file $testfile-shared] 74 set opts [list debug shlib=$objlib additional_flags=-DTEST_SHARED] 75 if {[gdb_compile $srcexec $binfile executable $opts] != ""} { 76 untested "failed to compile shared executable" 77 return false 78 } 79 80 # Move objects to non-default path. 81 remote_exec build "rm -rf $builddir" 82 remote_exec build "mkdir $builddir" 83 remote_exec build "mv $binfile $builddir" 84 remote_exec build "mv $objdso $builddir" 85 remote_exec build "mv $objlib $builddir" 86 87 return true 88} 89 90# Append DEBUGDIR to the debug-file-directory path. 91 92proc append_debug_dir {debugdir} { 93 global gdb_prompt 94 95 set orig_debugdir {} 96 gdb_test_multiple "show debug-file-directory" \ 97 "get debug-file-directory" { 98 -re "The directory where separate debug symbols are searched for is \"(.*)\"\.\[\r\n\]+$gdb_prompt $" { 99 set orig_debugdir $expect_out(1,string) 100 pass "get debug-file-directory" 101 } 102 } 103 gdb_test_no_output "set debug-file-directory $debugdir:$orig_debugdir" \ 104 "append debug directory" 105} 106 107# A convenience procedure to check if "info files" mentions the exec file 108# FILE. 109 110proc check_exec_file {file} { 111 global gdb_prompt 112 send_log "expecting exec file \"$file\"\n" 113 114 # Get line with "Local exec file:". 115 set ok 0 116 gdb_test_multiple "info files" "" -lbl { 117 -re "\r\nLocal exec file:" { 118 set test_name $gdb_test_name 119 set ok 1 120 } 121 } 122 123 if { $ok == 0 } { 124 return 125 } 126 127 # Get subsequent line with $file. 128 set ok 0 129 gdb_test_multiple "" $test_name -lbl { 130 -re "\r\n\[\t\ \]+`[string_to_regexp $file]'\[^\r\n\]*" { 131 set ok 1 132 } 133 } 134 135 if { $ok == 0 } { 136 return 137 } 138 139 # Skip till prompt. 140 gdb_test_multiple "" $test_name -lbl { 141 -re "\r\n$gdb_prompt $" { 142 pass $gdb_test_name 143 } 144 } 145} 146 147# Test whether gdb can find an exec file from a core file's build-id. 148# The executable (and separate debuginfo if SEPDEBUG is true) is 149# copied to the .build-id directory. 150# 151# SUFFIX is appended to the .builid-id parent directory name to 152# keep all tests separate. 153# SYMLINK specifies whether build-id files should be copied or symlinked. 154# SHARED is a boolean indicating whether we are testing the shared 155# library core dump test case. 156 157proc locate_exec_from_core_build_id {corefile buildid suffix \ 158 sepdebug symlink shared} { 159 global testfile binfile srcfile 160 161 clean_restart 162 163 # Set up the build-id directory and symlink the binary there. 164 if {$symlink} { 165 set d "symlinkdir" 166 } else { 167 set d "debugdir" 168 } 169 set debugdir [standard_output_file $d-$suffix] 170 remote_exec build "rm -rf $debugdir" 171 remote_exec build \ 172 "mkdir -p [file join $debugdir [file dirname $buildid]]" 173 174 set files_list {} 175 if {$sepdebug} { 176 lappend files_list "$binfile.stripped" $buildid 177 lappend files_list "$binfile.debug" "$buildid.debug" 178 } else { 179 lappend files_list $binfile $buildid 180 } 181 if {$shared} { 182 global sharedir 183 set builddir [standard_output_file $sharedir] 184 } else { 185 global execdir 186 set builddir [standard_output_file $execdir] 187 } 188 foreach {target name} $files_list { 189 set t [file join $builddir [file tail $target]] 190 if {$symlink} { 191 remote_exec build "ln -s $t [file join $debugdir $name]" 192 } else { 193 remote_exec build "cp $t [file join $debugdir $name]" 194 } 195 } 196 197 # Append the debugdir to the separate debug directory search path. 198 append_debug_dir $debugdir 199 200 gdb_test "core-file $corefile" "Program terminated with .*" \ 201 "load core file" 202 if {$symlink} { 203 if {$sepdebug} { 204 set expected_file [file join $builddir \ 205 [file tail "$binfile.stripped"]] 206 } else { 207 set expected_file [file join $builddir [file tail $binfile]] 208 } 209 } else { 210 set expected_file $buildid 211 } 212 check_exec_file [file join $debugdir $expected_file] 213} 214 215# Run a build-id tests on a core file. 216# Supported options: "-shared" and "-sepdebug" for running tests 217# of shared and/or stripped/.debug executables. 218 219proc do_corefile_buildid_tests {args} { 220 global binfile testfile srcfile execdir sharedir 221 222 # Parse options. 223 parse_args [list {sepdebug} {shared}] 224 225 # PROGRAM to run to generate core file. This could be different 226 # than the program that was originally built, e.g., for a stripped 227 # executable. 228 if {$shared} { 229 set builddir [standard_output_file $sharedir] 230 } else { 231 set builddir [standard_output_file $execdir] 232 } 233 set program_to_run [file join $builddir [file tail $binfile]] 234 235 # A list of suffixes to use to describe the test and the .build-id 236 # directory for the test. The suffix will be used, joined with spaces, 237 # to prefix all tests for the given run. It will be used, joined with 238 # dashes, to create a unique build-id directory. 239 set suffix {} 240 if {$shared} { 241 lappend suffix "shared" 242 } else { 243 lappend suffix "exec" 244 } 245 246 if {$sepdebug} { 247 # Strip debuginfo into its own file. 248 if {[gdb_gnu_strip_debug [standard_output_file $program_to_run]] \ 249 != 0} { 250 untested "could not strip executable for [join $suffix \ ]" 251 return 252 } 253 254 # Run the stripped program instead of the original. 255 set program_to_run [file join $builddir \ 256 [file tail "$binfile.stripped"]] 257 lappend suffix "sepdebug" 258 } 259 260 with_test_prefix "[join $suffix \ ]" { 261 # Find the core file. 262 set corefile [core_find $program_to_run] 263 if {$corefile == ""} { 264 untested "could not generate core file" 265 return 266 } 267 verbose -log "corefile is $corefile" 268 269 # Grab the build-id from the binary, removing ".debug" from the end. 270 set buildid [build_id_debug_filename_get $program_to_run] 271 if {$buildid == ""} { 272 untested "binary has no build-id" 273 } 274 regsub {\.debug$} $buildid {} buildid 275 verbose -log "build-id is $buildid" 276 277 locate_exec_from_core_build_id $corefile $buildid \ 278 [join $suffix -] $sepdebug false $shared 279 280 with_test_prefix "symlink" { 281 locate_exec_from_core_build_id $corefile $buildid \ 282 [join $suffix -] $sepdebug true $shared 283 } 284 } 285} 286 287# Directories where executables will be moved before testing. 288set execdir "build-exec" 289set sharedir "build-shared" 290 291# 292# Do tests 293# 294 295build_corefile_buildid_exec 296do_corefile_buildid_tests 297do_corefile_buildid_tests -sepdebug 298 299if {![skip_shlib_tests]} { 300 build_corefile_buildid_shared 301 do_corefile_buildid_tests -shared 302 do_corefile_buildid_tests -shared -sepdebug 303} 304