diff options
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/include/dl-hash.h | 2 | ||||
-rw-r--r-- | ldso/include/ldso.h | 7 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 84 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 60 |
4 files changed, 83 insertions, 70 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index a224012c4..a30c78afb 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -8,6 +8,7 @@ struct dyn_elf{ struct elf_resolve * dyn; struct dyn_elf * next_handle; /* Used by dlopen et al. */ + struct init_fini_list *init_fini; struct dyn_elf * next; struct dyn_elf * prev; }; @@ -57,6 +58,7 @@ struct elf_resolve{ #define RELOCS_DONE 2 #define JMP_RELOCS_DONE 4 #define INIT_FUNCS_CALLED 8 +#define FINI_FUNCS_CALLED 16 extern struct dyn_elf * _dl_symbol_tables; extern struct elf_resolve * _dl_loaded_modules; diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 8248b1574..37ec439cb 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -31,6 +31,13 @@ #include <dl-elf.h> #include <dl-hash.h> +/* For INIT/FINI handling */ +struct init_fini_list { + struct init_fini_list *next; + struct init_fini_list *prev; + struct elf_resolve *tpnt; +}; + /* Global variables used within the shared library loader */ extern char *_dl_library_path; /* Where we look for libraries */ extern char *_dl_preload; /* Things to be loaded before the libs */ diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 69f3b1760..6feebe624 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -104,6 +104,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, #if defined (__SUPPORT_LD_DEBUG__) int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*); #endif + struct init_fini_list *init_list; #ifdef __SUPPORT_LD_DEBUG_EARLY__ /* Wahoo!!! */ @@ -566,56 +567,55 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, } } #endif - - for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) - { + init_list = NULL; + for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { Elf32_Dyn *dpnt; - for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) - { - if (dpnt->d_tag == DT_NEEDED) - { + for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag == DT_NEEDED) { char *name; + struct init_fini_list *tmp; + lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); name = _dl_get_last_path_component(lpntstr); - if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects))) - { + if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, trace_loaded_objects))) { tpnt1->usage_count++; - continue; } #if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n", - lpntstr, _dl_progname); + if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname); #endif - if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) - { + if (!tpnt1) { + if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) { #ifdef __LDSO_LDD_SUPPORT__ - if (trace_loaded_objects) { - _dl_dprintf(1, "\t%s => not found\n", lpntstr); - continue; - } else + if (trace_loaded_objects) { + _dl_dprintf(1, "\t%s => not found\n", lpntstr); + continue; + } else #endif - { - _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr); - _dl_exit(16); + { + _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr); + _dl_exit(16); + } } - } else { - tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + } + tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */ + /* Don't set the tmp->next ptr, it is not used */ + tmp->tpnt = tpnt1; + tmp->prev = init_list; + init_list = tmp; + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; #ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); + _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #endif #ifdef __LDSO_LDD_SUPPORT__ - if (trace_loaded_objects && tpnt1->usage_count==1) { - _dl_dprintf(1, "\t%s => %s (%x)\n", lpntstr, tpnt1->libname, - (unsigned) tpnt1->loadaddr); - } -#endif + if (trace_loaded_objects && tpnt1->usage_count==1) { + _dl_dprintf(1, "\t%s => %s (%x)\n", lpntstr, tpnt1->libname, (unsigned) tpnt1->loadaddr); } +#endif } } } - _dl_unmap_cache(); /* @@ -722,23 +722,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, /* Notify the debugger we have added some objects. */ _dl_debug_addr->r_state = RT_ADD; _dl_debug_state(); - - for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next) - ; - - for (;rpnt!=NULL; rpnt=rpnt->prev) - { - tpnt = rpnt->dyn; - - if (tpnt->libtype == program_interpreter) - continue; - - /* Apparently crt0/1 for the application is responsible for handling this. - * We only need to run the init/fini for shared libraries - */ - if (tpnt->libtype == elf_executable) - break; /* at this point all shared libs are initialized !! */ - + for (; init_list; init_list = init_list->prev) { + tpnt = init_list->tpnt; if (tpnt->init_flag & INIT_FUNCS_CALLED) continue; tpnt->init_flag |= INIT_FUNCS_CALLED; @@ -751,6 +736,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, #endif (*dl_elf_func) (); } + tpnt->init_flag |= FINI_FUNCS_CALLED; if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) { void (*dl_elf_func) (void); dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); @@ -766,10 +752,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, else { if (!_dl_atexit) _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname); -#if 0 - if (!tpnt->dynamic_info[DT_FINI]) - _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname); -#endif } #endif } diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index d76d325c3..44fecbad9 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -134,6 +134,8 @@ void *dlopen(const char *libname, int flag) struct elf_resolve *tpnt1; void (*dl_brk) (void); int now_flag; + struct init_fini_list *init_list; + struct init_fini_list *tmp; /* A bit of sanity checking... */ if (!(flag & (RTLD_LAZY|RTLD_NOW))) { @@ -192,15 +194,23 @@ void *dlopen(const char *libname, int flag) if(_dl_debug) fprintf(stderr, "Looking for needed libraries\n"); #endif + init_list = NULL; + tmp = malloc(sizeof(struct init_fini_list)); + tmp->tpnt = tpnt; + tmp->next = NULL; + tmp->prev = init_list; + init_list = tmp; + + dyn_chain->init_fini = init_list; for (tcurr = tpnt; tcurr; tcurr = tcurr->next) { Elf32_Dyn *dpnt; char *lpntstr; for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { if (dpnt->d_tag == DT_NEEDED) { - char *name; + lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val); name = _dl_get_last_path_component(lpntstr); @@ -224,6 +234,12 @@ void *dlopen(const char *libname, int flag) tpnt1->rtld_flags |= RTLD_GLOBAL; tpnt1->usage_count++; } + tmp = malloc(sizeof(struct init_fini_list)); + tmp->tpnt = tpnt1; + tmp->next = NULL; + tmp->prev = init_list; + init_list->next = tmp; + init_list = init_list->next;; } } } @@ -273,20 +289,11 @@ void *dlopen(const char *libname, int flag) } #if defined (__LIBDL_SHARED__) - /* Find the last library so we can run things in the right order */ - for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next) - ; - - /* Run the ctors and set up the dtors */ - for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev) - { + /* Run the ctors and setup the dtors */ + for (; init_list; init_list = init_list->prev) { /* Apparently crt1 for the application is responsible for handling this. - * We only need to run the init/fini for shared libraries - */ - if (tpnt->libtype == program_interpreter) - continue; - if (tpnt->libtype == elf_executable) - continue; + * We only need to run the init/fini for shared libraries. */ + tpnt = init_list->tpnt; if (tpnt->init_flag & INIT_FUNCS_CALLED) continue; tpnt->init_flag |= INIT_FUNCS_CALLED; @@ -377,6 +384,7 @@ static int do_dlclose(void *vhandle, int need_fini) struct dyn_elf *handle; unsigned int end; int i = 0; + struct init_fini_list *fini_list, *tmp; handle = (struct dyn_elf *) vhandle; rpnt1 = NULL; @@ -394,15 +402,29 @@ static int do_dlclose(void *vhandle, int need_fini) rpnt1->next_handle = rpnt->next_handle; else _dl_handles = rpnt->next_handle; + if (need_fini) { + for (fini_list = handle->init_fini; fini_list; ) { + tpnt = fini_list->tpnt; + tmp = NULL; + if (tpnt->dynamic_info[DT_FINI] && tpnt->usage_count == 1 && + !(tpnt->init_flag & FINI_FUNCS_CALLED)) { + tpnt->init_flag |= FINI_FUNCS_CALLED; + dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); +#ifdef __SUPPORT_LD_DEBUG__ + if(_dl_debug) + fprintf(stderr, "running dtors for library %s at '%x'\n", tpnt->libname, dl_elf_fini); +#endif + (*dl_elf_fini) (); + tmp = fini_list; + } + fini_list = fini_list->next; + free(tmp); + } + } /* OK, this is a valid handle - now close out the file */ for (rpnt = handle; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; if (--tpnt->usage_count == 0) { - if (need_fini && tpnt->dynamic_info[DT_FINI]) { - dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); - (*dl_elf_fini) (); - } - end = 0; for (i = 0, ppnt = tpnt->ppnt; i < tpnt->n_phent; ppnt++, i++) { |