elf: Move post-relocation code of _dl_start into _dl_start_final

On non-PI_STATIC_AND_HIDDEN architectures, getting the address of
_rtld_local_ro (for GLRO (dl_final_object)) goes through a GOT entry.
The GOT load may be reordered before self relocation, leading to an
unrelocated/incorrect _rtld_local_ro address.

84e02af1eb tickled GCC powerpc32 to
reorder the GOT load before relative relocations, leading to ld.so
crash. This is similar to the m68k jump table reordering issue fixed by
a8e9b5b807.

Move code after self relocation into _dl_start_final to avoid the
reordering. This fixes powerpc32 and may help other architectures when
ELF_DYNAMIC_RELOCATE is simplified in the future.
This commit is contained in:
Fangrui Song 2022-04-25 10:30:26 -07:00
parent 33e03f9cd2
commit 1305edd42c

View File

@ -468,6 +468,10 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
{ {
ElfW(Addr) start_addr; ElfW(Addr) start_addr;
/* Do not use an initializer for these members because it would
intefere with __rtld_static_init. */
GLRO (dl_find_object) = &_dl_find_object;
/* If it hasn't happen yet record the startup time. */ /* If it hasn't happen yet record the startup time. */
rtld_timer_start (&start_time); rtld_timer_start (&start_time);
#if !defined DONT_USE_BOOTSTRAP_MAP #if !defined DONT_USE_BOOTSTRAP_MAP
@ -512,7 +516,10 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
print_statistics (RTLD_TIMING_REF(rtld_total_time)); print_statistics (RTLD_TIMING_REF(rtld_total_time));
} }
return start_addr; #ifndef ELF_MACHINE_START_ADDRESS
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
#endif
return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, start_addr);
} }
#ifdef DONT_USE_BOOTSTRAP_MAP #ifdef DONT_USE_BOOTSTRAP_MAP
@ -586,23 +593,11 @@ _dl_start (void *arg)
__rtld_malloc_init_stubs (); __rtld_malloc_init_stubs ();
/* Do not use an initializer for these members because it would
intefere with __rtld_static_init. */
GLRO (dl_find_object) = &_dl_find_object;
{
#ifdef DONT_USE_BOOTSTRAP_MAP #ifdef DONT_USE_BOOTSTRAP_MAP
ElfW(Addr) entry = _dl_start_final (arg); return _dl_start_final (arg);
#else #else
ElfW(Addr) entry = _dl_start_final (arg, &info); return _dl_start_final (arg, &info);
#endif #endif
#ifndef ELF_MACHINE_START_ADDRESS
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
#endif
return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
}
} }