[PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists
Victor Do Nascimento
victor.donascimento@arm.com
Wed May 4 10:41:46 GMT 2022
Hi,
This patch extends support for the encoding of the Return Address Authentication pseudo-register in lists containing other register types - e.g. '.save {r4,ra_auth_code,lr}'.
Lists are broken down into sub-lists allowing assembler to emit the correct new pacbti unwind opcode for the RA_AUTH_CODE pseudo register.
Tested for arm-none-eabi.
Thanks,
Victor.
gas/Changelog:
* testsuite/gas/arm/unwind-pacbti-m.s: Expand test for mixed
register type lists.
* testsuite/gas/arm/unwind-pacbti-m.d: Likewise.
* testsuite/gas/arm/unwind-pacbti-m-readelf.d: Likewise.
* config/tc-arm.c (parse_reg_list): Add handling of mixed register types.
(reg_names): Enumerate pseudoregister according to mapped physical
register number.
(s_arm_unwind_save_pseudo): Modify function signature.
(s_arm_unwind_save_core): Likewise.
(s_arm_unwind_save_mixed): New function.
(s_arm_unwind_save): Generate register list mask to pass to nested
functions.
---
gas/config/tc-arm.c | 117 +++++++++++++-----
.../gas/arm/unwind-pacbti-m-readelf.d | 12 +-
gas/testsuite/gas/arm/unwind-pacbti-m.d | 14 ++-
gas/testsuite/gas/arm/unwind-pacbti-m.s | 6 +
4 files changed, 107 insertions(+), 42 deletions(-)
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ca4f97b164ae8b0196e1830dc49e4927f8ea2480..8873269d76a482352c69d2d40a248549e7d6ba90 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1942,6 +1942,22 @@ parse_reg_list (char ** strp, enum reg_list_els etype)
rt = REG_TYPE_PSEUDO;
reg = arm_reg_parse (&str, rt);
+
+ /* Skip over allowed registers of alternative types in mixed-type
+ register lists. */
+ if (reg == FAIL && rt == REG_TYPE_PSEUDO
+ && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
+ {
+ cur_reg = reg;
+ continue;
+ }
+ else if (reg == FAIL && rt == REG_TYPE_RN
+ && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
+ {
+ cur_reg = reg;
+ continue;
+ }
+
if (etype == REGLIST_CLRM)
{
if (reg == REG_SP || reg == REG_PC)
@@ -4281,22 +4297,11 @@ s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
/* Parse a directive saving pseudo registers. */
static void
-s_arm_unwind_save_pseudo (void)
+s_arm_unwind_save_pseudo (long range)
{
valueT op;
- long range;
-
- range = parse_reg_list (&input_line_pointer, REGLIST_PSEUDO);
- if (range == FAIL)
- {
- as_bad (_("expected pseudo register list"));
- ignore_rest_of_line ();
- return;
- }
-
- demand_empty_rest_of_line ();
- if (range & (1 << 9))
+ if (range & (1 << 12))
{
/* Opcode for restoring RA_AUTH_CODE. */
op = 0xb4;
@@ -4308,22 +4313,11 @@ s_arm_unwind_save_pseudo (void)
/* Parse a directive saving core registers. */
static void
-s_arm_unwind_save_core (void)
+s_arm_unwind_save_core (long range)
{
valueT op;
- long range;
int n;
- range = parse_reg_list (&input_line_pointer, REGLIST_RN);
- if (range == FAIL)
- {
- as_bad (_("expected register list"));
- ignore_rest_of_line ();
- return;
- }
-
- demand_empty_rest_of_line ();
-
/* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
into .unwind_save {..., sp...}. We aren't bothered about the value of
ip because it is clobbered by calls. */
@@ -4722,6 +4716,40 @@ s_arm_unwind_save_mmxwcg (void)
ignore_rest_of_line ();
}
+static void
+s_arm_unwind_save_mixed (long range, long mask_range)
+{
+ const long roof = ((sizeof (long) * CHAR_BIT) - 1)
+ - __builtin_clzl (mask_range);
+
+ long subrange = 0;
+ unsigned lim_lo = 0;
+ unsigned lim_hi = 0;
+
+ /* Iterate over pseudoregister to establish subrange bounds. */
+ for (; lim_hi <= roof; lim_hi++)
+ {
+ if (mask_range & (1 << lim_hi))
+ {
+ /* Once we know where to split our range, construct subrange. */
+ for (unsigned n = lim_lo; n < lim_hi; n++)
+ {
+ if (range & (1 << n))
+ subrange |= (1 << n);
+ }
+
+ s_arm_unwind_save_core (subrange);
+ s_arm_unwind_save_pseudo (1 << lim_hi);
+
+ subrange = 0;
+ lim_lo = lim_hi + 1;
+ }
+ }
+
+ lim_lo = 0xffff << roof;
+ subrange = range & lim_lo;
+ s_arm_unwind_save_core (subrange);
+}
/* Parse an unwind_save directive.
If the argument is non-zero, this is a .vsave directive. */
@@ -4729,7 +4757,8 @@ s_arm_unwind_save_mmxwcg (void)
static void
s_arm_unwind_save (int arch_v6)
{
- char *peek;
+ char *peek, *mask_peek;
+ long range, mask_range;
struct reg_entry *reg;
bool had_brace = false;
@@ -4737,7 +4766,7 @@ s_arm_unwind_save (int arch_v6)
as_bad (MISSING_FNSTART);
/* Figure out what sort of save we have. */
- peek = input_line_pointer;
+ peek = mask_peek = input_line_pointer;
if (*peek == '{')
{
@@ -4767,13 +4796,35 @@ s_arm_unwind_save (int arch_v6)
s_arm_unwind_save_fpa (reg->number);
return;
+ case REG_TYPE_PSEUDO:
case REG_TYPE_RN:
- s_arm_unwind_save_core ();
- return;
+ mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
+ range = parse_reg_list (&input_line_pointer, REGLIST_RN);
- case REG_TYPE_PSEUDO:
- s_arm_unwind_save_pseudo ();
- return;
+ if (range == FAIL || mask_range == FAIL)
+ {
+ as_bad (_("expected register list"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ demand_empty_rest_of_line ();
+
+ if (!mask_range)
+ {
+ s_arm_unwind_save_core (range);
+ return;
+ }
+ else if (!range)
+ {
+ s_arm_unwind_save_pseudo (mask_range);
+ return;
+ }
+ else
+ {
+ s_arm_unwind_save_mixed (range, mask_range);
+ return;
+ }
case REG_TYPE_VFD:
if (arch_v6)
@@ -23976,7 +24027,7 @@ static const struct reg_entry reg_names[] =
for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
134 + reg_number should the range 134 to 142 be used for more pseudo regs
in the future. This also helps fit RA_AUTH_CODE into a bitmask. */
- REGDEF(ra_auth_code,9,PSEUDO),
+ REGDEF(ra_auth_code,12,PSEUDO),
};
#undef REGDEF
#undef REGNUM
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
index ba1d76dd18fbe0ca2c391c12ddcb180d1de3b32b..d8d647bb7f0d943ceeec47e2f4fc8d34bb0ea057 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
@@ -6,11 +6,15 @@
# VxWorks needs a special variant of this file.
#skip: *-*-vxworks*
-Unwind section '.ARM.exidx' at offset 0x40 contains 1 entry:
+Unwind section '.ARM.exidx' at offset 0x60 contains 1 entry:
-0x0 <foo>: 0x80b4a8b0
- Compact model index: 0
+0x0 <foo>: @0x0
+ Compact model index: 1
+ 0x84 0x00 pop {r14}
+ 0xb4 pop {ra_auth_code}
+ 0x84 0x00 pop {r14}
+ 0xb4 pop {ra_auth_code}
+ 0xa3 pop {r4, r5, r6, r7}
0xb4 pop {ra_auth_code}
0xa8 pop {r4, r14}
0xb0 finish
-
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.d b/gas/testsuite/gas/arm/unwind-pacbti-m.d
index 28021758a7487097689ef4c44cc25546ccac5221..06cb3145e4254b34c2d95616d7ea20506af3a42a 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
@@ -8,16 +8,20 @@
.*: file format.*
RELOCATION RECORDS FOR \[.ARM.exidx\]:
-OFFSET TYPE VALUE
+OFFSET TYPE VALUE.
00000000 R_ARM_PREL31 .text
-00000000 R_ARM_NONE __aeabi_unwind_cpp_pr0
+00000000 R_ARM_NONE __aeabi_unwind_cpp_pr1
+00000004 R_ARM_PREL31 .ARM.extab
Contents of section .text:
- 0000 (10b54df8 04cd5df8 04cb10bd|b510f84d cd04f85d cb04bd10) .*
+ 0000 (10b54df8 04cd5df8 04cb2de9 f050bde8|e8bd50f0 e92dcb04 f85dcd04 f84db510) .*
+ 0010 (f0502de9 0050bde8 005010bd|bd105000 e8bd5000 e92d50f0) .*
+Contents of section .ARM.extab:
+ 0000 (00840281 b40084b4 b0a8b4a3|a3b4a8b0 b48400b4 81028400) 00000000 .*
Contents of section .ARM.exidx:
- 0000 00000000 (b0a8b480|80b4a8b0) .*
+ 0000 00000000 00000000 .*
Contents of section .ARM.attributes:
0000 41(290000 00|000000 29)616561 62690001 (1f000000|0000001f) .*
0010 05382e31 2d4d2e4d 41494e00 0615074d .*
- 0020 09033202 34024a01 4c01 .*
+ 0020 09033202 34024a01 4c01 .*
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.s b/gas/testsuite/gas/arm/unwind-pacbti-m.s
index 5a6ea2eec2b8e48dd49963f0a4b93fa29c3c3a49..37202293133e95f7e94490aaa1729afb30a0afe7 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.s
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.s
@@ -16,5 +16,11 @@ foo:
push {r12}
.save {ra_auth_code}
pop {r12}
+ push {r4-r7, ip, lr}
+ .save {r4-r7, ra_auth_code, lr}
+ pop {r4-r7, ip, lr}
+ push {ip, lr}
+ .save {ra_auth_code, lr}
+ pop {ip, lr}
pop {r4, pc}
.fnend
--
2.17.1
More information about the Binutils
mailing list