diff options
author | Florian Weimer <fweimer@redhat.com> | 2018-06-06 16:02:02 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2019-04-15 17:39:45 +0200 |
commit | 59c45eeb109a3e4567f2bebe3feb5330d99a392a (patch) | |
tree | 098d597006bdc88499f913eba751b586b1ba26a4 /elf/rtld.c | |
parent | ed8938f4f66e87cd805e0b1b94bab868e8ae0ea3 (diff) | |
download | glibc-59c45eeb109a3e4567f2bebe3feb5330d99a392a.tar.gz glibc-59c45eeb109a3e4567f2bebe3feb5330d99a392a.tar.xz glibc-59c45eeb109a3e4567f2bebe3feb5330d99a392a.zip |
ld.so: Introduce delayed relocation processing fw/bug21242
This makes it possible to use IFUNC resolvers which depend on relocations themselves, as long as these reloctions do not depend on IFUNCs. So far, delayed relocation processing is only implemented for x86-64.
Diffstat (limited to 'elf/rtld.c')
-rw-r--r-- | elf/rtld.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/elf/rtld.c b/elf/rtld.c index 0b07656947..9a14e18db0 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -43,6 +43,7 @@ #include <stap-probe.h> #include <stackinfo.h> #include <not-cancel.h> +#include <dl-delayed-reloc.h> #include <assert.h> @@ -2185,6 +2186,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); _rtld_main_check (main_map, _dl_argv[0]); + /* Used to keep track of delayed IFUNC relocations. */ + struct dl_delayed_reloc_global delayed_relocations; + if (prelinked) { if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) @@ -2236,6 +2240,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); RTLD_TIMING_VAR (start); rtld_timer_start (&start); + + _dl_delayed_reloc_init (&delayed_relocations); + unsigned i = main_map->l_searchlist.r_nlist; while (i-- > 0) { @@ -2315,10 +2322,11 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); rtld_timer_accum (&relocate_time, start); } - /* Activate RELRO protection. In the prelink case, this was already - done earlier. */ + /* Perform delayed IFUNC relocations and activate RELRO protection. + In the prelink case, this was already done earlier. */ if (! prelinked) { + _dl_delayed_reloc_apply (); /* Make sure that this covers the dynamic linker as well. TODO: rtld_multiple_ref is always true because libc.so needs the dynamic linker internally. */ |