[glibc] elf: Use the effective lazy mode for the deferred IRELATIVE pass
Adhemerval Zanella via Glibc-cvs <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=16ad6a15393e2490f02bded0e0829b626ea02a29 commit 16ad6a15393e2490f02bded0e0829b626ea02a29 Author: Adhemerval Zanella <[email protected]> Date: Mon Aug 3 11:02:54 2026 -0300 elf: Use the effective lazy mode for the deferred IRELATIVE pass The 63b31c05a8a split relocation processing must agree for the lazy flag, a mismatch would change the .rel.plt handling. 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 <[email protected]> Diff: --- 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 5dc5a545a8..a3d984f602 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 6170d8689f..8077f90167 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -336,7 +336,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 @@ -350,7 +351,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 0130c63feb..81a3f0856e 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