Remove __ptrvalue, __bounded and __unbounded.
[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 #include <bp-sym.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 BP_SYM (__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 # endif
156 # ifdef DL_SYSDEP_OSCHECK
157   if (!__libc_multiple_libcs)
158     {
159       /* This needs to run to initiliaze _dl_osversion before TLS
160          setup might check it.  */
161       DL_SYSDEP_OSCHECK (__libc_fatal);
162     }
163 # endif
164
165   /* Perform IREL{,A} relocations.  */
166   apply_irel ();
167
168   /* Initialize the thread library at least a bit since the libgcc
169      functions are using thread functions if these are available and
170      we need to setup errno.  */
171   __pthread_initialize_minimal ();
172
173   /* Set up the stack checker's canary.  */
174   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
175 # ifdef THREAD_SET_STACK_GUARD
176   THREAD_SET_STACK_GUARD (stack_chk_guard);
177 # else
178   __stack_chk_guard = stack_chk_guard;
179 # endif
180 #endif
181
182   /* Register the destructor of the dynamic linker if there is any.  */
183   if (__builtin_expect (rtld_fini != NULL, 1))
184     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
185
186 #ifndef SHARED
187   /* Call the initializer of the libc.  This is only needed here if we
188      are compiling for the static library in which case we haven't
189      run the constructors in `_dl_start_user'.  */
190   __libc_init_first (argc, argv, __environ);
191
192   /* Register the destructor of the program, if any.  */
193   if (fini)
194     __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
195
196   /* Some security at this point.  Prevent starting a SUID binary where
197      the standard file descriptors are not opened.  We have to do this
198      only for statically linked applications since otherwise the dynamic
199      loader did the work already.  */
200   if (__builtin_expect (__libc_enable_secure, 0))
201     __libc_check_standard_fds ();
202 #endif
203
204   /* Call the initializer of the program, if any.  */
205 #ifdef SHARED
206   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
207     GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
208 #endif
209   if (init)
210     (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
211
212 #ifdef SHARED
213   /* Auditing checkpoint: we have a new object.  */
214   if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
215     {
216       struct audit_ifaces *afct = GLRO(dl_audit);
217       struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
218       for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
219         {
220           if (afct->preinit != NULL)
221             afct->preinit (&head->l_audit[cnt].cookie);
222
223           afct = afct->next;
224         }
225     }
226 #endif
227
228 #ifdef SHARED
229   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
230     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
231 #endif
232
233 #ifdef HAVE_CLEANUP_JMP_BUF
234   /* Memory for the cancellation buffer.  */
235   struct pthread_unwind_buf unwind_buf;
236
237   int not_first_call;
238   not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
239   if (__builtin_expect (! not_first_call, 1))
240     {
241       struct pthread *self = THREAD_SELF;
242
243       /* Store old info.  */
244       unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
245       unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
246
247       /* Store the new cleanup handler info.  */
248       THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
249
250       /* Run the program.  */
251       result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
252     }
253   else
254     {
255       /* Remove the thread-local data.  */
256 # ifdef SHARED
257       PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
258 # else
259       extern void __nptl_deallocate_tsd (void) __attribute ((weak));
260       __nptl_deallocate_tsd ();
261 # endif
262
263       /* One less thread.  Decrement the counter.  If it is zero we
264          terminate the entire process.  */
265       result = 0;
266 # ifdef SHARED
267       unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
268 #  ifdef PTR_DEMANGLE
269       PTR_DEMANGLE (ptr);
270 #  endif
271 # else
272       extern unsigned int __nptl_nthreads __attribute ((weak));
273       unsigned int *const ptr = &__nptl_nthreads;
274 # endif
275
276       if (! atomic_decrement_and_test (ptr))
277         /* Not much left to do but to exit the thread, not the process.  */
278         __exit_thread (0);
279     }
280 #else
281   /* Nothing fancy, just call the function.  */
282   result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
283 #endif
284
285   exit (result);
286 }