1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995, 1996, 1997, 1998 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>
29 #include <elf/ldsodefs.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 ElfW(Addr
) _dl_base_addr
;
49 int __libc_enable_secure
;
50 int __libc_multiple_libcs
; /* Defining this here avoids the inclusion
52 /* This variable contains the lowest stack address ever used. */
53 void *__libc_stack_end
;
54 static ElfW(auxv_t
) *_dl_auxv
;
55 unsigned long int _dl_hwcap_mask
= HWCAP_IMPORTANT
;
58 #ifndef DL_FIND_ARG_COMPONENTS
59 #define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
62 (argc) = *(long *) cookie; \
63 (argv) = (char **) cookie + 1; \
64 (envp) = (argv) + (argc) + 1; \
65 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
67 (auxp) = (void *) ++_tmp; \
73 _dl_sysdep_start (void **start_argptr
,
74 void (*dl_main
) (const ElfW(Phdr
) *phdr
, ElfW(Word
) phnum
,
75 ElfW(Addr
) *user_entry
))
77 const ElfW(Phdr
) *phdr
= NULL
;
79 ElfW(Addr
) user_entry
;
87 DL_FIND_ARG_COMPONENTS (start_argptr
, _dl_argc
, _dl_argv
, _environ
, _dl_auxv
);
89 user_entry
= (ElfW(Addr
)) &ENTRY_POINT
;
90 _dl_platform
= NULL
; /* Default to nothing known about the platform. */
93 #define M(type) (1 << (type))
95 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; seen
|= M ((++av
)->a_type
))
99 phdr
= av
->a_un
.a_ptr
;
102 phnum
= av
->a_un
.a_val
;
105 _dl_pagesize
= av
->a_un
.a_val
;
108 user_entry
= av
->a_un
.a_val
;
111 _dl_base_addr
= av
->a_un
.a_val
;
114 uid
= av
->a_un
.a_val
;
117 gid
= av
->a_un
.a_val
;
120 euid
= av
->a_un
.a_val
;
123 egid
= av
->a_un
.a_val
;
126 _dl_platform
= av
->a_un
.a_ptr
;
129 _dl_hwcap
= av
->a_un
.a_val
;
132 _dl_fpu_control
= av
->a_un
.a_val
;
136 /* Linux doesn't provide us with any of these values on the stack
137 when the dynamic linker is run directly as a program. */
139 #define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
145 __libc_enable_secure
= uid
!= euid
|| gid
!= egid
;
147 if (_dl_pagesize
== 0)
148 _dl_pagesize
= __getpagesize ();
150 #ifdef DL_SYSDEP_INIT
154 #ifdef DL_PLATFORM_INIT
158 /* Determine the length of the platform name. */
159 if (_dl_platform
!= NULL
)
160 _dl_platformlen
= strlen (_dl_platform
);
162 if (__sbrk (0) == &_end
)
163 /* The dynamic linker was run as a program, and so the initial break
164 starts just after our bss, at &_end. The malloc in dl-minimal.c
165 will consume the rest of this page, so tell the kernel to move the
166 break up that far. When the user program examines its break, it
167 will see this new value and not clobber our data. */
168 __sbrk (_dl_pagesize
- ((&_end
- (void *) 0) & (_dl_pagesize
- 1)));
170 (*dl_main
) (phdr
, phnum
, &user_entry
);
175 _dl_sysdep_start_cleanup (void)
186 /* Terminate string. */
189 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; ++av
)
193 _dl_sysdep_message ("AT_PHDR: 0x",
194 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
199 _dl_sysdep_message ("AT_PHNUM: ",
200 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
205 _dl_sysdep_message ("AT_PAGESZ: ",
206 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
211 _dl_sysdep_message ("AT_ENTRY: 0x",
212 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
217 _dl_sysdep_message ("AT_BASE: 0x",
218 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
223 _dl_sysdep_message ("AT_UID: ",
224 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
229 _dl_sysdep_message ("AT_GID: ",
230 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
235 _dl_sysdep_message ("AT_EUID: ",
236 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
241 _dl_sysdep_message ("AT_EGID: ",
242 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
247 _dl_sysdep_message ("AT_PLATFORM: ", av
->a_un
.a_ptr
, "\n", NULL
);
250 _dl_hwcap
= av
->a_un
.a_val
;
251 if (_dl_procinfo (_dl_hwcap
) < 0)
252 _dl_sysdep_message ("AT_HWCAP: ",
253 _itoa_word (_dl_hwcap
, buf
+ sizeof buf
- 1,
258 _dl_sysdep_message ("AT_FPUCW: ",
259 _itoa_word (av
->a_un
.a_val
, buf
+ sizeof buf
- 1,
267 /* Return an array of useful/necessary hardware capability names. */
268 const struct r_strlenpair
*
270 _dl_important_hwcaps (const char *platform
, size_t platform_len
, size_t *sz
,
271 size_t *max_capstrlen
)
273 /* Determine how many important bits are set. */
274 unsigned long int masked
= _dl_hwcap
& _dl_hwcap_mask
;
275 size_t cnt
= platform
!= NULL
;
278 struct r_strlenpair
*temp
;
279 struct r_strlenpair
*result
;
280 struct r_strlenpair
*rp
;
283 /* Count the number of bits set in the masked value. */
284 for (n
= 0; (~((1UL << n
) - 1) & masked
) != 0; ++n
)
285 if ((masked
& (1UL << n
)) != 0)
290 /* If we have platform name and no important capability we only have
291 the base directory to search. */
292 result
= (struct r_strlenpair
*) malloc (sizeof (*result
));
296 _dl_signal_error (ENOMEM
, NULL
, "cannot create capability list");
299 result
[0].str
= (char *) result
; /* Does not really matter. */
306 /* Create temporary data structure to generate result table. */
307 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
309 for (n
= 0; masked
!= 0; ++n
)
310 if ((masked
& (1UL << n
)) != 0)
312 temp
[m
].str
= _dl_hwcap_string (n
);
313 temp
[m
].len
= strlen (temp
[m
].str
);
317 if (platform
!= NULL
)
319 temp
[m
].str
= platform
;
320 temp
[m
].len
= platform_len
;
324 /* Determine the total size of all strings together. */
329 total
= (1 << (cnt
- 2)) * (temp
[0].len
+ temp
[cnt
- 1].len
+ 2);
330 for (n
= 1; n
+ 1 < cnt
; ++n
)
331 total
+= (1 << (cnt
- 3)) * (temp
[n
].len
+ 1);
334 /* The result structure: we use a very compressed way to store the
335 various combinations of capability names. */
337 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
343 result
[0].str
= (char *) (result
+ *sz
);
344 result
[0].len
= temp
[0].len
+ 1;
345 result
[1].str
= (char *) (result
+ *sz
);
347 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
350 *max_capstrlen
= result
[0].len
;
355 /* Fill in the information. This follows the following scheme
356 (indeces from TEMP for four strings):
357 entry #0: 0, 1, 2, 3 binary: 1111
361 This allows to represent all possible combinations of capability
362 names in the string. First generate the strings. */
363 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
365 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
378 /* We always add the last string. */
381 /* Add the strings which have the bit set in N. */
382 for (m
= cnt
- 2; m
> 0; --m
)
383 if ((n
& (1 << m
)) != 0)
386 /* Always add the first string. */
393 /* Now we are ready to install the string pointers and length. */
394 for (n
= 0; n
< (1 << cnt
); ++n
)
399 size_t mask
= 1 << --n
;
402 for (m
= 1 << cnt
; m
> 0; ++rp
)
403 if ((--m
& mask
) != 0)
404 rp
->len
+= temp
[n
].len
+ 1;
408 /* The first half of the strings all include the first string. */
411 while (n
!= (1 << (cnt
- 1)))
414 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
416 rp
[0].str
= rp
[-1].str
;
421 /* The second have starts right after the first part of the string of
422 corresponding entry in the first half. */
425 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
430 /* The maximum string length. */
431 *max_capstrlen
= result
[0].len
;