| # 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 <http://www.gnu.org/licenses/>. |
| |
| # 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}] != "" } { |
| untested "failed to 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 |
| } |