[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