Branch data Line data Source code
1 : : /* Error handling in libdwfl. 2 : : Copyright (C) 2005-2015 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <assert.h> 34 : : #include <stdbool.h> 35 : : #include <stdint.h> 36 : : #include <stdlib.h> 37 : : #include <errno.h> 38 : : 39 : : #include "libdwflP.h" 40 : : 41 : : 42 : : /* The error number. */ 43 : : static __thread int global_error; 44 : : 45 : : 46 : : int 47 : 392 : dwfl_errno (void) 48 : : { 49 : 392 : int result = global_error; 50 : 392 : global_error = DWFL_E_NOERROR; 51 : 392 : return result; 52 : : } 53 : : INTDEF (dwfl_errno) 54 : : 55 : : 56 : : struct msgtable 57 : : { 58 : : #define DWFL_ERROR(name, text) char msg_##name[sizeof text]; 59 : : DWFL_ERRORS 60 : : #undef DWFL_ERROR 61 : : }; 62 : : 63 : : static const union 64 : : { 65 : : struct msgtable table; 66 : : char strings[ 67 : : #define DWFL_ERROR(name, text) + sizeof text 68 : : DWFL_ERRORS 69 : : #undef DWFL_ERROR 70 : : ]; 71 : : } msgtable = 72 : : { 73 : : .table = 74 : : { 75 : : #define DWFL_ERROR(name, text) text, 76 : : DWFL_ERRORS 77 : : #undef DWFL_ERROR 78 : : } 79 : : }; 80 : : #define msgstr (msgtable.strings) 81 : : 82 : : static const uint_fast16_t msgidx[] = 83 : : { 84 : : #define DWFL_ERROR(name, text) \ 85 : : [DWFL_E_##name] = offsetof (struct msgtable, msg_##name), 86 : : DWFL_ERRORS 87 : : #undef DWFL_ERROR 88 : : }; 89 : : #define nmsgidx (sizeof msgidx / sizeof msgidx[0]) 90 : : 91 : : 92 : : static inline int 93 : 2924 : canonicalize (Dwfl_Error error) 94 : : { 95 : 2924 : unsigned int value; 96 : : 97 [ + + + + ]: 2924 : switch (error) 98 : : { 99 : 2732 : default: 100 : 2732 : value = error; 101 [ + + ]: 2732 : if ((value &~ 0xffff) != 0) 102 : : break; 103 [ - + ]: 2706 : assert (value < nmsgidx); 104 : : break; 105 : 2 : case DWFL_E_ERRNO: 106 : 2 : value = DWFL_E (ERRNO, errno); 107 : 2 : break; 108 : 6 : case DWFL_E_LIBELF: 109 : 6 : value = DWFL_E (LIBELF, elf_errno ()); 110 : 6 : break; 111 : 184 : case DWFL_E_LIBDW: 112 : 184 : value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ()); 113 : 184 : break; 114 : : #if 0 115 : : DWFL_E_LIBEBL: 116 : : value = DWFL_E (LIBEBL, ebl_errno ()); 117 : : break; 118 : : #endif 119 : : } 120 : : 121 : 2924 : return value; 122 : : } 123 : : 124 : : int 125 : : internal_function 126 : 2 : __libdwfl_canon_error (Dwfl_Error error) 127 : : { 128 : 2 : return canonicalize (error); 129 : : } 130 : : 131 : : void 132 : : internal_function 133 : 2922 : __libdwfl_seterrno (Dwfl_Error error) 134 : : { 135 : 2922 : global_error = canonicalize (error); 136 : 2922 : } 137 : : 138 : : 139 : : static const char * 140 : 0 : errnomsg(int error) 141 : : { 142 : : /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */ 143 : 0 : static char unknown[] = "unknown error"; 144 : : 145 : : #ifdef STRERROR_R_CHAR_P 146 : 0 : return strerror_r (error, unknown, 0); 147 : : #else 148 : : /* To store the error message from strerror_r in a thread-safe manner */ 149 : : static __thread char msg[128]; 150 : : return strerror_r (error, msg, sizeof (msg)) ? unknown : msg; 151 : : #endif 152 : : } 153 : : 154 : : const char * 155 : 30 : dwfl_errmsg (int error) 156 : : { 157 [ + + ]: 30 : if (error == 0 || error == -1) 158 : : { 159 : 28 : int last_error = global_error; 160 : : 161 [ + - ]: 28 : if (error == 0 && last_error == 0) 162 : : return NULL; 163 : : 164 : 28 : error = last_error; 165 : 28 : global_error = DWFL_E_NOERROR; 166 : : } 167 : : 168 [ - - + + ]: 30 : switch (error &~ 0xffff) 169 : : { 170 : 0 : case OTHER_ERROR (ERRNO): 171 : 0 : return errnomsg (error & 0xffff); 172 : 0 : case OTHER_ERROR (LIBELF): 173 : 0 : return elf_errmsg (error & 0xffff); 174 : 8 : case OTHER_ERROR (LIBDW): 175 : 8 : return INTUSE(dwarf_errmsg) (error & 0xffff); 176 : : #if 0 177 : : case OTHER_ERROR (LIBEBL): 178 : : return ebl_errmsg (error & 0xffff); 179 : : #endif 180 : : } 181 : : 182 [ - + ]: 22 : return _(&msgstr[msgidx[(unsigned int) error < nmsgidx 183 : : ? error : DWFL_E_UNKNOWN_ERROR]]); 184 : : } 185 : : INTDEF (dwfl_errmsg)