nptl threads: Fix bug in using a weak variable.
[uclibc-ng.git] / libc / misc / internals / __uClibc_main.c
blob849bca8d43228c1cd454045b675ab258c2a1d349
1 /*
2 * Copyright (C) 2006 by Steven J. Hill <sjhill@realitydiluted.com>
3 * Copyright (C) 2001 by Manuel Novoa III <mjn3@uclibc.org>
4 * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
6 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
8 * __uClibc_main is the routine to be called by all the arch-specific
9 * versions of crt1.S in uClibc.
11 * It is meant to handle any special initialization needed by the library
12 * such as setting the global variable(s) __environ (environ) and
13 * initializing the stdio package. Using weak symbols, the latter is
14 * avoided in the static library case.
17 #include <features.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <elf.h>
22 #include <link.h>
23 #include <bits/uClibc_page.h>
24 #include <paths.h>
25 #include <errno.h>
26 #include <netdb.h>
27 #include <stdio.h>
28 #ifndef __ARCH_HAS_NO_LDSO__
29 #include <fcntl.h>
30 #endif
31 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
32 #include <not-cancel.h>
33 #include <atomic.h>
34 #include <tls.h>
35 #endif
36 #ifdef __UCLIBC_HAS_THREADS__
37 #include <pthread.h>
38 #endif
39 #ifdef __UCLIBC_HAS_LOCALE__
40 #include <locale.h>
41 #endif
43 /* Are we in a secure process environment or are we dealing
44 * with setuid stuff? If we are dynamically linked, then we
45 * already have _dl_secure, otherwise we need to re-examine
46 * auxvt[] below.
48 int _pe_secure = 0;
49 libc_hidden_data_def(_pe_secure)
51 #if !defined(SHARED) && defined(__FDPIC__)
52 struct funcdesc_value
54 void *entry_point;
55 void *got_value;
56 } __attribute__((__aligned__(8)));
59 /* Prevent compiler optimization that removes GOT assignment.
61 Due to optimization passes (block split and move), in the rare case
62 where use r9 is the single instruction in a block we can have the
63 following behaviour:
64 - this block is marked as a forward block since use is not
65 considered as an active instruction after reload pass.
67 - In this case a jump in this block can be moved to the start of the
68 next one and so remove use in this flow of instructions which can
69 lead to a removal of r9 restoration after a call. */
70 #define _dl_stabilize_funcdesc(val) \
71 ({ __asm__ ("" : "+m" (*(val))); (val); })
73 static void fdpic_init_array_jump(void *addr)
75 struct funcdesc_value *fm = (struct funcdesc_value *) fdpic_init_array_jump;
76 struct funcdesc_value fd = {addr, fm->got_value};
78 void (*pf)(void) = (void*) _dl_stabilize_funcdesc(&fd);
80 (*pf)();
82 #endif
84 #ifndef SHARED
85 void *__libc_stack_end = NULL;
87 # ifdef __UCLIBC_HAS_SSP__
88 # include <dl-osinfo.h>
89 static uintptr_t stack_chk_guard;
90 # ifndef THREAD_SET_STACK_GUARD
91 /* Only exported for architectures that don't store the stack guard canary
92 * in thread local area. */
93 /* for gcc-4.1 non-TLS */
94 uintptr_t __stack_chk_guard attribute_relro;
95 # endif
96 # endif
99 * Needed to initialize _dl_phdr when statically linked
102 void internal_function _dl_aux_init (ElfW(auxv_t) *av);
104 #ifdef __UCLIBC_HAS_THREADS__
106 * uClibc internal locking requires that we have weak aliases
107 * for dummy functions in case a single threaded application is linked.
108 * This needs to be in compilation unit that is pulled always
109 * in or linker will disregard these weaks.
112 static int __pthread_return_0 (pthread_mutex_t *unused) { return 0; }
113 weak_alias (__pthread_return_0, __pthread_mutex_lock)
114 weak_alias (__pthread_return_0, __pthread_mutex_trylock)
115 weak_alias (__pthread_return_0, __pthread_mutex_unlock)
117 int weak_function
118 __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
120 return 0;
123 void weak_function
124 _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *__buffer,
125 void (*__routine) (void *), void *__arg)
127 __buffer->__routine = __routine;
128 __buffer->__arg = __arg;
131 void weak_function
132 _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *__buffer,
133 int __execute)
135 if (__execute)
136 __buffer->__routine(__buffer->__arg);
139 #endif /* __UCLIBC_HAS_THREADS__ */
141 #endif /* !SHARED */
143 /* Defeat compiler optimization which assumes function addresses are never NULL */
144 static __always_inline int not_null_ptr(const void *p)
146 const void *q;
147 __asm__ (""
148 : "=r" (q) /* output */
149 : "0" (p) /* input */
151 return q != 0;
155 * Prototypes.
157 #ifdef __UCLIBC_HAS_THREADS__
158 #if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED)
159 extern void weak_function __pthread_initialize_minimal(void);
160 #else
161 extern void __pthread_initialize_minimal(void);
162 #endif
163 #endif
165 #ifndef SHARED
166 extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
167 #endif
169 /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation and finalisation
170 * is handled by the routines passed to __uClibc_main(). */
171 #if defined (__UCLIBC_CTOR_DTOR__) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
172 extern void _dl_app_init_array(void);
173 extern void _dl_app_fini_array(void);
174 # ifndef SHARED
175 /* These magic symbols are provided by the linker. */
176 extern void (*__preinit_array_start []) (void) attribute_hidden;
177 extern void (*__preinit_array_end []) (void) attribute_hidden;
178 extern void (*__init_array_start []) (void) attribute_hidden;
179 extern void (*__init_array_end []) (void) attribute_hidden;
180 extern void (*__fini_array_start []) (void) attribute_hidden;
181 extern void (*__fini_array_end []) (void) attribute_hidden;
182 # endif
183 #endif
185 #ifdef SHARED
186 extern int _dl_secure;
187 #endif
188 extern size_t _dl_pagesize;
190 const char *__uclibc_progname = "";
191 #if !defined __UCLIBC_HAS___PROGNAME__ && defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
192 # define __progname program_invocation_short_name
193 # define __progname_full program_invocation_name
194 #endif
195 #if defined __UCLIBC_HAS___PROGNAME__ || (defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__)
196 const char *__progname = "";
197 /* psm: why have a visible __progname_full? */
198 const char *__progname_full = "";
199 # if defined __UCLIBC_HAS___PROGNAME__ && defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
200 weak_alias (__progname, program_invocation_short_name)
201 weak_alias (__progname_full, program_invocation_name)
202 # endif
203 #endif
206 * Declare the __environ global variable and create a weak alias environ.
207 * This must be initialized; we cannot have a weak alias into bss.
209 char **__environ = 0;
210 weak_alias(__environ, environ)
212 size_t __pagesize = 0;
214 #ifndef O_NOFOLLOW
215 # define O_NOFOLLOW 0
216 #endif
218 #ifndef __ARCH_HAS_NO_LDSO__
219 static void __check_one_fd(int fd, int mode)
221 /* Check if the specified fd is already open */
222 if (fcntl(fd, F_GETFD) == -1)
224 /* The descriptor is probably not open, so try to use /dev/null */
225 int nullfd = open(_PATH_DEVNULL, mode);
226 /* /dev/null is major=1 minor=3. Make absolutely certain
227 * that is in fact the device that we have opened and not
228 * some other wierd file... [removed in uclibc] */
229 if (nullfd!=fd)
231 abort();
236 #ifndef SHARED
237 static int __check_suid(void)
239 uid_t uid, euid;
240 gid_t gid, egid;
242 uid = getuid();
243 euid = geteuid();
244 if (uid != euid)
245 return 1;
246 gid = getgid();
247 egid = getegid();
248 if (gid != egid)
249 return 1;
250 return 0; /* we are not suid */
252 #endif
253 #endif
255 /* __uClibc_init completely initialize uClibc so it is ready to use.
257 * On ELF systems (with a dynamic loader) this function must be called
258 * from the dynamic loader (see TIS and ELF Specification), so that
259 * constructors of shared libraries (which depend on libc) can use all
260 * the libc code without restriction. For this we link the shared
261 * version of the uClibc with -init __uClibc_init so DT_INIT for
262 * uClibc is the address of __uClibc_init
264 * In all other cases we call it from the main stub
265 * __uClibc_main.
268 extern void __uClibc_init(void) attribute_hidden;
269 void __uClibc_init(void)
271 /* Don't recurse */
272 if (__pagesize)
273 return;
275 /* Setup an initial value. This may not be perfect, but is
276 * better than malloc using __pagesize=0 for atexit, ctors, etc. */
277 __pagesize = PAGE_SIZE;
279 #ifdef __UCLIBC_HAS_THREADS__
281 #if defined (__UCLIBC_HAS_THREADS_NATIVE__) && !defined (SHARED)
282 /* Unlike in the dynamically linked case the dynamic linker has not
283 taken care of initializing the TLS data structures. */
284 __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
285 #endif
287 /* Before we start initializing uClibc we have to call
288 * __pthread_initialize_minimal so we can use pthread_locks
289 * whenever they are needed.
291 #if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED)
292 if (likely(__pthread_initialize_minimal!=NULL))
293 #endif
294 __pthread_initialize_minimal();
295 #endif
297 #ifndef SHARED
298 # ifdef __UCLIBC_HAS_SSP__
299 /* Set up the stack checker's canary. */
300 stack_chk_guard = _dl_setup_stack_chk_guard();
301 # ifdef THREAD_SET_STACK_GUARD
302 THREAD_SET_STACK_GUARD (stack_chk_guard);
303 # else
304 __stack_chk_guard = stack_chk_guard;
305 # endif
306 # endif
307 #endif
309 #ifdef __UCLIBC_HAS_LOCALE__
310 /* Initialize the global locale structure. */
311 if (likely(not_null_ptr(_locale_init)))
312 _locale_init();
313 #endif
316 * Initialize stdio here. In the static library case, this will
317 * be bypassed if not needed because of the weak alias above.
318 * Thus we get a nice size savings because the stdio functions
319 * won't be pulled into the final static binary unless used.
321 if (likely(not_null_ptr(_stdio_init)))
322 _stdio_init();
326 #ifdef __UCLIBC_CTOR_DTOR__
327 void attribute_hidden (*__app_fini)(void) = NULL;
328 #endif
330 void attribute_hidden (*__rtld_fini)(void) = NULL;
332 extern void __uClibc_fini(void) attribute_hidden;
333 void __uClibc_fini(void)
335 #ifdef __UCLIBC_CTOR_DTOR__
336 /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array finalisation is handled
337 * by __app_fini. */
338 # ifdef SHARED
339 _dl_app_fini_array();
340 # elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
341 size_t i = __fini_array_end - __fini_array_start;
342 while (i-- > 0)
343 #if !defined(SHARED) && defined(__FDPIC__)
344 fdpic_init_array_jump(__fini_array_start[i]);
345 #else
346 (*__fini_array_start [i]) ();
347 #endif
348 # endif
349 if (__app_fini != NULL)
350 (__app_fini)();
351 #endif
352 if (__rtld_fini != NULL)
353 (__rtld_fini)();
356 #ifndef SHARED
357 extern void __nptl_deallocate_tsd (void) __attribute ((weak));
358 extern unsigned int __nptl_nthreads __attribute ((weak));
359 #endif
361 /* __uClibc_main is the new main stub for uClibc. This function is
362 * called from crt1 (version 0.9.28 or newer), after ALL shared libraries
363 * are initialized, just before we call the application's main function.
365 void __uClibc_main(int (*main)(int, char **, char **), int argc,
366 char **argv, void (*app_init)(void), void (*app_fini)(void),
367 void (*rtld_fini)(void),
368 void *stack_end attribute_unused) attribute_noreturn;
369 void __uClibc_main(int (*main)(int, char **, char **), int argc,
370 char **argv, void (*app_init)(void), void (*app_fini)(void),
371 void (*rtld_fini)(void), void *stack_end attribute_unused)
373 #if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
374 unsigned long *aux_dat;
375 ElfW(auxv_t) auxvt[AT_EGID + 1];
376 #endif
378 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
379 /* Result of the 'main' function. */
380 int result;
381 #endif
383 #ifndef SHARED
384 __libc_stack_end = stack_end;
385 #endif
387 __rtld_fini = rtld_fini;
389 /* The environment begins right after argv. */
390 __environ = &argv[argc + 1];
392 /* If the first thing after argv is the arguments
393 * then the environment is empty. */
394 if ((char *) __environ == *argv) {
395 /* Make __environ point to the NULL at argv[argc] */
396 __environ = &argv[argc];
399 #if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
400 /* Pull stuff from the ELF header when possible */
401 memset(auxvt, 0x00, sizeof(auxvt));
402 aux_dat = (unsigned long*)__environ;
403 while (*aux_dat) {
404 aux_dat++;
406 aux_dat++;
407 while (*aux_dat) {
408 ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
409 if (auxv_entry->a_type <= AT_EGID) {
410 memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
412 aux_dat += 2;
414 /* Get the program headers (_dl_phdr) from the aux vector
415 It will be used into __libc_setup_tls. */
417 _dl_aux_init (auxvt);
418 #endif
420 /* We need to initialize uClibc. If we are dynamically linked this
421 * may have already been completed by the shared lib loader. We call
422 * __uClibc_init() regardless, to be sure the right thing happens. */
423 __uClibc_init();
425 #ifndef __ARCH_HAS_NO_LDSO__
426 /* Make certain getpagesize() gives the correct answer.
427 * _dl_pagesize is defined into ld.so if SHARED or into libc.a otherwise. */
428 __pagesize = _dl_pagesize;
430 #ifndef SHARED
431 /* Prevent starting SUID binaries where the stdin. stdout, and
432 * stderr file descriptors are not already opened. */
433 if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) ||
434 (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
435 (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val ||
436 auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val)))
437 #else
438 if (_dl_secure)
439 #endif
441 __check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW);
442 __check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW);
443 __check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW);
444 _pe_secure = 1 ;
446 else
447 _pe_secure = 0 ;
448 #endif
450 __uclibc_progname = *argv;
451 #if defined __UCLIBC_HAS___PROGNAME__ || (defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__)
452 if (*argv != NULL) {
453 __progname_full = *argv;
454 __progname = strrchr(*argv, '/');
455 if (__progname != NULL)
456 ++__progname;
457 else
458 __progname = *argv;
460 #endif
462 #ifdef __UCLIBC_CTOR_DTOR__
463 /* Arrange for the application's dtors to run before we exit. */
464 __app_fini = app_fini;
466 /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled
467 * by __app_init. */
468 # if !defined (SHARED) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
469 /* For dynamically linked executables the preinit array is executed by
470 the dynamic linker (before initializing any shared object).
471 For static executables, preinit happens rights before init. */
473 const size_t size = __preinit_array_end - __preinit_array_start;
474 size_t i;
475 for (i = 0; i < size; i++)
476 #if !defined(SHARED) && defined(__FDPIC__)
477 fdpic_init_array_jump(__preinit_array_start[i]);
478 #else
479 (*__preinit_array_start [i]) ();
480 #endif
482 # endif
483 /* Run all the application's ctors now. */
484 if (app_init!=NULL) {
485 app_init();
487 /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled
488 * by __app_init. */
489 # ifdef SHARED
490 _dl_app_init_array();
491 # elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__)
493 const size_t size = __init_array_end - __init_array_start;
494 size_t i;
495 for (i = 0; i < size; i++)
496 #if !defined(SHARED) && defined(__FDPIC__)
497 fdpic_init_array_jump(__init_array_start[i]);
498 #else
499 (*__init_array_start [i]) ();
500 #endif
502 # endif
503 #endif
505 /* Note: It is possible that any initialization done above could
506 * have resulted in errno being set nonzero, so set it to 0 before
507 * we call main.
509 if (likely(not_null_ptr(__errno_location)))
510 *(__errno_location()) = 0;
512 /* Set h_errno to 0 as well */
513 if (likely(not_null_ptr(__h_errno_location)))
514 *(__h_errno_location()) = 0;
516 #if defined HAVE_CLEANUP_JMP_BUF && defined __UCLIBC_HAS_THREADS_NATIVE__
517 /* Memory for the cancellation buffer. */
518 struct pthread_unwind_buf unwind_buf;
520 int not_first_call;
521 not_first_call =
522 setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
523 if (__builtin_expect (! not_first_call, 1))
525 struct pthread *self = THREAD_SELF;
527 /* Store old info. */
528 unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
529 unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
531 /* Store the new cleanup handler info. */
532 THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
534 /* Run the program. */
535 result = main (argc, argv, __environ);
537 else
539 /* Remove the thread-local data. */
540 __nptl_deallocate_tsd ();
542 /* One less thread. Decrement the counter. If it is zero we
543 terminate the entire process. */
544 result = 0;
545 unsigned int *const ptr = &__nptl_nthreads;
547 if (ptr && ! atomic_decrement_and_test (ptr))
548 /* Not much left to do but to exit the thread, not the process. */
549 __exit_thread_inline (0);
552 exit (result);
553 #else
555 * Finally, invoke application's main and then exit.
557 exit (main (argc, argv, __environ));
558 #endif