RISC-V: Gas inserts cfa relocs in wrong section.
authorJim Wilson <jimw@sifive.com>
Sun, 24 May 2020 23:42:21 +0000 (16:42 -0700)
committerJim Wilson <jimw@sifive.com>
Sun, 24 May 2020 23:42:21 +0000 (16:42 -0700)
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.

gas/ChangeLog
gas/config/tc-riscv.c

index 1ff090ab688aa4cec78f89b7b5d7ee8b268003da..e3da87381eae5dfea641d783ab69b02d5715f9a6 100644 (file)
@@ -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)"
index 04df0884f372fc9f8bd7b3c286a9777c9a4e8474..2a03a440b195db4e1a7dc83ffbae9936ff8f9a3d 100644 (file)
@@ -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);
 }