* sysdeps/unix/readdir.c: Make sure we don't modify errno when we reached EOF.
[glibc.git] / sysdeps / generic / dl-sysdep.c
blob1880084c6e1217ef8405046380fa377fadb66872
1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995,1996,1997,1998,2000,2001 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <assert.h>
21 #include <elf.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mman.h>
30 #include <ldsodefs.h>
31 #include <stdio-common/_itoa.h>
32 #include <fpu_control.h>
34 #include <entry.h>
35 #include <dl-machine.h>
36 #include <dl-procinfo.h>
37 #include <dl-osinfo.h>
38 #include <hp-timing.h>
40 extern int _dl_argc;
41 extern char **_dl_argv;
42 extern char **_environ;
43 extern size_t _dl_pagesize;
44 extern int _dl_clktck;
45 extern const char *_dl_platform;
46 extern unsigned long int _dl_hwcap;
47 extern size_t _dl_platformlen;
48 extern fpu_control_t _dl_fpu_control;
49 extern void _end;
51 /* Protect SUID program against misuse of file descriptors. */
52 extern void __libc_check_standard_fds (void);
54 #ifdef NEED_DL_BASE_ADDR
55 ElfW(Addr) _dl_base_addr;
56 #endif
57 int __libc_enable_secure;
58 int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion
59 of init-first. */
60 /* This variable contains the lowest stack address ever used. */
61 void *__libc_stack_end;
62 static ElfW(auxv_t) *_dl_auxv;
63 unsigned long int _dl_hwcap_mask = HWCAP_IMPORTANT;
64 #if HP_TIMING_AVAIL
65 hp_timing_t _dl_cpuclock_offset = 0;
66 #endif
68 #ifndef DL_FIND_ARG_COMPONENTS
69 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
70 do { \
71 void **_tmp; \
72 (argc) = *(long int *) cookie; \
73 (argv) = (char **) ((long int *) cookie + 1); \
74 (envp) = (argv) + (argc) + 1; \
75 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
76 continue; \
77 (auxp) = (void *) ++_tmp; \
78 } while (0)
79 #endif
82 ElfW(Addr)
83 _dl_sysdep_start (void **start_argptr,
84 void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
85 ElfW(Addr) *user_entry))
87 const ElfW(Phdr) *phdr = NULL;
88 ElfW(Word) phnum = 0;
89 ElfW(Addr) user_entry;
90 ElfW(auxv_t) *av;
91 uid_t uid = 0;
92 uid_t euid = 0;
93 gid_t gid = 0;
94 gid_t egid = 0;
95 #ifdef HAVE_AUX_XID
96 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
97 #else
98 unsigned int seen = 0;
99 # define M(type) (1 << (type))
100 # define set_seen(tag) seen |= M ((tag)->a_type)
101 #endif
103 #if HP_TIMING_AVAIL
104 HP_TIMING_NOW (_dl_cpuclock_offset);
105 #endif
107 DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
108 _dl_auxv);
110 user_entry = (ElfW(Addr)) ENTRY_POINT;
111 _dl_platform = NULL; /* Default to nothing known about the platform. */
113 for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++))
114 switch (av->a_type)
116 case AT_PHDR:
117 phdr = av->a_un.a_ptr;
118 break;
119 case AT_PHNUM:
120 phnum = av->a_un.a_val;
121 break;
122 case AT_PAGESZ:
123 _dl_pagesize = av->a_un.a_val;
124 break;
125 case AT_ENTRY:
126 user_entry = av->a_un.a_val;
127 break;
128 #ifdef NEED_DL_BASE_ADDR
129 case AT_BASE:
130 _dl_base_addr = av->a_un.a_val;
131 break;
132 #endif
133 case AT_UID:
134 uid = av->a_un.a_val;
135 break;
136 case AT_GID:
137 gid = av->a_un.a_val;
138 break;
139 case AT_EUID:
140 euid = av->a_un.a_val;
141 break;
142 case AT_EGID:
143 egid = av->a_un.a_val;
144 break;
145 case AT_PLATFORM:
146 _dl_platform = av->a_un.a_ptr;
147 break;
148 case AT_HWCAP:
149 _dl_hwcap = av->a_un.a_val;
150 break;
151 case AT_CLKTCK:
152 _dl_clktck = av->a_un.a_val;
153 break;
154 case AT_FPUCW:
155 _dl_fpu_control = av->a_un.a_val;
156 break;
159 #ifdef DL_SYSDEP_OSCHECK
160 DL_SYSDEP_OSCHECK (dl_fatal);
161 #endif
163 /* Linux doesn't provide us with any of these values on the stack
164 when the dynamic linker is run directly as a program. */
166 #ifndef HAVE_AUX_XID
167 # define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
168 SEE (UID, uid);
169 SEE (GID, gid);
170 SEE (EUID, euid);
171 SEE (EGID, egid);
172 #endif
174 __libc_enable_secure = uid != euid || gid != egid;
176 #ifndef HAVE_AUX_PAGESIZE
177 if (_dl_pagesize == 0)
178 _dl_pagesize = __getpagesize ();
179 #endif
181 #ifdef DL_SYSDEP_INIT
182 DL_SYSDEP_INIT;
183 #endif
185 #ifdef DL_PLATFORM_INIT
186 DL_PLATFORM_INIT;
187 #endif
189 /* Determine the length of the platform name. */
190 if (_dl_platform != NULL)
191 _dl_platformlen = strlen (_dl_platform);
193 if (__sbrk (0) == &_end)
194 /* The dynamic linker was run as a program, and so the initial break
195 starts just after our bss, at &_end. The malloc in dl-minimal.c
196 will consume the rest of this page, so tell the kernel to move the
197 break up that far. When the user program examines its break, it
198 will see this new value and not clobber our data. */
199 __sbrk (_dl_pagesize - ((&_end - (void *) 0) & (_dl_pagesize - 1)));
201 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
202 allocated. If necessary we are doing it ourself. If it is not
203 possible we stop the program. */
204 if (__builtin_expect (__libc_enable_secure, 0))
205 __libc_check_standard_fds ();
207 (*dl_main) (phdr, phnum, &user_entry);
208 return user_entry;
211 void
212 internal_function
213 _dl_sysdep_start_cleanup (void)
217 void
218 internal_function
219 _dl_show_auxv (void)
221 char buf[64];
222 ElfW(auxv_t) *av;
224 /* Terminate string. */
225 buf[63] = '\0';
227 /* The following code assumes that the AT_* values are encoded
228 starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
229 close by (otherwise the array will be too large). In case we have
230 to support a platform where these requirements are not fulfilled
231 some alternative implementation has to be used. */
232 for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
234 static const struct
236 const char label[20];
237 enum { dec, hex, str } form;
238 } auxvars[] =
240 [AT_EXECFD - 2] = { "AT_EXECFD: ", dec },
241 [AT_PHDR - 2] = { "AT_PHDR: 0x", hex },
242 [AT_PHENT - 2] = { "AT_PHENT: ", dec },
243 [AT_PHNUM - 2] = { "AT_PHNUM: ", dec },
244 [AT_PAGESZ - 2] = { "AT_PAGESZ: ", dec },
245 [AT_BASE - 2] = { "AT_BASE: 0x", hex },
246 [AT_FLAGS - 2] = { "AT_FLAGS: 0x", hex },
247 [AT_ENTRY - 2] = { "AT_ENTRY: 0x", hex },
248 [AT_NOTELF - 2] = { "AT_NOTELF: ", hex },
249 [AT_UID - 2] = { "AT_UID: ", dec },
250 [AT_EUID - 2] = { "AT_EUID: ", dec },
251 [AT_GID - 2] = { "AT_GID: ", dec },
252 [AT_EGID - 2] = { "AT_EGID: ", dec },
253 [AT_PLATFORM - 2] = { "AT_PLATFORM: ", str },
254 [AT_HWCAP - 2] = { "AT_HWCAP: ", hex },
255 [AT_CLKTCK - 2] = { "AT_CLKTCK: ", dec },
256 [AT_FPUCW - 2] = { "AT_FPUCW: ", hex },
257 [AT_DCACHEBSIZE - 2] = { "AT_DCACHEBSIZE: 0x", hex },
258 [AT_ICACHEBSIZE - 2] = { "AT_ICACHEBSIZE: 0x", hex },
259 [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex }
261 unsigned int idx = (unsigned int) (av->a_type - 2);
263 assert (AT_NULL == 0);
264 assert (AT_IGNORE == 1);
265 if (idx < sizeof (auxvars) / sizeof (auxvars[0]))
267 if (av->a_type != AT_HWCAP || _dl_procinfo (av->a_un.a_val) < 0)
269 const char *val = av->a_un.a_ptr;
271 if (__builtin_expect (auxvars[idx].form, dec) == dec)
272 val = _itoa_word (av->a_un.a_val, buf + sizeof buf - 1, 10, 0);
273 else if (__builtin_expect (auxvars[idx].form, hex) == hex)
274 val = _itoa_word (av->a_un.a_val, buf + sizeof buf - 1, 16, 0);
276 _dl_printf ("%s%s\n", auxvars[idx].label, val);
283 /* Return an array of useful/necessary hardware capability names. */
284 const struct r_strlenpair *
285 internal_function
286 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
287 size_t *max_capstrlen)
289 /* Determine how many important bits are set. */
290 unsigned long int masked = _dl_hwcap & _dl_hwcap_mask;
291 size_t cnt = platform != NULL;
292 size_t n, m;
293 size_t total;
294 struct r_strlenpair *temp;
295 struct r_strlenpair *result;
296 struct r_strlenpair *rp;
297 char *cp;
299 /* Count the number of bits set in the masked value. */
300 for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
301 if ((masked & (1UL << n)) != 0)
302 ++cnt;
304 if (cnt == 0)
306 /* If we have platform name and no important capability we only have
307 the base directory to search. */
308 result = (struct r_strlenpair *) malloc (sizeof (*result));
309 if (result == NULL)
311 no_memory:
312 _dl_signal_error (ENOMEM, NULL, "cannot create capability list");
315 result[0].str = (char *) result; /* Does not really matter. */
316 result[0].len = 0;
318 *sz = 1;
319 return result;
322 /* Create temporary data structure to generate result table. */
323 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
324 m = 0;
325 for (n = 0; masked != 0; ++n)
326 if ((masked & (1UL << n)) != 0)
328 temp[m].str = _dl_hwcap_string (n);
329 temp[m].len = strlen (temp[m].str);
330 masked ^= 1UL << n;
331 ++m;
333 if (platform != NULL)
335 temp[m].str = platform;
336 temp[m].len = platform_len;
337 ++m;
340 /* Determine the total size of all strings together. */
341 if (cnt == 1)
342 total = temp[0].len;
343 else
345 total = (1 << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
346 for (n = 1; n + 1 < cnt; ++n)
347 total += (1 << (cnt - 3)) * (temp[n].len + 1);
350 /* The result structure: we use a very compressed way to store the
351 various combinations of capability names. */
352 *sz = 1 << cnt;
353 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
354 if (result == NULL)
355 goto no_memory;
357 if (cnt == 1)
359 result[0].str = (char *) (result + *sz);
360 result[0].len = temp[0].len + 1;
361 result[1].str = (char *) (result + *sz);
362 result[1].len = 0;
363 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
364 *cp = '/';
365 *sz = 2;
366 *max_capstrlen = result[0].len;
368 return result;
371 /* Fill in the information. This follows the following scheme
372 (indeces from TEMP for four strings):
373 entry #0: 0, 1, 2, 3 binary: 1111
374 #1: 0, 1, 3 1101
375 #2: 0, 2, 3 1011
376 #3: 0, 3 1001
377 This allows the representation of all possible combinations of
378 capability names in the string. First generate the strings. */
379 result[1].str = result[0].str = cp = (char *) (result + *sz);
380 #define add(idx) \
381 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
382 if (cnt == 2)
384 add (1);
385 add (0);
387 else
389 n = 1 << cnt;
392 n -= 2;
394 /* We always add the last string. */
395 add (cnt - 1);
397 /* Add the strings which have the bit set in N. */
398 for (m = cnt - 2; m > 0; --m)
399 if ((n & (1 << m)) != 0)
400 add (m);
402 /* Always add the first string. */
403 add (0);
405 while (n != 0);
407 #undef add
409 /* Now we are ready to install the string pointers and length. */
410 for (n = 0; n < (1UL << cnt); ++n)
411 result[n].len = 0;
412 n = cnt;
415 size_t mask = 1 << --n;
417 rp = result;
418 for (m = 1 << cnt; m > 0; ++rp)
419 if ((--m & mask) != 0)
420 rp->len += temp[n].len + 1;
422 while (n != 0);
424 /* The first half of the strings all include the first string. */
425 n = (1 << cnt) - 2;
426 rp = &result[2];
427 while (n != (1UL << (cnt - 1)))
429 if ((n & 1) != 0)
430 rp[0].str = rp[-2].str + rp[-2].len;
431 else
432 rp[0].str = rp[-1].str;
433 ++rp;
434 --n;
437 /* The second have starts right after the first part of the string of
438 corresponding entry in the first half. */
441 rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
442 ++rp;
444 while (--n != 0);
446 /* The maximum string length. */
447 *max_capstrlen = result[0].len;
449 return result;