RISC-V: PR29342, Fix RV32 disassembler address computation
authorTsukasa OI <research_trasio@irq.a4lg.com>
Sat, 27 Aug 2022 00:11:00 +0000 (00:11 +0000)
committerNelson Chu <nelson@rivosinc.com>
Fri, 2 Sep 2022 04:06:27 +0000 (12:06 +0800)
If either the base register is `zero', `tp' or `gp' and XLEN is 32, an
incorrectly sign-extended address is produced when printing.  This commit
fixes this by fitting an address into a 32-bit value on RV32.

Besides, H. Peter Anvin discovered that we have wrong address computation
for JALR instruction (the initial bug is back in 2018).  This commit also
fixes that based on the idea of Palmer Dabbelt.

gas/
pr29342
* testsuite/gas/riscv/lla32.d: Reflect RV32 address computation fix.
* testsuite/gas/riscv/dis-addr-overflow.s: New testcase.
* testsuite/gas/riscv/dis-addr-overflow-32.d: Likewise.
* testsuite/gas/riscv/dis-addr-overflow-64.d: Likewise.
opcodes/
pr29342
* riscv-dis.c (maybe_print_address): Fit address into 32-bit on RV32.
(print_insn_args): Fix JALR address by adding EXTRACT_ITYPE_IMM.

gas/testsuite/gas/riscv/dis-addr-overflow-32.d [new file with mode: 0644]
gas/testsuite/gas/riscv/dis-addr-overflow-64.d [new file with mode: 0644]
gas/testsuite/gas/riscv/dis-addr-overflow.s [new file with mode: 0644]
gas/testsuite/gas/riscv/lla32.d
opcodes/riscv-dis.c

