|
@@ -20,8 +20,6 @@
|
|
|
* Prototypes.
|
|
|
*/
|
|
|
extern int main(int argc, char **argv, char **envp);
|
|
|
-extern void weak_function _init(void);
|
|
|
-extern void weak_function _fini(void);
|
|
|
extern void weak_function _stdio_init(void);
|
|
|
extern int *weak_const_function __errno_location(void);
|
|
|
extern int *weak_const_function __h_errno_location(void);
|
|
@@ -36,10 +34,11 @@ extern void weak_function __pthread_initialize_minimal(void);
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
|
* Declare the __environ global variable and create a weak alias environ.
|
|
|
- * Note: Apparently we must initialize __environ for the weak environ
|
|
|
- * symbol to be included.
|
|
|
+ * Note: Apparently we must initialize __environ to ensure that the weak
|
|
|
+ * environ symbol is also included.
|
|
|
*/
|
|
|
|
|
|
char **__environ = 0;
|
|
@@ -47,68 +46,124 @@ weak_alias(__environ, environ);
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
+ *
|
|
|
+ * On ELF systems (with a dynamic loader) this function must be called
|
|
|
+ * from the dynamic loader (see TIS and ELF Specification), so that
|
|
|
+ * constructors of shared libraries (which depend on libc) can use all
|
|
|
+ * the libc code without restriction. For this we link the shared
|
|
|
+ * version of the uClibc with -init __uClibc_init so DT_INIT for
|
|
|
+ * uClibc is the address of __uClibc_init
|
|
|
+ *
|
|
|
+ * In all other cases we call it from the main stub
|
|
|
+ * __uClibc_start_main.
|
|
|
+ */
|
|
|
|
|
|
-void __attribute__ ((__noreturn__))
|
|
|
-__uClibc_main(int argc, char **argv, char **envp)
|
|
|
+void __uClibc_init(void)
|
|
|
{
|
|
|
-
|
|
|
- * already did this for us. But if we are statically
|
|
|
- * linked, we need to do this for ourselves. */
|
|
|
- if (__environ==NULL) {
|
|
|
-
|
|
|
- __environ = envp;
|
|
|
- }
|
|
|
+ static int been_there_done_that = 0;
|
|
|
+
|
|
|
+ if (been_there_done_that)
|
|
|
+ return;
|
|
|
+ been_there_done_that++;
|
|
|
|
|
|
#ifdef __UCLIBC_HAS_THREADS__
|
|
|
- if (likely(__pthread_initialize_minimal!=NULL))
|
|
|
- __pthread_initialize_minimal();
|
|
|
+
|
|
|
+ * __pthread_initialize_minimal so we can use pthread_locks
|
|
|
+ * whenever they are needed.
|
|
|
+ */
|
|
|
+ if (likely(__pthread_initialize_minimal!=NULL))
|
|
|
+ __pthread_initialize_minimal();
|
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
|
-
|
|
|
- * where the standard file descriptors are not opened. We have
|
|
|
- * to do this only for statically linked applications since
|
|
|
- * otherwise the dynamic loader did the work already. */
|
|
|
- if (unlikely (__libc_enable_secure!=NULL))
|
|
|
- __libc_check_standard_fds ();
|
|
|
+
|
|
|
+ * where the standard file descriptors are not opened. We have
|
|
|
+ * to do this only for statically linked applications since
|
|
|
+ * otherwise the dynamic loader did the work already. */
|
|
|
+ if (unlikely (__libc_enable_secure!=NULL))
|
|
|
+ __libc_check_standard_fds ();
|
|
|
#endif
|
|
|
|
|
|
#ifdef __UCLIBC_HAS_LOCALE__
|
|
|
-
|
|
|
- if (likely(_locale_init!=NULL))
|
|
|
- _locale_init();
|
|
|
+
|
|
|
+ if (likely(_locale_init!=NULL))
|
|
|
+ _locale_init();
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
- * Initialize stdio here. In the static library case, this will
|
|
|
- * be bypassed if not needed because of the weak alias above.
|
|
|
- */
|
|
|
- if (likely(_stdio_init != NULL))
|
|
|
- _stdio_init();
|
|
|
-
|
|
|
-
|
|
|
- if (likely(_fini!=NULL && atexit)) {
|
|
|
- atexit (&_fini);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (likely(_init!=NULL))
|
|
|
- _init();
|
|
|
-
|
|
|
-
|
|
|
- * Note: It is possible that any initialization done above could
|
|
|
- * have resulted in errno being set nonzero, so set it to 0 before
|
|
|
- * we call main.
|
|
|
- */
|
|
|
- if (likely(__errno_location!=NULL))
|
|
|
- *(__errno_location()) = 0;
|
|
|
-
|
|
|
-
|
|
|
- if (likely(__h_errno_location!=NULL))
|
|
|
- *(__h_errno_location()) = 0;
|
|
|
-
|
|
|
-
|
|
|
- * Finally, invoke application's main and then exit.
|
|
|
- */
|
|
|
- exit(main(argc, argv, envp));
|
|
|
+
|
|
|
+ * Initialize stdio here. In the static library case, this will
|
|
|
+ * be bypassed if not needed because of the weak alias above.
|
|
|
+ */
|
|
|
+ if (likely(_stdio_init != NULL))
|
|
|
+ _stdio_init();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * called from crt0 (version 0.9.16 or newer), after ALL shared libraries
|
|
|
+ * are initialized, just before we call the application's main function.
|
|
|
+ */
|
|
|
+void __attribute__ ((__noreturn__))
|
|
|
+__uClibc_start_main(int argc, char **argv, char **envp,
|
|
|
+ void (*app_init)(void), void (*app_fini)(void))
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ * did this for us. But if we are statically linked, we need
|
|
|
+ * to do this for ourselves. */
|
|
|
+ if (__environ==NULL) {
|
|
|
+
|
|
|
+ __environ = envp;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * may have already been completed by the shared lib loader. We call
|
|
|
+ * __uClibc_init() regardless, to be sure the right thing happens. */
|
|
|
+ __uClibc_init();
|
|
|
+
|
|
|
+
|
|
|
+ if (app_fini!=NULL && atexit) {
|
|
|
+ atexit (app_fini);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (app_init!=NULL) {
|
|
|
+ app_init();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * have resulted in errno being set nonzero, so set it to 0 before
|
|
|
+ * we call main.
|
|
|
+ */
|
|
|
+ if (likely(__errno_location!=NULL))
|
|
|
+ *(__errno_location()) = 0;
|
|
|
+
|
|
|
+
|
|
|
+ if (likely(__h_errno_location!=NULL))
|
|
|
+ *(__h_errno_location()) = 0;
|
|
|
+
|
|
|
+
|
|
|
+ * Finally, invoke application's main and then exit.
|
|
|
+ */
|
|
|
+ exit(main(argc, argv, envp));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * function is called from crt0 (uClibc 0.9.15 and older) after
|
|
|
+ * ALL shared libraries are initialized, and just before we call
|
|
|
+ * the application's main() function.
|
|
|
+ *
|
|
|
+ * Attention: This stub does not call the .init/.fini sections of
|
|
|
+ * the application. If you need this, please fix your uClibc port
|
|
|
+ * so that __uClibc_start_main is called by your crt0.S with
|
|
|
+ * _init and _fini properly set.
|
|
|
+*/
|
|
|
+void __attribute__ ((__noreturn__))
|
|
|
+__uClibc_main(int argc, char **argv, char ** envp)
|
|
|
+{
|
|
|
+ __uClibc_start_main(argc, argv, envp, NULL, NULL);
|
|
|
}
|
|
|
+
|