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
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 attribute_relro
= 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 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) \
64 (argc) = *(long int *) cookie; \
65 (argv) = (char **) ((long int *) cookie + 1); \
66 (envp) = (argv) + (argc) + 1; \
67 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
69 (auxp) = (void *) ++_tmp; \
74 # define DL_STACK_END(cookie) ((void *) (cookie))
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
;
84 ElfW(Addr
) user_entry
;
86 #ifdef HAVE_AUX_SECURE
87 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
88 # define set_seen_secure() ((void) 0)
92 unsigned int seen
= 0;
93 # define set_seen_secure() (seen = -1)
95 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
97 # define M(type) (1 << (type))
98 # define set_seen(tag) seen |= M ((tag)->a_type)
101 #ifdef NEED_DL_SYSINFO
102 uintptr_t new_sysinfo
= 0;
105 __libc_stack_end
= DL_STACK_END (start_argptr
);
106 DL_FIND_ARG_COMPONENTS (start_argptr
, _dl_argc
, INTUSE(_dl_argv
), _environ
,
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
++))
116 phdr
= av
->a_un
.a_ptr
;
119 phnum
= av
->a_un
.a_val
;
122 GLRO(dl_pagesize
) = av
->a_un
.a_val
;
125 user_entry
= av
->a_un
.a_val
;
127 #ifdef NEED_DL_BASE_ADDR
129 _dl_base_addr
= av
->a_un
.a_val
;
132 #ifndef HAVE_AUX_SECURE
135 uid
^= av
->a_un
.a_val
;
139 gid
^= av
->a_un
.a_val
;
143 #ifndef HAVE_AUX_SECURE
146 INTUSE(__libc_enable_secure
) = av
->a_un
.a_val
;
149 GLRO(dl_platform
) = av
->a_un
.a_ptr
;
152 GLRO(dl_hwcap
) = av
->a_un
.a_val
;
155 GLRO(dl_clktck
) = av
->a_un
.a_val
;
158 GLRO(dl_fpu_control
) = av
->a_un
.a_val
;
160 #ifdef NEED_DL_SYSINFO
162 new_sysinfo
= av
->a_un
.a_val
;
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
;
170 #ifdef DL_PLATFORM_AUXV
175 #ifdef DL_SYSDEP_OSCHECK
176 DL_SYSDEP_OSCHECK (dl_fatal
);
179 #ifndef HAVE_AUX_SECURE
182 /* Fill in the values we have not gotten from the kernel through the
184 # ifndef HAVE_AUX_XID
185 # define SEE(UID, var, uid) \
186 if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
188 SEE (EUID
, uid
, euid
);
190 SEE (EGID
, gid
, egid
);
193 /* If one of the two pairs of IDs does not match this is a setuid
195 INTUSE(__libc_enable_secure
) = uid
| gid
;
199 #ifndef HAVE_AUX_PAGESIZE
200 if (GLRO(dl_pagesize
) == 0)
201 GLRO(dl_pagesize
) = __getpagesize ();
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
;
210 #ifdef DL_SYSDEP_INIT
214 #ifdef DL_PLATFORM_INIT
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
);
243 _dl_sysdep_start_cleanup (void)
254 /* Terminate string. */
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
)
266 const char label
[20];
267 enum { unknown
= 0, dec
, hex
, str
, ignore
} form
;
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
)
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)
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
);
327 /* Unknown value: print a generic line. */
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
*
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
;
350 struct r_strlenpair
*temp
;
351 struct r_strlenpair
*result
;
352 struct r_strlenpair
*rp
;
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)
361 /* For TLS enabled builds always add 'tls'. */
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
));
372 result
[0].str
= (char *) result
; /* Does not really matter. */
380 /* Create temporary data structure to generate result table. */
381 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
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
);
391 if (platform
!= NULL
)
393 temp
[m
].str
= platform
;
394 temp
[m
].len
= platform_len
;
404 /* Determine the total size of all strings together. */
406 total
= temp
[0].len
+ 1;
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. */
417 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
423 _dl_signal_error (ENOMEM
, NULL
, NULL
,
424 N_("cannot create capability list"));
429 result
[0].str
= (char *) (result
+ *sz
);
430 result
[0].len
= temp
[0].len
+ 1;
431 result
[1].str
= (char *) (result
+ *sz
);
433 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
436 *max_capstrlen
= result
[0].len
;
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
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
);
451 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
464 /* We always add the last string. */
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)
472 /* Always add the first string. */
479 /* Now we are ready to install the string pointers and length. */
480 for (n
= 0; n
< (1UL << cnt
); ++n
)
485 size_t mask
= 1 << --n
;
488 for (m
= 1 << cnt
; m
> 0; ++rp
)
489 if ((--m
& mask
) != 0)
490 rp
->len
+= temp
[n
].len
+ 1;
494 /* The first half of the strings all include the first string. */
497 while (n
!= (1UL << (cnt
- 1)))
500 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
502 rp
[0].str
= rp
[-1].str
;
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;
515 /* The maximum string length. */
516 *max_capstrlen
= result
[0].len
;