(DL_FIND_ARG_COMPONENTS): Provide default macro to track down
[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, 1996, 1997 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 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.
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    Library General Public License for more details.
14
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.  */
19
20 #include <elf.h>
21 #include <entry.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/mman.h>
25 #include <fcntl.h>
26 #include <link.h>
27 #include <unistd.h>
28 #include <stdio-common/_itoa.h>
29
30 #include <dl-machine.h>
31
32 extern int _dl_argc;
33 extern char **_dl_argv;
34 extern char **_environ;
35 extern size_t _dl_pagesize;
36 extern const char *_dl_platform;
37 extern unsigned long _dl_hwcap;
38 extern size_t _dl_platformlen;
39 extern void _end;
40 extern void ENTRY_POINT (void);
41
42 ElfW(Addr) _dl_base_addr;
43 int __libc_enable_secure;
44 int __libc_multiple_libcs;      /* Defining this here avoids the inclusion
45                                    of init-first.  */
46 static ElfW(auxv_t) *_dl_auxv;
47
48
49 #ifndef DL_FIND_ARG_COMPONENTS
50 #define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp)  \
51   do {                                                          \
52     void **_tmp;                                                \
53     (argc) = *(long *) cookie;                                  \
54     (argv) = (char **) cookie + 1;                              \
55     (envp) = (argv) + (argc) + 1;                               \
56     for (_tmp = (void **) (envp); *_tmp; ++_tmp)                \
57       continue;                                                 \
58     (auxp) = (void *) ++_tmp;                                   \
59   } while (0)
60 #endif
61
62
63 ElfW(Addr)
64 _dl_sysdep_start (void **start_argptr,
65                   void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
66                                    ElfW(Addr) *user_entry))
67 {
68   const ElfW(Phdr) *phdr = NULL;
69   ElfW(Word) phnum = 0;
70   ElfW(Addr) user_entry;
71   ElfW(auxv_t) *av;
72   uid_t uid = 0;
73   uid_t euid = 0;
74   gid_t gid = 0;
75   gid_t egid = 0;
76   unsigned int seen;
77
78   DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ, _dl_auxv);
79
80   user_entry = (ElfW(Addr)) &ENTRY_POINT;
81   _dl_platform = NULL; /* Default to nothing known about the platform.  */
82
83   seen = 0;
84 #define M(type) (1 << (type))
85
86   for (av = _dl_auxv; av->a_type != AT_NULL; seen |= M ((++av)->a_type))
87     switch (av->a_type)
88       {
89       case AT_PHDR:
90         phdr = av->a_un.a_ptr;
91         break;
92       case AT_PHNUM:
93         phnum = av->a_un.a_val;
94         break;
95       case AT_PAGESZ:
96         _dl_pagesize = av->a_un.a_val;
97         break;
98       case AT_ENTRY:
99         user_entry = av->a_un.a_val;
100         break;
101       case AT_BASE:
102         _dl_base_addr = av->a_un.a_val;
103         break;
104       case AT_UID:
105         uid = av->a_un.a_val;
106         break;
107       case AT_GID:
108         gid = av->a_un.a_val;
109         break;
110       case AT_EUID:
111         euid = av->a_un.a_val;
112         break;
113       case AT_EGID:
114         egid = av->a_un.a_val;
115         break;
116       case AT_PLATFORM:
117         _dl_platform = av->a_un.a_ptr;
118         break;
119       case AT_HWCAP:
120         _dl_hwcap = av->a_un.a_val;
121         break;
122       }
123
124   /* Linux doesn't provide us with any of these values on the stack
125      when the dynamic linker is run directly as a program.  */
126
127 #define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
128   SEE (UID, uid);
129   SEE (GID, gid);
130   SEE (EUID, euid);
131   SEE (EGID, egid);
132
133
134   __libc_enable_secure = uid != euid || gid != egid;
135
136   if (_dl_pagesize == 0)
137     _dl_pagesize = __getpagesize ();
138
139 #ifdef DL_SYSDEP_INIT
140   DL_SYSDEP_INIT;
141 #endif
142
143 #ifdef DL_PLATFORM_INIT
144   DL_PLATFORM_INIT;
145 #endif
146
147   /* Determine the length of the platform name.  */
148   if (_dl_platform != NULL)
149     _dl_platformlen = strlen (_dl_platform);
150
151   if (__sbrk (0) == &_end)
152     /* The dynamic linker was run as a program, and so the initial break
153        starts just after our bss, at &_end.  The malloc in dl-minimal.c
154        will consume the rest of this page, so tell the kernel to move the
155        break up that far.  When the user program examines its break, it
156        will see this new value and not clobber our data.  */
157     __sbrk (_dl_pagesize - ((&_end - (void *) 0) & (_dl_pagesize - 1)));
158
159   (*dl_main) (phdr, phnum, &user_entry);
160   return user_entry;
161 }
162
163 void
164 _dl_sysdep_start_cleanup (void)
165 {
166 }
167
168 void
169 _dl_show_auxv (void)
170 {
171   char buf[64];
172   ElfW(auxv_t) *av;
173
174   /* Terminate string.  */
175   buf[63] = '\0';
176
177   for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
178     switch (av->a_type)
179       {
180       case AT_PHDR:
181         _dl_sysdep_message ("AT_PHDR:     0x",
182                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
183                                         16, 0),
184                             "\n", NULL);
185         break;
186       case AT_PHNUM:
187         _dl_sysdep_message ("AT_PHNUM:    ",
188                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
189                                         10, 0),
190                             "\n", NULL);
191         break;
192       case AT_PAGESZ:
193         _dl_sysdep_message ("AT_PAGESZ:   ",
194                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
195                                         10, 0),
196                             "\n", NULL);
197         break;
198       case AT_ENTRY:
199         _dl_sysdep_message ("AT_ENTRY:    0x",
200                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
201                                         16, 0),
202                             "\n", NULL);
203         break;
204       case AT_BASE:
205         _dl_sysdep_message ("AT_BASE:    0x",
206                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
207                                         16, 0),
208                             "\n", NULL);
209         break;
210       case AT_UID:
211         _dl_sysdep_message ("AT_UID:      ",
212                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
213                                         10, 0),
214                             "\n", NULL);
215         break;
216       case AT_GID:
217         _dl_sysdep_message ("AT_GID:      ",
218                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
219                                         10, 0),
220                             "\n", NULL);
221         break;
222       case AT_EUID:
223         _dl_sysdep_message ("AT_EUID:     ",
224                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
225                                         10, 0),
226                             "\n", NULL);
227         break;
228       case AT_EGID:
229         _dl_sysdep_message ("AT_EGID:     ",
230                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
231                                         10, 0),
232                             "\n", NULL);
233         break;
234       case AT_PLATFORM:
235         _dl_sysdep_message ("AT_PLATFORM: ", av->a_un.a_ptr, NULL);
236         break;
237       case AT_HWCAP:
238         _dl_sysdep_message ("AT_HWCAP:    ",
239                             _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
240                                         16, 0),
241                             "\n", NULL);
242         break;
243       }
244 }