]> git.ipfire.org Git - thirdparty/glibc.git/blame - csu/libc-start.c
[BZ #2510, BZ #2830, BZ #3137, BZ #3313, BZ #3426, BZ #3465, BZ #3480, BZ #3483,...
[thirdparty/glibc.git] / csu / libc-start.c
CommitLineData
11bf311e 1/* Copyright (C) 1998-2003, 2004, 2005, 2006 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
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
7dea968e 18
3db52d94 19#include <stdlib.h>
dde2652b 20#include <stdio.h>
3db52d94 21#include <unistd.h>
a42195db 22#include <ldsodefs.h>
ab95290c
UD
23#include <bp-start.h>
24#include <bp-sym.h>
3db52d94 25
31161268
UD
26extern void __libc_init_first (int argc, char **argv, char **envp);
27
31161268
UD
28extern int __libc_multiple_libcs;
29
7ae4abe9 30#include <tls.h>
4fb7a71f 31#ifndef SHARED
dde2652b 32# include <dl-osinfo.h>
11bf311e 33extern void __pthread_initialize_minimal (void);
35f1e827
UD
34# ifndef THREAD_SET_STACK_GUARD
35/* Only exported for architectures that don't store the stack guard canary
36 in thread local area. */
37uintptr_t __stack_chk_guard attribute_relro;
38# endif
4fb7a71f
AJ
39#endif
40
47202270
UD
41#ifdef HAVE_PTR_NTHREADS
42/* We need atomic operations. */
43# include <atomic.h>
44#endif
45
17427edd 46
2b089f21 47#ifdef LIBC_START_MAIN
11986c68
UD
48# ifdef LIBC_START_DISABLE_INLINE
49# define STATIC static
50# else
51# define STATIC static inline __attribute__ ((always_inline))
52# endif
2b089f21
RM
53#else
54# define STATIC
55# define LIBC_START_MAIN BP_SYM (__libc_start_main)
56#endif
57
2b089f21 58#ifdef MAIN_AUXVEC_ARG
09d65ff3
UD
59/* main gets passed a pointer to the auxiliary. */
60# define MAIN_AUXVEC_DECL , void *
61# define MAIN_AUXVEC_PARAM , auxvec
62#else
63# define MAIN_AUXVEC_DECL
64# define MAIN_AUXVEC_PARAM
2b089f21
RM
65#endif
66
09d65ff3
UD
67STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
68 MAIN_AUXVEC_DECL),
2b089f21
RM
69 int argc,
70 char *__unbounded *__unbounded ubp_av,
71#ifdef LIBC_START_MAIN_AUXVEC_ARG
72 ElfW(auxv_t) *__unbounded auxvec,
73#endif
2b089f21 74 __typeof (main) init,
2b089f21
RM
75 void (*fini) (void),
76 void (*rtld_fini) (void),
77 void *__unbounded stack_end)
17427edd 78 __attribute__ ((noreturn));
a828c2f5 79
9dcafc55 80
43c59a70
UD
81/* Note: the fini parameter is ignored here for shared library. It
82 is registered with __cxa_atexit. This had the disadvantage that
83 finalizers were called in more than one place. */
2b089f21 84STATIC int
09d65ff3 85LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
2b089f21
RM
86 int argc, char *__unbounded *__unbounded ubp_av,
87#ifdef LIBC_START_MAIN_AUXVEC_ARG
88 ElfW(auxv_t) *__unbounded auxvec,
89#endif
2b089f21 90 __typeof (main) init,
2b089f21
RM
91 void (*fini) (void),
92 void (*rtld_fini) (void), void *__unbounded stack_end)
7dea968e 93{
ab95290c
UD
94#if __BOUNDED_POINTERS__
95 char **argv;
96#else
97# define argv ubp_av
98#endif
99
7ae4abe9
UD
100 /* Result of the 'main' function. */
101 int result;
102
7ae4abe9 103 __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
c0fb8a56 104
3fb2606a 105#ifndef SHARED
4f657581
RM
106 char *__unbounded *__unbounded ubp_ev = &ubp_av[argc + 1];
107
ab95290c
UD
108 INIT_ARGV_and_ENVIRON;
109
ea4f25a7
UD
110 /* Store the lowest stack address. This is done in ld.so if this is
111 the code for the DSO. */
c0fb8a56 112 __libc_stack_end = stack_end;
31161268 113
8a30f00f
UD
114# ifdef HAVE_AUX_VECTOR
115 /* First process the auxiliary vector since we need to find the
116 program header to locate an eventually present PT_TLS entry. */
2b089f21
RM
117# ifndef LIBC_START_MAIN_AUXVEC_ARG
118 ElfW(auxv_t) *__unbounded auxvec;
119 {
7eecc0c2 120 char *__unbounded *__unbounded evp = ubp_ev;
97026947
UD
121 while (*evp++ != NULL)
122 ;
2b089f21
RM
123 auxvec = (ElfW(auxv_t) *__unbounded) evp;
124 }
125# endif
126 _dl_aux_init (auxvec);
8a30f00f 127# endif
dde2652b
RM
128# ifdef DL_SYSDEP_OSCHECK
129 if (!__libc_multiple_libcs)
130 {
131 /* This needs to run to initiliaze _dl_osversion before TLS
132 setup might check it. */
133 DL_SYSDEP_OSCHECK (__libc_fatal);
134 }
135# endif
8a30f00f 136
4fb7a71f
AJ
137 /* Initialize the thread library at least a bit since the libgcc
138 functions are using thread functions if these are available and
11bf311e
UD
139 we need to setup errno. */
140 __pthread_initialize_minimal ();
db33f7d4 141#endif
a828c2f5 142
35f1e827
UD
143# ifndef SHARED
144 /* Set up the stack checker's canary. */
145 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
146# ifdef THREAD_SET_STACK_GUARD
147 THREAD_SET_STACK_GUARD (stack_chk_guard);
148# else
149 __stack_chk_guard = stack_chk_guard;
150# endif
151#endif
152
3db52d94 153 /* Register the destructor of the dynamic linker if there is any. */
cf197e41 154 if (__builtin_expect (rtld_fini != NULL, 1))
c08bc50a 155 __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
3db52d94 156
43c59a70 157#ifndef SHARED
dacc8ffa
UD
158 /* Call the initializer of the libc. This is only needed here if we
159 are compiling for the static library in which case we haven't
160 run the constructors in `_dl_start_user'. */
31161268
UD
161 __libc_init_first (argc, argv, __environ);
162
43c59a70
UD
163 /* Register the destructor of the program, if any. */
164 if (fini)
165 __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
166
9946f75a
UD
167 /* Some security at this point. Prevent starting a SUID binary where
168 the standard file descriptors are not opened. We have to do this
169 only for statically linked applications since otherwise the dynamic
170 loader did the work already. */
171 if (__builtin_expect (__libc_enable_secure, 0))
172 __libc_check_standard_fds ();
173#endif
174
4194bc66 175 /* Call the initializer of the program, if any. */
b5567b2a 176#ifdef SHARED
afdca0f2 177 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
154d10bd 178 GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
31161268 179#endif
4194bc66 180 if (init)
04395c90 181 (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
3db52d94 182
9dcafc55
UD
183#ifdef SHARED
184 /* Auditing checkpoint: we have a new object. */
185 if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
186 {
187 struct audit_ifaces *afct = GLRO(dl_audit);
188 struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
189 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
190 {
191 if (afct->preinit != NULL)
192 afct->preinit (&head->l_audit[cnt].cookie);
193
194 afct = afct->next;
195 }
196 }
197#endif
198
b5567b2a 199#ifdef SHARED
afdca0f2 200 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
154d10bd 201 GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
31161268
UD
202#endif
203
09d65ff3
UD
204#ifdef HAVE_CLEANUP_JMP_BUF
205 /* Memory for the cancellation buffer. */
206 struct pthread_unwind_buf unwind_buf;
207
208 int not_first_call;
209 not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
210 if (__builtin_expect (! not_first_call, 1))
7ae4abe9 211 {
09d65ff3 212 struct pthread *self = THREAD_SELF;
7ae4abe9 213
09d65ff3
UD
214 /* Store old info. */
215 unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
216 unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
2b089f21 217
09d65ff3
UD
218 /* Store the new cleanup handler info. */
219 THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
220
221 /* Run the program. */
222 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9 223 }
7ae4abe9 224 else
47202270 225 {
3fa21fd8
UD
226 /* Remove the thread-local data. */
227# ifdef SHARED
228 __libc_pthread_functions.ptr__nptl_deallocate_tsd ();
229# else
230 extern void __nptl_deallocate_tsd (void) __attribute ((weak));
231 __nptl_deallocate_tsd ();
232# endif
233
47202270
UD
234 /* One less thread. Decrement the counter. If it is zero we
235 terminate the entire process. */
236 result = 0;
09d65ff3 237# ifdef SHARED
9cfe5381 238 unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads;
09d65ff3 239# else
9cfe5381
RM
240 extern unsigned int __nptl_nthreads __attribute ((weak));
241 unsigned int *const ptr = &__nptl_nthreads;
09d65ff3 242# endif
47202270
UD
243
244 if (! atomic_decrement_and_test (ptr))
47202270
UD
245 /* Not much left to do but to exit the thread, not the process. */
246 __exit_thread (0);
247 }
09d65ff3
UD
248#else
249 /* Nothing fancy, just call the function. */
250 result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
7ae4abe9
UD
251#endif
252
253 exit (result);
7dea968e 254}