Re: [PATCH v2 1/2] elf: Honour skip_ifunc for cross-object IFUNC relocations [BZ #34428]

Sam James <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Organization Gentoo
Message-ID <[email protected]>
Adhemerval Zanella <[email protected]> writes:

> Commit 63b31c05a8a ("elf: Defer all IRELATIVE relocations until after PLT
> setup") dropped the skip_ifunc argument from elf_dynamic_do_Rel, assuming
> the new deferred elf_dynamic_do_Rel_irelative pass handles every relocation
> that may run an IFUNC resolver.  That only holds for IFUNC symbols defined
> in the object being relocated: a reference to an IFUNC in another object is
> an ordinary JMP_SLOT or GLOB_DAT against an undefined symbol, and its IFUNC
> nature is only known after symbol resolution inside elf_machine_rel.  Those
> relocations stay in the regular pass, which no longer propagated
> skip_ifunc, so __RTLD_NOIFUNC was ignored for them.
>
> ldd -u forces non-lazy binding (GLRO(dl_lazy) = 0 for DL_DEBUG_UNUSED), so
> the resolver was called and the diagnostic emitted:
>
>   $ ldd -u /bin/ls
>   /bin/ls: Relink `' with `/usr/lib64/libc.so.6' for IFUNC symbol `__mempcpy_chk'
>
> ldd -r with LD_BIND_NOW is affected in the same way.
>
> Restore the skip_ifunc parameter and thread it through _ELF_DYNAMIC_DO_RELOC.
>
> This new semantic shows that ELF_DYNAMIC_RELOCATE_NOIFUNC naming is misleading
> (it reads as "do not process IFUNC", yet it takes a skip_ifunc
> argument). Replace it to:
>
>   DL_RELOC_BOTH     -> DL_RELOC_ALL
>   DL_RELOC_NOIFUNC  -> DL_RELOC_NORMAL
>   DL_RELOC_IFUNC    -> DL_RELOC_IRELATIVE
>
> ELF_DYNAMIC_RELOCATE_NOIFUNC and ELF_DYNAMIC_RELOCATE_IFUNC become a single
> ELF_DYNAMIC_RELOCATE_PASS taking the pass as its first argument, and
> ELF_DYNAMIC_DO_REL/ELF_DYNAMIC_DO_RELA take the pass instead of having three
> near-identical variants each.
>
> Checked on x86_64-linux-gnu, and built for all supported architectures.

Sorry for delay, I'd missed v2 was sent. It looks good (only real issue
I had w/ v1 was the name).

Reviewed-by: Sam James <[email protected]>

> ---
>  elf/Makefile                      |  28 +++++++
>  elf/dl-reloc-static-pie.c         |   4 +-
>  elf/dl-reloc.c                    |   6 +-
>  elf/do-rel.h                      |  24 ++++--
>  elf/dynamic-link.h                | 117 +++++++++++++-----------------
>  elf/tst-ifunc-fault-dep-bindnow.c |  19 +++++
>  elf/tst-ifunc-fault-dep-lazy.c    |  27 +++++++
>  elf/tst-ifunc-fault-mod.c         |  38 ++++++++++
>  8 files changed, 186 insertions(+), 77 deletions(-)
>  create mode 100644 elf/tst-ifunc-fault-dep-bindnow.c
>  create mode 100644 elf/tst-ifunc-fault-dep-lazy.c
>  create mode 100644 elf/tst-ifunc-fault-mod.c
>
> diff --git a/elf/Makefile b/elf/Makefile
> index 94c5b7e6ed8..6cfb1b5cf30 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1396,6 +1396,13 @@ modules-names += \
>    tst-ifunc-tls-write-lib \
>    tst-tls-tdata-reloc-lib \
>    # modules-names
> +ifeq (yes,$(have-gcc-ifunc))
> +tests += \
> +  tst-ifunc-fault-dep-bindnow \
> +  tst-ifunc-fault-dep-lazy \
> +  # tests
> +modules-names += tst-ifunc-fault-mod
> +endif
>  ifneq (no,$(have-test-mtls-descriptor))
>  tests += tst-ifunc-tls-init-tlsdesc
>  modules-names += tst-ifunc-tls-init-tlsdesc-lib
> @@ -2545,6 +2552,27 @@ $(objpfx)tst-ifunc-fault-bindnow.out: $(objpfx)tst-ifunc-fault-bindnow \
>     $(objpfx)ld.so
>  	$(tst-ifunc-fault-script)
>  
> +LDFLAGS-tst-ifunc-fault-dep-lazy = -Wl,-z,lazy
> +LDFLAGS-tst-ifunc-fault-dep-bindnow = -Wl,-z,now
> +define tst-ifunc-fault-dep-script
> +( $(test-wrapper) $(rtld-prefix) --verify $< \
> +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 $(rtld-prefix) $< \
> +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 LD_DEBUG=unused \
> +			 $(rtld-prefix) $< \
> +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 LD_WARN=yes LD_BIND_NOW=1 \
> +			 $(rtld-prefix) $< \
> +) > $@; $(evaluate-test)
> +endef
> +$(objpfx)tst-ifunc-fault-dep-lazy: $(objpfx)tst-ifunc-fault-mod.so
> +$(objpfx)tst-ifunc-fault-dep-bindnow: $(objpfx)tst-ifunc-fault-mod.so
> +$(objpfx)tst-ifunc-fault-dep-lazy.out: $(objpfx)tst-ifunc-fault-dep-lazy \
> +   $(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
> +	$(tst-ifunc-fault-dep-script)
> +$(objpfx)tst-ifunc-fault-dep-bindnow.out: \
> +   $(objpfx)tst-ifunc-fault-dep-bindnow \
> +   $(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
> +	$(tst-ifunc-fault-dep-script)
> +
>  LDFLAGS-tst-ifunc-plt-lib.so = -Wl,-z,lazy
>  
>  tst-ifunc-plt-bindnow-ENV = LD_BIND_NOW=1
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 8463e46147d..5dc5a545a8d 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -80,7 +80,7 @@ _dl_relocate_static_pie (void)
>  
>    /* Relocate ourselves so we can do normal function calls and data access
>       using the global offset table.  IRELATIVE entries are deferred.  */
> -  ELF_DYNAMIC_RELOCATE_NOIFUNC (main_map, NULL, 0, 0);
> +  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, main_map, NULL, 0, 0, 0);
>  
>    /* Initialize _r_debug_extended.  */
>    struct r_debug *r = _dl_debug_initialize (0, LM_ID_BASE);
> @@ -98,7 +98,7 @@ void
>  _dl_relocate_static_pie_ifunc (void)
>  {
>    struct link_map *main_map = _dl_get_dl_main_map ();
> -  ELF_DYNAMIC_RELOCATE_IFUNC (main_map, NULL, 0, 0);
> +  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, main_map, NULL, 0, 0, 0);
>    main_map->l_relocated = 1;
>  }
>  #endif
> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> index 15a6a4cffef..fa2f41ac445 100644
> --- a/elf/dl-reloc.c
> +++ b/elf/dl-reloc.c
> @@ -278,7 +278,8 @@ _dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
>         IFUNC resolvers.  Without this, a resolver would see the unrelocated
>         initialiser bytes that were placed into the slot by the early
>         _dl_allocate_tls_init.  */
> -    ELF_DYNAMIC_RELOCATE_NOIFUNC (l, scope, lazy, consider_profiling);
> +    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, l, scope, lazy,
> +			       consider_profiling, skip_ifunc);
>  
>  #ifdef SHARED
>      /* Re-initialise the static TLS slot with the .tdata so the IRELATIVE
> @@ -291,7 +292,8 @@ _dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
>        _dl_init_static_tls (l);
>  #endif
>  
> -    ELF_DYNAMIC_RELOCATE_IFUNC (l, scope, lazy, skip_ifunc);
> +    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, l, scope, lazy,
> +			       0, skip_ifunc);
>  
>      if ((consider_profiling || consider_symbind)
>  	&& l->l_info[DT_PLTRELSZ] != NULL)
> diff --git a/elf/do-rel.h b/elf/do-rel.h
> index 77022447348..c610d12dbeb 100644
> --- a/elf/do-rel.h
> +++ b/elf/do-rel.h
> @@ -79,17 +79,23 @@ elf_dynamic_Rel_audit_symbind (struct link_map *map,
>  /* Perform the relocations in MAP on the running program image as specified
>     by RELTAG, SZTAG.  If LAZY is nonzero, this is the first pass on PLT
>     relocations; they should be set up to call _dl_runtime_resolve, rather
> -   than fully resolved now.
> +   than fully resolved now.  If SKIP_IFUNC is nonzero no IFUNC resolver is
> +   called; this is required for the trace modes (ldd -u / ldd -r), which
> +   relocate objects.
>  
> -   IRELATIVE entries are always skipped (non-bootstrap); they are handled
> +   IRELATIVE entries and relocations against an STT_GNU_IFUNC symbol defined
> +   in MAP itself are always skipped (non-bootstrap); they are handled
>     separately by elf_dynamic_do_Rel_irelative after all other relocations
> -   for both .rel.dyn and .rel.plt have been processed.  */
> +   for both .rel.dyn and .rel.plt have been processed.  Relocations against
> +   an IFUNC symbol defined in *another* object are not deferred, since the
> +   IFUNC symbol is only known after symbol resolution, and the defining object
> +   has already been relocated at this point.  */
>  
>  static inline void __attribute__ ((always_inline))
>  elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
>  		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
>  		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
> -		    int lazy)
> +		    int lazy, int skip_ifunc)
>  {
>    const ElfW(Rel) *relative = (const void *) reladdr;
>    const ElfW(Rel) *r = relative + nrelative;
> @@ -111,7 +117,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
>        void *const r_addr_arg = (void *) (l_addr + r->r_offset);
>        const struct r_found_version *rversion = &map->l_versions[ndx];
>  
> -      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, 0);
> +      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, skip_ifunc);
>      }
>  #else /* !RTLD_BOOTSTRAP */
>  #if !defined DO_RELA || !defined ELF_MACHINE_PLT_REL
> @@ -126,7 +132,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
>  	  const ElfW (Sym) *sym = &symtab[ELFW (R_SYM) (r->r_info)];
>  	  if (elf_dynamic_is_Rel_irelative (r, sym))
>  	    continue;
> -	  elf_machine_lazy_rel (map, scope, l_addr, r, 0);
> +	  elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
>  	}
>      }
>    else
> @@ -158,7 +164,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
>  
>  	      if (elf_dynamic_is_Rel_irelative (r, sym))
>  		continue;
> -	      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, 0);
> +	      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
> +			       skip_ifunc);
>  	      elf_dynamic_Rel_audit_symbind (map, scope, r, sym, rversion,
>  					     r_addr_arg);
>  	    }
> @@ -172,7 +179,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
>  
>  	      if (elf_dynamic_is_Rel_irelative (r, sym))
>  		continue;
> -	      elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg, 0);
> +	      elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
> +			       skip_ifunc);
>  	      elf_dynamic_Rel_audit_symbind (map, scope, r, sym, NULL,
>  					     r_addr_arg);
>  	    }
> diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
> index 35141acec4b..0130c63feb1 100644
> --- a/elf/dynamic-link.h
> +++ b/elf/dynamic-link.h
> @@ -78,18 +78,23 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
>     consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
>     are completely separate and there is a gap between them.  */
>  
> -/* This controls which sub-passes _ELF_DYNAMIC_DO_RELOC runs.  Used to
> -   interleave TLS / stack-protector setup between the two passes so IFUNC
> -   resolvers see a fully-initialised TCB.  */
> -enum elf_dynamic_reloc_phase
> +/* Selects which relocations a pass processes.  Splitting them allows the
> +   caller to interleave TLS / stack-protector setup between the two passes,
> +   so IFUNC resolvers see a fully-initialised TCB.
> +
> +   This is orthogonal to the skip_ifunc argument, which says whether an IFUNC
> +   resolver may be run at all and is honoured by every pass.  In particular
> +   DL_RELOC_NORMAL also runs IFUNC resolvers, for relocations against an
> +   IFUNC symbol defined in another object.  */
> +enum elf_dynamic_reloc_pass
>  {
> -  DL_RELOC_BOTH     = 0,  /* Non-IRELATIVE pass then IRELATIVE pass.  */
> -  DL_RELOC_NOIFUNC  = 1,  /* Non-IRELATIVE pass only.  */
> -  DL_RELOC_IFUNC    = 2,  /* IRELATIVE pass only.  */
> +  DL_RELOC_ALL	     = 0, /* Non-IRELATIVE relocations, then IRELATIVE.  */
> +  DL_RELOC_NORMAL    = 1, /* Non-IRELATIVE relocations only.  */
> +  DL_RELOC_IRELATIVE = 2, /* IRELATIVE relocations only.  */
>  };
>  
>  # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, \
> -			       test_rel, phase)				      \
> +			       test_rel, pass)				      \
>    do {									      \
>      struct { ElfW(Addr) start, size;					      \
>  	     __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; }  \
> @@ -136,14 +141,15 @@ enum elf_dynamic_reloc_phase
>  	 by the linker.  */						      \
>        if (!DO_RTLD_BOOTSTRAP)						      \
>  	{								      \
> -	  if ((phase) != DL_RELOC_IFUNC)				      \
> +	  if ((pass) != DL_RELOC_IRELATIVE)				      \
>  	    for (int ranges_index = 0; ranges_index < 2; ++ranges_index)      \
>  	      elf_dynamic_do_##reloc ((map), scope,			      \
>  				      ranges[ranges_index].start,	      \
>  				      ranges[ranges_index].size,	      \
>  				      ranges[ranges_index].nrelative,	      \
> -				      ranges[ranges_index].lazy);	      \
> -	  if ((phase) != DL_RELOC_NOIFUNC)				      \
> +				      ranges[ranges_index].lazy,	      \
> +				      skip_ifunc);			      \
> +	  if ((pass) != DL_RELOC_NORMAL)				      \
>  	    for (int ranges_index = 0; ranges_index < 2; ++ranges_index)      \
>  	      elf_dynamic_do_##reloc##_irelative ((map), scope,		      \
>  						  ranges[ranges_index].start, \
> @@ -158,7 +164,8 @@ enum elf_dynamic_reloc_phase
>  				  ranges[ranges_index].start,		      \
>  				  ranges[ranges_index].size,		      \
>  				  ranges[ranges_index].nrelative,	      \
> -				  ranges[ranges_index].lazy);		      \
> +				  ranges[ranges_index].lazy,		      \
> +				  skip_ifunc);				      \
>    } while (0)
>  
>  # if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
> @@ -169,37 +176,21 @@ enum elf_dynamic_reloc_phase
>  
>  # if ! ELF_MACHINE_NO_REL
>  #  include "do-rel.h"
> -#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc)	      \
> +#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc, pass)      \
>    _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc,      \
> -			 _ELF_CHECK_REL, DL_RELOC_BOTH)
> -#  define ELF_DYNAMIC_DO_REL_NOIFUNC(map, scope, lazy)		      \
> -  _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, 0,		      \
> -			 _ELF_CHECK_REL, DL_RELOC_NOIFUNC)
> -#  define ELF_DYNAMIC_DO_REL_IFUNCONLY(map, scope, lazy, skip_ifunc)  \
> -  _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc,      \
> -			 _ELF_CHECK_REL, DL_RELOC_IFUNC)
> +			 _ELF_CHECK_REL, pass)
>  # else
> -#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do.  */
> -#  define ELF_DYNAMIC_DO_REL_NOIFUNC(map, scope, lazy) /* Nothing to do.  */
> -#  define ELF_DYNAMIC_DO_REL_IFUNCONLY(map, scope, lazy, skip_ifunc) /* Nothing.  */
> +#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc, pass) /* Nothing.  */
>  # endif
>  
>  # if ! ELF_MACHINE_NO_RELA
>  #  define DO_RELA
>  #  include "do-rel.h"
> -#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc)	      \
> +#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc, pass)     \
>    _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc,    \
> -			 _ELF_CHECK_REL, DL_RELOC_BOTH)
> -#  define ELF_DYNAMIC_DO_RELA_NOIFUNC(map, scope, lazy)		      \
> -  _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, 0,	      \
> -			 _ELF_CHECK_REL, DL_RELOC_NOIFUNC)
> -#  define ELF_DYNAMIC_DO_RELA_IFUNCONLY(map, scope, lazy, skip_ifunc) \
> -  _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc,    \
> -			 _ELF_CHECK_REL, DL_RELOC_IFUNC)
> +			 _ELF_CHECK_REL, pass)
>  # else
> -#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do.  */
> -#  define ELF_DYNAMIC_DO_RELA_NOIFUNC(map, scope, lazy) /* Nothing to do.  */
> -#  define ELF_DYNAMIC_DO_RELA_IFUNCONLY(map, scope, lazy, skip_ifunc) /* Nothing.  */
> +#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc, pass) /* Nothing.  */
>  # endif
>  
>  # define ELF_DYNAMIC_DO_RELR(map)					      \
> @@ -240,37 +231,33 @@ enum elf_dynamic_reloc_phase
>  # else
>  #  define DO_RTLD_BOOTSTRAP 0
>  # endif
> +/* Perform one relocation pass over MAP.  PASS selects which relocations are
> +   processed.  It is orthogonal to SKIP_IFUNC, which suppresses running IFUNC
> +   resolvers in whichever pass is selected.
> +
> +   Unless PASS is DL_RELOC_IRELATIVE, this also performs the machine-specific
> +   PLT/GOT setup, the DT_RELR relocations, and the ELF_DYNAMIC_AFTER_RELOC
> +   hook.  */
> +# define ELF_DYNAMIC_RELOCATE_PASS(pass, map, scope, lazy, consider_profile,  \
> +				   skip_ifunc)				      \
> +  do {									      \
> +    int edr_lazy = (lazy);						      \
> +    if ((pass) != DL_RELOC_IRELATIVE)					      \
> +      {									      \
> +	edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy),	      \
> +					      (consider_profile));	      \
> +	if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP)		      \
> +	  ELF_DYNAMIC_DO_RELR (map);					      \
> +      }									      \
> +    ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc, (pass));	      \
> +    ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc, (pass));	      \
> +    if ((pass) != DL_RELOC_IRELATIVE)					      \
> +      ELF_DYNAMIC_AFTER_RELOC ((map), edr_lazy);			      \
> +  } while (0)
> +
> +/* Run both passes back to back, for callers with nothing to interleave.  */
>  # define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
> -  do {									      \
> -    int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy),	      \
> -					      (consider_profile));	      \
> -    if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP)			      \
> -      ELF_DYNAMIC_DO_RELR (map);					      \
> -    ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc);		      \
> -    ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc);		      \
> -    ELF_DYNAMIC_AFTER_RELOC ((map), (edr_lazy));			      \
> -  } while (0)
> -
> -/* Like ELF_DYNAMIC_RELOCATE but only processes the non-IRELATIVE pass.
> -   The IRELATIVE pass must be completed later via ELF_DYNAMIC_RELOCATE_IFUNC.
> -   Used by the static-pie startup so the TCB and stack-protector canary can
> -   be initialised between the two passes.  */
> -# define ELF_DYNAMIC_RELOCATE_NOIFUNC(map, scope, lazy, consider_profile)     \
> -  do {									      \
> -    int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy),	      \
> -					      (consider_profile));	      \
> -    if (!is_rtld_link_map (map) || DO_RTLD_BOOTSTRAP)			      \
> -      ELF_DYNAMIC_DO_RELR (map);					      \
> -    ELF_DYNAMIC_DO_REL_NOIFUNC ((map), (scope), edr_lazy);		      \
> -    ELF_DYNAMIC_DO_RELA_NOIFUNC ((map), (scope), edr_lazy);		      \
> -    ELF_DYNAMIC_AFTER_RELOC ((map), (edr_lazy));			      \
> -  } while (0)
> -
> -/* IRELATIVE-only companion to ELF_DYNAMIC_RELOCATE_NOIFUNC.  */
> -# define ELF_DYNAMIC_RELOCATE_IFUNC(map, scope, lazy, skip_ifunc)	      \
> -  do {									      \
> -    ELF_DYNAMIC_DO_REL_IFUNCONLY ((map), (scope), (lazy), skip_ifunc);	      \
> -    ELF_DYNAMIC_DO_RELA_IFUNCONLY ((map), (scope), (lazy), skip_ifunc);	      \
> -  } while (0)
> +  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_ALL, (map), (scope), (lazy),	      \
> +			     (consider_profile), skip_ifunc)
>  
>  #endif
> diff --git a/elf/tst-ifunc-fault-dep-bindnow.c b/elf/tst-ifunc-fault-dep-bindnow.c
> new file mode 100644
> index 00000000000..60d97dcaa44
> --- /dev/null
> +++ b/elf/tst-ifunc-fault-dep-bindnow.c
> @@ -0,0 +1,19 @@
> +/* Program calling an IFUNC defined in a dependency.  BIND_NOW variant.
> +   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 "tst-ifunc-fault-dep-lazy.c"
> diff --git a/elf/tst-ifunc-fault-dep-lazy.c b/elf/tst-ifunc-fault-dep-lazy.c
> new file mode 100644
> index 00000000000..122d33f391e
> --- /dev/null
> +++ b/elf/tst-ifunc-fault-dep-lazy.c
> @@ -0,0 +1,27 @@
> +/* Program calling an IFUNC defined in a dependency (BZ 34428).
> +   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/>.  */
> +
> +extern void magic (void);
> +
> +int
> +main (void)
> +{
> +  /* JMP_SLOT relocation against an undefined symbol.  */
> +  magic ();
> +  return 1;
> +}
> diff --git a/elf/tst-ifunc-fault-mod.c b/elf/tst-ifunc-fault-mod.c
> new file mode 100644
> index 00000000000..11c21b48ac4
> --- /dev/null
> +++ b/elf/tst-ifunc-fault-mod.c
> @@ -0,0 +1,38 @@
> +/* Shared object exporting an IFUNC symbol with a resolver which crashes.
> +   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 <stddef.h>
> +
> +static void
> +implementation (void)
> +{
> +  /* Produce a crash, without depending on any relocations.  */
> +  volatile char *volatile p = NULL;
> +  *p = 0;
> +}
> +
> +static __typeof__ (implementation) *
> +resolver (void)
> +{
> +  /* Produce a crash, without depending on any relocations.  */
> +  volatile char *volatile p = NULL;
> +  *p = 0;
> +  return implementation;
> +}
> +
> +void magic (void) __attribute__ ((ifunc ("resolver")));
signature.asc (application/pgp-signature, 418 B)
-----BEGIN PGP SIGNATURE-----

iQEBBAEWCgCpFiEEJaa7iN2bdkxrVUHCc4QJ9SDfkZAFAmp2i3sbFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMiwyXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25z
Lm9wZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQyNUE2QkI4OEREOUI3NjRDNkI1NTQx
QzI3Mzg0MDlGNTIwREY5MTkwDxxzYW1AZ2VudG9vLm9yZwAKCRBzhAn1IN+RkGpG
AP9Q0oLBfEyaBMvUzpbBSJAiamw8j8iQ8yb19/i/D4L6SwD/fAdiNihUzqYXEZrS
lwbzuSc1o24xBPkrMYqN4/R8sgw=
=exaS
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.