From: Frank Ch. Eigler Date: Wed, 24 Jun 2026 18:31:17 +0000 (-0400) Subject: PR34309: debuginfod: support relative source paths for reproducible builds X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bcc06ae5c80dedc02dd0422b83c1905dccdc58ec;p=thirdparty%2Felfutils.git PR34309: debuginfod: support relative source paths for reproducible builds Relaxed constraint checks in debuginfod-client and debuginfod-find to allow relative source filenames (e.g. those starting with '.' or normal filenames), supporting binaries built with options like -fdebug-prefix-map as one way to produce reproducible builds. Note that such paths will not generally be resolvable by debuginfod within packages, nor if debuginfod's startup PWD is different from the build tree. This is a niche function only. Added tests/testfile-debug-map{.c,.bz2} compiled with -fdebug-prefix-map and tests/run-debuginfod-debug-map.sh to verify. Signed-off-By: Frank Ch. Eigler Reviewed-By: Aaron Merey --- diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c index 04c4a0eb..d9915719 100644 --- a/debuginfod/debuginfod-client.c +++ b/debuginfod/debuginfod-client.c @@ -1923,7 +1923,7 @@ debuginfod_query_server_by_buildid (debuginfod_client *c, { if (vfd >= 0) dprintf (vfd, "checking filename\n"); - if (filename[0] != '/') // must start with / + if (filename[0] == '\0') // must not be empty { rc = -EINVAL; goto out; @@ -2182,7 +2182,9 @@ debuginfod_query_server_by_buildid (debuginfod_client *c, size_t escaped_strlen = 0; if (filename) { - escaped_string = curl_easy_escape(&target_handle, filename+1, 0); + escaped_string = curl_easy_escape(&target_handle, + filename[0] == '/' ? filename+1 : filename, + 0); if (!escaped_string) { rc = -ENOMEM; diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c index d96c92af..5d492b26 100644 --- a/debuginfod/debuginfod-find.c +++ b/debuginfod/debuginfod-find.c @@ -247,9 +247,9 @@ main(int argc, char** argv) &cache_name); else if (strcmp(argv[remaining], "source") == 0) { - if (remaining+2 == argc || argv[remaining+2][0] != '/') + if (remaining+2 >= argc || argv[remaining+2][0] == '\0') { - fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n"); + fprintf(stderr, "If FILETYPE is \"source\" then FILENAME must be given\n"); return 1; } rc = debuginfod_find_source(client, diff --git a/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3 index ab7fc09e..2227a9c4 100644 --- a/doc/debuginfod_find_debuginfo.3 +++ b/doc/debuginfod_find_debuginfo.3 @@ -319,8 +319,8 @@ Unable to resolve remote host. .TP .BR EINVAL One or more arguments are incorrectly formatted. \fIbuild_id\fP may -be too long (greater than 256 characters), \fIfilename\fP may not -be an absolute path or a debuginfod URL is malformed. +be too long (greater than 256 characters), \fIfilename\fP may +be empty, or a debuginfod URL is malformed. .TP .BR EIO diff --git a/tests/Makefile.am b/tests/Makefile.am index 30a7b6ca..d3ecd35b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -299,7 +299,8 @@ TESTS += run-srcfiles-self.sh \ run-debuginfod-client-profile.sh \ run-debuginfod-find-metadata.sh \ run-debuginfod-longsource.sh \ - run-debuginfod-homesite.sh + run-debuginfod-homesite.sh \ + run-debuginfod-debug-map.sh if LZMA TESTS += run-debuginfod-seekable.sh endif @@ -641,6 +642,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-debuginfod-find-metadata.sh \ run-debuginfod-longsource.sh \ run-debuginfod-homesite.sh \ + run-debuginfod-debug-map.sh \ + testfile-debug-map.bz2 \ + testfile-debug-map.c \ debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm \ debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm \ debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm \ diff --git a/tests/run-debuginfod-debug-map.sh b/tests/run-debuginfod-debug-map.sh new file mode 100755 index 00000000..046dad41 --- /dev/null +++ b/tests/run-debuginfod-debug-map.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2026 Red Hat, Inc. +# This file is part of elfutils. +# +# This file 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. +# +# elfutils 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 . + +. $srcdir/debuginfod-subr.sh + +set -x +unset VALGRIND_CMD + +# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test +base=12100 +get_ports + +DB=${PWD}/.debuginfod_tmp.sqlite +tempfiles $DB +export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache + +# Copy the source file to the current directory so that debuginfod can index it +# since the binary was compiled with -fdebug-prefix-map=$(pwd)=. +# Therefore, DWARF points to the relative path testfile-debug-map.c in the cwd. +cp ${abs_srcdir}/testfile-debug-map.c . +tempfiles testfile-debug-map.c + +# Unpack the test binary +testfiles testfile-debug-map + +# Run debuginfod on current directory (in file/directory mode, scanning .) +env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB -t0 -g0 . > vlog$PORT1 2>&1 & +PID1=$! +tempfiles vlog$PORT1 +errfiles vlog$PORT1 + +wait_ready $PORT1 'ready' 1 +wait_ready $PORT1 'thread_work_total{role="traverse"}' 1 +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 +wait_ready $PORT1 'thread_busy{role="scan"}' 0 + +# Check that we can find the source file via debuginfod-find using relative pathnames! +# The build ID of testfile-debug-map is 4c1385643bcb37d365c59001932e908171c9f2dd. +# We test with both a relative path name starting with . and a plain relative path name. +export DEBUGINFOD_URLS="http://127.0.0.1:$PORT1/" + +# Test finding with relative path starting with '.' +filename1=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source 4c1385643bcb37d365c59001932e908171c9f2dd ./testfile-debug-map.c` +cmp $filename1 testfile-debug-map.c + +# Test finding with relative path starting with filename +filename2=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source 4c1385643bcb37d365c59001932e908171c9f2dd testfile-debug-map.c` +cmp $filename2 testfile-debug-map.c + +kill $PID1 +wait $PID1 +PID1=0 + +exit 0 diff --git a/tests/testfile-debug-map.bz2 b/tests/testfile-debug-map.bz2 new file mode 100755 index 00000000..5bd7890e Binary files /dev/null and b/tests/testfile-debug-map.bz2 differ diff --git a/tests/testfile-debug-map.c b/tests/testfile-debug-map.c new file mode 100644 index 00000000..76e81970 --- /dev/null +++ b/tests/testfile-debug-map.c @@ -0,0 +1 @@ +int main() { return 0; }