fa9085cf55ab6420d81ac320b36102291bc725ab
[platform/upstream/glibc.git] / csu / libc-start.c
1 /* Copyright (C) 1998-2013 Free Software Foundation, Inc.
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
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.
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
12    Lesser General Public License for more details.
13
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/>.  */
17
18 #include <assert.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <ldsodefs.h>
23
24 extern void __libc_init_first (int argc, char **argv, char **envp);
25 #ifndef SHARED
26 extern void __libc_csu_irel (void);
27 #endif
28
29 extern int __libc_multiple_libcs;
30
31 #include <tls.h>
32 #ifndef SHARED
33 # include <dl-osinfo.h>
34 extern void __pthread_initialize_minimal (void);
35 # ifndef THREAD_SET_STACK_GUARD
36 /* Only exported for architectures that don't store the stack guard canary
37    in thread local area.  */
38 uintptr_t __stack_chk_guard attribute_relro;
39 # endif
40 #endif
41
42 #ifdef HAVE_PTR_NTHREADS
43 /* We need atomic operations.  */
44 # include <atomic.h>
45 #endif
46
47
48 #ifndef SHARED
49 # include <link.h>
50 # include <dl-irel.h>
51
52 # ifdef ELF_MACHINE_IRELA
53 #  define IREL_T        ElfW(Rela)
54 #  define IPLT_START    __rela_iplt_start
55 #  define IPLT_END      __rela_iplt_end
56 #  define IREL          elf_irela
57 # elif defined ELF_MACHINE_IREL
58 #  define IREL_T        ElfW(Rel)
59 #  define IPLT_START    __rel_iplt_start
60 #  define IPLT_END      __rel_iplt_end
61 #  define IREL          elf_irel
62 # endif
63
64 static void
65 apply_irel (void)
66 {
67 # ifdef IREL
68   /* We use weak references for these so that we'll still work with a linker
69      that doesn't define them.  Such a linker doesn't support IFUNC at all
70      and so uses won't work, but a statically-linked program that doesn't
71      use any IFUNC symbols won't have a problem.  */
72   extern const IREL_T IPLT_START[] __attribute__ ((weak));
73   extern const IREL_T IPLT_END[] __attribute__ ((weak));
74   for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
75     IREL (ipltent);
76 # endif
77 }
78 #endif
79
80
81 #ifdef LIBC_START_MAIN
82 # ifdef LIBC_START_DISABLE_INLINE
83 #  define STATIC static
84 # else
85 #  define STATIC static inline __attribute__ ((always_inline))
86 # endif
87 #else
88 # define STATIC
89 # define LIBC_START_MAIN __libc_start_main
90 #endif
91
92 #ifdef MAIN_AUXVEC_ARG
93 /* main gets passed a pointer to the auxiliary.  */
94 # define MAIN_AUXVEC_DECL       , void *
95 # define MAIN_AUXVEC_PARAM      , auxvec
96 #else
97 # define MAIN_AUXVEC_DECL
98 # define MAIN_AUXVEC_PARAM
99 #endif
100
101 STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
102                                          MAIN_AUXVEC_DECL),
103                             int argc,
104                             char **argv,
105 #ifdef LIBC_START_MAIN_AUXVEC_ARG
106                             ElfW(auxv_t) *auxvec,
107 #endif
108                             __typeof (main) init,
109                             void (*fini) (void),
110                             void (*rtld_fini) (void),
111                             void *stack_end)
112      __attribute__ ((noreturn));
113
114
115 /* Note: the fini parameter is ignored here for shared library.  It
116    is registered with __cxa_atexit.  This had the disadvantage that
117    finalizers were called in more than one place.  */
118 STATIC int
119 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
120                  int argc, char **argv,
121 #ifdef LIBC_START_MAIN_AUXVEC_ARG
122                  ElfW(auxv_t) *auxvec,
123 #endif
124                  __typeof (main) init,
125                  void (*fini) (void),
126                  void (*rtld_fini) (void), void *stack_end)
127 {
128   /* Result of the 'main' function.  */
129   int result;
130
131   __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
132
133 #ifndef SHARED
134   char **ev = &argv[argc + 1];
135
136   __environ = ev;
137
138   /* Store the lowest stack address.  This is done in ld.so if this is
139      the code for the DSO.  */
140   __libc_stack_end = stack_end;
141
142 # ifdef HAVE_AUX_VECTOR
143   /* First process the auxiliary vector since we need to find the
144      program header to locate an eventually present PT_TLS entry.  */
145 #  ifndef LIBC_START_MAIN_AUXVEC_ARG
146   ElfW(auxv_t) *auxvec;
147   {
148     char **evp = ev;
149     while (*evp++ != NULL)
150       ;
151     auxvec = (ElfW(auxv_t) *) evp;
152   }
153 #  endif
154   _dl_aux_init (auxvec);
155   if (GL(dl_phdr) == NULL)
156 # endif
157     {
158       /* Starting from binutils-2.23, the linker will define the
159          magic symbol __ehdr_start to point to our own ELF header
160          if it is visible in a segment that also includes the phdrs.
161          So we can set up _dl_phdr and _dl_phnum even without any
162          information from auxv.  */
163
164       extern const ElfW(Ehdr) __ehdr_start __attribute__ ((weak));
165       if (&__ehdr_start != NULL)
166         {
167           assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));
168           GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
169           GL(dl_phnum) = __ehdr_start.e_phnum;
170         }
171     }
172
173 # ifdef DL_SYSDEP_OSCHECK
174   if (!__libc_multiple_libcs)
175     {
176       /* This needs to run to initiliaze _dl_osversion before TLS
177          setup might check it.  */
178       DL_SYSDEP_OSCHECK (__libc_fatal);
179     }
180 # endif
181
182   /* Perform IREL{,A} relocations.  */
183   apply_irel ();
184
185   /* Initialize the thread library at least a bit since the libgcc
186      functions are using thread functions if these are available and
187      we need to setup errno.  */
188   __pthread_initialize_minimal ();
189
190   /* Set up the stack checker's canary.  */
191   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
192 # ifdef THREAD_SET_STACK_GUARD
193   THREAD_SET_STACK_GUARD (stack_chk_guard);
194 # else
195   __stack_chk_guard = stack_chk_guard;
196 # endif
197 #endif
198
199   /* Register the destructor of the dynamic linker if there is any.  */
200   if (__builtin_expect (rtld_fini != NULL, 1))
201     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
202
203 #ifndef SHARED
204   /* Call the initializer of the libc.  This is only needed here if we
205      are compiling for the static library in which case we haven't
206      run the constructors in `_dl_start_user'.  */
207   __libc_init_first (argc, argv, __environ);
208
209   /* Register the destructor of the program, if any.  */
210   if (fini)
211     __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
212
213   /* Some security at this point.  Prevent starting a SUID binary where
214      the standard file descriptors are not opened.  We have to do this
215      only for statically linked applications since otherwise the dynamic
216      loader did the work already.  */
217   if (__builtin_expect (__libc_enable_secure, 0))
218     __libc_check_standard_fds ();
219 #endif
220
221   /* Call the initializer of the program, if any.  */
222 #ifdef SHARED
223   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
224     GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
225 #endif
226   if (init)
227     (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
228
229 #ifdef SHARED
230   /* Auditing checkpoint: we have a new object.  */
231   if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
232     {
233       struct audit_ifaces *afct = GLRO(dl_audit);
234       struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
235       for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
236         {
237           if (afct->preinit != NULL)
238             afct->preinit (&head->l_audit[cnt].cookie);
239
240           afct = afct->next;
241         }
242     }
243 #endif
244
245 #ifdef SHARED
246   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
247     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
248 #endif
249
250 #ifdef HAVE_CLEANUP_JMP_BUF
251   /* Memory for the cancellation buffer.  */
252   struct pthread_unwind_buf unwind_buf;
253
254   int not_first_call;
255   not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
256   if (__builtin_expect (! not_first_call, 1))
257     {
258       struct pthread *self = THREAD_SELF;
259
260       /* Store old info.  */
261       unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
262       unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
263
264       /* Store the new cleanup handler info.  */
265       THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
266
267       /* Run the program.  */
268       result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
269     }
270   else
271     {
272       /* Remove the thread-local data.  */
273 # ifdef SHARED
274       PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
275 # else
276       extern void __nptl_deallocate_tsd (void) __attribute ((weak));
277       __nptl_deallocate_tsd ();
278 # endif
279
280       /* One less thread.  Decrement the counter.  If it is zero we
281          terminate the entire process.  */
282       result = 0;
283 # ifdef SHARED
284       unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
285 #  ifdef PTR_DEMANGLE
286       PTR_DEMANGLE (ptr);
287 #  endif
288 # else
289       extern unsigned int __nptl_nthreads __attribute ((weak));
290       unsigned int *const ptr = &__nptl_nthreads;
291 # endif
292
293       if (! atomic_decrement_and_test (ptr))
294         /* Not much left to do but to exit the thread, not the process.  */
295         __exit_thread (0);
296     }
297 #else
298   /* Nothing fancy, just call the function.  */
299   result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
300 #endif
301
302   exit (result);
303 }