diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-10-01 05:30:25 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-10-01 05:30:25 +0000 |
commit | b58a631942341b6ccb62ab400e862f404e22dbbf (patch) | |
tree | 0c6e622729b6c98417a15c0b7c10279c17ca0038 /libc | |
parent | 351c1d9029844a97d2771da883fc2b432d5e1bd4 (diff) |
This commit contains a patch from Stefan Allius <allius@atecom.com> to change
how uClibc handles _init and _fini, allowing shared lib constructors and
destructors to initialize things in the correct sequence. Stefan ported the SH
architecture. I then ported x86, arm, and mips. x86 and arm are working fine,
but I don't think I quite got things correct for mips.
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Makefile | 4 | ||||
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 167 | ||||
-rw-r--r-- | libc/sysdeps/linux/arm/crt0.S | 28 | ||||
-rw-r--r-- | libc/sysdeps/linux/i386/crt0.S | 27 | ||||
-rw-r--r-- | libc/sysdeps/linux/mips/crt0.S | 17 | ||||
-rw-r--r-- | libc/sysdeps/linux/sh/crt0.S | 49 |
6 files changed, 185 insertions, 107 deletions
diff --git a/libc/Makefile b/libc/Makefile index 401a56695..1809779d6 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -53,9 +53,9 @@ shared: $(TOPDIR)lib/$(LIBNAME) /bin/sh $(TOPDIR)../extra/scripts/get-needed-libgcc-objects.sh) $(LD) $(LDFLAGS) $(VERSION_SCRIPT) -soname=$(SHARED_MAJORNAME) -o $(SHARED_FULLNAME) \ --whole-archive ./tmp/libgcc-need.a $(LIBNAME) --no-whole-archive \ - $(TOPDIR)/libc/misc/internals/interp.o \ + -init __uClibc_init $(TOPDIR)/libc/misc/internals/interp.o \ $(LIBGCC) - @/bin/true #rm -rf tmp + @true #rm -rf tmp install -d $(TOPDIR)lib rm -f $(TOPDIR)lib/$(SHARED_FULLNAME) install -m 644 $(SHARED_FULLNAME) $(TOPDIR)lib diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 53f897d9f..aa4655cec 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -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); +/* __uClibc_init completely initialize uClibc so it is ready to use. + * + * 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) { - /* If we are dynamically linked the shared lib loader - * already did this for us. But if we are statically - * linked, we need to do this for ourselves. */ - if (__environ==NULL) { - /* Statically linked. */ - __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(); + /* Before we start initialzing uClibc we have to call + * __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 - /* Some security at this point. Prevent starting a SUID binary - * 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 (); + /* Some security at this point. Prevent starting a SUID binary + * 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__ - /* Initialize the global locale structure. */ - if (likely(_locale_init!=NULL)) - _locale_init(); + /* Initialize the global locale structure. */ + 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(); - - /* Arrange for dtors to run at exit. */ - if (likely(_fini!=NULL && atexit)) { - atexit (&_fini); - } - - /* Run all ctors now. */ - 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; - - /* Set h_errno to 0 as well */ - 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(); + +} + + +/* __uClibc_start_main is the new main stub for uClibc. This function is + * 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)) +{ + + /* If we are dynamically linked the shared lib loader already + * did this for us. But if we are statically linked, we need + * to do this for ourselves. */ + if (__environ==NULL) { + /* Statically linked. */ + __environ = envp; + } + + /* We need to initialize uClibc. If we are dynamically linked this + * may have already been completed by the shared lib loader. We call + * __uClibc_init() regardless, to be sure the right thing happens. */ + __uClibc_init(); + + /* Arrange for the application's dtors to run before we exit. */ + if (app_fini!=NULL && atexit) { + atexit (app_fini); + } + + /* Run all the application's ctors now. */ + if (app_init!=NULL) { + app_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; + + /* Set h_errno to 0 as well */ + if (likely(__h_errno_location!=NULL)) + *(__h_errno_location()) = 0; + + /* + * Finally, invoke application's main and then exit. + */ + exit(main(argc, argv, envp)); +} + + +/* __uClibc_main is the old main stub of the uClibc. This + * 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); } + diff --git a/libc/sysdeps/linux/arm/crt0.S b/libc/sysdeps/linux/arm/crt0.S index 442c9e84b..dc0ec87d8 100644 --- a/libc/sysdeps/linux/arm/crt0.S +++ b/libc/sysdeps/linux/arm/crt0.S @@ -50,20 +50,10 @@ ARM register quick reference: .text .global _start - .global __uClibc_main - .type _start,%function - .type __uClibc_main,%function .text _start: -#if 0 /* some old code the I feel should not be here - davidm */ - @ adjust the data segment base pointer - ldr r3,=__data_start - sub sl,sl,r3 - mov BASEREG,sl -#endif - /* clear the frame pointer */ mov fp, #0 @@ -78,10 +68,11 @@ _start: we find there (hopefully the environment) in r2 */ add r2, r1, r0, lsl #2 add r2, r2, #4 + #else /* - * uClinux stacks look a little different to MMU stacks - * for no good reason + * uClinux stacks look a little different from normal + * MMU-full Linux stacks (for no good reason) */ /* pull argc, argv and envp off the stack */ ldr r0,[sp, #0] @@ -89,8 +80,19 @@ _start: ldr r2,[sp, #8] #endif + /* Store the address of _init in r3 as an argument to main() */ + ldr r3, =_init + + /* Push _fini onto the stack as the final argument to main() */ + stmfd sp!, {r0} + ldr a1, =_fini + stmfd sp!, {r0} + /* Ok, now run uClibc's main() -- shouldn't return */ - bl __uClibc_main + bl __uClibc_start_main + + /* Crash if somehow `exit' returns anyways. */ + bl abort /* Stick in a dummy reference to main(), so that if an application * is linking when the main() function is in a static library (.a) diff --git a/libc/sysdeps/linux/i386/crt0.S b/libc/sysdeps/linux/i386/crt0.S index 3623fe821..97f1fde63 100644 --- a/libc/sysdeps/linux/i386/crt0.S +++ b/libc/sysdeps/linux/i386/crt0.S @@ -33,11 +33,11 @@ Cambridge, MA 02139, USA. */ .text .align 4 -.globl _start - .type _start,@function + .globl _start + .type _start,@function _start: - /* First locate the start of the environment variables */ + /* locate the start of the environment variables */ popl %ecx /* Store argc into %ecx */ movl %esp,%ebx /* Store argv into ebx */ movl %esp,%eax /* Store argv into eax as well*/ @@ -52,7 +52,6 @@ _start: %eax = env ; argv + (argc * 4) + 4 */ - /* Set up an invalid (NULL return address, NULL frame pointer) callers stack frame so anybody unrolling the stack knows where to stop */ @@ -62,20 +61,18 @@ _start: pushl %ebp /* callers %ebp (frame pointer) */ movl %esp,%ebp /* mark callers stack frame as invalid */ - /* Now set the environment, argc, and argv where the app can get to them */ - pushl %eax /* Environment pointer */ - pushl %ebx /* Argument pointer */ - pushl %ecx /* And the argument count */ + /* Push .init and .fini arguments to __uClibc_start_main() on the stack */ + pushl $_fini + pushl $_init -#if 0 - /* Make sure we are not using iBCS2 personality. (i.e. force linux). */ - movl $136,%eax - sub %ebx,%ebx - int $0x80 -#endif + /* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ + pushl %eax /* Environment pointer */ + pushl %ebx /* Argument pointer */ + pushl %ecx /* And the argument count */ /* Ok, now run uClibc's main() -- shouldn't return */ - call __uClibc_main + call __uClibc_start_main + /* Crash if somehow `exit' returns anyways. */ hlt diff --git a/libc/sysdeps/linux/mips/crt0.S b/libc/sysdeps/linux/mips/crt0.S index 6770ab0b1..7ff3b253f 100644 --- a/libc/sysdeps/linux/mips/crt0.S +++ b/libc/sysdeps/linux/mips/crt0.S @@ -30,9 +30,22 @@ __start: addu a2, a0, 1 /* load envp */ sll a2, a2, 2 add a2, a2, a1 + + /* Store the address of _init in a3 as an argument to __uClibc_start_main() */ + la a3, _init + + /* Push _fini onto the stack as the final argument to __uClibc_start_main() + I don't think I am doing this properly but it at least compiles... + */ + la t0, _fini + sw t0,16(sp) + /* Ok, now run uClibc's main() -- shouldn't return */ - jal __uClibc_main - hlt: b hlt /* Crash if somehow it does return. */ + jal __uClibc_start_main + + /* Crash if somehow `exit' returns anyways. */ +hlt: + b hlt /* Stick in a dummy reference to main(), so that if an application * is linking when the main() function is in a static library (.a) diff --git a/libc/sysdeps/linux/sh/crt0.S b/libc/sysdeps/linux/sh/crt0.S index 10915d545..e74ae86c4 100644 --- a/libc/sysdeps/linux/sh/crt0.S +++ b/libc/sysdeps/linux/sh/crt0.S @@ -26,13 +26,6 @@ At this entry point, most registers' values are unspecified, except: - r4 Contains a function pointer to be registered with `atexit'. - This is how the dynamic linker arranges to have DT_FINI - functions called for shared libraries that have been loaded - before this code runs. - WARNING: At that stage only static linker is supported. For - uCLinux we won't bother with r4. - sp The stack contains the arguments and environment: 0(sp) argc 4(sp) argv[0] @@ -42,18 +35,26 @@ ... NULL */ + .file "crt0.S" .text .globl _start .type _start,@function .size _start,_start_end - _start _start: - /* Clear the frame pointer since this is the outermost frame. (in delay slot) */ + /* Clear the frame pointer since this is the outermost frame. */ mov #0, r14 /* Pop argc off the stack and save a pointer to argv */ mov.l @r15+,r4 mov r15, r5 + /* Push the finip argument to __uClibc_start_main() onto the stack */ + mov.l L_fini,r6 + mov.l r6,@-r15 + + /* Setup the value for the initp argument */ + mov.l L_init, r7 + /* * Setup the value for the environment pointer: * r6 = (argc + 1) * 4 @@ -62,27 +63,39 @@ _start: mov r4,r6 add #1,r6 shll2 r6 - add r5,r6 - /* call main */ + /* jump to __uClibc_start_main (argc, argv, envp, app_init, app_fini) */ mov.l L_main, r0 jsr @r0 - nop /* delay slot */ - + add r5, r6 /* delay slot */ /* We should not get here. */ mov.l L_abort, r0 - jsr @r0 - nop /* delay slot */ + jmp @r0 + nop _start_end: .align 2 + .weak _init + .type _init,@function +_init: + rts + nop + +.Lfe1: + .size _init,.Lfe1-_init + .weak _fini + .set _fini,_init L_main: - .long __uClibc_main + .long __uClibc_start_main /* in libuClibc.*.so */ -L_abort: - .long abort +L_init: + .long _init +L_fini: + .long _fini +L_abort: + .long abort /* Stick in a dummy reference to main(), so that if an application * is linking when the main() function is in a static library (.a) @@ -90,5 +103,3 @@ L_abort: L_dummy_main_reference: .long main - .data - |