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