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 <libintl.h> 35 #include <stdbool.h> 36 #include <stdint.h> 37 #include <stdlib.h> 38 #include <errno.h> 39 40 #include "libdwflP.h" 41 42 43 /* The error number. */ 44 static __thread int global_error; 45 46 47 int 48 dwfl_errno (void) 49 { 50 int result = global_error; 51 global_error = DWFL_E_NOERROR; 52 return result; 53 } 54 INTDEF (dwfl_errno) 55 56 57 struct msgtable 58 { 59 #define DWFL_ERROR(name, text) char msg_##name[sizeof text]; 60 DWFL_ERRORS 61 #undef DWFL_ERROR 62 }; 63 64 static const union 65 { 66 struct msgtable table; 67 char strings[ 68 #define DWFL_ERROR(name, text) + sizeof text 69 DWFL_ERRORS 70 #undef DWFL_ERROR 71 ]; 72 } msgtable = 73 { 74 .table = 75 { 76 #define DWFL_ERROR(name, text) text, 77 DWFL_ERRORS 78 #undef DWFL_ERROR 79 } 80 }; 81 #define msgstr (msgtable.strings) 82 83 static const uint_fast16_t msgidx[] = 84 { 85 #define DWFL_ERROR(name, text) \ 86 [DWFL_E_##name] = offsetof (struct msgtable, msg_##name), 87 DWFL_ERRORS 88 #undef DWFL_ERROR 89 }; 90 #define nmsgidx (sizeof msgidx / sizeof msgidx[0]) 91 92 93 static inline int 94 canonicalize (Dwfl_Error error) 95 { 96 unsigned int value; 97 98 switch (error) 99 { 100 default: 101 value = error; 102 if ((value &~ 0xffff) != 0) 103 break; 104 assert (value < nmsgidx); 105 break; 106 case DWFL_E_ERRNO: 107 value = DWFL_E (ERRNO, errno); 108 break; 109 case DWFL_E_LIBELF: 110 value = DWFL_E (LIBELF, elf_errno ()); 111 break; 112 case DWFL_E_LIBDW: 113 value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ()); 114 break; 115 #if 0 116 DWFL_E_LIBEBL: 117 value = DWFL_E (LIBEBL, ebl_errno ()); 118 break; 119 #endif 120 } 121 122 return value; 123 } 124 125 int 126 internal_function 127 __libdwfl_canon_error (Dwfl_Error error) 128 { 129 return canonicalize (error); 130 } 131 132 void 133 internal_function 134 __libdwfl_seterrno (Dwfl_Error error) 135 { 136 global_error = canonicalize (error); 137 } 138 139 140 const char * 141 dwfl_errmsg (int error) 142 { 143 if (error == 0 || error == -1) 144 { 145 int last_error = global_error; 146 147 if (error == 0 && last_error == 0) 148 return NULL; 149 150 error = last_error; 151 global_error = DWFL_E_NOERROR; 152 } 153 154 switch (error &~ 0xffff) 155 { 156 case OTHER_ERROR (ERRNO): 157 return strerror_r (error & 0xffff, "bad", 0); 158 case OTHER_ERROR (LIBELF): 159 return elf_errmsg (error & 0xffff); 160 case OTHER_ERROR (LIBDW): 161 return INTUSE(dwarf_errmsg) (error & 0xffff); 162 #if 0 163 case OTHER_ERROR (LIBEBL): 164 return ebl_errmsg (error & 0xffff); 165 #endif 166 } 167 168 return _(&msgstr[msgidx[(unsigned int) error < nmsgidx 169 ? error : DWFL_E_UNKNOWN_ERROR]]); 170 } 171 INTDEF (dwfl_errmsg) 172