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 attribute_hidden
;
42 extern void _end attribute_hidden
;
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
= 0;
51 INTVARDEF(__libc_enable_secure
)
52 int __libc_multiple_libcs
= 0; /* Defining this here avoids the inclusion
54 /* This variable contains the lowest stack address ever used. */
55 void *__libc_stack_end
;
56 static ElfW(auxv_t
) *_dl_auxv
;
58 #ifndef DL_FIND_ARG_COMPONENTS
59 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
62 (argc) = *(long int *) cookie; \
63 (argv) = (char **) ((long int *) 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
;
84 # define set_seen(tag) (tag) /* Evaluate for the side effects. */
86 unsigned int seen
= 0;
87 # define M(type) (1 << (type))
88 # define set_seen(tag) seen |= M ((tag)->a_type)
91 DL_FIND_ARG_COMPONENTS (start_argptr
, _dl_argc
, INTUSE(_dl_argv
), _environ
,
94 user_entry
= (ElfW(Addr
)) ENTRY_POINT
;
95 GL(dl_platform
) = NULL
; /* Default to nothing known about the platform. */
97 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; set_seen (av
++))
101 phdr
= av
->a_un
.a_ptr
;
104 phnum
= av
->a_un
.a_val
;
107 GL(dl_pagesize
) = av
->a_un
.a_val
;
110 user_entry
= av
->a_un
.a_val
;
112 #ifdef NEED_DL_BASE_ADDR
114 _dl_base_addr
= av
->a_un
.a_val
;
119 uid
^= av
->a_un
.a_val
;
123 gid
^= av
->a_un
.a_val
;
126 GL(dl_platform
) = av
->a_un
.a_ptr
;
129 GL(dl_hwcap
) = av
->a_un
.a_val
;
132 GL(dl_clktck
) = av
->a_un
.a_val
;
135 GL(dl_fpu_control
) = av
->a_un
.a_val
;
139 #ifdef DL_SYSDEP_OSCHECK
140 DL_SYSDEP_OSCHECK (dl_fatal
);
143 /* Fill in the values we have not gotten from the kernel through the
146 # define SEE(UID, var, uid) \
147 if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
149 SEE (EUID
, uid
, euid
);
151 SEE (EGID
, gid
, egid
);
154 /* If one of the two pairs of IDs does not mattch this is a setuid
156 INTUSE(__libc_enable_secure
) = uid
| gid
;
158 #ifndef HAVE_AUX_PAGESIZE
159 if (GL(dl_pagesize
) == 0)
160 GL(dl_pagesize
) = __getpagesize ();
163 #ifdef DL_SYSDEP_INIT
167 #ifdef DL_PLATFORM_INIT
171 /* Determine the length of the platform name. */
172 if (GL(dl_platform
) != NULL
)
173 GL(dl_platformlen
) = strlen (GL(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 (GL(dl_pagesize
) - ((&_end
- (void *) 0) & (GL(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 (INTUSE(__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 /* The following code assumes that the AT_* values are encoded
210 starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
211 close by (otherwise the array will be too large). In case we have
212 to support a platform where these requirements are not fulfilled
213 some alternative implementation has to be used. */
214 for (av
= _dl_auxv
; av
->a_type
!= AT_NULL
; ++av
)
218 const char label
[20];
219 enum { dec
, hex
, str
} form
;
222 [AT_EXECFD
- 2] = { "AT_EXECFD: ", dec
},
223 [AT_PHDR
- 2] = { "AT_PHDR: 0x", hex
},
224 [AT_PHENT
- 2] = { "AT_PHENT: ", dec
},
225 [AT_PHNUM
- 2] = { "AT_PHNUM: ", dec
},
226 [AT_PAGESZ
- 2] = { "AT_PAGESZ: ", dec
},
227 [AT_BASE
- 2] = { "AT_BASE: 0x", hex
},
228 [AT_FLAGS
- 2] = { "AT_FLAGS: 0x", hex
},
229 [AT_ENTRY
- 2] = { "AT_ENTRY: 0x", hex
},
230 [AT_NOTELF
- 2] = { "AT_NOTELF: ", hex
},
231 [AT_UID
- 2] = { "AT_UID: ", dec
},
232 [AT_EUID
- 2] = { "AT_EUID: ", dec
},
233 [AT_GID
- 2] = { "AT_GID: ", dec
},
234 [AT_EGID
- 2] = { "AT_EGID: ", dec
},
235 [AT_PLATFORM
- 2] = { "AT_PLATFORM: ", str
},
236 [AT_HWCAP
- 2] = { "AT_HWCAP: ", hex
},
237 [AT_CLKTCK
- 2] = { "AT_CLKTCK: ", dec
},
238 [AT_FPUCW
- 2] = { "AT_FPUCW: ", hex
},
239 [AT_DCACHEBSIZE
- 2] = { "AT_DCACHEBSIZE: 0x", hex
},
240 [AT_ICACHEBSIZE
- 2] = { "AT_ICACHEBSIZE: 0x", hex
},
241 [AT_UCACHEBSIZE
- 2] = { "AT_UCACHEBSIZE: 0x", hex
}
243 unsigned int idx
= (unsigned int) (av
->a_type
- 2);
245 assert (AT_NULL
== 0);
246 assert (AT_IGNORE
== 1);
247 if (idx
< sizeof (auxvars
) / sizeof (auxvars
[0]))
249 if (av
->a_type
!= AT_HWCAP
|| _dl_procinfo (av
->a_un
.a_val
) < 0)
251 const char *val
= av
->a_un
.a_ptr
;
253 if (__builtin_expect (auxvars
[idx
].form
, dec
) == dec
)
254 val
= _itoa ((unsigned long int) av
->a_un
.a_val
,
255 buf
+ sizeof buf
- 1, 10, 0);
256 else if (__builtin_expect (auxvars
[idx
].form
, hex
) == hex
)
257 val
= _itoa ((unsigned long int) av
->a_un
.a_val
,
258 buf
+ sizeof buf
- 1, 16, 0);
260 _dl_printf ("%s%s\n", auxvars
[idx
].label
, val
);
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
= GL(dl_hwcap
) & GL(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 INTUSE(_dl_signal_error
) (ENOMEM
, NULL
, NULL
,
297 N_("cannot create capability list"));
300 result
[0].str
= (char *) result
; /* Does not really matter. */
307 /* Create temporary data structure to generate result table. */
308 temp
= (struct r_strlenpair
*) alloca (cnt
* sizeof (*temp
));
310 for (n
= 0; masked
!= 0; ++n
)
311 if ((masked
& (1UL << n
)) != 0)
313 temp
[m
].str
= _dl_hwcap_string (n
);
314 temp
[m
].len
= strlen (temp
[m
].str
);
318 if (platform
!= NULL
)
320 temp
[m
].str
= platform
;
321 temp
[m
].len
= platform_len
;
326 /* Determine the total size of all strings together. */
331 total
= (1UL << (cnt
- 2)) * (temp
[0].len
+ temp
[cnt
- 1].len
+ 2);
332 for (n
= 1; n
+ 1 < cnt
; ++n
)
333 total
+= (1UL << (cnt
- 3)) * (temp
[n
].len
+ 1);
336 /* The result structure: we use a very compressed way to store the
337 various combinations of capability names. */
339 result
= (struct r_strlenpair
*) malloc (*sz
* sizeof (*result
) + total
);
345 result
[0].str
= (char *) (result
+ *sz
);
346 result
[0].len
= temp
[0].len
+ 1;
347 result
[1].str
= (char *) (result
+ *sz
);
349 cp
= __mempcpy ((char *) (result
+ *sz
), temp
[0].str
, temp
[0].len
);
352 *max_capstrlen
= result
[0].len
;
357 /* Fill in the information. This follows the following scheme
358 (indeces from TEMP for four strings):
359 entry #0: 0, 1, 2, 3 binary: 1111
363 This allows the representation of all possible combinations of
364 capability names in the string. First generate the strings. */
365 result
[1].str
= result
[0].str
= cp
= (char *) (result
+ *sz
);
367 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
380 /* We always add the last string. */
383 /* Add the strings which have the bit set in N. */
384 for (m
= cnt
- 2; m
> 0; --m
)
385 if ((n
& (1 << m
)) != 0)
388 /* Always add the first string. */
395 /* Now we are ready to install the string pointers and length. */
396 for (n
= 0; n
< (1UL << cnt
); ++n
)
401 size_t mask
= 1 << --n
;
404 for (m
= 1 << cnt
; m
> 0; ++rp
)
405 if ((--m
& mask
) != 0)
406 rp
->len
+= temp
[n
].len
+ 1;
410 /* The first half of the strings all include the first string. */
413 while (n
!= (1UL << (cnt
- 1)))
416 rp
[0].str
= rp
[-2].str
+ rp
[-2].len
;
418 rp
[0].str
= rp
[-1].str
;
422 /* The second have starts right after the first part of the string of
423 corresponding entry in the first half. */
426 rp
[0].str
= rp
[-(1 << (cnt
- 1))].str
+ temp
[cnt
- 1].len
+ 1;
431 /* The maximum string length. */
432 *max_capstrlen
= result
[0].len
;