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);
263 if (idx < sizeof (auxvars) / sizeof (auxvars[0]))
265 if (av->a_type != AT_HWCAP || _dl_procinfo (av->a_un.a_val) < 0)
267 const char *val = av->a_un.a_ptr;
269 if (__builtin_expect (auxvars[idx].form, dec) == dec)
270 val = _itoa ((unsigned long int) av->a_un.a_val,
271 buf + sizeof buf - 1, 10, 0);
272 else if (__builtin_expect (auxvars[idx].form, hex) == hex)
273 val = _itoa ((unsigned long int) av->a_un.a_val,
274 buf + sizeof buf - 1, 16, 0);
276 _dl_printf ("%s%s\n", auxvars[idx].label, val);
282 /* Unknown value: print a generic line. */
284 buf[sizeof (buf2) - 1] = '\0';
285 const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
286 buf2 + sizeof buf2 - 1, 16, 0);
287 const char *val = _itoa ((unsigned long int) av->a_type,
288 buf + sizeof buf - 1, 16, 0);
289 _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
294 /* Return an array of useful/necessary hardware capability names. */
295 const struct r_strlenpair *
297 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
298 size_t *max_capstrlen)
300 /* Determine how many important bits are set. */
301 unsigned long int masked = GL(dl_hwcap) & GL(dl_hwcap_mask);
302 size_t cnt = platform != NULL;
305 struct r_strlenpair *temp;
306 struct r_strlenpair *result;
307 struct r_strlenpair *rp;
310 /* Count the number of bits set in the masked value. */
311 for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
312 if ((masked & (1UL << n)) != 0)
316 /* For TLS enabled builds always add 'tls'. */
321 /* If we have platform name and no important capability we only have
322 the base directory to search. */
323 result = (struct r_strlenpair *) malloc (sizeof (*result));
327 result[0].str = (char *) result; /* Does not really matter. */
335 /* Create temporary data structure to generate result table. */
336 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
338 for (n = 0; masked != 0; ++n)
339 if ((masked & (1UL << n)) != 0)
341 temp[m].str = _dl_hwcap_string (n);
342 temp[m].len = strlen (temp[m].str);
346 if (platform != NULL)
348 temp[m].str = platform;
349 temp[m].len = platform_len;
359 /* Determine the total size of all strings together. */
361 total = temp[0].len + 1;
364 total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
365 for (n = 1; n + 1 < cnt; ++n)
366 total += (1UL << (cnt - 3)) * (temp[n].len + 1);
369 /* The result structure: we use a very compressed way to store the
370 various combinations of capability names. */
372 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
378 INTUSE(_dl_signal_error) (ENOMEM, NULL, NULL,
379 N_("cannot create capability list"));
384 result[0].str = (char *) (result + *sz);
385 result[0].len = temp[0].len + 1;
386 result[1].str = (char *) (result + *sz);
388 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
391 *max_capstrlen = result[0].len;
396 /* Fill in the information. This follows the following scheme
397 (indeces from TEMP for four strings):
398 entry #0: 0, 1, 2, 3 binary: 1111
402 This allows the representation of all possible combinations of
403 capability names in the string. First generate the strings. */
404 result[1].str = result[0].str = cp = (char *) (result + *sz);
406 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
419 /* We always add the last string. */
422 /* Add the strings which have the bit set in N. */
423 for (m = cnt - 2; m > 0; --m)
424 if ((n & (1 << m)) != 0)
427 /* Always add the first string. */
434 /* Now we are ready to install the string pointers and length. */
435 for (n = 0; n < (1UL << cnt); ++n)
440 size_t mask = 1 << --n;
443 for (m = 1 << cnt; m > 0; ++rp)
444 if ((--m & mask) != 0)
445 rp->len += temp[n].len + 1;
449 /* The first half of the strings all include the first string. */
452 while (n != (1UL << (cnt - 1)))
455 rp[0].str = rp[-2].str + rp[-2].len;
457 rp[0].str = rp[-1].str;
461 /* The second have starts right after the first part of the string of
462 corresponding entry in the first half. */
465 rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
470 /* The maximum string length. */
471 *max_capstrlen = result[0].len;