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>
38 extern char **_dl_argv
;
39 extern char **_environ
;
40 extern size_t _dl_pagesize
;
41 extern const char *_dl_platform
;
42 extern unsigned long int _dl_hwcap
;
43 extern size_t _dl_platformlen
;
44 extern fpu_control_t _dl_fpu_control
;
46 extern void ENTRY_POINT (void);
48 /* Protect SUID program against misuse of file descriptors. */
49 extern void __libc_check_standard_fds (void);
51 ElfW(Addr
) _dl_base_addr
;
52 int __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
;
58 unsigned long int _dl_hwcap_mask
= HWCAP_IMPORTANT
;
61 #ifndef DL_FIND_ARG_COMPONENTS
62 #define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
65 (argc) = *(long *) cookie; \
66 (argv) = (char **) cookie + 1; \
67 (envp) = (argv) + (argc) + 1; \
68 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
70 (auxp) = (void *) ++_tmp; \
76 _dl_sysdep_start (void **start_argptr
,
77 void (*dl_main
) (const ElfW(Phdr
) *phdr
, ElfW(Word
) phnum
,
78 ElfW(Addr
) *user_entry
))
80 const ElfW(Phdr
) *phdr
= NULL
;
82 ElfW(Addr
) user_entry
;
90 DL_FIND_ARG_COMPONENTS (start_argptr
, _dl_argc
, _dl_argv
, _environ
, _dl_auxv
);
92 user_entry
= (ElfW(Addr
)) &ENTRY_POINT
;
93 _dl_platform
= NULL
; /* Default to nothing known about the platform. */
96 #define M(type) (1 << (type))
98 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; seen
|= M ((++av
)->a_type
))
102 phdr
= av
->a_un
.a_ptr
;
105 phnum
= av
->a_un
.a_val
;
108 _dl_pagesize
= av
->a_un
.a_val
;
111 user_entry
= av
->a_un
.a_val
;
114 _dl_base_addr
= av
->a_un
.a_val
;
117 uid
= av
->a_un
.a_val
;
120 gid
= av
->a_un
.a_val
;
123 euid
= av
->a_un
.a_val
;
126 egid
= av
->a_un
.a_val
;
129 _dl_platform
= av
->a_un
.a_ptr
;
132 _dl_hwcap
= av
->a_un
.a_val
;
135 _dl_fpu_control
= av
->a_un
.a_val
;
139 /* Linux doesn't provide us with any of these values on the stack
140 when the dynamic linker is run directly as a program. */
142 #define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
148 __libc_enable_secure
= uid
!= euid
|| gid
!= egid
;
150 if (_dl_pagesize
== 0)
151 _dl_pagesize
= __getpagesize ();
153 #ifdef DL_SYSDEP_INIT
157 #ifdef DL_PLATFORM_INIT
161 /* Determine the length of the platform name. */
162 if (_dl_platform
!= NULL
)
163 _dl_platformlen
= strlen (_dl_platform
);
165 if (__sbrk (0) == &_end
)
166 /* The dynamic linker was run as a program, and so the initial break
167 starts just after our bss, at &_end. The malloc in dl-minimal.c
168 will consume the rest of this page, so tell the kernel to move the
169 break up that far. When the user program examines its break, it
170 will see this new value and not clobber our data. */
171 __sbrk (_dl_pagesize
- ((&_end
- (void *) 0) & (_dl_pagesize
- 1)));
173 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
174 allocated. If necessary we are doing it ourself. If it is not
175 possible we stop the program. */
176 if (__builtin_expect (__libc_enable_secure
, 0))
177 __libc_check_standard_fds ();
179 (*dl_main
) (phdr
, phnum
, &user_entry
);
184 _dl_sysdep_start_cleanup (void)
195 /* Terminate string. */
198 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; ++av
)
202 _dl_sysdep_message ("AT_PHDR: 0x",
203 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
208 _dl_sysdep_message ("AT_PHNUM: ",
209 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
214 _dl_sysdep_message ("AT_PAGESZ: ",
215 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
220 _dl_sysdep_message ("AT_ENTRY: 0x",
221 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
226 _dl_sysdep_message ("AT_BASE: 0x",
227 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
232 _dl_sysdep_message ("AT_UID: ",
233 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
238 _dl_sysdep_message ("AT_GID: ",
239 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
244 _dl_sysdep_message ("AT_EUID: ",
245 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
250 _dl_sysdep_message ("AT_EGID: ",
251 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
256 _dl_sysdep_message ("AT_PLATFORM: ", av
->a_un
.a_ptr
, "\n", NULL
);
259 _dl_hwcap
= av
->a_un
.a_val
;
260 if (_dl_procinfo (_dl_hwcap
) < 0)
261 _dl_sysdep_message ("AT_HWCAP: ",
262 _itoa_word (_dl_hwcap
, buf
+ sizeof buf
- 1,
267 _dl_sysdep_message ("AT_FPUCW: ",
268 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
276 /* Return an array of useful/necessary hardware capability names. */
277 const struct r_strlenpair
*
279 _dl_important_hwcaps (const char *platform
, size_t platform_len
, size_t *sz
,
280 size_t *max_capstrlen
)
282 /* Determine how many important bits are set. */
283 unsigned long int masked
= _dl_hwcap
& _dl_hwcap_mask
;
284 size_t cnt
= platform
!= NULL
;
287 struct r_strlenpair
*temp
;
288 struct r_strlenpair
*result
;
289 struct r_strlenpair
*rp
;
292 /* Count the number of bits set in the masked value. */
293 for (n
= 0; (~((1UL << n
) - 1) & masked
) != 0; ++n
)
294 if ((masked
& (1UL << n
)) != 0)
299 /* If we have platform name and no important capability we only have
300 the base directory to search. */
301 result
= (struct r_strlenpair
*) malloc (sizeof (*result
));
305 _dl_signal_error (ENOMEM
, NULL
, "cannot create capability list");
308 result
[0].str
= (char *) result
; /* Does not really matter. */
315 /* Create temporary data structure to generate result table. */
316 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
318 for (n
= 0; masked
!= 0; ++n
)
319 if ((masked
& (1UL << n
)) != 0)
321 temp
[m
].str
= _dl_hwcap_string (n
);
322 temp
[m
].len
= strlen (temp
[m
].str
);
326 if (platform
!= NULL
)
328 temp
[m
].str
= platform
;
329 temp
[m
].len
= platform_len
;
333 /* Determine the total size of all strings together. */
338 total
= (1 << (cnt
- 2)) * (temp
[0].len
+ temp
[cnt
- 1].len
+ 2);
339 for (n
= 1; n
+ 1 < cnt
; ++n
)
340 total
+= (1 << (cnt
- 3)) * (temp
[n
].len
+ 1);
343 /* The result structure: we use a very compressed way to store the
344 various combinations of capability names. */
346 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
352 result
[0].str
= (char *) (result
+ *sz
);
353 result
[0].len
= temp
[0].len
+ 1;
354 result
[1].str
= (char *) (result
+ *sz
);
356 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
359 *max_capstrlen
= result
[0].len
;
364 /* Fill in the information. This follows the following scheme
365 (indeces from TEMP for four strings):
366 entry #0: 0, 1, 2, 3 binary: 1111
370 This allows the representation of all possible combinations of
371 capability names in the string. First generate the strings. */
372 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
374 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
387 /* We always add the last string. */
390 /* Add the strings which have the bit set in N. */
391 for (m
= cnt
- 2; m
> 0; --m
)
392 if ((n
& (1 << m
)) != 0)
395 /* Always add the first string. */
402 /* Now we are ready to install the string pointers and length. */
403 for (n
= 0; n
< (1 << cnt
); ++n
)
408 size_t mask
= 1 << --n
;
411 for (m
= 1 << cnt
; m
> 0; ++rp
)
412 if ((--m
& mask
) != 0)
413 rp
->len
+= temp
[n
].len
+ 1;
417 /* The first half of the strings all include the first string. */
420 while (n
!= (1 << (cnt
- 1)))
423 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
425 rp
[0].str
= rp
[-1].str
;
430 /* The second have starts right after the first part of the string of
431 corresponding entry in the first half. */
434 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
439 /* The maximum string length. */
440 *max_capstrlen
= result
[0].len
;