elf: Testing infrastructure for ld.so DSO sorting (BZ #17645)
This is the first of a 2-part patch set that fixes slow DSO sorting behavior in
the dynamic loader, as reported in BZ #17645. In order to facilitate such a
large modification to the dynamic loader, this first patch implements a testing
framework for validating shared object sorting behavior, to enable comparison
between old/new sorting algorithms, and any later enhancements.
This testing infrastructure consists of a Python script
scripts/dso-ordering-test.py' which takes in a description language, consisting
of strings that describe a set of link dependency relations between DSOs, and
generates testcase programs and Makefile fragments to automatically test the
described situation, for example:
a->b->c->d # four objects linked one after another
a->[bc]->d;b->c # a depends on b and c, which both depend on d,
# b depends on c (b,c linked to object a in fixed order)
a->b->c;{+a;%a;-a} # a, b, c serially dependent, main program uses
# dlopen/dlsym/dlclose on object a
a->b->c;{}!->[abc] # a, b, c serially dependent; multiple tests generated
# to test all permutations of a, b, c ordering linked
# to main program
(Above is just a short description of what the script can do, more
documentation is in the script comments.)
Two files containing several new tests, elf/dso-sort-tests-[12].def are added,
including test scenarios for BZ #15311 and Redhat issue #1162810 [1].
Due to the nature of dynamic loader tests, where the sorting behavior and test
output occurs before/after main(), generating testcases to use
support/test-driver.c does not suffice to control meaningful timeout for ld.so.
Therefore a new utility program 'support/test-run-command', based on
test-driver.c/support_test_main.c has been added. This does the same testcase
control, but for a program specified through a command-line rather than at the
source code level. This utility is used to run the dynamic loader testcases
generated by dso-ordering-test.py.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1162810
Signed-off-by: Chung-Lin Tang <cltang@codesourcery.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2021-10-21 21:41:21 +08:00
|
|
|
# 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
|
2023-10-18 17:30:38 +08:00
|
|
|
# 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).
|
2023-11-17 02:55:35 +08:00
|
|
|
# The older dynamic_sort=1 algorithm originally did not achieve this,
|
|
|
|
# but this was a bug in the way _dl_sort_maps was called from _dl_close_worker,
|
|
|
|
# effectively disabling proper force_first handling.
|
|
|
|
# The new dynamic_sort=2 algorithm shows the effect of the simpler force_first
|
|
|
|
# handling: the a object is simply moved to the front.
|
2023-10-18 17:30:38 +08:00
|
|
|
# The below expected outputs are what the two algorithms currently produce
|
|
|
|
# respectively, for regression testing purposes.
|
elf: Testing infrastructure for ld.so DSO sorting (BZ #17645)
This is the first of a 2-part patch set that fixes slow DSO sorting behavior in
the dynamic loader, as reported in BZ #17645. In order to facilitate such a
large modification to the dynamic loader, this first patch implements a testing
framework for validating shared object sorting behavior, to enable comparison
between old/new sorting algorithms, and any later enhancements.
This testing infrastructure consists of a Python script
scripts/dso-ordering-test.py' which takes in a description language, consisting
of strings that describe a set of link dependency relations between DSOs, and
generates testcase programs and Makefile fragments to automatically test the
described situation, for example:
a->b->c->d # four objects linked one after another
a->[bc]->d;b->c # a depends on b and c, which both depend on d,
# b depends on c (b,c linked to object a in fixed order)
a->b->c;{+a;%a;-a} # a, b, c serially dependent, main program uses
# dlopen/dlsym/dlclose on object a
a->b->c;{}!->[abc] # a, b, c serially dependent; multiple tests generated
# to test all permutations of a, b, c ordering linked
# to main program
(Above is just a short description of what the script can do, more
documentation is in the script comments.)
Two files containing several new tests, elf/dso-sort-tests-[12].def are added,
including test scenarios for BZ #15311 and Redhat issue #1162810 [1].
Due to the nature of dynamic loader tests, where the sorting behavior and test
output occurs before/after main(), generating testcases to use
support/test-driver.c does not suffice to control meaningful timeout for ld.so.
Therefore a new utility program 'support/test-run-command', based on
test-driver.c/support_test_main.c has been added. This does the same testcase
control, but for a program specified through a command-line rather than at the
source code level. This utility is used to run the dynamic loader testcases
generated by dso-ordering-test.py.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1162810
Signed-off-by: Chung-Lin Tang <cltang@codesourcery.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2021-10-21 21:41:21 +08:00
|
|
|
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
|
2023-11-17 02:55:35 +08:00
|
|
|
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<b<c<d<g<f<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[<a<g<f<b<c<d<e];}
|
2022-09-20 17:00:42 +08:00
|
|
|
|
|
|
|
# Test that even in the presence of dependency loops involving dlopen'ed
|
|
|
|
# object, that object is initialized last (and not unloaded prematurely).
|
2023-10-18 17:30:38 +08:00
|
|
|
# Final destructor order is indeterminate due to the cycle.
|
2022-09-20 17:00:42 +08:00
|
|
|
tst-bz28937: {+a;+b;-b;+c;%c};a->a1;a->a2;a2->a;b->b1;c->a1;c=>a1
|
2023-10-18 17:30:38 +08:00
|
|
|
output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
|
|
|
|
output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1
|