1 /* Error handling in libdwfl. 2 Copyright (C) 2005-2010 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 static const struct msgtable 58 { 59 #define DWFL_ERROR(name, text) char msg_##name[sizeof text]; 60 DWFL_ERRORS 61 #undef DWFL_ERROR 62 } msgtable = 63 { 64 #define DWFL_ERROR(name, text) text, 65 DWFL_ERRORS 66 #undef DWFL_ERROR 67 }; 68 #define msgstr (&msgtable.msg_NOERROR[0]) 69 70 static const uint_fast16_t msgidx[] = 71 { 72 #define DWFL_ERROR(name, text) \ 73 [DWFL_E_##name] = offsetof (struct msgtable, msg_##name), 74 DWFL_ERRORS 75 #undef DWFL_ERROR 76 }; 77 #define nmsgidx (sizeof msgidx / sizeof msgidx[0]) 78 79 80 static inline int 81 canonicalize (Dwfl_Error error) 82 { 83 unsigned int value; 84 85 switch (error) 86 { 87 default: 88 value = error; 89 if ((value &~ 0xffff) != 0) 90 break; 91 assert (value < nmsgidx); 92 break; 93 case DWFL_E_ERRNO: 94 value = DWFL_E (ERRNO, errno); 95 break; 96 case DWFL_E_LIBELF: 97 value = DWFL_E (LIBELF, elf_errno ()); 98 break; 99 case DWFL_E_LIBDW: 100 value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ()); 101 break; 102 #if 0 103 DWFL_E_LIBEBL: 104 value = DWFL_E (LIBEBL, ebl_errno ()); 105 break; 106 #endif 107 } 108 109 return value; 110 } 111 112 int 113 internal_function 114 __libdwfl_canon_error (Dwfl_Error error) 115 { 116 return canonicalize (error); 117 } 118 119 void 120 internal_function 121 __libdwfl_seterrno (Dwfl_Error error) 122 { 123 global_error = canonicalize (error); 124 } 125 126 127 const char * 128 dwfl_errmsg (error) 129 int error; 130 { 131 if (error == 0 || error == -1) 132 { 133 int last_error = global_error; 134 135 if (error == 0 && last_error == 0) 136 return NULL; 137 138 error = last_error; 139 global_error = DWFL_E_NOERROR; 140 } 141 142 switch (error &~ 0xffff) 143 { 144 case OTHER_ERROR (ERRNO): 145 return strerror_r (error & 0xffff, "bad", 0); 146 case OTHER_ERROR (LIBELF): 147 return elf_errmsg (error & 0xffff); 148 case OTHER_ERROR (LIBDW): 149 return INTUSE(dwarf_errmsg) (error & 0xffff); 150 #if 0 151 case OTHER_ERROR (LIBEBL): 152 return ebl_errmsg (error & 0xffff); 153 #endif 154 } 155 156 return _(&msgstr[msgidx[(unsigned int) error < nmsgidx 157 ? error : DWFL_E_UNKNOWN_ERROR]]); 158 } 159 INTDEF (dwfl_errmsg) 160