1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 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. */
26 #include <sys/types.h>
30 #include <stdio-common/_itoa.h>
31 #include <fpu_control.h>
34 #include <dl-machine.h>
35 #include <dl-procinfo.h>
36 #include <dl-osinfo.h>
39 extern char **_dl_argv
;
40 extern char **_environ
;
41 extern size_t _dl_pagesize
;
42 extern int _dl_clktck
;
43 extern const char *_dl_platform
;
44 extern unsigned long int _dl_hwcap
;
45 extern size_t _dl_platformlen
;
46 extern fpu_control_t _dl_fpu_control
;
48 extern void ENTRY_POINT (void);
50 /* Protect SUID program against misuse of file descriptors. */
51 extern void __libc_check_standard_fds (void);
53 ElfW(Addr
) _dl_base_addr
;
54 int __libc_enable_secure
;
55 int __libc_multiple_libcs
= 0; /* Defining this here avoids the inclusion
57 /* This variable contains the lowest stack address ever used. */
58 void *__libc_stack_end
;
59 static ElfW(auxv_t
) *_dl_auxv
;
60 unsigned long int _dl_hwcap_mask
= HWCAP_IMPORTANT
;
63 #ifndef DL_FIND_ARG_COMPONENTS
64 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
67 (argc) = *(long int *) cookie; \
68 (argv) = (char **) ((long int *) cookie + 1); \
69 (envp) = (argv) + (argc) + 1; \
70 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
72 (auxp) = (void *) ++_tmp; \
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
;
92 DL_FIND_ARG_COMPONENTS (start_argptr
, _dl_argc
, _dl_argv
, _environ
,
95 user_entry
= (ElfW(Addr
)) &ENTRY_POINT
;
96 _dl_platform
= NULL
; /* Default to nothing known about the platform. */
99 #define M(type) (1 << (type))
101 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; seen
|= M ((++av
)->a_type
))
105 phdr
= av
->a_un
.a_ptr
;
108 phnum
= av
->a_un
.a_val
;
111 _dl_pagesize
= av
->a_un
.a_val
;
114 user_entry
= av
->a_un
.a_val
;
117 _dl_base_addr
= av
->a_un
.a_val
;
120 uid
= av
->a_un
.a_val
;
123 gid
= av
->a_un
.a_val
;
126 euid
= av
->a_un
.a_val
;
129 egid
= av
->a_un
.a_val
;
132 _dl_platform
= av
->a_un
.a_ptr
;
135 _dl_hwcap
= av
->a_un
.a_val
;
138 _dl_clktck
= av
->a_un
.a_val
;
141 _dl_fpu_control
= av
->a_un
.a_val
;
145 #ifdef DL_SYSDEP_OSCHECK
146 DL_SYSDEP_OSCHECK (dl_fatal
);
149 /* Linux doesn't provide us with any of these values on the stack
150 when the dynamic linker is run directly as a program. */
152 #define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
158 __libc_enable_secure
= uid
!= euid
|| gid
!= egid
;
160 if (_dl_pagesize
== 0)
161 _dl_pagesize
= __getpagesize ();
163 #ifdef DL_SYSDEP_INIT
167 #ifdef DL_PLATFORM_INIT
171 /* Determine the length of the platform name. */
172 if (_dl_platform
!= NULL
)
173 _dl_platformlen
= strlen (_dl_platform
);
175 if (__sbrk (0) == &_end
)
176 /* The dynamic linker was run as a program, and so the initial break
177 starts just after our bss, at &_end. The malloc in dl-minimal.c
178 will consume the rest of this page, so tell the kernel to move the
179 break up that far. When the user program examines its break, it
180 will see this new value and not clobber our data. */
181 __sbrk (_dl_pagesize
- ((&_end
- (void *) 0) & (_dl_pagesize
- 1)));
183 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
184 allocated. If necessary we are doing it ourself. If it is not
185 possible we stop the program. */
186 if (__builtin_expect (__libc_enable_secure
, 0))
187 __libc_check_standard_fds ();
189 (*dl_main
) (phdr
, phnum
, &user_entry
);
195 _dl_sysdep_start_cleanup (void)
206 /* Terminate string. */
209 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; ++av
)
213 _dl_sysdep_message ("AT_PHDR: 0x",
214 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
219 _dl_sysdep_message ("AT_PHNUM: ",
220 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
225 _dl_sysdep_message ("AT_PAGESZ: ",
226 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
231 _dl_sysdep_message ("AT_ENTRY: 0x",
232 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
237 _dl_sysdep_message ("AT_BASE: 0x",
238 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
243 _dl_sysdep_message ("AT_UID: ",
244 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
249 _dl_sysdep_message ("AT_GID: ",
250 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
255 _dl_sysdep_message ("AT_EUID: ",
256 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
261 _dl_sysdep_message ("AT_EGID: ",
262 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
267 _dl_sysdep_message ("AT_PLATFORM: ", av
->a_un
.a_ptr
, "\n", NULL
);
270 _dl_hwcap
= av
->a_un
.a_val
;
271 if (_dl_procinfo (_dl_hwcap
) < 0)
272 _dl_sysdep_message ("AT_HWCAP: ",
273 _itoa_word (_dl_hwcap
, buf
+ sizeof buf
- 1,
278 _dl_sysdep_message ("AT_CLKTCK: ",
279 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
284 _dl_sysdep_message ("AT_FPUCW: ",
285 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
293 /* Return an array of useful/necessary hardware capability names. */
294 const struct r_strlenpair
*
296 _dl_important_hwcaps (const char *platform
, size_t platform_len
, size_t *sz
,
297 size_t *max_capstrlen
)
299 /* Determine how many important bits are set. */
300 unsigned long int masked
= _dl_hwcap
& _dl_hwcap_mask
;
301 size_t cnt
= platform
!= NULL
;
304 struct r_strlenpair
*temp
;
305 struct r_strlenpair
*result
;
306 struct r_strlenpair
*rp
;
309 /* Count the number of bits set in the masked value. */
310 for (n
= 0; (~((1UL << n
) - 1) & masked
) != 0; ++n
)
311 if ((masked
& (1UL << n
)) != 0)
316 /* If we have platform name and no important capability we only have
317 the base directory to search. */
318 result
= (struct r_strlenpair
*) malloc (sizeof (*result
));
322 _dl_signal_error (ENOMEM
, NULL
, "cannot create capability list");
325 result
[0].str
= (char *) result
; /* Does not really matter. */
332 /* Create temporary data structure to generate result table. */
333 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
335 for (n
= 0; masked
!= 0; ++n
)
336 if ((masked
& (1UL << n
)) != 0)
338 temp
[m
].str
= _dl_hwcap_string (n
);
339 temp
[m
].len
= strlen (temp
[m
].str
);
343 if (platform
!= NULL
)
345 temp
[m
].str
= platform
;
346 temp
[m
].len
= platform_len
;
350 /* Determine the total size of all strings together. */
355 total
= (1 << (cnt
- 2)) * (temp
[0].len
+ temp
[cnt
- 1].len
+ 2);
356 for (n
= 1; n
+ 1 < cnt
; ++n
)
357 total
+= (1 << (cnt
- 3)) * (temp
[n
].len
+ 1);
360 /* The result structure: we use a very compressed way to store the
361 various combinations of capability names. */
363 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
369 result
[0].str
= (char *) (result
+ *sz
);
370 result
[0].len
= temp
[0].len
+ 1;
371 result
[1].str
= (char *) (result
+ *sz
);
373 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
376 *max_capstrlen
= result
[0].len
;
381 /* Fill in the information. This follows the following scheme
382 (indeces from TEMP for four strings):
383 entry #0: 0, 1, 2, 3 binary: 1111
387 This allows the representation of all possible combinations of
388 capability names in the string. First generate the strings. */
389 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
391 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
404 /* We always add the last string. */
407 /* Add the strings which have the bit set in N. */
408 for (m
= cnt
- 2; m
> 0; --m
)
409 if ((n
& (1 << m
)) != 0)
412 /* Always add the first string. */
419 /* Now we are ready to install the string pointers and length. */
420 for (n
= 0; n
< (1 << cnt
); ++n
)
425 size_t mask
= 1 << --n
;
428 for (m
= 1 << cnt
; m
> 0; ++rp
)
429 if ((--m
& mask
) != 0)
430 rp
->len
+= temp
[n
].len
+ 1;
434 /* The first half of the strings all include the first string. */
437 while (n
!= (1 << (cnt
- 1)))
440 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
442 rp
[0].str
= rp
[-1].str
;
447 /* The second have starts right after the first part of the string of
448 corresponding entry in the first half. */
451 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
456 /* The maximum string length. */
457 *max_capstrlen
= result
[0].len
;