1 /* Retrieve ELF descriptor used for DWARF access. 2 Copyright (C) 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 2002. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15 #ifdef HAVE_CONFIG_H 16 # include <config.h> 17 #endif 18 19 #include <assert.h> 20 #include <stddef.h> 21 22 #include "libdwP.h" 23 24 25 #ifdef USE_TLS 26 /* The error number. */ 27 static int global_error; 28 #else 29 /* This is the key for the thread specific memory. */ 30 static tls_key_t key; 31 32 /* The error number. Used in non-threaded programs. */ 33 static int global_error; 34 static bool threaded; 35 /* We need to initialize the thread-specific data. */ 36 once_define (static, once); 37 38 /* The initialization and destruction functions. */ 39 static void init (void); 40 static void free_key_mem (void *mem); 41 #endif /* TLS */ 42 43 44 int 45 dwarf_errno (void) 46 { 47 int result; 48 49 #ifndef USE_TLS 50 /* If we have not yet initialized the buffer do it now. */ 51 once_execute (once, init); 52 53 if (threaded) 54 { 55 /* We do not allocate memory for the data. It is only a word. 56 We can store it in place of the pointer. */ 57 result = (intptr_t) getspecific (key); 58 59 setspecific (key, (void *) (intptr_t) DWARF_E_NOERROR); 60 return result; 61 } 62 #endif /* TLS */ 63 64 result = global_error; 65 global_error = DWARF_E_NOERROR; 66 return result; 67 } 68 69 70 /* XXX For now we use string pointers. Once the table stablelizes 71 make it more DSO-friendly. */ 72 static const char *errmsgs[] = 73 { 74 [DWARF_E_NOERROR] = N_("no error"), 75 [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"), 76 [DWARF_E_INVALID_ACCESS] = N_("invalid access"), 77 [DWARF_E_NO_REGFILE] = N_("no regular file"), 78 [DWARF_E_IO_ERROR] = N_("I/O error"), 79 [DWARF_E_INVALID_ELF] = N_("invalid ELF file"), 80 [DWARF_E_NO_DWARF] = N_("no DWARF information"), 81 [DWARF_E_NOELF] = N_("no ELF file"), 82 [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"), 83 [DWARF_E_NOMEM] = N_("out of memory"), 84 [DWARF_E_UNIMPL] = N_("not implemented"), 85 [DWARF_E_INVALID_CMD] = N_("invalid command"), 86 [DWARF_E_INVALID_VERSION] = N_("invalid version"), 87 [DWARF_E_INVALID_FILE] = N_("invalid file"), 88 [DWARF_E_NO_ENTRY] = N_("no entries found"), 89 [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"), 90 [DWARF_E_NO_STRING] = N_("no string data"), 91 [DWARF_E_NO_ADDR] = N_("no address value"), 92 [DWARF_E_NO_CONSTANT] = N_("no constant value"), 93 [DWARF_E_NO_REFERENCE] = N_("no reference value"), 94 [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"), 95 [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"), 96 [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"), 97 [DWARF_E_TOO_BIG] = N_("debug information too big"), 98 [DWARF_E_VERSION] = N_("invalid DWARF version"), 99 [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"), 100 [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"), 101 [DWARF_E_NO_LOCLIST] = N_("no location list value"), 102 [DWARF_E_NO_BLOCK] = N_("no block data"), 103 [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"), 104 [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"), 105 [DWARF_E_NO_MATCH] = N_("no matching address range"), 106 [DWARF_E_NO_FLAG] = N_("no flag value"), 107 }; 108 #define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0])) 109 110 111 void 112 __libdw_seterrno (value) 113 int value; 114 { 115 #ifndef USE_TLS 116 /* If we have not yet initialized the buffer do it now. */ 117 once_execute (once, init); 118 119 if (threaded) 120 /* We do not allocate memory for the data. It is only a word. 121 We can store it in place of the pointer. */ 122 setspecific (key, (void *) (intptr_t) value); 123 #endif /* TLS */ 124 125 global_error = (value >= 0 && value < (int) nerrmsgs 126 ? value : DWARF_E_UNKNOWN_ERROR); 127 } 128 129 130 const char * 131 dwarf_errmsg (error) 132 int error; 133 { 134 int last_error; 135 136 #ifndef USE_TLS 137 /* If we have not yet initialized the buffer do it now. */ 138 once_execute (once, init); 139 140 if ((error == 0 || error == -1) && threaded) 141 /* We do not allocate memory for the data. It is only a word. 142 We can store it in place of the pointer. */ 143 last_error = (intptr_t) getspecific (key); 144 else 145 #endif /* TLS */ 146 last_error = global_error; 147 148 if (error == 0) 149 return last_error != 0 ? _(errmsgs[last_error]) : NULL; 150 else if (error < -1 || error >= (int) nerrmsgs) 151 return _(errmsgs[DWARF_E_UNKNOWN_ERROR]); 152 153 return _(errmsgs[error == -1 ? last_error : error]); 154 } 155 156 157 #ifndef USE_TLS 158 /* Free the thread specific data, this is done if a thread terminates. */ 159 static void 160 free_key_mem (void *mem) 161 { 162 setspecific (key, NULL); 163 } 164 165 166 /* Initialize the key for the global variable. */ 167 static void 168 init (void) 169 { 170 // XXX Screw you, gcc4, the unused function attribute does not work. 171 __asm ("" :: "r" (free_key_mem)); 172 173 if (key_create (&key, free_key_mem) == 0) 174 /* Creating the key succeeded. */ 175 threaded = true; 176 } 177 #endif /* TLS */ 178