diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2001-02-19 00:24:52 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2001-02-19 00:24:52 +0000 |
commit | dfe2d42547de8197f850f3ff0dfdc3caa4682518 (patch) | |
tree | 0b2969dbdd6c65f1fb5832e25d28bffa9570084a /libc | |
parent | 438aac726283dfffa6a5cf84b4acf6df0250af94 (diff) |
Create __uClibc_main to handle what can be done in C instead of each arch's
respective crt0.S. crt0.S should now only be responsible for setting things
up to call __uClibc_main(argc, argv, envp), which will do any other necessary
setup (setting global __environ, stdio init, etc), call main, and exit. This
should ease both maintainance and porting.
Diffstat (limited to 'libc')
-rw-r--r-- | libc/misc/internals/Makefile | 2 | ||||
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 80 | ||||
-rw-r--r-- | libc/stdlib/abort.c | 9 | ||||
-rw-r--r-- | libc/stdlib/atexit.c | 40 | ||||
-rw-r--r-- | libc/sysdeps/linux/i386/crt0.S | 33 |
5 files changed, 114 insertions, 50 deletions
diff --git a/libc/misc/internals/Makefile b/libc/misc/internals/Makefile index 863d32401..2f0496d9a 100644 --- a/libc/misc/internals/Makefile +++ b/libc/misc/internals/Makefile @@ -24,7 +24,7 @@ TOPDIR=../../ include $(TOPDIR)Rules.mak LIBC=$(TOPDIR)libc.a -CSRC=ultostr.c ltostr.c +CSRC=ultostr.c ltostr.c __uClibc_main.c ifeq ($(HAS_FLOATS),true) CSRC += dtostr.c zoicheck.c endif diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c new file mode 100644 index 000000000..088754ecc --- /dev/null +++ b/libc/misc/internals/__uClibc_main.c @@ -0,0 +1,80 @@ +/* + * Manuel Novoa III Feb 2001 + * + * __uClibc_main is the routine to be called by all the arch-specific + * versions of crt0.S in uClibc. + * + * It is meant to handle any special initialization needed by the library + * such as setting the global variable(s) __environ (environ) and + * initializing the stdio package. Using weak symbols, the latter is + * avoided in the static library case. + */ + +#include <stdlib.h> +#include <unistd.h> + +/* + * Prototypes. + */ + +extern int main(int argc, char **argv, char **envp); + +void __uClibc_main(int argc, char **argv, char **envp) + __attribute__ ((__noreturn__)); + +/* + * Define an empty function and use it as a weak alias for the stdio + * initialization routine. That way we don't pull in all the stdio + * code unless we need to. Similarly, do the same for __stdio_close_all + * so as not to include atexit unnecessarily. + * + * NOTE!!! This is only true for the _static_ case!!! + */ + +void __uClibc_empty_func(void) +{ +} + + __attribute__ ((__weak__, __alias__("__uClibc_empty_func"))) +void __init_stdio(void); + + __attribute__ ((__weak__, __alias__("__uClibc_empty_func"))) +void __stdio_close_all(void); + +typedef void (*vfuncp) (void); +vfuncp __uClibc_cleanup = __stdio_close_all; + +/* + * Now for our main routine. + */ + +void __uClibc_main(int argc, char **argv, char **envp) +{ + /* + * Initialize the global variable __environ. + */ + __environ = envp; + + /* + * Initialize stdio here. In the static library case, this will + * be bypassed if not needed because of the weak alias above. + */ + __init_stdio(); + + /* + * Finally, invoke application's main and then exit. + */ + exit(main(argc, argv, envp)); +} + +/* + * Declare the __environ global variable and create a weak alias environ. + */ + +char **__environ = 0; + +__asm__(".weak environ;environ = __environ"); + + + + diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c index 23510e913..7b7d6bb50 100644 --- a/libc/stdlib/abort.c +++ b/libc/stdlib/abort.c @@ -25,8 +25,8 @@ Cambridge, MA 02139, USA. */ #include <signal.h> #include <errno.h> -typedef void (*vfuncp) (); -extern vfuncp __cleanup; +typedef void (*vfuncp) (void); +extern vfuncp __uClibc_cleanup; extern void _exit __P((int __status)) __attribute__ ((__noreturn__)); /* Cause an abnormal program termination with core-dump. */ @@ -38,8 +38,9 @@ void abort(void) sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); } - if (__cleanup) - __cleanup(); + if (__uClibc_cleanup) { /* Not already executing __uClibc_cleanup. */ + __uClibc_cleanup(); + } while (1) if (raise(SIGABRT)) diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index c720d4e90..b18e7951d 100644 --- a/libc/stdlib/atexit.c +++ b/libc/stdlib/atexit.c @@ -4,45 +4,58 @@ */ /* - * Manuel Novoa III Dec 2000 + * Dec 2000 Manuel Novoa III * - * Modifications: * Made atexit handling conform to standards... i.e. no args. * Removed on_exit since it did not match gnu libc definition. * Combined atexit and __do_exit into one object file. + * + * Feb 2000 Manuel Novoa III + * + * Reworked file after addition of __uClibc_main. + * Changed name of __do_exit to atexit_handler. + * Changed name of __cleanup to __uClibc_cleanup. + * Moved declaration of __uClibc_cleanup to __uClibc_main + * where it is initialized with (possibly weak alias) + * __stdio_close_all. */ #include <stdlib.h> #include <errno.h> typedef void (*vfuncp) (void); -extern vfuncp __cleanup; +extern vfuncp __uClibc_cleanup; #ifdef L_atexit +extern void __stdio_close_all(void); + static vfuncp __atexit_table[__UCLIBC_MAX_ATEXIT]; static int __atexit_count = 0; -static void __do_exit(void) +static void atexit_handler(void) { - int count = __atexit_count - 1; + int count; - __atexit_count = -1; /* ensure no more will be added */ - __cleanup = 0; /* Calling exit won't re-do this */ + /* + * Guard against more functions being added and againt being reinvoked. + */ + __uClibc_cleanup = 0; /* In reverse order */ - for (; count >= 0; count--) { + for (count = __atexit_count ; count-- ; ) { (*__atexit_table[count])(); } + __stdio_close_all(); } int atexit(vfuncp ptr) { - if ((__atexit_count < 0) || (__atexit_count >= __UCLIBC_MAX_ATEXIT)) { + if ((__uClibc_cleanup == 0) || (__atexit_count >= __UCLIBC_MAX_ATEXIT)) { errno = ENOMEM; return -1; } if (ptr) { - __cleanup = __do_exit; + __uClibc_cleanup = atexit_handler; __atexit_table[__atexit_count++] = ptr; } return 0; @@ -50,12 +63,11 @@ int atexit(vfuncp ptr) #endif #ifdef L_exit -vfuncp __cleanup = 0; - void exit(int rv) { - if (__cleanup) - __cleanup(); + if (__uClibc_cleanup) { /* Not already executing __uClibc_cleanup. */ + __uClibc_cleanup(); + } _exit(rv); } #endif diff --git a/libc/sysdeps/linux/i386/crt0.S b/libc/sysdeps/linux/i386/crt0.S index a87287bc3..79e0a6748 100644 --- a/libc/sysdeps/linux/i386/crt0.S +++ b/libc/sysdeps/linux/i386/crt0.S @@ -30,11 +30,7 @@ Cambridge, MA 02139, USA. */ NULL */ -.global __environ .global _start -.global exit -.global main -.global _start_exit .text _start: @@ -73,30 +69,5 @@ _start: sub %ebx,%ebx int $0x80 - /* set up __environ */ - movl 8(%esp),%eax - movl %eax,__environ - - /* Ok, now run main() */ - call main - pushl %eax - call exit - - /* Just in case _exit fails... We use int $0x80 for __exit(). */ - popl %ebx - .align 4,0x90 -_start_exit: - movl $1,%eax - int $0x80 - jmp _start_exit - .align 4,0x90 -_void_void_null_func: - ret - -.data -__environ: - .long 0 -.weak environ -.align 4 -environ = __environ - + /* Ok, now run uClibc's main() -- shouldn't return */ + call __uClibc_main |