patch PR25722: /path/name based debuginfod-find & API lookups

Frank Ch. Eigler fche@redhat.com
Sat Mar 28 00:52:14 GMT 2020


Hi -

Like this?


Author: Frank Ch. Eigler <fche@redhat.com>
Date:   Fri Mar 27 20:47:45 2020 -0400

    PR25722: debuginfod-find: accept /path/names in place of buildid hex
    
    Extend the debuginfod-find command line interface to permit
    /file/names instead of only buildid hexadecimal strings.
    
    v2: move code into debuginfod-find; client API remains buildid only.
    
    Signed-off-by: Frank Ch. Eigler <fche@redhat.com>

diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 3329be3510d2..6fc4c0981687 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.c (main): Extract buildid from /binary/ if
+	given instead of hex string.
+	* Makefile.am: Add elfutils library prereqs for debuginfod-find.
+
 2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
 
 	* debuginfod.h, libdebuginfod.map: New functions for _add_url_header.
diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am
index 52ead30aebf8..51965f65dbb7 100644
--- a/debuginfod/Makefile.am
+++ b/debuginfod/Makefile.am
@@ -62,7 +62,7 @@ debuginfod_SOURCES = debuginfod.cxx
 debuginfod_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(libmicrohttpd_LIBS) $(libcurl_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl
 
 debuginfod_find_SOURCES = debuginfod-find.c
-debuginfod_find_LDADD = $(libeu) $(libdebuginfod)
+debuginfod_find_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod)
 
 noinst_LIBRARIES = libdebuginfod.a
 noinst_LIBRARIES += libdebuginfod_pic.a
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index 400c268224fb..83a43ce4be2e 100644
--- a/debuginfod/debuginfod-find.c
+++ b/debuginfod/debuginfod-find.c
@@ -25,6 +25,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <argp.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libdwelf.h>
 
 
 /* Name and version of program.  */
@@ -39,8 +43,12 @@ static const char doc[] = N_("Request debuginfo-related content "
 
 /* Strings for arguments in help texts.  */
 static const char args_doc[] = N_("debuginfo BUILDID\n"
+                                  "debuginfo PATH\n"
                                   "executable BUILDID\n"
-                                  "source BUILDID /FILENAME");
+                                  "executable PATH\n"
+                                  "source BUILDID /FILENAME\n"
+                                  "source PATH /FILENAME\n");
+
 
 /* Definitions of arguments for argp functions.  */
 static const struct argp_option options[] =
@@ -86,6 +94,8 @@ static struct argp argp =
 int
 main(int argc, char** argv)
 {
+  elf_version (EV_CURRENT);
+
   client = debuginfod_begin ();
   if (client == NULL)
     {
@@ -105,19 +115,61 @@ main(int argc, char** argv)
       return 1;
     }
 
-  int rc;
+  /* If we were passed an ELF file name in the BUILDID slot, look in there. */
+  unsigned char* build_id = (unsigned char*) argv[remaining+1];
+  int build_id_len = 0; /* assume text */
+
+  int any_non_hex = 0;
+  int i;
+  for (i = 0; build_id[i] != '\0'; i++)
+    if ((build_id[i] >= '0' && build_id[i] <= '9') ||
+        (build_id[i] >= 'a' && build_id[i] <= 'f'))
+      ;
+    else
+      any_non_hex = 1;
+
+  int fd = -1;
+  Elf* elf = NULL;
+  if (any_non_hex) /* raw build-id */
+    {
+      fd = open ((char*) build_id, O_RDONLY);
+      if (fd < 0)
+        fprintf (stderr, "Cannot open %s: %s\n", build_id, strerror(errno));
+    }
+  if (fd >= 0)
+    {
+      elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+      if (elf == NULL)
+        fprintf (stderr, "Cannot elf_begin %s: %s\n", build_id, elf_errmsg(-1));
+    }
+  if (elf != NULL)
+    {
+      const void *extracted_build_id;
+      ssize_t s = dwelf_elf_gnu_build_id(elf, &extracted_build_id);
+      if (s > 0)
+        {
+          /* Success: replace the build_id pointer/len with the binary blob
+             that elfutils is keeping for us.  It'll remain valid until elf_end(). */
+          build_id = (unsigned char*) extracted_build_id;
+          build_id_len = s;
+        }
+      else
+        fprintf (stderr, "Cannot extract build-id from %s: %s\n", build_id, elf_errmsg(-1));
+    }
+
   char *cache_name;
+  int rc = 0;
 
   /* Check whether FILETYPE is valid and call the appropriate
      debuginfod_find_* function. If FILETYPE is "source"
      then ensure a FILENAME was also supplied as an argument.  */
   if (strcmp(argv[remaining], "debuginfo") == 0)
     rc = debuginfod_find_debuginfo(client,
-				   (unsigned char *)argv[remaining+1], 0,
+				   build_id, build_id_len,
 				   &cache_name);
   else if (strcmp(argv[remaining], "executable") == 0)
     rc = debuginfod_find_executable(client,
-				    (unsigned char *)argv[remaining+1], 0,
+                                    build_id, build_id_len,
 				    &cache_name);
   else if (strcmp(argv[remaining], "source") == 0)
     {
@@ -126,8 +178,9 @@ main(int argc, char** argv)
           fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
           return 1;
         }
-      rc = debuginfod_find_source(client, (unsigned char *)argv[remaining+1],
-				  0, argv[remaining+2], &cache_name);
+      rc = debuginfod_find_source(client,
+                                  build_id, build_id_len,
+				  argv[remaining+2], &cache_name);
     }
   else
     {
@@ -143,6 +196,10 @@ main(int argc, char** argv)
     }
 
   debuginfod_end (client);
