[PATCH][AArch64] PR92424: Fix -fpatchable-function-entry=N,M with BTI
FÃÂng-ruì Sòng via gcc-patches
gcc-patches@gcc.gnu.org
Sun Jan 19 11:04:00 GMT 2020
On 2020-01-16, Richard Sandiford wrote:
>Szabolcs Nagy <Szabolcs.Nagy@arm.com> writes:
>> 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).
>
>Even for the backportable version, I think it would be better
>not to duplicate so much varasm stuff.
>
>Perhaps instead we could:
>
>(a) set a cfun->machine flag in aarch64_declare_function_name
> to say that we've assembled the label
>
>(b) override print_patchable_function_entry so that it prints a BTI if
> this flag is set and the usual other conditions are true
>
>As discussed off-list, it'd be good to avoid a second BTI after the
>nops if possible. print_patchable_function_entry should be able
>to find the first instruction using get_insns and next_real_insn,
>then remove it if it turns out to be a BTI.
>
>Thanks,
>Richard
It'd be great to have some tests, e.g.
1. -fpatchable-function-entry=0 -mbranch-protection=bti
2. -fpatchable-function-entry=2 -mbranch-protection=bti
I have updated clang to emit `.Lfunc_begin0: bti c; nop; nop` for case 2.
The __patchable_function_entries entry points to .Lfunc_begin0 (bti c).
(The change is not included in the llvm 10.0 branch.)
I think we can address all except the SHF_WRITE issue in a backward
compatible manner. For some items listed in
https://gcc.gnu.org/ml/gcc/2020-01/msg00067.html , the fixes require GNU as
(https://sourceware.org/bugzilla/show_bug.cgi?id=25380 https://sourceware.org/bugzilla/show_bug.cgi?id=25381)
and ld features (https://sourceware.org/ml/binutils/2019-11/msg00266.html).
>>
>> gcc/ChangeLog:
>>
>> 2020-01-16 Szabolcs Nagy <szabolcs.nagy@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.nagy@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. */
More information about the Gcc-patches
mailing list