mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 10:05:29 +00:00
debuginfod is an HTTP server for distributing ELF/DWARF debugging information. When a debuginfo file cannot be found locally, Valgrind is able to query debuginfod servers for the file using its build-id. readelf.c: Add debuginfod_find_debug_file(). Spawns a child process to exec `debuginfod-find` in order to query servers for the debuginfo file. Also add helper debuginfod_find_path(). pub_core_pathscan.h: Moved from priv_initimg_pathscan.h in order to use VG_(find_executable)() in readelf.c. docs: Add information regarding debuginfod to valgrind.1 memcheck/tests/linux: Add new test debuginfod-check. tests/vg_regtest.in: Clear $DEBUGINFOD_URLS before running any tests. https://bugs.kde.org/show_bug.cgi?id=432215
117 lines
3.0 KiB
Perl
Executable File
117 lines
3.0 KiB
Perl
Executable File
#! /usr/bin/perl
|
|
use warnings;
|
|
use strict;
|
|
use Cwd;
|
|
use IPC::Open3;
|
|
|
|
our $dir = Cwd::realpath("./.debuginfod");
|
|
our $pid = 0;
|
|
|
|
# Kill the server and remove temporary files.
|
|
sub cleanup_and_exit($) {
|
|
my $exit_code = $_[0];
|
|
mysystem("rm -rf $dir");
|
|
if ($pid != 0) {
|
|
kill "INT", $pid;
|
|
}
|
|
exit $exit_code;
|
|
}
|
|
|
|
# Propagate Ctrl-C and exit if command results in an error.
|
|
sub mysystem($)
|
|
{
|
|
my $exit_code = system($_[0]);
|
|
($exit_code == 2) and cleanup_and_exit(1); # Exit if SIGINT
|
|
if ($exit_code != 0) {
|
|
#warn "Error while executing: $_[0]";
|
|
cleanup_and_exit(1);
|
|
}
|
|
return $exit_code;
|
|
}
|
|
|
|
# Check that debuginfod and debuginfod-find can be found
|
|
mysystem("debuginfod --help > /dev/null");
|
|
mysystem("debuginfod-find --help > /dev/null");
|
|
|
|
$SIG{'INT'} = sub { cleanup_and_exit(1) };
|
|
|
|
my $testname = "debuginfod-check";
|
|
my $tmp = "$dir/debuginfod_test.tmp";
|
|
my $dbg = "$dir/dbg";
|
|
mysystem("rm -rf $dir");
|
|
mysystem("mkdir -p $dbg");
|
|
|
|
# Compile the test executable, strip its debuginfo and store it so
|
|
# that valgrind cannot find it without debuginfod.
|
|
mysystem("gcc -O0 -g -o $testname $testname.c");
|
|
mysystem("objcopy --only-keep-debug $testname $testname.debug");
|
|
mysystem("objcopy --strip-unneeded $testname");
|
|
mysystem("objcopy --add-gnu-debuglink=$testname.debug $testname");
|
|
mysystem("mv $testname.debug $dbg");
|
|
mysystem("readelf -n $testname > $tmp 2>&1");
|
|
|
|
my $buildid = "";
|
|
open(TMP, '<', $tmp);
|
|
while (my $out = <TMP>) {
|
|
if ($out =~ /Build ID: ([0-9a-f]*)/) {
|
|
$buildid = $1;
|
|
}
|
|
}
|
|
|
|
if ($buildid eq "") {
|
|
warn "can't find $testname build-id";
|
|
cleanup_and_exit(1);
|
|
}
|
|
|
|
my $found_port = 0;
|
|
my $port = 7999;
|
|
|
|
# Find an unused port
|
|
while ($found_port == 0 and $port < 65536) {
|
|
$port++;
|
|
$pid = open3(undef, "TMP", undef,
|
|
"debuginfod", "-d", "$dir/db", '-F', "$dbg", "--port=$port");
|
|
for (my $i = 0; $i < 5 and $found_port == 0; $i++) {
|
|
while (my $got = <TMP>) {
|
|
if ($got =~ /Failed to bind/) {
|
|
last;
|
|
} elsif ($got =~ /started http server/) {
|
|
$found_port = 1;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($port == 65536) {
|
|
warn "No available ports";
|
|
cleanup_and_exit(1);
|
|
}
|
|
|
|
my $server_ready = 0;
|
|
|
|
# Confirm that the server is ready to be queried
|
|
for (my $i = 0; $i < 10 and $server_ready == 0; $i++) {
|
|
sleep 1;
|
|
my $got = `curl -s http://localhost:$port/metrics`;
|
|
if ($got =~ /ready 1/
|
|
and $got =~ /thread_work_total\{role=\"traverse\"\} 1/
|
|
and $got =~ /thread_work_pending\{role=\"scan\"\} 0/
|
|
and $got =~ /thread_busy\{role=\"scan\"\} 0/) {
|
|
$server_ready = 1;
|
|
}
|
|
}
|
|
|
|
if ($server_ready == 0) {
|
|
warn "Can't start debuginfod server";
|
|
cleanup_and_exit(1);
|
|
}
|
|
|
|
# Query the server and store the debuginfo in the client cache for valgrind to find.
|
|
my $myres = mysystem("DEBUGINFOD_CACHE_PATH=$dir DEBUGINFOD_URLS=http://localhost:$port debuginfod-find debuginfo $buildid > /dev/null 2>&1");
|
|
if ($myres != 0) {
|
|
cleanup_and_exit(1);
|
|
}
|
|
kill "INT", $pid;
|
|
exit 0;
|