Updated to fedora-glibc-20060328T0900
[glibc/history.git] / elf / dl-minimal.c
blob868d3bd2ede07f5ca52522195e2db78a8aa727f6
1 /* Minimal replacements for basic facilities used in the dynamic linker.
2 Copyright (C) 1995-1998,2000-2002,2004,2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
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. */
20 #include <errno.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <tls.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include <ldsodefs.h>
29 #include <stdio-common/_itoa.h>
31 #include <assert.h>
33 /* Minimal `malloc' allocator for use while loading shared libraries.
34 No block is ever freed. */
36 static void *alloc_ptr, *alloc_end, *alloc_last_block;
38 /* Declarations of global functions. */
39 extern void weak_function free (void *ptr);
40 extern void * weak_function realloc (void *ptr, size_t n);
41 extern unsigned long int weak_function __strtoul_internal (const char *nptr,
42 char **endptr,
43 int base,
44 int group);
45 extern unsigned long int weak_function strtoul (const char *nptr,
46 char **endptr, int base);
49 /* Allocate an aligned memory block. */
50 void * weak_function
51 __libc_memalign (size_t align, size_t n)
53 #ifdef MAP_ANON
54 #define _dl_zerofd (-1)
55 #else
56 extern int _dl_zerofd;
58 if (_dl_zerofd == -1)
59 _dl_zerofd = _dl_sysdep_open_zero_fill ();
60 #define MAP_ANON 0
61 #endif
63 if (alloc_end == 0)
65 /* Consume any unused space in the last page of our data segment. */
66 extern int _end attribute_hidden;
67 alloc_ptr = &_end;
68 alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0)
69 + GLRO(dl_pagesize) - 1)
70 & ~(GLRO(dl_pagesize) - 1));
73 /* Make sure the allocation pointer is ideally aligned. */
74 alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + align - 1)
75 & ~(align - 1));
77 if (alloc_ptr + n >= alloc_end)
79 /* Insufficient space left; allocate another page. */
80 caddr_t page;
81 size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
82 page = __mmap (0, nup, PROT_READ|PROT_WRITE,
83 MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
84 assert (page != MAP_FAILED);
85 if (page != alloc_end)
86 alloc_ptr = page;
87 alloc_end = page + nup;
90 alloc_last_block = (void *) alloc_ptr;
91 alloc_ptr += n;
92 return alloc_last_block;
95 void * weak_function
96 malloc (size_t n)
98 return __libc_memalign (sizeof (double), n);
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. */
104 void * weak_function
105 calloc (size_t nmemb, size_t size)
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.) */
110 return malloc (nmemb * size);
113 /* This will rarely be called. */
114 void weak_function
115 free (void *ptr)
117 /* We can free only the last block allocated. */
118 if (ptr == alloc_last_block)
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;
127 /* This is only called with the most recent block returned by malloc. */
128 void * weak_function
129 realloc (void *ptr, size_t n)
131 void *new;
132 if (ptr == NULL)
133 return malloc (n);
134 assert (ptr == alloc_last_block);
135 alloc_ptr = alloc_last_block;
136 new = malloc (n);
137 assert (new == ptr);
138 return new;
141 /* Avoid signal frobnication in setjmp/longjmp. Keeps things smaller. */
143 #include <setjmp.h>
145 int weak_function
146 __sigjmp_save (sigjmp_buf env, int savemask __attribute__ ((unused)))
148 env[0].__mask_was_saved = 0;
149 return 0;
152 /* Define our own version of the internal function used by strerror. We
153 only provide the messages for some common errors. This avoids pulling
154 in the whole error list. */
156 char * weak_function
157 __strerror_r (int errnum, char *buf, size_t buflen)
159 char *msg;
161 switch (errnum)
163 case ENOMEM:
164 msg = (char *) "Cannot allocate memory";
165 break;
166 case EINVAL:
167 msg = (char *) "Invalid argument";
168 break;
169 case ENOENT:
170 msg = (char *) "No such file or directory";
171 break;
172 case EPERM:
173 msg = (char *) "Operation not permitted";
174 break;
175 case EIO:
176 msg = (char *) "Input/output error";
177 break;
178 case EACCES:
179 msg = (char *) "Permission denied";
180 break;
181 default:
182 /* No need to check buffer size, all calls in the dynamic linker
183 provide enough space. */
184 buf[buflen - 1] = '\0';
185 msg = _itoa (errnum, buf + buflen - 1, 10, 0);
186 msg = memcpy (msg - (sizeof ("Error ") - 1), "Error ",
187 sizeof ("Error ") - 1);
188 break;
191 return msg;
194 #ifndef NDEBUG
196 /* Define (weakly) our own assert failure function which doesn't use stdio.
197 If we are linked into the user program (-ldl), the normal __assert_fail
198 defn can override this one. */
200 void weak_function
201 __assert_fail (const char *assertion,
202 const char *file, unsigned int line, const char *function)
204 _dl_fatal_printf ("\
205 Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
206 file, line, function ?: "", function ? ": " : "",
207 assertion);
210 rtld_hidden_weak(__assert_fail)
212 void weak_function
213 __assert_perror_fail (int errnum,
214 const char *file, unsigned int line,
215 const char *function)
217 char errbuf[400];
218 _dl_fatal_printf ("\
219 Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n",
220 file, line, function ?: "", function ? ": " : "",
221 __strerror_r (errnum, errbuf, sizeof errbuf));
224 rtld_hidden_weak (__assert_perror_fail)
225 #endif
227 unsigned long int weak_function
228 __strtoul_internal (const char *nptr, char **endptr, int base, int group)
230 unsigned long int result = 0;
231 long int sign = 1;
233 while (*nptr == ' ' || *nptr == '\t')
234 ++nptr;
236 if (*nptr == '-')
238 sign = -1;
239 ++nptr;
241 else if (*nptr == '+')
242 ++nptr;
244 if (*nptr < '0' || *nptr > '9')
246 if (endptr != NULL)
247 *endptr = (char *) nptr;
248 return 0UL;
251 assert (base == 0);
252 base = 10;
253 if (*nptr == '0')
255 if (nptr[1] == 'x' || nptr[1] == 'X')
257 base = 16;
258 nptr += 2;
260 else
261 base = 8;
264 while (*nptr >= '0' && *nptr <= '9')
266 unsigned long int digval = *nptr - '0';
267 if (result > LONG_MAX / 10
268 || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
270 errno = ERANGE;
271 if (endptr != NULL)
272 *endptr = (char *) nptr;
273 return ULONG_MAX;
275 result *= base;
276 result += digval;
277 ++nptr;
280 if (endptr != NULL)
281 *endptr = (char *) nptr;
282 return result * sign;
286 /* We always use _itoa instead of _itoa_word in ld.so since the former
287 also has to be present and it is never about speed when these
288 functions are used. */
289 char *
290 _itoa (value, buflim, base, upper_case)
291 unsigned long long int value;
292 char *buflim;
293 unsigned int base;
294 int upper_case;
296 extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden;
298 assert (! upper_case);
301 *--buflim = INTUSE(_itoa_lower_digits)[value % base];
302 while ((value /= base) != 0);
304 return buflim;
308 /* The following is not a complete strsep implementation. It cannot
309 handle empty delimiter strings. But this isn't necessary for the
310 execution of ld.so. */
311 #undef strsep
312 #undef __strsep
313 char *
314 __strsep (char **stringp, const char *delim)
316 char *begin;
318 assert (delim[0] != '\0');
320 begin = *stringp;
321 if (begin != NULL)
323 char *end = begin;
325 while (*end != '\0' || (end = NULL))
327 const char *dp = delim;
330 if (*dp == *end)
331 break;
332 while (*++dp != '\0');
334 if (*dp != '\0')
336 *end++ = '\0';
337 break;
340 ++end;
343 *stringp = end;
346 return begin;
348 weak_alias (__strsep, strsep)
349 strong_alias (__strsep, __strsep_g)
351 void
352 __attribute__ ((noreturn))
353 __chk_fail (void)
355 _exit (127);
357 rtld_hidden_def (__chk_fail)
359 /* The '_itoa_lower_digits' variable in libc.so is able to handle bases
360 up to 36. We don't need this here. */
361 const char INTUSE(_itoa_lower_digits)[16] attribute_hidden
362 = "0123456789abcdef";