Add sysdeps/ieee754/soft-fp.
[glibc.git] / csu / libc-start.c
blob24c63be02f06484955071c0d79914e5162217065
1 /* Copyright (C) 1998-2017 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
18 #include <assert.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <ldsodefs.h>
23 #include <exit-thread.h>
24 #include <libc-internal.h>
26 #include <elf/dl-tunables.h>
28 extern void __libc_init_first (int argc, char **argv, char **envp);
30 #include <tls.h>
31 #ifndef SHARED
32 # include <dl-osinfo.h>
33 # ifndef THREAD_SET_STACK_GUARD
34 /* Only exported for architectures that don't store the stack guard canary
35 in thread local area. */
36 uintptr_t __stack_chk_guard attribute_relro;
37 # endif
38 # ifndef THREAD_SET_POINTER_GUARD
39 /* Only exported for architectures that don't store the pointer guard
40 value in thread local area. */
41 uintptr_t __pointer_chk_guard_local
42 attribute_relro attribute_hidden __attribute__ ((nocommon));
43 # endif
44 #endif
46 #ifdef HAVE_PTR_NTHREADS
47 /* We need atomic operations. */
48 # include <atomic.h>
49 #endif
52 #ifndef SHARED
53 # include <link.h>
54 # include <dl-irel.h>
56 # ifdef ELF_MACHINE_IRELA
57 # define IREL_T ElfW(Rela)
58 # define IPLT_START __rela_iplt_start
59 # define IPLT_END __rela_iplt_end
60 # define IREL elf_irela
61 # elif defined ELF_MACHINE_IREL
62 # define IREL_T ElfW(Rel)
63 # define IPLT_START __rel_iplt_start
64 # define IPLT_END __rel_iplt_end
65 # define IREL elf_irel
66 # endif
68 static void
69 apply_irel (void)
71 # ifdef IREL
72 /* We use weak references for these so that we'll still work with a linker
73 that doesn't define them. Such a linker doesn't support IFUNC at all
74 and so uses won't work, but a statically-linked program that doesn't
75 use any IFUNC symbols won't have a problem. */
76 extern const IREL_T IPLT_START[] __attribute__ ((weak));
77 extern const IREL_T IPLT_END[] __attribute__ ((weak));
78 for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
79 IREL (ipltent);
80 # endif
82 #endif
85 #ifdef LIBC_START_MAIN
86 # ifdef LIBC_START_DISABLE_INLINE
87 # define STATIC static
88 # else
89 # define STATIC static inline __attribute__ ((always_inline))
90 # endif
91 #else
92 # define STATIC
93 # define LIBC_START_MAIN __libc_start_main
94 #endif
96 #ifdef MAIN_AUXVEC_ARG
97 /* main gets passed a pointer to the auxiliary. */
98 # define MAIN_AUXVEC_DECL , void *
99 # define MAIN_AUXVEC_PARAM , auxvec
100 #else
101 # define MAIN_AUXVEC_DECL
102 # define MAIN_AUXVEC_PARAM
103 #endif
105 #ifndef ARCH_INIT_CPU_FEATURES
106 # define ARCH_INIT_CPU_FEATURES()
107 #endif
109 #include <libc-start.h>
111 STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
112 MAIN_AUXVEC_DECL),
113 int argc,
114 char **argv,
115 #ifdef LIBC_START_MAIN_AUXVEC_ARG
116 ElfW(auxv_t) *auxvec,
117 #endif
118 __typeof (main) init,
119 void (*fini) (void),
120 void (*rtld_fini) (void),
121 void *stack_end)
122 __attribute__ ((noreturn));
125 /* Note: the fini parameter is ignored here for shared library. It
126 is registered with __cxa_atexit. This had the disadvantage that
127 finalizers were called in more than one place. */
128 STATIC int
129 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
130 int argc, char **argv,
131 #ifdef LIBC_START_MAIN_AUXVEC_ARG
132 ElfW(auxv_t) *auxvec,
133 #endif
134 __typeof (main) init,
135 void (*fini) (void),
136 void (*rtld_fini) (void), void *stack_end)
138 /* Result of the 'main' function. */
139 int result;
141 __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
143 #ifndef SHARED
144 char **ev = &argv[argc + 1];
146 __environ = ev;
148 /* Store the lowest stack address. This is done in ld.so if this is
149 the code for the DSO. */
150 __libc_stack_end = stack_end;
152 # ifdef HAVE_AUX_VECTOR
153 /* First process the auxiliary vector since we need to find the
154 program header to locate an eventually present PT_TLS entry. */
155 # ifndef LIBC_START_MAIN_AUXVEC_ARG
156 ElfW(auxv_t) *auxvec;
158 char **evp = ev;
159 while (*evp++ != NULL)
161 auxvec = (ElfW(auxv_t) *) evp;
163 # endif
164 _dl_aux_init (auxvec);
165 if (GL(dl_phdr) == NULL)
166 # endif
168 /* Starting from binutils-2.23, the linker will define the
169 magic symbol __ehdr_start to point to our own ELF header
170 if it is visible in a segment that also includes the phdrs.
171 So we can set up _dl_phdr and _dl_phnum even without any
172 information from auxv. */
174 extern const ElfW(Ehdr) __ehdr_start
175 __attribute__ ((weak, visibility ("hidden")));
176 if (&__ehdr_start != NULL)
178 assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));
179 GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
180 GL(dl_phnum) = __ehdr_start.e_phnum;
184 /* Initialize very early so that tunables can use it. */
185 __libc_init_secure ();
187 __tunables_init (__environ);
189 ARCH_INIT_CPU_FEATURES ();
191 /* Perform IREL{,A} relocations. */
192 ARCH_SETUP_IREL ();
194 /* The stack guard goes into the TCB, so initialize it early. */
195 __libc_setup_tls ();
197 /* In some architectures, IREL{,A} relocations happen after TLS setup in
198 order to let IFUNC resolvers benefit from TCB information, e.g. powerpc's
199 hwcap and platform fields available in the TCB. */
200 ARCH_APPLY_IREL ();
202 /* Set up the stack checker's canary. */
203 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
204 # ifdef THREAD_SET_STACK_GUARD
205 THREAD_SET_STACK_GUARD (stack_chk_guard);
206 # else
207 __stack_chk_guard = stack_chk_guard;
208 # endif
210 # ifdef DL_SYSDEP_OSCHECK
211 if (!__libc_multiple_libcs)
213 /* This needs to run to initiliaze _dl_osversion before TLS
214 setup might check it. */
215 DL_SYSDEP_OSCHECK (__libc_fatal);
217 # endif
219 /* Initialize libpthread if linked in. */
220 if (__pthread_initialize_minimal != NULL)
221 __pthread_initialize_minimal ();
223 /* Set up the pointer guard value. */
224 uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
225 stack_chk_guard);
226 # ifdef THREAD_SET_POINTER_GUARD
227 THREAD_SET_POINTER_GUARD (pointer_chk_guard);
228 # else
229 __pointer_chk_guard_local = pointer_chk_guard;
230 # endif
232 #endif /* !SHARED */
234 /* Register the destructor of the dynamic linker if there is any. */
235 if (__glibc_likely (rtld_fini != NULL))
236 __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
238 #ifndef SHARED
239 /* Call the initializer of the libc. This is only needed here if we
240 are compiling for the static library in which case we haven't
241 run the constructors in `_dl_start_user'. */
242 __libc_init_first (argc, argv, __environ);
244 /* Register the destructor of the program, if any. */
245 if (fini)
246 __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
248 /* Some security at this point. Prevent starting a SUID binary where
249 the standard file descriptors are not opened. We have to do this
250 only for statically linked applications since otherwise the dynamic
251 loader did the work already. */
252 if (__builtin_expect (__libc_enable_secure, 0))
253 __libc_check_standard_fds ();
254 #endif
256 /* Call the initializer of the program, if any. */
257 #ifdef SHARED
258 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
259 GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
260 #endif
261 if (init)
262 (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
264 #ifdef SHARED
265 /* Auditing checkpoint: we have a new object. */
266 if (__glibc_unlikely (GLRO(dl_naudit) > 0))
268 struct audit_ifaces *afct = GLRO(dl_audit);
269 struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
270 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
272 if (afct->preinit != NULL)
273 afct->preinit (&head->l_audit[cnt].cookie);
275 afct = afct->next;
278 #endif
280 #ifdef SHARED
281 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
282 GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
283 #endif
285 #ifndef SHARED
286 _dl_debug_initialize (0, LM_ID_BASE);
287 #endif
288 #ifdef HAVE_CLEANUP_JMP_BUF
289 /* Memory for the cancellation buffer. */
290 struct pthread_unwind_buf unwind_buf;
292 int not_first_call;
293 not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
294 if (__glibc_likely (! not_first_call))
296 struct pthread *self = THREAD_SELF;
298 /* Store old info. */
299 unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
300 unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
302 /* Store the new cleanup handler info. */
303 THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
305 /* Run the program. */
306 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
308 else
310 /* Remove the thread-local data. */
311 # ifdef SHARED
312 PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
313 # else
314 extern void __nptl_deallocate_tsd (void) __attribute ((weak));
315 __nptl_deallocate_tsd ();
316 # endif
318 /* One less thread. Decrement the counter. If it is zero we
319 terminate the entire process. */
320 result = 0;
321 # ifdef SHARED
322 unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
323 # ifdef PTR_DEMANGLE
324 PTR_DEMANGLE (ptr);
325 # endif
326 # else
327 extern unsigned int __nptl_nthreads __attribute ((weak));
328 unsigned int *const ptr = &__nptl_nthreads;
329 # endif
331 if (! atomic_decrement_and_test (ptr))
332 /* Not much left to do but to exit the thread, not the process. */
333 __exit_thread ();
335 #else
336 /* Nothing fancy, just call the function. */
337 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
338 #endif
340 exit (result);