(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / generic / dl-sysdep.c
blob34498a880ca414ad3a2f63203b2a6a0d33e52426
1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995-1998, 2000-2003, 2004 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 <assert.h>
21 #include <elf.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <libintl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/mman.h>
31 #include <ldsodefs.h>
32 #include <stdio-common/_itoa.h>
33 #include <fpu_control.h>
35 #include <entry.h>
36 #include <dl-machine.h>
37 #include <dl-procinfo.h>
38 #include <dl-osinfo.h>
39 #include <hp-timing.h>
40 #include <tls.h>
42 extern char **_environ attribute_hidden;
43 extern void _end attribute_hidden;
45 /* Protect SUID program against misuse of file descriptors. */
46 extern void __libc_check_standard_fds (void);
48 #ifdef NEED_DL_BASE_ADDR
49 ElfW(Addr) _dl_base_addr;
50 #endif
51 int __libc_enable_secure attribute_relro = 0;
52 INTVARDEF(__libc_enable_secure)
53 int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion
54 of init-first. */
55 /* This variable contains the lowest stack address ever used. */
56 void *__libc_stack_end attribute_relro = NULL;
57 rtld_hidden_data_def(__libc_stack_end)
58 static ElfW(auxv_t) *_dl_auxv attribute_relro;
60 #ifndef DL_FIND_ARG_COMPONENTS
61 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
62 do { \
63 void **_tmp; \
64 (argc) = *(long int *) cookie; \
65 (argv) = (char **) ((long int *) cookie + 1); \
66 (envp) = (argv) + (argc) + 1; \
67 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
68 continue; \
69 (auxp) = (void *) ++_tmp; \
70 } while (0)
71 #endif
73 #ifndef DL_STACK_END
74 # define DL_STACK_END(cookie) ((void *) (cookie))
75 #endif
77 ElfW(Addr)
78 _dl_sysdep_start (void **start_argptr,
79 void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
80 ElfW(Addr) *user_entry))
82 const ElfW(Phdr) *phdr = NULL;
83 ElfW(Word) phnum = 0;
84 ElfW(Addr) user_entry;
85 ElfW(auxv_t) *av;
86 #ifdef HAVE_AUX_SECURE
87 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
88 # define set_seen_secure() ((void) 0)
89 #else
90 uid_t uid = 0;
91 gid_t gid = 0;
92 unsigned int seen = 0;
93 # define set_seen_secure() (seen = -1)
94 # ifdef HAVE_AUX_XID
95 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
96 # else
97 # define M(type) (1 << (type))
98 # define set_seen(tag) seen |= M ((tag)->a_type)
99 # endif
100 #endif
101 #ifdef NEED_DL_SYSINFO
102 uintptr_t new_sysinfo = 0;
103 #endif
105 __libc_stack_end = DL_STACK_END (start_argptr);
106 DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ,
107 _dl_auxv);
109 user_entry = (ElfW(Addr)) ENTRY_POINT;
110 GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */
112 for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++))
113 switch (av->a_type)
115 case AT_PHDR:
116 phdr = av->a_un.a_ptr;
117 break;
118 case AT_PHNUM:
119 phnum = av->a_un.a_val;
120 break;
121 case AT_PAGESZ:
122 GLRO(dl_pagesize) = av->a_un.a_val;
123 break;
124 case AT_ENTRY:
125 user_entry = av->a_un.a_val;
126 break;
127 #ifdef NEED_DL_BASE_ADDR
128 case AT_BASE:
129 _dl_base_addr = av->a_un.a_val;
130 break;
131 #endif
132 #ifndef HAVE_AUX_SECURE
133 case AT_UID:
134 case AT_EUID:
135 uid ^= av->a_un.a_val;
136 break;
137 case AT_GID:
138 case AT_EGID:
139 gid ^= av->a_un.a_val;
140 break;
141 #endif
142 case AT_SECURE:
143 #ifndef HAVE_AUX_SECURE
144 seen = -1;
145 #endif
146 INTUSE(__libc_enable_secure) = av->a_un.a_val;
147 break;
148 case AT_PLATFORM:
149 GLRO(dl_platform) = av->a_un.a_ptr;
150 break;
151 case AT_HWCAP:
152 GLRO(dl_hwcap) = av->a_un.a_val;
153 break;
154 case AT_CLKTCK:
155 GLRO(dl_clktck) = av->a_un.a_val;
156 break;
157 case AT_FPUCW:
158 GLRO(dl_fpu_control) = av->a_un.a_val;
159 break;
160 #ifdef NEED_DL_SYSINFO
161 case AT_SYSINFO:
162 new_sysinfo = av->a_un.a_val;
163 break;
164 #endif
165 #if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
166 case AT_SYSINFO_EHDR:
167 GLRO(dl_sysinfo_dso) = av->a_un.a_ptr;
168 break;
169 #endif
170 #ifdef DL_PLATFORM_AUXV
171 DL_PLATFORM_AUXV
172 #endif
175 #ifdef DL_SYSDEP_OSCHECK
176 DL_SYSDEP_OSCHECK (dl_fatal);
177 #endif
179 #ifndef HAVE_AUX_SECURE
180 if (seen != -1)
182 /* Fill in the values we have not gotten from the kernel through the
183 auxiliary vector. */
184 # ifndef HAVE_AUX_XID
185 # define SEE(UID, var, uid) \
186 if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
187 SEE (UID, uid, uid);
188 SEE (EUID, uid, euid);
189 SEE (GID, gid, gid);
190 SEE (EGID, gid, egid);
191 # endif
193 /* If one of the two pairs of IDs does not match this is a setuid
194 or setgid run. */
195 INTUSE(__libc_enable_secure) = uid | gid;
197 #endif
199 #ifndef HAVE_AUX_PAGESIZE
200 if (GLRO(dl_pagesize) == 0)
201 GLRO(dl_pagesize) = __getpagesize ();
202 #endif
204 #if defined NEED_DL_SYSINFO
205 /* Only set the sysinfo value if we also have the vsyscall DSO. */
206 if (GLRO(dl_sysinfo_dso) != 0 && new_sysinfo)
207 GLRO(dl_sysinfo) = new_sysinfo;
208 #endif
210 #ifdef DL_SYSDEP_INIT
211 DL_SYSDEP_INIT;
212 #endif
214 #ifdef DL_PLATFORM_INIT
215 DL_PLATFORM_INIT;
216 #endif
218 /* Determine the length of the platform name. */
219 if (GLRO(dl_platform) != NULL)
220 GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
222 if (__sbrk (0) == &_end)
223 /* The dynamic linker was run as a program, and so the initial break
224 starts just after our bss, at &_end. The malloc in dl-minimal.c
225 will consume the rest of this page, so tell the kernel to move the
226 break up that far. When the user program examines its break, it
227 will see this new value and not clobber our data. */
228 __sbrk (GLRO(dl_pagesize)
229 - ((&_end - (void *) 0) & (GLRO(dl_pagesize) - 1)));
231 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
232 allocated. If necessary we are doing it ourself. If it is not
233 possible we stop the program. */
234 if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
235 __libc_check_standard_fds ();
237 (*dl_main) (phdr, phnum, &user_entry);
238 return user_entry;
241 void
242 internal_function
243 _dl_sysdep_start_cleanup (void)
247 void
248 internal_function
249 _dl_show_auxv (void)
251 char buf[64];
252 ElfW(auxv_t) *av;
254 /* Terminate string. */
255 buf[63] = '\0';
257 /* The following code assumes that the AT_* values are encoded
258 starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
259 close by (otherwise the array will be too large). In case we have
260 to support a platform where these requirements are not fulfilled
261 some alternative implementation has to be used. */
262 for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
264 static const struct
266 const char label[20];
267 enum { unknown = 0, dec, hex, str, ignore } form;
268 } auxvars[] =
270 [AT_EXECFD - 2] = { "AT_EXECFD: ", dec },
271 [AT_PHDR - 2] = { "AT_PHDR: 0x", hex },
272 [AT_PHENT - 2] = { "AT_PHENT: ", dec },
273 [AT_PHNUM - 2] = { "AT_PHNUM: ", dec },
274 [AT_PAGESZ - 2] = { "AT_PAGESZ: ", dec },
275 [AT_BASE - 2] = { "AT_BASE: 0x", hex },
276 [AT_FLAGS - 2] = { "AT_FLAGS: 0x", hex },
277 [AT_ENTRY - 2] = { "AT_ENTRY: 0x", hex },
278 [AT_NOTELF - 2] = { "AT_NOTELF: ", hex },
279 [AT_UID - 2] = { "AT_UID: ", dec },
280 [AT_EUID - 2] = { "AT_EUID: ", dec },
281 [AT_GID - 2] = { "AT_GID: ", dec },
282 [AT_EGID - 2] = { "AT_EGID: ", dec },
283 [AT_PLATFORM - 2] = { "AT_PLATFORM: ", str },
284 [AT_HWCAP - 2] = { "AT_HWCAP: ", hex },
285 [AT_CLKTCK - 2] = { "AT_CLKTCK: ", dec },
286 [AT_FPUCW - 2] = { "AT_FPUCW: ", hex },
287 [AT_DCACHEBSIZE - 2] = { "AT_DCACHEBSIZE: 0x", hex },
288 [AT_ICACHEBSIZE - 2] = { "AT_ICACHEBSIZE: 0x", hex },
289 [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex },
290 [AT_IGNOREPPC - 2] = { "AT_IGNOREPPC", ignore },
291 [AT_SECURE - 2] = { "AT_SECURE: ", dec },
292 [AT_SYSINFO - 2] = { "AT_SYSINFO: 0x", hex },
293 [AT_SYSINFO_EHDR - 2] = { "AT_SYSINFO_EHDR: 0x", hex },
295 unsigned int idx = (unsigned int) (av->a_type - 2);
297 if ((unsigned int) av->a_type < 2u || auxvars[idx].form == ignore)
298 continue;
300 assert (AT_NULL == 0);
301 assert (AT_IGNORE == 1);
303 if (av->a_type == AT_HWCAP)
305 /* This is handled special. */
306 if (_dl_procinfo (av->a_un.a_val) == 0)
307 continue;
310 if (idx < sizeof (auxvars) / sizeof (auxvars[0])
311 && auxvars[idx].form != unknown)
313 const char *val = av->a_un.a_ptr;
315 if (__builtin_expect (auxvars[idx].form, dec) == dec)
316 val = _itoa ((unsigned long int) av->a_un.a_val,
317 buf + sizeof buf - 1, 10, 0);
318 else if (__builtin_expect (auxvars[idx].form, hex) == hex)
319 val = _itoa ((unsigned long int) av->a_un.a_val,
320 buf + sizeof buf - 1, 16, 0);
322 _dl_printf ("%s%s\n", auxvars[idx].label, val);
324 continue;
327 /* Unknown value: print a generic line. */
328 char buf2[17];
329 buf[sizeof (buf2) - 1] = '\0';
330 const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
331 buf2 + sizeof buf2 - 1, 16, 0);
332 const char *val = _itoa ((unsigned long int) av->a_type,
333 buf + sizeof buf - 1, 16, 0);
334 _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
339 /* Return an array of useful/necessary hardware capability names. */
340 const struct r_strlenpair *
341 internal_function
342 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
343 size_t *max_capstrlen)
345 /* Determine how many important bits are set. */
346 unsigned long int masked = GLRO(dl_hwcap) & GLRO(dl_hwcap_mask);
347 size_t cnt = platform != NULL;
348 size_t n, m;
349 size_t total;
350 struct r_strlenpair *temp;
351 struct r_strlenpair *result;
352 struct r_strlenpair *rp;
353 char *cp;
355 /* Count the number of bits set in the masked value. */
356 for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
357 if ((masked & (1UL << n)) != 0)
358 ++cnt;
360 #ifdef USE_TLS
361 /* For TLS enabled builds always add 'tls'. */
362 ++cnt;
363 #else
364 if (cnt == 0)
366 /* If we have platform name and no important capability we only have
367 the base directory to search. */
368 result = (struct r_strlenpair *) malloc (sizeof (*result));
369 if (result == NULL)
370 goto no_memory;
372 result[0].str = (char *) result; /* Does not really matter. */
373 result[0].len = 0;
375 *sz = 1;
376 return result;
378 #endif
380 /* Create temporary data structure to generate result table. */
381 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
382 m = 0;
383 for (n = 0; masked != 0; ++n)
384 if ((masked & (1UL << n)) != 0)
386 temp[m].str = _dl_hwcap_string (n);
387 temp[m].len = strlen (temp[m].str);
388 masked ^= 1UL << n;
389 ++m;
391 if (platform != NULL)
393 temp[m].str = platform;
394 temp[m].len = platform_len;
395 ++m;
397 #ifdef USE_TLS
398 temp[m].str = "tls";
399 temp[m].len = 3;
400 ++m;
401 #endif
402 assert (m == cnt);
404 /* Determine the total size of all strings together. */
405 if (cnt == 1)
406 total = temp[0].len + 1;
407 else
409 total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
410 for (n = 1; n + 1 < cnt; ++n)
411 total += (1UL << (cnt - 3)) * (temp[n].len + 1);
414 /* The result structure: we use a very compressed way to store the
415 various combinations of capability names. */
416 *sz = 1 << cnt;
417 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
418 if (result == NULL)
420 #ifndef USE_TLS
421 no_memory:
422 #endif
423 _dl_signal_error (ENOMEM, NULL, NULL,
424 N_("cannot create capability list"));
427 if (cnt == 1)
429 result[0].str = (char *) (result + *sz);
430 result[0].len = temp[0].len + 1;
431 result[1].str = (char *) (result + *sz);
432 result[1].len = 0;
433 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
434 *cp = '/';
435 *sz = 2;
436 *max_capstrlen = result[0].len;
438 return result;
441 /* Fill in the information. This follows the following scheme
442 (indeces from TEMP for four strings):
443 entry #0: 0, 1, 2, 3 binary: 1111
444 #1: 0, 1, 3 1101
445 #2: 0, 2, 3 1011
446 #3: 0, 3 1001
447 This allows the representation of all possible combinations of
448 capability names in the string. First generate the strings. */
449 result[1].str = result[0].str = cp = (char *) (result + *sz);
450 #define add(idx) \
451 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
452 if (cnt == 2)
454 add (1);
455 add (0);
457 else
459 n = 1 << (cnt - 1);
462 n -= 2;
464 /* We always add the last string. */
465 add (cnt - 1);
467 /* Add the strings which have the bit set in N. */
468 for (m = cnt - 2; m > 0; --m)
469 if ((n & (1 << m)) != 0)
470 add (m);
472 /* Always add the first string. */
473 add (0);
475 while (n != 0);
477 #undef add
479 /* Now we are ready to install the string pointers and length. */
480 for (n = 0; n < (1UL << cnt); ++n)
481 result[n].len = 0;
482 n = cnt;
485 size_t mask = 1 << --n;
487 rp = result;
488 for (m = 1 << cnt; m > 0; ++rp)
489 if ((--m & mask) != 0)
490 rp->len += temp[n].len + 1;
492 while (n != 0);
494 /* The first half of the strings all include the first string. */
495 n = (1 << cnt) - 2;
496 rp = &result[2];
497 while (n != (1UL << (cnt - 1)))
499 if ((--n & 1) != 0)
500 rp[0].str = rp[-2].str + rp[-2].len;
501 else
502 rp[0].str = rp[-1].str;
503 ++rp;
506 /* The second have starts right after the first part of the string of
507 corresponding entry in the first half. */
510 rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
511 ++rp;
513 while (--n != 0);
515 /* The maximum string length. */
516 *max_capstrlen = result[0].len;
518 return result;