summaryrefslogtreecommitdiff
path: root/debuginfod/debuginfod-find.c
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2020-03-27 20:47:45 -0400
committerFrank Ch. Eigler <fche@redhat.com>2020-03-27 20:47:45 -0400
commit3a9c5da0ac7004a1f04e8768a682f76514e66433 (patch)
tree90419e2d61a6b6dfae93748fedaea113359ec439 /debuginfod/debuginfod-find.c
parentdbfaf36ac283006621cce0d343462512c8c5635d (diff)
downloadelfutils-3a9c5da0ac7004a1f04e8768a682f76514e66433.tar.gz
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>
Diffstat (limited to 'debuginfod/debuginfod-find.c')
-rw-r--r--debuginfod/debuginfod-find.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index 400c2682..83a43ce4 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)
{