From fa0226a78a101d26fd80c7e9e70a5f0aa6f9d1cc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 17 Nov 2019 22:17:26 +0100 Subject: debuginfod: add client context Add a mandatory debuginfod_begin()/_end() call pair to manage a client object that represents persistent but non-global state. From libdwfl, dlopen the debuginfod.so client library early on. This hopefully makes sure that the code (and the libcurl.so dependency) is loaded before the program goes into multi-threaded mode. Signed-off-by: Mark Wielaard --- libdwfl/Makefile.am | 2 +- libdwfl/debuginfod-client.c | 131 +++++++++++++++++++++++++++++++++++++++ libdwfl/dwfl_build_id_find_elf.c | 36 +++-------- libdwfl/dwfl_end.c | 2 + libdwfl/find-debuginfo.c | 27 +------- libdwfl/libdwflP.h | 15 +++++ 6 files changed, 160 insertions(+), 53 deletions(-) create mode 100644 libdwfl/debuginfod-client.c (limited to 'libdwfl') diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am index 29046e9e..47bd62a5 100644 --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -70,7 +70,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \ link_map.c core-file.c open.c image-header.c \ dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \ linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \ - gzip.c + gzip.c debuginfod-client.c if BZLIB libdwfl_a_SOURCES += bzip2.c diff --git a/libdwfl/debuginfod-client.c b/libdwfl/debuginfod-client.c new file mode 100644 index 00000000..ee604ad9 --- /dev/null +++ b/libdwfl/debuginfod-client.c @@ -0,0 +1,131 @@ +/* Try to get an ELF or debug file through the debuginfod. + Copyright (C) 2019 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "libdwflP.h" +#include + +static __typeof__ (debuginfod_begin) *fp_debuginfod_begin; +static __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable; +static __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo; +static __typeof__ (debuginfod_end) *fp_debuginfod_end; + +/* NB: this is slightly thread-unsafe */ + +static debuginfod_client * +get_client (Dwfl *dwfl) +{ + if (dwfl->debuginfod != NULL) + return dwfl->debuginfod; + + if (fp_debuginfod_begin != NULL) + { + dwfl->debuginfod = (*fp_debuginfod_begin) (); + return dwfl->debuginfod; + } + + return NULL; +} + +int +__libdwfl_debuginfod_find_executable (Dwfl *dwfl, + const unsigned char *build_id_bits, + size_t build_id_len) +{ + int fd = -1; + if (build_id_len > 0) + { + debuginfod_client *c = get_client (dwfl); + if (c != NULL) + fd = (*fp_debuginfod_find_executable) (c, build_id_bits, + build_id_len, NULL); + } + + return fd; +} + +int +__libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl, + const unsigned char *build_id_bits, + size_t build_id_len) +{ + int fd = -1; + if (build_id_len > 0) + { + debuginfod_client *c = get_client (dwfl); + if (c != NULL) + fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits, + build_id_len, NULL); + } + + return fd; +} + +void +__libdwfl_debuginfod_end (debuginfod_client *c) +{ + if (c != NULL) + (*fp_debuginfod_end) (c); +} + +/* Try to get the libdebuginfod library functions to make sure + everything is initialized early. */ +void __attribute__ ((constructor)) +__libdwfl_debuginfod_init (void) +{ + void *debuginfod_so = dlopen("libdebuginfod-" VERSION ".so", RTLD_LAZY); + + if (debuginfod_so == NULL) + debuginfod_so = dlopen("libdebuginfod.so", RTLD_LAZY); + + if (debuginfod_so != NULL) + { + fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin"); + fp_debuginfod_find_executable = dlsym (debuginfod_so, + "debuginfod_find_executable"); + fp_debuginfod_find_debuginfo = dlsym (debuginfod_so, + "debuginfod_find_debuginfo"); + fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end"); + + /* We either get them all, or we get none. */ + if (fp_debuginfod_begin == NULL + || fp_debuginfod_find_executable == NULL + || fp_debuginfod_find_debuginfo == NULL + || fp_debuginfod_end == NULL) + { + fp_debuginfod_begin = NULL; + fp_debuginfod_find_executable = NULL; + fp_debuginfod_find_debuginfo = NULL; + fp_debuginfod_end = NULL; + dlclose (debuginfod_so); + } + } +} diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c index b775f50a..4e56143f 100644 --- a/libdwfl/dwfl_build_id_find_elf.c +++ b/libdwfl/dwfl_build_id_find_elf.c @@ -34,9 +34,7 @@ #include #include #include -#include #include "system.h" -#include "debuginfod.h" int @@ -189,31 +187,15 @@ dwfl_build_id_find_elf (Dwfl_Module *mod, free (*file_name); *file_name = NULL; } - else { - /* NB: this is slightly thread-unsafe */ - static __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable; - - if (fp_debuginfod_find_executable == NULL) - { - void *debuginfod_so = dlopen("libdebuginfod-" VERSION ".so", RTLD_LAZY); - if (debuginfod_so == NULL) - debuginfod_so = dlopen("libdebuginfod.so", RTLD_LAZY); - if (debuginfod_so != NULL) - fp_debuginfod_find_executable = dlsym (debuginfod_so, "debuginfod_find_executable"); - if (fp_debuginfod_find_executable == NULL) - fp_debuginfod_find_executable = (void *) -1; /* never try again */ - } - - if (fp_debuginfod_find_executable != NULL && fp_debuginfod_find_executable != (void *) -1) - { - /* If all else fails and a build-id is available, query the - debuginfo-server if enabled. */ - if (fd < 0 && mod->build_id_len > 0) - fd = (*fp_debuginfod_find_executable) (mod->build_id_bits, - mod->build_id_len, - NULL); - } - } + else + { + /* If all else fails and a build-id is available, query the + debuginfo-server if enabled. */ + if (fd < 0 && mod->build_id_len > 0) + fd = __libdwfl_debuginfod_find_executable (mod->dwfl, + mod->build_id_bits, + mod->build_id_len); + } if (fd < 0 && errno == 0 && mod->build_id_len > 0) /* Setting this with no file yet loaded is a marker that diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c index 74ee9e07..4f6c722a 100644 --- a/libdwfl/dwfl_end.c +++ b/libdwfl/dwfl_end.c @@ -39,6 +39,8 @@ dwfl_end (Dwfl *dwfl) if (dwfl == NULL) return; + __libdwfl_debuginfod_end (dwfl->debuginfod); + if (dwfl->process) __libdwfl_process_free (dwfl->process); diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c index ffc07f92..40857645 100644 --- a/libdwfl/find-debuginfo.c +++ b/libdwfl/find-debuginfo.c @@ -31,11 +31,9 @@ #endif #include "libdwflP.h" -#include "debuginfod.h" #include #include #include -#include #include #include "system.h" @@ -400,29 +398,8 @@ dwfl_standard_find_debuginfo (Dwfl_Module *mod, free (canon); } - { - /* NB: this is slightly thread-unsafe */ - static __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo; - - if (fp_debuginfod_find_debuginfo == NULL) - { - void *debuginfod_so = dlopen("libdebuginfod-" VERSION ".so", RTLD_LAZY); - if (debuginfod_so == NULL) - debuginfod_so = dlopen("libdebuginfod.so", RTLD_LAZY); - if (debuginfod_so != NULL) - fp_debuginfod_find_debuginfo = dlsym (debuginfod_so, "debuginfod_find_debuginfo"); - if (fp_debuginfod_find_debuginfo == NULL) - fp_debuginfod_find_debuginfo = (void *) -1; /* never try again */ - } - - if (fp_debuginfod_find_debuginfo != NULL && fp_debuginfod_find_debuginfo != (void *) -1) - { - /* If all else fails and a build-id is available, query the - debuginfo-server if enabled. */ - if (fd < 0 && bits_len > 0) - fd = (*fp_debuginfod_find_debuginfo) (bits, bits_len, NULL); - } - } + if (fd < 0 && bits_len > 0) + fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len); return fd; } diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 6b2d4867..f631f946 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -40,6 +40,7 @@ #include "../libdw/libdwP.h" /* We need its INTDECLs. */ #include "../libdwelf/libdwelfP.h" +#include "../debuginfod/debuginfod.h" typedef struct Dwfl_Process Dwfl_Process; @@ -114,6 +115,7 @@ struct Dwfl_User_Core struct Dwfl { const Dwfl_Callbacks *callbacks; + debuginfod_client *debuginfod; Dwfl_Module *modulelist; /* List in order used by full traversals. */ @@ -634,6 +636,19 @@ extern Dwfl_Error __libdw_open_elf (int fd, Elf **elfp) internal_function; extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp) internal_function; +/* Internal interface to libdebuginfod (if installed). */ +int +__libdwfl_debuginfod_find_executable (Dwfl *dwfl, + const unsigned char *build_id_bits, + size_t build_id_len); +int +__libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl, + const unsigned char *build_id_bits, + size_t build_id_len); +void +__libdwfl_debuginfod_end (debuginfod_client *c); + + /* These are working nicely for --core, but are not ready to be exported interfaces quite yet. */ -- cgit v1.2.1