public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* patch PR25722: /path/name based debuginfod-find & API lookups
@ 2020-03-26  1:39 Frank Ch. Eigler
  2020-03-27 14:44 ` Mark Wielaard
  0 siblings, 1 reply; 4+ messages in thread
From: Frank Ch. Eigler @ 2020-03-26  1:39 UTC (permalink / raw)
  To: elfutils-devel

Hi -

commit b27d38f7eed6d99715fd1cc8a70b0a6a2b04f0ce (HEAD -> fche/pr25722)
Author: Frank Ch. Eigler <fche@redhat.com>
Date:   Wed Mar 25 21:36:51 2020 -0400

    PR25722: debuginfod client api: accept /path/names in place of buildid hex
    
    As a convenience, this extends the debuginfod find functions (and thus
    debuginfod-find) to accept a /path/name to an ELF binary as an
    alternative to a hexadecimal string for buildid.  Doc & testing incl.
    
    Signed-off-by: Frank Ch. Eigler <fche@redhat.com>

diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index b34b4d2938dd..032a670fd2d0 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,3 +1,12 @@
+2020-03-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (lookup_elf_buildid): Quick dwelf based
+	filename-to-buildid lookup function.
+	(debuginfod_query_server): Use it for non-hexstring buildids.
+	* debuginfod-find.c (main): Call elf_version().
+	* Makefile.am: Add elfutils library prereqs for libdebuginfod.so
+	and debuginfod-find.
+
 2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
 
 	* debuginfod-client.c (debuginfod_query_server): Print the
diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am
index 52ead30aebf8..1a57d287f9a1 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 = $(libeu) $(libdebuginfod) $(libelf)
 
 noinst_LIBRARIES = libdebuginfod.a
 noinst_LIBRARIES += libdebuginfod_pic.a
@@ -74,7 +74,7 @@ am_libdebuginfod_pic_a_OBJECTS = $(libdebuginfod_a_SOURCES:.c=.os)
 pkginclude_HEADERS = debuginfod.h
 
 libdebuginfod_so_LIBS = libdebuginfod_pic.a
-libdebuginfod_so_LDLIBS = $(libcurl_LIBS)
+libdebuginfod_so_LDLIBS = $(libcurl_LIBS) $(libdw) $(libelf) $(libeu)
 libdebuginfod.so$(EXEEXT): $(srcdir)/libdebuginfod.map $(libdebuginfod_so_LIBS)
 	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
 		-Wl,--soname,$@.$(VERSION) \
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index ea2d16249a31..a0ca95cb1dc8 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -61,6 +61,8 @@
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <curl/curl.h>
+#include <gelf.h>
+#include <libdwelf.h>
 
 /* If fts.h is included before config.h, its indirect inclusions may not
    give us the right LFS aliases of these functions, so map them manually.  */
@@ -436,6 +438,43 @@ default_progressfn (debuginfod_client *c, long a, long b)
 }
 
 
+static int
+lookup_elf_buildid(const char* path,
+                   char *build_id_hex,
+                   ssize_t max_build_id_bytes)
+{
+  int rc = -ENOENT;
+  int fd = open (path, O_RDONLY);
+  if (fd < 0)
+    goto out;
+  Elf *elf =  elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+  if (elf == NULL)
+    goto out1;
+  const unsigned char *build_id;
+  ssize_t s = dwelf_elf_gnu_build_id(elf, (const void**) &build_id);
+  if (s < 0 || s > max_build_id_bytes) {
+    rc = -EINVAL;
+    goto out2;
+  }
+  ssize_t i;
+  for (i=0; i<s; i++)
+    {
+      build_id_hex[2*i+0] = "0123456789abcdef"[(build_id[i]&0xF0) >> 4];
+      build_id_hex[2*i+1] = "0123456789abcdef"[(build_id[i]&0x0F) >> 0];
+    }
+  build_id_hex[2*i] = '\0';
+  rc = 0;
+
+ out2:
+  elf_end (elf);
+ out1:
+  close (fd);
+ out:
+  return rc;
+}
+
+
+
 /* Query each of the server URLs found in $DEBUGINFOD_URLS for the file
    with the specified build-id, type (debuginfo, executable or source)
    and filename. filename may be NULL. If found, return a file
@@ -474,16 +513,43 @@ debuginfod_query_server (debuginfod_client *c,
       goto out;
     }
 
-  /* Copy lowercase hex representation of build_id into buf.  */
-  if ((build_id_len >= MAX_BUILD_ID_BYTES) ||
-      (build_id_len == 0 &&
-       sizeof(build_id_bytes) > MAX_BUILD_ID_BYTES*2 + 1))
-    return -EINVAL;
-  if (build_id_len == 0) /* expect clean hexadecimal */
-    strcpy (build_id_bytes, (const char *) build_id);
-  else
-    for (int i = 0; i < build_id_len; i++)
-      sprintf(build_id_bytes + (i * 2), "%02x", build_id[i]);
+  if (build_id_len > 0) /* raw bytes */
+    {
+      if (build_id_len > MAX_BUILD_ID_BYTES) /* too man raw bytes */
+        return -EINVAL;
+      int i;
+      for (i = 0; i < build_id_len; i++)
+        {
+          build_id_bytes[2*i+0] = "0123456789abcdef"[(build_id[i]&0xF0) >> 4];
+          build_id_bytes[2*i+1] = "0123456789abcdef"[(build_id[i]&0x0F) >> 0];
+        }
+       build_id_bytes[2*i] = '\0';
+    }
+  else if (build_id_len == 0) /* \0-terminated string */
+    {
+      int any_non_hex = 0;
+      for (int 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;
+
+      if (any_non_hex) /* a path name --- try to fetch its buildid */
+        {
+          rc = lookup_elf_buildid ((const char*) build_id,
+                                   build_id_bytes,
+                                   MAX_BUILD_ID_BYTES);
+          if (rc != 0)
+            return rc;
+        }
+      else /* hexadecimal string */
+        {
+          if (strlen((const char*) build_id) >= sizeof(build_id_bytes))
+            return -EINVAL;
+          strcpy (build_id_bytes, (const char*)build_id);
+        }
+    }
 
   if (filename != NULL)
     {
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index 400c268224fb..440b93247569 100644
--- a/debuginfod/debuginfod-find.c
+++ b/debuginfod/debuginfod-find.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <argp.h>
 
+#include <gelf.h>
 
 /* Name and version of program.  */
 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
@@ -86,6 +87,8 @@ static struct argp argp =
 int
 main(int argc, char** argv)
 {
+  elf_version (EV_CURRENT);
+
   client = debuginfod_begin ();
   if (client == NULL)
     {
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 59809ea8a1e2..0c996ab234f4 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@
+2020-03-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1, debuginfod_find_debuginfo.3: Document
+	acceptance of /path/names in place of buildids.
+
 2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
 
 	* debuginfod_get_url.3: New function, documented ...
diff --git a/doc/debuginfod-find.1 b/doc/debuginfod-find.1
index e71ca29be96e..8a4abd9e525e 100644
--- a/doc/debuginfod-find.1
+++ b/doc/debuginfod-find.1
@@ -52,6 +52,13 @@ Build ID: 8713b9c3fb8a720137a4a08b325905c7aaf8429d
 8713b9c3fb8a720137a4a08b325905c7aaf8429d
 .ESAMPLE
 
+In place of the hexadecimal buildid, debuginfod-find also accepts a path
+name to to an ELF binary, from which it will then extract the buildid
+and proceed.  In this case, pass the file name in place of the BUILDID
+parameter, and ensure it has some character other than \fB[0-9a-f]\fP.
+Files named \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/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3
index f7ec6cc134ba..c33da3488a2e 100644
--- a/doc/debuginfod_find_debuginfo.3
+++ b/doc/debuginfod_find_debuginfo.3
@@ -71,11 +71,19 @@ and
 query the debuginfod server URLs contained in
 .BR $DEBUGINFOD_URLS
 (see below) for the debuginfo, executable or source file with the
-given \fIbuild_id\fP. \fIbuild_id\fP should be a pointer to either
-a null-terminated, lowercase hex string or a binary blob. If
-\fIbuild_id\fP is given as a hex string, \fIbuild_id_len\fP should
-be 0. Otherwise \fIbuild_id_len\fP should be the number of bytes in
-the binary blob.
+given \fIbuild_id\fP. \fIbuild_id\fP may be given as:
+.TP
+a binary blob
+pass its address and length in bytes in \fIbuild_id_len\fP.
+.TP
+a null-terminated hexadecimal string
+pass its address and 0 as \fIbuild_id_len\fP.  Ensure the
+string contains only \fB[0-9a-f]\fP characters.
+.TP
+an file name of an ELF binary containing the build-id
+pass its name and 0 as \fIbuild_id_len\fP.  Ensure the name
+contains some non-\fB[0-9a-f]\fP characters.
+.P
 
 .BR debuginfod_find_source ()
 also requries a \fIfilename\fP in order to specify a particular
diff --git a/tests/ChangeLog b/tests/ChangeLog
index d0d32a87315a..73ac1a7ec6b5 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2020-03-25  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test /path/-based debuginfod-find.
+
 2020-03-23  Mark Wielaard  <mark@klomp.org>
 
 	* getphdrnum.c: Include config.h.
diff --git a/tests/run-debuginfod-find.sh b/tests/run-debuginfod-find.sh
index b64130282d86..16785a46a782 100755
--- a/tests/run-debuginfod-find.sh
+++ b/tests/run-debuginfod-find.sh
@@ -139,7 +139,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
 
 filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID ${PWD}/prog.c`


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-03-29 23:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26  1:39 patch PR25722: /path/name based debuginfod-find & API lookups Frank Ch. Eigler
2020-03-27 14:44 ` Mark Wielaard
2020-03-28  0:52   ` Frank Ch. Eigler
2020-03-29 23:11     ` Mark Wielaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).