diff --git a/gas/testsuite/gas/riscv/dis-addr-overflow-32.d b/gas/testsuite/gas/riscv/dis-addr-overflow-32.d
new file mode 100644 (file)
index 0000000..43f712a
--- /dev/null
@@ -0,0 +1,30 @@
+#as: -march=rv32ic
+#source: dis-addr-overflow.s
+#objdump: -d
+
+.*:     file format elf32-(little|big)riscv
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[      ]+[0-9a-f]+:[   ]+fffff2b7[     ]+lui[          ]+t0,0xfffff
+[      ]+[0-9a-f]+:[   ]+ffc2a903[     ]+lw[           ]+s2,-4\(t0\) # ffffeffc <addr_load>
+[      ]+[0-9a-f]+:[   ]+ffffe337[     ]+lui[          ]+t1,0xffffe
+[      ]+[0-9a-f]+:[   ]+ff332c23[     ]+sw[           ]+s3,-8\(t1\) # ffffdff8 <addr_store>
+[      ]+[0-9a-f]+:[   ]+ffffd3b7[     ]+lui[          ]+t2,0xffffd
+[      ]+[0-9a-f]+:[   ]+000380e7[     ]+jalr[         ]+t2 # ffffd000 <addr_jalr_1>
+[      ]+[0-9a-f]+:[   ]+ffffce37[     ]+lui[          ]+t3,0xffffc
+[      ]+[0-9a-f]+:[   ]+ff4e00e7[     ]+jalr[         ]+-12\(t3\) # ffffbff4 <addr_jalr_2>
+[      ]+[0-9a-f]+:[   ]+ffffbeb7[     ]+lui[          ]+t4,0xffffb
+[      ]+[0-9a-f]+:[   ]+000e8a67[     ]+jalr[         ]+s4,t4 # ffffb000 <addr_jalr_3>
+[      ]+[0-9a-f]+:[   ]+ffffaf37[     ]+lui[          ]+t5,0xffffa
+[      ]+[0-9a-f]+:[   ]+ff0f0a93[     ]+addi[         ]+s5,t5,-16 # ffff9ff0 <addr_loadaddr>
+[      ]+[0-9a-f]+:[   ]+ffff9fb7[     ]+lui[          ]+t6,0xffff9
+[      ]+[0-9a-f]+:[   ]+1fb1[         ]+addi[         ]+t6,t6,-20 # ffff8fec <addr_loadaddr_c>
+[      ]+[0-9a-f]+:[   ]+4001a283[     ]+lw[           ]+t0,1024\(gp\) # 600 <addr_rel_gp_pos>
+[      ]+[0-9a-f]+:[   ]+c001a303[     ]+lw[           ]+t1,-1024\(gp\) # fffffe00 <addr_rel_gp_neg>
+[      ]+[0-9a-f]+:[   ]+10002383[     ]+lw[           ]+t2,256\(zero\) # 100 <addr_rel_zero_pos>
+[      ]+[0-9a-f]+:[   ]+80002e03[     ]+lw[           ]+t3,-2048\(zero\) # fffff800 <addr_rel_zero_neg>
+[      ]+[0-9a-f]+:[   ]+10400ee7[     ]+jalr[         ]+t4,260\(zero\) # 104 <addr_jalr_rel_zero_pos>
+[      ]+[0-9a-f]+:[   ]+80400f67[     ]+jalr[         ]+t5,-2044\(zero\) # fffff804 <addr_jalr_rel_zero_neg>
diff --git a/gas/testsuite/gas/riscv/dis-addr-overflow-64.d b/gas/testsuite/gas/riscv/dis-addr-overflow-64.d
new file mode 100644 (file)
index 0000000..065ee25
--- /dev/null
@@ -0,0 +1,34 @@
+#as: -march=rv64ic -defsym rv64=1
+#source: dis-addr-overflow.s
+#objdump: -d
+
+.*:     file format elf64-(little|big)riscv
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[      ]+[0-9a-f]+:[   ]+fffff2b7[     ]+lui[          ]+t0,0xfffff
+[      ]+[0-9a-f]+:[   ]+ffc2a903[     ]+lw[           ]+s2,-4\(t0\) # ffffffffffffeffc <addr_load>
+[      ]+[0-9a-f]+:[   ]+ffffe337[     ]+lui[          ]+t1,0xffffe
+[      ]+[0-9a-f]+:[   ]+ff332c23[     ]+sw[           ]+s3,-8\(t1\) # ffffffffffffdff8 <addr_store>
+[      ]+[0-9a-f]+:[   ]+ffffd3b7[     ]+lui[          ]+t2,0xffffd
+[      ]+[0-9a-f]+:[   ]+000380e7[     ]+jalr[         ]+t2 # ffffffffffffd000 <addr_jalr_1>
+[      ]+[0-9a-f]+:[   ]+ffffce37[     ]+lui[          ]+t3,0xffffc
+[      ]+[0-9a-f]+:[   ]+ff4e00e7[     ]+jalr[         ]+-12\(t3\) # ffffffffffffbff4 <addr_jalr_2>
+[      ]+[0-9a-f]+:[   ]+ffffbeb7[     ]+lui[          ]+t4,0xffffb
+[      ]+[0-9a-f]+:[   ]+000e8a67[     ]+jalr[         ]+s4,t4 # ffffffffffffb000 <addr_jalr_3>
+[      ]+[0-9a-f]+:[   ]+ffffaf37[     ]+lui[          ]+t5,0xffffa
+[      ]+[0-9a-f]+:[   ]+ff0f0a93[     ]+addi[         ]+s5,t5,-16 # ffffffffffff9ff0 <addr_loadaddr>
+[      ]+[0-9a-f]+:[   ]+ffff9fb7[     ]+lui[          ]+t6,0xffff9
+[      ]+[0-9a-f]+:[   ]+1fb1[         ]+addi[         ]+t6,t6,-20 # ffffffffffff8fec <addr_loadaddr_c>
+[      ]+[0-9a-f]+:[   ]+ffff8b37[     ]+lui[          ]+s6,0xffff8
+[      ]+[0-9a-f]+:[   ]+fe8b0b9b[     ]+addiw[        ]+s7,s6,-24 # ffffffffffff7fe8 <addr_loadaddr_w>
+[      ]+[0-9a-f]+:[   ]+ffff7c37[     ]+lui[          ]+s8,0xffff7
+[      ]+[0-9a-f]+:[   ]+3c11[         ]+addiw[        ]+s8,s8,-28 # ffffffffffff6fe4 <addr_loadaddr_w_c>
+[      ]+[0-9a-f]+:[   ]+4001a283[     ]+lw[           ]+t0,1024\(gp\) # 600 <addr_rel_gp_pos>
+[      ]+[0-9a-f]+:[   ]+c001a303[     ]+lw[           ]+t1,-1024\(gp\) # fffffffffffffe00 <addr_rel_gp_neg>
+[      ]+[0-9a-f]+:[   ]+10002383[     ]+lw[           ]+t2,256\(zero\) # 100 <addr_rel_zero_pos>
+[      ]+[0-9a-f]+:[   ]+80002e03[     ]+lw[           ]+t3,-2048\(zero\) # fffffffffffff800 <addr_rel_zero_neg>
+[      ]+[0-9a-f]+:[   ]+10400ee7[     ]+jalr[         ]+t4,260\(zero\) # 104 <addr_jalr_rel_zero_pos>
+[      ]+[0-9a-f]+:[   ]+80400f67[     ]+jalr[         ]+t5,-2044\(zero\) # fffffffffffff804 <addr_jalr_rel_zero_neg>
diff --git a/gas/testsuite/gas/riscv/dis-addr-overflow.s b/gas/testsuite/gas/riscv/dis-addr-overflow.s
new file mode 100644 (file)
index 0000000..77ca39c
--- /dev/null
@@ -0,0 +1,70 @@
+.set __global_pointer$, 0x00000200
+
+.ifdef rv64
+topbase = 0xffffffff00000000
+.else
+topbase = 0
+.endif
+
+.set addr_load,              topbase + 0xffffeffc  # -0x1000 -4
+.set addr_store,             topbase + 0xffffdff8  # -0x2000 -8
+.set addr_jalr_1,            topbase + 0xffffd000  # -0x3000
+.set addr_jalr_2,            topbase + 0xffffbff4  # -0x4000 -12
+.set addr_jalr_3,            topbase + 0xffffb000  # -0x5000
+.set addr_loadaddr,          topbase + 0xffff9ff0  # -0x6000 -16
+.set addr_loadaddr_c,        topbase + 0xffff8fec  # -0x7000 -20
+.set addr_loadaddr_w,        topbase + 0xffff7fe8  # -0x8000 -24
+.set addr_loadaddr_w_c,      topbase + 0xffff6fe4  # -0x9000 -28
+.set addr_rel_gp_pos,                  0x00000600  # __global_pointer$ + 0x400
+.set addr_rel_gp_neg,        topbase + 0xfffffe00  # __global_pointer$ - 0x400
+.set addr_rel_zero_pos,                0x00000100
+.set addr_rel_zero_neg,      topbase + 0xfffff800  # -0x800
+.set addr_jalr_rel_zero_pos,           0x00000104
+.set addr_jalr_rel_zero_neg, topbase + 0xfffff804  # -0x7fc
+
+target:
+       .option push
+       .option arch, -c
+       ## Use hi_addr
+       # Load
+       lui     t0, 0xfffff
+       lw      s2, -4(t0)
+       # Store
+       lui     t1, 0xffffe
+       sw      s3, -8(t1)
+       # JALR (implicit destination, no offset)
+       lui     t2, 0xffffd
+       jalr    t2
+       # JALR (implicit destination, with offset)
+       lui     t3, 0xffffc
+       jalr    -12(t3)
+       # JALR (explicit destination, no offset)
+       lui     t4, 0xffffb
+       jalr    s4, t4
+       # ADDI (not compressed)
+       lui     t5, 0xffffa
+       addi    s5, t5, -16
+       # C.ADDI
+       lui     t6, 0xffff9
+       .option pop
+       c.addi  t6, -20
+.ifdef rv64
+       .option push
+       .option arch, -c
+       # ADDIW (not compressed)
+       lui     s6, 0xffff8
+       addiw   s7, s6, -24
+       # C.ADDIW
+       lui     s8, 0xffff7
+       .option pop
+       c.addiw s8, -28
+.endif
+
+       # Use addresses relative to gp
+       lw      t0, 0x400(gp)
+       lw      t1, -0x400(gp)
+       # Use addresses relative to zero
+       lw      t2, 0x100(zero)
+       lw      t3, -0x800(zero)
+       jalr    t4, 0x104(zero)
+       jalr    t5, -0x7fc(zero)
index 9d8756290642617be041714cc78648674a2e4e49..8e9324c1c96485dd43a12739a3d1401a62474115 100644 (file)
@@ -14,6 +14,6 @@ Disassembly of section .text:
   10:  00001537                lui     a0,0x1
   14:  fff50513                addi    a0,a0,-1 # fff <d>
   18:  80000537                lui     a0,0x80000
-  1c:  fff50513                addi    a0,a0,-1 # 7fffffff <h\+0x80000000>
+  1c:  fff50513                addi    a0,a0,-1 # 7fffffff <e>
   20:  00000513                li      a0,0
   24:  fff00513                li      a0,-1
index 164fd209dbd6720c9f4b4f6a527f036dcb38a7b5..b3ca680e50643e354642955e1bb743d436ffe0fb 100644 (file)
@@ -181,10 +181,16 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
     pd->print_addr = pd->gp + offset;
   else if (base_reg == X_TP || base_reg == 0)
     pd->print_addr = offset;
+  else
+    return;  /* Don't print the address.  */
 
   /* Sign-extend a 32-bit value to a 64-bit value.  */
   if (wide)
     pd->print_addr = (bfd_vma)(int32_t) pd->print_addr;
+
+  /* Fit into a 32-bit value on RV32.  */
+  if (xlen == 32)
+    pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
 }
 
 /* Print insn arguments for 32/64-bit code.  */
@@ -397,7 +403,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
        case 'b':
        case 's':
          if ((l & MASK_JALR) == MATCH_JALR)
-           maybe_print_address (pd, rs1, 0, 0);
+           maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
          print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]);
          break;