[PATCH v2 2/2] elf: Use the effective lazy mode for the deferred IRELATIVE pass

Sam James sam@gentoo.org
Sat Aug 8 01:52:06 GMT 2026


Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:

> The 63b31c05a8a split relocation processing must agree for the lazy
> flag, a mistamatch would change the .rel.plt handling.

mismatch

>
> This is not an issue for any port currently, but on hppa it may return
> a different value: if hppa implements IFUNC support, the second pass would
> route PLT entries to its empty lazy handler and leave the descriptors
> unrelocated, silently.
>
> Make ELF_DYNAMIC_RELOCATE_PASS take lazy as an int lvalue and store the
> effective mode back into it, so the DL_RELOC_IRELATIVE call reuses the
> same variable instead of a separately threaded copy.  The two passes can no
> longer disagree about the partitioning.  elf_machine_runtime_setup has side
> effects, so it must stay a single call.
>
> Checked on x86_64-linux-gnu, and built for all supported architectures.

Reviewed-by: Sam James <sam@gentoo.org>

> ---
>  elf/dl-reloc-static-pie.c | 12 +++++++++---
>  elf/dl-reloc.c            |  5 +++--
>  elf/dynamic-link.h        | 34 ++++++++++++++++++++++------------
>  3 files changed, 34 insertions(+), 17 deletions(-)
>
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 5dc5a545a8d..a3d984f6020 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -79,8 +79,12 @@ _dl_relocate_static_pie (void)
>  # endif
>  
>    /* Relocate ourselves so we can do normal function calls and data access
> -     using the global offset table.  IRELATIVE entries are deferred.  */
> -  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, main_map, NULL, 0, 0, 0);
> +     using the global offset table.  IRELATIVE entries are deferred.
> +     Lazy binding is never used here, so edr_lazy comes back as 0 and the
> +     deferred pass can hardcode the same value.  */
> +  int edr_lazy = 0;
> +  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, main_map, NULL, edr_lazy,
> +			     0, 0);
>  
>    /* Initialize _r_debug_extended.  */
>    struct r_debug *r = _dl_debug_initialize (0, LM_ID_BASE);
> @@ -98,7 +102,9 @@ void
>  _dl_relocate_static_pie_ifunc (void)
>  {
>    struct link_map *main_map = _dl_get_dl_main_map ();
> -  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, main_map, NULL, 0, 0, 0);
> +  int edr_lazy = 0;
> +  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, main_map, NULL, edr_lazy,
> +			     0, 0);
>    main_map->l_relocated = 1;
>  }
>  #endif
> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> index fa2f41ac445..bed0c4f844a 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_PASS (DL_RELOC_NORMAL, l, scope, lazy,
> +    int edr_lazy = lazy;
> +    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_NORMAL, l, scope, edr_lazy,
>  			       consider_profiling, skip_ifunc);
>  
>  #ifdef SHARED
> @@ -292,7 +293,7 @@ _dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
>        _dl_init_static_tls (l);
>  #endif
>  
> -    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, l, scope, lazy,
> +    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_IRELATIVE, l, scope, edr_lazy,
>  			       0, skip_ifunc);
>  
>      if ((consider_profiling || consider_symbind)
> diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
> index 0130c63feb1..81a3f0856e0 100644
> --- a/elf/dynamic-link.h
> +++ b/elf/dynamic-link.h
> @@ -235,29 +235,39 @@ enum elf_dynamic_reloc_pass
>     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.  */
> +   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.
> +
> +   LAZY must be an int lvalue.  elf_machine_runtime_setup may downgrade the
> +   requested mode (currently only hppa, when it cannot install the lazy
> +   trampoline) and it has side effects, so it must run exactly once (the
> +   effective mode is stored back into LAZY).  A later DL_RELOC_IRELATIVE
> +   call must be handed that same lvalue, so that both passes partition the
> +   relocation ranges identically.  */
>  # 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));	      \
> +	(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));	      \
> +    ELF_DYNAMIC_DO_REL ((map), (scope), (lazy), skip_ifunc, (pass));	      \
> +    ELF_DYNAMIC_DO_RELA ((map), (scope), (lazy), skip_ifunc, (pass));	      \
>      if ((pass) != DL_RELOC_IRELATIVE)					      \
> -      ELF_DYNAMIC_AFTER_RELOC ((map), edr_lazy);			      \
> +      ELF_DYNAMIC_AFTER_RELOC ((map), (lazy));				      \
>    } while (0)
>  
> -/* Run both passes back to back, for callers with nothing to interleave.  */
> +/* Run both passes back to back, for callers with nothing to interleave.
> +   Unlike ELF_DYNAMIC_RELOCATE_PASS, LAZY need not be an lvalue.  */
>  # define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
> -  ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_ALL, (map), (scope), (lazy),	      \
> -			     (consider_profile), skip_ifunc)
> +  do {									      \
> +    int edr_lazy = (lazy);						      \
> +    ELF_DYNAMIC_RELOCATE_PASS (DL_RELOC_ALL, (map), (scope), edr_lazy,	      \
> +			       (consider_profile), skip_ifunc);		      \
> +  } while (0)
>  
>  #endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 418 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260808/8ae93f0f/attachment.sig>


More information about the Libc-alpha mailing list