summaryrefslogtreecommitdiff
path: root/ldso/libdl/libdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/libdl/libdl.c')
-rw-r--r--ldso/libdl/libdl.c109
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);
}