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