diff --git a/csu/libc-start.c b/csu/libc-start.c index 5d9c3675fa..e4ddc2cc1d 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -66,7 +66,7 @@ uintptr_t __pointer_chk_guard_local # endif static void -apply_irel (void) +apply_irel (ElfW(Addr) load_addr) { # ifdef IREL /* We use weak references for these so that we'll still work with a linker @@ -76,7 +76,7 @@ apply_irel (void) extern const IREL_T IPLT_START[] __attribute__ ((weak)); extern const IREL_T IPLT_END[] __attribute__ ((weak)); for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent) - IREL (ipltent); + IREL (ipltent, load_addr); # endif } #endif @@ -141,7 +141,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED - _dl_relocate_static_pie (); + ElfW(Addr) load_addr = _dl_relocate_static_pie (); char **ev = &argv[argc + 1]; @@ -191,7 +191,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), ARCH_INIT_CPU_FEATURES (); /* Perform IREL{,A} relocations. */ - ARCH_SETUP_IREL (); + ARCH_SETUP_IREL (load_addr); /* The stack guard goes into the TCB, so initialize it early. */ ARCH_SETUP_TLS (); diff --git a/csu/static-reloc.c b/csu/static-reloc.c index 38bbb0ff6a..4205387a84 100644 --- a/csu/static-reloc.c +++ b/csu/static-reloc.c @@ -19,8 +19,9 @@ #if ENABLE_STATIC_PIE #include -void +ElfW(Addr) _dl_relocate_static_pie (void) { + return 0; } #endif diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c index 95aee984e8..e7e13e5443 100644 --- a/elf/dl-reloc-static-pie.c +++ b/elf/dl-reloc-static-pie.c @@ -23,7 +23,7 @@ /* Relocate static executable with PIE. */ -void +ElfW(Addr) _dl_relocate_static_pie (void) { struct link_map *main_map = _dl_get_dl_main_map (); @@ -64,5 +64,7 @@ _dl_relocate_static_pie (void) with the run-time address of the r_debug structure */ main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; # endif + + return main_map->l_addr; } #endif diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index a7f6b82da6..2d10245d1f 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1062,7 +1062,7 @@ void __libc_setup_tls (void); # if ENABLE_STATIC_PIE /* Relocate static executable with PIE. */ -extern void _dl_relocate_static_pie (void) attribute_hidden; +extern ElfW(Addr) _dl_relocate_static_pie (void) attribute_hidden; /* Get a pointer to _dl_main_map. */ extern struct link_map * _dl_get_dl_main_map (void) diff --git a/sysdeps/generic/libc-start.h b/sysdeps/generic/libc-start.h index c63849a745..23b6c8168e 100644 --- a/sysdeps/generic/libc-start.h +++ b/sysdeps/generic/libc-start.h @@ -23,7 +23,7 @@ /* By default we perform STT_GNU_IFUNC resolution *before* TLS initialization, and this means you cannot, without machine knowledge, access TLS from an IFUNC resolver. */ -#define ARCH_SETUP_IREL() apply_irel () +#define ARCH_SETUP_IREL(load_addr) apply_irel ((load_addr)) #define ARCH_SETUP_TLS() __libc_setup_tls () #define ARCH_APPLY_IREL() #endif /* ! SHARED */ diff --git a/sysdeps/mach/hurd/libc-start.h b/sysdeps/mach/hurd/libc-start.h index d907003551..cb1a3ba438 100644 --- a/sysdeps/mach/hurd/libc-start.h +++ b/sysdeps/mach/hurd/libc-start.h @@ -23,7 +23,7 @@ /* By default we perform STT_GNU_IFUNC resolution *before* TLS initialization, and this means you cannot, without machine knowledge, access TLS from an IFUNC resolver. */ -#define ARCH_SETUP_IREL() apply_irel () +#define ARCH_SETUP_IREL(load_addr) apply_irel ((load_addr)) #define ARCH_SETUP_TLS() #define ARCH_APPLY_IREL() #endif /* ! SHARED */ diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.h b/sysdeps/unix/sysv/linux/powerpc/libc-start.h index a5563f6815..ed4e710580 100644 --- a/sysdeps/unix/sysv/linux/powerpc/libc-start.h +++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.h @@ -22,7 +22,7 @@ #ifndef SHARED /* IREL{,A} must happen after TCB initialization in order to allow IFUNC resolvers to read TCB fields, e.g. hwcap and at_platform. */ -#define ARCH_SETUP_IREL() +#define ARCH_SETUP_IREL(load_addr) #define ARCH_SETUP_TLS() __libc_setup_tls () #define ARCH_APPLY_IREL() apply_irel () #endif /* ! SHARED */ diff --git a/sysdeps/x86/libc-start.h b/sysdeps/x86/libc-start.h index c76b1d917f..88bda474ba 100644 --- a/sysdeps/x86/libc-start.h +++ b/sysdeps/x86/libc-start.h @@ -17,7 +17,7 @@ . */ #ifndef SHARED -# define ARCH_SETUP_IREL() apply_irel () +# define ARCH_SETUP_IREL(load_addr) apply_irel ((load_addr)) # define ARCH_APPLY_IREL() # ifndef ARCH_SETUP_TLS # define ARCH_SETUP_TLS() __libc_setup_tls () diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h index b28a3c2bf3..bc9d1b8bf8 100644 --- a/sysdeps/x86_64/dl-irel.h +++ b/sysdeps/x86_64/dl-irel.h @@ -34,14 +34,14 @@ elf_ifunc_invoke (ElfW(Addr) addr) static inline void __attribute ((always_inline)) -elf_irela (const ElfW(Rela) *reloc) +elf_irela (const ElfW(Rela) *reloc, ElfW(Addr) load_addr) { - ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset; + ElfW(Addr) *const reloc_addr = (void *) (reloc->r_offset + load_addr); const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info); if (__glibc_likely (r_type == R_X86_64_IRELATIVE)) { - ElfW(Addr) value = elf_ifunc_invoke(reloc->r_addend); + ElfW(Addr) value = elf_ifunc_invoke(reloc->r_addend + load_addr); *reloc_addr = value; } else