]> sourceware.org Git - glibc.git/blame - csu/libc-start.c
Remove __libc_csu_irel declaration
[glibc.git] / csu / libc-start.c
CommitLineData
f7a9f785 1/* Copyright (C) 1998-2016 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
PE
15 License along with the GNU C Library; if not, see
16 <http://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>
3db52d94 24
31161268
UD
25extern void __libc_init_first (int argc, char **argv, char **envp);
26
31161268
UD
27extern int __libc_multiple_libcs;
28
7ae4abe9 29#include <tls.h>
4fb7a71f 30#ifndef SHARED
dde2652b 31# include <dl-osinfo.h>
4e9b5995 32extern void __pthread_initialize_minimal (void);
35f1e827
UD
33# ifndef THREAD_SET_STACK_GUARD
34/* Only exported for architectures that don't store the stack guard canary
35 in thread local area. */
36uintptr_t __stack_chk_guard attribute_relro;
37# endif
c61b4d41
CD
38# ifndef THREAD_SET_POINTER_GUARD
39/* Only exported for architectures that don't store the pointer guard
40 value in thread local area. */
41uintptr_t __pointer_chk_guard_local
42 attribute_relro attribute_hidden __attribute__ ((nocommon));
43# endif
4fb7a71f
AJ
44#endif
45
47202270
UD
46#ifdef HAVE_PTR_NTHREADS
47/* We need atomic operations. */
48# include <atomic.h>
49#endif
50
17427edd 51
21ad0558
RM
52#ifndef SHARED
53# include <link.h>
54# include <dl-irel.h>
55
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
67
21ad0558
RM
68static void
69apply_irel (void)
70{
35a5b08b
RM
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));
21ad0558
RM
78 for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
79 IREL (ipltent);
35a5b08b 80# endif
21ad0558
RM
81}
82#endif
83
84
2b089f21 85#ifdef LIBC_START_MAIN
11986c68
UD
86# ifdef LIBC_START_DISABLE_INLINE
87# define STATIC static
88# else
89# define STATIC static inline __attribute__ ((always_inline))
90# endif
2b089f21
RM
91#else
92# define STATIC
e97ed6dd 93# define LIBC_START_MAIN __libc_start_main
2b089f21
RM
94#endif
95
2b089f21 96#ifdef MAIN_AUXVEC_ARG
09d65ff3
UD
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
2b089f21
RM
103#endif
104
09d65ff3
UD
105STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
106 MAIN_AUXVEC_DECL),
2b089f21 107 int argc,
70d9946a 108 char **argv,
2b089f21 109#ifdef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 110 ElfW(auxv_t) *auxvec,
2b089f21 111#endif
2b089f21 112 __typeof (main) init,
2b089f21
RM
113 void (*fini) (void),
114 void (*rtld_fini) (void),
70d9946a 115 void *stack_end)
17427edd 116 __attribute__ ((noreturn));
a828c2f5 117
9dcafc55 118
43c59a70
UD
119/* Note: the fini parameter is ignored here for shared library. It
120 is registered with __cxa_atexit. This had the disadvantage that
121 finalizers were called in more than one place. */
2b089f21 122STATIC int
09d65ff3 123LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
70d9946a 124 int argc, char **argv,
2b089f21 125#ifdef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 126 ElfW(auxv_t) *auxvec,
2b089f21 127#endif
2b089f21 128 __typeof (main) init,
2b089f21 129 void (*fini) (void),
70d9946a 130 void (*rtld_fini) (void), void *stack_end)
7dea968e 131{
7ae4abe9
UD
132 /* Result of the 'main' function. */
133 int result;
134
7ae4abe9 135 __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
c0fb8a56 136
3fb2606a 137#ifndef SHARED
70d9946a 138 char **ev = &argv[argc + 1];
4f657581 139
70d9946a 140 __environ = ev;
ab95290c 141
ea4f25a7
UD
142 /* Store the lowest stack address. This is done in ld.so if this is
143 the code for the DSO. */
c0fb8a56 144 __libc_stack_end = stack_end;
31161268 145
8a30f00f
UD
146# ifdef HAVE_AUX_VECTOR
147 /* First process the auxiliary vector since we need to find the
148 program header to locate an eventually present PT_TLS entry. */
2b089f21 149# ifndef LIBC_START_MAIN_AUXVEC_ARG
70d9946a 150 ElfW(auxv_t) *auxvec;
2b089f21 151 {
70d9946a 152 char **evp = ev;
97026947
UD
153 while (*evp++ != NULL)
154 ;
70d9946a 155 auxvec = (ElfW(auxv_t) *) evp;
2b089f21
RM
156 }
157# endif
158 _dl_aux_init (auxvec);
288f7d79 159 if (GL(dl_phdr) == NULL)
8a30f00f 160# endif
288f7d79
RM
161 {
162 /* Starting from binutils-2.23, the linker will define the
163 magic symbol __ehdr_start to point to our own ELF header
164 if it is visible in a segment that also includes the phdrs.
165 So we can set up _dl_phdr and _dl_phnum even without any
166 information from auxv. */
167
ae9552cf
MR
168 extern const ElfW(Ehdr) __ehdr_start
169 __attribute__ ((weak, visibility ("hidden")));
288f7d79
RM
170 if (&__ehdr_start != NULL)
171 {
172 assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));
173 GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
174 GL(dl_phnum) = __ehdr_start.e_phnum;
175 }
176 }
177
dde2652b
RM
178# ifdef DL_SYSDEP_OSCHECK
179 if (!__libc_multiple_libcs)
180 {
181 /* This needs to run to initiliaze _dl_osversion before TLS
182 setup might check it. */
183 DL_SYSDEP_OSCHECK (__libc_fatal);
184 }
185# endif
8a30f00f 186
21ad0558
RM
187 /* Perform IREL{,A} relocations. */
188 apply_irel ();
1c3c269b 189
4fb7a71f
AJ
190 /* Initialize the thread library at least a bit since the libgcc
191 functions are using thread functions if these are available and
11bf311e 192 we need to setup errno. */
4e9b5995 193 __pthread_initialize_minimal ();
a828c2f5 194
35f1e827 195 /* Set up the stack checker's canary. */
5b656a0d 196 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
75fb247e 197# ifdef THREAD_SET_STACK_GUARD
35f1e827 198 THREAD_SET_STACK_GUARD (stack_chk_guard);
75fb247e 199# else
35f1e827 200 __stack_chk_guard = stack_chk_guard;
75fb247e 201# endif
c61b4d41
CD
202
203 /* Set up the pointer guard value. */
204 uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
205 stack_chk_guard);
206# ifdef THREAD_SET_POINTER_GUARD
207 THREAD_SET_POINTER_GUARD (pointer_chk_guard);
208# else
209 __pointer_chk_guard_local = pointer_chk_guard;
210# endif
211
75fb247e
UD
212#endif
213
3db52d94 214 /* Register the destructor of the dynamic linker if there is any. */
a1ffb40e 215 if (__glibc_likely (rtld_fini != NULL))
c08bc50a 216 __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
3db52d94 217
43c59a70 218#ifndef SHARED
dacc8ffa
UD
219 /* Call the initializer of the libc. This is only needed here if we
220 are compiling for the static library in which case we haven't
221 run the constructors in `_dl_start_user'. */
31161268
UD
222 __libc_init_first (argc, argv, __environ);
223
43c59a70
UD
224 /* Register the destructor of the program, if any. */
225 if (fini)
226 __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
227
9946f75a
UD
228 /* Some security at this point. Prevent starting a SUID binary where
229 the standard file descriptors are not opened. We have to do this
230 only for statically linked applications since otherwise the dynamic
231 loader did the work already. */
232 if (__builtin_expect (__libc_enable_secure, 0))
233 __libc_check_standard_fds ();
234#endif
235
4194bc66 236 /* Call the initializer of the program, if any. */
b5567b2a 237#ifdef SHARED
afdca0f2 238 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
154d10bd 239 GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
31161268 240#endif
4194bc66 241 if (init)
04395c90 242 (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
3db52d94 243
9dcafc55
UD
244#ifdef SHARED
245 /* Auditing checkpoint: we have a new object. */
a1ffb40e 246 if (__glibc_unlikely (GLRO(dl_naudit) > 0))
9dcafc55
UD
247 {
248 struct audit_ifaces *afct = GLRO(dl_audit);
249 struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
250 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
251 {
252 if (afct->preinit != NULL)
253 afct->preinit (&head->l_audit[cnt].cookie);
254
255 afct = afct->next;
256 }
257 }
258#endif
259
b5567b2a 260#ifdef SHARED
a1ffb40e 261 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
154d10bd 262 GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
31161268
UD
263#endif
264
f737dfd0
CD
265#ifndef SHARED
266 _dl_debug_initialize (0, LM_ID_BASE);
267#endif
09d65ff3
UD
268#ifdef HAVE_CLEANUP_JMP_BUF
269 /* Memory for the cancellation buffer. */
270 struct pthread_unwind_buf unwind_buf;
271
272 int not_first_call;
273 not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
a1ffb40e 274 if (__glibc_likely (! not_first_call))
7ae4abe9 275 {
09d65ff3 276 struct pthread *self = THREAD_SELF;
7ae4abe9 277
09d65ff3
UD
278 /* Store old info. */
279 unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
280 unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
2b089f21 281
09d65ff3
UD
282 /* Store the new cleanup handler info. */
283 THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
284
285 /* Run the program. */
286 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9 287 }
7ae4abe9 288 else
47202270 289 {
3fa21fd8
UD
290 /* Remove the thread-local data. */
291# ifdef SHARED
ea1533e0 292 PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
3fa21fd8
UD
293# else
294 extern void __nptl_deallocate_tsd (void) __attribute ((weak));
295 __nptl_deallocate_tsd ();
296# endif
297
47202270
UD
298 /* One less thread. Decrement the counter. If it is zero we
299 terminate the entire process. */
300 result = 0;
09d65ff3 301# ifdef SHARED
ea1533e0 302 unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
e10bb107 303# ifdef PTR_DEMANGLE
ea1533e0 304 PTR_DEMANGLE (ptr);
e10bb107 305# endif
09d65ff3 306# else
9cfe5381
RM
307 extern unsigned int __nptl_nthreads __attribute ((weak));
308 unsigned int *const ptr = &__nptl_nthreads;
09d65ff3 309# endif
47202270
UD
310
311 if (! atomic_decrement_and_test (ptr))
47202270 312 /* Not much left to do but to exit the thread, not the process. */
e0db6517 313 __exit_thread ();
47202270 314 }
09d65ff3
UD
315#else
316 /* Nothing fancy, just call the function. */
317 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9
UD
318#endif
319
320 exit (result);
7dea968e 321}
This page took 0.686555 seconds and 5 git commands to generate.