summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-03-28 09:36:28 +0000
committerJakub Jelinek <jakub@redhat.com>2006-03-28 09:36:28 +0000
commit5a6a773f6c388e7740afb495fcd03d3b500f30cb (patch)
treead7b4e3dd8bb8a750bf6b3a016c591e5d98026dc /elf
parent0c20be13c576b849ab201bd887a6585973a49d0e (diff)
downloadglibc-5a6a773f6c388e7740afb495fcd03d3b500f30cb.tar.gz
glibc-5a6a773f6c388e7740afb495fcd03d3b500f30cb.tar.xz
glibc-5a6a773f6c388e7740afb495fcd03d3b500f30cb.zip
Updated to fedora-glibc-20060328T0900 cvs/fedora-
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile17
-rw-r--r--elf/dl-load.c25
-rw-r--r--elf/rtld.c40
-rw-r--r--elf/tst-audit2.c50
-rw-r--r--elf/tst-leaks1.c25
5 files changed, 132 insertions, 25 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 791341758e..3b4ef26d45 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -91,7 +91,7 @@ distribute	:= rtld-Rules \
 		   order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
 		   tst-stackguard1.c tst-stackguard1-static.c \
 		   tst-array5.c tst-array5-static.c tst-array5dep.c \
-		   tst-array5.exp
+		   tst-array5.exp tst-leaks1.c
 
 CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
@@ -139,7 +139,7 @@ vpath %.c ../locale/programs
 endif
 endif
 
-tests = tst-tls1 tst-tls2 tst-tls9
+tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1
 ifeq (yes,$(have-initfini-array))
 tests += tst-array1 tst-array2 tst-array3 tst-array4 tst-array5
 endif
@@ -168,7 +168,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
 	 tst-dlmodcount tst-dlopenrpath tst-deep1 \
 	 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
-	 unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \
+	 unload3 unload4 unload5 unload6 tst-global1 order2 \
+	 tst-audit1 tst-audit2 \
 	 tst-stackguard1
 #	 reldep9
 test-srcs = tst-pathopt
@@ -180,6 +181,7 @@ endif
 ifeq (yesyes,$(have-fpie)$(build-shared))
 tests: $(objpfx)tst-pie1.out
 endif
+tests: $(objpfx)tst-leaks1-mem
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		testobj1_1 failobj constload2 constload3 unloadmod \
 		dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \
@@ -878,6 +880,9 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
 $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
 tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
 
+$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
+tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+
 $(objpfx)tst-global1: $(libdl)
 $(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
 
@@ -895,3 +900,9 @@ order2mod2.so-no-z-defs = yes
 
 tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
+
+$(objpfx)tst-leaks1: $(libdl)
+$(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
+	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
+
+tst-leaks1-ENV = MALLOC_TRACE=$(objpfx)tst-leaks1.mtrace
diff --git a/elf/dl-load.c b/elf/dl-load.c
index bba1c83ba0..088954a04f 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,6 @@
 /* Map in a shared object's segments from the file.
-   Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006  Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -1554,7 +1555,7 @@ print_search_path (struct r_search_path_elem **list,
    user might want to know about this.  */
 static int
 open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
-	     int whatcode, bool *found_other_class)
+	     int whatcode, bool *found_other_class, bool free_name)
 {
   /* This is the expected ELF header.  */
 #define ELF32_CLASS ELFCLASS32
@@ -1635,6 +1636,12 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
 	  errstring = (errval == 0
 		       ? N_("file too short") : N_("cannot read file data"));
 	call_lose:
+	  if (free_name)
+	    {
+	      char *realname = (char *) name;
+	      name = strdupa (realname);
+	      free (realname);
+	    }
 	  lose (errval, fd, name, NULL, NULL, errstring);
 	}
 
