[binutils-gdb] This fixes a bug in the ARm assembler where an immediate operand larger than 4 bits (0xF) could be p

Nick Clifton nickc@sourceware.org
Thu Jun 27 13:07:00 GMT 2019


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

commit ba85f98c42877287f45644a6d75513239c9490a5
Author: Barnaby Wilk  s <barnaby.wilks@arm.com>
Date:   Thu Jun 27 14:06:02 2019 +0100

    This fixes a bug in the ARm assembler where an immediate operand larger than 4 bits (0xF) could be passed to the SMC (Secure Monitor Call) instruction.
    
    For example, this code is invalid:
    smc #0x6951
    
    The code would previously check for and encode for up to 16 bit immediate values, however
    this immediate should instead be only a 4 bit value
    (as documented herehttps://static.docs.arm.com/ddi0406/c/DDI0406C_C_arm_architecture_reference_manual.pdf  ).
    
    Fixed this by adding range checks in the relevant areas and also removing code that would
    encode more than the first 4 bits of the immediate (code that is now redundant, as any immediate operand
    larger than 0xF would error now anyway).
    
    gas	* config/tc-arm.c (do_smc): Add range check for immediate operand.
    	(do_t_smc): Add range check for immediate operand. Remove
    	obsolete immediate encoding.
    	(md_apply_fix): Fix range check. Remove obsolete immediate encoding.
    	* testsuite/gas/arm/arch6zk.d: Fix test.
    	* testsuite/gas/arm/arch6zk.s: Fix test.
    	* testsuite/gas/arm/smc-bad.d: New test.
    	* testsuite/gas/arm/smc-bad.l: New test.
    	* testsuite/gas/arm/smc-bad.s: New test.
    	* testsuite/gas/arm/thumb32.d: Fix test.
    	* testsuite/gas/arm/thumb32.s: Fix test.

Diff:
---
 gas/ChangeLog                   | 14 ++++++++++++++
 gas/config/tc-arm.c             | 13 +++++++++----
 gas/testsuite/gas/arm/arch6zk.d |  4 ++--
 gas/testsuite/gas/arm/arch6zk.s |  4 ++--
 gas/testsuite/gas/arm/smc-bad.d |  3 +++
 gas/testsuite/gas/arm/smc-bad.l |  8 ++++++++
 gas/testsuite/gas/arm/smc-bad.s | 14 ++++++++++++++
 gas/testsuite/gas/arm/thumb32.d |  2 +-
 gas/testsuite/gas/arm/thumb32.s |  2 +-
 9 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index e08db78..98bae96 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,17 @@
+2019-06-27  Barnaby Wilk  s<barnaby.wilks@arm.com>
+
+	* config/tc-arm.c (do_smc): Add range check for immediate operand.
+	(do_t_smc): Add range check for immediate operand. Remove
+	obsolete immediate encoding.
+	(md_apply_fix): Fix range check. Remove obsolete immediate encoding.
+	* testsuite/gas/arm/arch6zk.d: Fix test.
+	* testsuite/gas/arm/arch6zk.s: Fix test.
+	* testsuite/gas/arm/smc-bad.d: New test.
+	* testsuite/gas/arm/smc-bad.l: New test.
+	* testsuite/gas/arm/smc-bad.s: New test.
+	* testsuite/gas/arm/thumb32.d: Fix test.
+	* testsuite/gas/arm/thumb32.s: Fix test.
+
 2019-06-27  Jan Beulich  <jbeulich@suse.com>
 
 	config/tc-i386.c (md_assemble): Check for protected mode
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 679361d..b70028f 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -10247,6 +10247,9 @@ do_shift (void)
 static void
 do_smc (void)
 {
+  unsigned int value = inst.relocs[0].exp.X_add_number;
+  constraint (value > 0xf, _("immediate too large (bigger than 0xF)"));
+
   inst.relocs[0].type = BFD_RELOC_ARM_SMC;
   inst.relocs[0].pc_rel = 0;
 }
@@ -13877,10 +13880,11 @@ do_t_smc (void)
 	      _("SMC is not permitted on this architecture"));
   constraint (inst.relocs[0].exp.X_op != O_constant,
 	      _("expression too complex"));
+  constraint (value > 0xf, _("immediate too large (bigger than 0xF)"));
+
   inst.relocs[0].type = BFD_RELOC_UNUSED;
-  inst.instruction |= (value & 0xf000) >> 12;
-  inst.instruction |= (value & 0x0ff0);
   inst.instruction |= (value & 0x000f) << 16;
+
   /* PR gas/15623: SMC instructions must be last in an IT block.  */
   set_pred_insn_type_last ();
 }
@@ -27765,11 +27769,12 @@ md_apply_fix (fixS *	fixP,
       break;
 
     case BFD_RELOC_ARM_SMC:
-      if (((unsigned long) value) > 0xffff)
+      if (((unsigned long) value) > 0xf)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
 		      _("invalid smc expression"));
+
       newval = md_chars_to_number (buf, INSN_SIZE);
-      newval |= (value & 0xf) | ((value & 0xfff0) << 4);
+      newval |= (value & 0xf);
       md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
