a0e6736b2225040f53286b591d498b36afe49456
[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       if (idx < sizeof (auxvars) / sizeof (auxvars[0]))
264         {
265           if (av->a_type != AT_HWCAP || _dl_procinfo (av->a_un.a_val) < 0)
266             {
267               const char *val = av->a_un.a_ptr;
268
269               if (__builtin_expect (auxvars[idx].form, dec) == dec)
270                 val = _itoa ((unsigned long int) av->a_un.a_val,
271                              buf + sizeof buf - 1, 10, 0);
272               else if (__builtin_expect (auxvars[idx].form, hex) == hex)
273                 val = _itoa ((unsigned long int) av->a_un.a_val,
274                              buf + sizeof buf - 1, 16, 0);
275
276               _dl_printf ("%s%s\n", auxvars[idx].label, val);
277
278               continue;
279             }
280         }
281
282       /* Unknown value: print a generic line.  */
283       char buf2[17];
284       buf[sizeof (buf2) - 1] = '\0';
285       const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
286                                 buf2 + sizeof buf2 - 1, 16, 0);
287       const char *val =  _itoa ((unsigned long int) av->a_type,
288                                 buf + sizeof buf - 1, 16, 0);
289       _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
290     }
291 }
292
293
294 /* Return an array of useful/necessary hardware capability names.  */
295 const struct r_strlenpair *
296 internal_function
297 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
298                       size_t *max_capstrlen)
299 {
300   /* Determine how many important bits are set.  */
301   unsigned long int masked = GL(dl_hwcap) & GL(dl_hwcap_mask);
302   size_t cnt = platform != NULL;
303   size_t n, m;
304   size_t total;
305   struct r_strlenpair *temp;
306   struct r_strlenpair *result;
307   struct r_strlenpair *rp;
308   char *cp;
309
310   /* Count the number of bits set in the masked value.  */
311   for (n = 0; (~((1UL << n) - 1) & masked) != 0; ++n)
312     if ((masked & (1UL << n)) != 0)
313       ++cnt;
314
315 #ifdef USE_TLS
316   /* For TLS enabled builds always add 'tls'.  */
317   ++cnt;
318 #else
319   if (cnt == 0)
320     {
321       /* If we have platform name and no important capability we only have
322          the base directory to search.  */
323       result = (struct r_strlenpair *) malloc (sizeof (*result));
324       if (result == NULL)
325         goto no_memory;
326
327       result[0].str = (char *) result;  /* Does not really matter.  */
328       result[0].len = 0;
329
330       *sz = 1;
331       return result;
332     }
333 #endif
334
335   /* Create temporary data structure to generate result table.  */
336   temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
337   m = 0;
338   for (n = 0; masked != 0; ++n)
339     if ((masked & (1UL << n)) != 0)
340       {
341         temp[m].str = _dl_hwcap_string (n);
342         temp[m].len = strlen (temp[m].str);
343         masked ^= 1UL << n;
344         ++m;
345       }
346   if (platform != NULL)
347     {
348       temp[m].str = platform;
349       temp[m].len = platform_len;
350       ++m;
351     }
352 #ifdef USE_TLS
353   temp[m].str = "tls";
354   temp[m].len = 3;
355   ++m;
356 #endif
357   assert (m == cnt);
358
359   /* Determine the total size of all strings together.  */
360   if (cnt == 1)
361     total = temp[0].len + 1;
362   else
363     {
364       total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2);
365       for (n = 1; n + 1 < cnt; ++n)
366         total += (1UL << (cnt - 3)) * (temp[n].len + 1);
367     }
368
369   /* The result structure: we use a very compressed way to store the
370      various combinations of capability names.  */
371   *sz = 1 << cnt;
372   result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
373   if (result == NULL)
374     {
375 #ifndef USE_TLS
376     no_memory:
377 #endif
378       INTUSE(_dl_signal_error) (ENOMEM, NULL, NULL,
379                                 N_("cannot create capability list"));
380     }
381
382   if (cnt == 1)
383     {
384       result[0].str = (char *) (result + *sz);
385       result[0].len = temp[0].len + 1;
386       result[1].str = (char *) (result + *sz);
387       result[1].len = 0;
388       cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
389       *cp = '/';
390       *sz = 2;
391       *max_capstrlen = result[0].len;
392
393       return result;
394     }
395
396   /* Fill in the information.  This follows the following scheme
397      (indeces from TEMP for four strings):
398         entry #0: 0, 1, 2, 3    binary: 1111
399               #1: 0, 1, 3               1101
400               #2: 0, 2, 3               1011
401               #3: 0, 3                  1001
402      This allows the representation of all possible combinations of
403      capability names in the string.  First generate the strings.  */
404   result[1].str = result[0].str = cp = (char *) (result + *sz);
405 #define add(idx) \
406       cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
407   if (cnt == 2)
408     {
409       add (1);
410       add (0);
411     }
412   else
413     {
414       n = 1 << cnt;
415       do
416         {
417           n -= 2;
418
419           /* We always add the last string.  */
420           add (cnt - 1);
421
422           /* Add the strings which have the bit set in N.  */
423           for (m = cnt - 2; m > 0; --m)
424             if ((n & (1 << m)) != 0)
425               add (m);
426
427           /* Always add the first string.  */
428           add (0);
429         }
430       while (n != 0);
431     }
432 #undef add
433
434   /* Now we are ready to install the string pointers and length.  */
435   for (n = 0; n < (1UL << cnt); ++n)
436     result[n].len = 0;
437   n = cnt;
438   do
439     {
440       size_t mask = 1 << --n;
441
442       rp = result;
443       for (m = 1 << cnt; m > 0; ++rp)
444         if ((--m & mask) != 0)
445           rp->len += temp[n].len + 1;
446     }
447   while (n != 0);
448
449   /* The first half of the strings all include the first string.  */
450   n = (1 << cnt) - 2;
451   rp = &result[2];
452   while (n != (1UL << (cnt - 1)))
453     {
454       if ((--n & 1) != 0)
455         rp[0].str = rp[-2].str + rp[-2].len;
456       else
457         rp[0].str = rp[-1].str;
458       ++rp;
459     }
460
461   /* The second have starts right after the first part of the string of
462      corresponding entry in the first half.  */
463   do
464     {
465       rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
466       ++rp;
467     }
468   while (--n != 0);
469
470   /* The maximum string length.  */
471   *max_capstrlen = result[0].len;
472
473   return result;
474 }