[PATCH v4] i386: Update ___tls_get_addr to preserve vector registers
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue Jun 17 12:52:34 GMT 2025
On 17/06/25 09:33, H.J. Lu wrote:
> On Tue, Jun 17, 2025 at 7:46 PM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>>> diff --git a/elf/tst-tls23.c b/elf/tst-tls23.c
>>> new file mode 100644
>>> index 0000000000..afe594c067
>>> --- /dev/null
>>> +++ b/elf/tst-tls23.c
>>> @@ -0,0 +1,106 @@
>>> +/* Test that __tls_get_addr preserves caller-saved registers.
>>> + Copyright (C) 2025 Free Software Foundation, Inc.
>>> + This file is part of the GNU C Library.
>>> +
>>> + The GNU C Library is free software; you can redistribute it and/or
>>> + modify it under the terms of the GNU Lesser General Public
>>> + License as published by the Free Software Foundation; either
>>> + version 2.1 of the License, or (at your option) any later version.
>>> +
>>> + The GNU C Library is distributed in the hope that it will be useful,
>>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>>> + Lesser General Public License for more details.
>>> +
>>> + You should have received a copy of the GNU Lesser General Public
>>> + License along with the GNU C Library; if not, see
>>> + <http://www.gnu.org/licenses/>. */
>>> +
>>> +#include <stdio.h>
>>> +#include <stdlib.h>
>>> +#include <string.h>
>>> +#include <dlfcn.h>
>>> +#include <pthread.h>
>>> +#include <support/xdlfcn.h>
>>> +#include <support/xthread.h>
>>> +#include <support/check.h>
>>> +#include <support/test-driver.h>
>>> +#include <tst-tls23.h>
>>> +
>>> +#ifndef IS_SUPPORTED
>>> +# define IS_SUPPORTED() true
>>> +#endif
>>> +
>>> +/* An architecture can define it to clobber caller-saved registers in
>>> + malloc below to verify that __tls_get_addr won't change caller-saved
>>> + registers. */
>>> +#ifndef PREPARE_MALLOC
>>> +# define PREPARE_MALLOC()
>>> +#endif
>>> +
>>> +extern void * __libc_malloc (size_t);
>>> +
>>> +size_t malloc_counter = 0;
>>> +
>>> +void *
>>> +malloc (size_t n)
>>> +{
>>> + PREPARE_MALLOC ();
>>> + malloc_counter++;
>>> + return __libc_malloc (n);
>>> +}
>>> +
>>> +static void *mod;
>>> +static const char *modname = "tst-tls23-mod.so";
>>> +
>>> +static void
>>> +open_mod (void)
>>> +{
>>> + mod = xdlopen (modname, RTLD_LAZY);
>>> + printf ("open %s\n", modname);
>>> +}
>>> +
>>> +static void
>>> +close_mod (void)
>>> +{
>>> + xdlclose (mod);
>>> + mod = NULL;
>>> + printf ("close %s\n", modname);
>>> +}
>>> +
>>> +static void
>>> +access_mod (const char *sym)
>>> +{
>>> + struct tls var = { -4, -4, -4, -4 };
>>> + struct tls *(*f) (struct tls *) = xdlsym (mod, sym);
>>> + /* Check that our malloc is called. */
>>> + malloc_counter = 0;
>>> + struct tls *p = f (&var);
>>> + TEST_VERIFY (malloc_counter != 0);
>>> + printf ("access %s: %s() = %p\n", modname, sym, p);
>>> + TEST_VERIFY_EXIT (memcmp (p, &var, sizeof (var)) == 0);
>>> + ++(p->a);
>>> +}
>>> +
>>> +static void *
>>> +start (void *arg)
>>> +{
>>> + access_mod ("apply_tls");
>>> + return arg;
>>> +}
>>> +
>>> +static int
>>> +do_test (void)
>>> +{
>>> + if (!IS_SUPPORTED ())
>>> + return EXIT_UNSUPPORTED;
>>> +
>>> + open_mod ();
>>> + pthread_t t = xpthread_create (NULL, start, NULL);
>>> + xpthread_join (t);
>>> + close_mod ();
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +#include <support/test-driver.c>
>>
>> This test fails on ppc64le because malloc_counter is not increased:
>>
>> =====FAIL: elf/tst-tls23.out=====
>> open tst-tls23-mod.so
>> error: tst-tls23.c:79: not true: malloc_counter != 0
>> access tst-tls23-mod.so: apply_tls() = 0x7fff9f7ff980
>> close tst-tls23-mod.so
>> error: 1 test failures
>>
>> This may be because of the POWER-specific __tls_get_addr_opt
>> optimization.
>>
>> Increasing the size of TLS variables may force an allocation ppc64le as
>> well.
>
> Can you find out what size should be?
I am checking on some different ABI to see if everything is ok and get a
proper number for powerpc.
More information about the Libc-alpha
mailing list