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