[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