Branch data Line data Source code
1 : : /* Try to get an ELF or debug file through the debuginfod.
2 : : Copyright (C) 2019 Red Hat, Inc.
3 : : Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include "libdwflP.h"
35 : :
36 : : #ifdef ENABLE_LIBDEBUGINFOD
37 : :
38 : : #include "debuginfod.h"
39 : :
40 : : #include <pthread.h>
41 : : #include <dlfcn.h>
42 : :
43 : : static __typeof__ (debuginfod_begin) *fp_debuginfod_begin;
44 : : static __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable;
45 : : static __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo;
46 : : static __typeof__ (debuginfod_end) *fp_debuginfod_end;
47 : :
48 : : static void __libdwfl_debuginfod_init (void);
49 : :
50 : : static pthread_once_t init_control = PTHREAD_ONCE_INIT;
51 : :
52 : : /* NB: this is slightly thread-unsafe */
53 : :
54 : : debuginfod_client *
55 : 206 : dwfl_get_debuginfod_client (Dwfl *dwfl)
56 : : {
57 [ + + ]: 206 : if (dwfl->debuginfod != NULL)
58 : 104 : return dwfl->debuginfod;
59 : :
60 : 102 : pthread_once (&init_control, __libdwfl_debuginfod_init);
61 : :
62 [ + - ]: 102 : if (fp_debuginfod_begin != NULL)
63 : : {
64 : 102 : dwfl->debuginfod = (*fp_debuginfod_begin) ();
65 : 102 : return dwfl->debuginfod;
66 : : }
67 : :
68 : 0 : return NULL;
69 : : }
70 : : INTDEF(dwfl_get_debuginfod_client)
71 : :
72 : : int
73 : 48 : __libdwfl_debuginfod_find_executable (Dwfl *dwfl,
74 : : const unsigned char *build_id_bits,
75 : : size_t build_id_len)
76 : : {
77 : 48 : int fd = -1;
78 [ + - ]: 48 : if (build_id_len > 0)
79 : : {
80 : 48 : debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
81 [ + - ]: 48 : if (c != NULL)
82 : 48 : fd = (*fp_debuginfod_find_executable) (c, build_id_bits,
83 : : build_id_len, NULL);
84 : : }
85 : :
86 : 48 : return fd;
87 : : }
88 : :
89 : : int
90 : 158 : __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
91 : : const unsigned char *build_id_bits,
92 : : size_t build_id_len)
93 : : {
94 : 158 : int fd = -1;
95 [ + - ]: 158 : if (build_id_len > 0)
96 : : {
97 : 158 : debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
98 [ + - ]: 158 : if (c != NULL)
99 : 158 : fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits,
100 : : build_id_len, NULL);
101 : : }
102 : :
103 : 158 : return fd;
104 : : }
105 : :
106 : : void
107 : 11554 : __libdwfl_debuginfod_end (debuginfod_client *c)
108 : : {
109 [ + + ]: 11554 : if (c != NULL)
110 : 102 : (*fp_debuginfod_end) (c);
111 : 11554 : }
112 : :
113 : : /* Try to get the libdebuginfod library functions.
114 : : Only needs to be called once from dwfl_get_debuginfod_client. */
115 : : static void
116 : 102 : __libdwfl_debuginfod_init (void)
117 : : {
118 : 102 : void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY);
119 : :
120 [ + - ]: 102 : if (debuginfod_so != NULL)
121 : : {
122 : 102 : fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin");
123 : 102 : fp_debuginfod_find_executable = dlsym (debuginfod_so,
124 : : "debuginfod_find_executable");
125 : 102 : fp_debuginfod_find_debuginfo = dlsym (debuginfod_so,
126 : : "debuginfod_find_debuginfo");
127 : 102 : fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end");
128 : :
129 : : /* We either get them all, or we get none. */
130 [ + - ]: 102 : if (fp_debuginfod_begin == NULL
131 [ + - ]: 102 : || fp_debuginfod_find_executable == NULL
132 [ + - ]: 102 : || fp_debuginfod_find_debuginfo == NULL
133 [ - + ]: 102 : || fp_debuginfod_end == NULL)
134 : : {
135 : 0 : fp_debuginfod_begin = NULL;
136 : 0 : fp_debuginfod_find_executable = NULL;
137 : 0 : fp_debuginfod_find_debuginfo = NULL;
138 : 0 : fp_debuginfod_end = NULL;
139 : 0 : dlclose (debuginfod_so);
140 : : }
141 : : }
142 : 102 : }
143 : :
144 : : #else // ENABLE_LIBDEBUGINFOD
145 : :
146 : : debuginfod_client *
147 : : dwfl_get_debuginfod_client (Dwfl *dummy __attribute__ ((unused)))
148 : : {
149 : : return NULL;
150 : : }
151 : :
152 : : #endif // ENABLE_LIBDEBUGINFOD
|