Update.
[glibc.git] / sysdeps / generic / dl-sysdep.c
blob4f2a2f6da3aea28cc2197d9500fce48e25950cca
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. */
20 #include <elf.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/mman.h>
29 #include <elf/ldsodefs.h>
30 #include <stdio-common/_itoa.h>
31 #include <fpu_control.h>
33 #include <entry.h>
34 #include <dl-machine.h>
35 #include <dl-procinfo.h>
37 extern int _dl_argc;
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;
45 extern void _end;
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
51 of init-first. */
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) \
60 do { \
61 void **_tmp; \
62 (argc) = *(long *) cookie; \
63 (argv) = (char **) cookie + 1; \
64 (envp) = (argv) + (argc) + 1; \
65 for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
66 continue; \
67 (auxp) = (void *) ++_tmp; \
68 } while (0)
69 #endif
72 ElfW(Addr)
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;
78 ElfW(Word) phnum = 0;
79 ElfW(Addr) user_entry;
80 ElfW(auxv_t) *av;
81 uid_t uid = 0;
82 uid_t euid = 0;
83 gid_t gid = 0;
84 gid_t egid = 0;
85 unsigned int seen;
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. */
92 seen = 0;
93 #define M(type) (1 << (type))
95 for (av = _dl_auxv; av->a_type != AT_NULL; seen |= M ((++av)->a_type))
96 switch (av->a_type)
98 case AT_PHDR:
99 phdr = av->a_un.a_ptr;
100 break;
101 case AT_PHNUM:
102 phnum = av->a_un.a_val;
103 break;
104 case AT_PAGESZ:
105 _dl_pagesize = av->a_un.a_val;
106 break;
107 case AT_ENTRY:
108 user_entry = av->a_un.a_val;
109 break;
110 case AT_BASE:
111 _dl_base_addr = av->a_un.a_val;
112 break;
113 case AT_UID:
114 uid = av->a_un.a_val;
115 break;
116 case AT_GID:
117 gid = av->a_un.a_val;
118 break;
119 case AT_EUID:
120 euid = av->a_un.a_val;
121 break;
122 case AT_EGID:
123 egid = av->a_un.a_val;
124 break;
125 case AT_PLATFORM:
126 _dl_platform = av->a_un.a_ptr;
127 break;
128 case AT_HWCAP:
129 _dl_hwcap = av->a_un.a_val;
130 break;
131 case AT_FPUCW:
132 _dl_fpu_control = av->a_un.a_val;
133 break;
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 ()
140 SEE (UID, uid);
141 SEE (GID, gid);
142 SEE (EUID, euid);
143 SEE (EGID, egid);
145 __libc_enable_secure = uid != euid || gid != egid;
147 if (_dl_pagesize == 0)
148 _dl_pagesize = __getpagesize ();
150 #ifdef DL_SYSDEP_INIT
151 DL_SYSDEP_INIT;
152 #endif
154 #ifdef DL_PLATFORM_INIT
155 DL_PLATFORM_INIT;
156 #endif
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);
171 return user_entry;
174 void
175 _dl_sysdep_start_cleanup (void)
179 void
180 internal_function
181 _dl_show_auxv (void)
183 char buf[64];
184 ElfW(auxv_t) *av;
186 /* Terminate string. */
187 buf[63] = '\0';
189 for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
190 switch (av->a_type)
192 case AT_PHDR:
193 _dl_sysdep_message ("AT_PHDR: 0x",
194 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
195 16, 0),
196 "\n", NULL);
197 break;
198 case AT_PHNUM:
199 _dl_sysdep_message ("AT_PHNUM: ",
200 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
201 10, 0),
202 "\n", NULL);
203 break;
204 case AT_PAGESZ:
205 _dl_sysdep_message ("AT_PAGESZ: ",
206 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
207 10, 0),
208 "\n", NULL);
209 break;
210 case AT_ENTRY:
211 _dl_sysdep_message ("AT_ENTRY: 0x",
212 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
213 16, 0),
214 "\n", NULL);
215 break;
216 case AT_BASE:
217 _dl_sysdep_message ("AT_BASE: 0x",
218 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
219 16, 0),
220 "\n", NULL);
221 break;
222 case AT_UID:
223 _dl_sysdep_message ("AT_UID: ",
224 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
225 10, 0),
226 "\n", NULL);
227 break;
228 case AT_GID:
229 _dl_sysdep_message ("AT_GID: ",
230 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
231 10, 0),
232 "\n", NULL);
233 break;
234 case AT_EUID:
235 _dl_sysdep_message ("AT_EUID: ",
236 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
237 10, 0),
238 "\n", NULL);
239 break;
240 case AT_EGID:
241 _dl_sysdep_message ("AT_EGID: ",
242 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
243 10, 0),
244 "\n", NULL);
245 break;
246 case AT_PLATFORM:
247 _dl_sysdep_message ("AT_PLATFORM: ", av->a_un.a_ptr, "\n", NULL);
248 break;
249 case AT_HWCAP:
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,
254 16, 0),
255 "\n", NULL);
256 break;
257 case AT_FPUCW:
258 _dl_sysdep_message ("AT_FPUCW: ",
259 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
260 10, 0),
261 "\n", NULL);
262 break;
267 /* Return an array of useful/necessary hardware capability names. */
268 const struct r_strlenpair *
269 internal_function
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;
276 size_t n, m;
277 size_t total;
278 struct r_strlenpair *temp;
279 struct r_strlenpair *result;
280 struct r_strlenpair *rp;
281 char *cp;
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)
286 ++cnt;
288 if (cnt == 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));
293 if (result == NULL)
295 no_memory:
296 _dl_signal_error (ENOMEM, NULL, "cannot create capability list");
299 result[0].str = (char *) result; /* Does not really matter. */
300 result[0].len = 0;
302 *sz = 1;
303 return result;
306 /* Create temporary data structure to generate result table. */
307 temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
308 m = 0;
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);
314 masked ^= 1UL << n;
315 ++m;
317 if (platform != NULL)
319 temp[m].str = platform;
320 temp[m].len = platform_len;
321 ++m;
324 /* Determine the total size of all strings together. */
325 if (cnt == 1)
326 total = temp[0].len;
327 else
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. */
336 *sz = 1 << cnt;
337 result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
338 if (result == NULL)
339 goto no_memory;
341 if (cnt == 1)
343 result[0].str = (char *) (result + *sz);
344 result[0].len = temp[0].len + 1;
345 result[1].str = (char *) (result + *sz);
346 result[1].len = 0;
347 cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
348 *cp = '/';
349 *sz = 2;
350 *max_capstrlen = result[0].len;
352 return result;
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
358 #1: 0, 1, 3 1101
359 #2: 0, 2, 3 1011
360 #3: 0, 3 1001
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);
364 #define add(idx) \
365 cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
366 if (cnt == 2)
368 add (1);
369 add (0);
371 else
373 n = 1 << cnt;
376 n -= 2;
378 /* We always add the last string. */
379 add (cnt - 1);
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)
384 add (m);
386 /* Always add the first string. */
387 add (0);
389 while (n != 0);
391 #undef add
393 /* Now we are ready to install the string pointers and length. */
394 for (n = 0; n < (1 << cnt); ++n)
395 result[n].len = 0;
396 n = cnt;
399 size_t mask = 1 << --n;
401 rp = result;
402 for (m = 1 << cnt; m > 0; ++rp)
403 if ((--m & mask) != 0)
404 rp->len += temp[n].len + 1;
406 while (n != 0);
408 /* The first half of the strings all include the first string. */
409 n = (1 << cnt) - 2;
410 rp = &result[2];
411 while (n != (1 << (cnt - 1)))
413 if ((n & 1) != 0)
414 rp[0].str = rp[-2].str + rp[-2].len;
415 else
416 rp[0].str = rp[-1].str;
417 ++rp;
418 --n;
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;
426 ++rp;
428 while (--n != 0);
430 /* The maximum string length. */
431 *max_capstrlen = result[0].len;
433 return result;