mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-05 12:53:16 +08:00
We currently have a single test for GDB's debuginfod support, this is gdb.debuginfod/fetch_src_and_symbols.exp, this script does all the setup, starts debuginfod, and then does the testing. This commit tries to split the existing script in two, there is a new library lib/debuginfod-support.exp, which contains a helper functions related to running debuginfod tests. All the code in the new library is basically copied from the existing test case (which is why I retained the copyright date range on the new library), with some minor adjustments to try and make the code a little more generic. One change I made, for example, is the library offers functions to shut down debuginfod, previously we just relied on expect shutting down debuginfod when dejagnu completed. The existing test script is updated to make use of the new library code, and this test is still passing for me. The only change in the test results is a single test where I changed the name to remove the port number from the test name - the port number can change from run to run, so could make it hard to compare test results. I have also done a little light house keeping on the original test script, updating and adding new comments, and making use of proc_with_prefix in a couple of places.
197 lines
5.9 KiB
Plaintext
197 lines
5.9 KiB
Plaintext
# Copyright 2020-2022 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/>.
|
|
|
|
# Helper functions to make it easier to write debuginfod tests.
|
|
|
|
# Return true if the debuginfod tests should be skipped, otherwise, return
|
|
# false.
|
|
proc skip_debuginfod_tests {} {
|
|
if [is_remote host] {
|
|
return true
|
|
}
|
|
|
|
if { [which debuginfod] == 0 } {
|
|
return true
|
|
}
|
|
|
|
if { [which curl] == 0 } {
|
|
untested "cannot find curl"
|
|
return true
|
|
}
|
|
|
|
# Skip testing if gdb was not configured with debuginfod.
|
|
#
|
|
# If GDB is built with ASan, it warns that some signal handlers
|
|
# (installed by ASan) exist on startup. That makes TCL's exec throw an
|
|
# error. Disable that by passing --quiet.
|
|
if { [string first "with-debuginfod" \
|
|
[eval exec $::GDB --quiet $::INTERNAL_GDBFLAGS \
|
|
--configuration]] == -1 } {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
# Create two directories within the current output directory. One directory
|
|
# will be used by GDB as the client cache to hold downloaded debug
|
|
# information, and the other directory will be used by the debuginfod server
|
|
# as its cache of the parsed debug files that will be served to GDB.
|
|
#
|
|
# Call this proc with the names to two variables, these variables will be
|
|
# set in the parent scope with the paths to the two directories.
|
|
#
|
|
# This proc allocates the names for the directories, but doesn't create
|
|
# them. In fact, if the directories already exist, this proc will delete
|
|
# them, this ensures that any existing contents are also deleted.
|
|
proc prepare_for_debuginfod { cache_var db_var } {
|
|
upvar $cache_var cache
|
|
upvar $db_var db
|
|
|
|
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
|
|
}
|
|
|
|
# Run BODY with the three environment variables required to control
|
|
# debuginfod set. The timeout is set based on the usual timeouts used by
|
|
# GDB within dejagnu (see get_largest_timeout), the debuginfod cache is set
|
|
# to CACHE (this is where downloaded debug data is placed), and the
|
|
# debuginfod urls environment variable is set to be the empty string.
|
|
#
|
|
# Within BODY you should start a debuginfod server and set the environment
|
|
# variable DEBUGINFOD_URLS as appropriate (see start_debuginfod for details).
|
|
#
|
|
# The reason that this proc doesn't automatically start debuginfod, is that
|
|
# in some test cases we want to initially test with debuginfod not running
|
|
# and/or disabled.
|
|
proc with_debuginfod_env { cache body } {
|
|
set envlist \
|
|
[list \
|
|
env(DEBUGINFOD_URLS) \
|
|
env(DEBUGINFOD_TIMEOUT) \
|
|
env(DEBUGINFOD_CACHE_PATH)]
|
|
|
|
save_vars $envlist {
|
|
setenv DEBUGINFOD_TIMEOUT [get_largest_timeout]
|
|
setenv DEBUGINFOD_CACHE_PATH $cache
|
|
setenv DEBUGINFOD_URLS ""
|
|
|
|
uplevel 1 $body
|
|
}
|
|
}
|
|
|
|
# Start a debuginfod server. DB is the directory to use for the server's
|
|
# database cache, while DEBUGDIR is a directory containing all the debug
|
|
# information that the server should server.
|
|
#
|
|
# This proc will try to find an available port to start the server on, will
|
|
# start the server, and check that the server has started correctly.
|
|
#
|
|
# If the server starts correctly, then this proc will return the url that
|
|
# should be used to communicate with the server. If the server can't be
|
|
# started, then an error will be printed, and an empty string returned.
|
|
#
|
|
# If the server is successfully started then the global variable
|
|
# debuginfod_spawn_id will be set with the spawn_id of the debuginfod
|
|
# process.
|
|
proc start_debuginfod { db debugdir } {
|
|
global debuginfod_spawn_id spawn_id
|
|
|
|
# Find an unused port.
|
|
set port 7999
|
|
set found false
|
|
while { ! $found } {
|
|
incr port
|
|
if { $port == 65536 } {
|
|
perror "no available ports"
|
|
return ""
|
|
}
|
|
|
|
if { [info exists spawn_id] } {
|
|
set old_spawn_id $spawn_id
|
|
}
|
|
|
|
spawn debuginfod -vvvv -d $db -p $port -F $debugdir
|
|
set debuginfod_spawn_id $spawn_id
|
|
|
|
if { [info exists old_spawn_id] } {
|
|
set spawn_id $old_spawn_id
|
|
unset old_spawn_id
|
|
}
|
|
|
|
expect {
|
|
-i $debuginfod_spawn_id
|
|
"started http server on IPv4 IPv6 port=$port" { set found true }
|
|
"started http server on IPv4 port=$port" { set found true }
|
|
"started http server on IPv6 port=$port" {}
|
|
"failed to bind to port" {}
|
|
timeout {
|
|
stop_debuginfod
|
|
perror "find port timeout"
|
|
return ""
|
|
}
|
|
}
|
|
if { ! $found } {
|
|
stop_debuginfod
|
|
}
|
|
}
|
|
|
|
set url "http://127.0.0.1:$port"
|
|
|
|
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 $url/metrics} got
|
|
|
|
if { [regexp $m $got] } {
|
|
break
|
|
}
|
|
|
|
incr timelim -1
|
|
}
|
|
|
|
if { $timelim == 0 } {
|
|
stop_debuginfod
|
|
perror "server init timeout"
|
|
return ""
|
|
}
|
|
}
|
|
|
|
return $url
|
|
}
|
|
|
|
# If the global debuginfod_spawn_id exists, then kill that process and unset
|
|
# the debuginfod_spawn_id global. This can be used to shutdown the
|
|
# debuginfod server.
|
|
proc stop_debuginfod { } {
|
|
global debuginfod_spawn_id
|
|
|
|
if [info exists debuginfod_spawn_id] {
|
|
kill_wait_spawned_process $debuginfod_spawn_id
|
|
unset debuginfod_spawn_id
|
|
}
|
|
}
|