From e888bcbe4fb8ad538ec640bfb18b687d51e001e7 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 22 Aug 2011 16:08:16 -0400 Subject: [PATCH] Correct cycle detection during dependency sorting --- ChangeLog | 15 +++++++++++++++ elf/Makefile | 29 ++++++++++++++++++++++++----- elf/dl-deps.c | 13 +++++++------ elf/dl-fini.c | 15 ++++++++------- elf/tst-initorder2.c | 20 ++++++++++++++++++++ elf/tst-initorder2.exp | 9 +++++++++ 6 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 elf/tst-initorder2.c create mode 100644 elf/tst-initorder2.exp diff --git a/ChangeLog b/ChangeLog index 01610406c1..1945002ff4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-08-16 Andreas Schwab + + [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 * sysdeps/unix/sysv/linux/x86_64/gettimeofday.S: Removed. diff --git a/elf/Makefile b/elf/Makefile index 709b61dddf..aeb63936af 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -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)) diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 0b03b903fe..cc0023d381 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -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:; } diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 0a138e9126..bafc83a92f 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -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 index 0000000000..050f9568b8 --- /dev/null +++ b/elf/tst-initorder2.c @@ -0,0 +1,20 @@ +#include + +#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 index 0000000000..5169489b85 --- /dev/null +++ b/elf/tst-initorder2.exp @@ -0,0 +1,9 @@ +init: d +init: c +init: b +init: a +main +fini: a +fini: b +fini: c +fini: d