diff options
-rw-r--r-- | .SRCINFO | 56 | ||||
-rw-r--r-- | 0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch | 308 | ||||
-rw-r--r-- | 0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch | 135 | ||||
-rw-r--r-- | 0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch | 26 | ||||
-rw-r--r-- | PKGBUILD | 245 | ||||
-rw-r--r-- | bz27343.patch | 48 | ||||
-rw-r--r-- | glibc.install | 5 | ||||
-rw-r--r-- | lib32-glibc.conf | 1 | ||||
-rwxr-xr-x | locale-gen | 42 | ||||
-rw-r--r-- | locale.gen.txt | 23 | ||||
-rw-r--r-- | sdt-config.h | 6 | ||||
-rw-r--r-- | sdt.h | 430 | ||||
-rw-r--r-- | v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch | 1974 | ||||
-rw-r--r-- | v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch | 569 |
14 files changed, 7 insertions, 3861 deletions
@@ -1,65 +1,15 @@ pkgbase = glibc-dso pkgver = 2.33 - pkgrel = 10 + pkgrel = 11 url = https://www.gnu.org/software/libc arch = x86_64 license = GPL license = LGPL - makedepends = git - makedepends = gd - makedepends = lib32-gcc-libs - makedepends = python - makedepends = cpio - optdepends = perl: for mtrace - options = !strip - options = staticlibs - source = https://ftp.gnu.org/gnu/glibc/glibc-2.33.tar.xz - source = https://ftp.gnu.org/gnu/glibc/glibc-2.33.tar.xz.sig - source = locale.gen.txt - source = locale-gen - source = lib32-glibc.conf - source = sdt.h - source = sdt-config.h - source = bz27343.patch - source = 0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch - source = 0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch - source = 0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch - source = v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch - source = v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch - validpgpkeys = 7273542B39962DF7B299931416792B4EA25340F8 - validpgpkeys = BC7C7372637EC10C57D7AA6579C43DFBF1CF2187 - md5sums = 390bbd889c7e8e8a7041564cb6b27cca - md5sums = SKIP - md5sums = 07ac979b6ab5eeb778d55f041529d623 - md5sums = 476e9113489f93b348b21e144b6a8fcf - md5sums = 6e052f1cb693d5d3203f50f9d4e8c33b - md5sums = 91fec3b7e75510ae2ac42533aa2e695e - md5sums = 680df504c683640b02ed4a805797c0b2 - md5sums = cfe57018d06bf748b8ca1779980fef33 - md5sums = 78f041fc66fee4ee372f13b00a99ff72 - md5sums = 9e418efa189c20053e887398df2253cf - md5sums = 7a09f1693613897add1791e7aead19c9 - md5sums = 5974b86859dd65c7cfda756a8b2445c2 - md5sums = 26a619a810de7d296608cc78377bc27c pkgname = glibc-dso pkgdesc = GNU C Library - DSO patch - install = glibc.install - depends = linux-api-headers>=4.10 - depends = tzdata - depends = filesystem - optdepends = gd: for memusagestat - provides = glibc=2.33 - conflicts = glibc - backup = etc/gai.conf - backup = etc/locale.gen - backup = etc/nscd.conf + depends = glibc pkgname = lib32-glibc-dso pkgdesc = GNU C Library (32-bit) - DSO patch - depends = glibc=2.33 - provides = lib32-glibc=2.33 - conflicts = lib32-glibc - options = !strip - options = staticlibs - options = !emptydirs + depends = lib32-glibc diff --git a/0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch b/0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch deleted file mode 100644 index 0b9c2efd4fe1..000000000000 --- a/0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch +++ /dev/null @@ -1,308 +0,0 @@ -From a64afc225240b2b27129ccfb0516d7c958b98040 Mon Sep 17 00:00:00 2001 -From: Florian Weimer <fweimer@redhat.com> -Date: Wed, 21 Apr 2021 11:50:43 +0200 -Subject: [PATCH 364/576] nptl_db: Support different libpthread/ld.so load - orders (bug 27744) - -libthread_db is loaded once GDB encounters libpthread, and at this -point, ld.so may not have been processed by GDB yet. As a result, -_rtld_global cannot be accessed by regular means from libthread_db. -To make this work until GDB can be fixed, acess _rtld_global through -a pointer stored in libpthread. - -The new test does not reproduce bug 27744 with ---disable-hardcoded-path-in-tests, but is still a valid smoke test. -With --enable-hardcoded-path-in-tests, it is necessary to avoid -add-symbol-file because this can tickle a GDB bug. - -Fixes commit 1daccf403b1bd86370eb94edca794dc106d02039 ("nptl: Move -stack list variables into _rtld_global"). - -Tested-by: Emil Velikov <emil.velikov@collabora.com> ---- - nptl/Makefile | 19 +++- - nptl/pthread_create.c | 8 ++ - nptl/tst-pthread-gdb-attach-static.c | 1 + - nptl/tst-pthread-gdb-attach.c | 143 +++++++++++++++++++++++++++ - nptl_db/structs.def | 3 +- - nptl_db/td_init.c | 15 +-- - nptl_db/thread_dbP.h | 2 + - 7 files changed, 180 insertions(+), 11 deletions(-) - create mode 100644 nptl/tst-pthread-gdb-attach-static.c - create mode 100644 nptl/tst-pthread-gdb-attach.c - -diff --git a/nptl/Makefile b/nptl/Makefile -index 8fe92d43fa..e665d37e52 100644 ---- a/nptl/Makefile -+++ b/nptl/Makefile -@@ -313,7 +313,8 @@ tests = tst-attr2 tst-attr3 tst-default-attr \ - tst-thread-affinity-sched \ - tst-pthread-defaultattr-free \ - tst-pthread-attr-sigmask \ -- tst-pthread-timedlock-lockloop -+ tst-pthread-timedlock-lockloop \ -+ tst-pthread-gdb-attach tst-pthread-gdb-attach-static - - tests-container = tst-pthread-getattr - -@@ -359,6 +360,19 @@ CPPFLAGS-test-cond-printers.c := $(CFLAGS-printers-tests) - CPPFLAGS-test-rwlockattr-printers.c := $(CFLAGS-printers-tests) - CPPFLAGS-test-rwlock-printers.c := $(CFLAGS-printers-tests) - -+# Reuse the CFLAGS setting for the GDB attaching test. It needs -+# debugging information. -+CFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests) -+CPPFLAGS-tst-pthread-gdb-attach.c := $(CFLAGS-printers-tests) -+ifeq ($(build-shared)$(build-hardcoded-path-in-tests),yesno) -+CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=1 -+else -+CPPFLAGS-tst-pthread-gdb-attach.c += -DDO_ADD_SYMBOL_FILE=0 -+endif -+CFLAGS-tst-pthread-gdb-attach-static.c := $(CFLAGS-printers-tests) -+CPPFLAGS-tst-pthread-gdb-attach-static.c := \ -+ $(CFLAGS-printers-tests) -DDO_ADD_SYMBOL_FILE=0 -+ - ifeq ($(build-shared),yes) - tests-printers-libs := $(shared-thread-library) - else -@@ -430,7 +444,8 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \ - tests-static += tst-stackguard1-static \ - tst-cancel24-static \ - tst-mutex8-static tst-mutexpi8-static tst-sem11-static \ -- tst-sem12-static tst-cond11-static -+ tst-sem12-static tst-cond11-static \ -+ tst-pthread-gdb-attach-static - - tests += tst-cancel24-static - -diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c -index 6c645aff48..f13d8e44a4 100644 ---- a/nptl/pthread_create.c -+++ b/nptl/pthread_create.c -@@ -51,6 +51,14 @@ static td_thr_events_t __nptl_threads_events __attribute_used__; - /* Pointer to descriptor with the last event. */ - static struct pthread *__nptl_last_event __attribute_used__; - -+#ifdef SHARED -+/* This variable is used to access _rtld_global from libthread_db. If -+ GDB loads libpthread before ld.so, it is not possible to resolve -+ _rtld_global directly during libpthread initialization. */ -+static struct rtld_global *__nptl_rtld_global __attribute_used__ -+ = &_rtld_global; -+#endif -+ - /* Number of threads running. */ - unsigned int __nptl_nthreads = 1; - -diff --git a/nptl/tst-pthread-gdb-attach-static.c b/nptl/tst-pthread-gdb-attach-static.c -new file mode 100644 -index 0000000000..e159632cac ---- /dev/null -+++ b/nptl/tst-pthread-gdb-attach-static.c -@@ -0,0 +1 @@ -+#include "tst-pthread-gdb-attach.c" -diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c -new file mode 100644 -index 0000000000..0603ad844d ---- /dev/null -+++ b/nptl/tst-pthread-gdb-attach.c -@@ -0,0 +1,143 @@ -+/* Smoke testing GDB process attach with thread-local variable access. -+ Copyright (C) 2021 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This test runs GDB against a forked copy of itself, to check -+ whether libthread_db can be loaded, and that access to thread-local -+ variables works. */ -+ -+#include <errno.h> -+#include <stdlib.h> -+#include <support/check.h> -+#include <support/support.h> -+#include <support/temp_file.h> -+#include <support/test-driver.h> -+#include <support/xstdio.h> -+#include <support/xthread.h> -+#include <support/xunistd.h> -+#include <unistd.h> -+ -+/* Starts out as zero, changed to 1 or 2 by the debugger, depending on -+ the thread. */ -+__thread volatile int altered_by_debugger; -+ -+/* Writes the GDB script to run the test to PATH. */ -+static void -+write_gdbscript (const char *path, int tested_pid) -+{ -+ FILE *fp = xfopen (path, "w"); -+ fprintf (fp, -+ "set trace-commands on\n" -+ "set debug libthread-db 1\n" -+#if DO_ADD_SYMBOL_FILE -+ /* Do not do this unconditionally to work around a GDB -+ assertion failure: ../../gdb/symtab.c:6404: -+ internal-error: CORE_ADDR get_msymbol_address(objfile*, -+ const minimal_symbol*): Assertion `(objf->flags & -+ OBJF_MAINLINE) == 0' failed. */ -+ "add-symbol-file %1$s/nptl/tst-pthread-gdb-attach\n" -+#endif -+ "set auto-load safe-path %1$s/nptl_db\n" -+ "set libthread-db-search-path %1$s/nptl_db\n" -+ "attach %2$d\n", -+ support_objdir_root, tested_pid); -+ fputs ("break debugger_inspection_point\n" -+ "continue\n" -+ "thread 1\n" -+ "print altered_by_debugger\n" -+ "print altered_by_debugger = 1\n" -+ "thread 2\n" -+ "print altered_by_debugger\n" -+ "print altered_by_debugger = 2\n" -+ "continue\n", -+ fp); -+ xfclose (fp); -+} -+ -+/* The test sets a breakpoint on this function and alters the -+ altered_by_debugger thread-local variable. */ -+void __attribute__ ((weak)) -+debugger_inspection_point (void) -+{ -+} -+ -+/* Thread function for the test thread in the subprocess. */ -+static void * -+subprocess_thread (void *closure) -+{ -+ /* Wait until altered_by_debugger changes the value away from 0. */ -+ while (altered_by_debugger == 0) -+ { -+ usleep (100 * 1000); -+ debugger_inspection_point (); -+ } -+ -+ TEST_COMPARE (altered_by_debugger, 2); -+ return NULL; -+} -+ -+/* This function implements the subprocess under test. It creates a -+ second thread, waiting for its value to change to 2, and checks -+ that the main thread also changed its value to 1. */ -+static void -+in_subprocess (void) -+{ -+ pthread_t thr = xpthread_create (NULL, subprocess_thread, NULL); -+ TEST_VERIFY (xpthread_join (thr) == NULL); -+ TEST_COMPARE (altered_by_debugger, 1); -+ _exit (0); -+} -+ -+static int -+do_test (void) -+{ -+ pid_t tested_pid = xfork (); -+ if (tested_pid == 0) -+ in_subprocess (); -+ char *tested_pid_string = xasprintf ("%d", tested_pid); -+ -+ char *gdbscript; -+ xclose (create_temp_file ("tst-pthread-gdb-attach-", &gdbscript)); -+ write_gdbscript (gdbscript, tested_pid); -+ -+ pid_t gdb_pid = xfork (); -+ if (gdb_pid == 0) -+ { -+ clearenv (); -+ xdup2 (STDOUT_FILENO, STDERR_FILENO); -+ execlp ("gdb", "gdb", "-nx", "-batch", "-x", gdbscript, NULL); -+ if (errno == ENOENT) -+ _exit (EXIT_UNSUPPORTED); -+ else -+ _exit (1); -+ } -+ -+ int status; -+ TEST_COMPARE (xwaitpid (gdb_pid, &status, 0), gdb_pid); -+ if (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_UNSUPPORTED) -+ /* gdb is not installed. */ -+ return EXIT_UNSUPPORTED; -+ TEST_COMPARE (status, 0); -+ TEST_COMPARE (xwaitpid (tested_pid, &status, 0), tested_pid); -+ TEST_COMPARE (status, 0); -+ -+ free (tested_pid_string); -+ free (gdbscript); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/nptl_db/structs.def b/nptl_db/structs.def -index 999a9fc35a..8a613dd2f5 100644 ---- a/nptl_db/structs.def -+++ b/nptl_db/structs.def -@@ -100,8 +100,7 @@ DB_STRUCT_FIELD (pthread, dtvp) - #endif - - #if !(IS_IN (libpthread) && !defined SHARED) --DB_STRUCT (rtld_global) --DB_RTLD_VARIABLE (_rtld_global) -+DB_VARIABLE (__nptl_rtld_global) - #endif - DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list) - DB_RTLD_GLOBAL_FIELD (dl_stack_user) -diff --git a/nptl_db/td_init.c b/nptl_db/td_init.c -index 1d15681228..06b5adc5c2 100644 ---- a/nptl_db/td_init.c -+++ b/nptl_db/td_init.c -@@ -33,13 +33,14 @@ td_init (void) - bool - __td_ta_rtld_global (td_thragent_t *ta) - { -- if (ta->ta_addr__rtld_global == 0 -- && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global, -- &ta->ta_addr__rtld_global) != PS_OK) -+ if (ta->ta_addr__rtld_global == 0) - { -- ta->ta_addr__rtld_global = (void*)-1; -- return false; -+ psaddr_t rtldglobalp; -+ if (DB_GET_VALUE (rtldglobalp, ta, __nptl_rtld_global, 0) == TD_OK) -+ ta->ta_addr__rtld_global = rtldglobalp; -+ else -+ ta->ta_addr__rtld_global = (void *) -1; - } -- else -- return ta->ta_addr__rtld_global != (void*)-1; -+ -+ return ta->ta_addr__rtld_global != (void *)-1; - } -diff --git a/nptl_db/thread_dbP.h b/nptl_db/thread_dbP.h -index 580a70c471..712fa3aeb6 100644 ---- a/nptl_db/thread_dbP.h -+++ b/nptl_db/thread_dbP.h -@@ -108,6 +108,8 @@ struct td_thragent - # undef DB_SYMBOL - # undef DB_VARIABLE - -+ psaddr_t ta_addr__rtld_global; -+ - /* The method of locating a thread's th_unique value. */ - enum - { --- -2.31.1 - diff --git a/0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch b/0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch deleted file mode 100644 index d3846d654ca7..000000000000 --- a/0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch +++ /dev/null @@ -1,135 +0,0 @@ -From f553dc066071a4465321fbc122bed8a75afd996b Mon Sep 17 00:00:00 2001 -From: Florian Weimer <fweimer@redhat.com> -Date: Thu, 22 Apr 2021 11:07:43 +0200 -Subject: [PATCH 405/576] nptl: Check for compatible GDB in - nptl/tst-pthread-gdb-attach - -Also do not clear the subprocess environment, in case running -GDB needs certain environment variables. ---- - nptl/tst-pthread-gdb-attach.c | 78 ++++++++++++++++++++++++++++++++++- - 1 file changed, 76 insertions(+), 2 deletions(-) - -diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c -index 0603ad844d..901a120034 100644 ---- a/nptl/tst-pthread-gdb-attach.c -+++ b/nptl/tst-pthread-gdb-attach.c -@@ -20,8 +20,12 @@ - whether libthread_db can be loaded, and that access to thread-local - variables works. */ - -+#include <elf.h> - #include <errno.h> -+#include <fcntl.h> -+#include <stdbool.h> - #include <stdlib.h> -+#include <string.h> - #include <support/check.h> - #include <support/support.h> - #include <support/temp_file.h> -@@ -35,6 +39,49 @@ - the thread. */ - __thread volatile int altered_by_debugger; - -+/* Common prefix between 32-bit and 64-bit ELF. */ -+struct elf_prefix -+{ -+ unsigned char e_ident[EI_NIDENT]; -+ uint16_t e_type; -+ uint16_t e_machine; -+ uint32_t e_version; -+}; -+_Static_assert (sizeof (struct elf_prefix) == EI_NIDENT + 8, -+ "padding in struct elf_prefix"); -+ -+/* Reads the ELF header from PATH. Returns true if the header can be -+ read, false if the file is too short. */ -+static bool -+read_elf_header (const char *path, struct elf_prefix *elf) -+{ -+ int fd = xopen (path, O_RDONLY, 0); -+ bool result = read (fd, elf, sizeof (*elf)) == sizeof (*elf); -+ xclose (fd); -+ return result; -+} -+ -+/* Searches for "gdb" alongside the path variable. See execvpe. */ -+static char * -+find_gdb (void) -+{ -+ const char *path = getenv ("PATH"); -+ if (path == NULL) -+ return NULL; -+ while (true) -+ { -+ const char *colon = strchrnul (path, ':'); -+ char *candidate = xasprintf ("%.*s/gdb", (int) (colon - path), path); -+ if (access (candidate, X_OK) == 0) -+ return candidate; -+ free (candidate); -+ if (*colon == '\0') -+ break; -+ path = colon + 1; -+ } -+ return NULL; -+} -+ - /* Writes the GDB script to run the test to PATH. */ - static void - write_gdbscript (const char *path, int tested_pid) -@@ -105,6 +152,33 @@ in_subprocess (void) - static int - do_test (void) - { -+ char *gdb_path = find_gdb (); -+ if (gdb_path == NULL) -+ FAIL_UNSUPPORTED ("gdb command not found in PATH: %s", getenv ("PATH")); -+ -+ /* Check that libthread_db is compatible with the gdb architecture -+ because gdb loads it via dlopen. */ -+ { -+ char *threaddb_path = xasprintf ("%s/nptl_db/libthread_db.so", -+ support_objdir_root); -+ struct elf_prefix elf_threaddb; -+ TEST_VERIFY_EXIT (read_elf_header (threaddb_path, &elf_threaddb)); -+ struct elf_prefix elf_gdb; -+ /* If the ELF header cannot be read or "gdb" is not an ELF file, -+ assume this is a wrapper script that can run. */ -+ if (read_elf_header (gdb_path, &elf_gdb) -+ && memcmp (&elf_gdb, ELFMAG, SELFMAG) == 0) -+ { -+ if (elf_gdb.e_ident[EI_CLASS] != elf_threaddb.e_ident[EI_CLASS]) -+ FAIL_UNSUPPORTED ("GDB at %s has wrong class", gdb_path); -+ if (elf_gdb.e_ident[EI_DATA] != elf_threaddb.e_ident[EI_DATA]) -+ FAIL_UNSUPPORTED ("GDB at %s has wrong data", gdb_path); -+ if (elf_gdb.e_machine != elf_threaddb.e_machine) -+ FAIL_UNSUPPORTED ("GDB at %s has wrong machine", gdb_path); -+ } -+ free (threaddb_path); -+ } -+ - pid_t tested_pid = xfork (); - if (tested_pid == 0) - in_subprocess (); -@@ -117,9 +191,8 @@ do_test (void) - pid_t gdb_pid = xfork (); - if (gdb_pid == 0) - { -- clearenv (); - xdup2 (STDOUT_FILENO, STDERR_FILENO); -- execlp ("gdb", "gdb", "-nx", "-batch", "-x", gdbscript, NULL); -+ execl (gdb_path, "gdb", "-nx", "-batch", "-x", gdbscript, NULL); - if (errno == ENOENT) - _exit (EXIT_UNSUPPORTED); - else -@@ -137,6 +210,7 @@ do_test (void) - - free (tested_pid_string); - free (gdbscript); -+ free (gdb_path); - return 0; - } - --- -2.31.1 - diff --git a/0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch b/0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch deleted file mode 100644 index 1ba043d0233c..000000000000 --- a/0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6f3e54d404cfe1ba7d1444e6dfcfd77b102d9287 Mon Sep 17 00:00:00 2001 -From: Florian Weimer <fweimer@redhat.com> -Date: Thu, 22 Apr 2021 19:53:15 +0200 -Subject: [PATCH 409/576] nptl: Do not build nptl/tst-pthread-gdb-attach as PIE - ---- - nptl/Makefile | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/nptl/Makefile b/nptl/Makefile -index a3d1ef8d66..294bb2faa4 100644 ---- a/nptl/Makefile -+++ b/nptl/Makefile -@@ -377,6 +377,9 @@ endif - CFLAGS-tst-pthread-gdb-attach-static.c := $(CFLAGS-printers-tests) - CPPFLAGS-tst-pthread-gdb-attach-static.c := \ - $(CFLAGS-printers-tests) -DDO_ADD_SYMBOL_FILE=0 -+# As of version 9.2, GDB cannot attach properly to PIE programs that -+# were launched with an explicit ld.so invocation. -+tst-pthread-gdb-attach-no-pie = yes - - ifeq ($(build-shared),yes) - tests-printers-libs := $(shared-thread-library) --- -2.31.1 - @@ -6,258 +6,21 @@ pkgbase=glibc-dso pkgname=(glibc-dso lib32-glibc-dso) pkgver=2.33 -pkgrel=10 +pkgrel=11 arch=(x86_64) url='https://www.gnu.org/software/libc' license=(GPL LGPL) -makedepends=(git gd lib32-gcc-libs python cpio) -optdepends=('perl: for mtrace') -options=(!strip staticlibs) -#_commit=3de512be7ea6053255afed6154db9ee31d4e557a -#source=(git+https://sourceware.org/git/glibc.git#commit=$_commit -source=(https://ftp.gnu.org/gnu/glibc/glibc-$pkgver.tar.xz{,.sig} - locale.gen.txt - locale-gen - lib32-glibc.conf - sdt.h sdt-config.h - bz27343.patch - 0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch - 0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch - 0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch - v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch - v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch) -validpgpkeys=(7273542B39962DF7B299931416792B4EA25340F8 # Carlos O'Donell - BC7C7372637EC10C57D7AA6579C43DFBF1CF2187) # Siddhesh Poyarekar -md5sums=('390bbd889c7e8e8a7041564cb6b27cca' - 'SKIP' - '07ac979b6ab5eeb778d55f041529d623' - '476e9113489f93b348b21e144b6a8fcf' - '6e052f1cb693d5d3203f50f9d4e8c33b' - '91fec3b7e75510ae2ac42533aa2e695e' - '680df504c683640b02ed4a805797c0b2' - 'cfe57018d06bf748b8ca1779980fef33' - '78f041fc66fee4ee372f13b00a99ff72' - '9e418efa189c20053e887398df2253cf' - '7a09f1693613897add1791e7aead19c9' - '5974b86859dd65c7cfda756a8b2445c2' - '26a619a810de7d296608cc78377bc27c') prepare() { - echo "THIS PACKAGE IS NO LONGER WORKING DO NOT INSTALL IT" - exit 1 - - mkdir -p glibc-build lib32-glibc-build - - [[ -d glibc-$pkgver ]] && ln -s glibc-$pkgver glibc - cd glibc - - # commit c3479fb7939898ec22c655c383454d6e8b982a67 - patch -p1 -i "$srcdir"/bz27343.patch - - # nptl_db: Support different libpthread/ld.so load orders (bug 27744) - patch -p1 -i "$srcdir"/0001-nptl_db-Support-different-libpthread-ld.so-load-orde.patch - - # nptl: Check for compatible GDB in nptl/tst-pthread-gdb-attach - patch -p1 -i "$srcdir"/0002-nptl-Check-for-compatible-GDB-in-nptl-tst-pthread-gd.patch - - # nptl: Do not build nptl/tst-pthread-gdb-attach as PIE - patch -p1 -i "$srcdir"/0003-nptl-Do-not-build-nptl-tst-pthread-gdb-attach-as-PIE.patch - patch -p1 -i "$srcdir"/v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch - patch -p1 -i "$srcdir"/v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch -} - -build() { - local _configure_flags=( - --prefix=/usr - --with-headers=/usr/include - --with-bugurl=https://bugs.archlinux.org/ - --enable-add-ons - --enable-bind-now - --enable-cet - --enable-kernel=4.4 - --enable-lock-elision - --enable-multi-arch - --enable-stack-protector=strong - --enable-stackguard-randomization - --enable-static-pie - --enable-systemtap - --disable-profile - --disable-werror - ) - - cd "$srcdir/glibc-build" - - echo "slibdir=/usr/lib" >> configparms - echo "rtlddir=/usr/lib" >> configparms - echo "sbindir=/usr/bin" >> configparms - echo "rootsbindir=/usr/bin" >> configparms - - # remove fortify for building libraries - CPPFLAGS=${CPPFLAGS/-D_FORTIFY_SOURCE=2/} - CFLAGS=${CFLAGS/-Wp,-D_FORTIFY_SOURCE=2/} - - # - CFLAGS=${CFLAGS/-fno-plt/} - CXXFLAGS=${CXXFLAGS/-fno-plt/} - LDFLAGS=${LDFLAGS/,-z,now/} - - "$srcdir/glibc/configure" \ - --libdir=/usr/lib \ - --libexecdir=/usr/lib \ - ${_configure_flags[@]} - - # build libraries with fortify disabled - echo "build-programs=no" >> configparms - make - - # re-enable fortify for programs - sed -i "/build-programs=/s#no#yes#" configparms - - echo "CC += -D_FORTIFY_SOURCE=2" >> configparms - echo "CXX += -D_FORTIFY_SOURCE=2" >> configparms - make - - # build info pages manually for reprducibility - make info - - cd "$srcdir/lib32-glibc-build" - export CC="gcc -m32 -mstackrealign" - export CXX="g++ -m32 -mstackrealign" - - echo "slibdir=/usr/lib32" >> configparms - echo "rtlddir=/usr/lib32" >> configparms - echo "sbindir=/usr/bin" >> configparms - echo "rootsbindir=/usr/bin" >> configparms - - # remove fortify for building libraries - CPPFLAGS=${CPPFLAGS/-D_FORTIFY_SOURCE=2/} - CFLAGS=${CFLAGS/-Wp,-D_FORTIFY_SOURCE=2/} - CFLAGS=${CFLAGS/-fno-plt/} - CXXFLAGS=${CXXFLAGS/-fno-plt/} - - "$srcdir/glibc/configure" \ - --host=i686-pc-linux-gnu \ - --libdir=/usr/lib32 \ - --libexecdir=/usr/lib32 \ - ${_configure_flags[@]} - - # build libraries with fortify disabled - echo "build-programs=no" >> configparms - make - - # re-enable fortify for programs - sed -i "/build-programs=/s#no#yes#" configparms - - echo "CC += -D_FORTIFY_SOURCE=2" >> configparms - echo "CXX += -D_FORTIFY_SOURCE=2" >> configparms - make - -} - -check() { - cd glibc-build - - # remove fortify in preparation to run test-suite - sed -i '/FORTIFY/d' configparms - - # some failures are "expected" - make check || true + echo "This package is decomisioned, installing this update will revert to your mainline glibc and should be installed ASAP" } package_glibc-dso() { pkgdesc='GNU C Library - DSO patch' - depends=('linux-api-headers>=4.10' tzdata filesystem) - optdepends=('gd: for memusagestat') - install=glibc.install - backup=(etc/gai.conf - etc/locale.gen - etc/nscd.conf) - provides=("glibc=${pkgver%%.r*}") - conflicts=('glibc') - - install -dm755 "$pkgdir/etc" - touch "$pkgdir/etc/ld.so.conf" - - make -C glibc-build install_root="$pkgdir" install - rm -f "$pkgdir"/etc/ld.so.{cache,conf} - - # Shipped in tzdata - rm -f "$pkgdir"/usr/bin/{tzselect,zdump,zic} - - cd glibc - - install -dm755 "$pkgdir"/usr/lib/{locale,systemd/system,tmpfiles.d} - install -m644 nscd/nscd.conf "$pkgdir/etc/nscd.conf" - install -m644 nscd/nscd.service "$pkgdir/usr/lib/systemd/system" - install -m644 nscd/nscd.tmpfiles "$pkgdir/usr/lib/tmpfiles.d/nscd.conf" - install -dm755 "$pkgdir/var/db/nscd" - - install -m644 posix/gai.conf "$pkgdir"/etc/gai.conf - - install -m755 "$srcdir/locale-gen" "$pkgdir/usr/bin" - - # Create /etc/locale.gen - install -m644 "$srcdir/locale.gen.txt" "$pkgdir/etc/locale.gen" - sed -e '1,3d' -e 's|/| |g' -e 's|\\| |g' -e 's|^|#|g' \ - "$srcdir/glibc/localedata/SUPPORTED" >> "$pkgdir/etc/locale.gen" - - if check_option 'debug' n; then - find "$pkgdir"/usr/bin -type f -executable -exec strip $STRIP_BINARIES {} + 2> /dev/null || true - find "$pkgdir"/usr/lib -name '*.a' -type f -exec strip $STRIP_STATIC {} + 2> /dev/null || true - - # Do not strip these for gdb and valgrind functionality, but strip the rest - find "$pkgdir"/usr/lib \ - -not -name 'ld-*.so' \ - -not -name 'libc-*.so' \ - -not -name 'libpthread-*.so' \ - -not -name 'libthread_db-*.so' \ - -name '*-*.so' -type f -exec strip $STRIP_SHARED {} + 2> /dev/null || true - fi - - # Provide tracing probes to libstdc++ for exceptions, possibly for other - # libraries too. Useful for gdb's catch command. - install -Dm644 "$srcdir/sdt.h" "$pkgdir/usr/include/sys/sdt.h" - install -Dm644 "$srcdir/sdt-config.h" "$pkgdir/usr/include/sys/sdt-config.h" - - # Provided by libxcrypt; keep the old shared library for backwards compatibility - rm -f "$pkgdir"/usr/include/crypt.h "$pkgdir"/usr/lib/libcrypt.{a,so} + depends=('glibc') } package_lib32-glibc-dso() { pkgdesc='GNU C Library (32-bit) - DSO patch' - depends=("glibc=$pkgver") - options+=('!emptydirs') - provides=("lib32-glibc=${pkgver%%.r*}") - conflicts=('lib32-glibc') - - cd lib32-glibc-build - - make install_root="$pkgdir" install - rm -rf "$pkgdir"/{etc,sbin,usr/{bin,sbin,share},var} - - # We need to keep 32 bit specific header files - find "$pkgdir/usr/include" -type f -not -name '*-32.h' -delete - - # Dynamic linker - install -d "$pkgdir/usr/lib" - ln -s ../lib32/ld-linux.so.2 "$pkgdir/usr/lib/" - - # Add lib32 paths to the default library search path - install -Dm644 "$srcdir/lib32-glibc.conf" "$pkgdir/etc/ld.so.conf.d/lib32-glibc.conf" - - # Symlink /usr/lib32/locale to /usr/lib/locale - ln -s ../lib/locale "$pkgdir/usr/lib32/locale" - - if check_option 'debug' n; then - find "$pkgdir"/usr/lib32 -name '*.a' -type f -exec strip $STRIP_STATIC {} + 2> /dev/null || true - find "$pkgdir"/usr/lib32 \ - -not -name 'ld-*.so' \ - -not -name 'libc-*.so' \ - -not -name 'libpthread-*.so' \ - -not -name 'libthread_db-*.so' \ - -name '*-*.so' -type f -exec strip $STRIP_SHARED {} + 2> /dev/null || true - fi - - # Provided by lib32-libxcrypt; keep the old shared library for backwards compatibility - rm -f "$pkgdir"/usr/lib32/libcrypt.{a,so} + depends=("lib32-glibc") } diff --git a/bz27343.patch b/bz27343.patch deleted file mode 100644 index 3db6a9440eb2..000000000000 --- a/bz27343.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c3479fb7939898ec22c655c383454d6e8b982a67 Mon Sep 17 00:00:00 2001 -From: Sergei Trofimovich <slyfox@gentoo.org> -Date: Fri, 5 Feb 2021 07:32:18 +0000 -Subject: [PATCH] nsswitch: return result when nss database is locked [BZ - #27343] - -Before the change nss_database_check_reload_and_get() did not populate -the '*result' value when it returned success in a case of chroot -detection. This caused initgroups() to use garage pointer in the -following test (extracted from unbound): - -``` - -int main() { - // load some NSS modules - struct passwd * pw = getpwnam("root"); - - chdir("/tmp"); - chroot("/tmp"); - chdir("/"); - // access nsswitch.conf in a chroot - initgroups("root", 0); -} -``` - -Reviewed-by: DJ Delorie <dj@redhat.com> ---- - nss/nss_database.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/nss/nss_database.c b/nss/nss_database.c -index cf0306adc4..e1bef6bd75 100644 ---- a/nss/nss_database.c -+++ b/nss/nss_database.c -@@ -398,8 +398,9 @@ nss_database_check_reload_and_get (struct nss_database_state *local, - && (str.st_ino != local->root_ino - || str.st_dev != local->root_dev))) - { -- /* Change detected; disable reloading. */ -+ /* Change detected; disable reloading and return current state. */ - atomic_store_release (&local->data.reload_disabled, 1); -+ *result = local->data.services[database_index]; - __libc_lock_unlock (local->lock); - __nss_module_disable_loading (); - return true; --- -2.27.0 - diff --git a/glibc.install b/glibc.install deleted file mode 100644 index 351f05b263cb..000000000000 --- a/glibc.install +++ /dev/null @@ -1,5 +0,0 @@ -post_upgrade() { - locale-gen - - ldconfig -r . -} diff --git a/lib32-glibc.conf b/lib32-glibc.conf deleted file mode 100644 index 9b08c3f43a78..000000000000 --- a/lib32-glibc.conf +++ /dev/null @@ -1 +0,0 @@ -/usr/lib32 diff --git a/locale-gen b/locale-gen deleted file mode 100755 index 5aff344c4e91..000000000000 --- a/locale-gen +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -set -e - -LOCALEGEN=/etc/locale.gen -LOCALES=/usr/share/i18n/locales -if [ -n "$POSIXLY_CORRECT" ]; then - unset POSIXLY_CORRECT -fi - - -[ -f $LOCALEGEN -a -s $LOCALEGEN ] || exit 0; - -# Remove all old locale dir and locale-archive before generating new -# locale data. -rm -rf /usr/lib/locale/* || true - -umask 022 - -is_entry_ok() { - if [ -n "$locale" -a -n "$charset" ] ; then - true - else - echo "error: Bad entry '$locale $charset'" - false - fi -} - -echo "Generating locales..." -while read locale charset; do \ - case $locale in \#*) continue;; "") continue;; esac; \ - is_entry_ok || continue - echo -n " `echo $locale | sed 's/\([^.\@]*\).*/\1/'`"; \ - echo -n ".$charset"; \ - echo -n `echo $locale | sed 's/\([^\@]*\)\(\@.*\)*/\2/'`; \ - echo -n '...'; \ - if [ -f $LOCALES/$locale ]; then input=$locale; else \ - input=`echo $locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; fi; \ - localedef -i $input -c -f $charset -A /usr/share/locale/locale.alias $locale; \ - echo ' done'; \ -done < $LOCALEGEN -echo "Generation complete." diff --git a/locale.gen.txt b/locale.gen.txt deleted file mode 100644 index ccdd817342c7..000000000000 --- a/locale.gen.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Configuration file for locale-gen -# -# lists of locales that are to be generated by the locale-gen command. -# -# Each line is of the form: -# -# <locale> <charset> -# -# where <locale> is one of the locales given in /usr/share/i18n/locales -# and <charset> is one of the character sets listed in /usr/share/i18n/charmaps -# -# Examples: -# en_US ISO-8859-1 -# en_US.UTF-8 UTF-8 -# de_DE ISO-8859-1 -# de_DE@euro ISO-8859-15 -# -# The locale-gen command will generate all the locales, -# placing them in /usr/lib/locale. -# -# A list of supported locales is included in this file. -# Uncomment the ones you need. -# diff --git a/sdt-config.h b/sdt-config.h deleted file mode 100644 index 733045a52771..000000000000 --- a/sdt-config.h +++ /dev/null @@ -1,6 +0,0 @@ -/* includes/sys/sdt-config.h. Generated from sdt-config.h.in by configure. - - This file just defines _SDT_ASM_SECTION_AUTOGROUP_SUPPORT to 0 or 1 to - indicate whether the assembler supports "?" in .pushsection directives. */ - -#define _SDT_ASM_SECTION_AUTOGROUP_SUPPORT 1 diff --git a/sdt.h b/sdt.h deleted file mode 100644 index c0c5a492cb9c..000000000000 --- a/sdt.h +++ /dev/null @@ -1,430 +0,0 @@ -/* <sys/sdt.h> - Systemtap static probe definition macros. - - This file is dedicated to the public domain, pursuant to CC0 - (https://creativecommons.org/publicdomain/zero/1.0/) -*/ - -#ifndef _SYS_SDT_H -#define _SYS_SDT_H 1 - -/* - This file defines a family of macros - - STAP_PROBEn(op1, ..., opn) - - that emit a nop into the instruction stream, and some data into an auxiliary - note section. The data in the note section describes the operands, in terms - of size and location. Each location is encoded as assembler operand string. - Consumer tools such as gdb or systemtap insert breakpoints on top of - the nop, and decode the location operand-strings, like an assembler, - to find the values being passed. - - The operand strings are selected by the compiler for each operand. - They are constrained by gcc inline-assembler codes. The default is: - - #define STAP_SDT_ARG_CONSTRAINT nor - - This is a good default if the operands tend to be integral and - moderate in number (smaller than number of registers). In other - cases, the compiler may report "'asm' requires impossible reload" or - similar. In this case, consider simplifying the macro call (fewer - and simpler operands), reduce optimization, or override the default - constraints string via: - - #define STAP_SDT_ARG_CONSTRAINT g - #include <sys/sdt.h> - - See also: - https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation - https://gcc.gnu.org/onlinedocs/gcc/Constraints.html - */ - - - -#ifdef __ASSEMBLER__ -# define _SDT_PROBE(provider, name, n, arglist) \ - _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING_1, (_SDT_DEPAREN_##n arglist)) \ - _SDT_ASM_BASE -# define _SDT_ASM_1(x) x; -# define _SDT_ASM_2(a, b) a,b; -# define _SDT_ASM_3(a, b, c) a,b,c; -# define _SDT_ASM_5(a, b, c, d, e) a,b,c,d,e; -# define _SDT_ASM_STRING_1(x) .asciz #x; -# define _SDT_DEPAREN_0() /* empty */ -# define _SDT_DEPAREN_1(a) a -# define _SDT_DEPAREN_2(a,b) a b -# define _SDT_DEPAREN_3(a,b,c) a b c -# define _SDT_DEPAREN_4(a,b,c,d) a b c d -# define _SDT_DEPAREN_5(a,b,c,d,e) a b c d e -# define _SDT_DEPAREN_6(a,b,c,d,e,f) a b c d e f -# define _SDT_DEPAREN_7(a,b,c,d,e,f,g) a b c d e f g -# define _SDT_DEPAREN_8(a,b,c,d,e,f,g,h) a b c d e f g h -# define _SDT_DEPAREN_9(a,b,c,d,e,f,g,h,i) a b c d e f g h i -# define _SDT_DEPAREN_10(a,b,c,d,e,f,g,h,i,j) a b c d e f g h i j -# define _SDT_DEPAREN_11(a,b,c,d,e,f,g,h,i,j,k) a b c d e f g h i j k -# define _SDT_DEPAREN_12(a,b,c,d,e,f,g,h,i,j,k,l) a b c d e f g h i j k l -#else -# define _SDT_PROBE(provider, name, n, arglist) \ - do { \ - __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \ - :: _SDT_ASM_OPERANDS_##n arglist); \ - __asm__ __volatile__ (_SDT_ASM_BASE); \ - } while (0) -# define _SDT_S(x) #x -# define _SDT_ASM_1(x) _SDT_S(x) "\n" -# define _SDT_ASM_2(a, b) _SDT_S(a) "," _SDT_S(b) "\n" -# define _SDT_ASM_3(a, b, c) _SDT_S(a) "," _SDT_S(b) "," \ - _SDT_S(c) "\n" -# define _SDT_ASM_5(a, b, c, d, e) _SDT_S(a) "," _SDT_S(b) "," \ - _SDT_S(c) "," _SDT_S(d) "," \ - _SDT_S(e) "\n" -# define _SDT_ASM_ARGS(n) _SDT_ASM_STRING(_SDT_ASM_TEMPLATE_##n) -# define _SDT_ASM_STRING_1(x) _SDT_ASM_1(.asciz #x) - -# define _SDT_ARGFMT(no) %n[_SDT_S##no]@_SDT_ARGTMPL(_SDT_A##no) - -# ifndef STAP_SDT_ARG_CONSTRAINT -# if defined __powerpc__ -# define STAP_SDT_ARG_CONSTRAINT nZr -# else -# define STAP_SDT_ARG_CONSTRAINT nor -# endif -# endif - -# define _SDT_STRINGIFY(x) #x -# define _SDT_ARG_CONSTRAINT_STRING(x) _SDT_STRINGIFY(x) -# define _SDT_ARG(n, x) \ - [_SDT_S##n] "n" ((_SDT_ARGSIGNED (x) ? 1 : -1) * (int) _SDT_ARGSIZE (x)), \ - [_SDT_A##n] _SDT_ARG_CONSTRAINT_STRING (STAP_SDT_ARG_CONSTRAINT) (_SDT_ARGVAL (x)) -#endif -#define _SDT_ASM_STRING(x) _SDT_ASM_STRING_1(x) - -#define _SDT_ARGARRAY(x) (__builtin_classify_type (x) == 14 \ - || __builtin_classify_type (x) == 5) - -#ifdef __cplusplus -# define _SDT_ARGSIGNED(x) (!_SDT_ARGARRAY (x) \ - && __sdt_type<__typeof (x)>::__sdt_signed) -# define _SDT_ARGSIZE(x) (_SDT_ARGARRAY (x) \ - ? sizeof (void *) : sizeof (x)) -# define _SDT_ARGVAL(x) (x) - -# include <cstddef> - -template<typename __sdt_T> -struct __sdt_type -{ - static const bool __sdt_signed = false; -}; - -#define __SDT_ALWAYS_SIGNED(T) \ -template<> struct __sdt_type<T> { static const bool __sdt_signed = true; }; -#define __SDT_COND_SIGNED(T,CT) \ -template<> struct __sdt_type<T> { static const bool __sdt_signed = ((CT)(-1) < 1); }; -__SDT_ALWAYS_SIGNED(signed char) -__SDT_ALWAYS_SIGNED(short) -__SDT_ALWAYS_SIGNED(int) -__SDT_ALWAYS_SIGNED(long) -__SDT_ALWAYS_SIGNED(long long) -__SDT_ALWAYS_SIGNED(volatile signed char) -__SDT_ALWAYS_SIGNED(volatile short) -__SDT_ALWAYS_SIGNED(volatile int) -__SDT_ALWAYS_SIGNED(volatile long) -__SDT_ALWAYS_SIGNED(volatile long long) -__SDT_ALWAYS_SIGNED(const signed char) -__SDT_ALWAYS_SIGNED(const short) -__SDT_ALWAYS_SIGNED(const int) -__SDT_ALWAYS_SIGNED(const long) -__SDT_ALWAYS_SIGNED(const long long) -__SDT_ALWAYS_SIGNED(const volatile signed char) -__SDT_ALWAYS_SIGNED(const volatile short) -__SDT_ALWAYS_SIGNED(const volatile int) -__SDT_ALWAYS_SIGNED(const volatile long) -__SDT_ALWAYS_SIGNED(const volatile long long) -__SDT_COND_SIGNED(char, char) -__SDT_COND_SIGNED(wchar_t, wchar_t) -__SDT_COND_SIGNED(volatile char, char) -__SDT_COND_SIGNED(volatile wchar_t, wchar_t) -__SDT_COND_SIGNED(const char, char) -__SDT_COND_SIGNED(const wchar_t, wchar_t) -__SDT_COND_SIGNED(const volatile char, char) -__SDT_COND_SIGNED(const volatile wchar_t, wchar_t) -#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -/* __SDT_COND_SIGNED(char16_t) */ -/* __SDT_COND_SIGNED(char32_t) */ -#endif - -template<typename __sdt_E> -struct __sdt_type<__sdt_E[]> : public __sdt_type<__sdt_E *> {}; - -template<typename __sdt_E, size_t __sdt_N> -struct __sdt_type<__sdt_E[__sdt_N]> : public __sdt_type<__sdt_E *> {}; - -#elif !defined(__ASSEMBLER__) -__extension__ extern unsigned long long __sdt_unsp; -# define _SDT_ARGINTTYPE(x) \ - __typeof (__builtin_choose_expr (((__builtin_classify_type (x) \ - + 3) & -4) == 4, (x), 0U)) -# define _SDT_ARGSIGNED(x) \ - (!__extension__ \ - (__builtin_constant_p ((((unsigned long long) \ - (_SDT_ARGINTTYPE (x)) __sdt_unsp) \ - & ((unsigned long long)1 << (sizeof (unsigned long long) \ - * __CHAR_BIT__ - 1))) == 0) \ - || (_SDT_ARGINTTYPE (x)) -1 > (_SDT_ARGINTTYPE (x)) 0)) -# define _SDT_ARGSIZE(x) \ - (_SDT_ARGARRAY (x) ? sizeof (void *) : sizeof (x)) -# define _SDT_ARGVAL(x) (x) -#endif - -#if defined __powerpc__ || defined __powerpc64__ -# define _SDT_ARGTMPL(id) %I[id]%[id] -#elif defined __i386__ -# define _SDT_ARGTMPL(id) %w[id] /* gcc.gnu.org/PR80115 */ -#else -# define _SDT_ARGTMPL(id) %[id] -#endif - -#ifdef __LP64__ -# define _SDT_ASM_ADDR .8byte -#else -# define _SDT_ASM_ADDR .4byte -#endif - -/* The ia64 and s390 nop instructions take an argument. */ -#if defined(__ia64__) || defined(__s390__) || defined(__s390x__) -#define _SDT_NOP nop 0 -#else -#define _SDT_NOP nop -#endif - -#define _SDT_NOTE_NAME "stapsdt" -#define _SDT_NOTE_TYPE 3 - -/* If the assembler supports the necessary feature, then we can play - nice with code in COMDAT sections, which comes up in C++ code. - Without that assembler support, some combinations of probe placements - in certain kinds of C++ code may produce link-time errors. */ -#include "sdt-config.h" -#if _SDT_ASM_SECTION_AUTOGROUP_SUPPORT -# define _SDT_ASM_AUTOGROUP "?" -#else -# define _SDT_ASM_AUTOGROUP "" -#endif - -#define _SDT_ASM_BODY(provider, name, pack_args, args) \ - _SDT_ASM_1(990: _SDT_NOP) \ - _SDT_ASM_3( .pushsection .note.stapsdt,_SDT_ASM_AUTOGROUP,"note") \ - _SDT_ASM_1( .balign 4) \ - _SDT_ASM_3( .4byte 992f-991f, 994f-993f, _SDT_NOTE_TYPE) \ - _SDT_ASM_1(991: .asciz _SDT_NOTE_NAME) \ - _SDT_ASM_1(992: .balign 4) \ - _SDT_ASM_1(993: _SDT_ASM_ADDR 990b) \ - _SDT_ASM_1( _SDT_ASM_ADDR _.stapsdt.base) \ - _SDT_SEMAPHORE(provider,name) \ - _SDT_ASM_STRING(provider) \ - _SDT_ASM_STRING(name) \ - pack_args args \ - _SDT_ASM_1(994: .balign 4) \ - _SDT_ASM_1( .popsection) - -#define _SDT_ASM_BASE \ - _SDT_ASM_1(.ifndef _.stapsdt.base) \ - _SDT_ASM_5( .pushsection .stapsdt.base,"aG","progbits", \ - .stapsdt.base,comdat) \ - _SDT_ASM_1( .weak _.stapsdt.base) \ - _SDT_ASM_1( .hidden _.stapsdt.base) \ - _SDT_ASM_1( _.stapsdt.base: .space 1) \ - _SDT_ASM_2( .size _.stapsdt.base, 1) \ - _SDT_ASM_1( .popsection) \ - _SDT_ASM_1(.endif) - -#if defined _SDT_HAS_SEMAPHORES -#define _SDT_SEMAPHORE(p,n) _SDT_ASM_1( _SDT_ASM_ADDR p##_##n##_semaphore) -#else -#define _SDT_SEMAPHORE(p,n) _SDT_ASM_1( _SDT_ASM_ADDR 0) -#endif - -#define _SDT_ASM_TEMPLATE_0 /* no arguments */ -#define _SDT_ASM_TEMPLATE_1 _SDT_ARGFMT(1) -#define _SDT_ASM_TEMPLATE_2 _SDT_ASM_TEMPLATE_1 _SDT_ARGFMT(2) -#define _SDT_ASM_TEMPLATE_3 _SDT_ASM_TEMPLATE_2 _SDT_ARGFMT(3) -#define _SDT_ASM_TEMPLATE_4 _SDT_ASM_TEMPLATE_3 _SDT_ARGFMT(4) -#define _SDT_ASM_TEMPLATE_5 _SDT_ASM_TEMPLATE_4 _SDT_ARGFMT(5) -#define _SDT_ASM_TEMPLATE_6 _SDT_ASM_TEMPLATE_5 _SDT_ARGFMT(6) -#define _SDT_ASM_TEMPLATE_7 _SDT_ASM_TEMPLATE_6 _SDT_ARGFMT(7) -#define _SDT_ASM_TEMPLATE_8 _SDT_ASM_TEMPLATE_7 _SDT_ARGFMT(8) -#define _SDT_ASM_TEMPLATE_9 _SDT_ASM_TEMPLATE_8 _SDT_ARGFMT(9) -#define _SDT_ASM_TEMPLATE_10 _SDT_ASM_TEMPLATE_9 _SDT_ARGFMT(10) -#define _SDT_ASM_TEMPLATE_11 _SDT_ASM_TEMPLATE_10 _SDT_ARGFMT(11) -#define _SDT_ASM_TEMPLATE_12 _SDT_ASM_TEMPLATE_11 _SDT_ARGFMT(12) -#define _SDT_ASM_OPERANDS_0() [__sdt_dummy] "g" (0) -#define _SDT_ASM_OPERANDS_1(arg1) _SDT_ARG(1, arg1) -#define _SDT_ASM_OPERANDS_2(arg1, arg2) \ - _SDT_ASM_OPERANDS_1(arg1), _SDT_ARG(2, arg2) -#define _SDT_ASM_OPERANDS_3(arg1, arg2, arg3) \ - _SDT_ASM_OPERANDS_2(arg1, arg2), _SDT_ARG(3, arg3) -#define _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4) \ - _SDT_ASM_OPERANDS_3(arg1, arg2, arg3), _SDT_ARG(4, arg4) -#define _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5) \ - _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4), _SDT_ARG(5, arg5) -#define _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ - _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5), _SDT_ARG(6, arg6) -#define _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6), _SDT_ARG(7, arg7) -#define _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ - _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7), \ - _SDT_ARG(8, arg8) -#define _SDT_ASM_OPERANDS_9(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) \ - _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), \ - _SDT_ARG(9, arg9) -#define _SDT_ASM_OPERANDS_10(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \ - _SDT_ASM_OPERANDS_9(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), \ - _SDT_ARG(10, arg10) -#define _SDT_ASM_OPERANDS_11(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \ - _SDT_ASM_OPERANDS_10(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), \ - _SDT_ARG(11, arg11) -#define _SDT_ASM_OPERANDS_12(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \ - _SDT_ASM_OPERANDS_11(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11), \ - _SDT_ARG(12, arg12) - -/* These macros can be used in C, C++, or assembly code. - In assembly code the arguments should use normal assembly operand syntax. */ - -#define STAP_PROBE(provider, name) \ - _SDT_PROBE(provider, name, 0, ()) -#define STAP_PROBE1(provider, name, arg1) \ - _SDT_PROBE(provider, name, 1, (arg1)) -#define STAP_PROBE2(provider, name, arg1, arg2) \ - _SDT_PROBE(provider, name, 2, (arg1, arg2)) -#define STAP_PROBE3(provider, name, arg1, arg2, arg3) \ - _SDT_PROBE(provider, name, 3, (arg1, arg2, arg3)) -#define STAP_PROBE4(provider, name, arg1, arg2, arg3, arg4) \ - _SDT_PROBE(provider, name, 4, (arg1, arg2, arg3, arg4)) -#define STAP_PROBE5(provider, name, arg1, arg2, arg3, arg4, arg5) \ - _SDT_PROBE(provider, name, 5, (arg1, arg2, arg3, arg4, arg5)) -#define STAP_PROBE6(provider, name, arg1, arg2, arg3, arg4, arg5, arg6) \ - _SDT_PROBE(provider, name, 6, (arg1, arg2, arg3, arg4, arg5, arg6)) -#define STAP_PROBE7(provider, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ - _SDT_PROBE(provider, name, 7, (arg1, arg2, arg3, arg4, arg5, arg6, arg7)) -#define STAP_PROBE8(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) \ - _SDT_PROBE(provider, name, 8, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)) -#define STAP_PROBE9(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)\ - _SDT_PROBE(provider, name, 9, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)) -#define STAP_PROBE10(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \ - _SDT_PROBE(provider, name, 10, \ - (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10)) -#define STAP_PROBE11(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \ - _SDT_PROBE(provider, name, 11, \ - (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11)) -#define STAP_PROBE12(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \ - _SDT_PROBE(provider, name, 12, \ - (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)) - -/* This STAP_PROBEV macro can be used in variadic scenarios, where the - number of probe arguments is not known until compile time. Since - variadic macro support may vary with compiler options, you must - pre-#define SDT_USE_VARIADIC to enable this type of probe. - - The trick to count __VA_ARGS__ was inspired by this post by - Laurent Deniau <laurent.deniau@cern.ch>: - http://groups.google.com/group/comp.std.c/msg/346fc464319b1ee5 - - Note that our _SDT_NARG is called with an extra 0 arg that's not - counted, so we don't have to worry about the behavior of macros - called without any arguments. */ - -#ifdef SDT_USE_VARIADIC -#define _SDT_NARG(...) __SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0) -#define __SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N -#define _SDT_PROBE_N(provider, name, N, ...) \ - _SDT_PROBE(provider, name, N, (__VA_ARGS__)) -#define STAP_PROBEV(provider, name, ...) \ - _SDT_PROBE_N(provider, name, _SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__) -#endif - -/* These macros are for use in asm statements. You must compile - with -std=gnu99 or -std=c99 to use the STAP_PROBE_ASM macro. - - The STAP_PROBE_ASM macro generates a quoted string to be used in the - template portion of the asm statement, concatenated with strings that - contain the actual assembly code around the probe site. - - For example: - - asm ("before\n" - STAP_PROBE_ASM(provider, fooprobe, %eax 4(%esi)) - "after"); - - emits the assembly code for "before\nafter", with a probe in between. - The probe arguments are the %eax register, and the value of the memory - word located 4 bytes past the address in the %esi register. Note that - because this is a simple asm, not a GNU C extended asm statement, these - % characters do not need to be doubled to generate literal %reg names. - - In a GNU C extended asm statement, the probe arguments can be specified - using the macro STAP_PROBE_ASM_TEMPLATE(n) for n arguments. The paired - macro STAP_PROBE_ASM_OPERANDS gives the C values of these probe arguments, - and appears in the input operand list of the asm statement. For example: - - asm ("someinsn %0,%1\n" // %0 is output operand, %1 is input operand - STAP_PROBE_ASM(provider, fooprobe, STAP_PROBE_ASM_TEMPLATE(3)) - "otherinsn %[namedarg]" - : "r" (outvar) - : "g" (some_value), [namedarg] "i" (1234), - STAP_PROBE_ASM_OPERANDS(3, some_value, some_ptr->field, 1234)); - - This is just like writing: - - STAP_PROBE3(provider, fooprobe, some_value, some_ptr->field, 1234)); - - but the probe site is right between "someinsn" and "otherinsn". - - The probe arguments in STAP_PROBE_ASM can be given as assembly - operands instead, even inside a GNU C extended asm statement. - Note that these can use operand templates like %0 or %[name], - and likewise they must write %%reg for a literal operand of %reg. */ - -#if __STDC_VERSION__ >= 199901L -# define STAP_PROBE_ASM(provider, name, ...) \ - _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING, (__VA_ARGS__)) \ - _SDT_ASM_BASE -# define STAP_PROBE_ASM_OPERANDS(n, ...) _SDT_ASM_OPERANDS_##n(__VA_ARGS__) -#else -# define STAP_PROBE_ASM(provider, name, args) \ - _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING, (args)) \ - _SDT_ASM_BASE -#endif -#define STAP_PROBE_ASM_TEMPLATE(n) _SDT_ASM_TEMPLATE_##n - - -/* DTrace compatible macro names. */ -#define DTRACE_PROBE(provider,probe) \ - STAP_PROBE(provider,probe) -#define DTRACE_PROBE1(provider,probe,parm1) \ - STAP_PROBE1(provider,probe,parm1) -#define DTRACE_PROBE2(provider,probe,parm1,parm2) \ - STAP_PROBE2(provider,probe,parm1,parm2) -#define DTRACE_PROBE3(provider,probe,parm1,parm2,parm3) \ - STAP_PROBE3(provider,probe,parm1,parm2,parm3) -#define DTRACE_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ - STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) -#define DTRACE_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ - STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) -#define DTRACE_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ - STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) -#define DTRACE_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ - STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) -#define DTRACE_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ - STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) -#define DTRACE_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ - STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) -#define DTRACE_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ - STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) -#define DTRACE_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) \ - STAP_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) -#define DTRACE_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12) \ - STAP_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12) - - -#endif /* sys/sdt.h */ diff --git a/v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch b/v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch deleted file mode 100644 index 82431bea85a3..000000000000 --- a/v8-1-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Testing-infrastructure.patch +++ /dev/null @@ -1,1974 +0,0 @@ -diff --git a/elf/Makefile b/elf/Makefile -index bf45d8ee24..bdcf4cb885 100644 ---- a/elf/Makefile -+++ b/elf/Makefile -@@ -477,6 +477,21 @@ tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \ - $(objpfx)tst-unused-dep-cmp.out - endif - -+# DSO sorting tests: -+# The dso-ordering-test.py script generates testcase source files in $(objpfx), -+# creating a $(objpfx)<testcase-name>-dir for each testcase, and creates a -+# Makefile fragment to be included. -+define include_dsosort_tests -+$(objpfx)$(1).generated-makefile: $(1) -+ $(PYTHON) $(..)scripts/dso-ordering-test.py \ -+ --description-file $$< --objpfx $(objpfx) --output-makefile $$@ -+include $(objpfx)$(1).generated-makefile -+endef -+ -+# Generate from each testcase description file -+$(eval $(call include_dsosort_tests,dso-sort-tests-1.def)) -+$(eval $(call include_dsosort_tests,dso-sort-tests-2.def)) -+ - check-abi: $(objpfx)check-abi-ld.out - tests-special += $(objpfx)check-abi-ld.out - update-abi: update-abi-ld -diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def -new file mode 100644 -index 0000000000..873ddf55d9 ---- /dev/null -+++ b/elf/dso-sort-tests-1.def -@@ -0,0 +1,66 @@ -+# DSO sorting test descriptions. -+# This file is to be processed by ../scripts/dso-ordering-test.py, see usage -+# in elf/Makefile for how it is executed. -+ -+# We test both dynamic loader sorting algorithms -+tunable_option: glibc.rtld.dynamic_sort=1 -+tunable_option: glibc.rtld.dynamic_sort=2 -+ -+# Sequence of single dependencies with no cycles. -+tst-dso-ordering1: a->b->c -+output: c>b>a>{}<a<b<c -+ -+# Sequence including 2 dependent DSOs not at the end of the graph. -+tst-dso-ordering2: a->b->[cd]->e -+output: e>d>c>b>a>{}<a<b<c<d<e -+ -+# Complex order with 3 "layers" of full dependencies -+tst-dso-ordering3: a->[bc]->[def]->[gh]->i -+output: i>h>g>f>e>d>c>b>a>{}<a<b<c<d<e<f<g<h<i -+ -+# Sequence including 2 dependent DSOs at the end of the graph. -+# Additionally the same dependencies appear in two paths. -+tst-dso-ordering4: a->b->[de];a->c->d->e -+output: e>d>c>b>a>{}<a<b<c<d<e -+ -+# Test that b->c cross link is respected correctly -+tst-dso-ordering5: a!->[bc]->d;b->c -+output: d>c>b>a>{}<a<b<c<d -+ -+# First DSO fully dependent on 4 DSOs, with another DSO at the end of chain. -+tst-dso-ordering6: a->[bcde]->f -+output: f>e>d>c>b>a>{}<a<b<c<d<e<f -+ -+# Sequence including 2 dependent and 3 dependent DSOs, and one of the -+# dependent DSOs is dependent on an earlier DSO. -+tst-dso-ordering7: a->[bc];b->[cde];e->f -+output: f>e>d>c>b>a>{}<a<b<c<d<e<f -+ -+# Sequence where the DSO c is unerlinked and calls a function in DSO a which -+# is technically a cycle. The main executable depends on the first two DSOs. -+# Note: This test has unspecified behavior. -+tst-dso-ordering8: a->b->c=>a;{}->[ba] -+output: c>b>a>{}<a<b<c -+ -+# Generate the permutation of DT_NEEDED order between the main binary and -+# all 5 DSOs; all link orders should produce exact same init/fini ordering -+tst-dso-ordering9: a->b->c->d->e;{}!->[abcde] -+output: e>d>c>b>a>{}<a<b<c<d<e -+ -+# Test if init/fini ordering behavior is proper, despite main program with -+# an soname that may cause confusion -+tst-dso-ordering10: {}->a->b->c;soname({})=c -+output: b>a>{}<a<b -+ -+# Complex example from Bugzilla #15311, under-linked and with circular -+# relocation(dynamic) dependencies. While this is technically unspecified, the -+# presumed reasonable practical behavior is for the destructor order to respect -+# the static DT_NEEDED links (here this means the a->b->c->d order). -+# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based -+# dynamic_sort=2 algorithm does, although it is still arguable whether going -+# beyond spec to do this is the right thing to do. -+# The below expected outputs are what the two algorithms currently produce -+# respectively, for regression testing purposes. -+tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c -+xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];} -+output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];} -diff --git a/elf/dso-sort-tests-2.def b/elf/dso-sort-tests-2.def -new file mode 100644 -index 0000000000..b79e79ecb7 ---- /dev/null -+++ b/elf/dso-sort-tests-2.def -@@ -0,0 +1,614 @@ -+# Large DSO sorting testcase adapted from Red Hat Bugzilla 1162810 -+# -+# Note that below we specify different expected outputs between dynamic_sort=1 -+# and dynamic_sort=2 algorithms, due to circular dependencies in the testcase -+# causing different sorting behavior. These expected outputs are what the two -+# algorithms currently produce, and are used for regression comparison tests. -+# They are not "definitively" correct outputs, for circular dependencies -+# inherently have unspecified behavior. -+ -+xtest(tst-redhat-1162810): -+{}->A101 -+{}->* -+A101->(B101 B163 B122 B181) -+A102->(B102 B140 B199 B158) -+A103->(B103 B117 B176 B135) -+A104->(B104 B194 B153 B112) -+A105->(B105 B171 B130 B189) -+A106->(B106 B148 B107 B166) -+A107->(B107 B125 B184 B143) -+A108->(B108 B102 B161 B120) -+A109->(B109 B179 B138 B197) -+A110->(B110 B156 B115 B174) -+A111->(B111 B133 B192 B151) -+A112->(B112 B110 B169 B128) -+A113->(B113 B187 B146 B105) -+A114->(B114 B164 B123 B182) -+A115->(B115 B141 B200 B159) -+A116->(B116 B118 B177 B136) -+A117->(B117 B195 B154 B113) -+A118->(B118 B172 B131 B190) -+A119->(B119 B149 B108 B167) -+A120->(B120 B126 B185 B144) -+A121->(B121 B103 B162) -+A122->(B122 B180 B139 B198) -+A123->(B123 B157 B116 B175) -+A124->(B124 B134 B193 B152) -+A125->(B125 B111 B170 B129) -+A126->(B126 B188 B147 B106) -+A127->(B127 B165 B124 B183) -+A128->(B128 B142 B101 B160) -+A129->(B129 B119 B178 B137) -+A130->(B130 B196 B155 B114) -+A131->(B131 B173 B132 B191) -+A132->(B132 B150 B109 B168) -+A133->(B133 B127 B186 B145) -+A134->(B134 B104 B163 B122) -+A135->(B135 B181 B140 B199) -+A136->(B136 B158 B117 B176) -+A137->(B137 B135 B194 B153) -+A138->(B138 B112 B171 B130) -+A139->(B139 B189 B148 B107) -+A140->(B140 B166 B125 B184) -+A141->(B141 B143 B102 B161) -+A142->(B142 B120 B179 B138) -+A143->(B143 B197 B156 B115) -+A144->(B144 B174 B133 B192) -+A145->(B145 B151 B110 B169) -+A146->(B146 B128 B187) -+A147->(B147 B105 B164 B123) -+A148->(B148 B182 B141 B200) -+A149->(B149 B159 B118 B177) -+A150->(B150 B136 B195 B154) -+A151->(B151 B113 B172 B131) -+A152->(B152 B190 B149 B108) -+A153->(B153 B167 B126 B185) -+A154->(B154 B144 B103 B162) -+A155->(B155 B121 B180 B139) -+A156->(B156 B198 B157 B116) -+A157->(B157 B175 B134 B193) -+A158->(B158 B152 B111 B170) -+A159->(B159 B129 B188 B147) -+A160->(B160 B106 B165 B124) -+A161->(B161 B183 B142 B101) -+A162->(B162 B160 B119 B178) -+A163->(B163 B137 B196 B155) -+A164->(B164 B114 B173 B132) -+A165->(B165 B191 B150 B109) -+A166->(B166 B168 B127 B186) -+A167->(B167 B145 B104 B163) -+A168->(B168 B122 B181 B140) -+A169->(B169 B199 B158 B117) -+A170->(B170 B176 B135 B194) -+A171->(B171 B153 B112) -+A172->(B172 B130 B189 B148) -+A173->(B173 B107 B166 B125) -+A174->(B174 B184 B143 B102) -+A175->(B175 B161 B120 B179) -+A176->(B176 B138 B197 B156) -+A177->(B177 B115 B174 B133) -+A178->(B178 B192 B151 B110) -+A179->(B179 B169 B128 B187) -+A180->(B180 B146 B105 B164) -+A181->(B181 B123 B182 B141) -+A182->(B182 B200 B159 B118) -+A183->(B183 B177 B136 B195) -+A184->(B184 B154 B113 B172) -+A185->(B185 B131 B190 B149) -+A186->(B186 B108 B167 B126) -+A187->(B187 B185 B144 B103) -+A188->(B188 B162 B121 B180) -+A189->(B189 B139 B198 B157) -+A190->(B190 B116 B175 B134) -+A191->(B191 B193 B152 B111) -+A192->(B192 B170 B129 B188) -+A193->(B193 B147 B106 B165) -+A194->(B194 B124 B183 B142) -+A195->(B195 B101 B160 B119) -+A196->(B196 B178 B137) -+A197->(B197 B155 B114 B173) -+A198->(B198 B132 B191 B150) -+A199->(B199 B109 B168 B127) -+A200->(B200 B186 B145 B104) -+B101->(C101 C164 C123 C182) -+B102->(C102 C141 C200 C159) -+B103->(C103 C118 C177 C136) -+B104->(C104 C195 C154 C113) -+B105->(C105 C172 C131 C190) -+B106->(C106 C149 C108 C167) -+B107->(C107 C126 C185 C144) -+B108->(C108 C103 C162 C121) -+B109->(C109 C180 C139 C198) -+B110->(C110 C157 C116 C175) -+B111->(C111 C134 C193 C152) -+B112->(C112 C111 C170 C129) -+B113->(C113 C188 C147 C106) -+B114->(C114 C165 C124 C183) -+B115->(C115 C142 C101 C160) -+B116->(C116 C119 C178 C137) -+B117->(C117 C196 C155 C114) -+B118->(C118 C173 C132 C191) -+B119->(C119 C150 C109 C168) -+B120->(C120 C127 C186 C145) -+B121->(C121 C104 C163 C122) -+B122->(C122 C181 C140 C199) -+B123->(C123 C158 C117 C176) -+B124->(C124 C135 C194 C153) -+B125->(C125 C112 C171 C130) -+B126->(C126 C189 C148 C107) -+B127->(C127 C166 C125 C184) -+B128->(C128 C143 C102 C161) -+B129->(C129 C120 C179 C138) -+B130->(C130 C197 C156 C115) -+B131->(C131 C174 C133 C192) -+B132->(C132 C151 C110 C169) -+B133->(C133 C128 C187 C146) -+B134->(C134 C105 C164 C123) -+B135->(C135 C182 C141 C200) -+B136->(C136 C159 C118 C177) -+B137->(C137 C136 C195 C154) -+B138->(C138 C113 C172 C131) -+B139->(C139 C190 C149 C108) -+B140->(C140 C167 C126 C185) -+B141->(C141 C144 C103 C162) -+B142->(C142 C121 C180 C139) -+B143->(C143 C198 C157 C116) -+B144->(C144 C175 C134 C193) -+B145->(C145 C152 C111 C170) -+B146->(C146 C129 C188 C147) -+B147->(C147 C106 C165 C124) -+B148->(C148 C183 C142 C101) -+B149->(C149 C160 C119 C178) -+B150->(C150 C137 C196 C155) -+B151->(C151 C114 C173 C132) -+B152->(C152 C191 C150 C109) -+B153->(C153 C168 C127 C186) -+B154->(C154 C145 C104 C163) -+B155->(C155 C122 C181 C140) -+B156->(C156 C199 C158 C117) -+B157->(C157 C176 C135 C194) -+B158->(C158 C153 C112 C171) -+B159->(C159 C130 C189 C148) -+B160->(C160 C107 C166 C125) -+B161->(C161 C184 C143 C102) -+B162->(C162 C161 C120 C179) -+B163->(C163 C138 C197 C156) -+B164->(C164 C115 C174 C133) -+B165->(C165 C192 C151 C110) -+B166->(C166 C169 C128 C187) -+B167->(C167 C146 C105 C164) -+B168->(C168 C123 C182 C141) -+B169->(C169 C200 C159 C118) -+B170->(C170 C177 C136 C195) -+B171->(C171 C154 C113 C172) -+B172->(C172 C131 C190 C149) -+B173->(C173 C108 C167 C126) -+B174->(C174 C185 C144 C103) -+B175->(C175 C162 C121 C180) -+B176->(C176 C139 C198 C157) -+B177->(C177 C116 C175 C134) -+B178->(C178 C193 C152 C111) -+B179->(C179 C170 C129 C188) -+B180->(C180 C147 C106 C165) -+B181->(C181 C124 C183 C142) -+B182->(C182 C101 C160 C119) -+B183->(C183 C178 C137 C196) -+B184->(C184 C155 C114 C173) -+B185->(C185 C132 C191 C150) -+B186->(C186 C109 C168 C127) -+B187->(C187 C186 C145 C104) -+B188->(C188 C163 C122 C181) -+B189->(C189 C140 C199 C158) -+B190->(C190 C117 C176 C135) -+B191->(C191 C194 C153 C112) -+B192->(C192 C171 C130 C189) -+B193->(C193 C148 C107 C166) -+B194->(C194 C125 C184 C143) -+B195->(C195 C102 C161 C120) -+B196->(C196 C179 C138 C197) -+B197->(C197 C156 C115 C174) -+B198->(C198 C133 C192 C151) -+B199->(C199 C110 C169 C128) -+B200->(C200 C187 C146 C105) -+C101->(A165 A124) -+C102->(A183 A142) -+C103->(A101 A160) -+C104->(A119 A178) -+C105->(A137 A196) -+C106->(A155 A114) -+C107->(A173 A132) -+C108->(A191 A150) -+C109->(A109 A168) -+C110->(A127 A186) -+C111->(A145 A104) -+C112->(A163 A122) -+C113->(A181 A140) -+C114->(A199 A158) -+C115->(A117 A176) -+C116->(A135 A194) -+C117->(A153 A112) -+C118->(A171 A130) -+C119->(A189 A148) -+C120->(A107 A166) -+C121->(A125 A184) -+C122->(A143 A102) -+C123->(A161 A120) -+C124->(A179 A138) -+C125->(A197 A156) -+C126->(A115 A174) -+C127->(A133 A192) -+C128->(A151 A110) -+C129->(A169 A128) -+C130->(A187 A146) -+C131->(A105 A164) -+C132->(A123 A182) -+C133->(A141 A200) -+C134->(A159 A118) -+C135->(A177 A136) -+C136->(A195 A154) -+C137->(A113 A172) -+C138->(A131 A190) -+C139->(A149 A108) -+C140->(A167 A126) -+C141->(A185 A144) -+C142->(A103 A162) -+C143->(A121 A180) -+C144->(A139 A198) -+C145->(A157 A116) -+C146->(A175 A134) -+C147->(A193 A152) -+C148->(A111 A170) -+C149->(A129 A188) -+C150->(A147 A106) -+C151->(A165 A124) -+C152->(A183 A142) -+C153->(A101 A160) -+C154->(A119 A178) -+C155->(A137 A196) -+C156->(A155 A114) -+C157->(A173 A132) -+C158->(A191 A150) -+C159->(A109 A168) -+C160->(A127 A186) -+C161->(A145 A104) -+C162->(A163 A122) -+C163->(A181 A140) -+C164->(A199 A158) -+C165->(A117 A176) -+C166->(A135 A194) -+C167->(A153 A112) -+C168->(A171 A130) -+C169->(A189 A148) -+C170->(A107 A166) -+C171->(A125 A184) -+C172->(A143 A102) -+C173->(A161 A120) -+C174->(A179 A138) -+C175->(A197 A156) -+C176->(A115 A174) -+C177->(A133 A192) -+C178->(A151 A110) -+C179->(A169 A128) -+C180->(A187 A146) -+C181->(A105 A164) -+C182->(A123 A182) -+C183->(A141 A200) -+C184->(A159 A118) -+C185->(A177 A136) -+C186->(A195 A154) -+C187->(A113 A172) -+C188->(A131 A190) -+C189->(A149 A108) -+C190->(A167 A126) -+C191->(A185 A144) -+C192->(A103 A162) -+C193->(A121 A180) -+C194->(A139 A198) -+C195->(A157 A116) -+C196->(A175 A134) -+C197->(A193 A152) -+C198->(A111 A170) -+C199->(A129 A188) -+C200->(A147 A106) -+M11X11->(M13X14 M12X13 M12X12 M12X11) -+M11X12->(M13X25 M12X24 M12X23 M12X22) -+M11X13->(M13X21 M12X20 M12X19 M12X18) -+M11X14->(M13X17 M12X16 M12X15 M12X14) -+M11X15->(M13X13 M12X12 M12X11 M12X25) -+M11X16->(M13X24 M12X23 M12X22 M12X21) -+M11X17->(M13X20 M12X19 M12X18 M12X17) -+M11X18->(M13X16 M12X15 M12X14 M12X13) -+M11X19->(M13X12 M12X11 M12X25 M12X24) -+M11X20->(M13X23 M12X22 M12X21 M12X20) -+M11X21->(M13X19 M12X18 M12X17 M12X16) -+M11X22->(M13X15 M12X14 M12X13 M12X12) -+M11X23->(M13X11 M12X25 M12X24 M12X23) -+M11X24->(M13X22 M12X21 M12X20 M12X19) -+M11X25->(M13X18 M12X17 M12X16 M12X15) -+M12X11->(M14X14 M13X13 M13X12 M13X11) -+M12X12->(M14X25 M13X24 M13X23 M13X22) -+M12X13->(M14X21 M13X20 M13X19 M13X18) -+M12X14->(M14X17 M13X16 M13X15 M13X14) -+M12X15->(M14X13 M13X12 M13X11 M13X25) -+M12X16->(M14X24 M13X23 M13X22 M13X21) -+M12X17->(M14X20 M13X19 M13X18 M13X17) -+M12X18->(M14X16 M13X15 M13X14 M13X13) -+M12X19->(M14X12 M13X11 M13X25 M13X24) -+M12X20->(M14X23 M13X22 M13X21 M13X20) -+M12X21->(M14X19 M13X18 M13X17 M13X16) -+M12X22->(M14X15 M13X14 M13X13 M13X12) -+M12X23->(M14X11 M13X25 M13X24 M13X23) -+M12X24->(M14X22 M13X21 M13X20 M13X19) -+M12X25->(M14X18 M13X17 M13X16 M13X15) -+M13X11->(M15X14 M14X13 M14X12 M14X11) -+M13X12->(M15X25 M14X24 M14X23 M14X22) -+M13X13->(M15X21 M14X20 M14X19 M14X18) -+M13X14->(M15X17 M14X16 M14X15 M14X14) -+M13X15->(M15X13 M14X12 M14X11 M14X25) -+M13X16->(M15X24 M14X23 M14X22 M14X21) -+M13X17->(M15X20 M14X19 M14X18 M14X17) -+M13X18->(M15X16 M14X15 M14X14 M14X13) -+M13X19->(M15X12 M14X11 M14X25 M14X24) -+M13X20->(M15X23 M14X22 M14X21 M14X20) -+M13X21->(M15X19 M14X18 M14X17 M14X16) -+M13X22->(M15X15 M14X14 M14X13 M14X12) -+M13X23->(M15X11 M14X25 M14X24 M14X23) -+M13X24->(M15X22 M14X21 M14X20 M14X19) -+M13X25->(M15X18 M14X17 M14X16 M14X15) -+M14X11->(M16X14 M15X13 M15X12 M15X11) -+M14X12->(M16X25 M15X24 M15X23 M15X22) -+M14X13->(M16X21 M15X20 M15X19 M15X18) -+M14X14->(M16X17 M15X16 M15X15 M15X14) -+M14X15->(M16X13 M15X12 M15X11 M15X25) -+M14X16->(M16X24 M15X23 M15X22 M15X21) -+M14X17->(M16X20 M15X19 M15X18 M15X17) -+M14X18->(M16X16 M15X15 M15X14 M15X13) -+M14X19->(M16X12 M15X11 M15X25 M15X24) -+M14X20->(M16X23 M15X22 M15X21 M15X20) -+M14X21->(M16X19 M15X18 M15X17 M15X16) -+M14X22->(M16X15 M15X14 M15X13 M15X12) -+M14X23->(M16X11 M15X25 M15X24 M15X23) -+M14X24->(M16X22 M15X21 M15X20 M15X19) -+M14X25->(M16X18 M15X17 M15X16 M15X15) -+M15X11->(M17X14 M16X13 M16X12 M16X11) -+M15X12->(M17X25 M16X24 M16X23 M16X22) -+M15X13->(M17X21 M16X20 M16X19 M16X18) -+M15X14->(M17X17 M16X16 M16X15 M16X14) -+M15X15->(M17X13 M16X12 M16X11 M16X25) -+M15X16->(M17X24 M16X23 M16X22 M16X21) -+M15X17->(M17X20 M16X19 M16X18 M16X17) -+M15X18->(M17X16 M16X15 M16X14 M16X13) -+M15X19->(M17X12 M16X11 M16X25 M16X24) -+M15X20->(M17X23 M16X22 M16X21 M16X20) -+M15X21->(M17X19 M16X18 M16X17 M16X16) -+M15X22->(M17X15 M16X14 M16X13 M16X12) -+M15X23->(M17X11 M16X25 M16X24 M16X23) -+M15X24->(M17X22 M16X21 M16X20 M16X19) -+M15X25->(M17X18 M16X17 M16X16 M16X15) -+M16X11->(M18X14 M17X13 M17X12 M17X11) -+M16X12->(M18X25 M17X24 M17X23 M17X22) -+M16X13->(M18X21 M17X20 M17X19 M17X18) -+M16X14->(M18X17 M17X16 M17X15 M17X14) -+M16X15->(M18X13 M17X12 M17X11 M17X25) -+M16X16->(M18X24 M17X23 M17X22 M17X21) -+M16X17->(M18X20 M17X19 M17X18 M17X17) -+M16X18->(M18X16 M17X15 M17X14 M17X13) -+M16X19->(M18X12 M17X11 M17X25 M17X24) -+M16X20->(M18X23 M17X22 M17X21 M17X20) -+M16X21->(M18X19 M17X18 M17X17 M17X16) -+M16X22->(M18X15 M17X14 M17X13 M17X12) -+M16X23->(M18X11 M17X25 M17X24 M17X23) -+M16X24->(M18X22 M17X21 M17X20 M17X19) -+M16X25->(M18X18 M17X17 M17X16 M17X15) -+M17X11->(M19X14 M18X13 M18X12 M18X11) -+M17X12->(M19X25 M18X24 M18X23 M18X22) -+M17X13->(M19X21 M18X20 M18X19 M18X18) -+M17X14->(M19X17 M18X16 M18X15 M18X14) -+M17X15->(M19X13 M18X12 M18X11 M18X25) -+M17X16->(M19X24 M18X23 M18X22 M18X21) -+M17X17->(M19X20 M18X19 M18X18 M18X17) -+M17X18->(M19X16 M18X15 M18X14 M18X13) -+M17X19->(M19X12 M18X11 M18X25 M18X24) -+M17X20->(M19X23 M18X22 M18X21 M18X20) -+M17X21->(M19X19 M18X18 M18X17 M18X16) -+M17X22->(M19X15 M18X14 M18X13 M18X12) -+M17X23->(M19X11 M18X25 M18X24 M18X23) -+M17X24->(M19X22 M18X21 M18X20 M18X19) -+M17X25->(M19X18 M18X17 M18X16 M18X15) -+M18X11->(M20X14 M19X13 M19X12 M19X11) -+M18X12->(M20X25 M19X24 M19X23 M19X22) -+M18X13->(M20X21 M19X20 M19X19 M19X18) -+M18X14->(M20X17 M19X16 M19X15 M19X14) -+M18X15->(M20X13 M19X12 M19X11 M19X25) -+M18X16->(M20X24 M19X23 M19X22 M19X21) -+M18X17->(M20X20 M19X19 M19X18 M19X17) -+M18X18->(M20X16 M19X15 M19X14 M19X13) -+M18X19->(M20X12 M19X11 M19X25 M19X24) -+M18X20->(M20X23 M19X22 M19X21 M19X20) -+M18X21->(M20X19 M19X18 M19X17 M19X16) -+M18X22->(M20X15 M19X14 M19X13 M19X12) -+M18X23->(M20X11 M19X25 M19X24 M19X23) -+M18X24->(M20X22 M19X21 M19X20 M19X19) -+M18X25->(M20X18 M19X17 M19X16 M19X15) -+M19X11->(M21X14 M20X13 M20X12 M20X11) -+M19X12->(M21X25 M20X24 M20X23 M20X22) -+M19X13->(M21X21 M20X20 M20X19 M20X18) -+M19X14->(M21X17 M20X16 M20X15 M20X14) -+M19X15->(M21X13 M20X12 M20X11 M20X25) -+M19X16->(M21X24 M20X23 M20X22 M20X21) -+M19X17->(M21X20 M20X19 M20X18 M20X17) -+M19X18->(M21X16 M20X15 M20X14 M20X13) -+M19X19->(M21X12 M20X11 M20X25 M20X24) -+M19X20->(M21X23 M20X22 M20X21 M20X20) -+M19X21->(M21X19 M20X18 M20X17 M20X16) -+M19X22->(M21X15 M20X14 M20X13 M20X12) -+M19X23->(M21X11 M20X25 M20X24 M20X23) -+M19X24->(M21X22 M20X21 M20X20 M20X19) -+M19X25->(M21X18 M20X17 M20X16 M20X15) -+M20X11->(M22X14 M21X13 M21X12 M21X11) -+M20X12->(M22X25 M21X24 M21X23 M21X22) -+M20X13->(M22X21 M21X20 M21X19 M21X18) -+M20X14->(M22X17 M21X16 M21X15 M21X14) -+M20X15->(M22X13 M21X12 M21X11 M21X25) -+M20X16->(M22X24 M21X23 M21X22 M21X21) -+M20X17->(M22X20 M21X19 M21X18 M21X17) -+M20X18->(M22X16 M21X15 M21X14 M21X13) -+M20X19->(M22X12 M21X11 M21X25 M21X24) -+M20X20->(M22X23 M21X22 M21X21 M21X20) -+M20X21->(M22X19 M21X18 M21X17 M21X16) -+M20X22->(M22X15 M21X14 M21X13 M21X12) -+M20X23->(M22X11 M21X25 M21X24 M21X23) -+M20X24->(M22X22 M21X21 M21X20 M21X19) -+M20X25->(M22X18 M21X17 M21X16 M21X15) -+M21X11->(M23X15 M22X14 M22X13 M22X12) -+M21X12->(M11X11 M23X25 M22X24 M22X23 M22X22) -+M21X13->(M23X21 M22X20 M22X19 M22X18) -+M21X14->(M23X17 M22X16 M22X15 M22X14) -+M21X15->(M23X13 M22X12 M22X11 M22X25) -+M21X16->(M23X24 M22X23 M22X22 M22X21) -+M21X17->(M23X20 M22X19 M22X18 M22X17) -+M21X18->(M23X16 M22X15 M22X14 M22X13) -+M21X19->(M23X12 M22X11 M22X25 M22X24) -+M21X20->(M23X23 M22X22 M22X21 M22X20) -+M21X21->(M23X19 M22X18 M22X17 M22X16) -+M21X22->(M23X15 M22X14 M22X13 M22X12) -+M21X23->(M23X11 M22X25 M22X24 M22X23) -+M21X24->(M23X22 M22X21 M22X20 M22X19) -+M21X25->(M23X18 M22X17 M22X16 M22X15) -+M22X11->(M24X16 M23X15 M23X14 M23X13) -+M22X12->(M12X12 M24X11 M23X25 M23X24 M23X23) -+M22X13->(M24X22 M23X21 M23X20 M23X19) -+M22X14->(M24X18 M23X17 M23X16 M23X15) -+M22X15->(M24X14 M23X13 M23X12 M23X11) -+M22X16->(M24X25 M23X24 M23X23 M23X22) -+M22X17->(M24X21 M23X20 M23X19 M23X18) -+M22X18->(M24X17 M23X16 M23X15 M23X14) -+M22X19->(M24X13 M23X12 M23X11 M23X25) -+M22X20->(M24X24 M23X23 M23X22 M23X21) -+M22X21->(M24X20 M23X19 M23X18 M23X17) -+M22X22->(M24X16 M23X15 M23X14 M23X13) -+M22X23->(M24X12 M23X11 M23X25 M23X24) -+M22X24->(M24X23 M23X22 M23X21 M23X20) -+M22X25->(M24X19 M23X18 M23X17 M23X16) -+M23X11->(M25X17 M24X16 M24X15 M24X14) -+M23X12->(M13X13 M25X12 M24X11 M24X25 M24X24) -+M23X13->(M25X23 M24X22 M24X21 M24X20) -+M23X14->(M25X19 M24X18 M24X17 M24X16) -+M23X15->(M25X15 M24X14 M24X13 M24X12) -+M23X16->(M25X11 M24X25 M24X24 M24X23) -+M23X17->(M25X22 M24X21 M24X20 M24X19) -+M23X18->(M25X18 M24X17 M24X16 M24X15) -+M23X19->(M25X14 M24X13 M24X12 M24X11) -+M23X20->(M25X25 M24X24 M24X23 M24X22) -+M23X21->(M25X21 M24X20 M24X19 M24X18) -+M23X22->(M25X17 M24X16 M24X15 M24X14) -+M23X23->(M25X13 M24X12 M24X11 M24X25) -+M23X24->(M25X24 M24X23 M24X22 M24X21) -+M23X25->(M25X20 M24X19 M24X18 M24X17) -+M24X11->(M26X18 M25X17 M25X16 M25X15) -+M24X12->(M14X14 M26X13 M25X12 M25X11 M25X25) -+M24X13->(M26X24 M25X23 M25X22 M25X21) -+M24X14->(M26X20 M25X19 M25X18 M25X17) -+M24X15->(M26X16 M25X15 M25X14 M25X13) -+M24X16->(M26X12 M25X11 M25X25 M25X24) -+M24X17->(M26X23 M25X22 M25X21 M25X20) -+M24X18->(M26X19 M25X18 M25X17 M25X16) -+M24X19->(M26X15 M25X14 M25X13 M25X12) -+M24X20->(M26X11 M25X25 M25X24 M25X23) -+M24X21->(M26X22 M25X21 M25X20 M25X19) -+M24X22->(M26X18 M25X17 M25X16 M25X15) -+M24X23->(M26X14 M25X13 M25X12 M25X11) -+M24X24->(M26X25 M25X24 M25X23 M25X22) -+M24X25->(M26X21 M25X20 M25X19 M25X18) -+M25X11->(M27X19 M26X18 M26X17 M26X16) -+M25X12->(M15X15 M27X14 M26X13 M26X12 M26X11) -+M25X13->(M27X25 M26X24 M26X23 M26X22) -+M25X14->(M27X21 M26X20 M26X19 M26X18) -+M25X15->(M27X17 M26X16 M26X15 M26X14) -+M25X16->(M27X13 M26X12 M26X11 M26X25) -+M25X17->(M27X24 M26X23 M26X22 M26X21) -+M25X18->(M27X20 M26X19 M26X18 M26X17) -+M25X19->(M27X16 M26X15 M26X14 M26X13) -+M25X20->(M27X12 M26X11 M26X25 M26X24) -+M25X21->(M27X23 M26X22 M26X21 M26X20) -+M25X22->(M27X19 M26X18 M26X17 M26X16) -+M25X23->(M27X15 M26X14 M26X13 M26X12) -+M25X24->(M27X11 M26X25 M26X24 M26X23) -+M25X25->(M27X22 M26X21 M26X20 M26X19) -+M26X11->(M28X20 M27X19 M27X18 M27X17) -+M26X12->(M16X16 M28X15 M27X14 M27X13 M27X12) -+M26X13->(M28X11 M27X25 M27X24 M27X23) -+M26X14->(M28X22 M27X21 M27X20 M27X19) -+M26X15->(M28X18 M27X17 M27X16 M27X15) -+M26X16->(M28X14 M27X13 M27X12 M27X11) -+M26X17->(M28X25 M27X24 M27X23 M27X22) -+M26X18->(M28X21 M27X20 M27X19 M27X18) -+M26X19->(M28X17 M27X16 M27X15 M27X14) -+M26X20->(M28X13 M27X12 M27X11 M27X25) -+M26X21->(M28X24 M27X23 M27X22 M27X21) -+M26X22->(M28X20 M27X19 M27X18 M27X17) -+M26X23->(M28X16 M27X15 M27X14 M27X13) -+M26X24->(M28X12 M27X11 M27X25 M27X24) -+M26X25->(M28X23 M27X22 M27X21 M27X20) -+M27X11->(M29X21 M28X20 M28X19 M28X18) -+M27X12->(M17X17 M29X16 M28X15 M28X14 M28X13) -+M27X13->(M29X12 M28X11 M28X25 M28X24) -+M27X14->(M29X23 M28X22 M28X21 M28X20) -+M27X15->(M29X19 M28X18 M28X17 M28X16) -+M27X16->(M29X15 M28X14 M28X13 M28X12) -+M27X17->(M29X11 M28X25 M28X24 M28X23) -+M27X18->(M29X22 M28X21 M28X20 M28X19) -+M27X19->(M29X18 M28X17 M28X16 M28X15) -+M27X20->(M29X14 M28X13 M28X12 M28X11) -+M27X21->(M29X25 M28X24 M28X23 M28X22) -+M27X22->(M29X21 M28X20 M28X19 M28X18) -+M27X23->(M29X17 M28X16 M28X15 M28X14) -+M27X24->(M29X13 M28X12 M28X11 M28X25) -+M27X25->(M29X24 M28X23 M28X22 M28X21) -+M28X11->(M30X22 M29X21 M29X20 M29X19) -+M28X12->(M18X18 M30X17 M29X16 M29X15 M29X14) -+M28X13->(M30X13 M29X12 M29X11 M29X25) -+M28X14->(M30X24 M29X23 M29X22 M29X21) -+M28X15->(M30X20 M29X19 M29X18 M29X17) -+M28X16->(M30X16 M29X15 M29X14 M29X13) -+M28X17->(M30X12 M29X11 M29X25 M29X24) -+M28X18->(M30X23 M29X22 M29X21 M29X20) -+M28X19->(M30X19 M29X18 M29X17 M29X16) -+M28X20->(M30X15 M29X14 M29X13 M29X12) -+M28X21->(M30X11 M29X25 M29X24 M29X23) -+M28X22->(M30X22 M29X21 M29X20 M29X19) -+M28X23->(M30X18 M29X17 M29X16 M29X15) -+M28X24->(M30X14 M29X13 M29X12 M29X11) -+M28X25->(M30X25 M29X24 M29X23 M29X22) -+M29X11->(M30X22 M30X21 M30X20) -+M29X12->(M30X17 M30X16 M30X15) -+M29X13->(M30X13 M30X12 M30X11) -+M29X14->(M30X24 M30X23 M30X22) -+M29X15->(M30X20 M30X19 M30X18) -+M29X16->(M30X16 M30X15 M30X14) -+M29X17->(M30X12 M30X11 M30X25) -+M29X18->(M30X23 M30X22 M30X21) -+M29X19->(M30X19 M30X18 M30X17) -+M29X20->(M30X15 M30X14 M30X13) -+M29X21->(M30X11 M30X25 M30X24) -+M29X22->(M30X22 M30X21 M30X20) -+M29X23->(M30X18 M30X17 M30X16) -+M29X24->(M30X14 M30X13 M30X12) -+M29X25->(M30X25 M30X24 M30X23) -+M30X11 -+M30X12 -+M30X13 -+M30X14 -+M30X15 -+M30X16 -+M30X17 -+M30X18 -+M30X19 -+M30X20 -+M30X21 -+M30X22 -+M30X23 -+M30X24 -+M30X25 -+xfail_output(glibc.rtld.dynamic_sort=1): M30X19>M30X15>M30X16>M30X11>M30X12>M30X17>M30X13>M30X14>M29X20>M30X23>M30X24>M30X20>M30X18>M29X15>M29X12>M30X22>M30X21>M29X22>M30X25>M29X19>M29X23>M29X16>M29X24>M29X13>M29X17>M29X18>M28X19>M29X21>M29X25>M29X14>M28X20>M28X15>M28X16>M28X21>M27X18>M29X11>M28X17>M28X11>M28X22>M27X14>M28X18>M27X15>M28X13>M27X11>M28X23>M27X25>M28X14>M28X25>M27X23>M27X22>M28X24>M27X21>M27X13>M27X19>M27X17>M26X11>M26X23>M26X21>M26X22>M26X20>M26X16>M25X21>M17X22>M15X15>M20X14>M20X16>M18X18>M28X12>M27X24>M25X17>M27X20>M26X18>M26X17>M27X16>M26X19>M25X18>M26X24>M25X20>M24X17>M23X18>M25X13>M26X13>M17X23>M16X16>M26X12>M25X12>M26X15>M24X19>M25X23>M25X24>M25X25>M24X20>M25X19>M24X21>M23X17>M22X21>M24X14>M23X22>M24X24>M22X20>M24X13>M25X11>M24X12>M25X15>M23X15>M25X16>M24X22>M23X13>M24X18>M23X14>M22X22>M21X20>M24X25>M23X16>M22X25>M21X19>M22X14>M23X11>M22X15>M21X18>M22X19>M21X17>M20X17>M19X17>M21X24>M21X12>M20X22>M19X16>M18X25>M19X21>M19X20>M18X24>M20X12>M19X11>M23X20>M22X24>M22X16>M21X21>M25X14>M23X19>M23X24>M20X24>M19X12>M18X15>M17X14>M16X18>M14X25>M16X22>M16X20>M17X17>M22X12>M21X11>M20X15>M18X22>M19X24>M19X18>M18X21>M17X16>M17X18>M16X21>M15X20>M19X22>M18X20>M18X11>M17X19>M16X17>M15X21>M16X14>M16X13>M15X22>M14X20>M17X25>M16X19>M14X21>M13X24>M12X12>M16X24>M15X23>M14X16>M16X15>M15X25>M15X11>M15X12>M14X15>M13X14>M14X22>M13X20>M12X13>M11X11>M22X23>M21X15>M21X16>M20X21>M20X20>M18X17>M19X25>M18X23>M21X13>M15X17>M15X18>M18X19>M17X24>M16X12>M17X13>M20X25>M19X23>M15X19>M14X13>M13X18>M15X13>M17X12>M16X11>M18X13>M18X12>M14X11>M14X24>M13X19>M15X14>M17X20>M20X11>M20X13>M21X14>M15X24>M14X12>M13X22>M14X23>M13X23>M14X19>M17X15>M16X25>M17X11>M18X14>M19X19>M21X25>M13X12>M13X11>M14X18>M13X13>M12X11>M15X16>M14X14>M27X12>M17X21>M20X23>M22X13>M21X22>M24X16>M24X15>M26X25>M23X25>M26X14>M23X12>M22X18>M24X11>M16X23>M19X14>M19X13>M21X23>M22X17>M23X23>M23X21>M25X22>M18X16>M19X15>M20X18>M20X19>M22X11>M24X23>C156>C118>C143>C137>C147>C106>C168>C113>C163>C155>C105>C146>C187>A150>C139>C180>C164>C193>C157>A191>C158>B188>A159>C184>C121>C154>B171>A105>C131>C104>B104>C161>C111>B145>C160>B155>A163>C112>C142>B148>C133>B198>A198>A115>C114>B157>A156>C175>B144>A120>C173>B184>A174>C126>B107>A139>C194>B194>A194>C116>B116>C166>B160>B110>A110>C128>B128>A128>C179>B162>A154>C186>B187>A179>C124>B181>A101>C153>B158>A136>C135>C176>A192>B133>A133>C177>B177>A177>C185>C103>B141>A141>C183>A162>C192>C129>B179>C144>B124>B183>C127>B127>A127>B108>A112>B153>A153>C167>B167>A186>A122>C162>A144>B149>C174>B131>A185>C141>B106>A126>A167>C140>B122>A170>C198>B143>C117>C123>B123>A147>A106>C200>B169>C191>B175>A123>B118>A182>C132>B151>A145>A104>A109>C159>C150>B119>A119>A178>B164>B114>A164>C181>A102>C122>B134>A157>A116>C195>B191>B111>C172>B172>A118>B129>A129>C149>A107>C170>B197>A197>A173>B168>A132>C107>B165>A160>A131>C188>A168>B109>C178>A189>A148>C119>C190>C120>B166>B176>C108>B135>B139>A103>B178>A169>B132>C125>C138>B163>A111>B170>C110>A165>C151>C169>C199>A138>C182>A135>B101>B142>C101>C148>B193>B152>A158>A199>C136>B137>A161>B120>A108>A149>A125>B113>A184>C171>A134>A175>A124>B150>B161>B102>A146>A187>C130>B192>B200>A200>A142>A183>C102>B105>B156>A176>C165>B147>A137>A196>B190>A190>B125>C134>C189>B126>B186>A166>B136>B195>A195>B154>B138>B112>B173>A117>B159>B182>A181>A140>C145>B117>A152>A193>C197>B130>A172>A113>A151>B115>A143>B140>B185>B103>A121>A180>A130>A171>B199>C196>B146>B180>C115>B174>B121>A188>B196>B189>C152>C109>A155>A114>M14X17>M13X15>M13X16>M13X17>M12X17>M12X21>M12X25>M12X14>M13X25>M12X15>M13X21>M12X16>M12X18>M12X19>M12X20>M12X22>M12X23>M12X24>M11X25>M11X24>M11X23>M11X22>M11X21>M11X20>M11X19>M11X18>M11X17>M11X16>M11X15>M11X14>M11X13>M11X12>{}<M11X12<M11X13<M11X14<M11X15<M11X16<M11X17<M11X18<M11X19<M11X20<M11X21<M11X22<M11X23<M11X24<M11X25<M12X24<M12X23<M12X22<M12X20<M12X19<M12X18<M12X16<M13X21<M12X15<M13X25<M12X14<M12X25<M12X21<M12X17<M13X17<M13X16<M13X15<M14X17<A114<A155<C109<C152<B189<B196<A188<B121<B174<C115<B180<B146<C196<B199<A171<A130<A180<A121<B103<B185<B140<A143<B115<A151<A113<A172<B130<C197<A193<A152<B117<C145<A140<A181<B182<B159<A117<B173<B112<B138<B154<A195<B195<B136<A166<B186<B126<C189<C134<B125<A190<B190<A196<A137<B147<C165<A176<B156<B105<C102<A183<A142<A200<B200<B192<C130<A187<A146<B102<B161<B150<A124<A175<A134<C171<A184<B113<A125<A149<A108<B120<A161<B137<C136<A199<A158<B152<B193<C148<C101<B142<B101<A135<C182<A138<C199<C169<C151<A165<C110<B170<A111<B163<C138<C125<B132<A169<B178<A103<B139<B135<C108<B176<B166<C120<C190<C119<A148<A189<C178<B109<A168<C188<A131<A160<B165<C107<A132<B168<A173<A197<B197<C170<A107<C149<A129<B129<A118<B172<C172<B111<B191<C195<A116<A157<B134<C122<A102<C181<A164<B114<B164<A178<A119<B119<C150<C159<A109<A104<A145<B151<C132<A182<B118<A123<B175<C191<B169<C200<A106<A147<B123<C123<C117<B143<C198<A170<B122<C140<A167<A126<B106<C141<A185<B131<C174<B149<A144<C162<A122<A186<B167<C167<A153<B153<A112<B108<A127<B127<C127<B183<B124<C144<B179<C129<C192<A162<C183<A141<B141<C103<C185<A177<B177<C177<A133<B133<A192<C176<C135<A136<B158<C153<A101<B181<C124<A179<B187<C186<A154<B162<C179<A128<B128<C128<A110<B110<B160<C166<B116<C116<A194<B194<C194<A139<B107<C126<A174<B184<C173<A120<B144<C175<A156<B157<C114<A115<A198<B198<C133<B148<C142<C112<A163<B155<C160<B145<C111<C161<B104<C104<C131<A105<B171<C154<C121<C184<A159<B188<C158<A191<C157<C193<C164<C180<C139<A150<C187<C146<C105<C155<C163<C113<C168<C106<C147<C137<C143<C118<C156<M24X23<M22X11<M20X19<M20X18<M19X15<M18X16<M25X22<M23X21<M23X23<M22X17<M21X23<M19X13<M19X14<M16X23<M24X11<M22X18<M23X12<M26X14<M23X25<M26X25<M24X15<M24X16<M21X22<M22X13<M20X23<M17X21<M27X12<M14X14<M15X16<M12X11<M13X13<M14X18<M13X11<M13X12<M21X25<M19X19<M18X14<M17X11<M16X25<M17X15<M14X19<M13X23<M14X23<M13X22<M14X12<M15X24<M21X14<M20X13<M20X11<M17X20<M15X14<M13X19<M14X24<M14X11<M18X12<M18X13<M16X11<M17X12<M15X13<M13X18<M14X13<M15X19<M19X23<M20X25<M17X13<M16X12<M17X24<M18X19<M15X18<M15X17<M21X13<M18X23<M19X25<M18X17<M20X20<M20X21<M21X16<M21X15<M22X23<M11X11<M12X13<M13X20<M14X22<M13X14<M14X15<M15X12<M15X11<M15X25<M16X15<M14X16<M15X23<M16X24<M12X12<M13X24<M14X21<M16X19<M17X25<M14X20<M15X22<M16X13<M16X14<M15X21<M16X17<M17X19<M18X11<M18X20<M19X22<M15X20<M16X21<M17X18<M17X16<M18X21<M19X18<M19X24<M18X22<M20X15<M21X11<M22X12<M17X17<M16X20<M16X22<M14X25<M16X18<M17X14<M18X15<M19X12<M20X24<M23X24<M23X19<M25X14<M21X21<M22X16<M22X24<M23X20<M19X11<M20X12<M18X24<M19X20<M19X21<M18X25<M19X16<M20X22<M21X12<M21X24<M19X17<M20X17<M21X17<M22X19<M21X18<M22X15<M23X11<M22X14<M21X19<M22X25<M23X16<M24X25<M21X20<M22X22<M23X14<M24X18<M23X13<M24X22<M25X16<M23X15<M25X15<M24X12<M25X11<M24X13<M22X20<M24X24<M23X22<M24X14<M22X21<M23X17<M24X21<M25X19<M24X20<M25X25<M25X24<M25X23<M24X19<M26X15<M25X12<M26X12<M16X16<M17X23<M26X13<M25X13<M23X18<M24X17<M25X20<M26X24<M25X18<M26X19<M27X16<M26X17<M26X18<M27X20<M25X17<M27X24<M28X12<M18X18<M20X16<M20X14<M15X15<M17X22<M25X21<M26X16<M26X20<M26X22<M26X21<M26X23<M26X11<M27X17<M27X19<M27X13<M27X21<M28X24<M27X22<M27X23<M28X25<M28X14<M27X25<M28X23<M27X11<M28X13<M27X15<M28X18<M27X14<M28X22<M28X11<M28X17<M29X11<M27X18<M28X21<M28X16<M28X15<M28X20<M29X14<M29X25<M29X21<M28X19<M29X18<M29X17<M29X13<M29X24<M29X16<M29X23<M29X19<M30X25<M29X22<M30X21<M30X22<M29X12<M29X15<M30X18<M30X20<M30X24<M30X23<M29X20<M30X14<M30X13<M30X17<M30X12<M30X11<M30X16<M30X15<M30X19 -+output(glibc.rtld.dynamic_sort=2): M30X19>M30X15>M30X16>M30X11>M30X12>M30X17>M30X13>M30X14>M29X20>M30X23>M30X24>M30X20>M30X18>M29X15>M29X12>M30X22>M30X21>M29X22>M30X25>M29X19>M29X23>M29X16>M29X24>M29X13>M29X17>M29X18>M28X19>M29X21>M29X25>M29X14>M28X20>M28X15>M28X16>M28X21>M27X18>M29X11>M28X17>M28X11>M28X22>M28X24>M28X23>M27X21>M28X13>M27X20>M27X19>M26X14>M27X25>M28X18>M27X11>M28X25>M27X24>M26X24>M27X15>M27X14>M27X13>M26X23>M27X17>M26X22>M25X13>M28X14>M27X16>M26X19>M26X18>M27X23>M27X22>M26X17>M25X18>M26X21>M25X17>M26X20>M26X15>M26X13>M25X19>M24X14>M25X23>M26X11>M26X25>M25X16>M25X15>M24X22>M25X21>M25X20>M24X21>M25X25>M25X24>M24X20>M23X13>M22X15>M25X14>M24X19>M23X17>M24X25>M23X24>M24X13>M23X15>M24X18>M23X14>M22X11>M24X15>M23X22>M24X11>M23X19>M22X21>M24X24>M23X21>M22X20>M23X25>M22X19>M21X24>M20X23>M22X22>M25X11>M23X16>M22X18>M23X20>M22X17>M21X21>M21X20>M20X24>M22X14>M22X13>M21X11>M21X17>M22X23>M21X16>M20X25>M19X23>M18X16>M21X22>M20X20>M20X19>M21X13>M20X18>M19X13>M21X18>M20X21>M19X24>M18X12>M20X14>M20X13>M22X25>M20X12>M20X15>M19X14>M18X22>M19X18>M20X17>M19X17>M19X16>M18X21>M17X20>M19X19>M18X13>M17X11>M18X17>M19X25>M18X15>M17X25>M18X19>M17X24>M16X19>M15X17>M17X21>M16X24>M18X23>M17X16>M16X25>M19X15>M18X25>M17X23>M16X23>M15X23>M18X14>M17X14>M16X14>M17X18>M16X13>M17X22>M16X12>M15X22>M14X16>M17X12>M16X22>M15X12>M16X11>M15X11>M16X15>M15X25>M14X15>M13X14>M15X18>M16X21>M15X16>M14X21>M15X14>M16X20>M15X13>M14X22>M15X20>M14X20>M13X20>M14X11>M15X19>M14X24>M13X19>M14X13>M13X18>M12X13>M15X24>M14X23>M13X12>M14X12>M13X11>M12X11>M11X11>M21X12>M20X11>M19X11>M18X11>M17X15>M16X18>M14X25>M14X19>M13X24>M13X23>M13X22>M12X12>M22X12>M21X15>M19X22>M18X20>M16X17>M14X14>M24X12>M23X23>M22X16>M21X14>M20X22>M18X24>M16X16>M26X12>M24X16>M23X11>M21X23>M19X20>M17X17>M27X12>M26X16>M25X22>M24X17>M23X18>M21X25>M19X12>M17X19>M15X21>M14X18>M13X13>M23X12>M21X19>M19X21>M17X13>M15X15>M25X12>M24X23>M22X24>M20X16>M18X18>M28X12>A150>C158>B112>A112>C167>B146>A146>C180>B180>A180>C143>B143>A115>C126>B126>A126>C190>B190>A190>C138>B138>A138>C174>B174>A102>C122>B122>A122>C162>B162>A162>C142>B142>A142>C102>B102>A174>C176>B176>A176>C115>B115>A143>C172>B172>A172>C187>B187>A187>C130>B130>A130>C118>B118>A118>C184>B184>A184>C171>B171>A171>C168>B182>A182>C182>B168>A168>C109>B109>A109>C159>B159>A159>C134>B134>A134>C146>B167>A167>C140>B140>A140>C163>B163>A163>C112>B158>A158>C164>B164>A164>C131>B131>A131>C188>B188>A188>C199>B199>A199>C114>B114>A114>C106>B106>A106>C200>B200>A200>C183>B183>A183>C152>B152>A152>C147>B147>A147>C150>B150>A198>C144>B144>A144>C191>B191>A191>C108>B108>A108>C139>B139>A139>C194>B194>A194>C166>B166>A166>C120>B120>A120>C123>B123>A123>C132>B132>A132>C107>B107>A107>C170>B170>A170>C198>B198>A156>C125>B125>A125>C121>B121>A121>C193>B193>A193>C197>B197>A197>C175>B175>A175>C196>B196>A196>C105>B105>A105>C181>B181>A181>C113>B113>A113>C137>B137>A137>C155>B155>A155>C156>B156>A110>C128>B128>A128>C179>B179>A179>C124>B124>A124>C151>B151>A151>C178>B178>A178>C104>B104>A104>C111>B111>A111>C148>B148>A148>C169>B169>A169>C129>B129>A129>C149>B149>A149>C189>B189>A189>C119>B119>A119>C154>B154>A154>C136>B136>A136>C135>B135>A135>C116>B116>A116>C145>B145>A145>C161>B161>A161>C173>B173>A173>C157>B157>A157>C195>B195>A195>C186>B186>A186>C160>B160>A160>C153>B153>A153>C117>B117>A117>C165>B165>A165>C101>B101>A101>C103>B103>A103>C192>B192>A192>C177>B177>A177>C185>B185>A185>C141>B141>A141>C133>B133>A133>C127>B127>A127>C110>B110>M14X17>M13X15>M13X16>M13X17>M12X17>M12X21>M12X25>M12X14>M13X25>M12X15>M13X21>M12X16>M12X18>M12X19>M12X20>M12X22>M12X23>M12X24>M11X25>M11X24>M11X23>M11X22>M11X21>M11X20>M11X19>M11X18>M11X17>M11X16>M11X15>M11X14>M11X13>M11X12>{}<M11X12<M11X13<M11X14<M11X15<M11X16<M11X17<M11X18<M11X19<M11X20<M11X21<M11X22<M11X23<M11X24<M11X25<M12X24<M12X23<M12X22<M12X20<M12X19<M12X18<M12X16<M13X21<M12X15<M13X25<M12X14<M12X25<M12X21<M12X17<M13X17<M13X16<M13X15<M14X17<B110<C110<A127<B127<C127<A133<B133<C133<A141<B141<C141<A185<B185<C185<A177<B177<C177<A192<B192<C192<A103<B103<C103<A101<B101<C101<A165<B165<C165<A117<B117<C117<A153<B153<C153<A160<B160<C160<A186<B186<C186<A195<B195<C195<A157<B157<C157<A173<B173<C173<A161<B161<C161<A145<B145<C145<A116<B116<C116<A135<B135<C135<A136<B136<C136<A154<B154<C154<A119<B119<C119<A189<B189<C189<A149<B149<C149<A129<B129<C129<A169<B169<C169<A148<B148<C148<A111<B111<C111<A104<B104<C104<A178<B178<C178<A151<B151<C151<A124<B124<C124<A179<B179<C179<A128<B128<C128<A110<B156<C156<A155<B155<C155<A137<B137<C137<A113<B113<C113<A181<B181<C181<A105<B105<C105<A196<B196<C196<A175<B175<C175<A197<B197<C197<A193<B193<C193<A121<B121<C121<A125<B125<C125<A156<B198<C198<A170<B170<C170<A107<B107<C107<A132<B132<C132<A123<B123<C123<A120<B120<C120<A166<B166<C166<A194<B194<C194<A139<B139<C139<A108<B108<C108<A191<B191<C191<A144<B144<C144<A198<B150<C150<A147<B147<C147<A152<B152<C152<A183<B183<C183<A200<B200<C200<A106<B106<C106<A114<B114<C114<A199<B199<C199<A188<B188<C188<A131<B131<C131<A164<B164<C164<A158<B158<C112<A163<B163<C163<A140<B140<C140<A167<B167<C146<A134<B134<C134<A159<B159<C159<A109<B109<C109<A168<B168<C182<A182<B182<C168<A171<B171<C171<A184<B184<C184<A118<B118<C118<A130<B130<C130<A187<B187<C187<A172<B172<C172<A143<B115<C115<A176<B176<C176<A174<B102<C102<A142<B142<C142<A162<B162<C162<A122<B122<C122<A102<B174<C174<A138<B138<C138<A190<B190<C190<A126<B126<C126<A115<B143<C143<A180<B180<C180<A146<B146<C167<A112<B112<C158<A150<M28X12<M18X18<M20X16<M22X24<M24X23<M25X12<M15X15<M17X13<M19X21<M21X19<M23X12<M13X13<M14X18<M15X21<M17X19<M19X12<M21X25<M23X18<M24X17<M25X22<M26X16<M27X12<M17X17<M19X20<M21X23<M23X11<M24X16<M26X12<M16X16<M18X24<M20X22<M21X14<M22X16<M23X23<M24X12<M14X14<M16X17<M18X20<M19X22<M21X15<M22X12<M12X12<M13X22<M13X23<M13X24<M14X19<M14X25<M16X18<M17X15<M18X11<M19X11<M20X11<M21X12<M11X11<M12X11<M13X11<M14X12<M13X12<M14X23<M15X24<M12X13<M13X18<M14X13<M13X19<M14X24<M15X19<M14X11<M13X20<M14X20<M15X20<M14X22<M15X13<M16X20<M15X14<M14X21<M15X16<M16X21<M15X18<M13X14<M14X15<M15X25<M16X15<M15X11<M16X11<M15X12<M16X22<M17X12<M14X16<M15X22<M16X12<M17X22<M16X13<M17X18<M16X14<M17X14<M18X14<M15X23<M16X23<M17X23<M18X25<M19X15<M16X25<M17X16<M18X23<M16X24<M17X21<M15X17<M16X19<M17X24<M18X19<M17X25<M18X15<M19X25<M18X17<M17X11<M18X13<M19X19<M17X20<M18X21<M19X16<M19X17<M20X17<M19X18<M18X22<M19X14<M20X15<M20X12<M22X25<M20X13<M20X14<M18X12<M19X24<M20X21<M21X18<M19X13<M20X18<M21X13<M20X19<M20X20<M21X22<M18X16<M19X23<M20X25<M21X16<M22X23<M21X17<M21X11<M22X13<M22X14<M20X24<M21X20<M21X21<M22X17<M23X20<M22X18<M23X16<M25X11<M22X22<M20X23<M21X24<M22X19<M23X25<M22X20<M23X21<M24X24<M22X21<M23X19<M24X11<M23X22<M24X15<M22X11<M23X14<M24X18<M23X15<M24X13<M23X24<M24X25<M23X17<M24X19<M25X14<M22X15<M23X13<M24X20<M25X24<M25X25<M24X21<M25X20<M25X21<M24X22<M25X15<M25X16<M26X25<M26X11<M25X23<M24X14<M25X19<M26X13<M26X15<M26X20<M25X17<M26X21<M25X18<M26X17<M27X22<M27X23<M26X18<M26X19<M27X16<M28X14<M25X13<M26X22<M27X17<M26X23<M27X13<M27X14<M27X15<M26X24<M27X24<M28X25<M27X11<M28X18<M27X25<M26X14<M27X19<M27X20<M28X13<M27X21<M28X23<M28X24<M28X22<M28X11<M28X17<M29X11<M27X18<M28X21<M28X16<M28X15<M28X20<M29X14<M29X25<M29X21<M28X19<M29X18<M29X17<M29X13<M29X24<M29X16<M29X23<M29X19<M30X25<M29X22<M30X21<M30X22<M29X12<M29X15<M30X18<M30X20<M30X24<M30X23<M29X20<M30X14<M30X13<M30X17<M30X12<M30X11<M30X16<M30X15<M30X19 -diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py -new file mode 100644 -index 0000000000..944ee74052 ---- /dev/null -+++ b/scripts/dso-ordering-test.py -@@ -0,0 +1,1144 @@ -+#!/usr/bin/python3 -+# Generate testcase files and Makefile fragments for DSO sorting test -+# Copyright (C) 2021 Free Software Foundation, Inc. -+# This file is part of the GNU C Library. -+# -+# The GNU C Library is free software; you can redistribute it and/or -+# modify it under the terms of the GNU Lesser General Public -+# License as published by the Free Software Foundation; either -+# version 2.1 of the License, or (at your option) any later version. -+# -+# The GNU C Library is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+# Lesser General Public License for more details. -+# -+# You should have received a copy of the GNU Lesser General Public -+# License along with the GNU C Library; if not, see -+# <http://www.gnu.org/licenses/>. -+ -+"""Generate testcase files and Makefile fragments for DSO sorting test -+ -+This script takes a small description string language, and generates -+testcases for displaying the ELF dynamic linker's dependency sorting -+behavior, allowing verification. -+ -+Testcase descriptions are semicolon-separated description strings, and -+this tool generates a testcase from the description, including main program, -+associated modules, and Makefile fragments for including into elf/Makefile. -+ -+This allows automation of what otherwise would be very laborous manual -+construction of complex dependency cases, however it must be noted that this -+is only a tool to speed up testcase construction, and thus the generation -+features are largely mechanical in nature; inconsistencies or errors may occur -+if the input description was itself erroneous or have unforeseen interactions. -+ -+The format of the input test description files are: -+ -+ # Each test description has a name, lines of description, -+ # and an expected output specification. Comments use '#'. -+ testname1: <test-description-line> -+ output: <expected-output-string> -+ -+ # Tests can be marked to be XFAIL by using 'xfail_output' instead -+ testname2: <test-description-line> -+ xfail_output: <expected-output-string> -+ -+ # A default set of GLIBC_TUNABLES tunables can be specified, for which -+ # all following tests will run multiple times, once for each of the -+ # GLIBC_TUNABLES=... strings set by the 'tunable_option' command. -+ tunable_option: <glibc-tunable-string1> -+ tunable_option: <glibc-tunable-string2> -+ -+ # Test descriptions can use multiple lines, which will all be merged -+ # together, so order is not important. -+ testname3: <test-description-line> -+ <test-description-line> -+ <test-description-line> -+ ... -+ output: <expected-output-string> -+ -+ # 'testname3' will be run and compared two times, for both -+ # GLIBC_TUNABLES=<glibc-tunable-string1> and -+ # GLIBC_TUNABLES=<glibc-tunable-string2>. This can be cleared and reset by the -+ # 'clear_tunables' command: -+ clear_tunables -+ -+ # Multiple expected outputs can also be specified, with an associated -+ # tunable option in (), which multiple tests will be run with each -+ # GLIBC_TUNABLES=... option tried. -+ testname4: -+ <test-description-line> -+ ... -+ output(<glibc-tunable-string1>): <expected-output-string-1> -+ output(<glibc-tunable-string2>): <expected-output-string-2> -+ # Individual tunable output cases can be XFAILed, though note that -+ # this will have the effect of XFAILing the entire 'testname4' test -+ # in the final top-level tests.sum summary. -+ xfail_output(<glibc-tunable-string3>): <expected-output-string-3> -+ -+ # When multiple outputs (with specific tunable strings) are specified, -+ # these take priority over any active 'tunable_option' settings. -+ -+ # When a test is meant to be placed under 'xtests' (not run under -+ # "make check", but only when "make xtests" is used), the testcase name can be -+ # declared using 'xtest(<test-name>)': -+ ... -+ xtest(test-too-big1): <test-description> -+ output: <expected-output-string> -+ ... -+ -+ # Do note that under current elf/Makefile organization, for such a xtest case, -+ # while the test execution is only run under 'make xtests', the associated -+ # DSOs are always built even under 'make check'. -+ -+On the description language used, an example description line string: -+ -+ a->b!->[cdef];c=>g=>h;{+c;%c;-c}->a -+ -+Each identifier represents a shared object module, currently sequences of -+letters/digits are allowed, case-sensitive. -+ -+All such shared objects have a constructor/destructor generated for them -+that emits its name followed by a '>' for constructors, and '<' followed by -+its name for destructors, e.g. if the name is 'obj1', then "obj1>" and "<obj1" -+is printed by its constructor/destructor respectively. -+ -+The -> operator specifies a link time dependency, these can be chained for -+convenience (e.g. a->b->c->d). -+ -+The => operator creates a call-reference, e.g. for a=>b, an fn_a() function -+is created inside module 'a', which calls fn_b() in module 'b'. -+These module functions emit 'name()' output in nested form, -+e.g. a=>b emits 'a(b())' -+ -+For single character object names, square brackets [] in the description -+allows specifying multiple objects; e.g. a->[bcd]->e is equivalent to -+ a->b->e;a->c->e;a->d->e -+ -+The () parenthesis construct with space separated names is also allowed for -+specifying objects. For names with integer suffixes a range can also be used, -+e.g. (foo1 bar2-5), specifies DSOs foo1, bar2, bar2, bar3, bar4, bar5. -+ -+A {} construct specifies the main test program, and its link dependencies -+are also specified using ->. Inside {}, a few ;-separated constructs are -+allowed: -+ +a Loads module a using dlopen(RTLD_LAZY|RTLD_GLOBAL) -+ ^a Loads module a using dlopen(RTLD_LAZY) -+ %a Use dlsym() to load and call fn_a() -+ @a Calls fn_a() directly. -+ -a Unloads module a using dlclose() -+ -+The generated main program outputs '{' '}' with all output from above -+constructs in between. The other output before/after {} are the ordered -+constructor/destructor output. -+ -+If no {} construct is present, a default empty main program is linked -+against all objects which have no dependency linked to it. e.g. for -+'[ab]->c;d->e', the default main program is equivalent to '{}->[abd]' -+ -+Sometimes for very complex or large testcases, besides specifying a -+few explicit dependencies from main{}, the above default dependency -+behavior is still useful to automatically have, but is turned off -+upon specifying a single explicit {}->dso_name. -+In this case, add {}->* to explicitly add this generation behavior: -+ -+ # Main program links to 'foo', and all other objects which have no -+ # dependency linked to it. -+ {}->foo,{}->* -+ -+Note that '*' works not only on main{}, but can be used as the -+dependency target of any object. Note that it only works as a target, -+not a dependency source. -+ -+The '!' operator after object names turns on permutation of its -+dependencies, e.g. while a->[bcd] only generates one set of objects, -+with 'a.so' built with a link line of "b.so c.so d.so", for a!->[bcd] -+permutations of a's dependencies creates multiple testcases with -+different link line orders: "b.so c.so d.so", "c.so b.so d.so", -+"b.so d.so c.so", etc. Note that for a <test-name> specified on -+the script command-line, multiple <test-name_1>, <test-name_2>, etc. -+tests will be generated (e.g. for a!->[bc]!->[de], eight tests with -+different link orders for a, b, and c will be generated) -+ -+It is possible to specify the ELF soname field for an object or the -+main program: -+ # DSO 'a' will be linked with the appropriate -Wl,-soname=x setting -+ a->b->c;soname(a)=x -+ # The the main program can also have a soname specified -+ soname({})=y -+ -+This can be used to test how ld.so behaves when objects and/or the -+main program have such a field set. -+ -+ -+Strings Output by Generated Testcase Programs -+ -+The text output produced by a generated testcase consists of three main -+parts: -+ 1. The constructors' output -+ 2. Output from the main program -+ 3. Destructors' output -+ -+To see by example, a simple test description "a->b->c" generates a testcase -+that when run, outputs: "c>b>a>{}<a<b<c" -+ -+Each generated DSO constructor prints its name followed by a '>' character, -+and the "c>b>a" part above is the full constructor output by all DSOs, the -+order indicating that DSO 'c', which does not depend on any other DSO, has -+its constructor run first, followed by 'b' and then 'a'. -+ -+Destructor output for each DSO is a '<' character followed by its name, -+reflecting its reverse nature of constructors. In the above example, the -+destructor output part is "<a<b<c". -+ -+The middle "{}" part is the main program. In this simple example, nothing -+was specified for the main program, so by default it is implicitly linked -+to the DSO 'a' (with no other DSOs depending on it) and only prints the -+brackets {} with no actions inside. -+ -+To see an example with actions inside the main program, lets see an example -+description: c->g=>h;{+c;%c;-c}->a->h -+ -+This produces a testcase, that when executed outputs: -+ h>a>{+c[g>c>];%c();-c[<c<g];}<a<h -+ -+The constructor and destructor parts display the a->h dependency as expected. -+Inside the main program, the "+c" action triggers a dlopen() of DSO 'c', -+causing another chain of constructors "g>c>" to be triggered. Here it is -+displayed inside [] brackets for each dlopen call. The same is done for "-c", -+a dlclose() of 'c'. -+ -+The "%c" output is due to calling to fn_c() inside DSO 'c', this comprises -+of two parts: the '%' character is printed by the caller, here it is the main -+program. The 'c' character is printed from inside fn_c(). The '%' character -+indicates that this is called by a dlsym() of "fn_c". A '@' character would -+mean a direct call (with a symbol reference). These can all be controlled -+by the main test program constructs documented earlier. -+ -+The output strings described here is the exact same form placed in -+test description files' "output: <expected output>" line. -+""" -+ -+import sys -+import re -+import os -+import subprocess -+import argparse -+from collections import OrderedDict -+import itertools -+ -+# BUILD_GCC is only used under the --build option, -+# which builds the generated testcase, including DSOs using BUILD_GCC. -+# Mainly for testing purposes, especially debugging of this script, -+# and can be changed here to another toolchain path if needed. -+build_gcc = "gcc" -+ -+def get_parser(): -+ parser = argparse.ArgumentParser("") -+ parser.add_argument("description", -+ help="Description string of DSO dependency test to be " -+ "generated (see script source for documentation of " -+ "description language), either specified here as " -+ "command line argument, or by input file using " -+ "-f/--description-file option", -+ nargs="?", default="") -+ parser.add_argument("test_name", -+ help="Identifier for testcase being generated", -+ nargs="?", default="") -+ parser.add_argument("--objpfx", -+ help="Path to place generated files, defaults to " -+ "current directory if none specified", -+ nargs="?", default="./") -+ parser.add_argument("-m", "--output-makefile", -+ help="File to write Makefile fragment to, defaults to " -+ "stdout when option not present", -+ nargs="?", default="") -+ parser.add_argument("-f", "--description-file", -+ help="Input file containing testcase descriptions", -+ nargs="?", default="") -+ parser.add_argument("--build", help="After C testcase generated, build it " -+ "using gcc (for manual testing purposes)", -+ action="store_true") -+ parser.add_argument("--debug-output", -+ help="Prints some internal data " -+ "structures; used for debugging of this script", -+ action="store_true") -+ return parser -+ -+# Main script starts here. -+cmdlineargs = get_parser().parse_args() -+test_name = cmdlineargs.test_name -+description = cmdlineargs.description -+objpfx = cmdlineargs.objpfx -+description_file = cmdlineargs.description_file -+output_makefile = cmdlineargs.output_makefile -+makefile = "" -+default_tunable_options = [] -+ -+current_input_lineno = 0 -+def error(msg): -+ global current_input_lineno -+ print("Error: %s%s" % ((("Line %d, " % current_input_lineno) -+ if current_input_lineno != 0 else ""), -+ msg)) -+ exit(1) -+ -+if(test_name or description) and description_file: -+ error("both command-line testcase and input file specified") -+if test_name and not description: -+ error("command-line testcase name without description string") -+ -+# Main class type describing a testcase. -+class TestDescr: -+ def __init__(self): -+ self.objs = [] # list of all DSO objects -+ self.deps = OrderedDict() # map of DSO object -> list of dependencies -+ -+ # map of DSO object -> list of call refs -+ self.callrefs = OrderedDict() -+ -+ # map of DSO object -> list of permutations of dependencies -+ self.dep_permutations = OrderedDict() -+ -+ # map of DSO object -> SONAME of object (if one is specified) -+ self.soname_map = OrderedDict() -+ -+ # list of main program operations -+ self.main_program = [] -+ # set if default dependencies added to main -+ self.main_program_default_deps = True -+ -+ self.test_name = "" # name of testcase -+ self.expected_outputs = OrderedDict() # expected outputs of testcase -+ self.xfail = False # set if this is a XFAIL testcase -+ self.xtest = False # set if this is put under 'xtests' -+ -+ # Add 'object -> [object, object, ...]' relations to CURR_MAP -+ def __add_deps_internal(self, src_objs, dst_objs, curr_map): -+ for src in src_objs: -+ for dst in dst_objs: -+ if not src in curr_map: -+ curr_map[src] = [] -+ if not dst in curr_map[src]: -+ curr_map[src].append(dst) -+ def add_deps(self, src_objs, dst_objs): -+ self.__add_deps_internal(src_objs, dst_objs, self.deps) -+ def add_callrefs(self, src_objs, dst_objs): -+ self.__add_deps_internal(src_objs, dst_objs, self.callrefs) -+ -+# Process commands inside the {} construct. -+# Note that throughout this script, the main program object is represented -+# by the '#' string. -+def process_main_program(test_descr, mainprog_str): -+ if mainprog_str: -+ test_descr.main_program = mainprog_str.split(';') -+ for s in test_descr.main_program: -+ m = re.match(r"^([+\-%^@])([0-9a-zA-Z]+)$", s) -+ if not m: -+ error("'%s' is not recognized main program operation" % (s)) -+ opr = m.group(1) -+ obj = m.group(2) -+ if not obj in test_descr.objs: -+ test_descr.objs.append(obj) -+ if opr == '%' or opr == '@': -+ test_descr.add_callrefs(['#'], [obj]) -+ # We have a main program specified, turn this off -+ test_descr.main_program_default_deps = False -+ -+# For(a1 a2 b1-12) object set descriptions, expand into an object list -+def expand_object_set_string(descr_str): -+ obj_list = [] -+ descr_list = descr_str.split() -+ for descr in descr_list: -+ m = re.match(r"^([a-zA-Z][0-9a-zA-Z]*)(-[0-9]+)?$", descr) -+ if not m: -+ error("'%s' is not a valid object set description" % (descr)) -+ obj = m.group(1) -+ idx_end = m.group(2) -+ if not idx_end: -+ if not obj in obj_list: -+ obj_list.append(obj) -+ else: -+ idx_end = int(idx_end[1:]) -+ m = re.match(r"^([0-9a-zA-Z][a-zA-Z]*)([0-9]+)$", obj) -+ if not m: -+ error("object description '%s' is malformed" % (obj)) -+ obj_name = m.group(1) -+ idx_start = int(m.group (2)) -+ if idx_start > idx_end: -+ error("index range %s-%s invalid" % (idx_start, idx_end)) -+ for i in range(idx_start, idx_end + 1): -+ o = obj_name + str(i) -+ if not o in obj_list: -+ obj_list.append(o) -+ return obj_list -+ -+# Lexer for tokens -+tokenspec = [ ("SONAME", r"soname\(([0-9a-zA-Z{}]+)\)=([0-9a-zA-Z]+)"), -+ ("OBJ", r"([0-9a-zA-Z]+)"), -+ ("DEP", r"->"), -+ ("CALLREF", r"=>"), -+ ("OBJSET", r"\[([0-9a-zA-Z]+)\]"), -+ ("OBJSET2", r"\(([0-9a-zA-Z \-]+)\)"), -+ ("OBJSET3", r"\*"), -+ ("PROG", r"{([0-9a-zA-Z;+^\-%@]*)}"), -+ ("PERMUTE", r"!"), -+ ("SEMICOL", r";"), -+ ("ERROR", r".") ] -+tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tokenspec) -+ -+# Main line parser of description language -+def parse_description_string(t, descr_str): -+ # State used when parsing dependencies -+ curr_objs = [] -+ in_dep = False -+ in_callref = False -+ def clear_dep_state(): -+ nonlocal in_dep, in_callref -+ in_dep = in_callref = False -+ -+ for m in re.finditer(tok_re, descr_str): -+ kind = m.lastgroup -+ value = m.group() -+ if kind == "SONAME": -+ s = re.match(r"soname\(([0-9a-zA-Z{}]+)\)=([0-9a-zA-Z]+)", value) -+ obj = s.group(1) -+ val = s.group(2) -+ if obj == "{}": -+ if '#' in t.soname_map: -+ error("soname of main program already set") -+ # Adjust to internal name -+ obj = '#' -+ else: -+ if re.match(r"[{}]", obj): -+ error("invalid object name '%s'" % (obj)) -+ if not obj in t.objs: -+ error("'%s' is not name of already defined object" % (obj)) -+ if obj in t.soname_map: -+ error("'%s' already has soname of '%s' set" -+ % (obj, t.soname_map[obj])) -+ t.soname_map[obj] = val -+ -+ elif kind == "OBJ": -+ if in_dep: -+ t.add_deps(curr_objs, [value]) -+ elif in_callref: -+ t.add_callrefs(curr_objs, [value]) -+ clear_dep_state() -+ curr_objs = [value] -+ if not value in t.objs: -+ t.objs.append(value) -+ -+ elif kind == "OBJSET": -+ objset = value[1:len(value)-1] -+ if in_dep: -+ t.add_deps(curr_objs, list (objset)) -+ elif in_callref: -+ t.add_callrefs(curr_objs, list (objset)) -+ clear_dep_state() -+ curr_objs = list(objset) -+ for o in list(objset): -+ if not o in t.objs: -+ t.objs.append(o) -+ -+ elif kind == "OBJSET2": -+ descr_str = value[1:len(value)-1] -+ descr_str.strip() -+ objs = expand_object_set_string(descr_str) -+ if not objs: -+ error("empty object set '%s'" % (value)) -+ if in_dep: -+ t.add_deps(curr_objs, objs) -+ elif in_callref: -+ t.add_callrefs(curr_objs, objs) -+ clear_dep_state() -+ curr_objs = objs -+ for o in objs: -+ if not o in t.objs: -+ t.objs.append(o) -+ -+ elif kind == "OBJSET3": -+ if in_dep: -+ t.add_deps(curr_objs, ['*']) -+ elif in_callref: -+ t.add_callrefs(curr_objs, ['*']) -+ else: -+ error("non-dependence target set '*' can only be used " -+ "as target of ->/=> operations") -+ clear_dep_state() -+ curr_objs = ['*'] -+ -+ elif kind == "PERMUTE": -+ if in_dep or in_callref: -+ error("syntax error, permute operation invalid here") -+ if not curr_objs: -+ error("syntax error, no objects to permute here") -+ -+ for obj in curr_objs: -+ if not obj in t.dep_permutations: -+ # Signal this object has permuted dependencies -+ t.dep_permutations[obj] = [] -+ -+ elif kind == "PROG": -+ if t.main_program: -+ error("cannot have more than one main program") -+ if in_dep: -+ error("objects cannot have dependency on main program") -+ if in_callref: -+ # TODO: A DSO can resolve to a symbol in the main binary, -+ # which we syntactically allow here, but haven't yet -+ # implemented. -+ t.add_callrefs(curr_objs, ["#"]) -+ process_main_program(t, value[1:len(value)-1]) -+ clear_dep_state() -+ curr_objs = ["#"] -+ -+ elif kind == "DEP": -+ if in_dep or in_callref: -+ error("syntax error, multiple contiguous ->,=> operations") -+ if '*' in curr_objs: -+ error("non-dependence target set '*' can only be used " -+ "as target of ->/=> operations") -+ in_dep = True -+ -+ elif kind == "CALLREF": -+ if in_dep or in_callref: -+ error("syntax error, multiple contiguous ->,=> operations") -+ if '*' in curr_objs: -+ error("non-dependence target set '*' can only be used " -+ "as target of ->/=> operations") -+ in_callref = True -+ -+ elif kind == "SEMICOL": -+ curr_objs = [] -+ clear_dep_state() -+ -+ else: -+ error("unknown token '%s'" % (value)) -+ return t -+ -+# Main routine to process each testcase description -+def process_testcase(t): -+ global objpfx -+ assert t.test_name -+ -+ base_test_name = t.test_name -+ test_subdir = base_test_name + "-dir" -+ testpfx = objpfx + test_subdir + "/" -+ -+ if not os.path.exists(testpfx): -+ os.mkdir(testpfx) -+ -+ def find_objs_not_depended_on(t): -+ objs_not_depended_on = [] -+ for obj in t.objs: -+ skip = False -+ for r in t.deps.items(): -+ if obj in r[1]: -+ skip = True -+ break -+ if not skip: -+ objs_not_depended_on.append(obj) -+ return objs_not_depended_on -+ -+ non_dep_tgt_objs = find_objs_not_depended_on(t) -+ for obj in t.objs: -+ if obj in t.deps: -+ deps = t.deps[obj] -+ if '*' in deps: -+ t.deps[obj].remove('*') -+ t.add_deps([obj], non_dep_tgt_objs) -+ if obj in t.callrefs: -+ deps = t.callrefs[obj] -+ if '*' in deps: -+ t.deps[obj].remove('*') -+ t.add_callrefs([obj], non_dep_tgt_objs) -+ if "#" in t.deps: -+ deps = t.deps["#"] -+ if '*' in deps: -+ t.deps["#"].remove('*') -+ t.add_deps(["#"], non_dep_tgt_objs) -+ -+ # If no main program was specified in dependency description, make a -+ # default main program with deps pointing to all DSOs which are not -+ # depended by another DSO. -+ if t.main_program_default_deps: -+ main_deps = non_dep_tgt_objs -+ if not main_deps: -+ error("no objects for default main program to point " -+ "dependency to(all objects strongly connected?)") -+ t.add_deps(["#"], main_deps) -+ -+ # Some debug output -+ if cmdlineargs.debug_output: -+ print("Testcase: %s" % (t.test_name)) -+ print("All objects: %s" % (t.objs)) -+ print("--- Static link dependencies ---") -+ for r in t.deps.items(): -+ print("%s -> %s" % (r[0], r[1])) -+ print("--- Objects whose dependencies are to be permuted ---") -+ for r in t.dep_permutations.items(): -+ print("%s" % (r[0])) -+ print("--- Call reference dependencies ---") -+ for r in t.callrefs.items(): -+ print("%s => %s" % (r[0], r[1])) -+ print("--- main program ---") -+ print(t.main_program) -+ -+ # Main testcase generation routine, does Makefile fragment generation, -+ # testcase source generation, and if --build specified builds testcase. -+ def generate_testcase(test_descr, test_suffix): -+ -+ test_name = test_descr.test_name + test_suffix -+ -+ # Print out needed Makefile fragments for use in glibc/elf/Makefile. -+ module_names = "" -+ for o in test_descr.objs: -+ module_names += " " + test_subdir + "/" + test_name + "-" + o -+ makefile.write("modules-names +=%s\n" % (module_names)) -+ -+ # Depth-first traversal, executing FN(OBJ) in post-order -+ def dfs(t, fn): -+ def dfs_rec(obj, fn, obj_visited): -+ if obj in obj_visited: -+ return -+ obj_visited[obj] = True -+ if obj in t.deps: -+ for dep in t.deps[obj]: -+ dfs_rec(dep, fn, obj_visited) -+ fn(obj) -+ -+ obj_visited = {} -+ for obj in t.objs: -+ dfs_rec(obj, fn, obj_visited) -+ -+ # Generate link dependencies for all DSOs, done in a DFS fashion. -+ # Usually this doesn't need to be this complex, just listing the direct -+ # dependencies is enough. However to support creating circular -+ # dependency situations, traversing it by DFS and tracking processing -+ # status is the natural way to do it. -+ obj_processed = {} -+ fake_created = {} -+ def gen_link_deps(obj): -+ if obj in test_descr.deps: -+ dso = test_subdir + "/" + test_name + "-" + obj + ".so" -+ dependencies = "" -+ for dep in test_descr.deps[obj]: -+ if dep in obj_processed: -+ depstr = (" $(objpfx)" + test_subdir + "/" -+ + test_name + "-" + dep + ".so") -+ else: -+ # A circular dependency is satisfied by making a -+ # fake DSO tagged with the correct SONAME -+ depstr = (" $(objpfx)" + test_subdir + "/" -+ + test_name + "-" + dep + ".FAKE.so") -+ # Create empty C file and Makefile fragments for fake -+ # object. This only needs to be done at most once for -+ # an object name. -+ if not dep in fake_created: -+ f = open(testpfx + test_name + "-" + dep -+ + ".FAKE.c", "w") -+ f.write(" \n") -+ f.close() -+ # Generate rule to create fake object -+ makefile.write \ -+ ("LDFLAGS-%s = -Wl,--no-as-needed " -+ "-Wl,-soname=%s\n" -+ % (test_name + "-" + dep + ".FAKE.so", -+ ("$(objpfx)" + test_subdir + "/" -+ + test_name + "-" + dep + ".so"))) -+ makefile.write \ -+ ("modules-names += %s\n" -+ % (test_subdir + "/" -+ + test_name + "-" + dep + ".FAKE")) -+ fake_created[dep] = True -+ dependencies += depstr -+ makefile.write("$(objpfx)%s:%s\n" % (dso, dependencies)) -+ # Mark obj as processed -+ obj_processed[obj] = True -+ -+ dfs(test_descr, gen_link_deps) -+ -+ # Print LDFLAGS-* and *-no-z-defs -+ for o in test_descr.objs: -+ dso = test_name + "-" + o + ".so" -+ ldflags = "-Wl,--no-as-needed" -+ if o in test_descr.soname_map: -+ soname = ("$(objpfx)" + test_subdir + "/" -+ + test_name + "-" -+ + test_descr.soname_map[o] + ".so") -+ ldflags += (" -Wl,-soname=" + soname) -+ makefile.write("LDFLAGS-%s = %s\n" % (dso, ldflags)) -+ if o in test_descr.callrefs: -+ makefile.write("%s-no-z-defs = yes\n" % (dso)) -+ -+ # Print dependencies for main test program. -+ depstr = "" -+ if '#' in test_descr.deps: -+ for o in test_descr.deps['#']: -+ depstr += (" $(objpfx)" + test_subdir + "/" -+ + test_name + "-" + o + ".so") -+ makefile.write("$(objpfx)%s/%s:%s\n" % (test_subdir, test_name, depstr)) -+ ldflags = "-Wl,--no-as-needed" -+ if '#' in test_descr.soname_map: -+ soname = ("$(objpfx)" + test_subdir + "/" -+ + test_name + "-" -+ + test_descr.soname_map['#'] + ".so") -+ ldflags += (" -Wl,-soname=" + soname) -+ makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags)) -+ -+ not_depended_objs = find_objs_not_depended_on(test_descr) -+ if not_depended_objs: -+ depstr = "" -+ for dep in not_depended_objs: -+ depstr += (" $(objpfx)" + test_subdir + "/" -+ + test_name + "-" + dep + ".so") -+ makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr)) -+ -+ # Add main executable to test-srcs -+ makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name)) -+ # Add dependency on main executable of test -+ makefile.write("$(objpfx)%s.out: $(objpfx)%s/%s\n" -+ % (base_test_name, test_subdir, test_name)) -+ -+ for r in test_descr.expected_outputs.items(): -+ tunable_options = [] -+ specific_tunable = r[0] -+ xfail = r[1][1] -+ if specific_tunable != "": -+ tunable_options = [specific_tunable] -+ else: -+ tunable_options = default_tunable_options -+ if not tunable_options: -+ tunable_options = [""] -+ -+ for tunable in tunable_options: -+ tunable_env = "" -+ tunable_sfx = "" -+ exp_tunable_sfx = "" -+ if tunable: -+ tunable_env = "GLIBC_TUNABLES=%s " % tunable -+ tunable_sfx = "-" + tunable.replace("=","_") -+ if specific_tunable: -+ tunable_sfx = "-" + specific_tunable.replace("=","_") -+ exp_tunable_sfx = tunable_sfx -+ tunable_descr = ("(%s)" % tunable_env.strip() -+ if tunable_env else "") -+ # Write out fragment of shell script for this single test. -+ test_descr.sh.write \ -+ ("%s${test_wrapper_env} ${run_program_env} \\\n" -+ "${common_objpfx}support/test-run-command \\\n" -+ "${common_objpfx}elf/ld.so \\\n" -+ "--library-path ${common_objpfx}elf/%s:" -+ "${common_objpfx}elf:${common_objpfx}.:" -+ "${common_objpfx}dlfcn \\\n" -+ "${common_objpfx}elf/%s/%s > \\\n" -+ " ${common_objpfx}elf/%s/%s%s.output\n" -+ % (tunable_env ,test_subdir, -+ test_subdir, test_name, test_subdir, test_name, -+ tunable_sfx)) -+ # Generate a run of each test and compare with expected out -+ test_descr.sh.write \ -+ ("if [ $? -ne 0 ]; then\n" -+ " echo '%sFAIL: %s%s execution test'\n" -+ " something_failed=true\n" -+ "else\n" -+ " diff -wu ${common_objpfx}elf/%s/%s%s.output \\\n" -+ " ${common_objpfx}elf/%s/%s%s.exp\n" -+ " if [ $? -ne 0 ]; then\n" -+ " echo '%sFAIL: %s%s expected output comparison'\n" -+ " something_failed=true\n" -+ " fi\n" -+ "fi\n" -+ % (("X" if xfail else ""), test_name, tunable_descr, -+ test_subdir, test_name, tunable_sfx, -+ test_subdir, base_test_name, exp_tunable_sfx, -+ ("X" if xfail else ""), test_name, tunable_descr)) -+ -+ # Generate C files according to dependency and calling relations from -+ # description string. -+ for obj in test_descr.objs: -+ src_name = test_name + "-" + obj + ".c" -+ f = open(testpfx + src_name, "w") -+ if obj in test_descr.callrefs: -+ called_objs = test_descr.callrefs[obj] -+ for callee in called_objs: -+ f.write("extern void fn_%s (void);\n" % (callee)) -+ if len(obj) == 1: -+ f.write("extern int putchar(int);\n") -+ f.write("static void __attribute__((constructor)) " + -+ "init(void){putchar('%s');putchar('>');}\n" % (obj)) -+ f.write("static void __attribute__((destructor)) " + -+ "fini(void){putchar('<');putchar('%s');}\n" % (obj)) -+ else: -+ f.write('extern int printf(const char *, ...);\n') -+ f.write('static void __attribute__((constructor)) ' + -+ 'init(void){printf("%s>");}\n' % (obj)) -+ f.write('static void __attribute__((destructor)) ' + -+ 'fini(void){printf("<%s");}\n' % (obj)) -+ if obj in test_descr.callrefs: -+ called_objs = test_descr.callrefs[obj] -+ if len(obj) != 1: -+ f.write("extern int putchar(int);\n") -+ f.write("void fn_%s (void) {\n" % (obj)) -+ if len(obj) == 1: -+ f.write(" putchar ('%s');\n" % (obj)); -+ f.write(" putchar ('(');\n"); -+ else: -+ f.write(' printf ("%s(");\n' % (obj)); -+ for callee in called_objs: -+ f.write(" fn_%s ();\n" % (callee)) -+ f.write(" putchar (')');\n"); -+ f.write("}\n") -+ else: -+ for callref in test_descr.callrefs.items(): -+ if obj in callref[1]: -+ if len(obj) == 1: -+ # We need to declare printf here in this case. -+ f.write('extern int printf(const char *, ...);\n') -+ f.write("void fn_%s (void) {\n" % (obj)) -+ f.write(' printf ("%s()");\n' % (obj)) -+ f.write("}\n") -+ break -+ f.close() -+ -+ # Open C file for writing main program -+ f = open(testpfx + test_name + ".c", "w") -+ -+ # if there are some operations in main(), it means we need -ldl -+ f.write("#include <stdio.h>\n") -+ f.write("#include <stdlib.h>\n") -+ f.write("#include <dlfcn.h>\n") -+ for s in test_descr.main_program: -+ if s[0] == '@': -+ f.write("extern void fn_%s (void);\n" % (s[1:])); -+ f.write("int main (void) {\n") -+ f.write(" putchar('{');\n") -+ -+ # Helper routine for generating sanity checking code. -+ def put_fail_check(fail_cond, action_desc): -+ f.write(' if (%s) { printf ("\\n%s failed: %%s\\n", ' -+ 'dlerror()); exit (1);}\n' % (fail_cond, action_desc)) -+ i = 0 -+ while i < len(test_descr.main_program): -+ s = test_descr.main_program[i] -+ obj = s[1:] -+ dso = test_name + "-" + obj -+ if s[0] == '+' or s[0] == '^': -+ if s[0] == '+': -+ dlopen_flags = "RTLD_LAZY|RTLD_GLOBAL" -+ f.write(" putchar('+');\n"); -+ else: -+ dlopen_flags = "RTLD_LAZY" -+ f.write(" putchar(':');\n"); -+ if len(obj) == 1: -+ f.write(" putchar('%s');\n" % (obj)); -+ else: -+ f.write(' printf("%s");\n' % (obj)); -+ f.write(" putchar('[');\n"); -+ f.write(' void *%s = dlopen ("%s.so", %s);\n' -+ % (obj, dso, dlopen_flags)) -+ put_fail_check("!%s" % (obj), -+ "%s.so dlopen" % (dso)) -+ f.write(" putchar(']');\n"); -+ elif s[0] == '-': -+ f.write(" putchar('-');\n"); -+ if len(obj) == 1: -+ f.write(" putchar('%s');\n" % (obj)); -+ else: -+ f.write(' printf("%s");\n' % (obj)); -+ f.write(" putchar('[');\n"); -+ put_fail_check("dlclose (%s) != 0" % (obj), -+ "%s.so dlclose" % (dso)) -+ f.write(" putchar(']');\n"); -+ elif s[0] == '%': -+ f.write(" putchar('%');\n"); -+ f.write(' void (*fn_%s)(void) = dlsym (%s, "fn_%s");\n' -+ % (obj, obj, obj)) -+ put_fail_check("!fn_%s" % (obj), -+ "dlsym(fn_%s) from %s.so" % (obj, dso)) -+ f.write(" fn_%s ();\n" % (obj)) -+ elif s[0] == '@': -+ f.write(" putchar('@');\n"); -+ f.write(" fn_%s ();\n" % (obj)) -+ f.write(" putchar(';');\n"); -+ i += 1 -+ f.write(" putchar('}');\n") -+ f.write(" return 0;\n") -+ f.write("}\n") -+ f.close() -+ -+ # --build option processing: build generated sources using 'build_gcc' -+ if cmdlineargs.build: -+ # Helper routine to run a shell command, for running GCC below -+ def run_cmd(args): -+ cmd = str.join(' ', args) -+ if cmdlineargs.debug_output: -+ print(cmd) -+ p = subprocess.Popen(args) -+ p.wait() -+ if p.returncode != 0: -+ error("error running command: %s" % (cmd)) -+ -+ # Compile individual .os files -+ for obj in test_descr.objs: -+ src_name = test_name + "-" + obj + ".c" -+ obj_name = test_name + "-" + obj + ".os" -+ run_cmd([build_gcc, "-c", "-fPIC", testpfx + src_name, -+ "-o", testpfx + obj_name]) -+ -+ obj_processed = {} -+ fake_created = {} -+ # Function to create <test_name>-<obj>.so -+ def build_dso(obj): -+ obj_name = test_name + "-" + obj + ".os" -+ dso_name = test_name + "-" + obj + ".so" -+ deps = [] -+ if obj in test_descr.deps: -+ for dep in test_descr.deps[obj]: -+ if dep in obj_processed: -+ deps.append(dep) -+ else: -+ deps.append(dep + ".FAKE") -+ if not dep in fake_created: -+ base_name = testpfx + test_name + "-" + dep -+ cmd = [build_gcc, "-Wl,--no-as-needed", -+ ("-Wl,-soname=" + base_name + ".so"), -+ "-shared", base_name + ".FAKE.c", -+ "-o", base_name + ".FAKE.so"] -+ run_cmd(cmd) -+ fake_created[dep] = True -+ dso_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", -+ deps) -+ cmd = [build_gcc, "-shared", "-o", testpfx + dso_name, -+ testpfx + obj_name, "-Wl,--no-as-needed"] -+ if obj in test_descr.soname_map: -+ soname = ("-Wl,-soname=" + testpfx + test_name + "-" -+ + test_descr.soname_map[obj] + ".so") -+ cmd += [soname] -+ cmd += list(dso_deps) -+ run_cmd(cmd) -+ obj_processed[obj] = True -+ -+ # Build all DSOs, this needs to be in topological dependency order, -+ # or link will fail -+ dfs(test_descr, build_dso) -+ -+ # Build main program -+ deps = [] -+ if '#' in test_descr.deps: -+ deps = test_descr.deps['#'] -+ main_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", -+ deps) -+ cmd = [build_gcc, "-Wl,--no-as-needed", "-o", testpfx + test_name, -+ testpfx + test_name + ".c", "-L%s" % (os.getcwd()), -+ "-Wl,-rpath-link=%s" % (os.getcwd())] -+ if '#' in test_descr.soname_map: -+ soname = ("-Wl,-soname=" + testpfx + test_name + "-" -+ + test_descr.soname_map['#'] + ".so") -+ cmd += [soname] -+ cmd += list(main_deps) -+ run_cmd(cmd) -+ -+ # Check if we need to enumerate permutations of dependencies -+ need_permutation_processing = False -+ if t.dep_permutations: -+ # Adjust dep_permutations into map of object -> dependency permutations -+ for r in t.dep_permutations.items(): -+ obj = r[0] -+ if obj in t.deps and len(t.deps[obj]) > 1: -+ deps = t.deps[obj] -+ t.dep_permutations[obj] = list(itertools.permutations (deps)) -+ need_permutation_processing = True -+ -+ def enum_permutations(t, perm_list): -+ test_subindex = 1 -+ curr_perms = [] -+ def enum_permutations_rec(t, perm_list): -+ nonlocal test_subindex, curr_perms -+ if len(perm_list) >= 1: -+ curr = perm_list[0] -+ obj = curr[0] -+ perms = curr[1] -+ if not perms: -+ # This may be an empty list if no multiple dependencies to -+ # permute were found, skip to next in this case -+ enum_permutations_rec(t, perm_list[1:]) -+ else: -+ for deps in perms: -+ t.deps[obj] = deps -+ permstr = "" if obj == "#" else obj + "_" -+ permstr += str.join('', deps) -+ curr_perms.append(permstr) -+ enum_permutations_rec(t, perm_list[1:]) -+ curr_perms = curr_perms[0:len(curr_perms)-1] -+ else: -+ # t.deps is now instantiated with one dependency order -+ # permutation(across all objects that have multiple -+ # permutations), now process a testcase -+ generate_testcase(t, ("_" + str (test_subindex) -+ + "-" + str.join('-', curr_perms))) -+ test_subindex += 1 -+ enum_permutations_rec(t, perm_list) -+ -+ # Create *.exp files with expected outputs -+ for r in t.expected_outputs.items(): -+ sfx = "" -+ if r[0] != "": -+ sfx = "-" + r[0].replace("=","_") -+ f = open(testpfx + t.test_name + sfx + ".exp", "w") -+ (output, xfail) = r[1] -+ f.write('%s' % output) -+ f.close() -+ -+ # Create header part of top-level testcase shell script, to wrap execution -+ # and output comparison together. -+ t.sh = open(testpfx + t.test_name + ".sh", "w") -+ t.sh.write("#!/bin/sh\n") -+ t.sh.write("# Test driver for %s, generated by " -+ "dso-ordering-test.py\n" % (t.test_name)) -+ t.sh.write("common_objpfx=$1\n") -+ t.sh.write("test_wrapper_env=$2\n") -+ t.sh.write("run_program_env=$3\n") -+ t.sh.write("something_failed=false\n") -+ -+ # Starting part of Makefile fragment -+ makefile.write("ifeq (yes,$(build-shared))\n") -+ -+ if need_permutation_processing: -+ enum_permutations(t, list (t.dep_permutations.items())) -+ else: -+ # We have no permutations to enumerate, just process testcase normally -+ generate_testcase(t, "") -+ -+ # If testcase is XFAIL, indicate so -+ if t.xfail: -+ makefile.write("test-xfail-%s = yes\n" % t.test_name) -+ -+ # Output end part of Makefile fragment -+ expected_output_files = "" -+ for r in t.expected_outputs.items(): -+ sfx = "" -+ if r[0] != "": -+ sfx = "-" + r[0].replace("=","_") -+ expected_output_files += " $(objpfx)%s/%s%s.exp" % (test_subdir, -+ t.test_name, sfx) -+ makefile.write \ -+ ("$(objpfx)%s.out: $(objpfx)%s/%s.sh%s " -+ "$(common-objpfx)support/test-run-command\n" -+ % (t.test_name, test_subdir, t.test_name, -+ expected_output_files)) -+ makefile.write("\t$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' " -+ "'$(run-program-env)' > $@; $(evaluate-test)\n") -+ makefile.write("ifeq ($(run-built-tests),yes)\n") -+ if t.xtest: -+ makefile.write("xtests-special += $(objpfx)%s.out\n" % (t.test_name)) -+ else: -+ makefile.write("tests-special += $(objpfx)%s.out\n" % (t.test_name)) -+ makefile.write("endif\n") -+ makefile.write("endif\n") -+ -+ # Write ending part of shell script generation -+ t.sh.write("if $something_failed; then\n" -+ " exit 1\n" -+ "else\n" -+ " echo '%sPASS: all tests for %s succeeded'\n" -+ " exit 0\n" -+ "fi\n" % (("X" if t.xfail else ""), -+ t.test_name)) -+ t.sh.close() -+ -+# Decription file parsing -+def parse_description_file(filename): -+ global default_tunable_options -+ global current_input_lineno -+ f = open(filename) -+ if not f: -+ error("cannot open description file %s" % (filename)) -+ descrfile_lines = f.readlines() -+ t = None -+ for line in descrfile_lines: -+ p = re.compile(r"#.*$") -+ line = p.sub("", line) # Filter out comments -+ line = line.strip() # Remove excess whitespace -+ current_input_lineno += 1 -+ -+ m = re.match(r"^tunable_option:\s*(.*)$", line) -+ if m: -+ if m.group(1) == "": -+ error("tunable option cannot be empty") -+ default_tunable_options.append(m.group (1)) -+ continue -+ -+ m = re.match(r"^clear_tunables$", line) -+ if m: -+ default_tunable_options = [] -+ continue -+ -+ m = re.match(r"^([^:]+):\s*(.*)$", line) -+ if m: -+ lhs = m.group(1) -+ o = re.match(r"^output(.*)$", lhs) -+ xfail = False -+ if not o: -+ o = re.match(r"^xfail_output(.*)$", lhs) -+ if o: -+ xfail = True; -+ if o: -+ if not t: -+ error("output specification without testcase description") -+ tsstr = "" -+ if o.group(1): -+ ts = re.match(r"^\(([a-zA-Z0-9_.=]*)\)$", o.group (1)) -+ if not ts: -+ error("tunable option malformed '%s'" % o.group(1)) -+ tsstr = ts.group(1) -+ t.expected_outputs[tsstr] = (m.group(2), xfail) -+ # Any tunable option XFAILed means entire testcase -+ # is XFAIL/XPASS -+ t.xfail |= xfail -+ else: -+ if t: -+ # Starting a new test description, end and process -+ # current one. -+ process_testcase(t) -+ t = TestDescr() -+ x = re.match(r"^xtest\((.*)\)$", lhs) -+ if x: -+ t.xtest = True -+ t.test_name = x.group(1) -+ else: -+ t.test_name = lhs -+ descr_string = m.group(2) -+ parse_description_string(t, descr_string) -+ continue -+ else: -+ if line: -+ if not t: -+ error("no active testcase description") -+ parse_description_string(t, line) -+ # Process last completed test description -+ if t: -+ process_testcase(t) -+ -+# Setup Makefile output to file or stdout as selected -+if output_makefile: -+ output_makefile_dir = os.path.dirname(output_makefile) -+ if output_makefile_dir: -+ os.makedirs(output_makefile_dir, exist_ok = True) -+ makefile = open(output_makefile, "w") -+else: -+ makefile = open(sys.stdout.fileno (), "w") -+ -+# Finally, the main top-level calling of above parsing routines. -+if description_file: -+ parse_description_file(description_file) -+else: -+ t = TestDescr() -+ t.test_name = test_name -+ parse_description_string(t, description) -+ process_testcase(t) -+ -+# Close Makefile fragment output -+makefile.close() -diff --git a/support/Depend b/support/Depend -new file mode 100644 -index 0000000000..7e7d5dc67c ---- /dev/null -+++ b/support/Depend -@@ -0,0 +1 @@ -+elf -diff --git a/support/Makefile b/support/Makefile -index 7f03950914..984ec02dfe 100644 ---- a/support/Makefile -+++ b/support/Makefile -@@ -257,10 +257,16 @@ others-noinstall += shell-container echo-container true-container - others += $(LINKS_DSO_PROGRAM) - others-noinstall += $(LINKS_DSO_PROGRAM) - -+others += test-run-command -+others-static += test-run-command -+others-noinstall += test-run-command -+LDLIBS-test-run-command = $(libsupport) -+ - $(objpfx)test-container : $(libsupport) - $(objpfx)shell-container : $(libsupport) - $(objpfx)echo-container : $(libsupport) - $(objpfx)true-container : $(libsupport) -+$(objpfx)test-run-command : $(libsupport) $(common-objpfx)elf/static-stubs.o - - tests = \ - README-testing \ -diff --git a/support/support_test_main.c b/support/support_test_main.c -index 07e3cdd173..66a754b84f 100644 ---- a/support/support_test_main.c -+++ b/support/support_test_main.c -@@ -228,6 +228,18 @@ run_test_function (int argc, char **argv, const struct test_config *config) - while (wait_for_debugger) - usleep (1000); - -+ if (config->run_command_mode) -+ { -+ /* In run-command-mode, the child process executes the command line -+ arguments as a new program. */ -+ char **argv_ = xmalloc (sizeof (char *) * argc); -+ memcpy (argv_, &argv[1], sizeof (char *) * (argc - 1)); -+ argv_[argc - 1] = NULL; -+ execv (argv_[0], argv_); -+ printf ("error: should not return here\n"); -+ exit (1); -+ } -+ - if (config->test_function != NULL) - return config->test_function (); - else if (config->test_function_argv != NULL) -diff --git a/support/test-driver.c b/support/test-driver.c -index b0bea46dee..1552f62c9b 100644 ---- a/support/test-driver.c -+++ b/support/test-driver.c -@@ -116,7 +116,9 @@ main (int argc, char **argv) - #if defined (TEST_FUNCTION) && defined (TEST_FUNCTON_ARGV) - # error TEST_FUNCTION and TEST_FUNCTION_ARGV cannot be defined at the same time - #endif --#if defined (TEST_FUNCTION) -+#ifdef RUN_COMMAND_MODE -+ test_config.run_command_mode = 1; -+#elif defined (TEST_FUNCTION) - test_config.test_function = TEST_FUNCTION; - #elif defined (TEST_FUNCTION_ARGV) - test_config.test_function_argv = TEST_FUNCTION_ARGV; -diff --git a/support/test-driver.h b/support/test-driver.h -index 8d4f38275d..b44c0ff033 100644 ---- a/support/test-driver.h -+++ b/support/test-driver.h -@@ -36,6 +36,7 @@ struct test_config - int expected_signal; /* If non-zero, expect termination by signal. */ - char no_mallopt; /* Boolean flag to disable mallopt. */ - char no_setvbuf; /* Boolean flag to disable setvbuf. */ -+ char run_command_mode; /* Boolean flag to indicate run-command-mode. */ - const char *optstring; /* Short command line options. */ - }; - -diff --git a/support/test-run-command.c b/support/test-run-command.c -new file mode 100644 -index 0000000000..61560d7bfb ---- /dev/null -+++ b/support/test-run-command.c -@@ -0,0 +1,22 @@ -+/* Main program for test-run-command support utility. -+ Copyright (C) 2021 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <https://www.gnu.org/licenses/>. */ -+ -+/* This is basically a configuration of test-driver.c into a general -+ command-line program runner. */ -+#define RUN_COMMAND_MODE -+#include <test-driver.c> diff --git a/v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch b/v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch deleted file mode 100644 index 8dae228961e2..000000000000 --- a/v8-2-2-BZ-17645-fix-slow-DSO-sorting-behavior-in-dynamic-loader----Algorithm-changes.patch +++ /dev/null @@ -1,569 +0,0 @@ -diff --git a/NEWS b/NEWS -index 220d327071..b39b1e5e33 100644 ---- a/NEWS -+++ b/NEWS -@@ -51,6 +51,15 @@ Major new features: - - * The ISO C2X macro _PRINTF_NAN_LEN_MAX has been added to <stdio.h>. - -+* A new DSO sorting algorithm has been added in the dynamic linker that uses -+ topological sorting by depth-first search (DFS), solving performance issues -+ of the existing sorting algorithm when encountering particular circular -+ object dependency cases. -+ -+* A new tunable, glibc.rtld.dynamic_sort, can be used to select between the two -+ DSO sorting algorithms. The default setting of '1' uses the current existing -+ algorithm, while a value of '2' selects the new DFS-based algorithm. -+ - Deprecated and removed features, and other changes affecting compatibility: - - * The r_version update in the debugger interface makes the glibc binary -diff --git a/elf/dl-close.c b/elf/dl-close.c -index cfe0f1c0c9..4f5cfcc1c3 100644 ---- a/elf/dl-close.c -+++ b/elf/dl-close.c -@@ -167,8 +167,6 @@ _dl_close_worker (struct link_map *map, bool force) - - bool any_tls = false; - const unsigned int nloaded = ns->_ns_nloaded; -- char used[nloaded]; -- char done[nloaded]; - struct link_map *maps[nloaded]; - - /* Run over the list and assign indexes to the link maps and enter -@@ -176,24 +174,21 @@ _dl_close_worker (struct link_map *map, bool force) - int idx = 0; - for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next) - { -+ l->l_map_used = 0; -+ l->l_map_done = 0; - l->l_idx = idx; - maps[idx] = l; - ++idx; -- - } - assert (idx == nloaded); - -- /* Prepare the bitmaps. */ -- memset (used, '\0', sizeof (used)); -- memset (done, '\0', sizeof (done)); -- - /* Keep track of the lowest index link map we have covered already. */ - int done_index = -1; - while (++done_index < nloaded) - { - struct link_map *l = maps[done_index]; - -- if (done[done_index]) -+ if (l->l_map_done) - /* Already handled. */ - continue; - -@@ -204,12 +199,12 @@ _dl_close_worker (struct link_map *map, bool force) - /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why - acquire is sufficient and correct. */ - && atomic_load_acquire (&l->l_tls_dtor_count) == 0 -- && !used[done_index]) -+ && !l->l_map_used) - continue; - - /* We need this object and we handle it now. */ -- done[done_index] = 1; -- used[done_index] = 1; -+ l->l_map_used = 1; -+ l->l_map_done = 1; - /* Signal the object is still needed. */ - l->l_idx = IDX_STILL_USED; - -@@ -225,9 +220,9 @@ _dl_close_worker (struct link_map *map, bool force) - { - assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded); - -- if (!used[(*lp)->l_idx]) -+ if (!(*lp)->l_map_used) - { -- used[(*lp)->l_idx] = 1; -+ (*lp)->l_map_used = 1; - /* If we marked a new object as used, and we've - already processed it, then we need to go back - and process again from that point forward to -@@ -250,9 +245,9 @@ _dl_close_worker (struct link_map *map, bool force) - { - assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded); - -- if (!used[jmap->l_idx]) -+ if (!jmap->l_map_used) - { -- used[jmap->l_idx] = 1; -+ jmap->l_map_used = 1; - if (jmap->l_idx - 1 < done_index) - done_index = jmap->l_idx - 1; - } -@@ -262,8 +257,7 @@ _dl_close_worker (struct link_map *map, bool force) - - /* Sort the entries. We can skip looking for the binary itself which is - at the front of the search list for the main namespace. */ -- _dl_sort_maps (maps + (nsid == LM_ID_BASE), nloaded - (nsid == LM_ID_BASE), -- used + (nsid == LM_ID_BASE), true); -+ _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true); - - /* Call all termination functions at once. */ - #ifdef SHARED -@@ -280,7 +274,7 @@ _dl_close_worker (struct link_map *map, bool force) - /* All elements must be in the same namespace. */ - assert (imap->l_ns == nsid); - -- if (!used[i]) -+ if (!imap->l_map_used) - { - assert (imap->l_type == lt_loaded && !imap->l_nodelete_active); - -@@ -333,7 +327,7 @@ _dl_close_worker (struct link_map *map, bool force) - if (i < first_loaded) - first_loaded = i; - } -- /* Else used[i]. */ -+ /* Else imap->l_map_used. */ - else if (imap->l_type == lt_loaded) - { - struct r_scope_elem *new_list = NULL; -@@ -560,7 +554,7 @@ _dl_close_worker (struct link_map *map, bool force) - for (unsigned int i = first_loaded; i < nloaded; ++i) - { - struct link_map *imap = maps[i]; -- if (!used[i]) -+ if (!imap->l_map_used) - { - assert (imap->l_type == lt_loaded); - -diff --git a/elf/dl-deps.c b/elf/dl-deps.c -index 087a49b212..237d9636c5 100644 ---- a/elf/dl-deps.c -+++ b/elf/dl-deps.c -@@ -613,10 +613,9 @@ Filters not supported with LD_TRACE_PRELINKING")); - - /* If libc.so.6 is the main map, it participates in the sort, so - that the relocation order is correct regarding libc.so.6. */ -- if (l_initfini[0] == GL (dl_ns)[l_initfini[0]->l_ns].libc_map) -- _dl_sort_maps (l_initfini, nlist, NULL, false); -- else -- _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); -+ _dl_sort_maps (l_initfini, nlist, -+ (l_initfini[0] != GL (dl_ns)[l_initfini[0]->l_ns].libc_map), -+ false); - - /* Terminate the list of dependencies. */ - l_initfini[nlist] = NULL; -diff --git a/elf/dl-fini.c b/elf/dl-fini.c -index 6dbdfe4b3e..c683884c35 100644 ---- a/elf/dl-fini.c -+++ b/elf/dl-fini.c -@@ -92,8 +92,7 @@ _dl_fini (void) - /* Now we have to do the sorting. We can skip looking for the - binary itself which is at the front of the search list for - the main namespace. */ -- _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE), -- NULL, true); -+ _dl_sort_maps (maps, nmaps, (ns == LM_ID_BASE), true); - - /* We do not rely on the linked list of loaded object anymore - from this point on. We have our own list here (maps). The -diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c -index d21770267a..a274ed66cc 100644 ---- a/elf/dl-sort-maps.c -+++ b/elf/dl-sort-maps.c -@@ -16,16 +16,24 @@ - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -+#include <assert.h> - #include <ldsodefs.h> -+#include <elf/dl-tunables.h> - -+/* Note: this is the older, "original" sorting algorithm, being used as -+ default up to 2.35. - --/* Sort array MAPS according to dependencies of the contained objects. -- Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is -- called for finishing an object. */ --void --_dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, -- bool for_fini) -+ Sort array MAPS according to dependencies of the contained objects. -+ If FOR_FINI is true, this is called for finishing an object. */ -+static void -+_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps, -+ unsigned int skip, bool for_fini) - { -+ /* Allows caller to do the common optimization of skipping the first map, -+ usually the main binary. */ -+ maps += skip; -+ nmaps -= skip; -+ - /* A list of one element need not be sorted. */ - if (nmaps <= 1) - return; -@@ -66,14 +74,6 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, - (k - i) * sizeof (maps[0])); - maps[k] = thisp; - -- if (used != NULL) -- { -- char here_used = used[i]; -- memmove (&used[i], &used[i + 1], -- (k - i) * sizeof (used[0])); -- used[k] = here_used; -- } -- - if (seen[i + 1] > nmaps - i) - { - ++i; -@@ -120,3 +120,183 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, - next:; - } - } -+ -+#if !HAVE_TUNABLES -+/* In this case, just default to the original algorithm. */ -+strong_alias (_dl_sort_maps_original, _dl_sort_maps); -+#else -+ -+/* We use a recursive function due to its better clarity and ease of -+ implementation, as well as faster execution speed. We already use -+ alloca() for list allocation during the breadth-first search of -+ dependencies in _dl_map_object_deps(), and this should be on the -+ same order of worst-case stack usage. -+ -+ Note: the '*rpo' parameter is supposed to point to one past the -+ last element of the array where we save the sort results, and is -+ decremented before storing the current map at each level. */ -+ -+static void -+dfs_traversal (struct link_map ***rpo, struct link_map *map, -+ bool *do_reldeps) -+{ -+ if (map->l_visited) -+ return; -+ -+ map->l_visited = 1; -+ -+ if (map->l_initfini) -+ { -+ for (int i = 0; map->l_initfini[i] != NULL; i++) -+ { -+ struct link_map *dep = map->l_initfini[i]; -+ if (dep->l_visited == 0 -+ && dep->l_main_map == 0) -+ dfs_traversal (rpo, dep, do_reldeps); -+ } -+ } -+ -+ if (__glibc_unlikely (do_reldeps != NULL && map->l_reldeps != NULL)) -+ { -+ /* Indicate that we encountered relocation dependencies during -+ traversal. */ -+ *do_reldeps = true; -+ -+ for (int m = map->l_reldeps->act - 1; m >= 0; m--) -+ { -+ struct link_map *dep = map->l_reldeps->list[m]; -+ if (dep->l_visited == 0 -+ && dep->l_main_map == 0) -+ dfs_traversal (rpo, dep, do_reldeps); -+ } -+ } -+ -+ *rpo -= 1; -+ **rpo = map; -+} -+ -+/* Topologically sort array MAPS according to dependencies of the contained -+ objects. */ -+ -+static void -+_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, -+ unsigned int skip __attribute__ ((unused)), bool for_fini) -+{ -+ for (int i = nmaps - 1; i >= 0; i--) -+ maps[i]->l_visited = 0; -+ -+ /* We apply DFS traversal for each of maps[i] until the whole total order -+ is found and we're at the start of the Reverse-Postorder (RPO) sequence, -+ which is a topological sort. -+ -+ We go from maps[nmaps - 1] backwards towards maps[0] at this level. -+ Due to the breadth-first search (BFS) ordering we receive, going -+ backwards usually gives a more shallow depth-first recursion depth, -+ adding more stack usage safety. Also, combined with the natural -+ processing order of l_initfini[] at each node during DFS, this maintains -+ an ordering closer to the original link ordering in the sorting results -+ under most simpler cases. -+ -+ Another reason we order the top level backwards, it that maps[0] is -+ usually exactly the main object of which we're in the midst of -+ _dl_map_object_deps() processing, and maps[0]->l_initfini[] is still -+ blank. If we start the traversal from maps[0], since having no -+ dependencies yet filled in, maps[0] will always be immediately -+ incorrectly placed at the last place in the order (first in reverse). -+ Adjusting the order so that maps[0] is last traversed naturally avoids -+ this problem. -+ -+ Further, the old "optimization" of skipping the main object at maps[0] -+ from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general -+ no longer valid, since traversing along object dependency-links -+ may "find" the main object even when it is not included in the initial -+ order (e.g. a dlopen()'ed shared object can have circular dependencies -+ linked back to itself). In such a case, traversing N-1 objects will -+ create a N-object result, and raise problems. -+ -+ To summarize, just passing in the full list, and iterating from back -+ to front makes things much more straightforward. */ -+ -+ /* Array to hold RPO sorting results, before we copy back to maps[]. */ -+ struct link_map *rpo[nmaps]; -+ -+ /* The 'head' position during each DFS iteration. Note that we start at -+ one past the last element due to first-decrement-then-store (see the -+ bottom of above dfs_traversal() routine). */ -+ struct link_map **rpo_head = &rpo[nmaps]; -+ -+ bool do_reldeps = false; -+ bool *do_reldeps_ref = (for_fini ? &do_reldeps : NULL); -+ -+ for (int i = nmaps - 1; i >= 0; i--) -+ { -+ dfs_traversal (&rpo_head, maps[i], do_reldeps_ref); -+ -+ /* We can break early if all objects are already placed. */ -+ if (rpo_head == rpo) -+ goto end; -+ } -+ assert (rpo_head == rpo); -+ -+ end: -+ /* Here we may do a second pass of sorting, using only l_initfini[] -+ static dependency links. This is avoided if !FOR_FINI or if we didn't -+ find any reldeps in the first DFS traversal. -+ -+ The reason we do this is: while it is unspecified how circular -+ dependencies should be handled, the presumed reasonable behavior is to -+ have destructors to respect static dependency links as much as possible, -+ overriding reldeps if needed. And the first sorting pass, which takes -+ l_initfini/l_reldeps links equally, may not preserve this priority. -+ -+ Hence we do a 2nd sorting pass, taking only DT_NEEDED links into account -+ (see how the do_reldeps argument to dfs_traversal() is NULL below). */ -+ if (do_reldeps) -+ { -+ for (int i = nmaps - 1; i >= 0; i--) -+ rpo[i]->l_visited = 0; -+ -+ struct link_map **maps_head = &maps[nmaps]; -+ for (int i = nmaps - 1; i >= 0; i--) -+ { -+ dfs_traversal (&maps_head, rpo[i], NULL); -+ -+ /* We can break early if all objects are already placed. -+ The below memcpy is not needed in the do_reldeps case here, -+ since we wrote back to maps[] during DFS traversal. */ -+ if (maps_head == maps) -+ return; -+ } -+ assert (maps_head == maps); -+ return; -+ } -+ -+ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps); -+} -+ -+void -+_dl_sort_maps_init (void) -+{ -+ int32_t algorithm = TUNABLE_GET (glibc, rtld, dynamic_sort, int32_t, NULL); -+ GLRO(dl_dso_sort_algo) = algorithm == 1 ? dso_sort_algorithm_original -+ : dso_sort_algorithm_dfs; -+} -+ -+void -+_dl_sort_maps (struct link_map **maps, unsigned int nmaps, -+ unsigned int skip, bool for_fini) -+{ -+ /* It can be tempting to use a static function pointer to store and call -+ the current selected sorting algorithm routine, but experimentation -+ shows that current processors still do not handle indirect branches -+ that efficiently, plus a static function pointer will involve -+ PTR_MANGLE/DEMANGLE, further impairing performance of small, common -+ input cases. A simple if-case with direct function calls appears to -+ be the fastest. */ -+ if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original)) -+ _dl_sort_maps_original (maps, nmaps, skip, for_fini); -+ else -+ _dl_sort_maps_dfs (maps, nmaps, skip, for_fini); -+} -+ -+#endif /* HAVE_TUNABLES. */ -diff --git a/elf/dl-support.c b/elf/dl-support.c -index d99c1f1d62..98d5d8db5c 100644 ---- a/elf/dl-support.c -+++ b/elf/dl-support.c -@@ -166,6 +166,8 @@ size_t _dl_phnum; - uint64_t _dl_hwcap; - uint64_t _dl_hwcap2; - -+enum dso_sort_algorithm _dl_dso_sort_algo; -+ - /* The value of the FPU control word the kernel will preset in hardware. */ - fpu_control_t _dl_fpu_control = _FPU_DEFAULT; - -diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c -index 2c684c2db2..4dc366eea4 100644 ---- a/elf/dl-sysdep.c -+++ b/elf/dl-sysdep.c -@@ -231,6 +231,9 @@ _dl_sysdep_start (void **start_argptr, - - __tunables_init (_environ); - -+ /* Initialize DSO sorting algorithm after tunables. */ -+ _dl_sort_maps_init (); -+ - #ifdef DL_SYSDEP_INIT - DL_SYSDEP_INIT; - #endif -diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list -index 8ddd4a2314..46ffb23784 100644 ---- a/elf/dl-tunables.list -+++ b/elf/dl-tunables.list -@@ -156,4 +156,13 @@ glibc { - security_level: SXID_IGNORE - } - } -+ -+ rtld { -+ dynamic_sort { -+ type: INT_32 -+ minval: 1 -+ maxval: 2 -+ default: 1 -+ } -+ } - } -diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def -index 873ddf55d9..5f7f18ef27 100644 ---- a/elf/dso-sort-tests-1.def -+++ b/elf/dso-sort-tests-1.def -@@ -62,5 +62,5 @@ output: b>a>{}<a<b - # The below expected outputs are what the two algorithms currently produce - # respectively, for regression testing purposes. - tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c --xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];} -+output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];} - output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];} -diff --git a/elf/rtld.c b/elf/rtld.c -index b8ba2d8836..be2d5d8e74 100644 ---- a/elf/rtld.c -+++ b/elf/rtld.c -@@ -1391,6 +1391,9 @@ dl_main (const ElfW(Phdr) *phdr, - main_map->l_name = (char *) ""; - *user_entry = main_map->l_entry; - -+ /* Set bit indicating this is the main program map. */ -+ main_map->l_main_map = 1; -+ - #ifdef HAVE_AUX_VECTOR - /* Adjust the on-stack auxiliary vector so that it looks like the - binary was executed directly. */ -diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp -index 9f66c52885..9bf572715f 100644 ---- a/elf/tst-rtld-list-tunables.exp -+++ b/elf/tst-rtld-list-tunables.exp -@@ -10,5 +10,6 @@ glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+) - glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+) - glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+) - glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+) -+glibc.rtld.dynamic_sort: 1 (min: 1, max: 2) - glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10) - glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+) -diff --git a/include/link.h b/include/link.h -index 484ee6cb1b..c1c382ccfa 100644 ---- a/include/link.h -+++ b/include/link.h -@@ -181,6 +181,11 @@ struct link_map - unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ - unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ - unsigned int l_reserved:2; /* Reserved for internal use. */ -+ unsigned int l_main_map:1; /* Nonzero for the map of the main program. */ -+ unsigned int l_visited:1; /* Used internally for map dependency -+ graph traversal. */ -+ unsigned int l_map_used:1; /* These two bits are used during traversal */ -+ unsigned int l_map_done:1; /* of maps in _dl_close_worker. */ - unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed - to by `l_phdr' is allocated. */ - unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in -diff --git a/manual/tunables.texi b/manual/tunables.texi -index 658547c613..10f4d75993 100644 ---- a/manual/tunables.texi -+++ b/manual/tunables.texi -@@ -309,6 +309,17 @@ changed once allocated at process startup. The default allocation of - optional static TLS is 512 bytes and is allocated in every thread. - @end deftp - -+@deftp Tunable glibc.rtld.dynamic_sort -+Sets the algorithm to use for DSO sorting, valid values are @samp{1} and -+@samp{2}. For value of @samp{1}, an older O(n^3) algorithm is used, which is -+long time tested, but may have performance issues when dependencies between -+shared objects contain cycles due to circular dependencies. When set to the -+value of @samp{2}, a different algorithm is used, which implements a -+topological sort through depth-first search, and does not exhibit the -+performance issues of @samp{1}. -+ -+The default value of this tunable is @samp{1}. -+@end deftp - - @node Elision Tunables - @section Elision Tunables -diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h -index 0410f777a6..65a6a51633 100644 ---- a/sysdeps/generic/ldsodefs.h -+++ b/sysdeps/generic/ldsodefs.h -@@ -245,6 +245,13 @@ enum allowmask - }; - - -+/* DSO sort algorithm to use (check dl-sort-maps.c). */ -+enum dso_sort_algorithm -+ { -+ dso_sort_algorithm_original, -+ dso_sort_algorithm_dfs -+ }; -+ - struct audit_ifaces - { - void (*activity) (uintptr_t *, unsigned int); -@@ -678,6 +685,8 @@ struct rtld_global_ro - platforms. */ - EXTERN uint64_t _dl_hwcap2; - -+ EXTERN enum dso_sort_algorithm _dl_dso_sort_algo; -+ - #ifdef SHARED - /* We add a function table to _rtld_global which is then used to - call the function instead of going through the PLT. The result -@@ -1104,7 +1113,7 @@ extern void _dl_fini (void) attribute_hidden; - - /* Sort array MAPS according to dependencies of the contained objects. */ - extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps, -- char *used, bool for_fini) attribute_hidden; -+ unsigned int skip, bool for_fini) attribute_hidden; - - /* The dynamic linker calls this function before and having changing - any shared object mappings. The `r_state' member of `struct r_debug' -@@ -1235,6 +1244,9 @@ extern struct link_map * _dl_get_dl_main_map (void) - # endif - #endif - -+/* Initialize the DSO sort algorithm to use. */ -+extern void _dl_sort_maps_init (void) attribute_hidden; -+ - /* Initialization of libpthread for statically linked applications. - If libpthread is not linked in, this is an empty function. */ - void __pthread_initialize_minimal (void) weak_function; |