1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.16 */ 28 29 30 #pragma weak elf_errmsg = _elf_errmsg 31 #pragma weak elf_errno = _elf_errno 32 33 #include "syn.h" 34 #include <thread.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <stdio.h> 38 #include <libelf.h> 39 #include "msg.h" 40 #include "decl.h" 41 42 #define ELFERRSHIFT 16 43 #define SYSERRMASK 0xffff 44 45 46 /* 47 * _elf_err has two values encoded in it, both the _elf_err # and 48 * the system errno value (if relevant). These values are encoded 49 * in the upper & lower 16 bits of the 4 byte integer. 50 */ 51 static int _elf_err = 0; 52 53 static mutex_t keylock; 54 static mutex_t buflock; 55 static thread_key_t errkey; 56 static thread_key_t bufkey; 57 static int keyonce = 0; 58 static int bufonce = 0; 59 NOTE(DATA_READABLE_WITHOUT_LOCK(keyonce)) 60 NOTE(DATA_READABLE_WITHOUT_LOCK(bufonce)) 61 62 63 extern char *_dgettext(const char *, const char *); 64 65 66 const char * 67 _libelf_msg(Msg mid) 68 { 69 return (_dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 70 } 71 72 73 void 74 _elf_seterr(Msg lib_err, int sys_err) 75 { 76 /*LINTED*/ 77 intptr_t encerr = ((int)lib_err << ELFERRSHIFT) | 78 (sys_err & SYSERRMASK); 79 80 #ifndef __lock_lint 81 if (thr_main()) { 82 _elf_err = (int)encerr; 83 return; 84 } 85 #endif 86 if (keyonce == 0) { 87 (void) mutex_lock(&keylock); 88 if (keyonce == 0) { 89 (void) thr_keycreate(&errkey, 0); 90 keyonce++; 91 } 92 (void) mutex_unlock(&keylock); 93 } 94 95 (void) thr_setspecific(errkey, (void *)encerr); 96 } 97 98 int 99 _elf_geterr() { 100 intptr_t rc; 101 102 #ifndef __lock_lint 103 if (thr_main()) 104 return (_elf_err); 105 #endif 106 if (keyonce == 0) 107 return (0); 108 109 (void) thr_getspecific(errkey, (void **)(&rc)); 110 return ((int)rc); 111 } 112 113 const char * 114 elf_errmsg(int err) 115 { 116 char *errno_str; 117 char *elferr_str; 118 char *buffer = 0; 119 int syserr; 120 int elferr; 121 static char intbuf[MAXELFERR]; 122 123 if (err == 0) { 124 if ((err = _elf_geterr()) == 0) 125 return (0); 126 } else if (err == -1) { 127 if ((err = _elf_geterr()) == 0) 128 /*LINTED*/ /* MSG_INTL(EINF_NULLERROR) */ 129 err = (int)EINF_NULLERROR << ELFERRSHIFT; 130 } 131 132 if (thr_main()) 133 buffer = intbuf; 134 else { 135 /* 136 * If this is a threaded APP then we store the 137 * errmsg buffer in Thread Specific Storage. 138 * 139 * Each thread has its own private buffer. 140 */ 141 if (bufonce == 0) { 142 (void) mutex_lock(&buflock); 143 if (bufonce == 0) { 144 if (thr_keycreate(&bufkey, free) != 0) { 145 (void) mutex_unlock(&buflock); 146 return (MSG_INTL(EBUG_THRDKEY)); 147 } 148 bufonce++; 149 } 150 (void) mutex_unlock(&buflock); 151 } 152 153 (void) thr_getspecific(bufkey, (void **)&buffer); 154 155 if (!buffer) { 156 if ((buffer = malloc(MAXELFERR)) == 0) 157 return (MSG_INTL(EMEM_ERRMSG)); 158 if (thr_setspecific(bufkey, buffer) != 0) { 159 free(buffer); 160 return (MSG_INTL(EBUG_THRDSET)); 161 } 162 } 163 } 164 165 elferr = (int)((uint_t)err >> ELFERRSHIFT); 166 syserr = err & SYSERRMASK; 167 /*LINTED*/ 168 elferr_str = (char *)MSG_INTL(elferr); 169 if (syserr && (errno_str = strerror(syserr))) 170 (void) snprintf(buffer, MAXELFERR, 171 MSG_ORIG(MSG_FMT_ERR), elferr_str, errno_str); 172 else { 173 (void) strncpy(buffer, elferr_str, MAXELFERR - 1); 174 buffer[MAXELFERR - 1] = '\0'; 175 } 176 177 return (buffer); 178 } 179 180 int 181 elf_errno() 182 { 183 int rc = _elf_geterr(); 184 185 _elf_seterr(0, 0); 186 return (rc); 187 } 188