diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-08-13 13:56:25 +0000 |
---|---|---|
committer | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-08-13 13:56:25 +0000 |
commit | 9f47eaf3223c17a99cc88aea3287697e2635681f (patch) | |
tree | bb46e11388b630617ed8a7f42d4338ad32697c38 /ldso/libdl/libdl.c | |
parent | 5e383688dc73a3b18d41eabe7714539e39bea752 (diff) |
Fix usage_count in ldso/libdl.
Don't' use atexit in libdl.
Make destrutor in libdl actually run and to dlclose all
dlopened libs.
Remove dlclosed libs from the _dl_symbol_tables list.
Diffstat (limited to 'ldso/libdl/libdl.c')
-rw-r--r-- | ldso/libdl/libdl.c | 109 |
1 files changed, 34 insertions, 75 deletions
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 03b7834a0..fd72509d0 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -117,15 +117,12 @@ static const char *dl_error_names[] = { "Unable to resolve symbol" }; -static void __attribute__ ((destructor)) dl_cleanup(void) +void __attribute__ ((destructor)) dl_cleanup(void) { struct dyn_elf *d; - - for (d = _dl_handles; d; d = d->next_handle) - if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) { - (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) (); - d->dyn->dynamic_info[DT_FINI] = 0; - } + for (d = _dl_handles; d; d = d->next_handle) { + do_dlclose(d, 1); + } } void *dlopen(const char *libname, int flag) @@ -227,6 +224,8 @@ void *dlopen(const char *libname, int flag) if (!tpnt1) goto oops; dyn_ptr->dyn = tpnt1; + } else { + tpnt1->usage_count++; } } } @@ -303,17 +302,6 @@ void *dlopen(const char *libname, int flag) (*dl_elf_func) (); } } - if (tpnt->dynamic_info[DT_FINI]) { - void (*dl_elf_func) (void); - dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); - if (dl_elf_func && *dl_elf_func != NULL) { -#ifdef __SUPPORT_LD_DEBUG__ - if(_dl_debug) - fprintf(stderr, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func); -#endif - atexit(dl_elf_func); - } - } } #endif return (void *) dyn_chain; @@ -382,7 +370,6 @@ void *dlsym(void *vhandle, const char *name) static int do_dlclose(void *vhandle, int need_fini) { struct dyn_elf *rpnt, *rpnt1; - struct dyn_elf *spnt, *spnt1; ElfW(Phdr) *ppnt; struct elf_resolve *tpnt; int (*dl_elf_fini) (void); @@ -394,9 +381,8 @@ static int do_dlclose(void *vhandle, int need_fini) handle = (struct dyn_elf *) vhandle; rpnt1 = NULL; for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) { - if (rpnt == handle) { + if (rpnt == handle) break; - } rpnt1 = rpnt; } @@ -404,74 +390,31 @@ static int do_dlclose(void *vhandle, int need_fini) _dl_error_number = LD_BAD_HANDLE; return 1; } - - /* OK, this is a valid handle - now close out the file. - * We check if we need to call fini () on the handle. */ - spnt = need_fini ? handle : handle->next; - for (; spnt; spnt = spnt1) { - spnt1 = spnt->next; - - /* We appended the module list to the end - when we get back here, - quit. The access counts were not adjusted to account for being here. */ - if (spnt == _dl_symbol_tables) - break; - if (spnt->dyn->usage_count == 1 - && spnt->dyn->libtype == loaded_file) { - tpnt = spnt->dyn; - /* Apparently crt1 for the application is responsible for handling this. - * We only need to run the init/fini for shared libraries - */ - - if (tpnt->dynamic_info[DT_FINI]) { - dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + - tpnt->dynamic_info[DT_FINI]); - (*dl_elf_fini) (); - } - } - } if (rpnt1) rpnt1->next_handle = rpnt->next_handle; else _dl_handles = rpnt->next_handle; - /* OK, this is a valid handle - now close out the file */ - for (rpnt = handle; rpnt; rpnt = rpnt1) { - rpnt1 = rpnt->next; - - /* We appended the module list to the end - when we get back here, - quit. The access counts were not adjusted to account for being here. */ - if (rpnt == _dl_symbol_tables) - break; - - rpnt->dyn->usage_count--; - if (rpnt->dyn->usage_count == 0 - && rpnt->dyn->libtype == loaded_file) { - tpnt = rpnt->dyn; - /* Apparently crt1 for the application is responsible for handling this. - * We only need to run the init/fini for shared libraries - */ -#if 0 - - /* We have to do this above, before we start closing objects. - * Otherwise when the needed symbols for _fini handling are - * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/ - if (tpnt->dynamic_info[DT_FINI]) { + 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) (); } -#endif + end = 0; - for (i = 0, ppnt = rpnt->dyn->ppnt; - i < rpnt->dyn->n_phent; ppnt++, i++) { + for (i = 0, ppnt = tpnt->ppnt; + i < tpnt->n_phent; ppnt++, i++) { if (ppnt->p_type != PT_LOAD) continue; if (end < ppnt->p_vaddr + ppnt->p_memsz) end = ppnt->p_vaddr + ppnt->p_memsz; } - _dl_munmap((void*)rpnt->dyn->loadaddr, end); - /* Next, remove rpnt->dyn from the loaded_module list */ - if (_dl_loaded_modules == rpnt->dyn) { - _dl_loaded_modules = rpnt->dyn->next; + _dl_munmap((void*)tpnt->loadaddr, end); + /* Next, remove tpnt from the loaded_module list */ + if (_dl_loaded_modules == tpnt) { + _dl_loaded_modules = tpnt->next; if (_dl_loaded_modules) _dl_loaded_modules->prev = 0; } else @@ -482,6 +425,22 @@ static int do_dlclose(void *vhandle, int need_fini) tpnt->next->prev = tpnt; break; } + + /* Next, remove tpnt from the global symbol table list */ + if (_dl_symbol_tables->dyn == rpnt->dyn) { + _dl_symbol_tables = rpnt->next; + if (_dl_symbol_tables) + _dl_symbol_tables->prev = 0; + } else + for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { + if (rpnt1->next->dyn == rpnt->dyn) { + free(rpnt1->next); + rpnt1->next = rpnt1->next->next; + if (rpnt1->next) + rpnt1->next->prev = rpnt1; + break; + } + } free(rpnt->dyn->libname); free(rpnt->dyn); } |