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