Update.
[platform/upstream/glibc.git] / sysdeps / generic / dl-sysdep.c
1 /* Operating system support for run-time dynamic linker.  Generic Unix version.
2    Copyright (C) 1995-1998, 2000-2002, 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
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.
9
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.
14
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
18    02111-1307 USA.  */
19
20 #include <assert.h>
21 #include <elf.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <libintl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/mman.h>
31 #include <ldsodefs.h>
32 #include <stdio-common/_itoa.h>
33 #include <fpu_control.h>
34
35 #include <entry.h>
36 #include <dl-machine.h>
37 #include <dl-procinfo.h>
38 #include <dl-osinfo.h>
39 #include <hp-timing.h>
40 #include <tls.h>
41
42 extern char **_environ attribute_hidden;
43 extern void _end attribute_hidden;
44
45 /* Protect SUID program against misuse of file descriptors.  */
46 extern void __libc_check_standard_fds (void);
47
48 #ifdef NEED_DL_BASE_ADDR
49 ElfW(Addr) _dl_base_addr;
50 #endif
51 int __libc_enable_secure = 0;
52 INTVARDEF(__libc_enable_secure)
53 int __libc_multiple_libcs = 0;  /* Defining this here avoids the inclusion
54                                    of init-first.  */
55 /* This variable contains the lowest stack address ever used.  */
56 void *__libc_stack_end;
57 static ElfW(auxv_t) *_dl_auxv;
58
59 #ifndef DL_FIND_ARG_COMPONENTS
60 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
61   do {                                                                        \
62     void **_tmp;                                                              \
63     (argc) = *(long int *) cookie;                                            \
64     (argv) = (char **) ((long int *) cookie + 1);                             \
65     (envp) = (argv) + (argc) + 1;                                             \
66     for (_tmp = (void **) (envp); *_tmp; ++_tmp)                              \
67       continue;                                                               \
68     (auxp) = (void *) ++_tmp;                                                 \
69   } while (0)
70 #endif
71
72
73 ElfW(Addr)
74 _dl_sysdep_start (void **start_argptr,
75                   void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
76                                    ElfW(Addr) *user_entry))
77 {
78   const ElfW(Phdr) *phdr = NULL;
79   ElfW(Word) phnum = 0;
80   ElfW(Addr) user_entry;
81   ElfW(auxv_t) *av;
82   uid_t uid = 0;
83   gid_t gid = 0;
84 #ifdef HAVE_AUX_XID
85 # define set_seen(tag) (tag) /* Evaluate for the side effects.  */
86 #else
87   unsigned int seen = 0;
88 # define M(type) (1 << (type))
89 # define set_seen(tag) seen |= M ((tag)->a_type)
90 #endif
91
92   DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ,
93                           _dl_auxv);
94
95   user_entry = (ElfW(Addr)) ENTRY_POINT;
96   GL(dl_platform) = NULL; /* Default to nothing known about the platform.  */
97
98   for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++))
99     switch (av->a_type)
100       {
101       case AT_PHDR:
102         phdr = av->a_un.a_ptr;
103         break;
104       case AT_PHNUM:
105         phnum = av->a_un.a_val;
106         break;
107       case AT_PAGESZ:
108         GL(dl_pagesize) = av->a_un.a_val;
109         break;
110       case AT_ENTRY:
111         user_entry = av->a_un.a_val;
112         break;
113 #ifdef NEED_DL_BASE_ADDR
114       case AT_BASE:
115         _dl_base_addr = av->a_un.a_val;
116         break;
117 #endif
118       case AT_UID:
119       case AT_EUID:
120         uid ^= av->a_un.a_val;
121         break;
122       case AT_GID:
123       case AT_EGID:
124         gid ^= av->a_un.a_val;
125         break;
126       case AT_PLATFORM:
127         GL(dl_platform) = av->a_un.a_ptr;
128         break;
129       case AT_HWCAP:
130         GL(dl_hwcap) = av->a_un.a_val;
131         break;
132       case AT_CLKTCK:
133         GL(dl_clktck) = av->a_un.a_val;
134         break;
135       case AT_FPUCW:
136         GL(dl_fpu_control) = av->a_un.a_val;
137         break;
138 #ifdef NEED_DL_SYSINFO
139       case AT_SYSINFO:
140         GL(dl_sysinfo) = av->a_un.a_val;
141         break;
142       case AT_SYSINFO_EHDR:
143         GL(dl_sysinfo_dso) = av->a_un.a_ptr;
144         break;
145 #endif
146 #ifdef DL_PLATFORM_AUXV
147       DL_PLATFORM_AUXV
148 #endif
149       }
150
151 #ifdef DL_SYSDEP_OSCHECK
152   DL_SYSDEP_OSCHECK (dl_fatal);
153 #endif
154
155   /* Fill in the values we have not gotten from the kernel through the
156      auxiliary vector.  */
157 #ifndef HAVE_AUX_XID
158 # define SEE(UID, var, uid) \
159    if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
160   SEE (UID, uid, uid);
161   SEE (EUID, uid, euid);
162   SEE (GID, gid, gid);
163   SEE (EGID, gid, egid);
164 #endif
165
166   /* If one of the two pairs of IDs does not match this is a setuid
167      or setgid run.  */
168   INTUSE(__libc_enable_secure) = uid | gid;
169
170 #ifndef HAVE_AUX_PAGESIZE
171   if (GL(dl_pagesize) == 0)
172     GL(dl_pagesize) = __getpagesize ();
173 #endif
174
175 #ifdef DL_SYSDEP_INIT
176   DL_SYSDEP_INIT;
177 #endif
178
179 #ifdef DL_PLATFORM_INIT
180   DL_PLATFORM_INIT;
181 #endif
182
183   /* Determine the length of the platform name.  */
184   if (GL(dl_platform) != NULL)
185     GL(dl_platformlen) = strlen (GL(dl_platform));
186
187   if (__sbrk (0) == &_end)
188     /* The dynamic linker was run as a program, and so the initial break
189        starts just after our bss, at &_end.  The malloc in dl-minimal.c
190        will consume the rest of this page, so tell the kernel to move the
191        break up that far.  When the user program examines its break, it
192        will see this new value and not clobber our data.  */
193     __sbrk (GL(dl_pagesize) - ((&_end - (void *) 0) & (GL(dl_pagesize) - 1)));
194
195   /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
196      allocated.  If necessary we are doing it ourself.  If it is not
197      possible we stop the program.  */
198   if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
199     __libc_check_standard_fds ();
200
201   (*dl_main) (phdr, phnum, &user_entry);
202   return user_entry;
203 }
204
205 void
206 internal_function
207 _dl_sysdep_start_cleanup (void)
208 {
209 }
210
211 void
212 internal_function
213 _dl_show_auxv (void)
214 {
215   char buf[64];
216   ElfW(auxv_t) *av;
217
218   /* Terminate string.  */
219   buf[63] = '\0';
220
221   /* The following code assumes that the AT_* values are encoded
222      starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
223      close by (otherwise the array will be too large).  In case we have
224      to support a platform where these requirements are not fulfilled
225      some alternative implementation has to be used.  */
226   for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
227     {
228       static const struct
229       {
230         const char label[20];
231         enum { dec, hex, str } form;
232       } auxvars[] =
233         {
234           [AT_EXECFD - 2] =             { "AT_EXECFD:       ", dec },
235           [AT_PHDR - 2] =               { "AT_PHDR:         0x", hex },
236           [AT_PHENT - 2] =              { "AT_PHENT:        ", dec },
237           [AT_PHNUM - 2] =              { "AT_PHNUM:        ", dec },
238           [AT_PAGESZ - 2] =             { "AT_PAGESZ:       ", dec },
239           [AT_BASE - 2] =               { "AT_BASE:         0x", hex },
240           [AT_FLAGS - 2] =              { "AT_FLAGS:        0x", hex },
241           [AT_ENTRY - 2] =              { "AT_ENTRY:        0x", hex },
242           [AT_NOTELF - 2] =             { "AT_NOTELF:       ", hex },
243           [AT_UID - 2] =                { "AT_UID:          ", dec },
244           [AT_EUID - 2] =               { "AT_EUID:         ", dec },
245           [AT_GID - 2] =                { "AT_GID:          ", dec },
246           [AT_EGID - 2] =               { "AT_EGID:         ", dec },
247           [AT_PLATFORM - 2] =           { "AT_PLATFORM:     ", str },
248           [AT_HWCAP - 2] =              { "AT_HWCAP:        ", hex },
249           [AT_CLKTCK - 2] =             { "AT_CLKTCK:       ", dec },
250           [AT_FPUCW - 2] =              { "AT_FPUCW:        ", hex },
251           [AT_DCACHEBSIZE - 2] =        { "AT_DCACHEBSIZE:  0x", hex },
252           [AT_ICACHEBSIZE - 2] =        { "AT_ICACHEBSIZE:  0x", hex },
253           [AT_UCACHEBSIZE - 2] =        { "AT_UCACHEBSIZE:  0x", hex },
254 #ifdef NEED_DL_SYSINFO
255           [AT_SYSINFO - 2] =            { "AT_SYSINFO:      0x", hex },
256           [AT_SYSINFO_EHDR - 2] =       { "AT_SYSINFO_EHDR: 0x", hex }
257 #endif
258         };
259       unsigned int idx = (unsigned int) (av->a_type - 2);
260
261       assert (AT_NULL == 0);
262       assert (AT_IGNORE == 1);
263
264       if (av->a_type == AT_HWCAP)
265         {
266           /* This is handled special.  */
267           if (_dl_procinfo (av->a_un.a_val) == 0)
268             continue;
269         }
270
271       if (idx < sizeof (auxvars) / sizeof (auxvars[0]))
272         {
273           const char *val = av->a_un.a_ptr;
274
275           if (__builtin_expect (auxvars[idx].form, dec) == dec)
276             val = _itoa ((unsigned long int) av->a_un.a_val,
277                          buf + sizeof buf - 1, 10, 0);
278           else if (__builtin_expect (auxvars[idx].form, hex) == hex)
279             val = _itoa ((unsigned long int) av->a_un.a_val,
280                          buf + sizeof buf - 1, 16, 0);
281
282           _dl_printf ("%s%s\n", auxvars[idx].label, val);
283
284           continue;
285         }
286
287       /* Unknown value: print a generic line.  */
288       char buf2[17];
289       buf[sizeof (buf2) - 1] = '\0';
290       const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
291                                 buf2 + sizeof buf2 - 1, 16, 0);
292       const char *val =  _itoa ((unsigned long int) av->a_type,
293                                 buf + sizeof buf - 1, 16, 0);
294       _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
295     }
296 }
297
298
299 /* Return an array of useful/necessary hardware capability names.  */
300 const struct r_strlenpair *
301 internal_function
302 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
303                       size_t *max_capstrlen)
304 {
305   /* Determine how many important bits are set.  */
306   unsigned long int masked = GL(dl_hwcap) & GL(dl_hwcap_mask);
307   size_t cnt = platform != NULL;
308   size_t n, m;
309   size_t total;
310   struct r_strlenpair *temp;
311   struct r_strlenpair *result;
312   struct r_strlenpair *rp;
313   char *cp;
314
315   /* Count the number of bits set in the masked value.  */
316   for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
317     if ((masked & (1UL << n)) != 0)
318       ++cnt;
319
320 #ifdef USE_TLS
321   /* For TLS enabled builds always add 'tls'.  */
322   ++cnt;
323 #else
324   if (cnt == 0)
325     {
326       /* If we have platform name and no important capability we only have
327          the base directory to search.  */
328       result = (struct r_strlenpair *) malloc (sizeof (*result));
329       if (result == NULL)
330         goto no_memory;
331
332       result[0].str = (char *) result;  /* Does not really matter.  */
333       result[0].len = 0;
334
335       *sz = 1;
336       return result;
337     }
338 #endif
339
340   /* Create temporary data structure to generate result table.  */
341   temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
342   m = 0;
343   for (n = 0; masked != 0; ++n)
344     if ((masked & (1UL << n)) != 0)
345       {
346         temp[m].str = _dl_hwcap_string (n);
347         temp[m].len = strlen (temp[m].str);
348         masked ^= 1UL << n;
349         ++m;
350       }
351   if (platform != NULL)
352     {
353       temp[m].str = platform;
354       temp[m].len = platform_len;
355       ++m;
356     }
357 #ifdef USE_TLS
358   temp[m].str = "tls";
359   temp[m].len = 3;
360   ++m;
361 #endif
362   assert (m == cnt);
363
364   /* Determine the total size of all strings together.  */
365   if (cnt == 1)
366     total = temp[0].len + 1;
367   else
368     {
369       total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
370       for (n = 1; n + 1 < cnt; ++n)
371         total += (1UL << (cnt - 3)) * (temp[n].len + 1);
372     }
373
374   /* The result structure: we use a very compressed way to store the
375      various combinations of capability names.  */
376   *sz = 1 << cnt;
377   result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
378   if (result == NULL)
379     {
380 #ifndef USE_TLS
381     no_memory:
382 #endif
383       INTUSE(_dl_signal_error) (ENOMEM, NULL, NULL,
384                                 N_("cannot create capability list"));
385     }
386
387   if (cnt == 1)
388     {
389       result[0].str = (char *) (result + *sz);
390       result[0].len = temp[0].len + 1;
391       result[1].str = (char *) (result + *sz);
392       result[1].len = 0;
393       cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
394       *cp = '/';
395       *sz = 2;
396       *max_capstrlen = result[0].len;
397
398       return result;
399     }
400
401   /* Fill in the information.  This follows the following scheme
402      (indeces from TEMP for four strings):
403         entry #0: 0, 1, 2, 3    binary: 1111
404               #1: 0, 1, 3               1101
405               #2: 0, 2, 3               1011
406               #3: 0, 3                  1001
407      This allows the representation of all possible combinations of
408      capability names in the string.  First generate the strings.  */
409   result[1].str = result[0].str = cp = (char *) (result + *sz);
410 #define add(idx) \
411       cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
412   if (cnt == 2)
413     {
414       add (1);
415       add (0);
416     }
417   else
418     {
419       n = 1 << cnt;
420       do
421         {
422           n -= 2;
423
424           /* We always add the last string.  */
425           add (cnt - 1);
426
427           /* Add the strings which have the bit set in N.  */
428           for (m = cnt - 2; m > 0; --m)
429             if ((n & (1 << m)) != 0)
430               add (m);
431
432           /* Always add the first string.  */
433           add (0);
434         }
435       while (n != 0);
436     }
437 #undef add
438
439   /* Now we are ready to install the string pointers and length.  */
440   for (n = 0; n < (1UL << cnt); ++n)
441     result[n].len = 0;
442   n = cnt;
443   do
444     {
445       size_t mask = 1 << --n;
446
447       rp = result;
448       for (m = 1 << cnt; m > 0; ++rp)
449         if ((--m & mask) != 0)
450           rp->len += temp[n].len + 1;
451     }
452   while (n != 0);
453
454   /* The first half of the strings all include the first string.  */
455   n = (1 << cnt) - 2;
456   rp = &result[2];
457   while (n != (1UL << (cnt - 1)))
458     {
459       if ((--n & 1) != 0)
460         rp[0].str = rp[-2].str + rp[-2].len;
461       else
462         rp[0].str = rp[-1].str;
463       ++rp;
464     }
465
466   /* The second have starts right after the first part of the string of
467      corresponding entry in the first half.  */
468   do
469     {
470       rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
471       ++rp;
472     }
473   while (--n != 0);
474
475   /* The maximum string length.  */
476   *max_capstrlen = result[0].len;
477
478   return result;
479 }