summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2020-03-25 21:36:51 -0400
committerFrank Ch. Eigler <fche@redhat.com>2020-03-25 21:36:51 -0400
commitb27d38f7eed6d99715fd1cc8a70b0a6a2b04f0ce (patch)
tree57d7e24e3b12cf5fd471f01e20b11f20dda90690
parentea7eb6934b5bd310000719a33e1109bcd116bb4f (diff)
downloadelfutils-fche/pr25722.tar.gz
PR25722: debuginfod client api: accept /path/names in place of buildid hexfche/pr25722
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>
-rw-r--r--debuginfod/ChangeLog9
-rw-r--r--debuginfod/Makefile.am4
-rw-r--r--debuginfod/debuginfod-client.c86
-rw-r--r--debuginfod/debuginfod-find.c3
-rw-r--r--doc/ChangeLog5
-rw-r--r--doc/debuginfod-find.17
-rw-r--r--doc/debuginfod_find_debuginfo.318
-rw-r--r--tests/ChangeLog4
-rwxr-xr-xtests/run-debuginfod-find.sh2
9 files changed, 120 insertions, 18 deletions
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index b34b4d29..032a670f 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 52ead30a..1a57d287 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 ea2d1624..a0ca95cb 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 400c2682..440b9324 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 59809ea8..0c996ab2 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 e71ca29b..8a4abd9e 100644
--- a/doc/debuginfod-find.1
+++ b/doc/debuginfod-find.1
@@ -52,6 +52,13 @@ Then the hexadecimal BUILDID is simply:
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 f7ec6cc1..c33da348 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 d0d32a87..73ac1a7e 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 b6413028..16785a46 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`