1 /* Operating system support for run-time dynamic linker. Generic Unix version.
2 Copyright (C) 1995-1998, 2000, 2001, 2002 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>
41 extern char **_environ
;
44 /* Protect SUID program against misuse of file descriptors. */
45 extern void __libc_check_standard_fds (void);
47 #ifdef NEED_DL_BASE_ADDR
48 ElfW(Addr
) _dl_base_addr
;
50 int __libc_enable_secure
;
51 int __libc_multiple_libcs
= 0; /* Defining this here avoids the inclusion
53 /* This variable contains the lowest stack address ever used. */
54 void *__libc_stack_end
;
55 static ElfW(auxv_t
) *_dl_auxv
;
57 #ifndef DL_FIND_ARG_COMPONENTS
58 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
61 (argc) = *(long int *) cookie; \
62 (argv) = (char **) ((long int *) cookie + 1); \
63 (envp) = (argv) + (argc) + 1; \
64 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
66 (auxp) = (void *) ++_tmp; \
72 _dl_sysdep_start (void **start_argptr
,
73 void (*dl_main
) (const ElfW(Phdr
) *phdr
, ElfW(Word
) phnum
,
74 ElfW(Addr
) *user_entry
))
76 const ElfW(Phdr
) *phdr
= NULL
;
78 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
, _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
;
119 uid
= av
->a_un
.a_val
;
122 gid
= av
->a_un
.a_val
;
125 euid
= av
->a_un
.a_val
;
128 egid
= av
->a_un
.a_val
;
131 GL(dl_platform
) = av
->a_un
.a_ptr
;
134 GL(dl_hwcap
) = av
->a_un
.a_val
;
137 GL(dl_clktck
) = av
->a_un
.a_val
;
140 GL(dl_fpu_control
) = av
->a_un
.a_val
;
144 #ifdef DL_SYSDEP_OSCHECK
145 DL_SYSDEP_OSCHECK (dl_fatal
);
148 /* Linux doesn't provide us with any of these values on the stack
149 when the dynamic linker is run directly as a program. */
152 # define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
159 __libc_enable_secure
= uid
!= euid
|| gid
!= egid
;
161 #ifndef HAVE_AUX_PAGESIZE
162 if (GL(dl_pagesize
) == 0)
163 GL(dl_pagesize
) = __getpagesize ();
166 #ifdef DL_SYSDEP_INIT
170 #ifdef DL_PLATFORM_INIT
174 /* Determine the length of the platform name. */
175 if (GL(dl_platform
) != NULL
)
176 GL(dl_platformlen
) = strlen (GL(dl_platform
));
178 if (__sbrk (0) == &_end
)
179 /* The dynamic linker was run as a program, and so the initial break
180 starts just after our bss, at &_end. The malloc in dl-minimal.c
181 will consume the rest of this page, so tell the kernel to move the
182 break up that far. When the user program examines its break, it
183 will see this new value and not clobber our data. */
184 __sbrk (GL(dl_pagesize
) - ((&_end
- (void *) 0) & (GL(dl_pagesize
) - 1)));
186 /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
187 allocated. If necessary we are doing it ourself. If it is not
188 possible we stop the program. */
189 if (__builtin_expect (__libc_enable_secure
, 0))
190 __libc_check_standard_fds ();
192 (*dl_main
) (phdr
, phnum
, &user_entry
);
198 _dl_sysdep_start_cleanup (void)
209 /* Terminate string. */
212 /* The following code assumes that the AT_* values are encoded
213 starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
214 close by (otherwise the array will be too large). In case we have
215 to support a platform where these requirements are not fulfilled
216 some alternative implementation has to be used. */
217 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; ++av
)
221 const char label
[20];
222 enum { dec
, hex
, str
} form
;
225 [AT_EXECFD
- 2] = { "AT_EXECFD: ", dec
},
226 [AT_PHDR
- 2] = { "AT_PHDR: 0x", hex
},
227 [AT_PHENT
- 2] = { "AT_PHENT: ", dec
},
228 [AT_PHNUM
- 2] = { "AT_PHNUM: ", dec
},
229 [AT_PAGESZ
- 2] = { "AT_PAGESZ: ", dec
},
230 [AT_BASE
- 2] = { "AT_BASE: 0x", hex
},
231 [AT_FLAGS
- 2] = { "AT_FLAGS: 0x", hex
},
232 [AT_ENTRY
- 2] = { "AT_ENTRY: 0x", hex
},
233 [AT_NOTELF
- 2] = { "AT_NOTELF: ", hex
},
234 [AT_UID
- 2] = { "AT_UID: ", dec
},
235 [AT_EUID
- 2] = { "AT_EUID: ", dec
},
236 [AT_GID
- 2] = { "AT_GID: ", dec
},
237 [AT_EGID
- 2] = { "AT_EGID: ", dec
},
238 [AT_PLATFORM
- 2] = { "AT_PLATFORM: ", str
},
239 [AT_HWCAP
- 2] = { "AT_HWCAP: ", hex
},
240 [AT_CLKTCK
- 2] = { "AT_CLKTCK: ", dec
},
241 [AT_FPUCW
- 2] = { "AT_FPUCW: ", hex
},
242 [AT_DCACHEBSIZE
- 2] = { "AT_DCACHEBSIZE: 0x", hex
},
243 [AT_ICACHEBSIZE
- 2] = { "AT_ICACHEBSIZE: 0x", hex
},
244 [AT_UCACHEBSIZE
- 2] = { "AT_UCACHEBSIZE: 0x", hex
}
246 unsigned int idx
= (unsigned int) (av
->a_type
- 2);
248 assert (AT_NULL
== 0);
249 assert (AT_IGNORE
== 1);
250 if (idx
< sizeof (auxvars
) / sizeof (auxvars
[0]))
252 if (av
->a_type
!= AT_HWCAP
|| _dl_procinfo (av
->a_un
.a_val
) < 0)
254 const char *val
= av
->a_un
.a_ptr
;
256 if (__builtin_expect (auxvars
[idx
].form
, dec
) == dec
)
257 val
= _itoa ((unsigned long int) av
->a_un
.a_val
,
258 buf
+ sizeof buf
- 1, 10, 0);
259 else if (__builtin_expect (auxvars
[idx
].form
, hex
) == hex
)
260 val
= _itoa ((unsigned long int) av
->a_un
.a_val
,
261 buf
+ sizeof buf
- 1, 16, 0);
263 _dl_printf ("%s%s\n", auxvars
[idx
].label
, val
);
270 /* Return an array of useful/necessary hardware capability names. */
271 const struct r_strlenpair
*
273 _dl_important_hwcaps (const char *platform
, size_t platform_len
, size_t *sz
,
274 size_t *max_capstrlen
)
276 /* Determine how many important bits are set. */
277 unsigned long int masked
= GL(dl_hwcap
) & GL(dl_hwcap_mask
);
278 size_t cnt
= platform
!= NULL
;
281 struct r_strlenpair
*temp
;
282 struct r_strlenpair
*result
;
283 struct r_strlenpair
*rp
;
286 /* Count the number of bits set in the masked value. */
287 for (n
= 0; (~((1UL << n
) - 1) & masked
) != 0; ++n
)
288 if ((masked
& (1UL << n
)) != 0)
293 /* If we have platform name and no important capability we only have
294 the base directory to search. */
295 result
= (struct r_strlenpair
*) malloc (sizeof (*result
));
299 INT(_dl_signal_error
) (ENOMEM
, NULL
, NULL
,
300 N_("cannot create capability list"));
303 result
[0].str
= (char *) result
; /* Does not really matter. */
310 /* Create temporary data structure to generate result table. */
311 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
313 for (n
= 0; masked
!= 0; ++n
)
314 if ((masked
& (1UL << n
)) != 0)
316 temp
[m
].str
= _dl_hwcap_string (n
);
317 temp
[m
].len
= strlen (temp
[m
].str
);
321 if (platform
!= NULL
)
323 temp
[m
].str
= platform
;
324 temp
[m
].len
= platform_len
;
328 /* Determine the total size of all strings together. */
333 total
= (1 << (cnt
- 2)) * (temp
[0].len
+ temp
[cnt
- 1].len
+ 2);
334 for (n
= 1; n
+ 1 < cnt
; ++n
)
335 total
+= (1 << (cnt
- 3)) * (temp
[n
].len
+ 1);
338 /* The result structure: we use a very compressed way to store the
339 various combinations of capability names. */
341 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
347 result
[0].str
= (char *) (result
+ *sz
);
348 result
[0].len
= temp
[0].len
+ 1;
349 result
[1].str
= (char *) (result
+ *sz
);
351 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
354 *max_capstrlen
= result
[0].len
;
359 /* Fill in the information. This follows the following scheme
360 (indeces from TEMP for four strings):
361 entry #0: 0, 1, 2, 3 binary: 1111
365 This allows the representation of all possible combinations of
366 capability names in the string. First generate the strings. */
367 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
369 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
382 /* We always add the last string. */
385 /* Add the strings which have the bit set in N. */
386 for (m
= cnt
- 2; m
> 0; --m
)
387 if ((n
& (1 << m
)) != 0)
390 /* Always add the first string. */
397 /* Now we are ready to install the string pointers and length. */
398 for (n
= 0; n
< (1UL << cnt
); ++n
)
403 size_t mask
= 1 << --n
;
406 for (m
= 1 << cnt
; m
> 0; ++rp
)
407 if ((--m
& mask
) != 0)
408 rp
->len
+= temp
[n
].len
+ 1;
412 /* The first half of the strings all include the first string. */
415 while (n
!= (1UL << (cnt
- 1)))
418 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
420 rp
[0].str
= rp
[-1].str
;
425 /* The second have starts right after the first part of the string of
426 corresponding entry in the first half. */
429 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
434 /* The maximum string length. */
435 *max_capstrlen
= result
[0].len
;