+  if (elf)
+    elf_end(elf);
+  if (fd >= 0)
+    close (fd);
 
   if (rc < 0)
     {
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 38ce441c4076..25404e5876ba 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1: Document /path/-based buildid passing.
+
 2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
 
 	* debuginfod_add_http_header.3: New function, documented ...
diff --git a/doc/debuginfod-find.1 b/doc/debuginfod-find.1
index a861a48ed1d1..aeb1cb120918 100644
--- a/doc/debuginfod-find.1
+++ b/doc/debuginfod-find.1
@@ -19,10 +19,11 @@ debuginfod-find \- request debuginfo-related data
 
 .SH SYNOPSIS
 .B debuginfod-find [\fIOPTION\fP]... debuginfo \fIBUILDID\fP
-
+.B debuginfod-find [\fIOPTION\fP]... debuginfo \fIPATH\fP
 .B debuginfod-find [\fIOPTION\fP]... executable \fIBUILDID\fP
-
+.B debuginfod-find [\fIOPTION\fP]... executable \fIPATH\fP
 .B debuginfod-find [\fIOPTION\fP]... source \fIBUILDID\fP \fI/FILENAME\fP
+.B debuginfod-find [\fIOPTION\fP]... source \fIPATH\fP \fI/FILENAME\fP
 
 .SH DESCRIPTION
 \fBdebuginfod-find\fP queries one or more \fBdebuginfod\fP servers for
@@ -52,6 +53,14 @@ Build ID: 8713b9c3fb8a720137a4a08b325905c7aaf8429d
 8713b9c3fb8a720137a4a08b325905c7aaf8429d
 .ESAMPLE
 
+In place of the hexadecimal \fIBUILDID\fP, debuginfod-find also
+accepts a path name to to an ELF binary, from which it extracts the
+buildid.  In this case, ensure the file name has some character other
+than \fB[0-9a-f]\fP.  Files ambiguously named files like
+"\fBdeadbeef\fP" can be passed with a \fB./deadbeef\fP extra path
+component.
+
+
 .SS debuginfo \fIBUILDID\fP
 
 If the given buildid is known to a server, this request will result
diff --git a/tests/ChangeLog b/tests/ChangeLog
index d1c9e952870a..66df34ced63c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test /path/-based debuginfod-find.
+
 2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
 
 	* run-debuginfod-find.sh: Test relay of UA and XFF headers across
diff --git a/tests/run-debuginfod-find.sh b/tests/run-debuginfod-find.sh
index 799b7005a26e..bba04c1fe20a 100755
--- a/tests/run-debuginfod-find.sh
+++ b/tests/run-debuginfod-find.sh
@@ -144,7 +144,7 @@ rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
 filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID`
 cmp $filename F/prog.debug
 
-filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID`
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable F/prog`
 cmp $filename F/prog
 
 # raw source filename



More information about the Elfutils-devel mailing list