]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-minimal.c
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / elf / dl-minimal.c
CommitLineData
42d2676e 1/* Minimal replacements for basic facilities used in the dynamic linker.
a334319f 2 Copyright (C) 1995-1998,2000-2002,2004 Free Software Foundation, Inc.
afd4eb37
UD
3 This file is part of the GNU C Library.
4
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.
afd4eb37
UD
9
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.
afd4eb37 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. */
42d2676e 19
a853022c 20#include <errno.h>
27a5bb33 21#include <limits.h>
a853022c 22#include <string.h>
739d440d 23#include <tls.h>
a853022c 24#include <unistd.h>
42d2676e 25#include <sys/mman.h>
aed283dd
UD
26#include <sys/param.h>
27#include <sys/types.h>
a42195db 28#include <ldsodefs.h>
ca34d7a7 29#include <stdio-common/_itoa.h>
a853022c
UD
30
31#include <assert.h>
42d2676e
RM
32
33/* Minimal `malloc' allocator for use while loading shared libraries.
ea7eb7e3 34 No block is ever freed. */
42d2676e
RM
35
36static void *alloc_ptr, *alloc_end, *alloc_last_block;
37
728c24ff
AJ
38/* Declarations of global functions. */
39extern void weak_function free (void *ptr);
40extern void * weak_function realloc (void *ptr, size_t n);
36461455
UD
41extern unsigned long int weak_function __strtoul_internal (const char *nptr,
42 char **endptr,
43 int base,
44 int group);
728c24ff
AJ
45extern unsigned long int weak_function strtoul (const char *nptr,
46 char **endptr, int base);
47
48
a816b435 49/* Allocate an aligned memory block. */
af5b3bc3 50void * weak_function
a816b435 51__libc_memalign (size_t align, size_t n)
42d2676e 52{
2064087b
RM
53#ifdef MAP_ANON
54#define _dl_zerofd (-1)
55#else
42d2676e 56 extern int _dl_zerofd;
42d2676e 57
42d2676e
RM
58 if (_dl_zerofd == -1)
59 _dl_zerofd = _dl_sysdep_open_zero_fill ();
2064087b
RM
60#define MAP_ANON 0
61#endif
62
42d2676e
RM
63 if (alloc_end == 0)
64 {
65 /* Consume any unused space in the last page of our data segment. */
36461455 66 extern int _end attribute_hidden;
42d2676e 67 alloc_ptr = &_end;
d6b5d570 68 alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0)
afdca0f2
UD
69 + GLRO(dl_pagesize) - 1)
70 & ~(GLRO(dl_pagesize) - 1));
42d2676e
RM
71 }
72
73 /* Make sure the allocation pointer is ideally aligned. */
a816b435
RM
74 alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + align - 1)
75 & ~(align - 1));
42d2676e 76
a334319f 77 if (alloc_ptr + n >= alloc_end)
42d2676e
RM
78 {
79 /* Insufficient space left; allocate another page. */
80 caddr_t page;
afdca0f2 81 size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
ea7eb7e3 82 page = __mmap (0, nup, PROT_READ|PROT_WRITE,
266180eb 83 MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
a334319f 84 assert (page != MAP_FAILED);
42d2676e
RM
85 if (page != alloc_end)
86 alloc_ptr = page;
ea7eb7e3 87 alloc_end = page + nup;
42d2676e
RM
88 }
89
90 alloc_last_block = (void *) alloc_ptr;
91 alloc_ptr += n;
92 return alloc_last_block;
93}
42d2676e 94
a816b435
RM
95void * weak_function
96malloc (size_t n)
97{
98 return __libc_memalign (sizeof (double), n);
99}
100
c131718c
UD
101/* We use this function occasionally since the real implementation may
102 be optimized when it can assume the memory it returns already is
103 set to NUL. */
104void * weak_function
105calloc (size_t nmemb, size_t size)
106{
fde89ad0
RM
107 /* New memory from the trivial malloc above is always already cleared.
108 (We make sure that's true in the rare occasion it might not be,
109 by clearing memory in free, below.) */
a334319f 110 return malloc (nmemb * size);
c131718c
UD
111}
112
42d2676e 113/* This will rarely be called. */
af5b3bc3 114void weak_function
42d2676e
RM
115free (void *ptr)
116{
117 /* We can free only the last block allocated. */
118 if (ptr == alloc_last_block)
fde89ad0
RM
119 {
120 /* Since this is rare, we clear the freed block here
121 so that calloc can presume malloc returns cleared memory. */
122 memset (alloc_last_block, '\0', alloc_ptr - alloc_last_block);
123 alloc_ptr = alloc_last_block;
124 }
42d2676e 125}
42d2676e 126
efec1d0c 127/* This is only called with the most recent block returned by malloc. */
af5b3bc3 128void * weak_function
42d2676e 129realloc (void *ptr, size_t n)
efec1d0c 130{
a334319f 131 void *new;
d252c479
UD
132 if (ptr == NULL)
133 return malloc (n);
efec1d0c
RM
134 assert (ptr == alloc_last_block);
135 alloc_ptr = alloc_last_block;
a334319f
UD
136 new = malloc (n);
137 assert (new == ptr);
138 return new;
efec1d0c 139}
42d2676e
RM
140\f
141/* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */
142
143#include <setjmp.h>
144
af5b3bc3 145int weak_function
1e71bd52 146__sigjmp_save (sigjmp_buf env, int savemask __attribute__ ((unused)))
ca34d7a7 147{
1e71bd52 148 env[0].__mask_was_saved = 0;
ca34d7a7
UD
149 return 0;
150}
a334319f
UD
151
152void weak_function
153longjmp (jmp_buf env, int val)
154{
155 __longjmp (env[0].__jmpbuf, val);
156}
42d2676e 157\f
da832465
UD
158/* Define our own version of the internal function used by strerror. We
159 only provide the messages for some common errors. This avoids pulling
160 in the whole error list. */
42d2676e 161
af5b3bc3 162char * weak_function
310b3460 163__strerror_r (int errnum, char *buf, size_t buflen)
42d2676e 164{
da832465
UD
165 char *msg;
166
167 switch (errnum)
168 {
169 case ENOMEM:
170 msg = (char *) "Cannot allocate memory";
171 break;
172 case EINVAL:
173 msg = (char *) "Invalid argument";
174 break;
175 case ENOENT:
176 msg = (char *) "No such file or directory";
177 break;
178 case EPERM:
179 msg = (char *) "Operation not permitted";
180 break;
181 case EIO:
182 msg = (char *) "Input/output error";
183 break;
184 case EACCES:
185 msg = (char *) "Permission denied";
186 break;
187 default:
188 /* No need to check buffer size, all calls in the dynamic linker
189 provide enough space. */
190 buf[buflen - 1] = '\0';
9710f75d 191 msg = _itoa (errnum, buf + buflen - 1, 10, 0);
da832465
UD
192 msg = memcpy (msg - (sizeof ("Error ") - 1), "Error ",
193 sizeof ("Error ") - 1);
194 break;
195 }
196
197 return msg;
42d2676e 198}
42d2676e
RM
199\f
200#ifndef NDEBUG
201
202/* Define (weakly) our own assert failure function which doesn't use stdio.
203 If we are linked into the user program (-ldl), the normal __assert_fail
204 defn can override this one. */
205
af5b3bc3 206void weak_function
42d2676e
RM
207__assert_fail (const char *assertion,
208 const char *file, unsigned int line, const char *function)
209{
35fc382a 210 _dl_fatal_printf ("\
28966366 211Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
35fc382a
UD
212 file, line, function ?: "", function ? ": " : "",
213 assertion);
42d2676e
RM
214
215}
37ba7d66 216rtld_hidden_weak(__assert_fail)
42d2676e 217
7a9ce79a
RM
218void weak_function
219__assert_perror_fail (int errnum,
220 const char *file, unsigned int line,
221 const char *function)
222{
223 char errbuf[400];
224 _dl_fatal_printf ("\
225Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n",
226 file, line, function ?: "", function ? ": " : "",
227 __strerror_r (errnum, errbuf, sizeof errbuf));
228
229}
230rtld_hidden_weak (__assert_perror_fail)
42d2676e 231#endif
27a5bb33 232
310b3460 233unsigned long int weak_function
27a5bb33
UD
234__strtoul_internal (const char *nptr, char **endptr, int base, int group)
235{
310b3460 236 unsigned long int result = 0;
27a5bb33
UD
237 long int sign = 1;
238
239 while (*nptr == ' ' || *nptr == '\t')
240 ++nptr;
241
242 if (*nptr == '-')
243 {
244 sign = -1;
245 ++nptr;
246 }
247 else if (*nptr == '+')
248 ++nptr;
249
250 if (*nptr < '0' || *nptr > '9')
251 {
252 if (endptr != NULL)
253 *endptr = (char *) nptr;
254 return 0UL;
255 }
256
257 assert (base == 0);
5aa8ff62 258 base = 10;
27a5bb33
UD
259 if (*nptr == '0')
260 {
261 if (nptr[1] == 'x' || nptr[1] == 'X')
262 {
263 base = 16;
264 nptr += 2;
265 }
266 else
267 base = 8;
268 }
27a5bb33
UD
269
270 while (*nptr >= '0' && *nptr <= '9')
271 {
310b3460 272 unsigned long int digval = *nptr - '0';
a334319f 273 if (result > LONG_MAX / 10
27a5bb33
UD
274 || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
275 {
276 errno = ERANGE;
a986484f
UD
277 if (endptr != NULL)
278 *endptr = (char *) nptr;
27a5bb33
UD
279 return ULONG_MAX;
280 }
5aa8ff62 281 result *= base;
27a5bb33 282 result += digval;
5aa8ff62 283 ++nptr;
27a5bb33
UD
284 }
285
a986484f
UD
286 if (endptr != NULL)
287 *endptr = (char *) nptr;
27a5bb33
UD
288 return result * sign;
289}
ccdf0cab
UD
290
291
9710f75d
UD
292/* We always use _itoa instead of _itoa_word in ld.so since the former
293 also has to be present and it is never about speed when these
294 functions are used. */
ccdf0cab
UD
295char *
296_itoa (value, buflim, base, upper_case)
297 unsigned long long int value;
298 char *buflim;
299 unsigned int base;
300 int upper_case;
301{
75bfdfc7 302 extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden;
ccdf0cab 303
9710f75d 304 assert (! upper_case);
ccdf0cab
UD
305
306 do
75bfdfc7 307 *--buflim = INTUSE(_itoa_lower_digits)[value % base];
9710f75d 308 while ((value /= base) != 0);
ccdf0cab 309
9710f75d 310 return buflim;
ccdf0cab 311}
5c1159b6
UD
312
313
314/* The following is not a complete strsep implementation. It cannot
315 handle empty delimiter strings. But this isn't necessary for the
316 execution of ld.so. */
317#undef strsep
318#undef __strsep
319char *
320__strsep (char **stringp, const char *delim)
321{
322 char *begin;
323
9710f75d
UD
324 assert (delim[0] != '\0');
325
5c1159b6
UD
326 begin = *stringp;
327 if (begin != NULL)
328 {
329 char *end = begin;
330
331 while (*end != '\0' || (end = NULL))
332 {
333 const char *dp = delim;
334
335 do
336 if (*dp == *end)
337 break;
338 while (*++dp != '\0');
339
340 if (*dp != '\0')
341 {
342 *end++ = '\0';
343 break;
344 }
345
346 ++end;
347 }
348
349 *stringp = end;
350 }
351
352 return begin;
353}
354weak_alias (__strsep, strsep)
355strong_alias (__strsep, __strsep_g)
37beecf7 356
b5cc329c
UD
357void
358__attribute__ ((noreturn))
359__chk_fail (void)
360{
361 _exit (127);
362}
363rtld_hidden_def (__chk_fail)
37beecf7
UD
364
365/* The '_itoa_lower_digits' variable in libc.so is able to handle bases
366 up to 36. We don't need this here. */
75bfdfc7
UD
367const char INTUSE(_itoa_lower_digits)[16] attribute_hidden
368 = "0123456789abcdef";