]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64 testsuite: explain expectections for pr94515* tests
authorMatthieu Longo <matthieu.longo@arm.com>
Mon, 23 Sep 2024 14:35:02 +0000 (15:35 +0100)
committerTamar Christina <tamar.christina@arm.com>
Mon, 23 Sep 2024 14:37:45 +0000 (15:37 +0100)
gcc/testsuite/ChangeLog:

* g++.target/aarch64/pr94515-1.C: Improve test documentation.
* g++.target/aarch64/pr94515-2.C: Same.

gcc/testsuite/g++.target/aarch64/pr94515-1.C
gcc/testsuite/g++.target/aarch64/pr94515-2.C

index d5c114a83a82ce9276f07c3ffe5de824f11dc370..359039e175367b0f14641eb34a47307394ec780f 100644 (file)
@@ -15,12 +15,20 @@ void unwind (void)
 __attribute__((noinline, noipa, target("branch-protection=pac-ret")))
 int test (int z)
 {
+  // paciasp -> cfi_negate_ra_state: RA_no_signing -> RA_signing_SP
   if (z) {
     asm volatile ("":::"x20","x21");
     unwind ();
+    // autiasp -> cfi_negate_ra_state: RA_signing_SP -> RA_no_signing
     return 1;
   } else {
+    // 2nd cfi_negate_ra_state because the CFI directives are processed linearily.
+    // At this point, the unwinder would believe that the address is not signed
+    // due to the previous return. That's why the compiler has to emit second
+    // cfi_negate_ra_state to mean that the return address is still signed.
+    // cfi_negate_ra_state: RA_no_signing -> RA_signing_SP
     unwind ();
+    // autiasp -> cfi_negate_ra_state: RA_signing_SP -> RA_no_signing
     return 2;
   }
 }
index f4a3333beed40ac978c6ab82becb32f384fdc4bd..bdb65411a0807b42120862ec8829c57c16b80311 100644 (file)
@@ -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,55 @@ 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.
+ *
+ * Expected layout:
+ *   A: path to return 0 without assignment to global
+ *   B: global=y + branch back into A
+ *   C: return 2
+ *   D: unwind
+ * Which gives with return pointer authentication:
+ *   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]
+ */
 __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.
 }
 
+/* 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