https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120653

--- Comment #15 from Florian Weimer <fw at gcc dot gnu.org> ---
Jakub, thanks for the really helpful analysis!

In glibc, we do additional gymnastics to self-relocate the dynamic linker
earlier, with a compiler barrier, but only for HIDDEN_VAR_NEEDS_DYNAMIC_RELOC
architectures (like MIPS)—not for x86-64. I admit that this is not entirely
correct because GCC can materialize constants that require relocation into
global data. This happens in the Fedora 42 build as well, for the rfv constant
in dl_vdso_vsym in sysdeps/unix/sysv/linux/dl-vdso.h:

  const struct r_found_version rfv = { VDSO_NAME, VDSO_HASH, 1, NULL };

  /* Search the scope of the vdso map.  */
  const ElfW (Sym) *ref = &wsym;
  lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref,
                                               map->l_local_scope,
                                               &rfv, 0, 0, NULL);
  return ref != NULL ? DL_SYMBOL_ADDRESS (result, ref) : NULL;

It just so happens that the first call to dl_vdso_vsym happens after the call
to ELF_DYNAMIC_RELOCATE for ld.so, which is why this works. But the entire
design really assumes that the ELF_DYNAMIC_RELOCATE call is a no-op.

So maybe we are just naïve, and need to treat all architectures as
HIDDEN_VAR_NEEDS_DYNAMIC_RELOC? Or get real, remove the ELF_DYNAMIC_RELOCATE
call for ld.so on !HIDDEN_VAR_NEEDS_DYNAMIC_RELOC architectures because it
should do nothing at all, and add a test case that requires that there are no
dynamic relocations whatsoever. But it looks like the latter would require a
way to request that GCC does not produce global data constants (with
relocations) for initializing local variables.

Reply via email to