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