From dae8a4ede6fec3e6f87f101c2708c2669c4075fa Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Sat, 31 Mar 2007 13:42:48 +0000 Subject: Bernd Schmidt writes: Currently a static libdl.a doesn't run all the constructors or destructors of the libraries it loads. I can't see a good reason for that, and it does cause aborts in the destructors it does run for things like libgcc.so on the Blackfin. Fixed with the patch below - untested in mainline, but the equivalent has been in our Blackfin tree for a while now. --- ldso/ldso/dl-array.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/ldso.c | 52 +------------------------------- ldso/libdl/libdl.c | 5 +--- 3 files changed, 86 insertions(+), 55 deletions(-) create mode 100644 ldso/ldso/dl-array.c diff --git a/ldso/ldso/dl-array.c b/ldso/ldso/dl-array.c new file mode 100644 index 000000000..dabb466f7 --- /dev/null +++ b/ldso/ldso/dl-array.c @@ -0,0 +1,84 @@ +/* vi: set sw=4 ts=4: */ +/* + * This file contains the helper routines to run init and fini functions. + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "ldso.h" + +static void _dl_run_array_forward(unsigned long array, unsigned long size, + DL_LOADADDR_TYPE loadaddr) +{ + if (array != 0) { + unsigned int j; + unsigned int jm; + ElfW(Addr) *addrs; + jm = size / sizeof (ElfW(Addr)); + addrs = (ElfW(Addr) *) DL_RELOC_ADDR(loadaddr, array); + for (j = 0; j < jm; ++j) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void))); + } + } +} + +void _dl_run_init_array(struct elf_resolve *tpnt); +void _dl_run_init_array(struct elf_resolve *tpnt) +{ + _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], + tpnt->dynamic_info[DT_INIT_ARRAYSZ], + tpnt->loadaddr); +} + +void _dl_app_init_array(void); +void _dl_app_init_array(void) +{ + _dl_run_init_array(_dl_loaded_modules); +} + +void _dl_run_fini_array(struct elf_resolve *tpnt); +void _dl_run_fini_array(struct elf_resolve *tpnt) +{ + if (tpnt->dynamic_info[DT_FINI_ARRAY]) { + ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI_ARRAY]); + unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); + while (i-- > 0) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) array[i]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void))); + } + } +} + +void _dl_app_fini_array(void); +void _dl_app_fini_array(void) +{ + _dl_run_fini_array(_dl_loaded_modules); +} + diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index e2a10737c..e1101bd57 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -66,6 +66,7 @@ int _dl_debug_file = 2; unsigned long attribute_hidden _dl_skip_args = 0; const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */ #include "dl-startup.c" +#include "dl-array.c" /* Forward function declarations */ static int _dl_suid_ok(void); @@ -107,57 +108,6 @@ uintptr_t __guard attribute_relro; # endif #endif -static void _dl_run_array_forward(unsigned long array, unsigned long size, - DL_LOADADDR_TYPE loadaddr) -{ - if (array != 0) { - unsigned int j; - unsigned int jm; - ElfW(Addr) *addrs; - jm = size / sizeof (ElfW(Addr)); - addrs = (ElfW(Addr) *) DL_RELOC_ADDR(loadaddr, array); - for (j = 0; j < jm; ++j) { - void (*dl_elf_func) (void); - dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; - DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void))); - } - } -} - -void _dl_run_init_array(struct elf_resolve *tpnt); -void _dl_run_init_array(struct elf_resolve *tpnt) -{ - _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], - tpnt->dynamic_info[DT_INIT_ARRAYSZ], - tpnt->loadaddr); -} - -void _dl_app_init_array(void); -void _dl_app_init_array(void) -{ - _dl_run_init_array(_dl_loaded_modules); -} - -void _dl_run_fini_array(struct elf_resolve *tpnt); -void _dl_run_fini_array(struct elf_resolve *tpnt) -{ - if (tpnt->dynamic_info[DT_FINI_ARRAY]) { - ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI_ARRAY]); - unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); - while (i-- > 0) { - void (*dl_elf_func) (void); - dl_elf_func = (void (*)(void)) (intptr_t) array[i]; - DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void))); - } - } -} - -void _dl_app_fini_array(void); -void _dl_app_fini_array(void) -{ - _dl_run_fini_array(_dl_loaded_modules); -} - static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) { int i; diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index e8a916c84..f018c0a0d 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -90,6 +90,7 @@ size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later /* This global variable is also to communicate with debuggers such as gdb. */ struct r_debug *_dl_debug_addr = NULL; #define _dl_malloc malloc +#include "../ldso/dl-array.c" #include "../ldso/dl-debug.c" #include LDSO_ELFINTERP #include "../ldso/dl-hash.c" @@ -395,7 +396,6 @@ void *dlopen(const char *libname, int flag) } } -#ifdef SHARED /* Run the ctors and setup the dtors */ for (i = nlist; i; --i) { tpnt = init_fini_list[i-1]; @@ -415,7 +415,6 @@ void *dlopen(const char *libname, int flag) _dl_run_init_array(tpnt); } -#endif /* SHARED */ _dl_unmap_cache(); return (void *) dyn_chain; @@ -535,9 +534,7 @@ static int do_dlclose(void *vhandle, int need_fini) && need_fini && !(tpnt->init_flag & FINI_FUNCS_CALLED)) { tpnt->init_flag |= FINI_FUNCS_CALLED; -#ifdef SHARED _dl_run_fini_array(tpnt); -#endif if (tpnt->dynamic_info[DT_FINI]) { dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]); -- cgit v1.2.3