xref: /aosp_15_r20/external/elfutils/libdwfl/debuginfod-client.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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