RISC-V: Use pc-relative relocation for FDE initial location
[deliverable/binutils-gdb.git] / gas / config / tc-riscv.c
index afda6c51248b9d1dc53d319e47875a1c13c38e65..55c41c5db3c9240e8da3cdf8906cfb745d041c6f 100644 (file)
@@ -1871,6 +1871,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
   bfd_byte *buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
   bfd_boolean relaxable = FALSE;
   offsetT loc;
+  segT sub_segment;
 
   /* Remember value for tc_gen_reloc.  */
   fixP->fx_addnumber = *valP;
@@ -1919,8 +1920,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
                      _("TLS relocation against a constant"));
       break;
 
-    case BFD_RELOC_64:
     case BFD_RELOC_32:
+      /* Use pc-relative relocation for FDE initial location.
+        The symbol address in .eh_frame may be adjusted in
+        _bfd_elf_discard_section_eh_frame, and the content of
+        .eh_frame will be adjusted in _bfd_elf_write_section_eh_frame.
+        Therefore, we cannot insert a relocation whose addend symbol is
+        in .eh_frame. Othrewise, the value may be adjusted twice.*/
+      if (fixP->fx_addsy && fixP->fx_subsy
+         && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
+         && strcmp (sub_segment->name, ".eh_frame") == 0
+         && S_GET_VALUE (fixP->fx_subsy)
+            == fixP->fx_frag->fr_address + fixP->fx_where)
+       {
+         fixP->fx_r_type = BFD_RELOC_RISCV_32_PCREL;
+         fixP->fx_subsy = NULL;
+         break;
+       }
+      /* Fall through.  */
+    case BFD_RELOC_64:
     case BFD_RELOC_16:
     case BFD_RELOC_8:
     case BFD_RELOC_RISCV_CFA:
This page took 0.024199 seconds and 4 git commands to generate.