diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 11 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 23 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/pr24991.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/pr24991.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/pr24991.s | 5 |
5 files changed, 38 insertions, 7 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 764789b..41fc4ce 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2019-09-24 Tamar Christina <tamar.christina@arm.com> + + PR gas/24991 + * config/tc-arm.c (out_of_range_p): New. + (md_apply_fix): Use it in BFD_RELOC_THUMB_PCREL_BRANCH9, + BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20, + BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25 + * testsuite/gas/arm/pr24991.d: New test. + * testsuite/gas/arm/pr24991.l: New test. + * testsuite/gas/arm/pr24991.s: New test. + 2019-09-23 Alan Modra <amodra@gmail.com> * config/obj-ecoff.c: Include ecoff-bfd.h. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 2f394ba..1f46230 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -107,6 +107,15 @@ enum arm_float_abi should define CPU_DEFAULT here. */ #endif +/* Perform range checks on positive and negative overflows by checking if the + VALUE given fits within the range of an BITS sized immediate. */ +static bfd_boolean out_of_range_p (offsetT value, offsetT bits) + { + gas_assert (bits < (offsetT)(sizeof (value) * 8)); + return (value & ~((1 << bits)-1)) + && ((value & ~((1 << bits)-1)) != ~((1 << bits)-1)); +} + #ifndef FPU_DEFAULT # ifdef TE_LINUX # define FPU_DEFAULT FPU_ARCH_FPA @@ -28089,7 +28098,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */ - if ((value & ~0xff) && ((value & ~0xff) != ~0xff)) + if (out_of_range_p (value, 8)) as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE); if (fixP->fx_done || !seg->use_rela_p) @@ -28101,7 +28110,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */ - if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff)) + if (out_of_range_p (value, 11)) as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE); if (fixP->fx_done || !seg->use_rela_p) @@ -28112,6 +28121,7 @@ md_apply_fix (fixS * fixP, } break; + /* This relocation is misnamed, it should be BRANCH21. */ case BFD_RELOC_THUMB_PCREL_BRANCH20: if (fixP->fx_addsy && (S_GET_SEGMENT (fixP->fx_addsy) == seg) @@ -28122,7 +28132,7 @@ md_apply_fix (fixS * fixP, /* Force a relocation for a branch 20 bits wide. */ fixP->fx_done = 0; } - if ((value & ~0x1fffff) && ((value & ~0x0fffff) != ~0x0fffff)) + if (out_of_range_p (value, 20)) as_bad_where (fixP->fx_file, fixP->fx_line, _("conditional branch out of range")); @@ -28201,12 +28211,11 @@ md_apply_fix (fixS * fixP, fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23; #endif - if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff)) + if (out_of_range_p (value, 22)) { if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2))) as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE); - else if ((value & ~0x1ffffff) - && ((value & ~0x1ffffff) != ~0x1ffffff)) + else if (out_of_range_p (value, 24)) as_bad_where (fixP->fx_file, fixP->fx_line, _("Thumb2 branch out of range")); } @@ -28217,7 +28226,7 @@ md_apply_fix (fixS * fixP, break; case BFD_RELOC_THUMB_PCREL_BRANCH25: - if ((value & ~0x0ffffff) && ((value & ~0x0ffffff) != ~0x0ffffff)) + if (out_of_range_p (value, 24)) as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE); if (fixP->fx_done || !seg->use_rela_p) diff --git a/gas/testsuite/gas/arm/pr24991.d b/gas/testsuite/gas/arm/pr24991.d new file mode 100644 index 0000000..2acca2d --- /dev/null +++ b/gas/testsuite/gas/arm/pr24991.d @@ -0,0 +1,4 @@ +#as: -march=armv7-a +#source: pr24991.s +#error_output: pr24991.l + diff --git a/gas/testsuite/gas/arm/pr24991.l b/gas/testsuite/gas/arm/pr24991.l new file mode 100644 index 0000000..4fc5875 --- /dev/null +++ b/gas/testsuite/gas/arm/pr24991.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +[^:]*:4: Error: conditional branch out of range diff --git a/gas/testsuite/gas/arm/pr24991.s b/gas/testsuite/gas/arm/pr24991.s new file mode 100644 index 0000000..27f8daf --- /dev/null +++ b/gas/testsuite/gas/arm/pr24991.s @@ -0,0 +1,5 @@ + .arch armv7-a + .syntax unified + .thumb + beq .+ 0x124f80 + |