aarch64: Fix missing BTI instruction in trampolines
authorOmar Tahir <omar.tahir@arm.com>
Wed, 1 Jul 2020 20:56:16 +0000 (21:56 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 1 Jul 2020 20:56:16 +0000 (21:56 +0100)
If two functions require trampolines, and the first has BTI enabled
while the second doesn't, the generated template will be lacking
a BTI instruction.  This patch fixes this by always adding a BTI
instruction, which is safe as BTI instructions are ignored on
unsupported architecture versions.

2020-07-01  Omar Tahir  <omar.tahir@arm.com>

gcc/
* config/aarch64/aarch64.c (aarch64_asm_trampoline_template): Always
generate a BTI instruction.

gcc/testsuite/
* gcc.target/aarch64/bti-4.c: New test.

gcc/config/aarch64/aarch64.c
gcc/testsuite/gcc.target/aarch64/bti-4.c [new file with mode: 0644]

index 57988f9330bc98321a086d90f9e3e2e1420f0ddb..24c31c2d02cdb779be16d2b5427bb1ecc5d9719f 100644 (file)
@@ -10833,40 +10833,26 @@ aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
   return get_hard_reg_initial_val (Pmode, LR_REGNUM);
 }
 
-
 static void
 aarch64_asm_trampoline_template (FILE *f)
 {
-  int offset1 = 16;
-  int offset2 = 20;
-
-  if (aarch64_bti_enabled ())
-    {
-      asm_fprintf (f, "\thint\t34 // bti c\n");
-      offset1 -= 4;
-      offset2 -= 4;
-    }
+  /* Even if the current function doesn't have branch protection, some
+     later function might, so since this template is only generated once
+     we have to add a BTI just in case. */
+  asm_fprintf (f, "\thint\t34 // bti c\n");
 
   if (TARGET_ILP32)
     {
-      asm_fprintf (f, "\tldr\tw%d, .+%d\n", IP1_REGNUM - R0_REGNUM, offset1);
-      asm_fprintf (f, "\tldr\tw%d, .+%d\n", STATIC_CHAIN_REGNUM - R0_REGNUM,
-                  offset1);
+      asm_fprintf (f, "\tldr\tw%d, .+12\n", IP1_REGNUM - R0_REGNUM);
+      asm_fprintf (f, "\tldr\tw%d, .+12\n", STATIC_CHAIN_REGNUM - R0_REGNUM);
     }
   else
     {
-      asm_fprintf (f, "\tldr\t%s, .+%d\n", reg_names [IP1_REGNUM], offset1);
-      asm_fprintf (f, "\tldr\t%s, .+%d\n", reg_names [STATIC_CHAIN_REGNUM],
-                  offset2);
+      asm_fprintf (f, "\tldr\t%s, .+12\n", reg_names [IP1_REGNUM]);
+      asm_fprintf (f, "\tldr\t%s, .+16\n", reg_names [STATIC_CHAIN_REGNUM]);
     }
   asm_fprintf (f, "\tbr\t%s\n", reg_names [IP1_REGNUM]);
 
-  /* The trampoline needs an extra padding instruction.  In case if BTI is
-     enabled the padding instruction is replaced by the BTI instruction at
-     the beginning.  */
-  if (!aarch64_bti_enabled ())
-    assemble_aligned_integer (4, const0_rtx);
-
   assemble_aligned_integer (POINTER_BYTES, const0_rtx);
   assemble_aligned_integer (POINTER_BYTES, const0_rtx);
 }
diff --git a/gcc/testsuite/gcc.target/aarch64/bti-4.c b/gcc/testsuite/gcc.target/aarch64/bti-4.c
new file mode 100644 (file)
index 0000000..28495a5
--- /dev/null
@@ -0,0 +1,60 @@
+/* { dg-do compile } */
+/* If configured with --enable-standard-branch-protection, disable it. */
+/* { dg-additional-options "-mbranch-protection=none" { target { default_branch_protection } } } */
+
+void f1 (void *);
+void f2 (void *);
+void f3 (void *, void (*)(void *));
+
+int
+retbr_trampolines (void *a, int b)
+{
+  if (!b)
+    {
+      f1 (a);
+      return 1;
+    }
+  if (b)
+    {
+      /* Suppress "ISO C forbids nested functions" warning. */
+      _Pragma("GCC diagnostic push")
+      _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
+      void retbr_tramp_internal (void *c)
+      {
+      _Pragma("GCC diagnostic pop")
+        if (c == a)
+          f2 (c);
+      }
+      f3 (a, retbr_tramp_internal);
+    }
+  return 0;
+}
+
+__attribute__((target("branch-protection=bti,arch=armv8.3-a")))
+int
+retbr_trampolines2 (void *a, int b)
+{
+  if (!b)
+    {
+      f1 (a);
+      return 1;
+    }
+  if (b)
+    {
+      /* Suppress "ISO C forbids nested functions" warning. */
+      _Pragma("GCC diagnostic push")
+      _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
+      __attribute__((target("branch-protection=bti,arch=armv8.3-a")))
+      void retbr_tramp_internal2 (void *c)
+      {
+      _Pragma("GCC diagnostic pop")
+        if (c == a)
+          f2 (c);
+      }
+      f3 (a, retbr_tramp_internal2);
+    }
+  return 0;
+}
+
+/* Trampoline should have BTI C. */
+/* { dg-final { scan-assembler "\.LTRAMP0:\n\thint\t34" } } */