rtld.c has
extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
...
_dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start;
_dl_rtld_map.l_map_end = (ElfW(Addr)) _end;
As
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120653
shows, compiler may generate run-time relocation on __ehdr_start with
movq .LC0(%rip), %xmm0
...
.section .data.rel.ro.local,"aw"
.align 8
.LC0:
.quad __ehdr_start
This won't work before run-time relocation is finished in rtld.c. Add
optimization barrier to prevent run-time relocations against __ehdr_start
and _end.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
_dl_setup_hash (&_dl_rtld_map);
_dl_rtld_map.l_real = &_dl_rtld_map;
_dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start;
+ /* Prevent run-time relocations against __ehdr_start and _end. */
+ asm ("" : "+g" (_dl_rtld_map.l_map_start));
_dl_rtld_map.l_map_end = (ElfW(Addr)) _end;
+ asm ("" : "+g" (_dl_rtld_map.l_map_end));
/* Copy the TLS related data if necessary. */
#ifndef DONT_USE_BOOTSTRAP_MAP
# if NO_TLS_OFFSET != 0
endif
test-internal-extras += tst-gnu2-tls2mod1
+
+tests-special += $(objpfx)check-rtld.out
+
+$(objpfx)rtld.reloc: $(objpfx)rtld.os
+ @rm -f $@T
+ LC_ALL=C $(READELF) -rW $< > $@T
+ test -s $@T
+ mv -f $@T $@
+common-generated += $(objpfx)rtld.reloc
+
+# Verify that there are no run-time relocations against __ehdr_start nor
+# _end.
+$(objpfx)check-rtld.out: $(objpfx)rtld.reloc
+ LC_ALL=C; \
+ if grep -E "R_X86_64_64.*(__ehdr_start|_end)" $^ > $@; \
+ then false; else true; fi; \
+ $(evaluate-test)
+generated += check-rtld.out
endif # $(subdir) == elf
ifeq ($(subdir),csu)