@@ -1821,7 +1828,8 @@ open_path (const char *name, size_t namelen, int preloaded,
 	  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
 	    _dl_debug_printf ("  trying file=%s\n", buf);
 
-	  fd = open_verify (buf, fbp, loader, whatcode, found_other_class);
+	  fd = open_verify (buf, fbp, loader, whatcode, found_other_class,
+			    false);
 	  if (this_dir->status[cnt] == unknown)
 	    {
 	      if (fd != -1)
@@ -2098,7 +2106,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 		{
 		  fd = open_verify (cached,
 				    &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
-				    LA_SER_CONFIG, &found_other_class);
+				    LA_SER_CONFIG, &found_other_class, false);
 		  if (__builtin_expect (fd != -1, 1))
 		    {
 		      realname = local_strdup (cached);
@@ -2136,7 +2144,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	{
 	  fd = open_verify (realname, &fb,
 			    loader ?: GL(dl_ns)[nsid]._ns_loaded, 0,
-			    &found_other_class);
+			    &found_other_class, true);
 	  if (__builtin_expect (fd, 0) == -1)
 	    free (realname);
 	}
@@ -2166,8 +2174,11 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	  if ((name_copy = local_strdup (name)) == NULL
 	      || (l = _dl_new_object (name_copy, name, type, loader,
 				      mode, nsid)) == NULL)
-	    _dl_signal_error (ENOMEM, name, NULL,
-			      N_("cannot create shared object descriptor"));
+	    {
+	      free (name_copy);
+	      _dl_signal_error (ENOMEM, name, NULL,
+				N_("cannot create shared object descriptor"));
+	    }
 	  /* Signal that this is a faked entry.  */
 	  l->l_faked = 1;
 	  /* Since the descriptor is initialized with zero we do not
diff --git a/elf/rtld.c b/elf/rtld.c
index 76d129a0a0..68fe809700 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1,5 +1,5 @@
 /* Run time dynamic linker.
-   Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -2200,7 +2200,6 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 #ifndef HP_TIMING_NONAVAIL
       hp_timing_t start;
       hp_timing_t stop;
-      hp_timing_t add;
 #endif
 
       /* If we are profiling we also must do lazy reloaction.  */
@@ -2255,19 +2254,6 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
       if (__builtin_expect (GL(dl_profile_map) != NULL, 0))
 	/* We must prepare the profiling.  */
 	_dl_start_profile ();
-
-      if (rtld_multiple_ref)
-	{
-	  /* There was an explicit ref to the dynamic linker as a shared lib.
-	     Re-relocate ourselves with user-controlled symbol definitions.  */
-	  HP_TIMING_NOW (start);
-	  /* Mark the link map as not yet relocated again.  */
-	  GL(dl_rtld_map).l_relocated = 0;
-	  _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
-	  HP_TIMING_NOW (stop);
-	  HP_TIMING_DIFF (add, start, stop);
-	  HP_TIMING_ACCUM_NT (relocate_time, add);
-	}
     }
 
 #ifndef NONTLS_INIT_TP
@@ -2296,6 +2282,30 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
   NONTLS_INIT_TP;
 #endif
 
+  if (! prelinked && rtld_multiple_ref)
+    {
+      /* There was an explicit ref to the dynamic linker as a shared lib.
+	 Re-relocate ourselves with user-controlled symbol definitions.
+
+	 We must do this after TLS initialization in case after this
+	 re-relocation, we might call a user-supplied function
+	 (e.g. calloc from _dl_relocate_object) that uses TLS data.  */
+
+#ifndef HP_TIMING_NONAVAIL
+      hp_timing_t start;
+      hp_timing_t stop;
+      hp_timing_t add;
+#endif
+
+      HP_TIMING_NOW (start);
+      /* Mark the link map as not yet relocated again.  */
+      GL(dl_rtld_map).l_relocated = 0;
+      _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
+      HP_TIMING_NOW (stop);
+      HP_TIMING_DIFF (add, start, stop);
+      HP_TIMING_ACCUM_NT (relocate_time, add);
+    }
+
 #ifdef SHARED
   /* Auditing checkpoint: we have added all objects.  */
   if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
diff --git a/elf/tst-audit2.c b/elf/tst-audit2.c
new file mode 100644
index 0000000000..fd089b6f64
--- /dev/null
+++ b/elf/tst-audit2.c
@@ -0,0 +1,50 @@
+/* Test case for early TLS initialization in dynamic linker.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE___THREAD
+# define MAGIC1 0xabcdef72
+# define MAGIC2 0xd8675309
+static __thread unsigned int magic[] = { MAGIC1, MAGIC2 };
+#endif
+
+#undef calloc
+
+/* This calloc definition will be called by the dynamic linker itself.
+   We test that it has initialized our TLS block by the time it does so.  */
+
+void *
+calloc (size_t n, size_t m)
+{
+#if HAVE___THREAD
+  if (magic[0] != MAGIC1 || magic[1] != MAGIC2)
+    {
+      printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC1, MAGIC2);
+      abort ();
+    }
+  magic[0] = MAGIC2;
+  magic[1] = MAGIC1;
+#endif
+
+  n *= m;
+  void *ptr = malloc (n);
+  if (ptr != NULL)
+    memset (ptr, '\0', n);
+  return ptr;
+}
+
+int
+main (void)
+{
+#if HAVE___THREAD
+  if (magic[1] != MAGIC1 || magic[0] != MAGIC2)
+    {
+      printf ("{%x, %x} != {%x, %x}\n", magic[0], magic[1], MAGIC2, MAGIC1);
+      return 1;
+    }
+#endif
+
+  return 0;
+}
diff --git a/elf/tst-leaks1.c b/elf/tst-leaks1.c
new file mode 100644
index 0000000000..36e4aee9cf
--- /dev/null
+++ b/elf/tst-leaks1.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  mtrace ();
+
+  int ret = 0;
+  for (int i = 0; i < 10; i++)
+    {
+      void *h = dlopen (i < 5 ? "./tst-leaks1.c"
+			      : "$ORIGIN/tst-leaks1.o", RTLD_LAZY);
+      if (h != NULL)
+	{
+	  puts ("dlopen unexpectedly succeeded");
+	  ret = 1;
+	  dlclose (h);
+	}
+    }
+
+  return ret;
+}