RISC-V: Ouput __global_pointer$ as dynamic symbol when generating dynamic PDE.
authorNelson Chu <nelson.chu@sifive.com>
Wed, 16 Dec 2020 03:03:34 +0000 (19:03 -0800)
committerNelson Chu <nelson.chu@sifive.com>
Tue, 5 Jan 2021 02:18:33 +0000 (10:18 +0800)
When the ifunc resolver is in the executable, we may relax the variables
to gp-relative access instruction in the ifunc resolver, or in other functions
that called by the ifunc resolver.  But this will cause the uninitialized
gp problem since the ifunc need to be resolved at the early runtime, that
is at the pre-load stage, but we set the gp until the startup code.

At first, we try to add a new dynamic tag, DT_RISCV_GP, to stroe the gp value
and let ld.so can init the gp register early, before the pre-load stage.  But
we need to extend the ABI if we want to add a new dynamic tag.  Therefore,
in the psabi discussion, we try another solution, which was suggested by the
lld and FreeBSD linker experts, to let ld.so set the gp earlier - make sure
__global_pointer$ is output as a dynamic symbol when we are generating pde,
since we only do the relaxation for it.  Afterwards, ld.so can search the
DT_SYMTAB to get the gp value, and set the gp register before resolving ifunc.

bfd/
    * elfnn-riscv.c (allocate_dynrelocs): When we are generating pde, make
      sure gp symbol is output as a dynamic symbol.

bfd/ChangeLog
bfd/elfnn-riscv.c

index f1ae342b4c3569240a31c28174730403176974b1..20ccea5920efe6e028739c37f6570b909d57a101 100644 (file)
@@ -1,3 +1,8 @@
+2021-01-05  Nelson Chu  <nelson.chu@sifive.com>
+
+       * elfnn-riscv.c (allocate_dynrelocs): When we are generating pde,
+       make sure gp symbol is output as a dynamic symbol.
+
 2021-01-04  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/26256
index 047f31b4eac4c9b3b95ec69d7ec2ad6b3e576747..9da415e604e5a9df45febb9d968f966432f0a2ae 100644 (file)
@@ -1083,6 +1083,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   htab = riscv_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
 
+  /* When we are generating pde, make sure gp symbol is output as a
+     dynamic symbol.  Then ld.so can set the gp register earlier, before
+     resolving the ifunc.  */
+  if (!bfd_link_pic (info)
+      && htab->elf.dynamic_sections_created
+      && strcmp (h->root.root.string, RISCV_GP_SYMBOL) == 0
+      && !bfd_elf_link_record_dynamic_symbol (info, h))
+    return FALSE;
+
   /* Since STT_GNU_IFUNC symbols must go through PLT, we handle them
      in the allocate_ifunc_dynrelocs and allocate_local_ifunc_dynrelocs,
      if they are defined and referenced in a non-shared object.  */