about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--elf/dl-lookup.c11
-rw-r--r--elf/tst-unique1.c42
-rw-r--r--sysdeps/generic/ldsodefs.h2
4 files changed, 60 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 006dd5ac60..bea7ba0e2d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2009-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/tst-unique1.c: Extend test to check for unloading DSO with
+	unique symbol definition.
+	Patch by Jakub Jelinek.
+	* elf/dl-lookup.c (do_lookup_x): When entering a new unique symbol,
+	make sure the object with the definition cannot be unloaded.  Adjust
+	a few types.
+	* sysdeps/generic/ldsodefs.h (struct rtld_global): The map element in
+	the unique symbol hash table should not be const.
+
 2009-07-21  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/x86_64/multiarch/strstr.c: Minor cleanups.  Remove
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index fd0d624430..bdc84afa56 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -312,7 +312,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
 		 definition we have to use it.  */
 	      void enter (struct unique_sym *table, size_t size,
 			  unsigned int hash, const char *name,
-			  const ElfW(Sym) *sym, const struct link_map *map)
+			  const ElfW(Sym) *sym, struct link_map *map)
 	      {
 		size_t idx = hash % size;
 		size_t hash2 = 1 + hash % (size - 2);
@@ -332,6 +332,12 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
 			    table[idx].sym = sym;
 			    table[idx].map = map;
 			  }
+
+			if (table[idx].map->l_type == lt_loaded)
+			  /* Make sure we don't unload this object by
+			     artificially increason the open count.  */
+			  ++table[idx].map->l_direct_opencount;
+
 			return;
 		      }
 
@@ -410,7 +416,8 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
 		  tab->free = free;
 		}
 
-	      enter (entries, size, new_hash, strtab + sym->st_name, sym, map);
+	      enter (entries, size, new_hash, strtab + sym->st_name, sym,
+		     (struct link_map *) map);
 	      ++tab->n_elements;
 
 	      __rtld_lock_unlock_recursive (tab->lock);
diff --git a/elf/tst-unique1.c b/elf/tst-unique1.c
index 9b7996cd96..46d41d9ff4 100644
--- a/elf/tst-unique1.c
+++ b/elf/tst-unique1.c
@@ -1,6 +1,7 @@
 #include <config.h>
 #include <dlfcn.h>
 #include <stdio.h>
+#include <sys/mman.h>
 
 static int
 do_test (void)
@@ -30,10 +31,45 @@ do_test (void)
       puts ("cannot locate f in tst-unique1mod2");
       return 1;
     }
-  return f2 (f1 ());
-#else
-  return 0;
+  if (f2 (f1 ()))
+    {
+      puts ("f from tst-unique1mod2 failed");
+      return 1;
+    }
+  dlclose (h2);
+  dlclose (h1);
+  mmap (NULL, 1024 * 1024 * 16, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  h2 = dlopen ("tst-unique1mod2.so", RTLD_LAZY);
+  if (h2 == NULL)
+    {
+      puts ("cannot load tst-unique1mod2");
+      return 1;
+    }
+  f2 = dlsym (h2, "f");
+  if (f2 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod2");
+      return 1;
+    }
+  h1 = dlopen ("tst-unique1mod1.so", RTLD_LAZY);
+  if (h1 == NULL)
+    {
+      puts ("cannot load tst-unique1mod1");
+      return 1;
+    }
+  f1 = dlsym (h1, "f");
+  if (f1 == NULL)
+    {
+      puts ("cannot locate f in tst-unique1mod1");
+      return 1;
+    }
+  if (f2 (f1 ()))
+    {
+      puts ("f from tst-unique1mod2 failed");
+      return 1;
+    }
 #endif
+  return 0;
 }
 
 #define TEST_FUNCTION do_test ()
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 30f9d23091..e18e60f73f 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -396,7 +396,7 @@ struct rtld_global
 	uint32_t hashval;
 	const char *name;
 	const ElfW(Sym) *sym;
-	const struct link_map *map;
+	struct link_map *map;
       } *entries;
       size_t size;
       size_t n_elements;