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 : 168 : dwfl_get_debuginfod_client (Dwfl *dwfl) 56 : : { 57 [ + + ]: 168 : if (dwfl->debuginfod != NULL) 58 : : return dwfl->debuginfod; 59 : : 60 : 104 : pthread_once (&init_control, __libdwfl_debuginfod_init); 61 : : 62 [ + - ]: 104 : if (fp_debuginfod_begin != NULL) 63 : : { 64 : 104 : dwfl->debuginfod = (*fp_debuginfod_begin) (); 65 : 104 : return dwfl->debuginfod; 66 : : } 67 : : 68 : : return NULL; 69 : : } 70 : : INTDEF(dwfl_get_debuginfod_client) 71 : : 72 : : int 73 : 28 : __libdwfl_debuginfod_find_executable (Dwfl *dwfl, 74 : : const unsigned char *build_id_bits, 75 : : size_t build_id_len) 76 : : { 77 : 28 : int fd = -1; 78 [ - + ]: 28 : if (build_id_len > 0) 79 : : { 80 : 28 : debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl); 81 [ - + ]: 28 : if (c != NULL) 82 : 28 : fd = (*fp_debuginfod_find_executable) (c, build_id_bits, 83 : : build_id_len, NULL); 84 : : } 85 : : 86 : 28 : return fd; 87 : : } 88 : : 89 : : int 90 : 140 : __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl, 91 : : const unsigned char *build_id_bits, 92 : : size_t build_id_len) 93 : : { 94 : 140 : int fd = -1; 95 [ - + ]: 140 : if (build_id_len > 0) 96 : : { 97 : 140 : debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl); 98 [ - + ]: 140 : if (c != NULL) 99 : 140 : fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits, 100 : : build_id_len, NULL); 101 : : } 102 : : 103 : 140 : return fd; 104 : : } 105 : : 106 : : void 107 : 11548 : __libdwfl_debuginfod_end (debuginfod_client *c) 108 : : { 109 [ + + ]: 11548 : if (c != NULL) 110 : 104 : (*fp_debuginfod_end) (c); 111 : 11548 : } 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 : 104 : __libdwfl_debuginfod_init (void) 117 : : { 118 : 104 : void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY); 119 : : 120 [ + - ]: 104 : if (debuginfod_so != NULL) 121 : : { 122 : 104 : fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin"); 123 : 104 : fp_debuginfod_find_executable = dlsym (debuginfod_so, 124 : : "debuginfod_find_executable"); 125 : 104 : fp_debuginfod_find_debuginfo = dlsym (debuginfod_so, 126 : : "debuginfod_find_debuginfo"); 127 : 104 : fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end"); 128 : : 129 : : /* We either get them all, or we get none. */ 130 [ + - ]: 104 : if (fp_debuginfod_begin == NULL 131 [ + - ]: 104 : || fp_debuginfod_find_executable == NULL 132 [ + - ]: 104 : || fp_debuginfod_find_debuginfo == NULL 133 [ - + ]: 104 : || 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 : 104 : } 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