[PATCH] elf: Initialize static TLS before relocation processing

H.J. Lu hjl.tools@gmail.com
Thu May 21 22:32:59 GMT 2026


On Thu, May 21, 2026 at 8:01 PM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 20/05/26 18:09, H.J. Lu wrote:
> > On Thu, May 21, 2026 at 4:07 AM Adhemerval Zanella
> > <adhemerval.zanella@linaro.org> wrote:
> >>
> >> An IFUNC resolver firing during dynamic linker relocation reads its
> >> DSO's __thread storage from a zero-filled slot: init_tls() allocates
> >> the static TLS block zero-filled, but .tdata is not copied in until
> >> the trailing _dl_allocate_tls_init at the end of dl_main, long after
> >> the per-object phase 2 resolvers from commit 63b31c05a8a901 have run.
> >> A resolver that *writes* TLS is even worse off -- the write is
> >> clobbered by that same trailing copy.
> >
> > Is there a bug report?  Is this a regression on x86?
>
> It is https://sourceware.org/bugzilla/show_bug.cgi?id=34164 now and afaik it is
> not a regression.  The testcase on the bug report can be reproduced on old
> glibcs (it shows on 2.39).

Please mention BZ #34164 in the commit message.

> >
> >> dl_main (elf/rtld.c): populate the DTV slotinfo, bump
> >> dl_tls_generation, and call _dl_allocate_tls_init right after
> >> init_tls(), before the relocation loop.
> >>
> >> _dl_try_allocate_static_tls (elf/dl-reloc.c): drop the
> >> "defer-if-not-relocated" branch and always run _dl_init_static_tls
> >> inline, so a CHECK_STATIC_TLS allocation triggered mid-relocation
> >> initialises the slot before the same object's phase 2 fires.
> >>
> >> The new tests cheks some scenariosn:
> >                                               Spelling?
>
> Ack.
>
> >
> >>
> >>   elf/tst-ifunc-tls-init         resolver reads its DSO's IE TLS.
> >>   elf/tst-ifunc-tls-init-dlopen  same, via dlopen.
> >>   elf/tst-ifunc-tls-write        resolver write to TLS must survive
> >>                                  to main.
> >>
> >> Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu.
> >> ---
> >>  elf/Makefile                          | 10 ++++
> >>  elf/dl-reloc.c                        | 27 +++++----
> >>  elf/rtld.c                            | 31 ++++++----
> >>  elf/tst-ifunc-tls-init-dlopen-lib.c   | 56 ++++++++++++++++++
> >>  elf/tst-ifunc-tls-init-lib-skeleton.c | 57 +++++++++++++++++++
> >>  elf/tst-ifunc-tls-init-lib1.c         |  1 +
> >>  elf/tst-ifunc-tls-init-lib2.c         |  1 +
> >>  elf/tst-ifunc-tls-init.c              | 81 +++++++++++++++++++++++++++
> >>  elf/tst-ifunc-tls-write-lib.c         | 54 ++++++++++++++++++
> >>  elf/tst-ifunc-tls-write.c             | 34 +++++++++++
> >>  10 files changed, 328 insertions(+), 24 deletions(-)
> >>  create mode 100644 elf/tst-ifunc-tls-init-dlopen-lib.c
> >>  create mode 100644 elf/tst-ifunc-tls-init-lib-skeleton.c
> >>  create mode 100644 elf/tst-ifunc-tls-init-lib1.c
> >>  create mode 100644 elf/tst-ifunc-tls-init-lib2.c
> >>  create mode 100644 elf/tst-ifunc-tls-init.c
> >>  create mode 100644 elf/tst-ifunc-tls-write-lib.c
> >>  create mode 100644 elf/tst-ifunc-tls-write.c
> >>
> >> diff --git a/elf/Makefile b/elf/Makefile
> >> index aef13b73ca5..ff42eb32d41 100644
> >> --- a/elf/Makefile
> >> +++ b/elf/Makefile
> >> @@ -1268,6 +1268,8 @@ tests += \
> >>    tst-ifunc-plt-bindnow \
> >>    tst-ifunc-plt-dlopen \
> >>    tst-ifunc-plt-dlopen-bindnow \
> >> +  tst-ifunc-tls-init \
> >> +  tst-ifunc-tls-write \
> >>    # tests
> >>  # Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8.
> >>  tests-internal += \
> >> @@ -1332,6 +1334,9 @@ modules-names += \
> >>    ifuncmod6 \
> >>    tst-ifunc-plt-dep \
> >>    tst-ifunc-plt-lib \
> >> +  tst-ifunc-tls-init-lib1 \
> >> +  tst-ifunc-tls-init-lib2 \
> >> +  tst-ifunc-tls-write-lib \
> >>    # modules-names
> >>  ifeq (no,$(with-lld))
> >>  modules-names += ifuncmod5
> >> @@ -2468,6 +2473,11 @@ $(objpfx)tst-ifunc-plt-dlopen.out: \
> >>  $(objpfx)tst-ifunc-plt-dlopen-bindnow.out: \
> >>    $(objpfx)tst-ifunc-plt-lib.so $(objpfx)tst-ifunc-plt-dep.so
> >>
> >> +$(objpfx)tst-ifunc-tls-init: $(objpfx)tst-ifunc-tls-init-lib1.so
> >> +$(objpfx)tst-ifunc-tls-init.out: \
> >> +  $(objpfx)tst-ifunc-tls-init-lib2.so
> >> +$(objpfx)tst-ifunc-tls-write: $(objpfx)tst-ifunc-tls-write-lib.so
> >> +
> >>  $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
> >>                           $(objpfx)tst-unique1mod2.so
> >>
> >> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> >> index f1a432ac099..67299400cad 100644
> >> --- a/elf/dl-reloc.c
> >> +++ b/elf/dl-reloc.c
> >> @@ -107,22 +107,21 @@ _dl_try_allocate_static_tls (struct link_map *map, bool optional)
> >>  # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
> >>  #endif
> >>
> >> -  /* If the object is not yet relocated we cannot initialize the
> >> -     static TLS region.  Delay it.  */
> >> -  if (map->l_real->l_relocated)
> >> -    {
> >> +  /* Initialise the static TLS region, the map may not yet be l_relocated (a
> >> +     TLS reloc inside the relocation loop triggered the allocation), but
> >> +     _dl_init_static_tls only writes .tdata into the static TLS slot, which is
> >> +     independent of relocation state.
> >> +     Doing this inline ensures any IFUNC resolver that fires laterin the same
> >> +     object's relocation pass sees an initialised TLS slot, and the
> >> +     post-relocation TLS init loop in dl_open_worker_begin becomes a no-op for
> >> +     this map.  */
> >>  #ifdef SHARED
> >> -      /* Update the DTV of the current thread.  Note: GL(dl_load_tls_lock)
> >> -        is held here so normal load of the generation counter is valid.  */
> >> -      if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
> >> -                           0))
> >> -       (void) _dl_update_slotinfo (map->l_tls_modid, GL(dl_tls_generation));
> >> +  /* Update the DTV of the current thread.  Note: GL(dl_load_tls_lock)
> >> +     is held here so normal load of the generation counter is valid.  */
> >> +  if (__glibc_unlikely (THREAD_DTV()[0].counter != GL(dl_tls_generation)))
> >> +    _dl_update_slotinfo (map->l_tls_modid, GL(dl_tls_generation));
> >>  #endif
> >> -
> >> -      _dl_init_static_tls (map);
> >> -    }
> >> -  else
> >> -    map->l_need_tls_init = 1;
> >> +  _dl_init_static_tls (map);
> >>
> >>    return 0;
> >>  }
> >> diff --git a/elf/rtld.c b/elf/rtld.c
> >> index e926ec73e49..12e1b4dd71f 100644
> >> --- a/elf/rtld.c
> >> +++ b/elf/rtld.c
> >> @@ -2263,6 +2263,26 @@ dl_main (const ElfW(Phdr) *phdr,
> >>        rtld_timer_accum (&relocate_time, start);
> >>    }
> >>
> >> +  /* Populate the DTV slotinfo and copy each TLS module's into thestatic TLS
> >> +     block *before* the relocation loop.  IFUNC resolvers fired during phase 2
> >> +     of the per-object two-phase scheme therefore observe initialised TLS.  */
> >> +  if (__rtld_tls_init_tp_called)
> >> +    {
> >> +      unsigned int i = main_map->l_searchlist.r_nlist;
> >> +      while (i-- > 0)
> >> +       {
> >> +         struct link_map *l = main_map->l_initfini[i];
> >> +         if (l->l_tls_blocksize != 0)
> >> +           _dl_add_to_slotinfo (l, true);
> >> +       }
> >> +      /* _dl_add_to_slotinfo records gen = dl_tls_generation + 1, and
> >> +        _dl_allocate_tls_init asserts gen <= dl_tls_generation, so bump
> >> +        the generation before init.  */
> >> +      if (GL(dl_tls_max_dtv_idx) > 0)
> >> +       ++GL(dl_tls_generation);
> >> +      _dl_allocate_tls_init (tcbp, true);
> >> +    }
> >> +
> >>    RTLD_TIMING_VAR (start);
> >>    rtld_timer_start (&start);
> >>    {
> >> @@ -2286,10 +2306,6 @@ dl_main (const ElfW(Phdr) *phdr,
> >>
> >>         _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
> >>                              consider_profiling);
> >> -
> >> -       /* Add object to slot information data if necessary.  */
> >> -       if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
> >> -         _dl_add_to_slotinfo (l, true);
> >>        }
> >>    }
> >>    rtld_timer_stop (&relocate_time, start);
> >> @@ -2310,12 +2326,7 @@ dl_main (const ElfW(Phdr) *phdr,
> >>        || count_modids != _dl_count_modids ())
> >>      ++GL(dl_tls_generation);
> >>
> >> -  /* Now that we have completed relocation, the initializer data
> >> -     for the TLS blocks has its final values and we can copy them
> >> -     into the main thread's TLS area, which we allocated above.
> >> -     Note: thread-local variables must only be accessed after completing
> >> -     the next step.  */
> >> -  _dl_allocate_tls_init (tcbp, true);
> >> +  /* TLS .tdata copy moved before the relocation loop above.  */
> >>
> >>    /* And finally install it for the main thread.  */
> >>    if (! __rtld_tls_init_tp_called)
> >> diff --git a/elf/tst-ifunc-tls-init-dlopen-lib.c b/elf/tst-ifunc-tls-init-dlopen-lib.c
> >> new file mode 100644
> >> index 00000000000..b3e587a3f40
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-init-dlopen-lib.c
> >> @@ -0,0 +1,56 @@
> >> +/* Shared library for tst-ifunc-tls-init-dlopen.
> >> +   Copyright (C) 2026 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
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +/* Same as tst-ifunc-tls-init-lib.c, but exercises the dlopen path.  */
> >> +
> >> +#define SENTINEL 0x5A5A1234
> >> +
> >> +static volatile __thread int sentinel
> >> +  __attribute__ ((tls_model ("initial-exec"))) = SENTINEL;
> >> +static volatile int last_seen_sentinel;
> >> +
> >> +static int
> >> +impl_ok (void)
> >> +{
> >> +  return SENTINEL;
> >> +}
> >> +
> >> +static int
> >> +impl_bad (void)
> >> +{
> >> +  return 0;
> >> +}
> >> +
> >> +int
> >> +get_last_seen_sentinel (void)
> >> +{
> >> +  return last_seen_sentinel;
> >> +}
> >> +
> >> +static int (*
> >> +resolver (void)) (void)
> >
> > static int (*resolver (void)) (void)
> >
> >> +{
> >> +  int s = sentinel;
> >> +  last_seen_sentinel = s;
> >> +  return s == SENTINEL ? impl_ok : impl_bad;
> >> +}
> >> +
> >> +int ifunc_tls (void) __attribute__ ((ifunc ("resolver")));
> >> +
> >> +/* Force a non-PLT relocation against the IFUNC symbol.  */
> >> +int (*fptr) (void) = ifunc_tls;
> >> diff --git a/elf/tst-ifunc-tls-init-lib-skeleton.c b/elf/tst-ifunc-tls-init-lib-skeleton.c
> >> new file mode 100644
> >> index 00000000000..d8b2a4f0f10
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-init-lib-skeleton.c
> >> @@ -0,0 +1,57 @@
> >> +/* Test that static-TLS initialisation works correctly with IFUNC resolvers.
> >> +   Copyright (C) 2026 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
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +/* The initial-exec TLS model keeps the access path to a single TP-relative
> >> +   load, so the test is sensitive to whether the static TLS block has been
> >> +   populated rather than to any __tls_get_addr / DTV-update timing.  */
> >> +
> >> +#define SENTINEL 0x5A5A1234
> >> +
> >> +/* The 'volatile' avoids constant fold optimization in impl_ok.  */
> >> +static volatile __thread int sentinel
> >> +  __attribute__ ((tls_model ("initial-exec"))) = SENTINEL;
> >> +static volatile int last_seen_sentinel;
> >> +
> >> +static int
> >> +impl_ok (void)
> >> +{
> >> +  return SENTINEL;
> >> +}
> >> +
> >> +static int
> >> +impl_bad (void)
> >> +{
> >> +  return 0;
> >> +}
> >> +
> >> +int
> >> +get_last_seen_sentinel (void)
> >> +{
> >> +  return last_seen_sentinel;
> >> +}
> >> +
> >> +static int (*resolver (void)) (void)
> >> +{
> >> +  int s = sentinel;
> >> +  last_seen_sentinel = s;
> >> +  return s == SENTINEL ? impl_ok : impl_bad;
> >> +}
> >> +int ifunc_tls (void) __attribute__ ((ifunc ("resolver")));
> >> +
> >> +/* Force a non-PLT relocation against the IFUNC symbol.  */
> >> +int (*fptr) (void) = ifunc_tls;
> >> diff --git a/elf/tst-ifunc-tls-init-lib1.c b/elf/tst-ifunc-tls-init-lib1.c
> >> new file mode 100644
> >> index 00000000000..ed9db110b1a
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-init-lib1.c
> >> @@ -0,0 +1 @@
> >> +#include "tst-ifunc-tls-init-lib-skeleton.c"
> >> diff --git a/elf/tst-ifunc-tls-init-lib2.c b/elf/tst-ifunc-tls-init-lib2.c
> >> new file mode 100644
> >> index 00000000000..ed9db110b1a
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-init-lib2.c
> >> @@ -0,0 +1 @@
> >> +#include "tst-ifunc-tls-init-lib-skeleton.c"
> >> diff --git a/elf/tst-ifunc-tls-init.c b/elf/tst-ifunc-tls-init.c
> >> new file mode 100644
> >> index 00000000000..8b996b7c60c
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-init.c
> >> @@ -0,0 +1,81 @@
> >> +/* Check if static-TLS variables are correctly intialized in IFUNC resolvers.
> >> +   Copyright (C) 2026 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
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +/* Checks if a IFUNC resolver sees if a TLS blocker is properly initialized.
> >> +   The tst-ifunc-tls-init-lib.so carries:
> >> +
> >> +   - a thread-local 'sentinel' initialised to SENTINEL.
> >> +   - an IFUNC 'ifunc_tls' whose resolver picks impl_ok when sentinel reads
> >> +     as SENTINEL and impl_bad (returning 0) otherwise.
> >> +   - an IFUNC-backed function-pointer global 'fptr' whose initialiser
> >> +     produces a non-PLT relocation.  */
> >> +
> >> +#include <support/check.h>
> >> +#include <support/xdlfcn.h>
> >> +
> >> +#define SENTINEL 0x5A5A1234
> >> +
> >> +extern int ifunc_tls (void);
> >> +extern int (*fptr) (void);
> >> +extern int get_last_seen_sentinel (void);
> >> +
> >> +static void
> >> +test_tls_ifunc (int (*check_sentinel)(void),
> >> +               int (*check_fptr)(void),
> >> +               int (*check_ifunc_tls)(void))
> >> +{
> >> +  /* 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
> >> +     PLT-resolved function in the DSO, so the read of the diagnostic global
> >> +     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
> >> +do_test (void)
> >> +{
> >> +  test_tls_ifunc (get_last_seen_sentinel, fptr, ifunc_tls);
> >> +
> >> +  /* Same as before, but check the dlopen path.  */
> >> +  void *handle = xdlopen ("tst-ifunc-tls-init-lib2.so",
> >> +                         RTLD_LAZY | RTLD_LOCAL);
> >> +
> >> +  int (*get_last_seen_sentinel_dlopen) (void)
> >> +    = xdlsym (handle, "get_last_seen_sentinel");
> >> +  int (**fptr_dlopen) (void) = xdlsym (handle, "fptr");
> >> +  int (*ifunc_tls_dlopen) (void) = xdlsym (handle, "ifunc_tls");
> >> +
> >> +  test_tls_ifunc (get_last_seen_sentinel_dlopen, *fptr_dlopen,
> >> +                 ifunc_tls_dlopen);
> >> +
> >> +  xdlclose (handle);
> >> +
> >> +  return 0;
> >> +}
> >> +
> >> +#include <support/test-driver.c>
> >> diff --git a/elf/tst-ifunc-tls-write-lib.c b/elf/tst-ifunc-tls-write-lib.c
> >> new file mode 100644
> >> index 00000000000..ef1dff90e01
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-write-lib.c
> >> @@ -0,0 +1,54 @@
> >> +/* Shared library for tst-ifunc-tls-write.
> >> +   Copyright (C) 2026 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
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +/* The DSO defines an initial-exec thread-local 'counter' initialised to
> >> +   SENTINEL, the IFUNC resolver (via the non-PLT IFUNC reloc on 'fptr')
> >> +   overwrites counter with MARKER, and the test then reads counter back
> >> +   through a getter.  */
> >> +
> >> +#define SENTINEL 0x5A5A1234u
> >> +#define MARKER   0x32125A5Au
> >> +
> >> +/* The 'volatile' avoids constant fold optimization in impl_ok.  */
> >> +static volatile __thread unsigned int counter
> >> +  __attribute__ ((tls_model ("initial-exec"))) = SENTINEL;
> >> +
> >> +static unsigned int
> >> +impl (void)
> >> +{
> >> +  return 0;
> >> +}
> >> +
> >> +static unsigned int (*resolver (void)) (void)
> >> +{
> >> +  counter = MARKER;
> >> +  return impl;
> >> +}
> >> +unsigned int ifunc_write (void) __attribute__ ((ifunc ("resolver")));
> >> +
> >> +/* Force the resolver rather than lazy bind on first call, which would
> >> +   re-write counter after the test reads it).  Using a COPY'd fptr also lets
> >> +   the test verify the resolver ran without making a PLT call that would
> >> +   itself fire the resolver again.  */
> >> +unsigned int (*fptr) (void) = ifunc_write;
> >> +
> >> +unsigned int
> >> +get_counter (void)
> >> +{
> >> +  return counter;
> >> +}
> >> diff --git a/elf/tst-ifunc-tls-write.c b/elf/tst-ifunc-tls-write.c
> >> new file mode 100644
> >> index 00000000000..8c3711c161c
> >> --- /dev/null
> >> +++ b/elf/tst-ifunc-tls-write.c
> >> @@ -0,0 +1,34 @@
> >> +/* Check if static-TLS variables are correctly intialized in IFUNC resolvers.
> >> +   Copyright (C) 2026 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
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +#include <support/check.h>
> >> +
> >> +#define MARKER   0x32125A5Au
> >> +
> >> +extern unsigned int (*fptr) (void);
> >> +extern unsigned int get_counter (void);
> >> +
> >> +static int
> >> +do_test (void)
> >> +{
> >> +  TEST_VERIFY (fptr != NULL);
> >> +  TEST_COMPARE (get_counter (), MARKER);
> >> +  return 0;
> >> +}
> >> +
> >> +#include <support/test-driver.c>
> >> --
> >> 2.43.0
> >>
> >
> >
>


-- 
H.J.


More information about the Libc-alpha mailing list