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