[binutils-gdb] RISC-V: Gas inserts cfa relocs in wrong section.

Jim Wilson wilson@sourceware.org
Sun May 24 23:43:27 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=72393fd1030f4d55cd12e2a84a91ce42212d037c

commit 72393fd1030f4d55cd12e2a84a91ce42212d037c
Author: Jim Wilson <jimw@sifive.com>
Date:   Sun May 24 16:42:21 2020 -0700

    RISC-V: Gas inserts cfa relocs in wrong section.
    
    The frag code makes a distinction between inserting frags before the frag
    chains are chained together and afterward.  After chaining, we need to set
    now_seg before creating the frag.  tc-xtensa.c has a function called
    fix_new_exp_in_seg that handles this right, but switches segments twice each
    time it is called.  In this case, we can inline it and pull the save and
    restore out of the loop to get better code.
    
            gas/
            PR 26025
            * config/tc-riscv.c (riscv_pre_output_hook): Change s type from const
            asection to segT.  New locals seg and subseg.  Call subseg_set before
            fix_new_exp.  Call subseg_set after loop to restore original values.

Diff:
---
 gas/ChangeLog         |  7 +++++++
 gas/config/tc-riscv.c | 13 ++++++++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 1ff090ab688..e3da87381ea 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2020-05-24  Jim Wilson  <jimw@sifive.com>
+
+	PR 26025
+	* config/tc-riscv.c (riscv_pre_output_hook): Change s type from const
+	asection to segT.  New locals seg and subseg.  Call subseg_set before
+	fix_new_exp.  Call subseg_set after loop to restore original values.
+
 2020-05-21  Alan Modra  <amodra@gmail.com>
 
 	* atof-generic.c: Replace "if (x) free (x)" with "free (x)"
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 04df0884f37..2a03a440b19 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -3062,7 +3062,11 @@ void
 riscv_pre_output_hook (void)
 {
   const frchainS *frch;
-  const asection *s;
+  segT s;
+
+  /* Save the current segment info.  */
+  segT seg = now_seg;
+  subsegT subseg = now_subseg;
 
   for (s = stdoutput->sections; s; s = s->next)
     for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
@@ -3082,11 +3086,18 @@ riscv_pre_output_hook (void)
 		exp.X_add_number = 0;
 		exp.X_op_symbol = symval->X_op_symbol;
 
+		/* We must set the segment before creating a frag after all
+		   frag chains have been chained together.  */
+		subseg_set (s, frch->frch_subseg);
+
 		fix_new_exp (frag, (int) frag->fr_offset, 1, &exp, 0,
 			     BFD_RELOC_RISCV_CFA);
 	      }
 	  }
       }
+
+  /* Restore the original segment info.  */
+  subseg_set (seg, subseg);
 }


More information about the Binutils-cvs mailing list