]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
debuginfod: add client context
authorMark Wielaard <mark@klomp.org>
Sun, 17 Nov 2019 21:17:26 +0000 (22:17 +0100)
committerMark Wielaard <mark@klomp.org>
Sat, 23 Nov 2019 00:03:13 +0000 (01:03 +0100)
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>
14 files changed:
debuginfod/debuginfod-client.c
debuginfod/debuginfod-find.c
debuginfod/debuginfod.cxx
debuginfod/debuginfod.h
debuginfod/libdebuginfod.map
doc/debuginfod_begin.3 [new file with mode: 0644]
doc/debuginfod_end.3 [new file with mode: 0644]
doc/debuginfod_find_debuginfo.3
libdwfl/Makefile.am
libdwfl/debuginfod-client.c [new file with mode: 0644]
libdwfl/dwfl_build_id_find_elf.c
libdwfl/dwfl_end.c
libdwfl/find-debuginfo.c
libdwfl/libdwflP.h

index 64dd608a6ec3702e83484b6f1604ded67baa8470..6e62b86c24971fa34229c833198388e11cc6b3cd 100644 (file)
   #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;
 }
 
 
index 4c1a94c66089896048b4a857b6258521bd7d221a..8bd3a3dba7a07433b4b4dba1894083b2bfedbd37 100644 (file)
@@ -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;
 }
index e2535cefdbdf3b994782c915d88fb86a3d8dde74..f4bbc7b73d86577ceca96d81fe64836da30a58a8 100644 (file)
@@ -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
index 0620f02ad1a58261a0db7631c32e11262d70bd3d..6b1b1cc3e8ae04e76f4595219eb56581951d26ff 100644 (file)
 #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
 }
index b322cba644f50ed320d22de01759371d20795fda..0d26f93e04fe6c2266c0315f7e6a9183ce651386 100644 (file)
@@ -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 (file)
index 0000000..1627993
--- /dev/null
@@ -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 (file)
index 0000000..1627993
--- /dev/null
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
index d8d9236e0f27d686f51ef96b16fc4e85e52d19c3..be8eed09eb88c96fdb213ce385e593611c3b9e73 100644 (file)
@@ -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
index 29046e9e5e85a37177388b69a3b8d7f41b220650..47bd62a5e430e6361a49d304285695b094dc2512 100644 (file)
@@ -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 (file)
index 0000000..ee604ad
--- /dev/null
@@ -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);
+       }
+    }
+}
index b775f50abbbaee14d09c862b3f48547140f36542..4e56143f4fd1de76e1e22decacee42e892a32ddd 100644 (file)
@@ -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
index 74ee9e07244fd5022b2bd68c95e6544198933997..4f6c722a7c56a43c1c1ab43ef65926e52617cc72 100644 (file)
@@ -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);
 
index ffc07f92877833e6a4027fb115922f796ab14d20..4085764547fbe2a06d3e1aeffd83bea834f3d36f 100644 (file)
 #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;
 }
index 6b2d48672177be88341215747c1b3e9bacbaf821..f631f9464f8dc796b9836a67786bdb16ec6ef43e 100644 (file)
@@ -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.  */