aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2020-05-24 16:42:21 -0700
committerJim Wilson <jimw@sifive.com>2020-05-24 16:42:21 -0700
commit72393fd1030f4d55cd12e2a84a91ce42212d037c (patch)
tree5f2028354959997fc1bcae4eaec43e615f4aeea9
parent41a77cbaadd63b92362f5ea35b2cd11f90edf170 (diff)
downloadfsf-binutils-gdb-72393fd1030f4d55cd12e2a84a91ce42212d037c.zip
fsf-binutils-gdb-72393fd1030f4d55cd12e2a84a91ce42212d037c.tar.gz
fsf-binutils-gdb-72393fd1030f4d55cd12e2a84a91ce42212d037c.tar.bz2
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.
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-riscv.c13
2 files changed, 19 insertions, 1 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 1ff090a..e3da873 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 04df088..2a03a44 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);
}