This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] RISC-V: Avoid emitting invalid instructions in mixed RVC/no-RVC code


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

commit ed0816bd936492aa7dc00e4fbbf8ff8de1253854
Author: Palmer Dabbelt <palmer@dabbelt.com>
Date:   Fri Jun 16 14:33:16 2017 -0700

    RISC-V: Avoid emitting invalid instructions in mixed RVC/no-RVC code
    
    When linking the following code
    
        .global _prog_start
        _prog_start:
                mv x1, x1
                mv x2, x2
        .align 2
        rvc_boundry:
        .option norvc
        .align 3
                mv x3, x3
    
    we currently emit an invalid two-byte 0 instruction.  The actual output
    code looks like
    
        0000000080000000 <_prog_start>:
            80000000:   8086                    mv      ra,ra
            80000002:   810a                    mv      sp,sp
    
        0000000080000004 <rvc_boundry>:
            80000004:   0000                    unimp
            80000006:   0001                    nop
            80000008:   00018193                mv      gp,gp
    
    This ends up manifesting due to the two-byte compressed NOP that's
    pessimisticly emitted by the ".align 2", which results in "rvc_boundry"
    being 2-byte aligned.  frag_align_code() then goes and outputs a 2-byte
    NOP (which is invalid in no-RVC mode) to align the code back to a 4-byte
    boundry, which can't be relaxed away by the linker as it's not part of
    the R_RISCV_RELAX relocation.
    
    The fix is to just always emit the worst case possible alignment into
    the output as a single R_RISCV_RELAX, which the linker will then fix up.
    
    With this patch I get the expected code generation
    
        0000000080000000 <_prog_start>:
            80000000:   8086                    mv      ra,ra
            80000002:   810a                    mv      sp,sp
    
        0000000080000004 <rvc_boundry>:
            80000004:   00000013                nop
            80000008:   00018193                mv      gp,gp
    
    gas/ChangeLog
    
    2017-09-07  Palmer Dabbelt  <palmer@dabbelt.com>
    
            * config/tc-riscv.c (riscv_frag_align_code): Emit the entire
            alignment sequence inside R_RISCV_ALIGN.

Diff:
---
 gas/ChangeLog         |  5 +++++
 gas/config/tc-riscv.c | 25 ++++++++-----------------
 2 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index b52259f..5dc06f5 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-07  Palmer Dabbelt  <palmer@dabbelt.com>
+
+	* config/tc-riscv.c (riscv_frag_align_code): Emit the entire
+	alignment sequence inside R_RISCV_ALIGN.
+
 2017-09-05  Alexander Fedotov <alexander.fedotov@nxp.com>
 	    Edmar Wienskoski <edmar.wienskoski@nxp.com
 
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 4c644ab..1a15efc 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -2274,30 +2274,21 @@ bfd_boolean
 riscv_frag_align_code (int n)
 {
   bfd_vma bytes = (bfd_vma) 1 << n;
-  bfd_vma min_text_alignment_order = riscv_opts.rvc ? 1 : 2;
-  bfd_vma min_text_alignment = (bfd_vma) 1 << min_text_alignment_order;
-
-  /* First, get back to minimal alignment.  */
-  frag_align_code (min_text_alignment_order, 0);
+  bfd_vma worst_case_bytes = bytes - 2;
+  char *nops = frag_more (worst_case_bytes);
+  expressionS ex;
 
   /* When not relaxing, riscv_handle_align handles code alignment.  */
   if (!riscv_opts.relax)
     return FALSE;
 
-  if (bytes > min_text_alignment)
-    {
-      bfd_vma worst_case_bytes = bytes - min_text_alignment;
-      char *nops = frag_more (worst_case_bytes);
-      expressionS ex;
+  ex.X_op = O_constant;
+  ex.X_add_number = worst_case_bytes;
 
-      ex.X_op = O_constant;
-      ex.X_add_number = worst_case_bytes;
+  riscv_make_nops (nops, worst_case_bytes);
 
-      riscv_make_nops (nops, worst_case_bytes);
-
-      fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
-		   &ex, FALSE, BFD_RELOC_RISCV_ALIGN);
-    }
+  fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
+	       &ex, FALSE, BFD_RELOC_RISCV_ALIGN);
 
   return TRUE;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]