Update.
[glibc.git] / sysdeps / generic / dl-sysdep.c
blobb2ae75cc9e21abb92ff6424a7188acb9b1c8efcd
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.
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 <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>
30 #include <dl-machine.h>
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);
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;
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
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))
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;
78 DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ, _dl_auxv);
80 user_entry = (ElfW(Addr)) &ENTRY_POINT;
81 _dl_platform = NULL; /* Default to nothing known about the platform. */
83 seen = 0;
84 #define M(type) (1 << (type))
86 for (av = _dl_auxv; av->a_type != AT_NULL; seen |= M ((++av)->a_type))
87 switch (av->a_type)
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;
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. */
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);
133 __libc_enable_secure = uid != euid || gid != egid;
135 if (_dl_pagesize == 0)
136 _dl_pagesize = __getpagesize ();
138 #ifdef DL_SYSDEP_INIT
139 DL_SYSDEP_INIT;
140 #endif
142 #ifdef DL_PLATFORM_INIT
143 DL_PLATFORM_INIT;
144 #endif
146 /* Determine the length of the platform name. */
147 if (_dl_platform != NULL)
148 _dl_platformlen = strlen (_dl_platform);
150 if (__sbrk (0) == &_end)
151 /* The dynamic linker was run as a program, and so the initial break
152 starts just after our bss, at &_end. The malloc in dl-minimal.c
153 will consume the rest of this page, so tell the kernel to move the
154 break up that far. When the user program examines its break, it
155 will see this new value and not clobber our data. */
156 __sbrk (_dl_pagesize - ((&_end - (void *) 0) & (_dl_pagesize - 1)));
158 (*dl_main) (phdr, phnum, &user_entry);
159 return user_entry;
162 void
163 _dl_sysdep_start_cleanup (void)
167 void
168 _dl_show_auxv (void)
170 char buf[64];
171 ElfW(auxv_t) *av;
173 /* Terminate string. */
174 buf[63] = '\0';
176 for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
177 switch (av->a_type)
179 case AT_PHDR:
180 _dl_sysdep_message ("AT_PHDR: 0x",
181 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
182 16, 0),
183 "\n", NULL);
184 break;
185 case AT_PHNUM:
186 _dl_sysdep_message ("AT_PHNUM: ",
187 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
188 10, 0),
189 "\n", NULL);
190 break;
191 case AT_PAGESZ:
192 _dl_sysdep_message ("AT_PAGESZ: ",
193 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
194 10, 0),
195 "\n", NULL);
196 break;
197 case AT_ENTRY:
198 _dl_sysdep_message ("AT_ENTRY: 0x",
199 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
200 16, 0),
201 "\n", NULL);
202 break;
203 case AT_BASE:
204 _dl_sysdep_message ("AT_BASE: 0x",
205 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
206 16, 0),
207 "\n", NULL);
208 break;
209 case AT_UID:
210 _dl_sysdep_message ("AT_UID: ",
211 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
212 10, 0),
213 "\n", NULL);
214 break;
215 case AT_GID:
216 _dl_sysdep_message ("AT_GID: ",
217 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
218 10, 0),
219 "\n", NULL);
220 break;
221 case AT_EUID:
222 _dl_sysdep_message ("AT_EUID: ",
223 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
224 10, 0),
225 "\n", NULL);
226 break;
227 case AT_EGID:
228 _dl_sysdep_message ("AT_EGID: ",
229 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
230 10, 0),
231 "\n", NULL);
232 break;
233 case AT_PLATFORM:
234 _dl_sysdep_message ("AT_PLATFORM: ", av->a_un.a_ptr, NULL);
235 break;
236 case AT_HWCAP:
237 _dl_sysdep_message ("AT_HWCAP: ",
238 _itoa_word (av->a_un.a_val, buf + sizeof buf - 1,
239 16, 0),
240 "\n", NULL);
241 break;