# Copyright (C) 2002-2020 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, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. # test debuginfod with readelf and objdump set test "debuginfod" if {[which debuginfod] == 0} { unsupported "$test (not found)" return } if {[which curl] == 0} { unsupported "$test (curl not found)" return } if { ![is_elf_format] } { unsupported "$test (unsupported target)" } if { [which $OBJDUMP] == 0} { perror "$test $OBJDUMP (does not exist)" return } if { [which $READELF] == 0} { perror "$test $READELF (does not exist)" return } # Compile testprog.c, move the debuginfo to a separate file and add .gnu_debuglink. if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog executable debug] != ""} { fail "$test (compilation failed)" return } if { [binutils_run $OBJCOPY "--only-keep-debug tmpdir/testprog tmpdir/testprog.debug"] != "" } { fail "$test (create separate debug info file)" return } if { [binutils_run $OBJCOPY "--strip-debug tmpdir/testprog"] != "" } { fail "$test (strip debug info)" return } if { [binutils_run $OBJCOPY "--add-gnu-debuglink=tmpdir/testprog.debug tmpdir/testprog"] != "" } { fail "$test (add debuglink)" return } # Assemble an elf file with a debugaltlink if { ![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o] } { fail "$test (assemble debuglink)" } if { ![binutils_assemble $srcdir/$subdir/linkdebug.s tmpdir/linkdebug.debug] } { fail "$test (assemble linkdebug)" } set cache [file join [pwd] "tmpdir/.debuginfod_cache"] set db [file join [pwd] "tmpdir/.debuginfod.db"] setenv DEBUGINFOD_URLS "" setenv DEBUGINFOD_TIMEOUT 30 setenv DEBUGINFOD_CACHE_PATH $cache # Move debug files into another directory so that readelf and objdump cannot # find them without debuginfod. file mkdir tmpdir/dbg file rename -force tmpdir/testprog.debug tmpdir/dbg file rename -force tmpdir/linkdebug.debug tmpdir/dbg # Remove old cache and database if they exist. file delete -force $cache file delete -force $db # Check whether objdump and readelf are configured with debuginfod. # To check this we attempt to follow a broken debuglink. If configured # with debuginfod the output will contain the debuginfod URLs that were # queried (these queries fail since the server is not yet running). set conf_objdump [binutils_run $OBJDUMP "-WK tmpdir/testprog"] set conf_readelf [binutils_run $READELF "-wK tmpdir/testprog"] # Find an unused port set port 7999 set found 0 while { ! $found } { incr port if { $port == 65536 } { untested "$test (no available ports)" return } spawn debuginfod -vvvv -d $db -p $port -F tmpdir/dbg expect { "started http server on IPv4 IPv6 port=$port" { set found 1 } "Failed to bind to port" { exec kill -INT -[exp_pid] catch {close}; catch {wait -i $spawn_id} } timeout { fail "$test (find port timeout)" return } } } 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 "$test (server init timeout)" exec kill -INT -[exp_pid] catch {close}; catch {wait -i $spawn_id} return } } setenv DEBUGINFOD_URLS http://127.0.0.1:$port # Test whether prog can fetch separate debuginfo using debuginfod # if it's configured to do so. proc test_fetch_debuglink { prog progargs } { global test global cache set got [binutils_run $prog "$progargs tmpdir/testprog"] if { [regexp ".*Found separate debug info file.*Contents\[^\n\]*loaded from\[^\n\]*$cache.*" $got] } { pass "$test ($prog debuglink)" } else { fail "$test ($prog debuglink)" } } # Test whether prog can fetch debugaltlink files using debuginfod # if it's configured to do so. proc test_fetch_debugaltlink { prog progargs } { global test global cache set got [binutils_run $prog "$progargs tmpdir/debuglink.o"] set buildid "00112233445566778899aabbccddeeff0123456789abcdef" if { [regexp ".*Found separate debug info file\[^\n\]*$cache/$buildid" $got] } { pass "$test ($prog debugaltlink)" } else { fail "$test ($prog debugaltlink)" } } if { [regexp ".*DEBUGINFOD.*" $conf_objdump] } { test_fetch_debuglink $OBJDUMP "-W" test_fetch_debugaltlink $OBJDUMP "-WK" } else { untested "$test (objdump not configured with debuginfod)" } if { [regexp ".*DEBUGINFOD.*" $conf_readelf] } { test_fetch_debuglink $READELF "-w" test_fetch_debugaltlink $READELF "-wK" } else { untested "$test (readelf not configured with debuginfod)" }