]> sourceware.org Git - glibc.git/blame - dlfcn/dlerror.c
(__libc_dlsym_private, __libc_register_dl_open_hook): New functions. (__libc_dlopen_m...
[glibc.git] / dlfcn / dlerror.c
CommitLineData
c84142e8 1/* Return error detail for failing <dlfcn.h> functions.
154d10bd 2 Copyright (C) 1995-2000,2002,2003,2004 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
d66e34cd 9
afd4eb37
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
d66e34cd 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
d66e34cd 19
d66e34cd 20#include <dlfcn.h>
04470dc0 21#include <libintl.h>
d66e34cd 22#include <stdio.h>
d66e34cd 23#include <stdlib.h>
a853022c 24#include <string.h>
8d9618b7 25#include <bits/libc-lock.h>
154d10bd 26#include <ldsodefs.h>
8d9618b7
UD
27
28/* Type for storing results of dynamic loading actions. */
29struct dl_action_result
30 {
31 int errcode;
4f2793d4 32 int returned;
04470dc0
UD
33 const char *objname;
34 const char *errstring;
8d9618b7
UD
35 };
36static struct dl_action_result last_result;
37static struct dl_action_result *static_buf;
38
8d9618b7
UD
39/* This is the key for the thread specific memory. */
40static __libc_key_t key;
d347a4ab 41__libc_once_define (static, once);
8d9618b7
UD
42
43/* Destructor for the thread-specific data. */
44static void init (void);
45static void free_key_mem (void *mem);
d66e34cd 46
d66e34cd
RM
47
48char *
49dlerror (void)
50{
fb0dd050 51 char *buf = NULL;
8d9618b7 52 struct dl_action_result *result;
d66e34cd 53
d347a4ab
UD
54 /* If we have not yet initialized the buffer do it now. */
55 __libc_once (once, init);
56
8d9618b7 57 /* Get error string. */
af3878df
UD
58 result = (struct dl_action_result *) __libc_getspecific (key);
59 if (result == NULL)
8d9618b7
UD
60 result = &last_result;
61
4f2793d4
UD
62 /* Test whether we already returned the string. */
63 if (result->returned != 0)
64 {
65 /* We can now free the string. */
66 if (result->errstring != NULL)
67 {
ca3c0135
UD
68 if (strcmp (result->errstring, "out of memory") != 0)
69 free ((char *) result->errstring);
4f2793d4
UD
70 result->errstring = NULL;
71 }
4f2793d4 72 }
fb0dd050 73 else if (result->errstring != NULL)
8d9618b7 74 {
04470dc0 75 buf = (char *) result->errstring;
4a8ff87c
RM
76 int n;
77 if (result->errcode == 0)
78 n = __asprintf (&buf, "%s%s%s",
79 result->objname,
80 result->objname[0] == '\0' ? "" : ": ",
81 _(result->errstring));
82 else
83 n = __asprintf (&buf, "%s%s%s: %s",
84 result->objname,
85 result->objname[0] == '\0' ? "" : ": ",
86 _(result->errstring),
87 strerror (result->errcode));
88 if (n != -1)
4f2793d4
UD
89 {
90 /* We don't need the error string anymore. */
ca3c0135
UD
91 if (strcmp (result->errstring, "out of memory") != 0)
92 free ((char *) result->errstring);
4f2793d4
UD
93 result->errstring = buf;
94 }
8d9618b7 95
4f2793d4
UD
96 /* Mark the error as returned. */
97 result->returned = 1;
8d9618b7 98 }
421f82e5 99
8d9618b7 100 return buf;
d66e34cd
RM
101}
102
103int
d0fc4041 104internal_function
993b3242 105_dlerror_run (void (*operate) (void *), void *args)
d66e34cd 106{
8d9618b7
UD
107 struct dl_action_result *result;
108
109 /* If we have not yet initialized the buffer do it now. */
110 __libc_once (once, init);
111
112 /* Get error string and number. */
113 if (static_buf != NULL)
114 result = static_buf;
115 else
116 {
117 /* We don't use the static buffer and so we have a key. Use it
118 to get the thread-specific buffer. */
119 result = __libc_getspecific (key);
120 if (result == NULL)
121 {
122 result = (struct dl_action_result *) calloc (1, sizeof (*result));
123 if (result == NULL)
124 /* We are out of memory. Since this is no really critical
125 situation we carry on by using the global variable.
126 This might lead to conflicts between the threads but
127 they soon all will have memory problems. */
128 result = &last_result;
129 else
130 /* Set the tsd. */
131 __libc_setspecific (key, result);
132 }
133 }
134
135 if (result->errstring != NULL)
d743ba1e
UD
136 {
137 /* Free the error string from the last failed command. This can
138 happen if `dlerror' was not run after an error was found. */
ca3c0135
UD
139 if (strcmp (result->errstring, "out of memory") != 0)
140 free ((char *) result->errstring);
d743ba1e
UD
141 result->errstring = NULL;
142 }
8d9618b7 143
154d10bd
UD
144 result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring,
145 operate, args);
8d9618b7 146
4f2793d4
UD
147 /* If no error we mark that no error string is available. */
148 result->returned = result->errstring == NULL;
149
8d9618b7
UD
150 return result->errstring != NULL;
151}
152
dcf0671d 153
8d9618b7
UD
154/* Initialize buffers for results. */
155static void
156init (void)
157{
158 if (__libc_key_create (&key, free_key_mem))
159 /* Creating the key failed. This means something really went
160 wrong. In any case use a static buffer which is better than
161 nothing. */
162 static_buf = &last_result;
163}
164
0bf5c050
RM
165static void
166__attribute__ ((destructor))
167fini (void)
168{
169 if (last_result.errstring != NULL
170 && strcmp (last_result.errstring, "out of memory") != 0)
171 free ((char *) last_result.errstring);
172}
173
8d9618b7
UD
174
175/* Free the thread specific data, this is done if a thread terminates. */
176static void
177free_key_mem (void *mem)
178{
ca3c0135
UD
179 struct dl_action_result *result = (struct dl_action_result *) mem;
180
181 if (result->errstring != NULL
182 && strcmp (result->errstring, "out of memory") != 0)
ea1efc6f 183 free ((char *) result->errstring);
ca3c0135 184
8d9618b7
UD
185 free (mem);
186 __libc_setspecific (key, NULL);
d66e34cd 187}
This page took 0.240156 seconds and 5 git commands to generate.