]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[AArch64] PR92424: Fix -fpatchable-function-entry=N,M with BTI
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 15 Jan 2020 12:23:40 +0000 (12:23 +0000)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 29 Jan 2020 14:31:50 +0000 (14:31 +0000)
This is a workaround that emits a BTI after the function label if that
is followed by a patch area. We try to remove the BTI that follows the
patch area (this may fail e.g. if the first instruction is a PACIASP).

So before this commit -fpatchable-function-entry=3,1 with bti generates

    .section __patchable_function_entries
    .8byte .LPFE
    .text
  .LPFE:
    nop
  foo:
    nop
    nop
    bti c // or paciasp
    ...

and after this commit

    .section __patchable_function_entries
    .8byte .LPFE
    .text
  .LPFE:
    nop
  foo:
    bti c
    nop
    nop
    // may be paciasp
    ...

and with -fpatchable-function-entry=1 (M=0) the code now is

  foo:
    bti c
    .section __patchable_function_entries
    .8byte .LPFE
    .text
  .LPFE:
    nop
    // may be paciasp
    ...

There is a new bti insn in the middle of the patchable area users need
to be aware of unless M=0 (patch area is after the new bti) or M=N
(patch area is before the label, no new bti). Note: bti is not added to
all functions consistently (it can be turned off per function using a
target attribute or the compiler may detect that the function is never
called indirectly), so if bti is inserted in the middle of a patch area
then user code needs to deal with detecting it.

Tested on aarch64-none-linux-gnu.

gcc/ChangeLog:

PR target/92424
* config/aarch64/aarch64.c (aarch64_declare_function_name): Set
cfun->machine->label_is_assembled.
(aarch64_print_patchable_function_entry): New.
(TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY): Define.
* config/aarch64/aarch64.h (struct machine_function): New field,
label_is_assembled.

gcc/testsuite/ChangeLog:

PR target/92424
* gcc.target/aarch64/pr92424-2.c: New test.
* gcc.target/aarch64/pr92424-3.c: New test.

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/pr92424-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/pr92424-3.c [new file with mode: 0644]

index bf3c477e562f13cfcfed472354b1471ff76b4aa1..4e84692926f6cdc9ec31112e4db6c07850071c84 100644 (file)
@@ -1,3 +1,16 @@
+2020-01-29  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       Backport from mainline
+       2020-01-21  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       PR target/92424
+       * config/aarch64/aarch64.c (aarch64_declare_function_name): Set
+       cfun->machine->label_is_assembled.
+       (aarch64_print_patchable_function_entry): New.
+       (TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY): Define.
+       * config/aarch64/aarch64.h (struct machine_function): New field,
+       label_is_assembled.
+
 2020-01-27  Wilco Dijkstra  <wdijkstr@arm.com>
 
        PR target/92692
index d2a74a7e9d85875be092a19e7675835dbc7cb4d5..26a28570be9f7a9d99488f2851bbe09228e55a95 100644 (file)
@@ -15343,6 +15343,34 @@ aarch64_declare_function_name (FILE *stream, const char* name,
   /* Don't forget the type directive for ELF.  */
   ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function");
   ASM_OUTPUT_LABEL (stream, name);
+
+  cfun->machine->label_is_assembled = true;
+}
+
+/* Implement PRINT_PATCHABLE_FUNCTION_ENTRY.  Check if the patch area is after
+   the function label and emit a BTI if necessary.  */
+
+void
+aarch64_print_patchable_function_entry (FILE *file,
+                                       unsigned HOST_WIDE_INT patch_area_size,
+                                       bool record_p)
+{
+  if (cfun->machine->label_is_assembled
+      && aarch64_bti_enabled ()
+      && !cgraph_node::get (cfun->decl)->only_called_directly_p ())
+    {
+      /* Remove the BTI that follows the patch area and insert a new BTI
+        before the patch area right after the function label.  */
+      rtx_insn *insn = next_real_nondebug_insn (get_insns ());
+      if (insn
+         && INSN_P (insn)
+         && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+         && XINT (PATTERN (insn), 1) == UNSPECV_BTI_C)
+       delete_insn (insn);
+      asm_fprintf (file, "\thint\t34 // bti c\n");
+    }
+
+  default_print_patchable_function_entry (file, patch_area_size, record_p);
 }
 
 /* Implement ASM_OUTPUT_DEF_FROM_DECLS.  Output .variant_pcs for aliases.  */
@@ -18953,6 +18981,9 @@ aarch64_run_selftests (void)
 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
 #define TARGET_ASM_TRAMPOLINE_TEMPLATE aarch64_asm_trampoline_template
 
+#undef TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY
+#define TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY aarch64_print_patchable_function_entry
+
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST aarch64_build_builtin_va_list
 
index fc6df970c2e759b4f1975cb94e0f8b4b6612b75c..772a97296880688c13a3421a3d1c822444cb4a33 100644 (file)
@@ -731,6 +731,7 @@ typedef struct GTY (()) machine_function
   struct aarch64_frame frame;
   /* One entry for each hard register.  */
   bool reg_is_wrapped_separately[LAST_SAVED_REGNUM];
+  bool label_is_assembled;
 } machine_function;
 #endif
 
index 5b0b1b937228f684a9043c0290516703b53b88a0..f17f7f44a2e370efe04811c7f457f5cd25a5743e 100644 (file)
@@ -1,3 +1,12 @@
+2020-01-29  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       Backport from mainline
+       2020-01-21  Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       PR target/92424
+       * gcc.target/aarch64/pr92424-2.c: New test.
+       * gcc.target/aarch64/pr92424-3.c: New test.
+
 2020-01-26  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.target/i386/pr91298-1.c: xfail on Solaris/x86 with native
diff --git a/gcc/testsuite/gcc.target/aarch64/pr92424-2.c b/gcc/testsuite/gcc.target/aarch64/pr92424-2.c
new file mode 100644 (file)
index 0000000..0e75657
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+__attribute__ ((target("branch-protection=bti"),
+               patchable_function_entry (1, 0)))
+f10_bti ()
+{
+}
+/* { dg-final { scan-assembler "f10_bti:\n\thint\t34 // bti c\n.*\.LPFE1:\n\tnop\n.*\tret\n" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr92424-3.c b/gcc/testsuite/gcc.target/aarch64/pr92424-3.c
new file mode 100644 (file)
index 0000000..0a1f74d
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do "compile" } */
+/* { dg-options "-O1" } */
+
+/* Test the placement of the .LPFE1 label.  */
+
+void
+__attribute__ ((target("branch-protection=bti+pac-ret+leaf"),
+               patchable_function_entry (1, 0)))
+f10_pac ()
+{
+}
+/* { dg-final { scan-assembler "f10_pac:\n\thint\t34 // bti c\n.*\.LPFE1:\n\tnop\n.*\thint\t25 // paciasp\n.*\thint\t29 // autiasp\n.*\tret\n" } } */