diff options
| -rw-r--r-- | ldso/ldso/dl-elf.c | 2 | ||||
| -rw-r--r-- | ldso/libdl/libdl.c | 4 | ||||
| -rw-r--r-- | test/dlopen/Makefile.in | 4 | ||||
| -rw-r--r-- | test/dlopen/nodelete1.c | 59 | 
4 files changed, 66 insertions, 3 deletions
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 8f71aeb05..a046aeb74 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -884,6 +884,8 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned int rflags,  #endif  	(*rpnt)->dyn = tpnt;  	tpnt->usage_count++; +	if (tpnt->rtld_flags & RTLD_NODELETE) +		tpnt->usage_count++;  #ifdef __LDSO_STANDALONE_SUPPORT__  	tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable;  #else diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 489c78759..0cf3b7037 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -818,7 +818,7 @@ static int do_dlclose(void *vhandle, int need_fini)  		_dl_handles = rpnt->next_handle;  	_dl_if_debug_print("%s: usage count: %d\n",  			handle->dyn->libname, handle->dyn->usage_count); -	if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) { +	if (handle->dyn->usage_count != 1) {  		handle->dyn->usage_count--;  		free(handle);  		return 0; @@ -840,7 +840,7 @@ static int do_dlclose(void *vhandle, int need_fini)  	for (j = 0; j < handle->init_fini.nlist; ++j) {  		tpnt = handle->init_fini.init_fini[j];  		tpnt->usage_count--; -		if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) { +		if (tpnt->usage_count == 0) {  			if ((tpnt->dynamic_info[DT_FINI]  			     || tpnt->dynamic_info[DT_FINI_ARRAY])  			 && need_fini diff --git a/test/dlopen/Makefile.in b/test/dlopen/Makefile.in index 0bed0f749..740453a19 100644 --- a/test/dlopen/Makefile.in +++ b/test/dlopen/Makefile.in @@ -5,7 +5,7 @@  export UCLIBC_ONLY := 1  TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr \ -	testscope nodelete tst-origin +	testscope nodelete nodelete1 tst-origin  ifneq ($(HAVE_SHARED),y)  TESTS_DISABLED := test3 @@ -80,3 +80,5 @@ LDFLAGS_nodelete := -rdynamic -ldl  LDFLAGS_nodelmod1.so := -Wl,-z,nodelete  LDFLAGS_nodelmod3.so := ./nodelmod4.so  LDFLAGS_nodelmod4.so := -Wl,-z,nodelete +nodelete1: nodelmod1.so nodelmod2.so +LDFLAGS_nodelete1 := -rdynamic -ldl diff --git a/test/dlopen/nodelete1.c b/test/dlopen/nodelete1.c new file mode 100644 index 000000000..720e37fd1 --- /dev/null +++ b/test/dlopen/nodelete1.c @@ -0,0 +1,59 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + + +int fini_ran; + +#define LIBNAME1	"nodelmod1.so" + +static int +do_test (void) +{ +  /* Verify ability to reload RTLD_NODELETE libraries. +   */ +  void *p; + +  p = dlopen (LIBNAME1, RTLD_NOW); +  if (p == NULL) +  { +      printf ("failed to load "LIBNAME1": %s\n", dlerror ()); +      exit (1); +  } + +  if (dlclose (p) != 0) +  { +      puts ("failed to close "LIBNAME1""); +      exit (1); +  } + +  p = dlopen (LIBNAME1, RTLD_LAZY); +  if (p == NULL) +  { +      printf ("failed to load "LIBNAME1": %s\n", dlerror ()); +      exit (1); +  } + +  if (dlclose (p) != 0) +  { +      puts ("failed to close "LIBNAME1""); +      exit (1); +  } + +  p = dlopen ("nodelmod2.so", RTLD_LAZY); +  if (p == NULL) +  { +      printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ()); +      exit (1); +  } +  if (dlclose (p) != 0) +  { +      puts ("failed to close \"nodelmod2.so\""); +      exit (1); +  } + +  return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c"  | 
