This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] RISC-V: Don't segfault for two regs in auipc or lui.
- From: Jim Wilson <jimw at sifive dot com>
- To: binutils at sourceware dot org
- Cc: Jim Wilson <jimw at sifive dot com>
- Date: Mon, 10 Dec 2018 16:41:55 -0800
- Subject: [PATCH] RISC-V: Don't segfault for two regs in auipc or lui.
This fixes two problems with the handling of auipc and lui. The first problem
is that we get a segfault if we parse a register operand. This is because
the my_getSmallExpression function isn't setting expr_end as documented when
there is a register operand. I also expanded the comment to explain why we
need to accept a register operand here. The second problem is that we were
missing a check for the 'u' operand code to reject register operands. I
handled this the same way as the existing 'B' operand code for consistency.
I also add a testcase for the instructions that were causing a segfault to
verify that they now give an illegal operand error.
This was tested cross for riscv{32,64}-{elf,linux} with binutils and gcc
builds and checks. There were no regressions.
Committed.
Jim
gas/
PR gas/23954
* config/tc-riscv.c (my_getSmallExpression): Expand comment for
register support. Set expr_end if parse a register.
(riscv_ip) <'u'>: Break if imm_expr is not a symbol or constant.
* testsuite/gas/riscv/auipc-parsing.d: New.
* testsuite/gas/riscv/auipc-parsing.l: New.
* testsuite/gas/riscv/auipc-parsing.s: New.
---
gas/config/tc-riscv.c | 9 ++++++++-
gas/testsuite/gas/riscv/auipc-parsing.d | 3 +++
gas/testsuite/gas/riscv/auipc-parsing.l | 3 +++
gas/testsuite/gas/riscv/auipc-parsing.s | 3 +++
4 files changed, 17 insertions(+), 1 deletion(-)
create mode 100644 gas/testsuite/gas/riscv/auipc-parsing.d
create mode 100644 gas/testsuite/gas/riscv/auipc-parsing.l
create mode 100644 gas/testsuite/gas/riscv/auipc-parsing.s
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 9e2035b109..f164134470 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1263,11 +1263,15 @@ my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
unsigned crux_depth, str_depth, regno;
char *crux;
- /* First, check for integer registers. */
+ /* First, check for integer registers. No callers can accept a reg, but
+ we need to avoid accidentally creating a useless undefined symbol below,
+ if this is an instruction pattern that can't match. A glibc build fails
+ if this is removed. */
if (reg_lookup (&str, RCLASS_GPR, ®no))
{
ep->X_op = O_register;
ep->X_add_number = regno;
+ expr_end = str;
return 0;
}
@@ -1940,6 +1944,9 @@ branch:
*imm_reloc = BFD_RELOC_RISCV_HI20;
imm_expr->X_add_number <<= RISCV_IMM_BITS;
}
+ /* The 'u' format specifier must be a symbol or a constant. */
+ if (imm_expr->X_op != O_symbol && imm_expr->X_op != O_constant)
+ break;
s = expr_end;
continue;
diff --git a/gas/testsuite/gas/riscv/auipc-parsing.d b/gas/testsuite/gas/riscv/auipc-parsing.d
new file mode 100644
index 0000000000..a91102cec7
--- /dev/null
+++ b/gas/testsuite/gas/riscv/auipc-parsing.d
@@ -0,0 +1,3 @@
+#as:
+#source: auipc-parsing.s
+#error_output: auipc-parsing.l
diff --git a/gas/testsuite/gas/riscv/auipc-parsing.l b/gas/testsuite/gas/riscv/auipc-parsing.l
new file mode 100644
index 0000000000..df41e0e2f9
--- /dev/null
+++ b/gas/testsuite/gas/riscv/auipc-parsing.l
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*: Error: illegal operands `auipc x8,x9'
+.*: Error: illegal operands `lui x10,x11'
diff --git a/gas/testsuite/gas/riscv/auipc-parsing.s b/gas/testsuite/gas/riscv/auipc-parsing.s
new file mode 100644
index 0000000000..f580869cbe
--- /dev/null
+++ b/gas/testsuite/gas/riscv/auipc-parsing.s
@@ -0,0 +1,3 @@
+# Don't accept a register for 'u' operands.
+ auipc x8,x9
+ lui x10,x11
--
2.17.1