diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 95a0650..91aa926 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -544,11 +544,19 @@ static void *do_dlopen(const char *libname, int flag) * to the GOT tables. We need to do this in reverse order so that COPY * directives work correctly */ - /* Get the tail of the list */ - for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next); + /* Extend the global scope by adding the local scope of the dlopened DSO. + * But only if it's not there. It can happen under certain cases that the + * DSO had refcount = 0, but was already loaded. (NODELETE flag is set, or + * it is pulled in via both NEEDED dependency and explicit dlopen()). */ + for (ls = &_dl_loaded_modules->symbol_scope; ; ls = ls->next) { + if (ls == &dyn_chain->dyn->symbol_scope) + break; + if (ls->next == NULL) { + ls->next = &dyn_chain->dyn->symbol_scope; + break; + } + } - /* Extend the global scope by adding the local scope of the dlopened DSO. */ - ls->next = &dyn_chain->dyn->symbol_scope; #ifdef __mips__ /* * Relocation of the GOT entries for MIPS have to be done