diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c index dad265e1d..fa9f3f32b 100644 --- a/libc/arch-common/bionic/crtbegin.c +++ b/libc/arch-common/bionic/crtbegin.c @@ -36,6 +36,9 @@ void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1; __attribute__ ((section (".init_array"))) void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1; +__attribute__ ((section (".fini_array"))) +void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; + __LIBC_HIDDEN__ #ifdef __i386__ __attribute__((force_align_arg_pointer)) @@ -44,6 +47,7 @@ void _start() { structors_array_t array; array.preinit_array = &__PREINIT_ARRAY__; array.init_array = &__INIT_ARRAY__; + array.fini_array = &__FINI_ARRAY__; void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*)); #ifdef __x86_64__ diff --git a/libc/arch-mips/bionic/crtbegin.c b/libc/arch-mips/bionic/crtbegin.c index 33f7f407d..28e8817f9 100644 --- a/libc/arch-mips/bionic/crtbegin.c +++ b/libc/arch-mips/bionic/crtbegin.c @@ -36,11 +36,15 @@ void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1; __attribute__ ((section (".init_array"))) void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1; +__attribute__ ((section (".fini_array"))) +void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; + __LIBC_HIDDEN__ void do_mips_start(void *raw_args) { structors_array_t array; array.preinit_array = &__PREINIT_ARRAY__; array.init_array = &__INIT_ARRAY__; + array.fini_array = &__FINI_ARRAY__; __libc_init(raw_args, NULL, &main, &array); } diff --git a/libc/arch-mips64/bionic/crtbegin.c b/libc/arch-mips64/bionic/crtbegin.c index fe6985dbe..2ea31ad64 100644 --- a/libc/arch-mips64/bionic/crtbegin.c +++ b/libc/arch-mips64/bionic/crtbegin.c @@ -36,10 +36,15 @@ void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1; __attribute__ ((section (".init_array"))) void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1; +__attribute__ ((section (".fini_array"))) +void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; + + __LIBC_HIDDEN__ void do_mips_start(void *raw_args) { structors_array_t array; array.preinit_array = &__PREINIT_ARRAY__; array.init_array = &__INIT_ARRAY__; + array.fini_array = &__FINI_ARRAY__; __libc_init(raw_args, NULL, &main, &array); } diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h index ee3d32b89..3032f99c2 100644 --- a/libc/bionic/libc_init_common.h +++ b/libc/bionic/libc_init_common.h @@ -33,6 +33,7 @@ typedef struct { void (**preinit_array)(void); void (**init_array)(void); + void (**fini_array)(void); } structors_array_t; __BEGIN_DECLS diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 3d9fa1ab7..78125f968 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -60,9 +60,6 @@ extern "C" { extern int __cxa_atexit(void (*)(void *), void *, void *); }; -__attribute__ ((section (".fini_array"))) -void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; - // We flag the __libc_preinit function as a constructor to ensure // that its address is listed in libc.so's .init_array section. // This ensures that the function is called by the dynamic linker @@ -82,11 +79,6 @@ __attribute__((constructor)) static void __libc_preinit() { // Hooks for various libraries to let them know that we're starting up. malloc_debug_init(); netdClientInit(); - - // The executable may have its own destructors listed in its .fini_array - // so we need to ensure that these are called when the program exits - // normally. - __cxa_atexit(__libc_fini, &__FINI_ARRAY__, NULL); } __LIBC_HIDDEN__ void __libc_postfini() { @@ -104,11 +96,19 @@ __LIBC_HIDDEN__ void __libc_postfini() { __noreturn void __libc_init(void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**), - structors_array_t const * const structors __unused) { + structors_array_t const * const structors) { + KernelArgumentBlock args(raw_args); // Several Linux ABIs don't pass the onexit pointer, and the ones that // do never use it. Therefore, we ignore it. + // The executable may have its own destructors listed in its .fini_array + // so we need to ensure that these are called when the program exits + // normally. + if (structors->fini_array) { + __cxa_atexit(__libc_fini,structors->fini_array,NULL); + } + exit(slingshot(args.argc, args.argv, args.envp)); } diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index f2e34c227..bc11f3d93 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -61,9 +61,6 @@ extern "C" int __cxa_atexit(void (*)(void *), void *, void *); -__attribute__ ((section (".fini_array"))) -void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1; - static void call_array(void(**list)()) { // First element is -1, list is null-terminated while (*++list) { @@ -102,13 +99,14 @@ __noreturn void __libc_init(void* raw_args, // do never use it. Therefore, we ignore it. call_array(structors->preinit_array); + call_array(structors->init_array); // The executable may have its own destructors listed in its .fini_array // so we need to ensure that these are called when the program exits // normally. - __cxa_atexit(__libc_fini,&__FINI_ARRAY__, NULL); - - call_array(structors->init_array); + if (structors->fini_array != NULL) { + __cxa_atexit(__libc_fini,structors->fini_array,NULL); + } exit(slingshot(args.argc, args.argv, args.envp)); }