Hi - Like this?
Author: Frank Ch. Eigler <f...@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 <f...@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 <f...@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 <f...@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 <f...@redhat.com> + + * debuginfod-find.1: Document /path/-based buildid passing. + 2020-03-24 Frank Ch. Eigler <f...@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 <f...@redhat.com> + + * run-debuginfod-find.sh: Test /path/-based debuginfod-find. + 2020-03-24 Frank Ch. Eigler <f...@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