]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
PR34309: debuginfod: support relative source paths for reproducible builds
authorFrank Ch. Eigler <fche@redhat.com>
Wed, 24 Jun 2026 18:31:17 +0000 (14:31 -0400)
committerFrank Ch. Eigler <fche@elastic.org>
Fri, 26 Jun 2026 20:41:41 +0000 (16:41 -0400)
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 <fche@redhat.com>
Reviewed-By: Aaron Merey <amerey@redhat.com>
debuginfod/debuginfod-client.c
debuginfod/debuginfod-find.c
doc/debuginfod_find_debuginfo.3
tests/Makefile.am
tests/run-debuginfod-debug-map.sh [new file with mode: 0755]
tests/testfile-debug-map.bz2 [new file with mode: 0755]
tests/testfile-debug-map.c [new file with mode: 0644]

index 04c4a0eb509ba7fa62b8cbe4659787b3e043b0d9..d9915719a271ff786fb8bab86d53b35fae571711 100644 (file)
@@ -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;
index d96c92af24f2f05a1482c131e17e524bc8c8a397..5d492b269533a8aa3af55c3ee3c864aa30b3521a 100644 (file)
@@ -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,
index ab7fc09e6807178981e963e1b0483391d9b3ac32..2227a9c4442914a7519d878426714d4f0bb8743a 100644 (file)
@@ -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
index 30a7b6cabce9e5a4df5406ea72d65ac052692d56..d3ecd35bbf42cdb89f17e45bb9d73635fd6cbd0a 100644 (file)
@@ -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 (executable)
index 0000000..046dad4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+. $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 (executable)
index 0000000..5bd7890
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 (file)
index 0000000..76e8197
--- /dev/null
@@ -0,0 +1 @@
+int main() { return 0; }