summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2019-11-17 22:17:26 +0100
committerMark Wielaard <mark@klomp.org>2019-11-23 01:03:13 +0100
commitfa0226a78a101d26fd80c7e9e70a5f0aa6f9d1cc (patch)
treebe11c41ebeee936545633327bc76d48cdd0a8d61
parent8d5a05a7f006968653f813529be1df253a881040 (diff)
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 <mark@klomp.org>
-rw-r--r--debuginfod/debuginfod-client.c72
-rw-r--r--debuginfod/debuginfod-find.c29
-rw-r--r--debuginfod/debuginfod.cxx35
-rw-r--r--debuginfod/debuginfod.h23
-rw-r--r--debuginfod/libdebuginfod.map2
-rw-r--r--doc/debuginfod_begin.31
-rw-r--r--doc/debuginfod_end.31
-rw-r--r--doc/debuginfod_find_debuginfo.351
-rw-r--r--libdwfl/Makefile.am2
-rw-r--r--libdwfl/debuginfod-client.c131
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c36
-rw-r--r--libdwfl/dwfl_end.c2
-rw-r--r--libdwfl/find-debuginfo.c27
-rw-r--r--libdwfl/libdwflP.h15
14 files changed, 317 insertions, 110 deletions
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 64dd608a..6e62b86c 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -71,6 +71,16 @@
#include <fts.h>
#endif
+struct debuginfod_client
+{
+ /* Progress/interrupt callback function. */
+ debuginfod_progressfn_t progressfn;
+
+ /* Can contain all other context, like cache_path, server_urls,
+ timeout or other info gotten from environment variables, the
+ handle data, etc. So those don't have to be reparsed and
+ recreated on each request. */
+};
/* The cache_clean_interval_s file within the debuginfod cache specifies
how frequently the cache should be cleaned. The file's st_mtime represents
@@ -99,9 +109,6 @@ static const char url_delim_char = ' ';
static const char *server_timeout_envvar = DEBUGINFOD_TIMEOUT_ENV_VAR;
static int server_timeout = 5;
-/* Progress/interrupt callback function. */
-static debuginfod_progressfn_t progressfn;
-
/* Data associated with a particular CURL easy handle. Passed to
the write callback. */
struct handle_data
@@ -181,7 +188,9 @@ debuginfod_init_cache (char *cache_path, char *interval_path, char *maxage_path)
/* Delete any files that have been unmodied for a period
longer than $DEBUGINFOD_CACHE_CLEAN_INTERVAL_S. */
static int
-debuginfod_clean_cache(char *cache_path, char *interval_path, char *max_unused_path)
+debuginfod_clean_cache(debuginfod_client *c,
+ char *cache_path, char *interval_path,
+ char *max_unused_path)
{
struct stat st;
FILE *interval_file;
@@ -236,8 +245,8 @@ debuginfod_clean_cache(char *cache_path, char *interval_path, char *max_unused_p
while ((f = fts_read(fts)) != NULL)
{
files++;
- if (progressfn) /* inform/check progress callback */
- if ((*progressfn) (files, 0))
+ if (c->progressfn) /* inform/check progress callback */
+ if ((c->progressfn) (c, files, 0))
break;
switch (f->fts_info)
@@ -275,7 +284,8 @@ debuginfod_clean_cache(char *cache_path, char *interval_path, char *max_unused_p
descriptor for the target, otherwise return an error code.
*/
static int
-debuginfod_query_server (const unsigned char *build_id,
+debuginfod_query_server (debuginfod_client *c,
+ const unsigned char *build_id,
int build_id_len,
const char *type,
const char *filename,
@@ -366,7 +376,7 @@ debuginfod_query_server (const unsigned char *build_id,
int rc = debuginfod_init_cache(cache_path, interval_path, maxage_path);
if (rc != 0)
goto out;
- rc = debuginfod_clean_cache(cache_path, interval_path, maxage_path);
+ rc = debuginfod_clean_cache(c, cache_path, interval_path, maxage_path);
if (rc != 0)
goto out;
@@ -501,7 +511,7 @@ debuginfod_query_server (const unsigned char *build_id,
{
CURLMcode curl_res;
- if (progressfn) /* inform/check progress callback */
+ if (c->progressfn) /* inform/check progress callback */
{
loops ++;
long pa = loops; /* default params for progress callback */
@@ -541,7 +551,7 @@ debuginfod_query_server (const unsigned char *build_id,
#endif
}
- if ((*progressfn) (pa, pb))
+ if ((*c->progressfn) (c, pa, pb))
break;
}
@@ -674,41 +684,59 @@ debuginfod_query_server (const unsigned char *build_id,
return rc;
}
-
/* See debuginfod.h */
+debuginfod_client *
+debuginfod_begin (void)
+{
+ debuginfod_client *client;
+ size_t size = sizeof (struct debuginfod_client);
+ client = (debuginfod_client *) malloc (size);
+ if (client != NULL)
+ client->progressfn = NULL;
+ return client;
+}
+
+void
+debuginfod_end (debuginfod_client *client)
+{
+ free (client);
+}
+
int
-debuginfod_find_debuginfo (const unsigned char *build_id, int build_id_len,
+debuginfod_find_debuginfo (debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
char **path)
{
- return debuginfod_query_server(build_id, build_id_len,
+ return debuginfod_query_server(client, build_id, build_id_len,
"debuginfo", NULL, path);
}
/* See debuginfod.h */
int
-debuginfod_find_executable(const unsigned char *build_id, int build_id_len,
+debuginfod_find_executable(debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
char **path)
{
- return debuginfod_query_server(build_id, build_id_len,
+ return debuginfod_query_server(client, build_id, build_id_len,
"executable", NULL, path);
}
/* See debuginfod.h */
-int debuginfod_find_source(const unsigned char *build_id, int build_id_len,
+int debuginfod_find_source(debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
const char *filename, char **path)
{
- return debuginfod_query_server(build_id, build_id_len,
+ return debuginfod_query_server(client, build_id, build_id_len,
"source", filename, path);
}
-debuginfod_progressfn_t
-debuginfod_set_progressfn(debuginfod_progressfn_t fn)
+void
+debuginfod_set_progressfn(debuginfod_client *client,
+ debuginfod_progressfn_t fn)
{
- debuginfod_progressfn_t it = progressfn;
- progressfn = fn;
- return it;
+ client->progressfn = fn;
}
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index 4c1a94c6..8bd3a3db 100644
--- a/debuginfod/debuginfod-find.c
+++ b/debuginfod/debuginfod-find.c
@@ -49,9 +49,11 @@ static const struct argp_option options[] =
{ NULL, 0, NULL, 0, NULL, 0 }
};
+/* debuginfod connection handle. */
+static debuginfod_client *client;
-
-int progressfn(long a, long b)
+int progressfn(debuginfod_client *c __attribute__((__unused__)),
+ long a, long b)
{
fprintf (stderr, "Progress %ld / %ld\n", a, b);
return 0;
@@ -64,7 +66,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
(void) state;
switch (key)
{
- case 'v': debuginfod_set_progressfn (& progressfn); break;
+ case 'v': debuginfod_set_progressfn (client, & progressfn); break;
default: return ARGP_ERR_UNKNOWN;
}
return 0;
@@ -82,6 +84,13 @@ static struct argp argp =
int
main(int argc, char** argv)
{
+ client = debuginfod_begin ();
+ if (client == NULL)
+ {
+ fprintf(stderr, "Couldn't create debuginfod client context\n");
+ return 1;
+ }
+
int remaining;
(void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
@@ -98,9 +107,13 @@ main(int argc, char** argv)
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((unsigned char *)argv[remaining+1], 0, &cache_name);
+ rc = debuginfod_find_debuginfo(client,
+ (unsigned char *)argv[remaining+1], 0,
+ &cache_name);
else if (strcmp(argv[remaining], "executable") == 0)
- rc = debuginfod_find_executable((unsigned char *)argv[remaining+1], 0, &cache_name);
+ rc = debuginfod_find_executable(client,
+ (unsigned char *)argv[remaining+1], 0,
+ &cache_name);
else if (strcmp(argv[remaining], "source") == 0)
{
if (remaining+2 == argc || argv[3][0] != '/')
@@ -108,8 +121,8 @@ main(int argc, char** argv)
fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
return 1;
}
- rc = debuginfod_find_source((unsigned char *)argv[remaining+1], 0,
- argv[remaining+2], &cache_name);
+ rc = debuginfod_find_source(client, (unsigned char *)argv[remaining+1],
+ 0, argv[remaining+2], &cache_name);
}
else
{
@@ -126,5 +139,7 @@ main(int argc, char** argv)
printf("%s\n", cache_name);
free (cache_name);
+ debuginfod_end (client);
+
return 0;
}
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index e2535cef..f4bbc7b7 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -944,7 +944,7 @@ handle_buildid_match (int64_t b_mtime,
static int
-debuginfod_find_progress (long a, long b)
+debuginfod_find_progress (debuginfod_client *, long a, long b)
{
if (verbose > 4)
obatched(clog) << "federated debuginfod progress=" << a << "/" << b << endl;
@@ -1036,15 +1036,28 @@ static struct MHD_Response* handle_buildid (const string& buildid /* unsafe */,
// is to defer to other debuginfo servers.
int fd = -1;
- if (artifacttype == "debuginfo")
- fd = debuginfod_find_debuginfo ((const unsigned char*) buildid.c_str(), 0,
- NULL);
- else if (artifacttype == "executable")
- fd = debuginfod_find_executable ((const unsigned char*) buildid.c_str(), 0,
- NULL);
- else if (artifacttype == "source")
- fd = debuginfod_find_source ((const unsigned char*) buildid.c_str(), 0,
- suffix.c_str(), NULL);
+ debuginfod_client *client = debuginfod_begin ();
+ if (client != NULL)
+ {
+ debuginfod_set_progressfn (client, & debuginfod_find_progress);
+
+ if (artifacttype == "debuginfo")
+ fd = debuginfod_find_debuginfo (client,
+ (const unsigned char*) buildid.c_str(),
+ 0, NULL);
+ else if (artifacttype == "executable")
+ fd = debuginfod_find_executable (client,
+ (const unsigned char*) buildid.c_str(),
+ 0, NULL);
+ else if (artifacttype == "source")
+ fd = debuginfod_find_source (client,
+ (const unsigned char*) buildid.c_str(),
+ 0, suffix.c_str(), NULL);
+ }
+ else
+ fd = -errno; /* Set by debuginfod_begin. */
+ debuginfod_end (client);
+
if (fd >= 0)
{
inc_metric ("http_responses_total","result","upstream");
@@ -2508,8 +2521,6 @@ main (int argc, char *argv[])
"cannot run database schema ddl: %s", sqlite3_errmsg(db));
}
- (void) debuginfod_set_progressfn (& debuginfod_find_progress);
-
// Start httpd server threads. Separate pool for IPv4 and IPv6, in
// case the host only has one protocol stack.
MHD_Daemon *d4 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
diff --git a/debuginfod/debuginfod.h b/debuginfod/debuginfod.h
index 0620f02a..6b1b1cc3 100644
--- a/debuginfod/debuginfod.h
+++ b/debuginfod/debuginfod.h
@@ -34,10 +34,16 @@
#define DEBUGINFOD_CACHE_PATH_ENV_VAR "DEBUGINFOD_CACHE_PATH"
#define DEBUGINFOD_TIMEOUT_ENV_VAR "DEBUGINFOD_TIMEOUT"
+/* Handle for debuginfod-client connection. */
+typedef struct debuginfod_client debuginfod_client;
+
#ifdef __cplusplus
extern "C" {
#endif
+/* Create a handle for a new debuginfod-client session. */
+debuginfod_client *debuginfod_begin (void);
+
/* Query the urls contained in $DEBUGINFOD_URLS for a file with
the specified type and build id. If build_id_len == 0, the
build_id is supplied as a lowercase hexadecimal string; otherwise
@@ -48,21 +54,28 @@ extern "C" {
strdup'd copy of the name of the same file in the cache.
Caller must free() it later. */
-int debuginfod_find_debuginfo (const unsigned char *build_id,
+int debuginfod_find_debuginfo (debuginfod_client *client,
+ const unsigned char *build_id,
int build_id_len,
char **path);
-int debuginfod_find_executable (const unsigned char *build_id,
+int debuginfod_find_executable (debuginfod_client *client,
+ const unsigned char *build_id,
int build_id_len,
char **path);
-int debuginfod_find_source (const unsigned char *build_id,
+int debuginfod_find_source (debuginfod_client *client,
+ const unsigned char *build_id,
int build_id_len,
const char *filename,
char **path);
-typedef int (*debuginfod_progressfn_t)(long a, long b);
-debuginfod_progressfn_t debuginfod_set_progressfn(debuginfod_progressfn_t fn);
+typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);
+void debuginfod_set_progressfn(debuginfod_client *c,
+ debuginfod_progressfn_t fn);
+
+/* Release debuginfod client connection context handle. */
+void debuginfod_end (debuginfod_client *client);
#ifdef __cplusplus
}
diff --git a/debuginfod/libdebuginfod.map b/debuginfod/libdebuginfod.map
index b322cba6..0d26f93e 100644
--- a/debuginfod/libdebuginfod.map
+++ b/debuginfod/libdebuginfod.map
@@ -1,6 +1,8 @@
ELFUTILS_0 { };
ELFUTILS_0.178 {
global:
+ debuginfod_begin;
+ debuginfod_end;
debuginfod_find_debuginfo;
debuginfod_find_executable;
debuginfod_find_source;
diff --git a/doc/debuginfod_begin.3 b/doc/debuginfod_begin.3
new file mode 100644
index 00000000..16279936
--- /dev/null
+++ b/doc/debuginfod_begin.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_end.3 b/doc/debuginfod_end.3
new file mode 100644
index 00000000..16279936
--- /dev/null
+++ b/doc/debuginfod_end.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3
index d8d9236e..be8eed09 100644
--- a/doc/debuginfod_find_debuginfo.3
+++ b/doc/debuginfod_find_debuginfo.3
@@ -21,15 +21,39 @@ debuginfod_find_debuginfo \- request debuginfo from debuginfod
.nf
.B #include <elfutils/debuginfod.h>
.PP
-.BI "int debuginfod_find_debuginfo(const unsigned char *" build_id ", int " build_id_len ", char ** " path ");"
-.BI "int debuginfod_find_executable(const unsigned char *" build_id ", int " build_id_len ", char ** " path ");"
-.BI "int debuginfod_find_source(const unsigned char *" build_id ", int " build_id_len ", const char *" filename ", char ** " path ");"
-.BI "typedef int (*debuginfo_progressfn_t)(long a, long b);"
-.BI "debuginfo_progressfn_t debuginfod_set_progressfn(debuginfo_progressfn_t " progressfn ");"
+.BI "debuginfod_client *debuginfod_begin(void);"
+.BI "void debuginfod_end(debuginfod_client *" client ");"
+
+.BI "int debuginfod_find_debuginfo(debuginfod_client *" client ","
+.BI " const unsigned char *" build_id ","
+.BI " int " build_id_len ","
+.BI " char ** " path ");"
+.BI "int debuginfod_find_executable(debuginfod_client *" client ","
+.BI " const unsigned char *" build_id ","
+.BI " int " build_id_len ","
+.BI " char ** " path ");"
+.BI "int debuginfod_find_source(debuginfod_client *" client ","
+.BI " const unsigned char *" build_id ","
+.BI " int " build_id_len ","
+.BI " const char *" filename ","
+.BI " char ** " path ");"
+
+.BI "typedef int (*debuginfo_progressfn_t)(debuginfod_client *" client ","
+.BI " long a, long b);"
+.BI "void debuginfod_set_progressfn(debuginfod_client *" client ","
+.BI " debuginfo_progressfn_t " progressfn ");"
Link with \fB-ldebuginfod\fP.
.SH DESCRIPTION
+
+.BR debuginfod_begin ()
+creates a \fBdebuginfod_client\fP connection handle that should be used
+with all other calls.
+.BR debuginfod_end ()
+should be called on the \fBclient\fP handle to release all state and
+storage when done.
+
.BR debuginfod_find_debuginfo (),
.BR debuginfod_find_executable (),
and
@@ -65,9 +89,14 @@ The URLs in \fB$DEBUGINFOD_URLS\fP may be queried in parallel. As soon
as a debuginfod server begins transferring the target file all of the
connections to the other servers are closed.
-These functions are MT-safe.
+A \fBclient\fP handle should be used from only one thread at a time.
.SH "RETURN VALUE"
+
+\fBdebuginfod_begin\fP returns the \fBdebuginfod_client\fP handle to
+use with all other calls. On error \fBNULL\fP will be returned and
+\fBerrno\fP will be set.
+
If a find family function is successful, the resulting file is saved
to the client cache and a file descriptor to that file is returned.
The caller needs to \fBclose\fP() this descriptor. Otherwise, a
@@ -75,12 +104,12 @@ negative error code is returned.
.SH "PROGRESS CALLBACK"
-As the \fBdebuginfod_find_*\fP() functions may block for seconds or longer, a progress
-callback function is called periodically, if configured with
+As the \fBdebuginfod_find_*\fP() functions may block for seconds or
+longer, a progress callback function is called periodically, if
+configured with
.BR debuginfod_set_progressfn ().
-This function sets a new progress callback function (or NULL) and
-returns the previously set function (or NULL). This function may be
-MT-unsafe.
+This function sets a new progress callback function (or NULL) for the
+client handle.
The given callback function is called from the context of each thread
that is invoking any of the other lookup functions. It is given two
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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <dlfcn.h>
+
+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 <inttypes.h>
#include <fcntl.h>
#include <unistd.h>
-#include <dlfcn.h>
#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 <stdio.h>
#include <fcntl.h>
#include <unistd.h>
-#include <dlfcn.h>
#include <sys/stat.h>
#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. */