Szabolcs Nagy <szabolcs.n...@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

>
> 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.  */

Reply via email to