aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2022-08-24 17:08:07 +0100
committerRichard Earnshaw <rearnsha@arm.com>2022-08-24 17:08:07 +0100
commita37854f9162fac592b669eda53f465fc190c9341 (patch)
treea7044b2aa6e637b6b2dbaa3d74a03125b35e1df8 /gas
parent70175292616118bad315296ba6180f375326bb6c (diff)
downloadfsf-binutils-gdb-a37854f9162fac592b669eda53f465fc190c9341.zip
fsf-binutils-gdb-a37854f9162fac592b669eda53f465fc190c9341.tar.gz
fsf-binutils-gdb-a37854f9162fac592b669eda53f465fc190c9341.tar.bz2
gas: arm: handle multiple .directives on a single line (PR29519)
There's been a long-standing bug in the arm backend where target-specific directives did not correctly handle lines with multiple statements. This patch fixes the issue for all the cases I've been able to find. It does result in a slight change in behaviour when errors are encountered: where, previously, .cpu arm6 bar would result in the error "junk at end of line, first unrecognized character is `b'", we now get "unknown cpu `arm6 bar'", which I think is slightly more helpful anyway. Similar errors are generated for other directives.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-arm.c64
-rw-r--r--gas/testsuite/gas/arm/directives.d18
-rw-r--r--gas/testsuite/gas/arm/directives.s11
3 files changed, 73 insertions, 20 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 6cdc2db..0f7d769 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -2851,12 +2851,7 @@ s_unreq (int a ATTRIBUTE_UNUSED)
char saved_char;
name = input_line_pointer;
-
- while (*input_line_pointer != 0
- && *input_line_pointer != ' '
- && *input_line_pointer != '\n')
- ++input_line_pointer;
-
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
@@ -3208,6 +3203,7 @@ s_code (int unused ATTRIBUTE_UNUSED)
default:
as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
}
+ demand_empty_rest_of_line ();
}
static void
@@ -3230,7 +3226,7 @@ s_force_thumb (int ignore ATTRIBUTE_UNUSED)
static void
s_thumb_func (int ignore ATTRIBUTE_UNUSED)
{
- s_thumb (0);
+ s_thumb (0); /* Will check for end-of-line. */
/* The following label is the name/address of the start of a Thumb function.
We need to know this for the interworking support. */
@@ -3781,6 +3777,7 @@ s_ltorg (int ignored ATTRIBUTE_UNUSED)
literal_pool * pool;
char sym_name[20];
+ demand_empty_rest_of_line ();
pool = find_literal_pool ();
if (pool == NULL
|| pool->symbol == NULL
@@ -33365,11 +33362,17 @@ s_arm_cpu (int ignored ATTRIBUTE_UNUSED)
char saved_char;
name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
+ if (!*name)
+ {
+ as_bad (_(".cpu: missing cpu name"));
+ *input_line_pointer = saved_char;
+ return;
+ }
+
/* Skip the first "all" entry. */
for (opt = arm_cpus + 1; opt->name != NULL; opt++)
if (streq (opt->name, name))
@@ -33395,7 +33398,6 @@ s_arm_cpu (int ignored ATTRIBUTE_UNUSED)
}
as_bad (_("unknown cpu `%s'"), name);
*input_line_pointer = saved_char;
- ignore_rest_of_line ();
}
/* Parse a .arch directive. */
@@ -33408,11 +33410,17 @@ s_arm_arch (int ignored ATTRIBUTE_UNUSED)
char *name;
name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
+ if (!*name)
+ {
+ as_bad (_(".arch: missing architecture name"));
+ *input_line_pointer = saved_char;
+ return;
+ }
+
/* Skip the first "all" entry. */
for (opt = arm_archs + 1; opt->name != NULL; opt++)
if (streq (opt->name, name))
@@ -33443,11 +33451,17 @@ s_arm_object_arch (int ignored ATTRIBUTE_UNUSED)
char *name;
name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
+ if (!*name)
+ {
+ as_bad (_(".object_arch: missing architecture name"));
+ *input_line_pointer = saved_char;
+ return;
+ }
+
/* Skip the first "all" entry. */
for (opt = arm_archs + 1; opt->name != NULL; opt++)
if (streq (opt->name, name))
@@ -33474,11 +33488,17 @@ s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED)
int adding_value = 1;
name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
+ if (!*name)
+ {
+ as_bad (_(".arch_extension: missing architecture extension"));
+ *input_line_pointer = saved_char;
+ return;
+ }
+
if (strlen (name) >= 2
&& startswith (name, "no"))
{
@@ -33557,7 +33577,6 @@ s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED)
as_bad (_("unknown architecture extension `%s'\n"), name);
*input_line_pointer = saved_char;
- ignore_rest_of_line ();
}
/* Parse a .fpu directive. */
@@ -33570,11 +33589,17 @@ s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
char *name;
name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
+ input_line_pointer = find_end_of_line (input_line_pointer, flag_m68k_mri);
saved_char = *input_line_pointer;
*input_line_pointer = 0;
+ if (!*name)
+ {
+ as_bad (_(".fpu: missing fpu name"));
+ *input_line_pointer = saved_char;
+ return;
+ }
+
for (opt = arm_fpus; opt->name != NULL; opt++)
if (streq (opt->name, name))
{
@@ -33587,7 +33612,6 @@ s_arm_fpu (int ignored ATTRIBUTE_UNUSED)
#endif
ARM_MERGE_FEATURE_SETS (cpu_variant, selected_cpu, selected_fpu);
*input_line_pointer = saved_char;
- demand_empty_rest_of_line ();
return;
}
diff --git a/gas/testsuite/gas/arm/directives.d b/gas/testsuite/gas/arm/directives.d
new file mode 100644
index 0000000..6600218
--- /dev/null
+++ b/gas/testsuite/gas/arm/directives.d
@@ -0,0 +1,18 @@
+# name: multiple directives on one line
+# source: directives.s
+# as: --fatal-warnings
+# readelf: -A
+# This test is only valid on EABI based ports.
+# target: *-*-*eabi* *-*-nacl*
+
+Attribute Section: aeabi
+File Attributes
+ Tag_CPU_name: "custom_name"
+ Tag_CPU_arch: v8
+ Tag_CPU_arch_profile: Application
+ Tag_ARM_ISA_use: Yes
+ Tag_THUMB_ISA_use: Thumb-2
+ Tag_FP_arch: FP for ARMv8
+ Tag_ABI_align_preserved: 8-byte, except leaf SP
+ Tag_MPextension_use: Allowed
+ Tag_Virtualization_use: TrustZone and Virtualization Extensions
diff --git a/gas/testsuite/gas/arm/directives.s b/gas/testsuite/gas/arm/directives.s
new file mode 100644
index 0000000..c594741
--- /dev/null
+++ b/gas/testsuite/gas/arm/directives.s
@@ -0,0 +1,11 @@
+@ Check that various arm-specific directives can appear on the same line
+ .cpu cortex-a5 ; .arch armv8-a ; .arch_extension fp ; .arch_extension nosimd ; .syntax unified ; .thumb; .code 16 ; movs r0, r1
+ t1 .req r1 ; t2 .req r2 ;
+ movs t1, t2 @ mov r1, r2
+
+ .unreq t1;.unreq t2;
+ t1 .req r2
+ t2 .req r3
+ movs t1, t2 @ movs r2, r3
+ vmov.f32 s0, s1
+ .eabi_attribute Tag_CPU_name, "custom_name" ; .eabi_attribute Tag_ABI_align8_preserved, 1;