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 : : #include <pthread.h> 36 : : #include <dlfcn.h> 37 : : 38 : : static __typeof__ (debuginfod_begin) *fp_debuginfod_begin; 39 : : static __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable; 40 : : static __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo; 41 : : static __typeof__ (debuginfod_end) *fp_debuginfod_end; 42 : : 43 : : static void __libdwfl_debuginfod_init (void); 44 : : 45 : : static pthread_once_t init_control = PTHREAD_ONCE_INIT; 46 : : 47 : : /* NB: this is slightly thread-unsafe */ 48 : : 49 : : static debuginfod_client * 50 : 71 : get_client (Dwfl *dwfl) 51 : : { 52 [ + + ]: 71 : if (dwfl->debuginfod != NULL) 53 : : return dwfl->debuginfod; 54 : : 55 : 44 : pthread_once (&init_control, __libdwfl_debuginfod_init); 56 : : 57 [ + - ]: 44 : if (fp_debuginfod_begin != NULL) 58 : : { 59 : 44 : dwfl->debuginfod = (*fp_debuginfod_begin) (); 60 : 44 : return dwfl->debuginfod; 61 : : } 62 : : 63 : : return NULL; 64 : : } 65 : : 66 : : int 67 : 14 : __libdwfl_debuginfod_find_executable (Dwfl *dwfl, 68 : : const unsigned char *build_id_bits, 69 : : size_t build_id_len) 70 : : { 71 : 14 : int fd = -1; 72 [ + - ]: 14 : if (build_id_len > 0) 73 : : { 74 : 14 : debuginfod_client *c = get_client (dwfl); 75 [ + - ]: 14 : if (c != NULL) 76 : 14 : fd = (*fp_debuginfod_find_executable) (c, build_id_bits, 77 : : build_id_len, NULL); 78 : : } 79 : : 80 : 14 : return fd; 81 : : } 82 : : 83 : : int 84 : 57 : __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl, 85 : : const unsigned char *build_id_bits, 86 : : size_t build_id_len) 87 : : { 88 : 57 : int fd = -1; 89 [ + - ]: 57 : if (build_id_len > 0) 90 : : { 91 : 57 : debuginfod_client *c = get_client (dwfl); 92 [ + - ]: 57 : if (c != NULL) 93 : 57 : fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits, 94 : : build_id_len, NULL); 95 : : } 96 : : 97 : 57 : return fd; 98 : : } 99 : : 100 : : void 101 : 5678 : __libdwfl_debuginfod_end (debuginfod_client *c) 102 : : { 103 [ + + ]: 5678 : if (c != NULL) 104 : 44 : (*fp_debuginfod_end) (c); 105 : 5678 : } 106 : : 107 : : /* Try to get the libdebuginfod library functions. 108 : : Only needs to be called once from get_client. */ 109 : : static void 110 : 44 : __libdwfl_debuginfod_init (void) 111 : : { 112 : 44 : void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY); 113 : : 114 [ + - ]: 44 : if (debuginfod_so != NULL) 115 : : { 116 : 44 : fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin"); 117 : 44 : fp_debuginfod_find_executable = dlsym (debuginfod_so, 118 : : "debuginfod_find_executable"); 119 : 44 : fp_debuginfod_find_debuginfo = dlsym (debuginfod_so, 120 : : "debuginfod_find_debuginfo"); 121 : 44 : fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end"); 122 : : 123 : : /* We either get them all, or we get none. */ 124 [ + - ]: 44 : if (fp_debuginfod_begin == NULL 125 [ + - ]: 44 : || fp_debuginfod_find_executable == NULL 126 [ + - ]: 44 : || fp_debuginfod_find_debuginfo == NULL 127 [ - + ]: 44 : || fp_debuginfod_end == NULL) 128 : : { 129 : 0 : fp_debuginfod_begin = NULL; 130 : 0 : fp_debuginfod_find_executable = NULL; 131 : 0 : fp_debuginfod_find_debuginfo = NULL; 132 : 0 : fp_debuginfod_end = NULL; 133 : 0 : dlclose (debuginfod_so); 134 : : } 135 : : } 136 : 44 : }