1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995-1998, 2000-2002, 2003 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
28 #include <sys/types.h>
32 #include <stdio-common/_itoa.h>
33 #include <fpu_control.h>
36 #include <dl-machine.h>
37 #include <dl-procinfo.h>
38 #include <dl-osinfo.h>
39 #include <hp-timing.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;
51 int __libc_enable_secure = 0;
52 INTVARDEF(__libc_enable_secure)
53 int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion
55 /* This variable contains the lowest stack address ever used. */
56 void *__libc_stack_end;
57 static ElfW(auxv_t) *_dl_auxv;
59 #ifndef DL_FIND_ARG_COMPONENTS
60 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
63 (argc) = *(long int *) cookie; \
64 (argv) = (char **) ((long int *) cookie + 1); \
65 (envp) = (argv) + (argc) + 1; \
66 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
68 (auxp) = (void *) ++_tmp; \
74 _dl_sysdep_start (void **start_argptr,
75 void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
76 ElfW(Addr) *user_entry))
78 const ElfW(Phdr) *phdr = NULL;
80 ElfW(Addr) user_entry;
85 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
87 unsigned int seen = 0;
88 # define M(type) (1 << (type))
89 # define set_seen(tag) seen |= M ((tag)->a_type)
92 DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ,
95 user_entry = (ElfW(Addr)) ENTRY_POINT;
96 GL(dl_platform) = NULL; /* Default to nothing known about the platform. */
98 for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++))
102 phdr = av->a_un.a_ptr;
105 phnum = av->a_un.a_val;
108 GL(dl_pagesize) = av->a_un.a_val;
111 user_entry = av->a_un.a_val;
113 #ifdef NEED_DL_BASE_ADDR
115 _dl_base_addr = av->a_un.a_val;
120 uid ^= av->a_un.a_val;
124 gid ^= av->a_un.a_val;
127 GL(dl_platform) = av->a_un.a_ptr;
130 GL(dl_hwcap) = av->a_un.a_val;
133 GL(dl_clktck) = av->a_un.a_val;
136 GL(dl_fpu_control) = av->a_un.a_val;
138 #ifdef NEED_DL_SYSINFO
140 GL(dl_sysinfo) = av->a_un.a_val;
142 case AT_SYSINFO_EHDR:
143 GL(dl_sysinfo_dso) = av->a_un.a_ptr;
146 #ifdef DL_PLATFORM_AUXV
151 #ifdef DL_SYSDEP_OSCHECK
152 DL_SYSDEP_OSCHECK (dl_fatal);
155 /* Fill in the values we have not gotten from the kernel through the
158 # define SEE(UID, var, uid) \
159 if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
161 SEE (EUID, uid, euid);
163 SEE (EGID, gid, egid);
166 /* If one of the two pairs of IDs does not match this is a setuid
168 INTUSE(__libc_enable_secure) = uid | gid;
170 #ifndef HAVE_AUX_PAGESIZE
171 if (GL(dl_pagesize) == 0)
172 GL(dl_pagesize) = __getpagesize ();
175 #ifdef DL_SYSDEP_INIT
179 #ifdef DL_PLATFORM_INIT
183 /* Determine the length of the platform name. */
184 if (GL(dl_platform) != NULL)
185 GL(dl_platformlen) = strlen (GL(dl_platform));
187 if (__sbrk (0) == &_end)
188 /* The dynamic linker was run as a program, and so the initial break
189 starts just after our bss, at &_end. The malloc in dl-minimal.c
190 will consume the rest of this page, so tell the kernel to move the
191 break up that far. When the user program examines its break, it
192 will see this new value and not clobber our data. */
193 __sbrk (GL(dl_pagesize) - ((&_end - (void *) 0) & (GL(dl_pagesize) - 1)));
195 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
196 allocated. If necessary we are doing it ourself. If it is not
197 possible we stop the program. */
198 if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
199 __libc_check_standard_fds ();
201 (*dl_main) (phdr, phnum, &user_entry);
207 _dl_sysdep_start_cleanup (void)
218 /* Terminate string. */
221 /* The following code assumes that the AT_* values are encoded
222 starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
223 close by (otherwise the array will be too large). In case we have
224 to support a platform where these requirements are not fulfilled
225 some alternative implementation has to be used. */
226 for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
230 const char label[20];
231 enum { dec, hex, str } form;
234 [AT_EXECFD - 2] = { "AT_EXECFD: ", dec },
235 [AT_PHDR - 2] = { "AT_PHDR: 0x", hex },
236 [AT_PHENT - 2] = { "AT_PHENT: ", dec },
237 [AT_PHNUM - 2] = { "AT_PHNUM: ", dec },
238 [AT_PAGESZ - 2] = { "AT_PAGESZ: ", dec },
239 [AT_BASE - 2] = { "AT_BASE: 0x", hex },
240 [AT_FLAGS - 2] = { "AT_FLAGS: 0x", hex },
241 [AT_ENTRY - 2] = { "AT_ENTRY: 0x", hex },
242 [AT_NOTELF - 2] = { "AT_NOTELF: ", hex },
243 [AT_UID - 2] = { "AT_UID: ", dec },
244 [AT_EUID - 2] = { "AT_EUID: ", dec },
245 [AT_GID - 2] = { "AT_GID: ", dec },
246 [AT_EGID - 2] = { "AT_EGID: ", dec },
247 [AT_PLATFORM - 2] = { "AT_PLATFORM: ", str },
248 [AT_HWCAP - 2] = { "AT_HWCAP: ", hex },
249 [AT_CLKTCK - 2] = { "AT_CLKTCK: ", dec },
250 [AT_FPUCW - 2] = { "AT_FPUCW: ", hex },
251 [AT_DCACHEBSIZE - 2] = { "AT_DCACHEBSIZE: 0x", hex },
252 [AT_ICACHEBSIZE - 2] = { "AT_ICACHEBSIZE: 0x", hex },
253 [AT_UCACHEBSIZE - 2] = { "AT_UCACHEBSIZE: 0x", hex },
254 #ifdef NEED_DL_SYSINFO
255 [AT_SYSINFO - 2] = { "AT_SYSINFO: 0x", hex },
256 [AT_SYSINFO_EHDR - 2] = { "AT_SYSINFO_EHDR: 0x", hex }
259 unsigned int idx = (unsigned int) (av->a_type - 2);
261 assert (AT_NULL == 0);
262 assert (AT_IGNORE == 1);
264 if (av->a_type == AT_HWCAP)
266 /* This is handled special. */
267 if (_dl_procinfo (av->a_un.a_val) == 0)
271 if (idx < sizeof (auxvars) / sizeof (auxvars[0]))
273 const char *val = av->a_un.a_ptr;
275 if (__builtin_expect (auxvars[idx].form, dec) == dec)
276 val = _itoa ((unsigned long int) av->a_un.a_val,
277 buf + sizeof buf - 1, 10, 0);
278 else if (__builtin_expect (auxvars[idx].form, hex) == hex)
279 val = _itoa ((unsigned long int) av->a_un.a_val,
280 buf + sizeof buf - 1, 16, 0);
282 _dl_printf ("%s%s\n", auxvars[idx].label, val);
287 /* Unknown value: print a generic line. */
289 buf[sizeof (buf2) - 1] = '\0';
290 const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
291 buf2 + sizeof buf2 - 1, 16, 0);
292 const char *val = _itoa ((unsigned long int) av->a_type,
293 buf + sizeof buf - 1, 16, 0);
294 _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
299 /* Return an array of useful/necessary hardware capability names. */
300 const struct r_strlenpair *
302 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
303 size_t *max_capstrlen)
305 /* Determine how many important bits are set. */
306 unsigned long int masked = GL(dl_hwcap) & GL(dl_hwcap_mask);
307 size_t cnt = platform != NULL;
310 struct r_strlenpair *temp;
311 struct r_strlenpair *result;
312 struct r_strlenpair *rp;
315 /* Count the number of bits set in the masked value. */
316 for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
317 if ((masked & (1UL << n)) != 0)
321 /* For TLS enabled builds always add 'tls'. */
326 /* If we have platform name and no important capability we only have
327 the base directory to search. */
328 result = (struct r_strlenpair *) malloc (sizeof (*result));
332 result[0].str = (char *) result; /* Does not really matter. */
340 /* Create temporary data structure to generate result table. */
341 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
343 for (n = 0; masked != 0; ++n)
344 if ((masked & (1UL << n)) != 0)
346 temp[m].str = _dl_hwcap_string (n);
347 temp[m].len = strlen (temp[m].str);
351 if (platform != NULL)
353 temp[m].str = platform;
354 temp[m].len = platform_len;
364 /* Determine the total size of all strings together. */
366 total = temp[0].len + 1;
369 total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
370 for (n = 1; n + 1 < cnt; ++n)
371 total += (1UL << (cnt - 3)) * (temp[n].len + 1);
374 /* The result structure: we use a very compressed way to store the
375 various combinations of capability names. */
377 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
383 INTUSE(_dl_signal_error) (ENOMEM, NULL, NULL,
384 N_("cannot create capability list"));
389 result[0].str = (char *) (result + *sz);
390 result[0].len = temp[0].len + 1;
391 result[1].str = (char *) (result + *sz);
393 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
396 *max_capstrlen = result[0].len;
401 /* Fill in the information. This follows the following scheme
402 (indeces from TEMP for four strings):
403 entry #0: 0, 1, 2, 3 binary: 1111
407 This allows the representation of all possible combinations of
408 capability names in the string. First generate the strings. */
409 result[1].str = result[0].str = cp = (char *) (result + *sz);
411 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
424 /* We always add the last string. */
427 /* Add the strings which have the bit set in N. */
428 for (m = cnt - 2; m > 0; --m)
429 if ((n & (1 << m)) != 0)
432 /* Always add the first string. */
439 /* Now we are ready to install the string pointers and length. */
440 for (n = 0; n < (1UL << cnt); ++n)
445 size_t mask = 1 << --n;
448 for (m = 1 << cnt; m > 0; ++rp)
449 if ((--m & mask) != 0)
450 rp->len += temp[n].len + 1;
454 /* The first half of the strings all include the first string. */
457 while (n != (1UL << (cnt - 1)))
460 rp[0].str = rp[-2].str + rp[-2].len;
462 rp[0].str = rp[-1].str;
466 /* The second have starts right after the first part of the string of
467 corresponding entry in the first half. */
470 rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
475 /* The maximum string length. */
476 *max_capstrlen = result[0].len;