diff options
| -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++) { | 
