On 2024-08-13 16:53, Richard Sandiford wrote:
Matthieu Longo <matthieu.lo...@arm.com> writes:
gcc/testsuite/ChangeLog:
* g++.target/aarch64/pr94515-1.C: Improve test documentation.
* g++.target/aarch64/pr94515-2.C: Same.
The patch is OK as-is, since it's clearly a strict improvement over
the status quo. But a suggestion below:
---
gcc/testsuite/g++.target/aarch64/pr94515-1.C | 8 ++++++
gcc/testsuite/g++.target/aarch64/pr94515-2.C | 28 +++++++++++++++-----
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/gcc/testsuite/g++.target/aarch64/pr94515-2.C
b/gcc/testsuite/g++.target/aarch64/pr94515-2.C
index f4a3333beed..af6b128b8fd 100644
--- a/gcc/testsuite/g++.target/aarch64/pr94515-2.C
+++ b/gcc/testsuite/g++.target/aarch64/pr94515-2.C
@@ -6,6 +6,7 @@
volatile int zero = 0;
int global = 0;
+/* This is a leaf function, so no .cfi_negate_ra_state directive is expected. */
__attribute__((noinline))
int bar(void)
{
@@ -13,29 +14,44 @@ int bar(void)
return 0;
}
+/* This function does not return normally, so the address is signed but no
+ * authentication code is emitted. It means that only one CFI directive is
+ * supposed to be emitted at signing time. */
__attribute__((noinline, noreturn))
void unwind (void)
{
throw 42;
}
+/* This function has several return instructions, and alternates different RA
+ * states. 4 .cfi_negate_ra_state and a .cfi_remember_state/.cfi_restore_state
+ * should be emitted.
+ */
__attribute__((noinline, noipa))
int test(int x)
{
- if (x==1) return 2; /* This return path may not use the stack. */
+ // This return path may not use the stack. This means that the return address
+ // won't be signed.
+ if (x==1) return 2;
+
+ // All the return paths of the code below must have RA mangle state set, and
+ // the return address must be signed.
int y = bar();
if (y > global) global=y;
- if (y==3) unwind(); /* This return path must have RA mangle state set. */
- return 0;
+ if (y==3) unwind(); // authentication of the return address is not required.
+ return 0; // authentication of the return address is required.
}
I wasn't sure from reading this why it would give 4 .cfi_negate_ra_states,
and had to run the test to find out. I think a key part is that the
current block layout is:
A: path to return 0 without assignment to global
B: global=y + branch back into A
C: return 2
D: unwind
so we have:
A: sign -> authenticate [2 negate_ra_states + remember_state for B]
B: signed [restore_state]
C: unsigned [negate_ra_state]
D: signed [negate_ra_state]
If the order had been ABDC then we would only need 3 negate_ra_states.
If the x==1 branch had been:
cmp w0, 1
bne .L10
mov w0, 2
ret
.L10:
followed by the rest of A, B and D, then we would only have needed
2 negate_ra_states.
So it might be helpful to give the block layout above too.
Like I say, it's just a suggestion though.
Thanks,
Richard
Done in the next revision.
Thanks,
Matthieu
+/* This function requires only 2 .cfi_negate_ra_state. */
int main ()
{
+ // paciasp -> cfi_negate_ra_state: RA_no_signing -> RA_signing_SP
try {
test (zero);
- __builtin_abort ();
+ __builtin_abort (); // authentication of the return address is not
required.
} catch (...) {
+ // autiasp -> cfi_negate_ra_state: RA_signing_SP -> RA_no_signing
return 0;
}
- __builtin_abort ();
-}
+ __builtin_abort (); // authentication of the return address is not required.
+}
\ No newline at end of file