diff options
| author | Carmelo Amoroso <carmelo.amoroso@st.com> | 2012-01-17 18:23:43 +0100 | 
|---|---|---|
| committer | Khem Raj <raj.khem@gmail.com> | 2012-01-23 16:21:18 -0800 | 
| commit | 99d28cc0860e240357c02483f0c4016a6b30aad0 (patch) | |
| tree | 3e72ca9bcf6d3481b4fee8302b53a98ff800cd0b | |
| parent | b18b4210a84f87f7155683d73a0ab924c34fa3f2 (diff) | |
libdl: fix dlclose handling of symbol scope
Defer removal of the local scope of a dl-opened library after
all the destructors (of itself and related dependencies) are actually
get unloaded, otherwise any function registered via atexit()
won't be resolved.
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
| -rw-r--r-- | ldso/libdl/libdl.c | 33 | 
1 files changed, 21 insertions, 12 deletions
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 32afe1c01..086a05932 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -781,7 +781,9 @@ static int do_dlclose(void *vhandle, int need_fini)  	struct dyn_elf *handle;  	unsigned int end = 0, start = 0xffffffff;  	unsigned int i, j; -	struct r_scope_elem *ls; +	struct r_scope_elem *ls, *ls_next = NULL; +	struct elf_resolve **handle_rlist; +  #if defined(USE_TLS) && USE_TLS  	bool any_tls = false;  	size_t tls_free_start = NO_TLS_OFFSET; @@ -814,6 +816,19 @@ static int do_dlclose(void *vhandle, int need_fini)  		free(handle);  		return 0;  	} + +	/* Store the handle's local scope array for later removal */ +	handle_rlist = handle->dyn->symbol_scope.r_list; + +	/* Store references to the local scope entries for later removal */ +	for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next) +		if (ls->next->r_list[0] == handle->dyn) { +			break; +		} +	/* ls points to the previous local symbol scope */ +	if(ls && ls->next) +		ls_next = ls->next->next; +  	/* OK, this is a valid handle - now close out the file */  	for (j = 0; j < handle->init_fini.nlist; ++j) {  		tpnt = handle->init_fini.init_fini[j]; @@ -975,16 +990,6 @@ static int do_dlclose(void *vhandle, int need_fini)  				}  			} -			if (handle->dyn == tpnt) { -				/* Unlink the local scope from global one */ -				for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next) -					if (ls->next->r_list[0] == tpnt) { -						_dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname); -						break; -					} -				ls->next = ls->next->next; -			} -  			/* Next, remove tpnt from the global symbol table list */  			if (_dl_symbol_tables) {  				if (_dl_symbol_tables->dyn == tpnt) { @@ -1006,10 +1011,14 @@ static int do_dlclose(void *vhandle, int need_fini)  				}  			}  			free(tpnt->libname); -			free(tpnt->symbol_scope.r_list);  			free(tpnt);  		}  	} +	/* Unlink and release the handle's local scope from global one */ +	if(ls) +		ls->next = ls_next; +	free(handle_rlist); +  	for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) {  		rpnt1_tmp = rpnt1->next;  		free(rpnt1);  | 
