# Copyright 2020-2021 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 . # Test debuginfod functionality standard_testfile main.c load_lib dwarf.exp if { [which debuginfod] == 0 } { untested "cannot find debuginfod" return -1 } if { [which curl] == 0 } { untested "cannot find curl" return -1 } # Skip testing if gdb was not configured with debuginfod if { [string first "with-debuginfod" \ [eval exec $GDB $INTERNAL_GDBFLAGS --configuration]] == -1 } { untested "gdb not configured with debuginfod" return -1 } set cache [standard_output_file ".client_cache"] set db [standard_output_file ".debuginfod.db"] # Delete any preexisting test files file delete -force $cache file delete -force $db set sourcetmp [standard_output_file tmp-${srcfile}] set outputdir [standard_output_file {}] # Make a copy source file that we can move around if { [catch {file copy -force ${srcdir}/${subdir}/${srcfile} \ [standard_output_file ${sourcetmp}]}] != 0 } { error "create temporary file" return -1 } if { [gdb_compile "$sourcetmp" "$binfile" executable {debug}] != "" } { fail "compile" return -1 } # Write some assembly that just has a .gnu_debugaltlink section. # Copied from testsuite/gdb.dwarf2/dwzbuildid.exp. proc write_just_debugaltlink {filename dwzname buildid} { set asm_file [standard_output_file $filename] Dwarf::assemble $asm_file { upvar dwzname dwzname upvar buildid buildid gnu_debugaltlink $dwzname $buildid # Only the DWARF reader checks .gnu_debugaltlink, so make sure # there is a bit of DWARF in here. cu {} { compile_unit {{language @DW_LANG_C}} { } } } } # Write some DWARF that also sets the buildid. # Copied from testsuite/gdb.dwarf2/dwzbuildid.exp. proc write_dwarf_file {filename buildid {value 99}} { set asm_file [standard_output_file $filename] Dwarf::assemble $asm_file { declare_labels int_label int_label2 upvar buildid buildid upvar value value build_id $buildid cu {} { compile_unit {{language @DW_LANG_C}} { int_label2: base_type { {name int} {byte_size 4 sdata} {encoding @DW_ATE_signed} } constant { {name the_int} {type :$int_label2} {const_value $value data1} } } } } } proc no_url { } { global binfile outputdir debugdir setenv DEBUGINFOD_URLS "" # Test that gdb cannot find source without debuginfod clean_restart $binfile gdb_test_no_output "set substitute-path $outputdir /dev/null" \ "set substitute-path" gdb_test "list" ".*No such file or directory.*" # Strip symbols into separate file and move it so gdb cannot find it \ without debuginfod if { [gdb_gnu_strip_debug $binfile ""] != 0 } { fail "strip debuginfo" return -1 } set debugdir [standard_output_file "debug"] set debuginfo [standard_output_file "fetch_src_and_symbols.debug"] file mkdir $debugdir file rename -force $debuginfo $debugdir # Test that gdb cannot find symbols without debuginfod clean_restart $binfile gdb_test "file" ".*No symbol file.*" set buildid "01234567890abcdef0123456" write_just_debugaltlink ${binfile}_has_altlink.S ${binfile}_dwz.o \ $buildid write_dwarf_file ${binfile}_dwz.S $buildid if {[gdb_compile ${binfile}_has_altlink.S ${binfile}_alt.o object \ nodebug] != ""} { fail "compile main with altlink" return -1 } if {[gdb_compile ${binfile}_dwz.S ${binfile}_dwz.o object \ nodebug] != ""} { fail "compile altlink" return -1 } file rename -force ${binfile}_dwz.o $debugdir # Test that gdb cannot find dwz without debuginfod. clean_restart gdb_test "file ${binfile}_alt.o" \ ".*could not find '.gnu_debugaltlink'.*" \ "file [file tail ${binfile}_alt.o]" } proc local_url { } { global binfile outputdir db debugdir # Find an unused port set port 7999 set found 0 while { ! $found } { incr port if { $port == 65536 } { fail "no available ports" return -1 } spawn debuginfod -vvvv -d $db -p $port -F $debugdir expect { "started http server on IPv4 IPv6 port=$port" { set found 1 } "failed to bind to port" { kill_wait_spawned_process $spawn_id } timeout { fail "find port timeout" return -1 } } } set metrics [list "ready 1" \ "thread_work_total{role=\"traverse\"} 1" \ "thread_work_pending{role=\"scan\"} 0" \ "thread_busy{role=\"scan\"} 0"] # Check server metrics to confirm init has completed. foreach m $metrics { set timelim 20 while { $timelim != 0 } { sleep 0.5 catch {exec curl -s http://127.0.0.1:$port/metrics} got if { [regexp $m $got] } { break } incr timelim -1 } if { $timelim == 0 } { fail "server init timeout" return -1 } } # Point the client to the server setenv DEBUGINFOD_URLS http://127.0.0.1:$port # gdb should now find the symbol and source files clean_restart $binfile gdb_test_no_output "set substitute-path $outputdir /dev/null" \ "set substitute-path" gdb_test "br main" "Breakpoint 1 at.*file.*" gdb_test "l" ".*This program is distributed in the hope.*" # gdb should now find the debugaltlink file clean_restart gdb_test "file ${binfile}_alt.o" \ ".*Reading symbols from ${binfile}_alt.o\.\.\.*" \ "file [file tail ${binfile}_alt.o]" } set envlist \ [list \ env(DEBUGINFOD_URLS) \ env(DEBUGINFOD_TIMEOUT) \ env(DEBUGINFOD_CACHE_PATH)] save_vars $envlist { setenv DEBUGINFOD_TIMEOUT 30 setenv DEBUGINFOD_CACHE_PATH $cache with_test_prefix no_url no_url with_test_prefix local_url local_url }