From bcc06ae5c80dedc02dd0422b83c1905dccdc58ec Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 24 Jun 2026 14:31:17 -0400 Subject: [PATCH] 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 --- debuginfod/debuginfod-client.c | 6 ++- debuginfod/debuginfod-find.c | 4 +- doc/debuginfod_find_debuginfo.3 | 4 +- tests/Makefile.am | 6 ++- tests/run-debuginfod-debug-map.sh | 69 ++++++++++++++++++++++++++++++ tests/testfile-debug-map.bz2 | Bin 0 -> 2645 bytes tests/testfile-debug-map.c | 1 + 7 files changed, 83 insertions(+), 7 deletions(-) create mode 100755 tests/run-debuginfod-debug-map.sh create mode 100755 tests/testfile-debug-map.bz2 create mode 100644 tests/testfile-debug-map.c 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 0000000000000000000000000000000000000000..5bd7890ec87278599f169ac162a52394a9515be4 GIT binary patch literal 2645 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 D;tR~9 literal 0 Hc-jL100001 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; } -- 2.47.3