diff options
author | Barnaby Wilk s <barnaby.wilks@arm.com> | 2019-06-27 14:06:02 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-06-27 14:06:02 +0100 |
commit | ba85f98c42877287f45644a6d75513239c9490a5 (patch) | |
tree | 4b99cd21520a8c6a56fa4ba4e4fbe4e25d36dfe9 /gas | |
parent | 5ceb1f4d804b09cb8767ca704c2ba41e50a2bcdb (diff) | |
download | gdb-ba85f98c42877287f45644a6d75513239c9490a5.zip gdb-ba85f98c42877287f45644a6d75513239c9490a5.tar.gz gdb-ba85f98c42877287f45644a6d75513239c9490a5.tar.bz2 |
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 14 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 13 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/arch6zk.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/arch6zk.s | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/smc-bad.d | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/smc-bad.l | 8 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/smc-bad.s | 14 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/thumb32.d | 2 | ||||
-rw-r--r-- | 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 |