Correct cycle detection during dependency sorting
authorAndreas Schwab <schwab@redhat.com>
Mon, 22 Aug 2011 20:08:16 +0000 (16:08 -0400)
committerUlrich Drepper <drepper@gmail.com>
Mon, 22 Aug 2011 20:08:16 +0000 (16:08 -0400)
ChangeLog
elf/Makefile
elf/dl-deps.c
elf/dl-fini.c
elf/tst-initorder2.c [new file with mode: 0644]
elf/tst-initorder2.exp [new file with mode: 0644]

index 0161040..1945002 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-08-16  Andreas Schwab  <schwab@redhat.com>
+
+       [BZ #11724]
+       * elf/dl-deps.c (_dl_map_object_deps): Only assume cycle when
+       object is seen twice.
+       * elf/dl-fini.c (_dl_sort_fini): Likewise.
+
+       * elf/Makefile (distribute): Add tst-initorder2.c.
+       (tests): Add tst-initorder2.
+       (modules-names): Add tst-initorder2a tst-initorder2b
+       tst-initorder2c tst-initorder2d.  Add rules to build them.
+       ($(objpfx)tst-initorder2.out): New rule.
+       * elf/tst-initorder2.c: New file.
+       * elf/tst-initorder2.exp: New file.
+
 2011-08-21  Ulrich Drepper  <drepper@gmail.com>
 
        * sysdeps/unix/sysv/linux/x86_64/gettimeofday.S: Removed.
index 709b61d..aeb6393 100644 (file)
@@ -120,9 +120,10 @@ distribute := rtld-Rules \
                   ifuncmain7pie.c ifuncmain7static.c \
                   tst-unique1.c tst-unique1mod1.c tst-unique1mod2.c \
                   tst-unique2.c tst-unique2mod1.c tst-unique2mod2.c \
-                        tst-initordera1.c tst-initordera2.c tst-initorderb1.c \
-                        tst-initorderb2.c tst-initordera3.c tst-initordera4.c \
-                        tst-initorder.c
+                  tst-initordera1.c tst-initordera2.c tst-initorderb1.c \
+                  tst-initorderb2.c tst-initordera3.c tst-initordera4.c \
+                  tst-initorder.c \
+                  tst-initorder2.c
 
 CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
@@ -227,7 +228,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
         tst-audit1 tst-audit2 \
         tst-stackguard1 tst-addr1 tst-thrlock \
         tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
-        tst-initorder
+        tst-initorder tst-initorder2
 #       reldep9
 test-srcs = tst-pathopt
 selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
@@ -288,7 +289,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                tst-unique4lib \
                tst-initordera1 tst-initorderb1 \
                tst-initordera2 tst-initorderb2 \
-               tst-initordera3 tst-initordera4
+               tst-initordera3 tst-initordera4 \
+               tst-initorder2a tst-initorder2b tst-initorder2c tst-initorder2d
 ifeq (yes,$(have-initfini-array))
 modules-names += tst-array2dep tst-array5dep
 endif
@@ -1157,6 +1159,23 @@ $(objpfx)tst-initorder.out: $(objpfx)tst-initorder
          $< > $@
        cmp $@ tst-initorder.exp > /dev/null
 
+$(objpfx)tst-initorder2: $(objpfx)tst-initorder2a.so $(objpfx)tst-initorder2d.so $(objpfx)tst-initorder2c.so
+$(objpfx)tst-initorder2a.so: $(objpfx)tst-initorder2b.so
+$(objpfx)tst-initorder2b.so: $(objpfx)tst-initorder2c.so
+$(objpfx)tst-initorder2c.so: $(objpfx)tst-initorder2d.so
+define o-iterator-doit
+$(objpfx)tst-initorder2$o.os: tst-initorder2.c; \
+$$(compile-command.c) -DNAME=\"$o\"
+endef
+object-suffixes-left := a b c d
+include $(o-iterator)
+
+$(objpfx)tst-initorder2.out: $(objpfx)tst-initorder2
+       $(elf-objpfx)${rtld-installed-name} \
+         --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
+         $< > $@
+       cmp $@ tst-initorder2.exp > /dev/null
+
 ifeq (yes,$(config-cflags-avx))
 AVX-CFLAGS=-mavx
 ifeq (yes,$(config-cflags-novzeroupper))
index 0b03b90..cc0023d 100644 (file)
@@ -626,12 +626,12 @@ Filters not supported with LD_TRACE_PRELINKING"));
       /* We can skip looking for the binary itself which is at the front
         of the search list.  */
       i = 1;
-      bool seen[nlist];
-      memset (seen, false, nlist * sizeof (seen[0]));
+      char seen[nlist];
+      memset (seen, 0, nlist * sizeof (seen[0]));
       while (1)
        {
          /* Keep track of which object we looked at this round.  */
-         seen[i] = true;
+         seen[i] += seen[i] < 2;
          struct link_map *thisp = l_initfini[i];
 
          /* Find the last object in the list for which the current one is
@@ -652,15 +652,16 @@ Filters not supported with LD_TRACE_PRELINKING"));
                               (k - i) * sizeof (l_initfini[0]));
                      l_initfini[k] = thisp;
 
-                     if (seen[i + 1])
+                     if (seen[i + 1] > 1)
                        {
                          ++i;
                          goto next_clear;
                        }
 
+                     char this_seen = seen[i];
                      memmove (&seen[i], &seen[i + 1],
                               (k - i) * sizeof (seen[0]));
-                     seen[k] = true;
+                     seen[k] = this_seen;
 
                      goto next;
                    }
@@ -671,7 +672,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
          if (++i == nlist)
            break;
        next_clear:
-         memset (&seen[i], false, (nlist - i) * sizeof (seen[0]));
+         memset (&seen[i], 0, (nlist - i) * sizeof (seen[0]));
 
        next:;
        }
index 0a138e9..bafc83a 100644 (file)
@@ -39,12 +39,12 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
   /* We can skip looking for the binary itself which is at the front
      of the search list for the main namespace.  */
   unsigned int i = ns == LM_ID_BASE;
-  bool seen[nmaps];
-  memset (seen, false, nmaps * sizeof (seen[0]));
+  char seen[nmaps];
+  memset (seen, 0, nmaps * sizeof (seen[0]));
   while (1)
     {
       /* Keep track of which object we looked at this round.  */
-      seen[i] = true;
+      seen[i] += seen[i] < 2;
       struct link_map *thisp = maps[i];
 
       /* Do not handle ld.so in secondary namespaces and object which
@@ -79,14 +79,15 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
                      used[k] = here_used;
                    }
 
-                 if (seen[i + 1])
+                 if (seen[i + 1] > 1)
                    {
                      ++i;
                      goto next_clear;
                    }
 
+                 char this_seen = seen[i];
                  memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0]));
-                 seen[k] = true;
+                 seen[k] = this_seen;
 
                  goto next;
                }
@@ -96,7 +97,7 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
              unsigned int m = maps[k]->l_reldeps->act;
              struct link_map **relmaps = &maps[k]->l_reldeps->list[0];
 
-           /* Look through the relocation dependencies of the object.  */
+             /* Look through the relocation dependencies of the object.  */
              while (m-- > 0)
                if (__builtin_expect (relmaps[m] == thisp, 0))
                  goto move;
@@ -109,7 +110,7 @@ _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
       if (++i == nmaps)
        break;
     next_clear:
-      memset (&seen[i], false, (nmaps - i) * sizeof (seen[0]));
+      memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
 
     next:;
     }
diff --git a/elf/tst-initorder2.c b/elf/tst-initorder2.c
new file mode 100644 (file)
index 0000000..050f956
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+#ifndef NAME
+int
+main (void)
+{
+  puts ("main");
+}
+#else
+static void __attribute__ ((constructor))
+init (void)
+{
+  puts ("init: " NAME);
+}
+static void __attribute__ ((destructor))
+fini (void)
+{
+  puts ("fini: " NAME);
+}
+#endif
diff --git a/elf/tst-initorder2.exp b/elf/tst-initorder2.exp
new file mode 100644 (file)
index 0000000..5169489
--- /dev/null
@@ -0,0 +1,9 @@
+init: d
+init: c
+init: b
+init: a
+main
+fini: a
+fini: b
+fini: c
+fini: d