summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-09-03 21:17:10 +0000
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-09-03 21:17:10 +0000
commitb54df7ec544e86c33e534a67bb9e38250467df4e (patch)
tree3c608eddd9f6f8a99acb83b6ce83c6e58f2cf389
parentbec90733b9de6e7d75b8bda19b3f0a7117e6b78d (diff)
First attempt to fix the INIT/FINI ordering. Fingers crossed :)
-rw-r--r--ldso/include/dl-hash.h2
-rw-r--r--ldso/include/ldso.h7
-rw-r--r--ldso/ldso/ldso.c84
-rw-r--r--ldso/libdl/libdl.c60
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++) {