about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--elf/rtld.c4
-rw-r--r--sysdeps/generic/dl-tls.c26
-rw-r--r--sysdeps/generic/ldsodefs.h4
3 files changed, 26 insertions, 8 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 1472c18235..a035a26c99 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1091,6 +1091,10 @@ of this helper program; chances are you did not intend to run this program.\n\
       if (tcbp == NULL)
 	_dl_fatal_printf ("\
 cannot allocate TLS data structures for initial thread");
+
+      /* Store for detection of the special case by __tls_get_addr
+	 so it knows not to pass this dtv to the normal realloc.  */
+      _dl_initial_dtv = GET_DTV (tcbp);
     }
 #endif
 
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 2d211fb662..2ef69e5abc 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -487,15 +487,29 @@ __tls_get_addr (GET_ADDR_ARGS)
 
 		      assert (map->l_tls_modid <= newsize);
 
-		      newp = (dtv_t *) realloc (&dtv[-1],
-						(2 + newsize)
-						* sizeof (dtv_t));
-		      if (newp == NULL)
-			oom ();
+		      if (dtv == GL(dl_initial_dtv))
+			{
+			  /* This is the initial dtv that was allocated
+			     during rtld startup using the dl-minimal.c
+			     malloc instead of the real malloc.  We can't
+			     free it, we have to abandon the old storage.  */
+
+			  newp = malloc ((2 + newsize) * sizeof (dtv_t));
+			  if (newp == NULL)
+			    oom ();
+			  memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
+			}
+		      else
+			{
+			  newp = realloc (&dtv[-1],
+					  (2 + newsize) * sizeof (dtv_t));
+			  if (newp == NULL)
+			    oom ();
+			}
 
 		      newp[0].counter = newsize;
 
-		      /* Clear the newly allocate part.  */
+		      /* Clear the newly allocated part.  */
 		      memset (newp + 2 + oldsize, '\0',
 			      (newsize - oldsize) * sizeof (dtv_t));
 
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 2269950045..cd499f61b7 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -323,8 +323,8 @@ struct rtld_global
 /* Number of additional slots in the dtv allocated.  */
 # define DTV_SURPLUS	(14)
 
-  /* True if the dtv for the initial thread was malloc()ed.  */
-  EXTERN bool _dl_initial_dtv_malloced;
+  /* Initial dtv of the main thread, not allocated with normal malloc.  */
+  EXTERN void *_dl_initial_dtv;
   /* Generation counter for the dtv.  */
   EXTERN size_t _dl_tls_generation;
 #endif