about summary refs log tree commit diff
path: root/elf/rtld.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2018-06-06 16:02:02 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-04-15 17:39:45 +0200
commit59c45eeb109a3e4567f2bebe3feb5330d99a392a (patch)
tree098d597006bdc88499f913eba751b586b1ba26a4 /elf/rtld.c
parented8938f4f66e87cd805e0b1b94bab868e8ae0ea3 (diff)
downloadglibc-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.c12
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.  */