]> sourceware.org Git - glibc.git/blame - dlfcn/dlerror.c
math: Update alpha ulps
[glibc.git] / dlfcn / dlerror.c
CommitLineData
c84142e8 1/* Return error detail for failing <dlfcn.h> functions.
dff8da6b 2 Copyright (C) 1995-2024 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 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
d66e34cd 18
d66e34cd 19#include <dlfcn.h>
04470dc0 20#include <libintl.h>
74780cf6 21#include <stdbool.h>
d66e34cd 22#include <stdio.h>
d66e34cd 23#include <stdlib.h>
a853022c 24#include <string.h>
ec999b8e 25#include <libc-lock.h>
154d10bd 26#include <ldsodefs.h>
2827ab99 27#include <libc-symbols.h>
fada9018
FW
28#include <assert.h>
29#include <dlerror.h>
8d9618b7 30
d66e34cd 31char *
5f21997b 32__dlerror (void)
d66e34cd 33{
5f21997b 34# ifdef SHARED
8dcb6d0a 35 if (GLRO (dl_dlfcn_hook) != NULL)
466c1ea1 36 return GLRO (dl_dlfcn_hook)->dlerror ();
5f21997b
UD
37# endif
38
fada9018 39 struct dl_action_result *result = __libc_dlerror_result;
d347a4ab 40
fada9018
FW
41 /* No libdl function has been called. No error is possible. */
42 if (result == NULL)
43 return NULL;
44
45 /* For an early malloc failure, clear the error flag and return the
46 error message. This marks the error as delivered. */
47 if (result == dl_action_result_malloc_failed)
11b451c8 48 {
fada9018
FW
49 __libc_dlerror_result = NULL;
50 return (char *) "out of memory";
11b451c8 51 }
8d9618b7 52
fada9018
FW
53 /* Placeholder object. This can be observed in a recursive call,
54 e.g. from an ELF constructor. */
55 if (result->errstring == NULL)
56 return NULL;
57
58 /* If we have already reported the error, we can free the result and
59 return NULL. See __libc_dlerror_result_free. */
60 if (result->returned)
4f2793d4 61 {
fada9018
FW
62 __libc_dlerror_result = NULL;
63 dl_action_result_errstring_free (result);
64 free (result);
65 return NULL;
4f2793d4 66 }
8d9618b7 67
fada9018
FW
68 assert (result->errstring != NULL);
69
70 /* Create the combined error message. */
71 char *buf;
72 int n;
73 if (result->errcode == 0)
74 n = __asprintf (&buf, "%s%s%s",
75 result->objname,
76 result->objname[0] == '\0' ? "" : ": ",
77 _(result->errstring));
78 else
a23c28ec
FW
79 {
80 __set_errno (result->errcode);
81 n = __asprintf (&buf, "%s%s%s: %m",
82 result->objname,
83 result->objname[0] == '\0' ? "" : ": ",
84 _(result->errstring));
85 /* Set errno again in case asprintf clobbered it. */
86 __set_errno (result->errcode);
87 }
421f82e5 88
fada9018
FW
89 /* Mark the error as delivered. */
90 result->returned = true;
91
92 if (n >= 0)
93 {
94 /* Replace the error string with the newly allocated one. */
95 dl_action_result_errstring_free (result);
96 result->errstring = buf;
97 result->errstring_source = dl_action_result_errstring_local;
98 return buf;
99 }
100 else
101 /* We could not create the combined error message, so use the
102 existing string as a fallback. */
103 return result->errstring;
d66e34cd 104}
a23c28ec
FW
105versioned_symbol (libc, __dlerror, dlerror, GLIBC_2_34);
106
107#if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_0, GLIBC_2_34)
108compat_symbol (libdl, __dlerror, dlerror, GLIBC_2_0);
109#endif
d66e34cd
RM
110
111int
993b3242 112_dlerror_run (void (*operate) (void *), void *args)
d66e34cd 113{
fada9018
FW
114 struct dl_action_result *result = __libc_dlerror_result;
115 if (result != NULL)
8d9618b7 116 {
fada9018 117 if (result == dl_action_result_malloc_failed)
8d9618b7 118 {
fada9018
FW
119 /* Clear the previous error. */
120 __libc_dlerror_result = NULL;
121 result = NULL;
122 }
123 else
124 {
125 /* There is an existing object. Free its error string, but
126 keep the object. */
127 dl_action_result_errstring_free (result);
128 /* Mark the object as not containing an error. This ensures
129 that call to dlerror from, for example, an ELF
130 constructor will not notice this result object. */
131 result->errstring = NULL;
8d9618b7
UD
132 }
133 }
134
fada9018
FW
135 const char *objname;
136 const char *errstring;
137 bool malloced;
138 int errcode = GLRO (dl_catch_error) (&objname, &errstring, &malloced,
139 operate, args);
4f2793d4 140
fada9018
FW
141 /* ELF constructors or destructors may have indirectly altered the
142 value of __libc_dlerror_result, therefore reload it. */
143 result = __libc_dlerror_result;
8d9618b7 144
fada9018 145 if (errstring == NULL)
bfeabc79 146 {
fada9018
FW
147 /* There is no error. We no longer need the result object if it
148 does not contain an error. However, a recursive call may
149 have added an error even if this call did not cause it. Keep
150 the other error. */
151 if (result != NULL && result->errstring == NULL)
bcdaad21 152 {
fada9018
FW
153 __libc_dlerror_result = NULL;
154 free (result);
bcdaad21 155 }
fada9018 156 return 0;
bfeabc79 157 }
fada9018
FW
158 else
159 {
160 /* A new error occurred. Check if a result object has to be
161 allocated. */
162 if (result == NULL || result == dl_action_result_malloc_failed)
163 {
164 /* Allocating storage for the error message after the fact
165 is not ideal. But this avoids an infinite recursion in
166 case malloc itself calls libdl functions (without
167 triggering errors). */
168 result = malloc (sizeof (*result));
169 if (result == NULL)
170 {
171 /* Assume that the dlfcn failure was due to a malloc
172 failure, too. */
173 if (malloced)
174 dl_error_free ((char *) errstring);
175 __libc_dlerror_result = dl_action_result_malloc_failed;
176 return 1;
177 }
178 __libc_dlerror_result = result;
179 }
180 else
181 /* Deallocate the existing error message from a recursive
182 call, but reuse the result object. */
183 dl_action_result_errstring_free (result);
184
185 result->errcode = errcode;
186 result->objname = objname;
187 result->errstring = (char *) errstring;
188 result->returned = false;
189 /* In case of an error, the malloced flag indicates whether the
190 error string is constant or not. */
191 if (malloced)
192 result->errstring_source = dl_action_result_errstring_rtld;
193 else
194 result->errstring_source = dl_action_result_errstring_constant;
ca3c0135 195
fada9018
FW
196 return 1;
197 }
d66e34cd 198}
This page took 0.572515 seconds and 6 git commands to generate.