[glibc] elf: Fix tst-ifunc-tls-init with --disable-default-pie
Adhemerval Zanella via Glibc-cvs <[email protected]> Tue, 2 Jun 2026 18:42:12 +0000 (GMT)
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5879990337c1e37d3ded6bf6d03b8af9737a2d86 commit 5879990337c1e37d3ded6bf6d03b8af9737a2d86 Author: Adhemerval Zanella <[email protected]> Date: Mon Jun 1 10:00:20 2026 -0300 elf: Fix tst-ifunc-tls-init with --disable-default-pie The test failed with --disable-default-pie because its primary check read the resolver's diagnostic side effect before the resolver had run. In a non-PIE executable the references to the IFUNC (fptr and ifunc_tls) are satisfied through a canonical IPLT entry in the executable itself. Under the default lazy binding that IPLT is resolved on first use, not during startup relocation, so the resolver had not yet run when 'check_sentinel' inspected that value. With a PIE executable (or LD_BIND_NOW=1) the resolver runs eagerly at startup and the check passed. The dlopen path was unaffected because dlopen resolves the data relocation eagerly. This is a test ordering issue: the resolver always reads the initial-exec TLS correctly whenever it runs, so the BZ 34164 fix is not involved. Reorder test_tls_ifunc so that fptr/ifunc_tls force the IFUNC to be resolved before the last_seen_sentinel value is inspected. Checked on x86_64-linux-gnu and i686-linux-gnu with --disable-default-pie. Reported-by: Yury Khrustalev <[email protected]> Reviewed-by: Yury Khrustalev <[email protected]> Diff: --- elf/tst-ifunc-tls-init.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/elf/tst-ifunc-tls-init.c b/elf/tst-ifunc-tls-init.c index 8b996b7c60..b18210bf00 100644 --- a/elf/tst-ifunc-tls-init.c +++ b/elf/tst-ifunc-tls-init.c @@ -39,6 +39,18 @@ test_tls_ifunc (int (*check_sentinel)(void), int (*check_fptr)(void), int (*check_ifunc_tls)(void)) { + /* Force the IFUNC to be resolved before inspecting what the resolver + observed. In a non-PIE executable the references to the IFUNC are + satisfied through a canonical IPLT entry in the executable, which under + lazy binding is resolved on first use rather than during startup + relocation. Calling fptr/ifunc_tls here guarantees the resolver has run + regardless of PIE-ness or binding mode. */ + TEST_VERIFY (check_fptr != NULL); + TEST_COMPARE (check_fptr (), SENTINEL); + + /* Issue the ifunc directly as well. */ + TEST_COMPARE (check_ifunc_tls (), SENTINEL); + /* Primary check: 'get_last_seen_sentinel' returns the value of the DSO's thread-local 'sentinel' as observed by the resolver at the moment it ran for the IFUNC reloc that initialised fptr. The getter is a regular @@ -46,14 +58,6 @@ test_tls_ifunc (int (*check_sentinel)(void), does NOT go through a COPY relocation that could overwrite the resolver's write. */ TEST_COMPARE (check_sentinel (), SENTINEL); - - /* Secondary check: fptr is set during IFUNC resolver call, then copied into - the exe's. Returns SENTINEL only if the resolver picked impl_ok. */ - TEST_VERIFY (check_fptr != NULL); - TEST_COMPARE (check_fptr (), SENTINEL); - - /* Sanity check: issue the ifunc. */ - TEST_COMPARE (check_ifunc_tls (), SENTINEL); } static int