From b27d38f7eed6d99715fd1cc8a70b0a6a2b04f0ce Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 25 Mar 2020 21:36:51 -0400 Subject: 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 --- debuginfod/ChangeLog | 9 +++++ debuginfod/Makefile.am | 4 +- debuginfod/debuginfod-client.c | 86 ++++++++++++++++++++++++++++++++++++----- debuginfod/debuginfod-find.c | 3 ++ doc/ChangeLog | 5 +++ doc/debuginfod-find.1 | 7 ++++ doc/debuginfod_find_debuginfo.3 | 18 ++++++--- tests/ChangeLog | 4 ++ tests/run-debuginfod-find.sh | 2 +- 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 + + * 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 * 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 #include #include +#include +#include /* 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> 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 #include +#include /* 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 + + * debuginfod-find.1, debuginfod_find_debuginfo.3: Document + acceptance of /path/names in place of buildids. + 2020-03-22 Frank Ch. Eigler * 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 + + * run-debuginfod-find.sh: Test /path/-based debuginfod-find. + 2020-03-23 Mark Wielaard * 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` -- cgit v1.2.1