[PATCH] elf: Fix tst-ifunc-tls-init with --disable-default-pie
Yury Khrustalev
yury.khrustalev@arm.com
Tue Jun 2 13:04:37 GMT 2026
On Mon, Jun 01, 2026 at 10:00:20AM -0300, Adhemerval Zanella wrote:
> 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.
Also checked on aarch64-linux-gnu.
>
> Reported-by: Yury Khrustalev <yury.khrustalev@arm.com>
> ---
> 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 8b996b7c60c..b18210bf008 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
> --
> 2.43.0
>
LGTM
Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
Thanks,
Yury
More information about the Libc-alpha
mailing list