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