1 /* Error handling in libelf. 2 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 1998. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18 #ifdef HAVE_CONFIG_H 19 # include <config.h> 20 #endif 21 22 #include <assert.h> 23 //#include <libintl.h> 24 #include <stdbool.h> 25 #include <stdint.h> 26 #include <stdlib.h> 27 28 #include "libelfP.h" 29 30 31 #ifdef USE_TLS 32 /* The error number. */ 33 static __thread int global_error; 34 #else 35 /* This is the key for the thread specific memory. */ 36 static tls_key_t key; 37 38 /* The error number. Used in non-threaded programs. */ 39 static int global_error; 40 static bool threaded; 41 /* We need to initialize the thread-specific data. */ 42 once_define (static, once); 43 44 /* The initialization and destruction functions. */ 45 static void init (void); 46 static void free_key_mem (void *mem); 47 #endif /* TLS */ 48 49 50 int 51 elf_errno (void) 52 { 53 int result; 54 55 #ifndef USE_TLS 56 /* If we have not yet initialized the buffer do it now. */ 57 once_execute (once, init); 58 59 if (threaded) 60 { 61 /* We do not allocate memory for the data. It is only a word. 62 We can store it in place of the pointer. */ 63 result = (intptr_t) getspecific (key); 64 65 setspecific (key, (void *) (intptr_t) ELF_E_NOERROR); 66 return result; 67 } 68 #endif /* TLS */ 69 70 result = global_error; 71 global_error = ELF_E_NOERROR; 72 return result; 73 } 74 75 76 /* Return the appropriate message for the error. */ 77 static const char msgstr[] = 78 { 79 #define ELF_E_NOERROR_IDX 0 80 N_("no error") 81 "\0" 82 #define ELF_E_UNKNOWN_ERROR_IDX (ELF_E_NOERROR_IDX + sizeof "no error") 83 N_("unknown error") 84 "\0" 85 #define ELF_E_UNKNOWN_VERSION_IDX \ 86 (ELF_E_UNKNOWN_ERROR_IDX + sizeof "unknown error") 87 N_("unknown version") 88 "\0" 89 #define ELF_E_UNKNOWN_TYPE_IDX \ 90 (ELF_E_UNKNOWN_VERSION_IDX + sizeof "unknown version") 91 N_("unknown type") 92 "\0" 93 #define ELF_E_INVALID_HANDLE_IDX \ 94 (ELF_E_UNKNOWN_TYPE_IDX + sizeof "unknown type") 95 N_("invalid `Elf' handle") 96 "\0" 97 #define ELF_E_SOURCE_SIZE_IDX \ 98 (ELF_E_INVALID_HANDLE_IDX + sizeof "invalid `Elf' handle") 99 N_("invalid size of source operand") 100 "\0" 101 #define ELF_E_DEST_SIZE_IDX \ 102 (ELF_E_SOURCE_SIZE_IDX + sizeof "invalid size of source operand") 103 N_("invalid size of destination operand") 104 "\0" 105 #define ELF_E_INVALID_ENCODING_IDX \ 106 (ELF_E_DEST_SIZE_IDX + sizeof "invalid size of destination operand") 107 N_("invalid encoding") 108 "\0" 109 #define ELF_E_NOMEM_IDX \ 110 (ELF_E_INVALID_ENCODING_IDX + sizeof "invalid encoding") 111 N_("out of memory") 112 "\0" 113 #define ELF_E_INVALID_FILE_IDX \ 114 (ELF_E_NOMEM_IDX + sizeof "out of memory") 115 N_("invalid file descriptor") 116 "\0" 117 #define ELF_E_INVALID_OP_IDX \ 118 (ELF_E_INVALID_FILE_IDX + sizeof "invalid file descriptor") 119 N_("invalid operation") 120 "\0" 121 #define ELF_E_NO_VERSION_IDX \ 122 (ELF_E_INVALID_OP_IDX + sizeof "invalid operation") 123 N_("ELF version not set") 124 "\0" 125 #define ELF_E_INVALID_CMD_IDX \ 126 (ELF_E_NO_VERSION_IDX + sizeof "ELF version not set") 127 N_("invalid command") 128 "\0" 129 #define ELF_E_RANGE_IDX \ 130 (ELF_E_INVALID_CMD_IDX + sizeof "invalid command") 131 N_("offset out of range") 132 "\0" 133 #define ELF_E_ARCHIVE_FMAG_IDX \ 134 (ELF_E_RANGE_IDX + sizeof "offset out of range") 135 N_("invalid fmag field in archive header") 136 "\0" 137 #define ELF_E_INVALID_ARCHIVE_IDX \ 138 (ELF_E_ARCHIVE_FMAG_IDX + sizeof "invalid fmag field in archive header") 139 N_("invalid archive file") 140 "\0" 141 #define ELF_E_NO_ARCHIVE_IDX \ 142 (ELF_E_INVALID_ARCHIVE_IDX + sizeof "invalid archive file") 143 N_("descriptor is not for an archive") 144 "\0" 145 #define ELF_E_NO_INDEX_IDX \ 146 (ELF_E_NO_ARCHIVE_IDX + sizeof "descriptor is not for an archive") 147 N_("no index available") 148 "\0" 149 #define ELF_E_READ_ERROR_IDX \ 150 (ELF_E_NO_INDEX_IDX + sizeof "no index available") 151 N_("cannot read data from file") 152 "\0" 153 #define ELF_E_WRITE_ERROR_IDX \ 154 (ELF_E_READ_ERROR_IDX + sizeof "cannot read data from file") 155 N_("cannot write data to file") 156 "\0" 157 #define ELF_E_INVALID_CLASS_IDX \ 158 (ELF_E_WRITE_ERROR_IDX + sizeof "cannot write data to file") 159 N_("invalid binary class") 160 "\0" 161 #define ELF_E_INVALID_INDEX_IDX \ 162 (ELF_E_INVALID_CLASS_IDX + sizeof "invalid binary class") 163 N_("invalid section index") 164 "\0" 165 #define ELF_E_INVALID_OPERAND_IDX \ 166 (ELF_E_INVALID_INDEX_IDX + sizeof "invalid section index") 167 N_("invalid operand") 168 "\0" 169 #define ELF_E_INVALID_SECTION_IDX \ 170 (ELF_E_INVALID_OPERAND_IDX + sizeof "invalid operand") 171 N_("invalid section") 172 "\0" 173 #define ELF_E_INVALID_COMMAND_IDX \ 174 (ELF_E_INVALID_SECTION_IDX + sizeof "invalid section") 175 N_("invalid command") 176 "\0" 177 #define ELF_E_WRONG_ORDER_EHDR_IDX \ 178 (ELF_E_INVALID_COMMAND_IDX + sizeof "invalid command") 179 N_("executable header not created first") 180 "\0" 181 #define ELF_E_FD_DISABLED_IDX \ 182 (ELF_E_WRONG_ORDER_EHDR_IDX + sizeof "executable header not created first") 183 N_("file descriptor disabled") 184 "\0" 185 #define ELF_E_FD_MISMATCH_IDX \ 186 (ELF_E_FD_DISABLED_IDX + sizeof "file descriptor disabled") 187 N_("archive/member fildes mismatch") 188 "\0" 189 #define ELF_E_OFFSET_RANGE_IDX \ 190 (ELF_E_FD_MISMATCH_IDX + sizeof "archive/member fildes mismatch") 191 N_("offset out of range") 192 "\0" 193 #define ELF_E_NOT_NUL_SECTION_IDX \ 194 (ELF_E_OFFSET_RANGE_IDX + sizeof "offset out of range") 195 N_("cannot manipulate null section") 196 "\0" 197 #define ELF_E_DATA_MISMATCH_IDX \ 198 (ELF_E_NOT_NUL_SECTION_IDX + sizeof "cannot manipulate null section") 199 N_("data/scn mismatch") 200 "\0" 201 #define ELF_E_INVALID_SECTION_HEADER_IDX \ 202 (ELF_E_DATA_MISMATCH_IDX + sizeof "data/scn mismatch") 203 N_("invalid section header") 204 "\0" 205 #define ELF_E_INVALID_DATA_IDX \ 206 (ELF_E_INVALID_SECTION_HEADER_IDX + sizeof "invalid section header") 207 N_("invalid data") 208 "\0" 209 #define ELF_E_DATA_ENCODING_IDX \ 210 (ELF_E_INVALID_DATA_IDX + sizeof "invalid data") 211 N_("unknown data encoding") 212 "\0" 213 #define ELF_E_SECTION_TOO_SMALL_IDX \ 214 (ELF_E_DATA_ENCODING_IDX + sizeof "unknown data encoding") 215 N_("section `sh_size' too small for data") 216 "\0" 217 #define ELF_E_INVALID_ALIGN_IDX \ 218 (ELF_E_SECTION_TOO_SMALL_IDX + sizeof "section `sh_size' too small for data") 219 N_("invalid section alignment") 220 "\0" 221 #define ELF_E_INVALID_SHENTSIZE_IDX \ 222 (ELF_E_INVALID_ALIGN_IDX + sizeof "invalid section alignment") 223 N_("invalid section entry size") 224 "\0" 225 #define ELF_E_UPDATE_RO_IDX \ 226 (ELF_E_INVALID_SHENTSIZE_IDX + sizeof "invalid section entry size") 227 N_("update() for write on read-only file") 228 "\0" 229 #define ELF_E_NOFILE_IDX \ 230 (ELF_E_UPDATE_RO_IDX + sizeof "update() for write on read-only file") 231 N_("no such file") 232 "\0" 233 #define ELF_E_GROUP_NOT_REL_IDX \ 234 (ELF_E_NOFILE_IDX + sizeof "no such file") 235 N_("only relocatable files can contain section groups") 236 "\0" 237 #define ELF_E_INVALID_PHDR_IDX \ 238 (ELF_E_GROUP_NOT_REL_IDX \ 239 + sizeof "only relocatable files can contain section groups") 240 N_("program header only allowed in executables and shared objects") 241 "\0" 242 #define ELF_E_NO_PHDR_IDX \ 243 (ELF_E_INVALID_PHDR_IDX \ 244 + sizeof "program header only allowed in executables and shared objects") 245 N_("file has no program header") 246 }; 247 248 249 static const uint_fast16_t msgidx[ELF_E_NUM] = 250 { 251 [ELF_E_NOERROR] = ELF_E_NOERROR_IDX, 252 [ELF_E_UNKNOWN_ERROR] = ELF_E_UNKNOWN_ERROR_IDX, 253 [ELF_E_UNKNOWN_VERSION] = ELF_E_UNKNOWN_VERSION_IDX, 254 [ELF_E_UNKNOWN_TYPE] = ELF_E_UNKNOWN_TYPE_IDX, 255 [ELF_E_INVALID_HANDLE] = ELF_E_INVALID_HANDLE_IDX, 256 [ELF_E_SOURCE_SIZE] = ELF_E_SOURCE_SIZE_IDX, 257 [ELF_E_DEST_SIZE] = ELF_E_DEST_SIZE_IDX, 258 [ELF_E_INVALID_ENCODING] = ELF_E_INVALID_ENCODING_IDX, 259 [ELF_E_NOMEM] = ELF_E_NOMEM_IDX, 260 [ELF_E_INVALID_FILE] = ELF_E_INVALID_FILE_IDX, 261 [ELF_E_INVALID_OP] = ELF_E_INVALID_OP_IDX, 262 [ELF_E_NO_VERSION] = ELF_E_NO_VERSION_IDX, 263 [ELF_E_INVALID_CMD] = ELF_E_INVALID_CMD_IDX, 264 [ELF_E_RANGE] = ELF_E_RANGE_IDX, 265 [ELF_E_ARCHIVE_FMAG] = ELF_E_ARCHIVE_FMAG_IDX, 266 [ELF_E_INVALID_ARCHIVE] = ELF_E_INVALID_ARCHIVE_IDX, 267 [ELF_E_NO_ARCHIVE] = ELF_E_NO_ARCHIVE_IDX, 268 [ELF_E_NO_INDEX] = ELF_E_NO_INDEX_IDX, 269 [ELF_E_READ_ERROR] = ELF_E_READ_ERROR_IDX, 270 [ELF_E_WRITE_ERROR] = ELF_E_WRITE_ERROR_IDX, 271 [ELF_E_INVALID_CLASS] = ELF_E_INVALID_CLASS_IDX, 272 [ELF_E_INVALID_INDEX] = ELF_E_INVALID_INDEX_IDX, 273 [ELF_E_INVALID_OPERAND] = ELF_E_INVALID_OPERAND_IDX, 274 [ELF_E_INVALID_SECTION] = ELF_E_INVALID_SECTION_IDX, 275 [ELF_E_INVALID_COMMAND] = ELF_E_INVALID_COMMAND_IDX, 276 [ELF_E_WRONG_ORDER_EHDR] = ELF_E_WRONG_ORDER_EHDR_IDX, 277 [ELF_E_FD_DISABLED] = ELF_E_FD_DISABLED_IDX, 278 [ELF_E_FD_MISMATCH] = ELF_E_FD_MISMATCH_IDX, 279 [ELF_E_OFFSET_RANGE] = ELF_E_OFFSET_RANGE_IDX, 280 [ELF_E_NOT_NUL_SECTION] = ELF_E_NOT_NUL_SECTION_IDX, 281 [ELF_E_DATA_MISMATCH] = ELF_E_DATA_MISMATCH_IDX, 282 [ELF_E_INVALID_SECTION_HEADER] = ELF_E_INVALID_SECTION_HEADER_IDX, 283 [ELF_E_INVALID_DATA] = ELF_E_INVALID_DATA_IDX, 284 [ELF_E_DATA_ENCODING] = ELF_E_DATA_ENCODING_IDX, 285 [ELF_E_SECTION_TOO_SMALL] = ELF_E_SECTION_TOO_SMALL_IDX, 286 [ELF_E_INVALID_ALIGN] = ELF_E_INVALID_ALIGN_IDX, 287 [ELF_E_INVALID_SHENTSIZE] = ELF_E_INVALID_SHENTSIZE_IDX, 288 [ELF_E_UPDATE_RO] = ELF_E_UPDATE_RO_IDX, 289 [ELF_E_NOFILE] = ELF_E_NOFILE_IDX, 290 [ELF_E_GROUP_NOT_REL] = ELF_E_GROUP_NOT_REL_IDX, 291 [ELF_E_INVALID_PHDR] = ELF_E_INVALID_PHDR_IDX, 292 [ELF_E_NO_PHDR] = ELF_E_NO_PHDR_IDX 293 }; 294 #define nmsgidx ((int) (sizeof (msgidx) / sizeof (msgidx[0]))) 295 296 297 void 298 __libelf_seterrno (value) 299 int value; 300 { 301 #ifndef USE_TLS 302 /* If we have not yet initialized the buffer do it now. */ 303 once_execute (once, init); 304 305 if (threaded) 306 /* We do not allocate memory for the data. It is only a word. 307 We can store it in place of the pointer. */ 308 setspecific (key, (void *) (intptr_t) value); 309 #endif /* TLS */ 310 311 global_error = value >= 0 && value < nmsgidx ? value : ELF_E_UNKNOWN_ERROR; 312 } 313 314 315 const char * 316 elf_errmsg (error) 317 int error; 318 { 319 int last_error; 320 321 #ifndef USE_TLS 322 /* If we have not yet initialized the buffer do it now. */ 323 once_execute (once, init); 324 325 if ((error == 0 || error == -1) && threaded) 326 /* We do not allocate memory for the data. It is only a word. 327 We can store it in place of the pointer. */ 328 last_error = (intptr_t) getspecific (key); 329 else 330 #endif /* TLS */ 331 last_error = global_error; 332 333 if (error == 0) 334 { 335 assert (msgidx[last_error] < sizeof (msgstr)); 336 return last_error != 0 ? _(msgstr + msgidx[last_error]) : NULL; 337 } 338 else if (error < -1 || error >= nmsgidx) 339 return _(msgstr + ELF_E_UNKNOWN_ERROR_IDX); 340 341 assert (msgidx[error == -1 ? last_error : error] < sizeof (msgstr)); 342 return _(msgstr + msgidx[error == -1 ? last_error : error]); 343 } 344 345 346 #ifndef USE_TLS 347 /* Free the thread specific data, this is done if a thread terminates. */ 348 static void 349 free_key_mem (void *mem) 350 { 351 setspecific (key, NULL); 352 } 353 354 355 /* Initialize the key for the global variable. */ 356 static void 357 init (void) 358 { 359 // XXX Screw you, gcc4, the unused function attribute does not work. 360 __asm ("" :: "r" (free_key_mem)); 361 362 if (key_create (&key, free_key_mem) == 0) 363 /* Creating the key succeeded. */ 364 threaded = true; 365 } 366 #endif /* TLS */ 367