diff --git a/gas/testsuite/gas/arm/arch6zk.d b/gas/testsuite/gas/arm/arch6zk.d
index 5ec8def..f9ae025 100644
--- a/gas/testsuite/gas/arm/arch6zk.d
+++ b/gas/testsuite/gas/arm/arch6zk.d
@@ -24,6 +24,6 @@ Disassembly of section .text:
 0+040 <[^>]*> e320f002 ?	wfe
 0+044 <[^>]*> e320f003 ?	wfi
 0+048 <[^>]*> e320f001 ?	yield
-0+04c <[^>]*> e16ec371 ?	smc	60465.*
-0+050 <[^>]*> 11613c7e ?	smcne	5070.*
+0+04c <[^>]*> e1600071 ?	smc	1.*
+0+050 <[^>]*> 1160007e ?	smcne	14.*
 #...
diff --git a/gas/testsuite/gas/arm/arch6zk.s b/gas/testsuite/gas/arm/arch6zk.s
index 19c2c65..db2e0b2 100644
--- a/gas/testsuite/gas/arm/arch6zk.s
+++ b/gas/testsuite/gas/arm/arch6zk.s
@@ -23,8 +23,8 @@ label:
 	wfi
 	yield
 	# ARMV6Z instructions
-	smc 0xec31
-	smcne 0x13ce
+	smc 0x1
+	smcne 0xe
 
 	# Ensure output is 32-byte aligned as required for arm-aout.
 	.p2align 5
diff --git a/gas/testsuite/gas/arm/smc-bad.d b/gas/testsuite/gas/arm/smc-bad.d
new file mode 100644
index 0000000..ca3a5a5
--- /dev/null
+++ b/gas/testsuite/gas/arm/smc-bad.d
@@ -0,0 +1,3 @@
+# name: Invalid SMC operand test
+# source: smc-bad.s
+# error_output: smc-bad.l
diff --git a/gas/testsuite/gas/arm/smc-bad.l b/gas/testsuite/gas/arm/smc-bad.l
new file mode 100644
index 0000000..ac206e0
--- /dev/null
+++ b/gas/testsuite/gas/arm/smc-bad.l
@@ -0,0 +1,8 @@
+.*smc-bad.s: Assembler messages:
+.*smc-bad.s:2: Error: immediate too large \(bigger than 0xF\) -- `smc #0xfefe'
+.*smc-bad.s:3: Error: immediate too large \(bigger than 0xF\) -- `smc #0x12'
+.*smc-bad.s:4: Error: immediate too large \(bigger than 0xF\) -- `smc 123'
+.*smc-bad.s:7: Error: immediate too large \(bigger than 0xF\) -- `smc #0xdfd'
+.*smc-bad.s:8: Error: immediate too large \(bigger than 0xF\) -- `smc #0x43'
+.*smc-bad.s:9: Error: immediate too large \(bigger than 0xF\) -- `smc 4343343'
+.*smc-bad.s:14: Error: immediate too large \(bigger than 0xF\) -- `smc #0x6951'
diff --git a/gas/testsuite/gas/arm/smc-bad.s b/gas/testsuite/gas/arm/smc-bad.s
new file mode 100644
index 0000000..04453ae
--- /dev/null
+++ b/gas/testsuite/gas/arm/smc-bad.s
@@ -0,0 +1,14 @@
+.arm
+	smc #0xfefe
+	smc #0x12
+	smc 123
+
+.thumb
+	smc #0xdfd
+	smc #0x43
+	smc 4343343
+
+.arm
+.syntax unified
+.cpu cortex-a8
+	smc #0x6951
diff --git a/gas/testsuite/gas/arm/thumb32.d b/gas/testsuite/gas/arm/thumb32.d
index 8a81262..f265f5a 100644
--- a/gas/testsuite/gas/arm/thumb32.d
+++ b/gas/testsuite/gas/arm/thumb32.d
@@ -844,7 +844,7 @@ Disassembly of section .text:
 0[0-9a-f]+ <[^>]+> ea4f 0132 	mov.w	r1, r2, rrx
 0[0-9a-f]+ <[^>]+> ea5f 0334 	movs.w	r3, r4, rrx
 0[0-9a-f]+ <[^>]+> f7f0 8000 	smc	#0
-0[0-9a-f]+ <[^>]+> f7fd 8bca 	smc	#43981	; 0xabcd
+0[0-9a-f]+ <[^>]+> f7fd 8000 	smc	#13
 0[0-9a-f]+ <[^>]+> fb10 0000 	smlabb	r0, r0, r0, r0
 0[0-9a-f]+ <[^>]+> fb10 0900 	smlabb	r9, r0, r0, r0
 0[0-9a-f]+ <[^>]+> fb19 0000 	smlabb	r0, r9, r0, r0
diff --git a/gas/testsuite/gas/arm/thumb32.s b/gas/testsuite/gas/arm/thumb32.s
index d6dbdd6..5f8cb83 100644
--- a/gas/testsuite/gas/arm/thumb32.s
+++ b/gas/testsuite/gas/arm/thumb32.s
@@ -637,7 +637,7 @@ rrx:
 	.arch_extension sec
 smc:
 	smc	#0
-	smc	#0xabcd
+	smc	#0xd
 
 smla:
 	smlabb	r0, r0, r0, r0



More information about the Binutils-cvs mailing list