Submitted By: DJ Lucas <dj_AT_linuxfromscratch_DOT_org>
Date: 2005-11-20
Initial Package Version: 2.3.4
Upstream Status: Comitted
Origin:  http://bugs.gentoo.org/show_bug.cgi?id=52374#c23
Description:  Fixes the follwoing error:
Inconsistency detected by ld.so: ../sysdeps/generic/dl-tls.c: 72:
_dl_next_tls_modid: Assertion `result <= _rtld_local._dl_tls_max_dtv_idx' 
failed!

diff -urpN glibc-2.3.4.az/elf/Makefile glibc-2.3.4/elf/Makefile
--- glibc-2.3.4.az/elf/Makefile	2005-03-15 17:38:36.000000000 +0200
+++ glibc-2.3.4/elf/Makefile	2005-03-15 17:39:07.000000000 +0200
@@ -152,7 +152,7 @@ tests += loadtest restest1 preloadtest l
 	 neededtest3 neededtest4 unload2 lateglobal initfirst global \
 	 restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
 	 circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
-	 tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
+	 tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \
 	 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
 	 tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3
 #	 reldep9
@@ -182,6 +182,7 @@ modules-names = testobj1 testobj2 testob
 		tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
 		tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
 		tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
+		tst-tlsmod15a tst-tlsmod15b \
 		circlemod1 circlemod1a circlemod2 circlemod2a \
 		circlemod3 circlemod3a \
 		reldep8mod1 reldep8mod2 reldep8mod3 \
@@ -454,6 +455,7 @@ tst-tlsmod10.so-no-z-defs = yes
 tst-tlsmod12.so-no-z-defs = yes
 tst-tlsmod14a.so-no-z-defs = yes
 tst-tlsmod14b.so-no-z-defs = yes
+tst-tlsmod15a.so-no-z-defs = yes
 circlemod2.so-no-z-defs = yes
 circlemod3.so-no-z-defs = yes
 circlemod3a.so-no-z-defs = yes
@@ -664,8 +666,11 @@ $(objpfx)tst-tls12: $(objpfx)tst-tlsmod1
 $(objpfx)tst-tls13: $(libdl)
 $(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so
 
-$(objpfx)tst-tls14:  $(objpfx)tst-tlsmod14a.so $(libdl)
-$(objpfx)tst-tls14.out:$(objpfx)tst-tlsmod14b.so
+$(objpfx)tst-tls14: $(objpfx)tst-tlsmod14a.so $(libdl)
+$(objpfx)tst-tls14.out: $(objpfx)tst-tlsmod14b.so
+
+$(objpfx)tst-tls15: $(libdl)
+$(objpfx)tst-tls15.out: $(objpfx)tst-tlsmod15a.so $(objpfx)tst-tlsmod15b.so
 
 CFLAGS-tst-align.c = $(stack-align-test-flags)
 CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
diff -urpN glibc-2.3.4.az/elf/tst-tls15.c glibc-2.3.4/elf/tst-tls15.c
--- glibc-2.3.4.az/elf/tst-tls15.c	1970-01-01 02:00:00.000000000 +0200
+++ glibc-2.3.4/elf/tst-tls15.c	2005-03-15 17:39:07.000000000 +0200
@@ -0,0 +1,32 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  void *h = dlopen ("tst-tlsmod15a.so", RTLD_NOW);
+  if (h != NULL)
+    {
+      puts ("unexpectedly succeeded to open tst-tlsmod15a.so");
+      exit (1);
+    }
+
+  h = dlopen ("tst-tlsmod15b.so", RTLD_NOW);
+  if (h == NULL)
+    {
+      puts ("failed to open tst-tlsmod15b.so");
+      exit (1);
+    }
+
+  int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso");
+  if (fp == NULL)
+    {
+      puts ("cannot find in_dso");
+      exit (1);
+    }
+
+  return fp ();
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff -urpN glibc-2.3.4.az/elf/tst-tlsmod15a.c glibc-2.3.4/elf/tst-tlsmod15a.c
--- glibc-2.3.4.az/elf/tst-tlsmod15a.c	1970-01-01 02:00:00.000000000 +0200
+++ glibc-2.3.4/elf/tst-tlsmod15a.c	2005-03-15 17:39:07.000000000 +0200
@@ -0,0 +1,6 @@
+extern int nonexistent_dummy_var;
+int *
+foo (void)
+{
+  return &nonexistent_dummy_var;
+}
diff -urpN glibc-2.3.4.az/elf/tst-tlsmod15b.c glibc-2.3.4/elf/tst-tlsmod15b.c
--- glibc-2.3.4.az/elf/tst-tlsmod15b.c	1970-01-01 02:00:00.000000000 +0200
+++ glibc-2.3.4/elf/tst-tlsmod15b.c	2005-03-15 17:39:07.000000000 +0200
@@ -0,0 +1,17 @@
+#include "tst-tls10.h"
+
+#ifdef USE_TLS__THREAD
+__thread int mod15b_var __attribute__((tls_model("initial-exec")));
+
+int
+in_dso (void)
+{
+  return mod15b_var;
+}
+#else
+int
+in_dso (void)
+{
+  return 0;
+}
+#endif
diff -urpN glibc-2.3.4.az/sysdeps/generic/dl-tls.c glibc-2.3.4/sysdeps/generic/dl-tls.c
--- glibc-2.3.4.az/sysdeps/generic/dl-tls.c	2005-03-15 17:40:56.000000000 +0200
+++ glibc-2.3.4/sysdeps/generic/dl-tls.c	2005-03-15 17:39:07.000000000 +0200
@@ -65,34 +65,35 @@ _dl_next_tls_modid (void)
       /* Note that this branch will never be executed during program
 	 start since there are no gaps at that time.  Therefore it
 	 does not matter that the dl_tls_dtv_slotinfo is not allocated
-	 yet when the function is called for the first times.  */
-      result = GL(dl_tls_static_nelem) + 1;
-      /* If the following would not be true we mustn't have assumed
-	 there is a gap.  */
-      assert (result <= GL(dl_tls_max_dtv_idx));
-      do
-	{
-	  while (result - disp < runp->len)
-	    {
-	      if (runp->slotinfo[result - disp].map == NULL)
-		break;
-
-	      ++result;
-	      assert (result <= GL(dl_tls_max_dtv_idx) + 1);
-	    }
+	 yet when the function is called for the first times.
 
-	  if (result - disp < runp->len)
-	    break;
-
-	  disp += runp->len;
-	}
-      while ((runp = runp->next) != NULL);
+	 NB: the offset +1 is due to the fact that DTV[0] is used
+	 for something else.  */
+      result = GL(dl_tls_static_nelem) + 1;
+      if (result <= GL(dl_tls_max_dtv_idx))
+	do
+	  {
+	    while (result - disp < runp->len)
+	      {
+		if (runp->slotinfo[result - disp].map == NULL)
+		  break;
+
+		++result;
+		assert (result <= GL(dl_tls_max_dtv_idx) + 1);
+	      }
+
+	    if (result - disp < runp->len)
+	      break;
+
+	    disp += runp->len;
+	  }
+	while ((runp = runp->next) != NULL);
 
-      if (result >= GL(dl_tls_max_dtv_idx))
+      if (result > GL(dl_tls_max_dtv_idx))
 	{
 	  /* The new index must indeed be exactly one higher than the
 	     previous high.  */
-	  assert (result == GL(dl_tls_max_dtv_idx));
+	  assert (result == GL(dl_tls_max_dtv_idx) + 1);
 
 	  /* There is no gap anymore.  */
 	  GL(dl_tls_dtv_gaps) = false;
@@ -577,7 +578,7 @@ __tls_get_addr (GET_ADDR_ARGS)
 	    {
 	      size_t cnt;
 
-	      for (cnt = total = 0 ? 1 : 0; cnt < listp->len; ++cnt)
+	      for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
 		{
 		  size_t gen = listp->slotinfo[cnt].gen;
 		  struct link_map *map;

