[v2,2/2] riscv: Initialize $gp before resolving the IRELATIVE relocation

Message ID 1608023800-14560-3-git-send-email-vincent.chen@sifive.com
State Committed
Commit 313bfd505e7c6a70c508ba9b2e2c0ff6e901c2a0
Headers
Series riscv: add support for GNU indirect function |

Commit Message

Vincent Chen Dec. 15, 2020, 9:16 a.m. UTC
  The $gp register may be used to access the global variable in
the PDE program, so the $gp register should be initialized before
executing the IFUNC resolver of PDE program to avoid unexpected
error occurs.
---
 sysdeps/riscv/dl-machine.h | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)
  

Patch

diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
index 0ae45dd0c3..211835f0e6 100644
--- a/sysdeps/riscv/dl-machine.h
+++ b/sysdeps/riscv/dl-machine.h
@@ -339,8 +339,28 @@  elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
       gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve;
       gotplt[1] = (ElfW(Addr)) l;
     }
-#endif
 
+  if (l->l_type == lt_executable)
+    {
+      /* The __global_pointer$ may not be defined by the linker if the
+	 $gp register does not be used to access the global variable
+	 in the executable program. Therefore, the search symbol is
+	 set to a weak symbol to avoid we error out if the
+	 __global_pointer$ is not found.  */
+      ElfW(Sym) gp_sym = { 0 };
+      gp_sym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE));
+
+      const ElfW(Sym) *ref = &gp_sym;
+      _dl_lookup_symbol_x ("__global_pointer$", l, &ref,
+			   l->l_scope, NULL, 0, 0, NULL);
+      if (ref)
+        asm (
+          "mv gp, %0\n"
+          :
+          : "r" (ref->st_value)
+        );
+    }
+#endif
   return lazy;
 }