[PATCH] libdl: fix dlclose handling of symbol scope
Khem Raj
raj.khem at gmail.com
Wed Jan 18 06:58:19 UTC 2012
On Tue, Jan 17, 2012 at 9:23 AM, Carmelo AMOROSO <carmelo.amoroso at st.com> wrote:
> 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.
this patch works nicely. I so far tried it on x86 but I will test
other arches soon
but the patch is good to go in with testcase added as Mike pointed
>
> Signed-off-by: Khem Raj <raj.khem at gmail.com>
> Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
> Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
> ---
> 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 bc3ef8a..da3c405 100644
> --- a/ldso/libdl/libdl.c
> +++ b/ldso/libdl/libdl.c
> @@ -780,7 +780,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;
> @@ -813,6 +815,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];
> @@ -974,16 +989,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) {
> @@ -1005,10 +1010,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);
> --
> 1.7.4.4
>
More information about the uClibc
mailing list