summaryrefslogtreecommitdiffstats
path: root/libdwfl/dwfl_build_id_find_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/dwfl_build_id_find_elf.c')
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c76
1 files changed, 52 insertions, 24 deletions
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index 1a226dfd..381203d8 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -53,18 +53,44 @@
#include <unistd.h>
-int
+static bool
+open_and_check (struct dwfl_file *file,
+ const struct dwfl_build_id *build_id,
+ GElf_Addr bias,
+ char *file_name, int fd)
+{
+ if (__libdwfl_open_file (file, file_name,
+ fd, NULL) != DWFL_E_NOERROR)
+ return false;
+
+ /* For the "check" (set==false) call, we can safely cast away const
+ and take stack pointer. */
+ if (__libdwfl_find_build_id ((struct dwfl_build_id **)&build_id,
+ bias, false, file->shared->elf) != 2)
+ {
+ __libdwfl_close_file (file);
+ return false;
+ }
+
+ return true;
+}
+
+bool
internal_function
-__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
+__libdwfl_open_by_build_id (const Dwfl_Callbacks *const cb,
+ struct dwfl_file *file,
+ const struct dwfl_build_id *build_id,
+ GElf_Addr bias,
+ bool debug, char **file_name)
{
/* If *FILE_NAME was primed into the module, leave it there
as the fallback when we have nothing to offer. */
errno = 0;
- if (mod->build_id_len <= 0)
+ if (!BUILD_ID_PTR (build_id))
return -1;
- const size_t id_len = mod->build_id_len;
- const uint8_t *id = mod->build_id_bits;
+ const size_t id_len = build_id->len;
+ const uint8_t *id = build_id->bits;
/* Search debuginfo_path directories' .build-id/ subdirectories. */
@@ -83,7 +109,6 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
strcpy (&id_name[sizeof "/.build-id/" - 1 + 3 + (id_len - 1) * 2],
".debug");
- const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
?: DEFAULT_DEBUGINFO_PATH);
@@ -126,7 +151,17 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
if (fd < 0 && errno == ENOENT)
errno = 0;
- return fd;
+ if (fd >= 0)
+ {
+ char *fn = *file_name;
+ *file_name = open_and_check (file, build_id, bias, fn, fd)
+ ? file->name : NULL;
+
+ if (fn != *file_name)
+ free (fn); /* Failure, or strdup in __libdwfl_open_file. */
+ }
+
+ return *file_name != NULL;
}
int
@@ -137,24 +172,17 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
char **file_name, Elf **elfp)
{
*elfp = NULL;
- int fd = __libdwfl_open_by_build_id (mod, false, file_name);
- if (fd >= 0)
+ if (__libdwfl_open_by_build_id (mod->dwfl->callbacks,
+ &mod->main, mod->build_id,
+ mod->bias, false, file_name)
+ && mod->main.shared->build_id == NULL)
{
- *elfp = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
- if (__libdwfl_find_build_id (mod, false, *elfp) == 2)
- /* This is a backdoor signal to short-circuit the ID refresh. */
- mod->main.valid = true;
- else
- {
- /* This file does not contain the ID it should! */
- elf_end (*elfp);
- *elfp = NULL;
- close (fd);
- fd = -1;
- free (*file_name);
- *file_name = NULL;
- }
+ /* Move build ID bits into the cache. */
+ mod->build_id->vaddr -= mod->bias;
+ mod->main.shared->build_id = mod->build_id;
+ mod->build_id = NULL;
}
- return fd;
+
+ return -1;
}
INTDEF (dwfl_build_id_find_elf)