]> git.ipfire.org Git - thirdparty/glibc.git/blame - csu/libc-start.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / csu / libc-start.c
CommitLineData
2b778ceb 1/* Copyright (C) 1998-2021 Free Software Foundation, Inc.
7dea968e
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
7dea968e
UD
8
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
41bdb6e2 12 Lesser General Public License for more details.
7dea968e 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
7dea968e 17
288f7d79 18#include <assert.h>
3db52d94 19#include <stdlib.h>
dde2652b 20#include <stdio.h>
3db52d94 21#include <unistd.h>
a42195db 22#include <ldsodefs.h>
e0db6517 23#include <exit-thread.h>
2098d403 24#include <libc-diag.h>
67e58f39 25#include <libc-internal.h>
ec935dea 26#include <elf/libc-early-init.h>
03e187a4 27#include <stdbool.h>
67e58f39
SP
28
29#include <elf/dl-tunables.h>
3db52d94 30
31161268
UD
31extern void __libc_init_first (int argc, char **argv, char **envp);
32
7ae4abe9 33#include <tls.h>
4fb7a71f 34#ifndef SHARED
dde2652b 35# include <dl-osinfo.h>
35f1e827
UD
36# ifndef THREAD_SET_STACK_GUARD
37/* Only exported for architectures that don't store the stack guard canary
38 in thread local area. */
39uintptr_t __stack_chk_guard attribute_relro;
40# endif
c61b4d41
CD
41# ifndef THREAD_SET_POINTER_GUARD
42/* Only exported for architectures that don't store the pointer guard
43 value in thread local area. */
44uintptr_t __pointer_chk_guard_local
45 attribute_relro attribute_hidden __attribute__ ((nocommon));
46# endif
4fb7a71f
AJ
47#endif
48
47202270
UD
49#ifdef HAVE_PTR_NTHREADS
50/* We need atomic operations. */
51# include <atomic.h>
52#endif
53
17427edd 54
21ad0558
RM
55#ifndef SHARED
56# include <link.h>
57# include <dl-irel.h>
58
59# ifdef ELF_MACHINE_IRELA
60# define IREL_T ElfW(Rela)
61# define IPLT_START __rela_iplt_start
62# define IPLT_END __rela_iplt_end
63# define IREL elf_irela
64# elif defined ELF_MACHINE_IREL
65# define IREL_T ElfW(Rel)
66# define IPLT_START __rel_iplt_start
67# define IPLT_END __rel_iplt_end
68# define IREL elf_irel
69# endif
70
21ad0558
RM
71static void
72apply_irel (void)
73{
35a5b08b
RM
74# ifdef IREL
75 /* We use weak references for these so that we'll still work with a linker
76 that doesn't define them. Such a linker doesn't support IFUNC at all
77 and so uses won't work, but a statically-linked program that doesn't
78 use any IFUNC symbols won't have a problem. */
79 extern const IREL_T IPLT_START[] __attribute__ ((weak));
80 extern const IREL_T IPLT_END[] __attribute__ ((weak));
21ad0558
RM
81 for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
82 IREL (ipltent);
35a5b08b 83# endif
21ad0558
RM
84}
85#endif
86
87
2b089f21 88#ifdef LIBC_START_MAIN
11986c68
UD
89# ifdef LIBC_START_DISABLE_INLINE
90# define STATIC static
91# else
92# define STATIC static inline __attribute__ ((always_inline))
93# endif
2b089f21
RM
94#else
95# define STATIC
e97ed6dd 96# define LIBC_START_MAIN __libc_start_main
2b089f21
RM
97#endif
98
2b089f21 99#ifdef MAIN_AUXVEC_ARG
09d65ff3
UD
100/* main gets passed a pointer to the auxiliary. */
101# define MAIN_AUXVEC_DECL , void *
102# define MAIN_AUXVEC_PARAM , auxvec
103#else
104# define MAIN_AUXVEC_DECL
105# define MAIN_AUXVEC_PARAM
2b089f21
RM
106#endif
107
4158ba08
SP
108#ifndef ARCH_INIT_CPU_FEATURES
109# define ARCH_INIT_CPU_FEATURES()
110#endif
111
91ac3a7d
TMQMF
112#include <libc-start.h>
113
09d65ff3
UD
114STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
115 MAIN_AUXVEC_DECL),
2b089f21 116 int argc,
70d9946a 117 char **argv,
2b089f21 118#ifdef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 119 ElfW(auxv_t) *auxvec,
2b089f21 120#endif
2b089f21 121 __typeof (main) init,
2b089f21
RM
122 void (*fini) (void),
123 void (*rtld_fini) (void),
70d9946a 124 void *stack_end)
17427edd 125 __attribute__ ((noreturn));
a828c2f5 126
9dcafc55 127
43c59a70
UD
128/* Note: the fini parameter is ignored here for shared library. It
129 is registered with __cxa_atexit. This had the disadvantage that
130 finalizers were called in more than one place. */
2b089f21 131STATIC int
09d65ff3 132LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
70d9946a 133 int argc, char **argv,
2b089f21 134#ifdef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 135 ElfW(auxv_t) *auxvec,
2b089f21 136#endif
2b089f21 137 __typeof (main) init,
2b089f21 138 void (*fini) (void),
70d9946a 139 void (*rtld_fini) (void), void *stack_end)
7dea968e 140{
7ae4abe9
UD
141 /* Result of the 'main' function. */
142 int result;
143
3fb2606a 144#ifndef SHARED
9d7a3741
L
145 _dl_relocate_static_pie ();
146
70d9946a 147 char **ev = &argv[argc + 1];
4f657581 148
70d9946a 149 __environ = ev;
ab95290c 150
ea4f25a7
UD
151 /* Store the lowest stack address. This is done in ld.so if this is
152 the code for the DSO. */
c0fb8a56 153 __libc_stack_end = stack_end;
31161268 154
8a30f00f
UD
155# ifdef HAVE_AUX_VECTOR
156 /* First process the auxiliary vector since we need to find the
157 program header to locate an eventually present PT_TLS entry. */
2b089f21 158# ifndef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 159 ElfW(auxv_t) *auxvec;
2b089f21 160 {
70d9946a 161 char **evp = ev;
97026947
UD
162 while (*evp++ != NULL)
163 ;
70d9946a 164 auxvec = (ElfW(auxv_t) *) evp;
2b089f21
RM
165 }
166# endif
167 _dl_aux_init (auxvec);
288f7d79 168 if (GL(dl_phdr) == NULL)
8a30f00f 169# endif
288f7d79
RM
170 {
171 /* Starting from binutils-2.23, the linker will define the
172 magic symbol __ehdr_start to point to our own ELF header
173 if it is visible in a segment that also includes the phdrs.
174 So we can set up _dl_phdr and _dl_phnum even without any
175 information from auxv. */
176
ae9552cf
MR
177 extern const ElfW(Ehdr) __ehdr_start
178 __attribute__ ((weak, visibility ("hidden")));
288f7d79
RM
179 if (&__ehdr_start != NULL)
180 {
181 assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));
182 GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
183 GL(dl_phnum) = __ehdr_start.e_phnum;
184 }
185 }
186
67e58f39
SP
187 /* Initialize very early so that tunables can use it. */
188 __libc_init_secure ();
189
190 __tunables_init (__environ);
191
4158ba08
SP
192 ARCH_INIT_CPU_FEATURES ();
193
21ad0558 194 /* Perform IREL{,A} relocations. */
91ac3a7d 195 ARCH_SETUP_IREL ();
1c3c269b 196
003a27e8 197 /* The stack guard goes into the TCB, so initialize it early. */
bcfa607b 198 ARCH_SETUP_TLS ();
a828c2f5 199
91ac3a7d
TMQMF
200 /* In some architectures, IREL{,A} relocations happen after TLS setup in
201 order to let IFUNC resolvers benefit from TCB information, e.g. powerpc's
202 hwcap and platform fields available in the TCB. */
203 ARCH_APPLY_IREL ();
204
35f1e827 205 /* Set up the stack checker's canary. */
5b656a0d 206 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
75fb247e 207# ifdef THREAD_SET_STACK_GUARD
35f1e827 208 THREAD_SET_STACK_GUARD (stack_chk_guard);
75fb247e 209# else
35f1e827 210 __stack_chk_guard = stack_chk_guard;
75fb247e 211# endif
c61b4d41 212
003a27e8 213# ifdef DL_SYSDEP_OSCHECK
e7570f41
FW
214 {
215 /* This needs to run to initiliaze _dl_osversion before TLS
216 setup might check it. */
217 DL_SYSDEP_OSCHECK (__libc_fatal);
218 }
003a27e8
NA
219# endif
220
221 /* Initialize libpthread if linked in. */
222 if (__pthread_initialize_minimal != NULL)
223 __pthread_initialize_minimal ();
224
c61b4d41
CD
225 /* Set up the pointer guard value. */
226 uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
227 stack_chk_guard);
228# ifdef THREAD_SET_POINTER_GUARD
229 THREAD_SET_POINTER_GUARD (pointer_chk_guard);
230# else
231 __pointer_chk_guard_local = pointer_chk_guard;
232# endif
233
91ac3a7d 234#endif /* !SHARED */
75fb247e 235
3db52d94 236 /* Register the destructor of the dynamic linker if there is any. */
a1ffb40e 237 if (__glibc_likely (rtld_fini != NULL))
c08bc50a 238 __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
3db52d94 239
43c59a70 240#ifndef SHARED
ec935dea
FW
241 /* Perform early initialization. In the shared case, this function
242 is called from the dynamic loader as early as possible. */
03e187a4 243 __libc_early_init (true);
ec935dea 244
dacc8ffa
UD
245 /* Call the initializer of the libc. This is only needed here if we
246 are compiling for the static library in which case we haven't
247 run the constructors in `_dl_start_user'. */
31161268
UD
248 __libc_init_first (argc, argv, __environ);
249
43c59a70
UD
250 /* Register the destructor of the program, if any. */
251 if (fini)
252 __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
253
9946f75a
UD
254 /* Some security at this point. Prevent starting a SUID binary where
255 the standard file descriptors are not opened. We have to do this
256 only for statically linked applications since otherwise the dynamic
257 loader did the work already. */
258 if (__builtin_expect (__libc_enable_secure, 0))
259 __libc_check_standard_fds ();
260#endif
261
4194bc66 262 /* Call the initializer of the program, if any. */
b5567b2a 263#ifdef SHARED
afdca0f2 264 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
154d10bd 265 GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
31161268 266#endif
4194bc66 267 if (init)
04395c90 268 (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
3db52d94 269
9dcafc55
UD
270#ifdef SHARED
271 /* Auditing checkpoint: we have a new object. */
a1ffb40e 272 if (__glibc_unlikely (GLRO(dl_naudit) > 0))
9dcafc55
UD
273 {
274 struct audit_ifaces *afct = GLRO(dl_audit);
275 struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
276 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
277 {
278 if (afct->preinit != NULL)
e1d559f3 279 afct->preinit (&link_map_audit_state (head, cnt)->cookie);
9dcafc55
UD
280
281 afct = afct->next;
282 }
283 }
284#endif
285
b5567b2a 286#ifdef SHARED
a1ffb40e 287 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
154d10bd 288 GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
31161268
UD
289#endif
290
f737dfd0
CD
291#ifndef SHARED
292 _dl_debug_initialize (0, LM_ID_BASE);
293#endif
09d65ff3
UD
294#ifdef HAVE_CLEANUP_JMP_BUF
295 /* Memory for the cancellation buffer. */
296 struct pthread_unwind_buf unwind_buf;
297
298 int not_first_call;
2098d403
JM
299 DIAG_PUSH_NEEDS_COMMENT;
300#if __GNUC_PREREQ (7, 0)
301 /* This call results in a -Wstringop-overflow warning because struct
302 pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp
303 do not use anything beyond the common prefix (they never access
304 the saved signal mask), so that is a false positive. */
305 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow=");
306#endif
09d65ff3 307 not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
2098d403 308 DIAG_POP_NEEDS_COMMENT;
a1ffb40e 309 if (__glibc_likely (! not_first_call))
7ae4abe9 310 {
09d65ff3 311 struct pthread *self = THREAD_SELF;
7ae4abe9 312
09d65ff3
UD
313 /* Store old info. */
314 unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
315 unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
2b089f21 316
09d65ff3
UD
317 /* Store the new cleanup handler info. */
318 THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
319
320 /* Run the program. */
321 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9 322 }
7ae4abe9 323 else
47202270 324 {
3fa21fd8
UD
325 /* Remove the thread-local data. */
326# ifdef SHARED
ea1533e0 327 PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
3fa21fd8
UD
328# else
329 extern void __nptl_deallocate_tsd (void) __attribute ((weak));
330 __nptl_deallocate_tsd ();
331# endif
332
47202270
UD
333 /* One less thread. Decrement the counter. If it is zero we
334 terminate the entire process. */
335 result = 0;
09d65ff3 336# ifdef SHARED
ea1533e0 337 unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
e10bb107 338# ifdef PTR_DEMANGLE
ea1533e0 339 PTR_DEMANGLE (ptr);
e10bb107 340# endif
09d65ff3 341# else
9cfe5381
RM
342 extern unsigned int __nptl_nthreads __attribute ((weak));
343 unsigned int *const ptr = &__nptl_nthreads;
09d65ff3 344# endif
47202270
UD
345
346 if (! atomic_decrement_and_test (ptr))
47202270 347 /* Not much left to do but to exit the thread, not the process. */
e0db6517 348 __exit_thread ();
47202270 349 }
09d65ff3
UD
350#else
351 /* Nothing fancy, just call the function. */
352 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9
UD
353#endif
354
355 exit (result);
7dea968e 356}