this affects the linux kernel and technically a wrong code bug so this fix tries to be backportable (fixing all issues with -fpatchable-function-entry=N,M will likely require new option).
gcc/ChangeLog: 2020-01-16 Szabolcs Nagy <szabolcs.n...@arm.com> PR target/92424 * config/aarch64/aarch64.c (aarch64_declare_function_name): Emit BTI c if the function label is followed by a patch area.
From ac2a46bab60ecc80a453328b4749a951908c02c5 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy <szabolcs.n...@arm.com> Date: Wed, 15 Jan 2020 12:23:40 +0000 Subject: [PATCH] [AArch64] PR92424: Fix -fpatchable-function-entry=N,M with BTI This is a minimal workaround that emits another BTI after the function label if that is followed by a patch area. 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 bti c // or paciasp ... There is a new bti insn in the middle of the patchable area unless M=0 (patch area is after the new bti) or M=N (patch area is before the label, no new bti). Note that .cfi_startproc and the asynchronous unwind table entry label comes after the patch area, but whatever effect that has on the newly inserted bti c, it already affected the insns in the patch area. Tested on aarch64-none-linux-gnu. gcc/ChangeLog: PR target/92424 * config/aarch64/aarch64.c (aarch64_declare_function_name): Emit BTI c if the function label is followed by a patch area. --- gcc/config/aarch64/aarch64.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 66e20becaf2..0394c274330 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -18079,6 +18079,39 @@ 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); + + if (!aarch64_bti_enabled () + || cgraph_node::get (fndecl)->only_called_directly_p ()) + return; + + /* Copy logic from varasm.c assemble_start_function + to handle -fpatchable-function-entry=N,M with BTI. */ + unsigned HOST_WIDE_INT patch_area_size = function_entry_patch_area_size; + unsigned HOST_WIDE_INT patch_area_entry = function_entry_patch_area_start; + + tree patchable_function_entry_attr + = lookup_attribute ("patchable_function_entry", DECL_ATTRIBUTES (fndecl)); + if (patchable_function_entry_attr) + { + tree pp_val = TREE_VALUE (patchable_function_entry_attr); + tree patchable_function_entry_value1 = TREE_VALUE (pp_val); + + patch_area_size = tree_to_uhwi (patchable_function_entry_value1); + patch_area_entry = 0; + if (TREE_CHAIN (pp_val) != NULL_TREE) + { + tree patchable_function_entry_value2 + = TREE_VALUE (TREE_CHAIN (pp_val)); + patch_area_entry = tree_to_uhwi (patchable_function_entry_value2); + } + } + + if (patch_area_entry > patch_area_size) + patch_area_entry = 0; + + /* Emit a BTI c if a patch area comes after the function label. */ + if (patch_area_size > patch_area_entry) + asm_fprintf (stream, "\thint\t34 // bti c\n"); } /* Implement ASM_OUTPUT_DEF_FROM_DECLS. Output .variant_pcs for aliases. */ -- 2.17.1