diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 17 | ||||
-rw-r--r-- | elf/dl-close.c | 33 | ||||
-rw-r--r-- | elf/dl-open.c | 2 | ||||
-rw-r--r-- | elf/tst-nodelete-rtldmod.cc | 6 | ||||
-rw-r--r-- | elf/tst-nodelete-uniquemod.cc | 14 | ||||
-rw-r--r-- | elf/tst-nodelete-zmod.cc | 6 | ||||
-rw-r--r-- | elf/tst-nodelete.cc | 51 | ||||
-rw-r--r-- | elf/tst-znodelete-zlib.cc | 6 |
8 files changed, 130 insertions, 5 deletions
diff --git a/elf/Makefile b/elf/Makefile index f21276c006..bd0f24dd51 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -132,7 +132,7 @@ tests += $(tests-static) ifeq (yes,$(build-shared)) tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order noload filter unload \ - reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ + reldep reldep2 reldep3 reldep4 nodelete nodelete2 tst-nodelete \ nodlopen nodlopen2 neededtest neededtest2 \ neededtest3 neededtest4 unload2 lateglobal initfirst global \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ @@ -207,7 +207,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-unique1mod1 tst-unique1mod2 \ tst-unique2mod1 tst-unique2mod2 \ tst-auditmod9a tst-auditmod9b \ - $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib) \ + $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ + tst-nodelete-uniquemod) \ + tst-nodelete-rtldmod tst-nodelete-zmod \ tst-initordera1 tst-initorderb1 \ tst-initordera2 tst-initorderb2 \ tst-initordera3 tst-initordera4 \ @@ -591,6 +593,9 @@ ifuncmod5.so-no-z-defs = yes ifuncmod6.so-no-z-defs = yes tst-auditmod9a.so-no-z-defs = yes tst-auditmod9b.so-no-z-defs = yes +tst-nodelete-uniquemod.so-no-z-defs = yes +tst-nodelete-rtldmod.so-no-z-defs = yes +tst-nodelete-zmod.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1153,6 +1158,14 @@ $(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so $(objpfx)tst-unique4: $(objpfx)tst-unique4lib.so +$(objpfx)tst-nodelete: $(libdl) +$(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \ + $(objpfx)tst-nodelete-rtldmod.so \ + $(objpfx)tst-nodelete-zmod.so + +LDFLAGS-tst-nodelete = -rdynamic +LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete + $(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out cmp $^ > $@; \ $(evaluate-test) diff --git a/elf/dl-close.c b/elf/dl-close.c index 412f71d70b..2104674bd0 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -108,7 +108,7 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, void -_dl_close_worker (struct link_map *map) +_dl_close_worker (struct link_map *map, bool force) { /* One less direct use. */ --map->l_direct_opencount; @@ -152,6 +152,10 @@ _dl_close_worker (struct link_map *map) l->l_idx = idx; maps[idx] = l; ++idx; + + /* Clear DF_1_NODELETE to force object deletion. */ + if (force) + l->l_flags_1 &= ~DF_1_NODELETE; } assert (idx == nloaded); @@ -635,6 +639,31 @@ _dl_close_worker (struct link_map *map) } } + /* Reset unique symbols if forced. */ + if (force) + { + struct unique_sym_table *tab = &ns->_ns_unique_sym_table; + __rtld_lock_lock_recursive (tab->lock); + struct unique_sym *entries = tab->entries; + if (entries != NULL) + { + size_t idx, size = tab->size; + for (idx = 0; idx < size; ++idx) + { + /* Clear unique symbol entries that belong to this + object. */ + if (entries[idx].name != NULL + && entries[idx].map == imap) + { + entries[idx].name = NULL; + entries[idx].hashval = 0; + tab->n_elements--; + } + } + } + __rtld_lock_unlock_recursive (tab->lock); + } + /* We can unmap all the maps at once. We determined the start address and length when we loaded the object and the `munmap' call does the rest. */ @@ -782,7 +811,7 @@ _dl_close (void *_map) /* Acquire the lock. */ __rtld_lock_lock_recursive (GL(dl_load_lock)); - _dl_close_worker (map); + _dl_close_worker (map, false); __rtld_lock_unlock_recursive (GL(dl_load_lock)); } diff --git a/elf/dl-open.c b/elf/dl-open.c index 2d0e082271..027c1e0eda 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -670,7 +670,7 @@ no more namespaces available for dlmopen()")); if ((mode & __RTLD_AUDIT) == 0) GL(dl_tls_dtv_gaps) = true; - _dl_close_worker (args.map); + _dl_close_worker (args.map, true); } assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); diff --git a/elf/tst-nodelete-rtldmod.cc b/elf/tst-nodelete-rtldmod.cc new file mode 100644 index 0000000000..740e1d8181 --- /dev/null +++ b/elf/tst-nodelete-rtldmod.cc @@ -0,0 +1,6 @@ +extern int not_exist (void); + +int foo (void) +{ + return not_exist (); +} diff --git a/elf/tst-nodelete-uniquemod.cc b/elf/tst-nodelete-uniquemod.cc new file mode 100644 index 0000000000..632b303d58 --- /dev/null +++ b/elf/tst-nodelete-uniquemod.cc @@ -0,0 +1,14 @@ +extern int not_exist (void); + +inline int make_unique (void) +{ + /* Static variables in inline functions and classes + generate STB_GNU_UNIQUE symbols. */ + static int unique; + return ++unique; +} + +int foo (void) +{ + return make_unique () + not_exist (); +} diff --git a/elf/tst-nodelete-zmod.cc b/elf/tst-nodelete-zmod.cc new file mode 100644 index 0000000000..740e1d8181 --- /dev/null +++ b/elf/tst-nodelete-zmod.cc @@ -0,0 +1,6 @@ +extern int not_exist (void); + +int foo (void) +{ + return not_exist (); +} diff --git a/elf/tst-nodelete.cc b/elf/tst-nodelete.cc new file mode 100644 index 0000000000..176cb68836 --- /dev/null +++ b/elf/tst-nodelete.cc @@ -0,0 +1,51 @@ +#include "../dlfcn/dlfcn.h" +#include <stdio.h> +#include <stdlib.h> + +static int +do_test (void) +{ + int result = 0; + + /* This is a test for correct handling of dlopen failures for library that + is loaded with RTLD_NODELETE flag. The first dlopen should fail because + of undefined symbols in shared library. The second dlopen then verifies + that library was properly unloaded. */ + if (dlopen ("tst-nodelete-rtldmod.so", RTLD_NOW | RTLD_NODELETE) != NULL + || dlopen ("tst-nodelete-rtldmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL) + { + printf ("RTLD_NODELETE test failed\n"); + result = 1; + } + + /* This is a test for correct handling of dlopen failures for library that + is linked with '-z nodelete' option and hence has DF_1_NODELETE flag. + The first dlopen should fail because of undefined symbols in shared + library. The second dlopen then verifies that library was properly + unloaded. */ + if (dlopen ("tst-nodelete-zmod.so", RTLD_NOW) != NULL + || dlopen ("tst-nodelete-zmod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL) + { + printf ("-z nodelete test failed\n"); + result = 1; + } + + /* This is a test for correct handling of dlopen failures for library + with unique symbols. The first dlopen should fail because of undefined + symbols in shared library. The second dlopen then verifies that library + was properly unloaded. */ + if (dlopen ("tst-nodelete-uniquemod.so", RTLD_NOW) != NULL + || dlopen ("tst-nodelete-uniquemod.so", RTLD_LAZY | RTLD_NOLOAD) != NULL) + { + printf ("Unique symbols test failed\n"); + result = 1; + } + + if (result == 0) + printf ("SUCCESS\n"); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-znodelete-zlib.cc b/elf/tst-znodelete-zlib.cc new file mode 100644 index 0000000000..1e8f3686d7 --- /dev/null +++ b/elf/tst-znodelete-zlib.cc @@ -0,0 +1,6 @@ +extern int not_exist (void); + +int foo (void) +{ + return not_exist (); +} |