548bcb
commit 8f85075a2e9c26ff7486d4bbaf358999807d215c
548bcb
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
548bcb
Date:   Thu Dec 31 12:24:38 2020 +0000
548bcb
548bcb
    elf: Add a DTV setup test [BZ #27136]
548bcb
    
548bcb
    The test dlopens a large number of modules with TLS, they are reused
548bcb
    from an existing test.
548bcb
    
548bcb
    The test relies on the reuse of slotinfo entries after dlclose, without
548bcb
    bug 27135 fixed this needs a failing dlopen. With a slotinfo list that
548bcb
    has non-monotone increasing generation counters, bug 27136 can trigger.
548bcb
    
548bcb
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
548bcb
548bcb
Conflicts:
548bcb
	elf/Makefile
548bcb
	  (usual test differences)
548bcb
548bcb
diff --git a/elf/Makefile b/elf/Makefile
548bcb
index 82fb019a634caf81..0995d810b57d0dda 100644
548bcb
--- a/elf/Makefile
548bcb
+++ b/elf/Makefile
548bcb
@@ -209,7 +209,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
548bcb
 	 tst-audit14 tst-audit15 tst-audit16 \
548bcb
 	 tst-tls-ie tst-tls-ie-dlmopen \
548bcb
 	 argv0test \
548bcb
-	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask
548bcb
+	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
548bcb
+	 tst-tls20
548bcb
 #	 reldep9
548bcb
 tests-internal += loadtest unload unload2 circleload1 \
548bcb
 	 neededtest neededtest2 neededtest3 neededtest4 \
548bcb
@@ -332,6 +333,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
548bcb
 		libmarkermod2-1 libmarkermod2-2 \
548bcb
 		libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
548bcb
 		libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
548bcb
+		tst-tls20mod-bad
548bcb
 
548bcb
 # Most modules build with _ISOMAC defined, but those filtered out
548bcb
 # depend on internal headers.
548bcb
@@ -1828,3 +1830,9 @@ $(objpfx)tst-rtld-help.out: $(objpfx)ld.so
548bcb
 	fi; \
548bcb
 	(exit $$status); \
548bcb
 	$(evaluate-test)
548bcb
+
548bcb
+# Reuses tst-tls-many-dynamic-modules
548bcb
+tst-tls20mod-bad.so-no-z-defs = yes
548bcb
+$(objpfx)tst-tls20: $(libdl) $(shared-thread-library)
548bcb
+$(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
548bcb
+			$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
548bcb
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
548bcb
new file mode 100644
548bcb
index 0000000000000000..ac5f8c8d39b66dd6
548bcb
--- /dev/null
548bcb
+++ b/elf/tst-tls20.c
548bcb
@@ -0,0 +1,98 @@
548bcb
+/* Test dtv setup if entries don't have monotone increasing generation.
548bcb
+   Copyright (C) 2021 Free Software Foundation, Inc.
548bcb
+   This file is part of the GNU C Library.
548bcb
+
548bcb
+   The GNU C Library is free software; you can redistribute it and/or
548bcb
+   modify it under the terms of the GNU Lesser General Public
548bcb
+   License as published by the Free Software Foundation; either
548bcb
+   version 2.1 of the License, or (at your option) any later version.
548bcb
+
548bcb
+   The GNU C Library is distributed in the hope that it will be useful,
548bcb
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
548bcb
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
548bcb
+   Lesser General Public License for more details.
548bcb
+
548bcb
+   You should have received a copy of the GNU Lesser General Public
548bcb
+   License along with the GNU C Library; if not, see
548bcb
+   <http://www.gnu.org/licenses/>.  */
548bcb
+
548bcb
+#include <dlfcn.h>
548bcb
+#include <pthread.h>
548bcb
+#include <stdio.h>
548bcb
+#include <stdlib.h>
548bcb
+#include <support/check.h>
548bcb
+#include <support/xdlfcn.h>
548bcb
+#include <support/xthread.h>
548bcb
+
548bcb
+#define NMOD 100
548bcb
+static void *mod[NMOD];
548bcb
+
548bcb
+static void
548bcb
+load_fail (void)
548bcb
+{
548bcb
+  /* Expected to fail because of a missing symbol.  */
548bcb
+  void *m = dlopen ("tst-tls20mod-bad.so", RTLD_NOW);
548bcb
+  if (m != NULL)
548bcb
+    FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
548bcb
+}
548bcb
+
548bcb
+static void
548bcb
+load_mod (int i)
548bcb
+{
548bcb
+  char *buf = xasprintf ("tst-tls-manydynamic%02dmod.so", i);
548bcb
+  mod[i] = xdlopen (buf, RTLD_LAZY);
548bcb
+  free (buf);
548bcb
+}
548bcb
+
548bcb
+static void
548bcb
+unload_mod (int i)
548bcb
+{
548bcb
+  if (mod[i] != NULL)
548bcb
+    xdlclose (mod[i]);
548bcb
+  mod[i] = NULL;
548bcb
+}
548bcb
+
548bcb
+static void
548bcb
+access (int i)
548bcb
+{
548bcb
+  char *buf = xasprintf ("tls_global_%02d", i);
548bcb
+  dlerror ();
548bcb
+  int *p = dlsym (mod[i], buf);
548bcb
+  printf ("mod[%d]: &tls = %p\n", i, p);
548bcb
+  if (p == NULL)
548bcb
+    FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
548bcb
+  ++*p;
548bcb
+  free (buf);
548bcb
+}
548bcb
+
548bcb
+static void *
548bcb
+start (void *a)
548bcb
+{
548bcb
+  for (int i = 0; i < NMOD; i++)
548bcb
+    if (mod[i] != NULL)
548bcb
+      access (i);
548bcb
+  return 0;
548bcb
+}
548bcb
+
548bcb
+static int
548bcb
+do_test (void)
548bcb
+{
548bcb
+  int i;
548bcb
+
548bcb
+  for (i = 0; i < NMOD; i++)
548bcb
+    {
548bcb
+      load_mod (i);
548bcb
+      /* Bump the generation of mod[0] without using new dtv slot.  */
548bcb
+      unload_mod (0);
548bcb
+      load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135.  */
548bcb
+      load_mod (0);
548bcb
+      /* Access TLS in all loaded modules.  */
548bcb
+      pthread_t t = xpthread_create (0, start, 0);
548bcb
+      xpthread_join (t);
548bcb
+    }
548bcb
+  for (i = 0; i < NMOD; i++)
548bcb
+    unload_mod (i);
548bcb
+  return 0;
548bcb
+}
548bcb
+
548bcb
+#include <support/test-driver.c>
548bcb
diff --git a/elf/tst-tls20mod-bad.c b/elf/tst-tls20mod-bad.c
548bcb
new file mode 100644
548bcb
index 0000000000000000..c1aed8ea7deffd22
548bcb
--- /dev/null
548bcb
+++ b/elf/tst-tls20mod-bad.c
548bcb
@@ -0,0 +1,2 @@
548bcb
+void missing_symbol (void);
548bcb
+void f (void) {missing_symbol ();}