Richard Earnshaw <richard.earns...@foss.arm.com> writes:

> On 14/09/2022 15:20, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> 
>> this patch enables address return signature and verification based on
>> Armv8.1-M Pointer Authentication [1].
>> 
>> To sign the return address, we use the PAC R12, LR, SP instruction
>> upon function entry.  This is signing LR using SP and storing the
>> result in R12.  R12 will be pushed into the stack.
>> 
>> During function epilogue R12 will be popped and AUT R12, LR, SP will
>> be used to verify that the content of LR is still valid before return.
>> 
>> Here an example of PAC instrumented function prologue and epilogue:
>> 
>> void foo (void);
>> 
>> int main()
>> {
>>    foo ();
>>    return 0;
>> }
>> 
>> Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
>> -mthumb' translates into:
>> 
>> main:
>>      pac     ip, lr, sp
>>      push    {r3, r7, ip, lr}
>>      add     r7, sp, #0
>>      bl      foo
>>      movs    r3, #0
>>      mov     r0, r3
>>      pop     {r3, r7, ip, lr}
>>      aut     ip, lr, sp
>>      bx      lr
>> 
>> The patch also takes care of generating a PACBTI instruction in place
>> of the sequence BTI+PAC when Branch Target Identification is enabled
>> contextually.
>> 
>> Ex. the previous example compiled with '-march=armv8.1-m.main
>> -mbranch-protection=pac-ret+bti -mthumb' translates into:
>> 
>> main:
>>      pacbti  ip, lr, sp
>>      push    {r3, r7, ip, lr}
>>      add     r7, sp, #0
>>      bl      foo
>>      movs    r3, #0
>>      mov     r0, r3
>>      pop     {r3, r7, ip, lr}
>>      aut     ip, lr, sp
>>      bx      lr
>> 
>> As part of previous upstream suggestions a test for varargs has been
>> added and '-mtpcs-frame' is deemed being incompatible with this return
>> signing address feature being introduced.
>> 
>> [1] 
>> <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
>> 
>> gcc/Changelog
>> 
>> 2021-11-03  Andrea Corallo  <andrea.cora...@arm.com>
>> 
>>      * config/arm/arm.c: (arm_compute_frame_layout)
>>      (arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
>>      (arm_conditional_register_usage): Update for pac codegen.
>>      (arm_current_function_pac_enabled_p): New function.
>>      * config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
>>      Add new patterns.
>>      * config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
>>      (UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
>> 
>> gcc/testsuite/Changelog
>> 
>> 2021-11-03  Andrea Corallo  <andrea.cora...@arm.com>
>> 
>>      * gcc.target/arm/pac.h : New file.
>>      * gcc.target/arm/pac-1.c : New test case.
>>      * gcc.target/arm/pac-2.c : Likewise.
>>      * gcc.target/arm/pac-3.c : Likewise.
>>      * gcc.target/arm/pac-4.c : Likewise.
>>      * gcc.target/arm/pac-5.c : Likewise.
>>      * gcc.target/arm/pac-6.c : Likewise.
>>      * gcc.target/arm/pac-7.c : Likewise.
>>      * gcc.target/arm/pac-8.c : Likewise.
>> 
>
> +  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && 
> arm_arch_cmse))
> +    error ("This architecture does not support branch protection 
> instructions");
>
> This test feels wrong.  What does having cmse give us?  I suspect you 
> want a test that ensures we have at least v8-m.main so that the NOP 
> instructions are correctly defined as NOPs (or, in this case, PACBTI 
> instructions) rather than unpredictable; but if that's the case then I 
> think you really want to write the test that way here (perhaps in a 
> macro) and then move this test into that so that it becomes 
> self-documenting - but don't we have a v8-m.main test anyway?

Yep

> +       if (arm_current_function_pac_enabled_p ())
> +         {
> +              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
> +           arm_emit_multi_reg_pop (saved_regs_mask);
> +           emit_insn (gen_aut_nop ());
> +           emit_jump_insn (simple_return_rtx);
> +         }
>
> The assert is using indents that are just spaces, but the other lines 
> use tabs.  Please use tabs everywhere rather than mixing like this.

Ack.

> +/* Return TRUE if return address signing mechanism is enabled.  */
> +bool
> +arm_current_function_pac_enabled_p (void)
> +{
> +  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
> +    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
> +     && !crtl->is_leaf);
> +}
>
> This is a case where you should use parenthesis around the expression so 
> that the continuation lines are correctly indented.

Ack.

> @@ -11518,7 +11518,7 @@ (define_expand "prologue"
>        arm_expand_prologue ();
>      else
>        thumb1_expand_prologue ();
> -  DONE;
> +   DONE;
>     "
>   )
>
> Although this is a trivial cleanup, it has nothing to do with this 
> patch.  Please remove.

Okay.

> +  "arm_arch7 && arm_arch_cmse"
>
> See my comments earlier about this test; the same applies here.
>
> +     (unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +                   UNSPEC_PAC_NOP))]
> +
> Again you have a mix of lines indented with tabs and lines indented with 
> just spaces.  Similarly with pacbti_nop and aut_nop.
>
> Do you have a test for the nested functions case (I can't see it, but 
> perhaps I've missed it somewhere)?

We have gcc/testsuite/gcc.target/arm/pac-7.c added by this patch.

> R.

  Andrea

Reply via email to