[PATCH] aarch64: libgcc: Cleanup ELF marking in asm

2024-01-30 Thread Szabolcs Nagy
Use aarch64-asm.h in asm code consistently, this was started in

  commit c608ada288ced0268c1fd4136f56c34b24d4
  Author: Zac Walker 
  CommitDate: 2024-01-23 15:32:30 +

  Ifdef `.hidden`, `.type`, and `.size` pseudo-ops for `aarch64-w64-mingw32` 
target

But that commit failed to remove some existing markings from asm files,
which means some objects got double marked with gnu property notes.

libgcc/ChangeLog:

* config/aarch64/crti.S: Remove stack marking.
* config/aarch64/crtn.S: Remove stack marking, include aarch64-asm.h
* config/aarch64/lse.S: Remove stack and GNU property markings.
---
 libgcc/config/aarch64/crti.S |  6 --
 libgcc/config/aarch64/crtn.S |  6 +-
 libgcc/config/aarch64/lse.S  | 40 
 3 files changed, 1 insertion(+), 51 deletions(-)

diff --git a/libgcc/config/aarch64/crti.S b/libgcc/config/aarch64/crti.S
index b6805b86421..52ca1bb56d6 100644
--- a/libgcc/config/aarch64/crti.S
+++ b/libgcc/config/aarch64/crti.S
@@ -23,12 +23,6 @@
 
 #include "aarch64-asm.h"
 
-/* An executable stack is *not* required for these functions.  */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
 # This file creates a stack frame for the contents of the .fini and
 # .init sections.  Users may put any desired instructions in those
 # sections.
diff --git a/libgcc/config/aarch64/crtn.S b/libgcc/config/aarch64/crtn.S
index 59f2441032a..67bcfab8564 100644
--- a/libgcc/config/aarch64/crtn.S
+++ b/libgcc/config/aarch64/crtn.S
@@ -21,11 +21,7 @@
 # see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 # .
 
-/* An executable stack is *not* required for these functions.  */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
+#include "aarch64-asm.h"
 
 # This file just makes sure that the .fini and .init sections do in
 # fact return.  Users may put any desired instructions in those sections.
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index cee1e88c6a4..ecef47086c6 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -315,43 +315,3 @@ STARTFNNAME(LDNM)
 
 ENDFN  NAME(LDNM)
 #endif
-
-/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
-#define FEATURE_1_AND 0xc000
-#define FEATURE_1_BTI 1
-#define FEATURE_1_PAC 2
-
-/* Supported features based on the code generation options.  */
-#if defined(__ARM_FEATURE_BTI_DEFAULT)
-# define BTI_FLAG FEATURE_1_BTI
-#else
-# define BTI_FLAG 0
-#endif
-
-#if __ARM_FEATURE_PAC_DEFAULT & 3
-# define PAC_FLAG FEATURE_1_PAC
-#else
-# define PAC_FLAG 0
-#endif
-
-/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
-#define GNU_PROPERTY(type, value)  \
-  .section .note.gnu.property, "a";\
-  .p2align 3;  \
-  .word 4; \
-  .word 16;\
-  .word 5; \
-  .asciz "GNU";\
-  .word type;  \
-  .word 4; \
-  .word value; \
-  .word 0;
-
-#if defined(__linux__) || defined(__FreeBSD__)
-.section .note.GNU-stack, "", %progbits
-
-/* Add GNU property note if built with branch protection.  */
-# if (BTI_FLAG|PAC_FLAG) != 0
-GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
-# endif
-#endif
-- 
2.25.1



Re: [RFC] Either fix or disable SME feature for `aarch64-w64-mingw32` target?

2024-01-25 Thread Szabolcs Nagy
this patch added double notes on crt*.o and lse derived objects.
(which does not seem to cause build break but some linkers may
not like it)

after #include "aarch64-asm.h" all gnu-stack and gnu-property
related stuff should be removed since the header takes care of it.





Re: [RFC] Either fix or disable SME feature for `aarch64-w64-mingw32` target?

2024-01-25 Thread Szabolcs Nagy
The 01/15/2024 17:21, Radek Barton wrote:


v4-0001-Ifdef-.hidden-.type-and-.size-pseudo-ops-for-aarc.patch
Description: v4-0001-Ifdef-.hidden-.type-and-.size-pseudo-ops-for-aarc.patch


[PATCH v2] aarch64: Fix eh_return for -mtrack-speculation [PR112987]

2024-01-25 Thread Szabolcs Nagy
Recent commit introduced a conditional branch in eh_return epilogues
that is not compatible with speculation tracking:

  commit 426fddcbdad6746fe70e031f707fb07f55dfb405
  Author: Szabolcs Nagy 
  CommitDate: 2023-11-27 15:52:48 +

  aarch64: Use br instead of ret for eh_return

Refactor the compare zero and jump pattern and use it to fix the issue.

gcc/ChangeLog:

PR target/112987
* config/aarch64/aarch64.cc (aarch64_gen_compare_zero_and_branch): New.
(aarch64_expand_epilogue): Use the new function.
(aarch64_split_compare_and_swap): Likewise.
(aarch64_split_atomic_op): Likewise.
---
v2: factor out aarch64_gen_compare_zero_and_branch

 gcc/config/aarch64/aarch64.cc | 75 +++
 1 file changed, 32 insertions(+), 43 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 3d6dd98c5c5..d2014ce1527 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -2637,6 +2637,28 @@ aarch64_gen_compare_reg_maybe_ze (RTX_CODE code, rtx x, 
rtx y,
   return aarch64_gen_compare_reg (code, x, y);
 }
 
+/* Generate conditional branch to LABEL, comparing X to 0 using CODE.
+   Return the jump instruction.  */
+
+static rtx
+aarch64_gen_compare_zero_and_branch (rtx_code code, rtx x,
+rtx_code_label *label)
+{
+  if (aarch64_track_speculation)
+{
+  /* Emit an explicit compare instruction, so that we can correctly
+track the condition codes.  */
+  rtx cc_reg = aarch64_gen_compare_reg (code, x, const0_rtx);
+  x = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+}
+  else
+x = gen_rtx_fmt_ee (code, VOIDmode, x, const0_rtx);
+
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
+   gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
+  return gen_rtx_SET (pc_rtx, x);
+}
+
 /* Consider the operation:
 
  OPERANDS[0] = CODE (OPERANDS[1], OPERANDS[2]) + OPERANDS[3]
@@ -9882,11 +9904,10 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
 to be SP; letting the CFA move during this adjustment
 is just as correct as retaining the CFA from the body
 of the function.  Therefore, do nothing special.  */
-  rtx label = gen_label_rtx ();
-  rtx x = gen_rtx_EQ (VOIDmode, EH_RETURN_TAKEN_RTX, const0_rtx);
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
-   gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
-  rtx jump = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
+  rtx_code_label *label = gen_label_rtx ();
+  rtx x = aarch64_gen_compare_zero_and_branch (EQ, EH_RETURN_TAKEN_RTX,
+  label);
+  rtx jump = emit_jump_insn (x);
   JUMP_LABEL (jump) = label;
   LABEL_NUSES (label)++;
   emit_insn (gen_add2_insn (stack_pointer_rtx,
@@ -24657,19 +24678,8 @@ aarch64_split_compare_and_swap (rtx operands[])
 
   if (!is_weak)
 {
-  if (aarch64_track_speculation)
-   {
- /* Emit an explicit compare instruction, so that we can correctly
-track the condition codes.  */
- rtx cc_reg = aarch64_gen_compare_reg (NE, scratch, const0_rtx);
- x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx);
-   }
-  else
-   x = gen_rtx_NE (VOIDmode, scratch, const0_rtx);
-
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
-   gen_rtx_LABEL_REF (Pmode, label1), pc_rtx);
-  aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
+  x = aarch64_gen_compare_zero_and_branch (NE, scratch, label1);
+  aarch64_emit_unlikely_jump (x);
 }
   else
 aarch64_gen_compare_reg (NE, scratch, const0_rtx);
@@ -24685,18 +24695,8 @@ aarch64_split_compare_and_swap (rtx operands[])
   emit_label (label2);
   aarch64_emit_store_exclusive (mode, scratch, mem, rval, model_rtx);
 
-  if (aarch64_track_speculation)
-   {
- /* Emit an explicit compare instruction, so that we can correctly
-track the condition codes.  */
- rtx cc_reg = aarch64_gen_compare_reg (NE, scratch, const0_rtx);
- x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx);
-   }
-  else
-   x = gen_rtx_NE (VOIDmode, scratch, const0_rtx);
-  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
-   gen_rtx_LABEL_REF (Pmode, label1), pc_rtx);
-  aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x));
+  x = aarch64_gen_compare_zero_and_branch (NE, scratch, label1);
+  aarch64_emit_unlikely_jump (x);
 
   label2 = label3;
 }
@@ -24780,19 +24780,8 @@ aarch64_split_atomic_op (enum rtx_code code, rtx 
old_out, rtx new_out, rtx mem,
   aarch64_emit_store_exclusive (mode, cond, mem,
gen_lowpart (mode, new_out), model_rtx);
 
-  if (aarch64_track_speculation)
-{
-  /* Emit an explicit compare instruction, so that we can correctly
-track

[PATCH] aarch64: Fix eh_return for -mtrack-speculation [PR112987]

2024-01-17 Thread Szabolcs Nagy
Recent commit introduced a conditional branch in eh_return epilogues
that is not compatible with speculation tracking:

  commit 426fddcbdad6746fe70e031f707fb07f55dfb405
  Author: Szabolcs Nagy 
  CommitDate: 2023-11-27 15:52:48 +

  aarch64: Use br instead of ret for eh_return

gcc/ChangeLog:

PR target/112987
* config/aarch64/aarch64.cc (aarch64_expand_epilogue): Use
explicit compare and separate jump with speculation tracking.
---
 gcc/config/aarch64/aarch64.cc | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index e6bd3fd0bb4..e6de62dc02a 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9879,7 +9879,17 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
 is just as correct as retaining the CFA from the body
 of the function.  Therefore, do nothing special.  */
   rtx label = gen_label_rtx ();
-  rtx x = gen_rtx_EQ (VOIDmode, EH_RETURN_TAKEN_RTX, const0_rtx);
+  rtx x;
+  if (aarch64_track_speculation)
+   {
+ /* Emit an explicit compare, so cc can be tracked.  */
+ rtx cc_reg = aarch64_gen_compare_reg (EQ,
+   EH_RETURN_TAKEN_RTX,
+   const0_rtx);
+ x = gen_rtx_EQ (GET_MODE (cc_reg), cc_reg, const0_rtx);
+   }
+  else
+   x = gen_rtx_EQ (VOIDmode, EH_RETURN_TAKEN_RTX, const0_rtx);
   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
   rtx jump = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
-- 
2.25.1



Re: [PATCH v2 7/7] aarch64,arm: Move branch-protection data to targets

2024-01-11 Thread Szabolcs Nagy
The 12/07/2023 13:13, Richard Earnshaw wrote:
> On 03/11/2023 15:36, Szabolcs Nagy wrote:
> > * config/aarch64/aarch64.cc (aarch_handle_no_branch_protection): Copy.
> > (aarch_handle_standard_branch_protection): Copy.
> > (aarch_handle_pac_ret_protection): Copy.
> > (aarch_handle_pac_ret_leaf): Copy.
> > (aarch_handle_pac_ret_b_key): Copy.
> > (aarch_handle_bti_protection): Copy.
> 
> I think all of the above functions that have been moved back from
> aarch-common should be renamed back to aarch64_..., unless they are directly
> referenced statically by code in aarch-common.c.

done.

> > +const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
> 
> can this be made static now?  And maybe pass the structure as a parameter if
> that's not done already.

done in v4.

> It would be nice if, when we raise an error, we could print out the list of
> valid options (and modifiers), much like we do on Arm for -march/-mcpu.
> 
> eg.
> $ gcc -mcpu=crotex-a8
> cc1: error: unrecognised -mcpu target: crotex-a8
> cc1: note: valid arguments are: arm8 arm810 strongarm strongarm110 fa526
> [...rest of list]; did you mean ‘cortex-a8’?

i implemented this with candidates_list_and_hint but it does
not work very well if the typo is in a subtype, so i think
this should be done in a separate patch if at all.



[PATCH v4] aarch64,arm: Move branch-protection data to targets

2024-01-11 Thread Szabolcs Nagy
The branch-protection types are target specific, not the same on arm
and aarch64.  This currently affects pac-ret+b-key, but there will be
a new type on aarch64 that is not relevant for arm.

After the move, change aarch_ identifiers to aarch64_ or arm_ as
appropriate.

Refactor aarch_validate_mbranch_protection to take the target specific
branch-protection types as an argument.

In case of invalid input currently no hints are provided: the way
branch-protection types and subtypes can be mixed makes it difficult
without causing confusion.

gcc/ChangeLog:

* config/aarch64/aarch64.md: Rename aarch_ to aarch64_.
* config/aarch64/aarch64.opt: Likewise.
* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Likewise.
* config/aarch64/aarch64.cc (aarch64_expand_prologue): Likewise.
(aarch64_expand_epilogue): Likewise.
(aarch64_post_cfi_startproc): Likewise.
(aarch64_handle_no_branch_protection): Copy and rename.
(aarch64_handle_standard_branch_protection): Likewise.
(aarch64_handle_pac_ret_protection): Likewise.
(aarch64_handle_pac_ret_leaf): Likewise.
(aarch64_handle_pac_ret_b_key): Likewise.
(aarch64_handle_bti_protection): Likewise.
(aarch64_override_options): Update branch protection validation.
(aarch64_handle_attr_branch_protection): Likewise.
* config/arm/aarch-common-protos.h (aarch_validate_mbranch_protection):
Pass branch protection type description as argument.
(struct aarch_branch_protect_type): Move from aarch-common.h.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Remove.
(aarch_handle_standard_branch_protection): Remove.
(aarch_handle_pac_ret_protection): Remove.
(aarch_handle_pac_ret_leaf): Remove.
(aarch_handle_pac_ret_b_key): Remove.
(aarch_handle_bti_protection): Remove.
(aarch_validate_mbranch_protection): Pass branch protection type
description as argument.
* config/arm/aarch-common.h (enum aarch_key_type): Remove.
(struct aarch_branch_protect_type): Remove.
* config/arm/arm-c.cc (arm_cpu_builtins): Remove aarch_ra_sign_key.
* config/arm/arm.cc (arm_handle_no_branch_protection): Copy and rename.
(arm_handle_standard_branch_protection): Likewise.
(arm_handle_pac_ret_protection): Likewise.
(arm_handle_pac_ret_leaf): Likewise.
(arm_handle_bti_protection): Likewise.
(arm_configure_build_target): Update branch protection validation.
* config/arm/arm.opt: Remove aarch_ra_sign_key.
---
v4:
- pass types as argument to validation.
- make target specific types data static.

 gcc/config/aarch64/aarch64-c.cc  |  4 +-
 gcc/config/aarch64/aarch64.cc| 75 
 gcc/config/aarch64/aarch64.md|  2 +-
 gcc/config/aarch64/aarch64.opt   |  2 +-
 gcc/config/arm/aarch-common-protos.h | 19 ++-
 gcc/config/arm/aarch-common.cc   | 71 --
 gcc/config/arm/aarch-common.h| 20 
 gcc/config/arm/arm-c.cc  |  2 -
 gcc/config/arm/arm.cc| 55 +---
 gcc/config/arm/arm.opt   |  3 --
 10 files changed, 145 insertions(+), 108 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index c3bc8c49034..b5a6917d06d 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -235,9 +235,9 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
 {
   int v = 0;
-  if (aarch_ra_sign_key == AARCH_KEY_A)
+  if (aarch64_ra_sign_key == AARCH64_KEY_A)
v |= 1;
-  if (aarch_ra_sign_key == AARCH_KEY_B)
+  if (aarch64_ra_sign_key == AARCH64_KEY_B)
v |= 2;
   if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
v |= 4;
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index a5a6b52730d..3ae8fc1878f 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9478,12 +9478,12 @@ aarch64_expand_prologue (void)
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
 {
-  switch (aarch_ra_sign_key)
+  switch (aarch64_ra_sign_key)
{
- case AARCH_KEY_A:
+ case AARCH64_KEY_A:
insn = emit_insn (gen_paciasp ());
break;
- case AARCH_KEY_B:
+ case AARCH64_KEY_B:
insn = emit_insn (gen_pacibsp ());
break;
  default:
@@ -9897,12 +9897,12 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
   if (aarch64_return_address_signing_enabled ()
   && (sibcall || !TARGET_ARMV8_3))
 {
-  switch (aarch_ra_sign_key)
+  switch (aarch64_ra_sign_key)
{
- case AARCH_KEY_A:
+ case AARCH64_KEY_A:
insn = emit_insn (gen_autiasp 

[PATCH] aarch64: fortran: Adjust vect-8.f90 for libmvec

2023-12-28 Thread Szabolcs Nagy
With new glibc one more loop can be vectorized via simd exp in libmvec.

Found by the Linaro TCWG CI.

gcc/testsuite/ChangeLog:

* gfortran/vect/vect-8.f90: Accept more vectorized loops.
---
 gcc/testsuite/gfortran.dg/vect/vect-8.f90 | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gfortran.dg/vect/vect-8.f90 
b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
index ca72ddcffca..938dfc29754 100644
--- a/gcc/testsuite/gfortran.dg/vect/vect-8.f90
+++ b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
@@ -704,7 +704,7 @@ CALL track('KERNEL  ')
 RETURN
 END SUBROUTINE kernel
 
-! { dg-final { scan-tree-dump-times "vectorized 25 loops" 1 "vect" { target 
aarch64_sve } } }
-! { dg-final { scan-tree-dump-times "vectorized 24 loops" 1 "vect" { target { 
aarch64*-*-* && { ! aarch64_sve } } } } }
+! { dg-final { scan-tree-dump-times "vectorized 2\[56\] loops" 1 "vect" { 
target aarch64_sve } } }
+! { dg-final { scan-tree-dump-times "vectorized 2\[45\] loops" 1 "vect" { 
target { aarch64*-*-* && { ! aarch64_sve } } } } }
 ! { dg-final { scan-tree-dump-times "vectorized 2\[234\] loops" 1 "vect" { 
target { vect_intdouble_cvt && { ! aarch64*-*-* } } } } }
 ! { dg-final { scan-tree-dump-times "vectorized 17 loops" 1 "vect" { target { 
{ ! vect_intdouble_cvt } && { ! aarch64*-*-* } } } } }
-- 
2.25.1



[PATCH v3] aarch64,arm: Move branch-protection data to targets

2023-12-12 Thread Szabolcs Nagy
The branch-protection types are target specific, not the same on arm
and aarch64.  This currently affects pac-ret+b-key, but there will be
a new type on aarch64 that is not relevant for arm.

After the move, change aarch_ identifiers to aarch64_ or arm_ as
appropriate.

gcc/ChangeLog:

* config/aarch64/aarch64.md: Rename aarch_ to aarch64_.
* config/aarch64/aarch64.opt: Likewise.
* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Likewise.
* config/aarch64/aarch64.cc (aarch64_expand_prologue): Likewise.
(aarch64_expand_epilogue): Likewise.
(aarch64_post_cfi_startproc): Likewise.
(aarch64_handle_no_branch_protection): Copy and rename.
(aarch64_handle_standard_branch_protection): Likewise.
(aarch64_handle_pac_ret_protection): Likewise.
(aarch64_handle_pac_ret_leaf): Likewise.
(aarch64_handle_pac_ret_b_key): Likewise.
(aarch64_handle_bti_protection): Likewise.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Remove.
(aarch_handle_standard_branch_protection): Remove.
(aarch_handle_pac_ret_protection): Remove.
(aarch_handle_pac_ret_leaf): Remove.
(aarch_handle_pac_ret_b_key): Remove.
(aarch_handle_bti_protection): Remove.
* config/arm/aarch-common.h (enum aarch_key_type): Remove.
(struct aarch_branch_protect_type): Declare.
* config/arm/arm-c.cc (arm_cpu_builtins): Remove aarch_ra_sign_key.
* config/arm/arm.cc (arm_handle_no_branch_protection): Copy and rename.
(arm_handle_standard_branch_protection): Likewise.
(arm_handle_pac_ret_protection): Likewise.
(arm_handle_pac_ret_leaf): Likewise.
(arm_handle_bti_protection): Likewise.
(arm_configure_build_target): Likewise.
* config/arm/arm.opt: Remove aarch_ra_sign_key.
---
v3: aarch_ to aarch64_/arm_ renames.
---
 gcc/config/aarch64/aarch64-c.cc |  4 +-
 gcc/config/aarch64/aarch64.cc   | 69 +
 gcc/config/aarch64/aarch64.md   |  2 +-
 gcc/config/aarch64/aarch64.opt  |  2 +-
 gcc/config/arm/aarch-common.cc  | 55 --
 gcc/config/arm/aarch-common.h   | 11 +++---
 gcc/config/arm/arm-c.cc |  2 -
 gcc/config/arm/arm.cc   | 52 ++---
 gcc/config/arm/arm.opt  |  3 --
 9 files changed, 117 insertions(+), 83 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index 115a2a8b756..553c99845e2 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -235,9 +235,9 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
 {
   int v = 0;
-  if (aarch_ra_sign_key == AARCH_KEY_A)
+  if (aarch64_ra_sign_key == AARCH64_KEY_A)
v |= 1;
-  if (aarch_ra_sign_key == AARCH_KEY_B)
+  if (aarch64_ra_sign_key == AARCH64_KEY_B)
v |= 2;
   if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
v |= 4;
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 9530618abea..dfd374c901e 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9461,12 +9461,12 @@ aarch64_expand_prologue (void)
   /* Sign return address for functions.  */
   if (aarch64_return_address_signing_enabled ())
 {
-  switch (aarch_ra_sign_key)
+  switch (aarch64_ra_sign_key)
{
- case AARCH_KEY_A:
+ case AARCH64_KEY_A:
insn = emit_insn (gen_paciasp ());
break;
- case AARCH_KEY_B:
+ case AARCH64_KEY_B:
insn = emit_insn (gen_pacibsp ());
break;
  default:
@@ -9880,12 +9880,12 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
   if (aarch64_return_address_signing_enabled ()
   && (sibcall || !TARGET_ARMV8_3))
 {
-  switch (aarch_ra_sign_key)
+  switch (aarch64_ra_sign_key)
{
- case AARCH_KEY_A:
+ case AARCH64_KEY_A:
insn = emit_insn (gen_autiasp ());
break;
- case AARCH_KEY_B:
+ case AARCH64_KEY_B:
insn = emit_insn (gen_autibsp ());
break;
  default:
@@ -18541,6 +18541,61 @@ aarch64_set_asm_isa_flags (aarch64_feature_flags flags)
   aarch64_set_asm_isa_flags (_options, flags);
 }
 
+static void
+aarch64_handle_no_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+  aarch_enable_bti = 0;
+}
+
+static void
+aarch64_handle_standard_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch64_ra_sign_key = AARCH64_KEY_A;
+  aarch_enable_bti = 1;
+}
+
+static void
+aarch64_handle_pac_ret_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch64_ra_sign_key = AARCH64_KEY_A;
+}
+
+static void
+aarch64_handle_pac_ret_leaf (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+}
+
+static 

Re: [PATCH] libatomic: Add rcpc3 128-bit atomic operations for AArch64

2023-12-08 Thread Szabolcs Nagy
The 11/13/2023 11:47, Victor Do Nascimento wrote:
> +/* LRCPC atomic support encoded in ID_AA64ISAR1_EL1.Atomic,
> +   bits[23:20].  The expected value is 0b0011.  Check that.  */
> +#define HAS_LRCPC3() ({  \
> +  unsigned long val; \
> +  asm volatile ("mrs %0, ID_AA64ISAR1_EL1" : "=r" (val));\
> +  (val & 0xf0) >= 0x30;  \
> +})

same comment as for the lse128 patch: use hwcaps
(and wait for linux release before committing).


Re: [PATCH v2 2/2] libatomic: Enable LSE128 128-bit atomics for armv9.4-a

2023-12-08 Thread Szabolcs Nagy
The 11/29/2023 15:15, Richard Earnshaw wrote:
> On 13/11/2023 11:37, Victor Do Nascimento wrote:
> > +/* LSE128 atomic support encoded in ID_AA64ISAR0_EL1.Atomic,
> > +   bits[23:20].  The expected value is 0b0011.  Check that.  */
> > +#define HAS_LSE128() ({\
> > +  unsigned long val;   \
> > +  asm volatile ("mrs %0, ID_AA64ISAR0_EL1" : "=r" (val));  \
> > +  (val & 0xf0) >= 0x30;\
> > +})
> > +
> 
> The pseudo-code for this register reads:
> 
> if PSTATE.EL == EL0 then
>   if IsFeatureImplemented(FEAT_IDST) then
> if EL2Enabled() && HCR_EL2.TGE == '1' then
>   AArch64.SystemAccessTrap(EL2, 0x18);
> else
>   AArch64.SystemAccessTrap(EL1, 0x18);
>   else
> UNDEFINED;
> ...
> 
> So this instruction may result in SIGILL if run on cores without FEAT_IDST.
> SystemAccessTrap just punts the problem up to the kernel or hypervisor as
> well.

yes, HWCAP_CPUID has to be checked to see if
linux traps and emulates the mrs for userspace.

> I think we need a hwcap bit to work this out, which is the preferred way on

yes, use hwcap instead of id reg (hwcap2 is
passed to aarch64 ifuncs or __getauxval works)

> Linux anyway.  Something like this? :) 
> https://lore.kernel.org/linux-arm-kernel/20231003124544.858804-2-joey.go...@arm.com/T/

note that there was no linux release since this
got added.

we can add the hwcap values tentatively, but
there is a risk of revert on the kernel side
(which means libatomic vs linux abi break) so
i would only commit the patch into gcc after
a linux release is tagged.


[committed] libgcc: Fix config.in

2023-12-08 Thread Szabolcs Nagy
It was updated incorrectly in

  commit dbbfb52b0e9c66ee9d05b8fd17c4f44655e48463
  Author: Szabolcs Nagy 
  CommitDate: 2023-12-08 11:29:06 +

libgcc: aarch64: Configure check for __getauxval

so regenerate it.

libgcc/ChangeLog:

* config.in: Regenerate.
---
 libgcc/config.in | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libgcc/config.in b/libgcc/config.in
index 441d4d39b95..8f7dd437b0e 100644
--- a/libgcc/config.in
+++ b/libgcc/config.in
@@ -16,9 +16,6 @@
 /* Define to 1 if the assembler supports .variant_pcs. */
 #undef HAVE_AS_VARIANT_PCS
 
-/* Define to 1 if __getauxval is available. */
-#undef HAVE___GETAUXVAL
-
 /* Define to 1 if the target assembler supports thread-local storage. */
 #undef HAVE_CC_TLS
 
@@ -67,6 +64,9 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if __getauxval is available. */
+#undef HAVE___GETAUXVAL
+
 /* Define to the address where bug reports for this package should be sent. */
 #undef PACKAGE_BUGREPORT
 
-- 
2.25.1



[PATCH v2] libgcc: aarch64: Add SME runtime support

2023-12-08 Thread Szabolcs Nagy
The call ABI for SME (Scalable Matrix Extension) requires a number of
helper routines which are added to libgcc so they are tied to the
compiler version instead of the libc version. See
https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#sme-support-routines

The routines are in shared libgcc and static libgcc eh, even though
they are not related to exception handling.  This is to avoid linking
a copy of the routines into dynamic linked binaries, because TPIDR2_EL0
block can be extended in the future which is better to handle in a
single place per process.

The support routines have to decide if SME is accessible or not. Linux
tells userspace if SME is accessible via AT_HWCAP2, otherwise a new
__aarch64_sme_accessible symbol was introduced that a libc can define.
Due to libgcc and libc build order, the symbol availability cannot be
checked so for __aarch64_sme_accessible an unistd.h feature test macro
is used while such detection mechanism is not available for __getauxval
so we rely on configure checks based on the target triplet.

Asm helper code is added to make writing the routines easier.

libgcc/ChangeLog:

* config/aarch64/t-aarch64: Add sources to the build.
* config/aarch64/__aarch64_have_sme.c: New file.
* config/aarch64/__arm_sme_state.S: New file.
* config/aarch64/__arm_tpidr2_restore.S: New file.
* config/aarch64/__arm_tpidr2_save.S: New file.
* config/aarch64/__arm_za_disable.S: New file.
* config/aarch64/aarch64-asm.h: New file.
* config/aarch64/libgcc-sme.ver: New file.
---
v2:
- do not include unistd.h when inhibit_libc is set.
- use msr tpidr2_el0,xzr in __arm_za_disable.

 libgcc/config/aarch64/__aarch64_have_sme.c   |  75 ++
 libgcc/config/aarch64/__arm_sme_state.S  |  55 ++
 libgcc/config/aarch64/__arm_tpidr2_restore.S |  89 
 libgcc/config/aarch64/__arm_tpidr2_save.S| 101 +++
 libgcc/config/aarch64/__arm_za_disable.S |  65 
 libgcc/config/aarch64/aarch64-asm.h  |  98 ++
 libgcc/config/aarch64/libgcc-sme.ver |  24 +
 libgcc/config/aarch64/t-aarch64  |  10 ++
 8 files changed, 517 insertions(+)
 create mode 100644 libgcc/config/aarch64/__aarch64_have_sme.c
 create mode 100644 libgcc/config/aarch64/__arm_sme_state.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_restore.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_save.S
 create mode 100644 libgcc/config/aarch64/__arm_za_disable.S
 create mode 100644 libgcc/config/aarch64/aarch64-asm.h
 create mode 100644 libgcc/config/aarch64/libgcc-sme.ver

diff --git a/libgcc/config/aarch64/__aarch64_have_sme.c 
b/libgcc/config/aarch64/__aarch64_have_sme.c
new file mode 100644
index 000..5e649246270
--- /dev/null
+++ b/libgcc/config/aarch64/__aarch64_have_sme.c
@@ -0,0 +1,75 @@
+/* Initializer for SME support.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   .  */
+
+#include "auto-target.h"
+
+#ifndef inhibit_libc
+/* For libc feature test macros.  */
+# include 
+#endif
+
+#if __ARM_FEATURE_SME
+/* Avoid runtime SME detection if libgcc is built with SME.  */
+# define HAVE_SME_CONST const
+# define HAVE_SME_VALUE 1
+#elif HAVE___GETAUXVAL
+/* SME access detection on Linux.  */
+# define HAVE_SME_CONST
+# define HAVE_SME_VALUE 0
+# define HAVE_SME_CTOR sme_accessible ()
+
+# define AT_HWCAP2 26
+# define HWCAP2_SME(1 << 23)
+unsigned long int __getauxval (unsigned long int);
+
+static _Bool
+sme_accessible (void)
+{
+  unsigned long hwcap2 = __getauxval (AT_HWCAP2);
+  return (hwcap2 & HWCAP2_SME) != 0;
+}
+#elif __LIBC___AARCH64_SME_ACCESSIBLE
+/* Alternative SME access detection.  */
+# define HAVE_SME_CONST
+# define HAVE_SME_VALUE 0
+# define HAVE_SME_CTOR __aarch64_sme_accessible ()
+_Bool __aarch64_sme_accessible (void);
+#else
+# define HAVE_SME_CONST const
+# define HAVE_SME_VALUE 0
+#endif
+
+/* Define the symbol gating SME support in libgcc.  */

Re: [PATCH 3/4] libgcc: aarch64: Add SME runtime support

2023-12-07 Thread Szabolcs Nagy
The 12/07/2023 17:36, Richard Sandiford wrote:
> Szabolcs Nagy  writes:
> > +
> > +#include "auto-target.h"
> > +#include 
> > +

sorry, this seems to fail when building --without-headers

i will respin this, handling the 'inhibit_libc' case.


[PATCH 4/4] libgcc: aarch64: Add SME unwinder support

2023-12-07 Thread Szabolcs Nagy
To support the ZA lazy save scheme, the PCS requires the unwinder to
reset the SME state to PSTATE.SM=0, PSTATE.ZA=0, TPIDR2_EL0=0 on entry
to an exception handler. We use the __arm_za_disable SME runtime call
unconditionally to achieve this.
https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#exceptions

The hidden alias is used to avoid a PLT and avoid inconsistent VPCS
marking (we don't rely on special PCS at the call site). In case of
static linking the SME runtime init code is linked in code that raises
exceptions.

libgcc/ChangeLog:

* config/aarch64/__arm_za_disable.S: Add hidden alias.
* config/aarch64/aarch64-unwind.h: Reset the SME state before
EH return via the _Unwind_Frames_Extra hook.
---
 libgcc/config/aarch64/__arm_za_disable.S |  5 +
 libgcc/config/aarch64/aarch64-unwind.h   | 16 
 2 files changed, 21 insertions(+)

diff --git a/libgcc/config/aarch64/__arm_za_disable.S 
b/libgcc/config/aarch64/__arm_za_disable.S
index 7a888a98d49..f61d4255fdc 100644
--- a/libgcc/config/aarch64/__arm_za_disable.S
+++ b/libgcc/config/aarch64/__arm_za_disable.S
@@ -64,3 +64,8 @@ ENTRY (__arm_za_disable)
 L(end):
ret
 END (__arm_za_disable)
+
+/* Hidden alias used by the unwinder.  */
+.global __libgcc_arm_za_disable
+.hidden __libgcc_arm_za_disable
+.set __libgcc_arm_za_disable, __arm_za_disable
diff --git a/libgcc/config/aarch64/aarch64-unwind.h 
b/libgcc/config/aarch64/aarch64-unwind.h
index d669edd671b..9fe6c8f61c3 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -78,4 +78,20 @@ aarch64_demangle_return_addr (struct _Unwind_Context 
*context,
   return addr;
 }
 
+/* SME runtime function local to libgcc, streaming compatible
+   and preserves more registers than the base PCS requires, but
+   we don't rely on that here.  */
+__attribute__ ((visibility ("hidden")))
+void __libgcc_arm_za_disable (void);
+
+/* Disable the SME ZA state in case an unwound frame used the ZA
+   lazy saving scheme.  */
+#undef _Unwind_Frames_Extra
+#define _Unwind_Frames_Extra(x)\
+  do   \
+{  \
+  __libgcc_arm_za_disable ();  \
+}  \
+  while (0)
+
 #endif /* defined AARCH64_UNWIND_H && defined __ILP32__ */
-- 
2.25.1



[PATCH 3/4] libgcc: aarch64: Add SME runtime support

2023-12-07 Thread Szabolcs Nagy
The call ABI for SME (Scalable Matrix Extension) requires a number of
helper routines which are added to libgcc so they are tied to the
compiler version instead of the libc version. See
https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#sme-support-routines

The routines are in shared libgcc and static libgcc eh, even though
they are not related to exception handling.  This is to avoid linking
a copy of the routines into dynamic linked binaries, because TPIDR2_EL0
block can be extended in the future which is better to handle in a
single place per process.

The support routines have to decide if SME is accessible or not. Linux
tells userspace if SME is accessible via AT_HWCAP2, otherwise a new
__aarch64_sme_accessible symbol was introduced that a libc can define.
Due to libgcc and libc build order, the symbol availability cannot be
checked so for __aarch64_sme_accessible an unistd.h feature test macro
is used while such detection mechanism is not available for __getauxval
so we rely on configure checks based on the target triplet.

Asm helper code is added to make writing the routines easier.

libgcc/ChangeLog:

* config/aarch64/t-aarch64: Add sources to the build.
* config/aarch64/__aarch64_have_sme.c: New file.
* config/aarch64/__arm_sme_state.S: New file.
* config/aarch64/__arm_tpidr2_restore.S: New file.
* config/aarch64/__arm_tpidr2_save.S: New file.
* config/aarch64/__arm_za_disable.S: New file.
* config/aarch64/aarch64-asm.h: New file.
* config/aarch64/libgcc-sme.ver: New file.
---
 libgcc/config/aarch64/__aarch64_have_sme.c   |  71 +
 libgcc/config/aarch64/__arm_sme_state.S  |  55 ++
 libgcc/config/aarch64/__arm_tpidr2_restore.S |  89 
 libgcc/config/aarch64/__arm_tpidr2_save.S| 101 +++
 libgcc/config/aarch64/__arm_za_disable.S |  66 
 libgcc/config/aarch64/aarch64-asm.h  |  98 ++
 libgcc/config/aarch64/libgcc-sme.ver |  24 +
 libgcc/config/aarch64/t-aarch64  |  10 ++
 8 files changed, 514 insertions(+)
 create mode 100644 libgcc/config/aarch64/__aarch64_have_sme.c
 create mode 100644 libgcc/config/aarch64/__arm_sme_state.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_restore.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_save.S
 create mode 100644 libgcc/config/aarch64/__arm_za_disable.S
 create mode 100644 libgcc/config/aarch64/aarch64-asm.h
 create mode 100644 libgcc/config/aarch64/libgcc-sme.ver

diff --git a/libgcc/config/aarch64/__aarch64_have_sme.c 
b/libgcc/config/aarch64/__aarch64_have_sme.c
new file mode 100644
index 000..2dc6be63ce9
--- /dev/null
+++ b/libgcc/config/aarch64/__aarch64_have_sme.c
@@ -0,0 +1,71 @@
+/* Initializer for SME support.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   .  */
+
+#include "auto-target.h"
+#include 
+
+#if __ARM_FEATURE_SME
+/* Avoid runtime SME detection if libgcc is built with SME.  */
+# define HAVE_SME_CONST const
+# define HAVE_SME_VALUE 1
+#elif HAVE___GETAUXVAL
+/* SME access detection on Linux.  */
+# define HAVE_SME_CONST
+# define HAVE_SME_VALUE 0
+# define HAVE_SME_CTOR sme_accessible ()
+
+# define AT_HWCAP2 26
+# define HWCAP2_SME(1 << 23)
+unsigned long int __getauxval (unsigned long int);
+
+static _Bool
+sme_accessible (void)
+{
+  unsigned long hwcap2 = __getauxval (AT_HWCAP2);
+  return (hwcap2 & HWCAP2_SME) != 0;
+}
+#elif __LIBC___AARCH64_SME_ACCESSIBLE
+/* Alternative SME access detection.  */
+# define HAVE_SME_CONST
+# define HAVE_SME_VALUE 0
+# define HAVE_SME_CTOR __aarch64_sme_accessible ()
+_Bool __aarch64_sme_accessible (void);
+#else
+# define HAVE_SME_CONST const
+# define HAVE_SME_VALUE 0
+#endif
+
+/* Define the symbol gating SME support in libgcc.  */
+HAVE_SME_CONST _Bool __aarch64_have_sme
+  __attribute__((visibility("hidden"), nocommon)) = HAVE_SME_VALUE;
+
+#ifdef HAVE_SME_CTOR
+/* Use a higher priority to ensure it runs before 

[PATCH 2/4] libgcc: aarch64: Configure check for __getauxval

2023-12-07 Thread Szabolcs Nagy
Add configure check for the __getauxval ABI symbol, which is always
available on aarch64 glibc, and may be available on other linux C
runtimes. For now only enabled on glibc, others have to override it

  target_configargs=libgcc_cv_have___getauxval=yes

This is deliberately obscure as it should be auto detected, ideally
via a feature test macro in unistd.h (link time detection is not
possible since the libc may not be installed at libgcc build time),
but currently there is no such feature test mechanism.

Without __getauxval, libgcc cannot do runtime CPU feature detection
and has to assume only the build time known features are available.

libgcc/ChangeLog:

* config.in: Undef HAVE___GETAUXVAL.
* configure: Regenerate.
* configure.ac: Check for __getauxval.
---
 libgcc/config.in|  3 +++
 libgcc/configure| 26 ++
 libgcc/configure.ac | 19 +++
 3 files changed, 48 insertions(+)

diff --git a/libgcc/config.in b/libgcc/config.in
index 5dd96cdf648..441d4d39b95 100644
--- a/libgcc/config.in
+++ b/libgcc/config.in
@@ -16,6 +16,9 @@
 /* Define to 1 if the assembler supports .variant_pcs. */
 #undef HAVE_AS_VARIANT_PCS
 
+/* Define to 1 if __getauxval is available. */
+#undef HAVE___GETAUXVAL
+
 /* Define to 1 if the target assembler supports thread-local storage. */
 #undef HAVE_CC_TLS
 
diff --git a/libgcc/configure b/libgcc/configure
index 571e3437701..746d29587d5 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -5657,6 +5657,32 @@ $as_echo "#define HAVE_AS_VARIANT_PCS 1" >>confdefs.h
   ;;
 esac
 
+# Check __getauxval ABI symbol for CPU feature detection.
+case ${target} in
+aarch64*-linux-*)
+  # No link check because the libc may not be present.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __getauxval" >&5
+$as_echo_n "checking for __getauxval... " >&6; }
+if ${libgcc_cv_have___getauxval+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case ${target} in
+ *-linux-gnu*)
+   libgcc_cv_have___getauxval=yes
+   ;;
+ *)
+   libgcc_cv_have___getauxval=no
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have___getauxval" 
>&5
+$as_echo "$libgcc_cv_have___getauxval" >&6; }
+  if test x$libgcc_cv_have___getauxval = xyes; then
+
+$as_echo "#define HAVE___GETAUXVAL 1" >>confdefs.h
+
+  fi
+esac
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" 
>&5
 $as_echo_n "checking for init priority support... " >&6; }
 if ${libgcc_cv_init_priority+:} false; then :
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index abc398c91e4..64b45ae1423 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -665,6 +665,25 @@ aarch64*-*-*)
 esac])
 LIBGCC_CHECK_AS_VARIANT_PCS
 
+# Check __getauxval ABI symbol for CPU feature detection.
+case ${target} in
+aarch64*-linux-*)
+  # No link check because the libc may not be present.
+  AC_CACHE_CHECK([for __getauxval],
+[libgcc_cv_have___getauxval],
+[case ${target} in
+ *-linux-gnu*)
+   libgcc_cv_have___getauxval=yes
+   ;;
+ *)
+   libgcc_cv_have___getauxval=no
+ esac])
+  if test x$libgcc_cv_have___getauxval = xyes; then
+AC_DEFINE(HAVE___GETAUXVAL, 1,
+ [Define to 1 if __getauxval is available.])
+  fi
+esac
+
 dnl Check if as supports RTM instructions.
 AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
-- 
2.25.1



[PATCH 1/4] libgcc: aarch64: Configure check for .variant_pcs support

2023-12-07 Thread Szabolcs Nagy
Ideally SME support routines in libgcc are marked as variant PCS symbols
so check if as supports the directive.
---
 libgcc/config.in|  3 +++
 libgcc/configure| 39 +++
 libgcc/configure.ac | 17 +
 3 files changed, 59 insertions(+)

diff --git a/libgcc/config.in b/libgcc/config.in
index f93c64a00c3..5dd96cdf648 100644
--- a/libgcc/config.in
+++ b/libgcc/config.in
@@ -13,6 +13,9 @@
 /* Define to 1 if the assembler supports LSE. */
 #undef HAVE_AS_LSE
 
+/* Define to 1 if the assembler supports .variant_pcs. */
+#undef HAVE_AS_VARIANT_PCS
+
 /* Define to 1 if the target assembler supports thread-local storage. */
 #undef HAVE_CC_TLS
 
diff --git a/libgcc/configure b/libgcc/configure
index cf149209652..571e3437701 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -5618,6 +5618,45 @@ $as_echo "#define HAVE_AS_LSE 1" >>confdefs.h
   ;;
 esac
 
+
+
+case "${target}" in
+aarch64*-*-*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if as supports 
.variant_pcs" >&5
+$as_echo_n "checking if as supports .variant_pcs... " >&6; }
+if ${libgcc_cv_as_variant_pcs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm (".variant_pcs foobar");
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_as_variant_pcs=yes
+else
+  libgcc_cv_as_variant_pcs=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_as_variant_pcs" >&5
+$as_echo "$libgcc_cv_as_variant_pcs" >&6; }
+  if test x$libgcc_cv_as_variant_pcs = xyes; then
+
+$as_echo "#define HAVE_AS_VARIANT_PCS 1" >>confdefs.h
+
+  fi
+  ;;
+esac
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" 
>&5
 $as_echo_n "checking for init priority support... " >&6; }
 if ${libgcc_cv_init_priority+:} false; then :
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 2fc9d5d7c93..abc398c91e4 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -648,6 +648,23 @@ changequote([,])dnl
 esac])
 LIBGCC_CHECK_AS_LSE
 
+dnl Check if as supports .variant_pcs.
+AC_DEFUN([LIBGCC_CHECK_AS_VARIANT_PCS], [
+case "${target}" in
+aarch64*-*-*)
+  AC_CACHE_CHECK([if as supports .variant_pcs], libgcc_cv_as_variant_pcs, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
+  [[asm (".variant_pcs foobar");]])],
+  [libgcc_cv_as_variant_pcs=yes], [libgcc_cv_as_variant_pcs=no])
+  ])
+  if test x$libgcc_cv_as_variant_pcs = xyes; then
+AC_DEFINE(HAVE_AS_VARIANT_PCS, 1,
+ [Define to 1 if the assembler supports .variant_pcs.])
+  fi
+  ;;
+esac])
+LIBGCC_CHECK_AS_VARIANT_PCS
+
 dnl Check if as supports RTM instructions.
 AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
-- 
2.25.1



[PATCH 0/4] libgcc: aarch64: Add SME runtime

2023-12-07 Thread Szabolcs Nagy
Add SME (Scalable Matrix Extension) support to libgcc.

Szabolcs Nagy (4):
  libgcc: aarch64: Configure check for .variant_pcs support
  libgcc: aarch64: Configure check for __getauxval
  libgcc: aarch64: Add SME runtime support
  libgcc: aarch64: Add SME unwinder support

 libgcc/config.in |   6 ++
 libgcc/config/aarch64/__aarch64_have_sme.c   |  71 +
 libgcc/config/aarch64/__arm_sme_state.S  |  55 ++
 libgcc/config/aarch64/__arm_tpidr2_restore.S |  89 
 libgcc/config/aarch64/__arm_tpidr2_save.S| 101 +++
 libgcc/config/aarch64/__arm_za_disable.S |  71 +
 libgcc/config/aarch64/aarch64-asm.h  |  98 ++
 libgcc/config/aarch64/aarch64-unwind.h   |  16 +++
 libgcc/config/aarch64/libgcc-sme.ver |  24 +
 libgcc/config/aarch64/t-aarch64  |  10 ++
 libgcc/configure |  65 
 libgcc/configure.ac  |  36 +++
 12 files changed, 642 insertions(+)
 create mode 100644 libgcc/config/aarch64/__aarch64_have_sme.c
 create mode 100644 libgcc/config/aarch64/__arm_sme_state.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_restore.S
 create mode 100644 libgcc/config/aarch64/__arm_tpidr2_save.S
 create mode 100644 libgcc/config/aarch64/__arm_za_disable.S
 create mode 100644 libgcc/config/aarch64/aarch64-asm.h
 create mode 100644 libgcc/config/aarch64/libgcc-sme.ver

-- 
2.25.1



[PATCH] aarch64: fix eh_return-3.c test

2023-12-04 Thread Szabolcs Nagy
gcc/testsuite/ChangeLog:

* gcc.target/aarch64/eh_return-3.c: Fix when retaa is available.
---
 gcc/testsuite/gcc.target/aarch64/eh_return-3.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-3.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
index a17baa86501..d180fa7c455 100644
--- a/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
@@ -12,8 +12,12 @@
 ** cbz x4, .*
 ** add sp, sp, x5
 ** br  x6
+** (
 ** hint29 // autiasp
 ** ret
+** |
+** retaa
+** )
 ** mov x5, x0
 ** mov x4, 1
 ** mov x6, x1
-- 
2.25.1



Re: [PATCH] aarch64: Avoid -Wincompatible-pointer-types warning in Linux unwinder

2023-11-29 Thread Szabolcs Nagy
The 11/10/2023 19:48, Florian Weimer wrote:
>   * config/aarch64/linux-unwind.h
>   (aarch64_fallback_frame_state): Add cast to the expected type
>   in sc assignment.
> 
> (Almost a v2, but the other issue was already fixed via in r14-4183.)
> 
> ---
>  libgcc/config/aarch64/linux-unwind.h | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/libgcc/config/aarch64/linux-unwind.h 
> b/libgcc/config/aarch64/linux-unwind.h
> index 00eba866049..18b3df71e7b 100644
> --- a/libgcc/config/aarch64/linux-unwind.h
> +++ b/libgcc/config/aarch64/linux-unwind.h
> @@ -77,7 +77,10 @@ aarch64_fallback_frame_state (struct _Unwind_Context 
> *context,
>  }
>  
>rt_ = context->cfa;
> -  sc = _->uc.uc_mcontext;
> +  /* Historically, the uc_mcontext member was of type struct sigcontext, but
> + glibc uses a different type now with member names in the implementation
> + namespace.  */
> +  sc = (struct sigcontext *) _->uc.uc_mcontext;

FWIW this looks good to me.
(but i cannot approve patches)

(changing the type of sc to mcontext_t* is another option,
but then _GNU_SOURCE is required for the field names to
remain the same across glibc versions, while struct
sigcontext* is unlikely to cause API issues.)

>  
>  /* This define duplicates the definition in aarch64.md */
>  #define SP_REGNUM 31
> 
> base-commit: 3a6df3281a525ae6113f50d7b38b09fcd803801e
> 


Re: [PATCH] aarch64: Call named function in gcc.target/aarch64/aapcs64/ice_1.c

2023-11-29 Thread Szabolcs Nagy
The 11/10/2023 12:22, Florian Weimer wrote:
> This test looks like it intends to pass a small struct argument
> through both a non-variadic and variadic argument, but due to
> the typo, it does not achieve that.
> 
> gcc/testsuite/
> 
>   * gcc.target/aarch64/aapcs64/ice_1.c (foo): Call named.


FWIW, this looks good to me.
(but i cannot approve patches)

> 
> ---
>  gcc/testsuite/gcc.target/aarch64/aapcs64/ice_1.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_1.c 
> b/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_1.c
> index 906ccebf616..edc35db2f6e 100644
> --- a/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_1.c
> @@ -16,6 +16,6 @@ void unnamed (int, ...);
>  
>  void foo ()
>  {
> -  name (0, );
> +  named (0, );
>unnamed (0, );
>  }
> 
> base-commit: 5f6c5fe078c45bc32c8d21da6b14c27c0ed7be6e
> 


Re: [PATCH v2 3/7] aarch64: Add eh_return compile tests

2023-11-27 Thread Szabolcs Nagy
The 11/26/2023 14:37, Richard Sandiford wrote:
> Szabolcs Nagy  writes:
> > +++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
> > @@ -0,0 +1,30 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf" } */
> 
> Probably best to add -fno-schedule-insns -fno-schedule-insns2, so that the
> instructions in the check-function-bodies are in a more predictable order.
> 
> > +/* { dg-final { check-function-bodies "**" "" "" } } */
> > +
> > +/*
> > +**foo:
> > +** hint25 // paciasp
> > +** stp x0, x1, .*
> > +** stp x2, x3, .*
> > +** cbz w2, .*
> > +** mov x4, 0
> > +** ldp x2, x3, .*
> > +** ldp x0, x1, .*
> > +** cbz x4, .*
> > +** add sp, sp, x5
> > +** br  x6
> > +** hint29 // autiasp
> > +** ret
> > +** mov x5, x0
> > +** mov x6, x1
> > +** mov x4, 1
> > +** b   .*
> > +*/
> 
> What's the significance of x3 here?  It looks from the function definition
> like it should be undefined.  And what are the stps and ldps doing?
> 
> If those aren't an important part of the test, it might be better
> to stub them out with "...", e.g.:
> 
> /*
> **foo:
> **hint25 // paciasp
> **...
> **cbz w2, .*
> **mov x4, 0
> **...
> **cbz x4, .*
> **add sp, sp, x5
> **br  x6
> **hint29 // autiasp
> **ret
> **mov x5, x0
> **mov x6, x1
> **mov x4, 1
> **b   .*
> */
> 
> LGTM otherwise.

committed as

>From cad7e1e3e0dea1922f89290bbbc27b4c44f53bf5 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy 
Date: Fri, 2 Jun 2023 14:17:02 +0100
Subject: [PATCH] aarch64: Add eh_return compile tests

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/eh_return-2.c: New test.
* gcc.target/aarch64/eh_return-3.c: New test.
---
 .../gcc.target/aarch64/eh_return-2.c  |  9 ++
 .../gcc.target/aarch64/eh_return-3.c  | 28 +++
 2 files changed, 37 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-3.c

diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-2.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
new file mode 100644
index 000..4a9d124e891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "add\tsp, sp, x5" } } */
+/* { dg-final { scan-assembler "br\tx6" } } */
+
+void
+foo (unsigned long off, void *handler)
+{
+  __builtin_eh_return (off, handler);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-3.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
new file mode 100644
index 000..a17baa86501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf -fno-schedule-insns 
-fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+**foo:
+** hint25 // paciasp
+** ...
+** cbz w2, .*
+** mov x4, 0
+** ...
+** cbz x4, .*
+** add sp, sp, x5
+** br  x6
+** hint29 // autiasp
+** ret
+** mov x5, x0
+** mov x4, 1
+** mov x6, x1
+** b   .*
+*/
+void
+foo (unsigned long off, void *handler, int c)
+{
+  if (c)
+return;
+  __builtin_eh_return (off, handler);
+}
-- 
2.25.1



Re: [PATCH v2 3/7] aarch64: Add eh_return compile tests

2023-11-27 Thread Szabolcs Nagy
The 11/26/2023 14:37, Richard Sandiford wrote:
> Szabolcs Nagy  writes:
> > +++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
> > @@ -0,0 +1,30 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf" } */
> 
> Probably best to add -fno-schedule-insns -fno-schedule-insns2, so that the
> instructions in the check-function-bodies are in a more predictable order.
> 
> > +/* { dg-final { check-function-bodies "**" "" "" } } */
> > +
> > +/*
> > +**foo:
> > +** hint25 // paciasp
> > +** stp x0, x1, .*
> > +** stp x2, x3, .*
> > +** cbz w2, .*
> > +** mov x4, 0
> > +** ldp x2, x3, .*
> > +** ldp x0, x1, .*
> > +** cbz x4, .*
> > +** add sp, sp, x5
> > +** br  x6
> > +** hint29 // autiasp
> > +** ret
> > +** mov x5, x0
> > +** mov x6, x1
> > +** mov x4, 1
> > +** b   .*
> > +*/
> 
> What's the significance of x3 here?  It looks from the function definition
> like it should be undefined.  And what are the stps and ldps doing?

x0,..,x3 are preserved registers for eh (EH_RETURN_DATA_REGNO).

they are saved in the prologue and restored in the epilogue so
they can pass arguments to eh, which i think is relevant to an
eh_return test, although if the compiler knows they are not
clobbered then it could eliminate the save/restore.

> If those aren't an important part of the test, it might be better
> to stub them out with "...", e.g.:

i can do that.

> /*
> **foo:
> **hint25 // paciasp
> **...
> **cbz w2, .*
> **mov x4, 0
> **...
> **cbz x4, .*
> **add sp, sp, x5
> **br  x6
> **hint29 // autiasp
> **ret
> **mov x5, x0
> **mov x6, x1
> **mov x4, 1
> **b   .*
> */
> 
> LGTM otherwise.

thanks.


Re: [PATCH v2 1/7] aarch64: Use br instead of ret for eh_return

2023-11-13 Thread Szabolcs Nagy
The 11/13/2023 01:27, Hans-Peter Nilsson wrote:
> > From: Szabolcs Nagy 
> > Date: Fri, 3 Nov 2023 15:36:08 +
> 
> I don't see others commenting on this patch, and you're not
> mentioning this aspect, so I wonder:
> 
> > * config/aarch64/aarch64.h (EH_RETURN_TAKEN_RTX): Define.
> > (EH_RETURN_STACKADJ_RTX): Change to R5.
> > (EH_RETURN_HANDLER_RTX): Change to R6.
> 
> Isn't this an ABI change?

not really: this is interface between the function body
and the epilogue, so all within the code of a single
function doing eh return, not a public abi boundary.

(e.g. R0..R3 are preserved from the function throwing
the exception to the exception handler, so that's abi.
R4..R6 are just an internal detail of the function doing
the eh return in the unwinder.)

> 
> (I've forgotten relevant bits of the exception machinery; if
> throw and catch are always in the same object and everything
> in between register-number-agnostic then the only flaw would
> be not mentioning that in the commit message.)
> 
> brgds, H-P


[PATCH v2 7/7] aarch64,arm: Move branch-protection data to targets

2023-11-03 Thread Szabolcs Nagy
The branch-protection types are target specific, not the same on arm
and aarch64.  This currently affects pac-ret+b-key, but there will be
a new type on aarch64 that is not relevant for arm.

gcc/ChangeLog:

* config/aarch64/aarch64-opts.h (enum aarch64_key_type): Rename to ...
(enum aarch_key_type): ... this.
* config/aarch64/aarch64.cc (aarch_handle_no_branch_protection): Copy.
(aarch_handle_standard_branch_protection): Copy.
(aarch_handle_pac_ret_protection): Copy.
(aarch_handle_pac_ret_leaf): Copy.
(aarch_handle_pac_ret_b_key): Copy.
(aarch_handle_bti_protection): Copy.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Remove.
(aarch_handle_standard_branch_protection): Remove.
(aarch_handle_pac_ret_protection): Remove.
(aarch_handle_pac_ret_leaf): Remove.
(aarch_handle_pac_ret_b_key): Remove.
(aarch_handle_bti_protection): Remove.
* config/arm/aarch-common.h (enum aarch_key_type): Remove.
(struct aarch_branch_protect_type): Declare.
* config/arm/arm-c.cc (arm_cpu_builtins): Remove aarch_ra_sign_key.
* config/arm/arm.cc (aarch_handle_no_branch_protection): Copy.
(aarch_handle_standard_branch_protection): Copy.
(aarch_handle_pac_ret_protection): Copy.
(aarch_handle_pac_ret_leaf): Copy.
(aarch_handle_bti_protection): Copy.
(arm_configure_build_target): Copy.
* config/arm/arm.opt: Remove aarch_ra_sign_key.
---
unchanged compared to v1.
---
 gcc/config/aarch64/aarch64-opts.h |  6 ++--
 gcc/config/aarch64/aarch64.cc | 55 +++
 gcc/config/arm/aarch-common.cc| 55 ---
 gcc/config/arm/aarch-common.h | 11 +++
 gcc/config/arm/arm-c.cc   |  2 --
 gcc/config/arm/arm.cc | 52 +
 gcc/config/arm/arm.opt|  3 --
 7 files changed, 109 insertions(+), 75 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-opts.h 
b/gcc/config/aarch64/aarch64-opts.h
index 831e28ab52a..1abae1442b5 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -103,9 +103,9 @@ enum stack_protector_guard {
 };
 
 /* The key type that -msign-return-address should use.  */
-enum aarch64_key_type {
-  AARCH64_KEY_A,
-  AARCH64_KEY_B
+enum aarch_key_type {
+  AARCH_KEY_A,
+  AARCH_KEY_B
 };
 
 /* An enum specifying how to handle load and store pairs using
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 4f7f707b675..9739223831f 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18620,6 +18620,61 @@ aarch64_set_asm_isa_flags (aarch64_feature_flags flags)
   aarch64_set_asm_isa_flags (_options, flags);
 }
 
+static void
+aarch_handle_no_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+  aarch_enable_bti = 0;
+}
+
+static void
+aarch_handle_standard_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  aarch_enable_bti = 1;
+}
+
+static void
+aarch_handle_pac_ret_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+}
+
+static void
+aarch_handle_pac_ret_leaf (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+}
+
+static void
+aarch_handle_pac_ret_b_key (void)
+{
+  aarch_ra_sign_key = AARCH_KEY_B;
+}
+
+static void
+aarch_handle_bti_protection (void)
+{
+  aarch_enable_bti = 1;
+}
+
+static const struct aarch_branch_protect_type aarch_pac_ret_subtypes[] = {
+  { "leaf", false, aarch_handle_pac_ret_leaf, NULL, 0 },
+  { "b-key", false, aarch_handle_pac_ret_b_key, NULL, 0 },
+  { NULL, false, NULL, NULL, 0 }
+};
+
+const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
+  { "none", true, aarch_handle_no_branch_protection, NULL, 0 },
+  { "standard", true, aarch_handle_standard_branch_protection, NULL, 0 },
+  { "pac-ret", false, aarch_handle_pac_ret_protection, aarch_pac_ret_subtypes,
+ARRAY_SIZE (aarch_pac_ret_subtypes) },
+  { "bti", false, aarch_handle_bti_protection, NULL, 0 },
+  { NULL, false, NULL, NULL, 0 }
+};
+
 /* Implement TARGET_OPTION_OVERRIDE.  This is called once in the beginning
and is used to parse the -m{cpu,tune,arch} strings and setup the initial
tuning structs.  In particular it must set selected_tune and
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 159c61b786c..92e1248f83f 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -659,61 +659,6 @@ arm_md_asm_adjust (vec , vec & 
/*inputs*/,
   return saw_asm_flag ? seq : NULL;
 }
 
-static void
-aarch_handle_no_branch_protection (void)
-{
-  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
-  aarch_enable_bti = 0;
-}
-
-static void
-aarch_handle_standard_branch_protection (void)
-{
-  aarch_ra_sign_scope = 

[PATCH v2 4/7] aarch64: Disable branch-protection for pcs tests

2023-11-03 Thread Szabolcs Nagy
The tests manipulate the return address in abitest-2.h and thus not
compatible with -mbranch-protection=pac-ret+leaf or
-mbranch-protection=gcs.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/aapcs64/func-ret-1.c: Disable branch-protection.
* gcc.target/aarch64/aapcs64/func-ret-2.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-3.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-4.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-64x1_1.c: Likewise.
---
unchanged compared to v1
already approved at
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/629353.html
---
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c | 1 +
 5 files changed, 5 insertions(+)

diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
index 5405e1e4920..7bd7757efe6 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
@@ -4,6 +4,7 @@
AAPCS64 \S 4.1.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
index 6b171c46fbb..85a822ace4a 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
@@ -4,6 +4,7 @@
Homogeneous floating-point aggregate types are covered in func-ret-3.c.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
index ad312b675b9..1d35ebf14b4 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
@@ -4,6 +4,7 @@
in AAPCS64 \S 4.3.5.  */
 
 /* { dg-do run { target aarch64-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 /* { dg-require-effective-target aarch64_big_endian } */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
index af05fbe9fdf..15e1408c62d 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
@@ -5,6 +5,7 @@
are treated as general composite types.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 /* { dg-require-effective-target aarch64_big_endian } */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
index 05957e2dcae..fe7bbb6a835 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
@@ -3,6 +3,7 @@
   Test 64-bit singleton vector types which should be in FP/SIMD registers.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
-- 
2.25.1



[PATCH v2 2/7] aarch64: Do not force a stack frame for EH returns

2023-11-03 Thread Szabolcs Nagy
EH returns no longer rely on clobbering the return address on the stack
so forcing a stack frame is not necessary.

This does not actually change the code gen for the unwinder since there
are calls before the EH return.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_needs_frame_chain): Do not
force frame chain for eh_return.
---
unchanged compared to v1
already approved at:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/629346.html
---
 gcc/config/aarch64/aarch64.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 5cdb33dd3dc..88594bed8ce 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -8492,8 +8492,7 @@ aarch64_output_probe_sve_stack_clash (rtx base, rtx 
adjustment,
 static bool
 aarch64_needs_frame_chain (void)
 {
-  /* Force a frame chain for EH returns so the return address is at FP+8.  */
-  if (frame_pointer_needed || crtl->calls_eh_return)
+  if (frame_pointer_needed)
 return true;
 
   /* A leaf function cannot have calls or write LR.  */
-- 
2.25.1



[PATCH v2 6/7] aarch64,arm: Fix branch-protection= parsing

2023-11-03 Thread Szabolcs Nagy
Refactor the parsing to have a single API and fix a few parsing issues:

- Different handling of "bti+none" and "none+bti": these should be
  rejected because "none" can only appear alone.

- Accepted empty strings such as "bti++pac-ret" or "bti+", this bug
  was caused by using strtok_r.

- Memory got leaked (str_root was never freed). And two buffers got
  allocated when one is enough.

The callbacks now have no failure mode, only parsing can fail and
all failures are handled locally.  The "-mbranch-protection=" vs
"target("branch-protection=")" difference in the error message is
handled by a separate argument to aarch_validate_mbranch_protection.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_override_options): Update.
(aarch64_handle_attr_branch_protection): Update.
* config/arm/aarch-common-protos.h (aarch_parse_branch_protection):
Remove.
(aarch_validate_mbranch_protection): Add new argument.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Update.
(aarch_handle_standard_branch_protection): Update.
(aarch_handle_pac_ret_protection): Update.
(aarch_handle_pac_ret_leaf): Update.
(aarch_handle_pac_ret_b_key): Update.
(aarch_handle_bti_protection): Update.
(aarch_parse_branch_protection): Remove.
(next_tok): New.
(aarch_validate_mbranch_protection): Rewrite.
* config/arm/aarch-common.h (struct aarch_branch_protect_type):
Add field "alone".
* config/arm/arm.cc (arm_configure_build_target): Update.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/branch-protection-attr.c: Update.
* gcc.target/aarch64/branch-protection-option.c: Update.
---
v2: merge tests updates into the patch
error message is not changed, see previous discussion:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/633945.html
---
 gcc/config/aarch64/aarch64.cc |  37 +--
 gcc/config/arm/aarch-common-protos.h  |   5 +-
 gcc/config/arm/aarch-common.cc| 214 --
 gcc/config/arm/aarch-common.h |  14 +-
 gcc/config/arm/arm.cc |   3 +-
 .../aarch64/branch-protection-attr.c  |   6 +-
 .../aarch64/branch-protection-option.c|   2 +-
 7 files changed, 113 insertions(+), 168 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index f8e8fefc8d8..4f7f707b675 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18642,7 +18642,8 @@ aarch64_override_options (void)
 aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
 
   if (aarch64_branch_protection_string)
-aarch_validate_mbranch_protection (aarch64_branch_protection_string);
+aarch_validate_mbranch_protection (aarch64_branch_protection_string,
+  "-mbranch-protection=");
 
   /* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
  If either of -march or -mtune is given, they override their
@@ -19016,34 +19017,12 @@ aarch64_handle_attr_cpu (const char *str)
 
 /* Handle the argument STR to the branch-protection= attribute.  */
 
- static bool
- aarch64_handle_attr_branch_protection (const char* str)
- {
-  char *err_str = (char *) xmalloc (strlen (str) + 1);
-  enum aarch_parse_opt_result res = aarch_parse_branch_protection (str,
-  _str);
-  bool success = false;
-  switch (res)
-{
- case AARCH_PARSE_MISSING_ARG:
-   error ("missing argument to % pragma 
or"
- " attribute");
-   break;
- case AARCH_PARSE_INVALID_ARG:
-   error ("invalid protection type %qs in % pragma or attribute", err_str);
-   break;
- case AARCH_PARSE_OK:
-   success = true;
-  /* Fall through.  */
- case AARCH_PARSE_INVALID_FEATURE:
-   break;
- default:
-   gcc_unreachable ();
-}
-  free (err_str);
-  return success;
- }
+static bool
+aarch64_handle_attr_branch_protection (const char* str)
+{
+  return aarch_validate_mbranch_protection (str,
+   "target(\"branch-protection=\")");
+}
 
 /* Handle the argument STR to the tune= target attribute.  */
 
diff --git a/gcc/config/arm/aarch-common-protos.h 
b/gcc/config/arm/aarch-common-protos.h
index f8cb6562096..75ffdfbb050 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -159,10 +159,7 @@ rtx_insn *arm_md_asm_adjust (vec , vec & 
/*inputs*/,
 vec , HARD_REG_SET _regs,
 location_t loc);
 
-/* Parsing routine for branch-protection common to AArch64 and Arm.  */
-enum aarch_parse_opt_result aarch_parse_branch_protection (const char*, 
char**);
-
 /* Validation routine for branch-protection common to AArch64 and Arm.  */
-bool aarch_validate_mbranch_protection (const char *);
+bool 

[PATCH v2 3/7] aarch64: Add eh_return compile tests

2023-11-03 Thread Szabolcs Nagy
gcc/testsuite/ChangeLog:

* gcc.target/aarch64/eh_return-2.c: New test.
* gcc.target/aarch64/eh_return-3.c: New test.

---
v2: check-function-bodies in eh_return-3.c
(this is not very robust, but easier to read)
---
 .../gcc.target/aarch64/eh_return-2.c  |  9 ++
 .../gcc.target/aarch64/eh_return-3.c  | 30 +++
 2 files changed, 39 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-3.c

diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-2.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
new file mode 100644
index 000..4a9d124e891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "add\tsp, sp, x5" } } */
+/* { dg-final { scan-assembler "br\tx6" } } */
+
+void
+foo (unsigned long off, void *handler)
+{
+  __builtin_eh_return (off, handler);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-3.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
new file mode 100644
index 000..bfbe92af427
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/*
+**foo:
+** hint25 // paciasp
+** stp x0, x1, .*
+** stp x2, x3, .*
+** cbz w2, .*
+** mov x4, 0
+** ldp x2, x3, .*
+** ldp x0, x1, .*
+** cbz x4, .*
+** add sp, sp, x5
+** br  x6
+** hint29 // autiasp
+** ret
+** mov x5, x0
+** mov x6, x1
+** mov x4, 1
+** b   .*
+*/
+void
+foo (unsigned long off, void *handler, int c)
+{
+  if (c)
+return;
+  __builtin_eh_return (off, handler);
+}
-- 
2.25.1



[PATCH v2 5/7] aarch64,arm: Remove accepted_branch_protection_string

2023-11-03 Thread Szabolcs Nagy
On aarch64 this caused ICE with pragma push_options since

  commit ae54c1b09963779c5c3914782324ff48af32e2f1
  Author: Wilco Dijkstra 
  CommitDate: 2022-06-01 18:13:57 +0100

  AArch64: Cleanup option processing code

The failure is at pop_options:

internal compiler error: ‘global_options’ are modified in local context

On arm the variable was unused.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_override_options_after_change_1):
Do not override branch_protection options.
(aarch64_override_options): Remove accepted_branch_protection_string.
* config/arm/aarch-common.cc (BRANCH_PROTECT_STR_MAX): Remove.
(aarch_parse_branch_protection): Remove
accepted_branch_protection_string.
* config/arm/arm.cc: Likewise.
---
unchanged from v1
---
 gcc/config/aarch64/aarch64.cc  | 10 +-
 gcc/config/arm/aarch-common.cc | 16 
 gcc/config/arm/arm.cc  |  2 --
 3 files changed, 1 insertion(+), 27 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 88594bed8ce..f8e8fefc8d8 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -323,8 +323,6 @@ bool aarch64_pcrelative_literal_loads;
 /* Global flag for whether frame pointer is enabled.  */
 bool aarch64_use_frame_pointer;
 
-char *accepted_branch_protection_string = NULL;
-
 /* Support for command line parsing of boolean flags in the tuning
structures.  */
 struct aarch64_flag_desc
@@ -18101,12 +18099,6 @@ aarch64_adjust_generic_arch_tuning (struct tune_params 
_tune)
 static void
 aarch64_override_options_after_change_1 (struct gcc_options *opts)
 {
-  if (accepted_branch_protection_string)
-{
-  opts->x_aarch64_branch_protection_string
-   = xstrdup (accepted_branch_protection_string);
-}
-
   /* PR 70044: We have to be careful about being called multiple times for the
  same function.  This means all changes should be repeatable.  */
 
@@ -18715,7 +18707,7 @@ aarch64_override_options (void)
   /* Return address signing is currently not supported for ILP32 targets.  For
  LP64 targets use the configured option in the absence of a command-line
  option for -mbranch-protection.  */
-  if (!TARGET_ILP32 && accepted_branch_protection_string == NULL)
+  if (!TARGET_ILP32 && aarch64_branch_protection_string == NULL)
 {
 #ifdef TARGET_ENABLE_PAC_RET
   aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 5b96ff4c2e8..cbc7f68a8bf 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -659,9 +659,6 @@ arm_md_asm_adjust (vec , vec & /*inputs*/,
   return saw_asm_flag ? seq : NULL;
 }
 
-#define BRANCH_PROTECT_STR_MAX 255
-extern char *accepted_branch_protection_string;
-
 static enum aarch_parse_opt_result
 aarch_handle_no_branch_protection (char* str, char* rest)
 {
@@ -812,19 +809,6 @@ aarch_parse_branch_protection (const char *const_str, 
char** last_str)
   else
*last_str = NULL;
 }
-
-  if (res == AARCH_PARSE_OK)
-{
-  /* If needed, alloc the accepted string then copy in const_str.
-   Used by override_option_after_change_1.  */
-  if (!accepted_branch_protection_string)
-   accepted_branch_protection_string
- = (char *) xmalloc (BRANCH_PROTECT_STR_MAX + 1);
-  strncpy (accepted_branch_protection_string, const_str,
-  BRANCH_PROTECT_STR_MAX + 1);
-  /* Forcibly null-terminate.  */
-  accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
-}
   return res;
 }
 
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 6e933c80183..f49312cace0 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -2424,8 +2424,6 @@ const struct tune_params arm_fa726te_tune =
   tune_params::SCHED_AUTOPREF_OFF
 };
 
-char *accepted_branch_protection_string = NULL;
-
 /* Auto-generated CPU, FPU and architecture tables.  */
 #include "arm-cpu-data.h"
 
-- 
2.25.1



[PATCH v2 1/7] aarch64: Use br instead of ret for eh_return

2023-11-03 Thread Szabolcs Nagy
The expected way to handle eh_return is to pass the stack adjustment
offset and landing pad address via

  EH_RETURN_STACKADJ_RTX
  EH_RETURN_HANDLER_RTX

to the epilogue that is shared between normal return paths and the
eh_return paths.  EH_RETURN_HANDLER_RTX is the stack slot of the
return address that is overwritten with the landing pad in the
eh_return case and EH_RETURN_STACKADJ_RTX is a register added to sp
right before return and it is set to 0 in the normal return case.

The issue with this design is that eh_return and normal return may
require different return sequence but there is no way to distinguish
the two cases in the epilogue (the stack adjustment may be 0 in the
eh_return case too).

The reason eh_return and normal return requires different return
sequence is that control flow integrity hardening may need to treat
eh_return as a forward-edge transfer (it is not returning to the
previous stack frame) and normal return as a backward-edge one.
In case of AArch64 forward-edge is protected by BTI and requires br
instruction and backward-edge is protected by PAUTH or GCS and
requires ret (or authenticated ret) instruction.

This patch resolves the issue by introducing EH_RETURN_TAKEN_RTX that
is a flag set to 1 in the eh_return path and 0 in normal return paths.
Branching on the EH_RETURN_TAKEN_RTX flag, the right return sequence
can be used in the epilogue.

The handler could be passed the old way via clobbering the return
address, but since now the eh_return case can be distinguished, the
handler can be in a different register than x30 and no stack frame
is needed for eh_return.

This patch fixes a return to anywhere gadget in the unwinder with
existing standard branch protection as well as makes EH return
compatible with the Guarded Control Stack (GCS) extension.

Some tests are adjusted because eh_return no longer prevents pac-ret
in the normal return path.

gcc/ChangeLog:

* config/aarch64/aarch64-protos.h (aarch64_eh_return_handler_rtx):
Remove.
* config/aarch64/aarch64.cc (aarch64_return_address_signing_enabled):
Sign return address even in functions with eh_return.
(aarch64_expand_epilogue): Conditionally return with br or ret.
(aarch64_eh_return_handler_rtx): Remove.
* config/aarch64/aarch64.h (EH_RETURN_TAKEN_RTX): Define.
(EH_RETURN_STACKADJ_RTX): Change to R5.
(EH_RETURN_HANDLER_RTX): Change to R6.
* df-scan.cc: Handle EH_RETURN_TAKEN_RTX.
* doc/tm.texi: Regenerate.
* doc/tm.texi.in: Document EH_RETURN_TAKEN_RTX.
* except.cc (expand_eh_return): Handle EH_RETURN_TAKEN_RTX.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/return_address_sign_1.c: Move func4 to ...
* gcc.target/aarch64/return_address_sign_2.c: ... here and fix the
scan asm check.
* gcc.target/aarch64/return_address_sign_b_1.c: Move func4 to ...
* gcc.target/aarch64/return_address_sign_b_2.c: ... here and fix the
scan asm check.

---
v2:
- Introduce EH_RETURN_TAKEN_RTX instead of abusing EH_RETURN_STACKADJ_RTX.
- Merge test fixes.
---
 gcc/config/aarch64/aarch64-protos.h   |  1 -
 gcc/config/aarch64/aarch64.cc | 88 ++-
 gcc/config/aarch64/aarch64.h  |  9 +-
 gcc/df-scan.cc| 10 +++
 gcc/doc/tm.texi   | 12 +++
 gcc/doc/tm.texi.in| 12 +++
 gcc/except.cc | 20 +
 .../aarch64/return_address_sign_1.c   | 13 +--
 .../aarch64/return_address_sign_2.c   | 17 +++-
 .../aarch64/return_address_sign_b_1.c | 11 ---
 .../aarch64/return_address_sign_b_2.c | 17 +++-
 11 files changed, 116 insertions(+), 94 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 60a55f4bc19..80296024f04 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -859,7 +859,6 @@ machine_mode aarch64_hard_regno_caller_save_mode (unsigned, 
unsigned,
   machine_mode);
 int aarch64_uxt_size (int, HOST_WIDE_INT);
 int aarch64_vec_fpconst_pow_of_2 (rtx);
-rtx aarch64_eh_return_handler_rtx (void);
 rtx aarch64_mask_from_zextract_ops (rtx, rtx);
 const char *aarch64_output_move_struct (rtx *operands);
 rtx aarch64_return_addr_rtx (void);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index a28b66acf6a..5cdb33dd3dc 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9113,17 +9113,6 @@ aarch64_return_address_signing_enabled (void)
   /* This function should only be called after frame laid out.   */
   gcc_assert (cfun->machine->frame.laid_out);
 
-  /* Turn return address signing off in any function that uses
- __builtin_eh_return.  The address passed to __builtin_eh_return
- is not signed so either it has 

[PATCH v2 0/7] aarch64 GCS preliminary patches

2023-11-03 Thread Szabolcs Nagy
I'm working on Guarded Control Stack support for aarch64 and have a
set of patches that are needed for GCS but seem useful without it so
makes sense to review them separately from the rest of the GCS work.

previous version:
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628123.html

Szabolcs Nagy (7):
  aarch64: Use br instead of ret for eh_return
  aarch64: Do not force a stack frame for EH returns
  aarch64: Add eh_return compile tests
  aarch64: Disable branch-protection for pcs tests
  aarch64,arm: Remove accepted_branch_protection_string
  aarch64,arm: Fix branch-protection= parsing
  aarch64,arm: Move branch-protection data to targets

 gcc/config/aarch64/aarch64-opts.h |   6 +-
 gcc/config/aarch64/aarch64-protos.h   |   1 -
 gcc/config/aarch64/aarch64.cc | 193 +++
 gcc/config/aarch64/aarch64.h  |   9 +-
 gcc/config/arm/aarch-common-protos.h  |   5 +-
 gcc/config/arm/aarch-common.cc| 229 +-
 gcc/config/arm/aarch-common.h |  25 +-
 gcc/config/arm/arm-c.cc   |   2 -
 gcc/config/arm/arm.cc |  57 -
 gcc/config/arm/arm.opt|   3 -
 gcc/df-scan.cc|  10 +
 gcc/doc/tm.texi   |  12 +
 gcc/doc/tm.texi.in|  12 +
 gcc/except.cc |  20 ++
 .../gcc.target/aarch64/aapcs64/func-ret-1.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-2.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-3.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-4.c   |   1 +
 .../aarch64/aapcs64/func-ret-64x1_1.c |   1 +
 .../aarch64/branch-protection-attr.c  |   6 +-
 .../aarch64/branch-protection-option.c|   2 +-
 .../gcc.target/aarch64/eh_return-2.c  |   9 +
 .../gcc.target/aarch64/eh_return-3.c  |  30 +++
 .../aarch64/return_address_sign_1.c   |  13 +-
 .../aarch64/return_address_sign_2.c   |  17 +-
 .../aarch64/return_address_sign_b_1.c |  11 -
 .../aarch64/return_address_sign_b_2.c |  17 +-
 27 files changed, 356 insertions(+), 338 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-3.c

-- 
2.25.1



Re: [PATCH 10/11] aarch64: Fix branch-protection error message tests

2023-10-23 Thread Szabolcs Nagy
The 10/13/2023 11:29, Richard Earnshaw (lists) wrote:
> On 05/09/2023 16:00, Richard Sandiford via Gcc-patches wrote:
> > Szabolcs Nagy  writes:
> >> @@ -4,19 +4,19 @@ void __attribute__ ((target("branch-protection=leaf")))
> >>  foo1 ()
> >>  {
> >>  }
> >> -/* { dg-error {invalid protection type 'leaf' in 
> >> 'target\("branch-protection="\)' pragma or attribute} "" { target *-*-* } 
> >> 5 } */
> >> +/* { dg-error {invalid argument 'leaf' for 
> >> 'target\("branch-protection="\)'} "" { target *-*-* } 5 } */
> >>  /* { dg-error {pragma or attribute 'target\("branch-protection=leaf"\)' 
> >> is not valid} "" { target *-*-* } 5 } */
> 
> 'leaf' is really a modifier for the other branch protection strategies; 
> perhaps it would be better to describe it as that.

this error message is used for arbitrary strings, e.g.
branch-protection=foobar or branch-protection=bti+foo.

with further processing we can figure out that 'leaf'
is a valid modifier for pac-ret and change the error to

invalid placement of modifier 'leaf' in 'target("branch-protection=")'

otherwise fall back to

invalid argument 'foobar' for 'target("branch-protection=")'.

does that help?

(currently 'leaf' and 'b-key' are the only modifiers.)

> But this brings up another issue/question.  If the compiler has been 
> configured with, say, '--enable-branch-protection=standard' or some other 
> variety, is there (or do we want) a way to extend that to leaf functions 
> without changing the underlying strategy?

there are several limitations in branch-protection handling,
i'm only fixing bugs and assumptions that don't work when arm
and aarch64 has different set of branch-protection options.

i think it can be useful to add/remove branch-protection options
incrementally in cflags instead of having one string, but it's
not obvious to me how to get there.

> >>  void __attribute__ ((target("branch-protection=none+pac-ret")))
> >>  foo2 ()
> >>  {
> >>  }
> >> -/* { dg-error "unexpected 'pac-ret' after 'none'" "" { target *-*-* } 12 
> >> } */
> >> +/* { dg-error {argument 'none' can only appear alone in 
> >> 'target\("branch-protection="\)'} "" { target *-*-* } 12 } */
> 
> Or maybe better still: "branch protection strategies 'none' and 'pac-ret' are 
> incompatible".

i can make this change, but e.g.

in case of branch-protection=standard+bti+foo it would
say "'standard' and 'bti' are incompatible" which can be
surprising given that standard includes bti, meanwhile
"'standard' can only appear alone" explains the problem.

> But this is all a matter of taste.
> 
> However, this patch should be merged with the patch that changes the error 
> messages.  Or has that already gone in?

i can do that merge.


[PATCH 11/11] aarch64,arm: Move branch-protection data to targets

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
The branch-protection types are target specific, not the same on arm
and aarch64.  This currently affects pac-ret+b-key, but there will be
a new type on aarch64 that is not relevant for arm.

gcc/ChangeLog:

* config/aarch64/aarch64-opts.h (enum aarch64_key_type): Rename to ...
(enum aarch_key_type): ... this.
* config/aarch64/aarch64.cc (aarch_handle_no_branch_protection): Copy.
(aarch_handle_standard_branch_protection): Copy.
(aarch_handle_pac_ret_protection): Copy.
(aarch_handle_pac_ret_leaf): Copy.
(aarch_handle_pac_ret_b_key): Copy.
(aarch_handle_bti_protection): Copy.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Remove.
(aarch_handle_standard_branch_protection): Remove.
(aarch_handle_pac_ret_protection): Remove.
(aarch_handle_pac_ret_leaf): Remove.
(aarch_handle_pac_ret_b_key): Remove.
(aarch_handle_bti_protection): Remove.
* config/arm/aarch-common.h (enum aarch_key_type): Remove.
(struct aarch_branch_protect_type): Declare.
* config/arm/arm-c.cc (arm_cpu_builtins): Remove aarch_ra_sign_key.
* config/arm/arm.cc (aarch_handle_no_branch_protection): Copy.
(aarch_handle_standard_branch_protection): Copy.
(aarch_handle_pac_ret_protection): Copy.
(aarch_handle_pac_ret_leaf): Copy.
(aarch_handle_bti_protection): Copy.
(arm_configure_build_target): Copy.
* config/arm/arm.opt: Remove aarch_ra_sign_key.
---
 gcc/config/aarch64/aarch64-opts.h |  6 ++--
 gcc/config/aarch64/aarch64.cc | 55 +++
 gcc/config/arm/aarch-common.cc| 55 ---
 gcc/config/arm/aarch-common.h | 11 +++
 gcc/config/arm/arm-c.cc   |  2 --
 gcc/config/arm/arm.cc | 52 +
 gcc/config/arm/arm.opt|  3 --
 7 files changed, 109 insertions(+), 75 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-opts.h 
b/gcc/config/aarch64/aarch64-opts.h
index 7e8f1babed8..75ef00b60d4 100644
--- a/gcc/config/aarch64/aarch64-opts.h
+++ b/gcc/config/aarch64/aarch64-opts.h
@@ -103,9 +103,9 @@ enum stack_protector_guard {
 };
 
 /* The key type that -msign-return-address should use.  */
-enum aarch64_key_type {
-  AARCH64_KEY_A,
-  AARCH64_KEY_B
+enum aarch_key_type {
+  AARCH_KEY_A,
+  AARCH_KEY_B
 };
 
 #endif
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 661ac12cacc..734980f78ec 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18517,6 +18517,61 @@ aarch64_set_asm_isa_flags (aarch64_feature_flags flags)
   aarch64_set_asm_isa_flags (_options, flags);
 }
 
+static void
+aarch_handle_no_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+  aarch_enable_bti = 0;
+}
+
+static void
+aarch_handle_standard_branch_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+  aarch_enable_bti = 1;
+}
+
+static void
+aarch_handle_pac_ret_protection (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+  aarch_ra_sign_key = AARCH_KEY_A;
+}
+
+static void
+aarch_handle_pac_ret_leaf (void)
+{
+  aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+}
+
+static void
+aarch_handle_pac_ret_b_key (void)
+{
+  aarch_ra_sign_key = AARCH_KEY_B;
+}
+
+static void
+aarch_handle_bti_protection (void)
+{
+  aarch_enable_bti = 1;
+}
+
+static const struct aarch_branch_protect_type aarch_pac_ret_subtypes[] = {
+  { "leaf", false, aarch_handle_pac_ret_leaf, NULL, 0 },
+  { "b-key", false, aarch_handle_pac_ret_b_key, NULL, 0 },
+  { NULL, false, NULL, NULL, 0 }
+};
+
+const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
+  { "none", true, aarch_handle_no_branch_protection, NULL, 0 },
+  { "standard", true, aarch_handle_standard_branch_protection, NULL, 0 },
+  { "pac-ret", false, aarch_handle_pac_ret_protection, aarch_pac_ret_subtypes,
+ARRAY_SIZE (aarch_pac_ret_subtypes) },
+  { "bti", false, aarch_handle_bti_protection, NULL, 0 },
+  { NULL, false, NULL, NULL, 0 }
+};
+
 /* Implement TARGET_OPTION_OVERRIDE.  This is called once in the beginning
and is used to parse the -m{cpu,tune,arch} strings and setup the initial
tuning structs.  In particular it must set selected_tune and
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 159c61b786c..92e1248f83f 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -659,61 +659,6 @@ arm_md_asm_adjust (vec , vec & 
/*inputs*/,
   return saw_asm_flag ? seq : NULL;
 }
 
-static void
-aarch_handle_no_branch_protection (void)
-{
-  aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
-  aarch_enable_bti = 0;
-}
-
-static void
-aarch_handle_standard_branch_protection (void)
-{
-  aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
-  aarch_ra_sign_key = AARCH_KEY_A;
-  aarch_enable_bti = 1;
-}
-

[PATCH 05/11] aarch64: Add eh_return compile tests

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
gcc/testsuite/ChangeLog:

* gcc.target/aarch64/eh_return-2.c: New test.
* gcc.target/aarch64/eh_return-3.c: New test.
---
 gcc/testsuite/gcc.target/aarch64/eh_return-2.c |  9 +
 gcc/testsuite/gcc.target/aarch64/eh_return-3.c | 14 ++
 2 files changed, 23 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-3.c

diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-2.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
new file mode 100644
index 000..4a9d124e891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "add\tsp, sp, x5" } } */
+/* { dg-final { scan-assembler "br\tx6" } } */
+
+void
+foo (unsigned long off, void *handler)
+{
+  __builtin_eh_return (off, handler);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/eh_return-3.c 
b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
new file mode 100644
index 000..35989eee806
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/eh_return-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf" } */
+/* { dg-final { scan-assembler "add\tsp, sp, x5" } } */
+/* { dg-final { scan-assembler "br\tx6" } } */
+/* { dg-final { scan-assembler "hint\t25 // paciasp" } } */
+/* { dg-final { scan-assembler "hint\t29 // autiasp" } } */
+
+void
+foo (unsigned long off, void *handler, int c)
+{
+  if (c)
+return;
+  __builtin_eh_return (off, handler);
+}
-- 
2.25.1



[PATCH 10/11] aarch64: Fix branch-protection error message tests

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
Update tests for the new branch-protection parser errors.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/branch-protection-attr.c: Update.
* gcc.target/aarch64/branch-protection-option.c: Update.
---
 gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c   | 6 +++---
 gcc/testsuite/gcc.target/aarch64/branch-protection-option.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c 
b/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c
index 272000c2747..dae2a758a56 100644
--- a/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c
+++ b/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c
@@ -4,19 +4,19 @@ void __attribute__ ((target("branch-protection=leaf")))
 foo1 ()
 {
 }
-/* { dg-error {invalid protection type 'leaf' in 
'target\("branch-protection="\)' pragma or attribute} "" { target *-*-* } 5 } */
+/* { dg-error {invalid argument 'leaf' for 'target\("branch-protection="\)'} 
"" { target *-*-* } 5 } */
 /* { dg-error {pragma or attribute 'target\("branch-protection=leaf"\)' is not 
valid} "" { target *-*-* } 5 } */
 
 void __attribute__ ((target("branch-protection=none+pac-ret")))
 foo2 ()
 {
 }
-/* { dg-error "unexpected 'pac-ret' after 'none'" "" { target *-*-* } 12 } */
+/* { dg-error {argument 'none' can only appear alone in 
'target\("branch-protection="\)'} "" { target *-*-* } 12 } */
 /* { dg-error {pragma or attribute 
'target\("branch-protection=none\+pac-ret"\)' is not valid} "" { target *-*-* } 
12 } */
 
 void __attribute__ ((target("branch-protection=")))
 foo3 ()
 {
 }
-/* { dg-error {missing argument to 'target\("branch-protection="\)' pragma or 
attribute} "" { target *-*-* } 19 } */
+/* { dg-error {invalid argument '' for 'target\("branch-protection="\)'} "" { 
target *-*-* } 19 } */
 /* { dg-error {pragma or attribute 'target\("branch-protection="\)' is not 
valid} "" { target *-*-* } 19 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/branch-protection-option.c 
b/gcc/testsuite/gcc.target/aarch64/branch-protection-option.c
index 1b3bf4ee2b8..e2f847a31c4 100644
--- a/gcc/testsuite/gcc.target/aarch64/branch-protection-option.c
+++ b/gcc/testsuite/gcc.target/aarch64/branch-protection-option.c
@@ -1,4 +1,4 @@
 /* { dg-do "compile" } */
 /* { dg-options "-mbranch-protection=leaf -mbranch-protection=none+pac-ret" } 
*/
 
-/* { dg-error "unexpected 'pac-ret' after 'none'"  "" { target *-*-* } 0 } */
+/* { dg-error "argument 'none' can only appear alone in 
'-mbranch-protection='" "" { target *-*-* } 0 } */
-- 
2.25.1



[PATCH 04/11] aarch64: Do not force a stack frame for EH returns

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
EH returns no longer rely on clobbering the return address on the stack
so forcing a stack frame is not necessary.

This does not actually change the code gen for the unwinder since there
are calls before the EH return.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_needs_frame_chain): Do not
force frame chain for eh_return.
---
 gcc/config/aarch64/aarch64.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 36cd172d182..afdbf4213c1 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -8417,8 +8417,7 @@ aarch64_output_probe_sve_stack_clash (rtx base, rtx 
adjustment,
 static bool
 aarch64_needs_frame_chain (void)
 {
-  /* Force a frame chain for EH returns so the return address is at FP+8.  */
-  if (frame_pointer_needed || crtl->calls_eh_return)
+  if (frame_pointer_needed)
 return true;
 
   /* A leaf function cannot have calls or write LR.  */
-- 
2.25.1



[PATCH 09/11] aarch64,arm: Fix branch-protection= parsing

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
Refactor the parsing to have a single API and fix a few parsing issues:

- Different handling of "bti+none" and "none+bti": these should be
  rejected because "none" can only appear alone.

- Accepted empty strings such as "bti++pac-ret" or "bti+", this bug
  was caused by using strtok_r.

- Memory got leaked (str_root was never freed). And two buffers got
  allocated when one is enough.

The callbacks now have no failure mode, only parsing can fail and
all failures are handled locally.  The "-mbranch-protection=" vs
"target("branch-protection=")" difference in the error message is
handled by a separate argument to aarch_validate_mbranch_protection.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_override_options): Update.
(aarch64_handle_attr_branch_protection): Update.
* config/arm/aarch-common-protos.h (aarch_parse_branch_protection):
Remove.
(aarch_validate_mbranch_protection): Add new argument.
* config/arm/aarch-common.cc (aarch_handle_no_branch_protection):
Update.
(aarch_handle_standard_branch_protection): Update.
(aarch_handle_pac_ret_protection): Update.
(aarch_handle_pac_ret_leaf): Update.
(aarch_handle_pac_ret_b_key): Update.
(aarch_handle_bti_protection): Update.
(aarch_parse_branch_protection): Remove.
(next_tok): New.
(aarch_validate_mbranch_protection): Rewrite.
* config/arm/aarch-common.h (struct aarch_branch_protect_type):
Add field "alone".
* config/arm/arm.cc (arm_configure_build_target): Update.
---
 gcc/config/aarch64/aarch64.cc|  37 +
 gcc/config/arm/aarch-common-protos.h |   5 +-
 gcc/config/arm/aarch-common.cc   | 214 ---
 gcc/config/arm/aarch-common.h|  14 +-
 gcc/config/arm/arm.cc|   3 +-
 5 files changed, 109 insertions(+), 164 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 7f0a22fae9c..661ac12cacc 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18539,7 +18539,8 @@ aarch64_override_options (void)
 aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
 
   if (aarch64_branch_protection_string)
-aarch_validate_mbranch_protection (aarch64_branch_protection_string);
+aarch_validate_mbranch_protection (aarch64_branch_protection_string,
+  "-mbranch-protection=");
 
   /* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
  If either of -march or -mtune is given, they override their
@@ -18913,34 +18914,12 @@ aarch64_handle_attr_cpu (const char *str)
 
 /* Handle the argument STR to the branch-protection= attribute.  */
 
- static bool
- aarch64_handle_attr_branch_protection (const char* str)
- {
-  char *err_str = (char *) xmalloc (strlen (str) + 1);
-  enum aarch_parse_opt_result res = aarch_parse_branch_protection (str,
-  _str);
-  bool success = false;
-  switch (res)
-{
- case AARCH_PARSE_MISSING_ARG:
-   error ("missing argument to % pragma 
or"
- " attribute");
-   break;
- case AARCH_PARSE_INVALID_ARG:
-   error ("invalid protection type %qs in % pragma or attribute", err_str);
-   break;
- case AARCH_PARSE_OK:
-   success = true;
-  /* Fall through.  */
- case AARCH_PARSE_INVALID_FEATURE:
-   break;
- default:
-   gcc_unreachable ();
-}
-  free (err_str);
-  return success;
- }
+static bool
+aarch64_handle_attr_branch_protection (const char* str)
+{
+  return aarch_validate_mbranch_protection (str,
+   "target(\"branch-protection=\")");
+}
 
 /* Handle the argument STR to the tune= target attribute.  */
 
diff --git a/gcc/config/arm/aarch-common-protos.h 
b/gcc/config/arm/aarch-common-protos.h
index f8cb6562096..75ffdfbb050 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -159,10 +159,7 @@ rtx_insn *arm_md_asm_adjust (vec , vec & 
/*inputs*/,
 vec , HARD_REG_SET _regs,
 location_t loc);
 
-/* Parsing routine for branch-protection common to AArch64 and Arm.  */
-enum aarch_parse_opt_result aarch_parse_branch_protection (const char*, 
char**);
-
 /* Validation routine for branch-protection common to AArch64 and Arm.  */
-bool aarch_validate_mbranch_protection (const char *);
+bool aarch_validate_mbranch_protection (const char *, const char *);
 
 #endif /* GCC_AARCH_COMMON_PROTOS_H */
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index cbc7f68a8bf..159c61b786c 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -659,169 +659,143 @@ arm_md_asm_adjust (vec , vec & 
/*inputs*/,
   return saw_asm_flag ? seq : NULL;
 }
 
-static enum aarch_parse_opt_result

[PATCH 02/11] Handle epilogues that contain jumps

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
From: Richard Sandiford 

The prologue/epilogue pass allows the prologue sequence
to contain jumps.  The sequence is then partitioned into
basic blocks using find_many_sub_basic_blocks.

This patch treats epilogues in the same way.  It's needed for
a follow-on aarch64 patch that adds conditional code to both
the prologue and the epilogue.

Tested on aarch64-linux-gnu (including with a follow-on patch)
and x86_64-linux-gnu.  OK to install?

Richard

gcc/
* function.cc (thread_prologue_and_epilogue_insns): Handle
epilogues that contain jumps.
---

This is a previously approved patch that was not committed
because it was not needed at the time, but i'd like to commit
it as it is needed for the followup aarch64 eh_return changes:

https://gcc.gnu.org/pipermail/gcc-patches/2022-November/605769.html

---
 gcc/function.cc | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/gcc/function.cc b/gcc/function.cc
index dd2c1136e07..70d1cd65303 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -6120,6 +6120,11 @@ thread_prologue_and_epilogue_insns (void)
  && returnjump_p (BB_END (e->src)))
e->flags &= ~EDGE_FALLTHRU;
}
+
+ auto_sbitmap blocks (last_basic_block_for_fn (cfun));
+ bitmap_clear (blocks);
+   bitmap_set_bit (blocks, BLOCK_FOR_INSN (epilogue_seq)->index);
+ find_many_sub_basic_blocks (blocks);
}
   else if (next_active_insn (BB_END (exit_fallthru_edge->src)))
{
@@ -6218,6 +6223,11 @@ thread_prologue_and_epilogue_insns (void)
  set_insn_locations (seq, epilogue_location);
 
  emit_insn_before (seq, insn);
+
+ auto_sbitmap blocks (last_basic_block_for_fn (cfun));
+ bitmap_clear (blocks);
+ bitmap_set_bit (blocks, BLOCK_FOR_INSN (insn)->index);
+ find_many_sub_basic_blocks (blocks);
}
 }
 
-- 
2.25.1



[PATCH 03/11] aarch64: Use br instead of ret for eh_return

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
The expected way to handle eh_return is to pass the stack adjustment
offset and landing pad address via

  EH_RETURN_STACKADJ_RTX
  EH_RETURN_HANDLER_RTX

to the epilogue that is shared between normal return paths and the
eh_return paths.  EH_RETURN_HANDLER_RTX is the stack slot of the
return address that is overwritten with the landing pad in the
eh_return case and EH_RETURN_STACKADJ_RTX is a register added to sp
right before return and it is set to 0 in the normal return case.

The issue with this design is that eh_return and normal return may
require different return sequence but there is no way to distinguish
the two cases in the epilogue (the stack adjustment may be 0 in the
eh_return case too).

The reason eh_return and normal return requires different return
sequence is that control flow integrity hardening may need to treat
eh_return as a forward-edge transfer (it is not returning to the
previous stack frame) and normal return as a backward-edge one.
In case of AArch64 forward-edge is protected by BTI and requires br
instruction and backward-edge is protected by PAUTH or GCS and
requires ret (or authenticated ret) instruction.

This patch resolves the issue by using the EH_RETURN_STACKADJ_RTX
register only as a flag that is set to 1 in the eh_return paths
(it is 0 in normal return paths) and introduces

  AARCH64_EH_RETURN_STACKADJ_RTX
  AARCH64_EH_RETURN_HANDLER_RTX

to pass the actual stack adjustment and landing pad address to the
epilogue in the eh_return case. Then the epilogue can use the right
return sequence based on the EH_RETURN_STACKADJ_RTX flag.

The handler could be passed the old way via clobbering the return
address, but since now the eh_return case can be distinguished, the
handler can be in a different register than x30 and no stack frame
is needed for eh_return.

The new code generation for functions with eh_return is not amazing,
since x5 and x6 is assumed to be used by the epilogue even in the
normal return path, not just for eh_return.  But only the unwinder
is expected to use eh_return so this is fine.

This patch fixes a return to anywhere gadget in the unwinder with
existing standard branch protection as well as makes EH return
compatible with the Guarded Control Stack (GCS) extension.

gcc/ChangeLog:

* config/aarch64/aarch64-protos.h (aarch64_eh_return_handler_rtx):
Remove.
(aarch64_eh_return): New.
* config/aarch64/aarch64.cc (aarch64_return_address_signing_enabled):
Sign return address even in functions with eh_return.
(aarch64_epilogue_uses): Mark two registers as used.
(aarch64_expand_epilogue): Conditionally return with br or ret.
(aarch64_eh_return_handler_rtx): Remove.
(aarch64_eh_return): New.
* config/aarch64/aarch64.h (EH_RETURN_HANDLER_RTX): Remove.
(AARCH64_EH_RETURN_STACKADJ_REGNUM): Define.
(AARCH64_EH_RETURN_STACKADJ_RTX): Define.
(AARCH64_EH_RETURN_HANDLER_REGNUM): Define.
(AARCH64_EH_RETURN_HANDLER_RTX): Define.
* config/aarch64/aarch64.md (eh_return): New.
---
 gcc/config/aarch64/aarch64-protos.h |   2 +-
 gcc/config/aarch64/aarch64.cc   | 106 +++-
 gcc/config/aarch64/aarch64.h|  11 ++-
 gcc/config/aarch64/aarch64.md   |   8 +++
 4 files changed, 73 insertions(+), 54 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 70303d6fd95..5d1834162a4 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -855,7 +855,7 @@ machine_mode aarch64_hard_regno_caller_save_mode (unsigned, 
unsigned,
   machine_mode);
 int aarch64_uxt_size (int, HOST_WIDE_INT);
 int aarch64_vec_fpconst_pow_of_2 (rtx);
-rtx aarch64_eh_return_handler_rtx (void);
+void aarch64_eh_return (rtx);
 rtx aarch64_mask_from_zextract_ops (rtx, rtx);
 const char *aarch64_output_move_struct (rtx *operands);
 rtx aarch64_return_addr_rtx (void);
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index eba5d4a7e04..36cd172d182 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -8972,17 +8972,6 @@ aarch64_return_address_signing_enabled (void)
   /* This function should only be called after frame laid out.   */
   gcc_assert (cfun->machine->frame.laid_out);
 
-  /* Turn return address signing off in any function that uses
- __builtin_eh_return.  The address passed to __builtin_eh_return
- is not signed so either it has to be signed (with original sp)
- or the code path that uses it has to avoid authenticating it.
- Currently eh return introduces a return to anywhere gadget, no
- matter what we do here since it uses ret with user provided
- address. An ideal fix for that is to use indirect branch which
- can be protected with BTI j (to some extent).  */
-  if (crtl->calls_eh_return)
-return false;
-
   /* If signing scope 

[PATCH 08/11] aarch64,arm: Remove accepted_branch_protection_string

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
On aarch64 this caused ICE with pragma push_options since

  commit ae54c1b09963779c5c3914782324ff48af32e2f1
  Author: Wilco Dijkstra 
  CommitDate: 2022-06-01 18:13:57 +0100

  AArch64: Cleanup option processing code

The failure is at pop_options:

internal compiler error: ‘global_options’ are modified in local context

On arm the variable was unused.

gcc/ChangeLog:

* config/aarch64/aarch64.cc (aarch64_override_options_after_change_1):
Do not override branch_protection options.
(aarch64_override_options): Remove accepted_branch_protection_string.
* config/arm/aarch-common.cc (BRANCH_PROTECT_STR_MAX): Remove.
(aarch_parse_branch_protection): Remove
accepted_branch_protection_string.
* config/arm/arm.cc: Likewise.
---
 gcc/config/aarch64/aarch64.cc  | 10 +-
 gcc/config/arm/aarch-common.cc | 16 
 gcc/config/arm/arm.cc  |  2 --
 3 files changed, 1 insertion(+), 27 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index afdbf4213c1..7f0a22fae9c 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -322,8 +322,6 @@ bool aarch64_pcrelative_literal_loads;
 /* Global flag for whether frame pointer is enabled.  */
 bool aarch64_use_frame_pointer;
 
-char *accepted_branch_protection_string = NULL;
-
 /* Support for command line parsing of boolean flags in the tuning
structures.  */
 struct aarch64_flag_desc
@@ -18004,12 +18002,6 @@ aarch64_adjust_generic_arch_tuning (struct tune_params 
_tune)
 static void
 aarch64_override_options_after_change_1 (struct gcc_options *opts)
 {
-  if (accepted_branch_protection_string)
-{
-  opts->x_aarch64_branch_protection_string
-   = xstrdup (accepted_branch_protection_string);
-}
-
   /* PR 70044: We have to be careful about being called multiple times for the
  same function.  This means all changes should be repeatable.  */
 
@@ -18612,7 +18604,7 @@ aarch64_override_options (void)
   /* Return address signing is currently not supported for ILP32 targets.  For
  LP64 targets use the configured option in the absence of a command-line
  option for -mbranch-protection.  */
-  if (!TARGET_ILP32 && accepted_branch_protection_string == NULL)
+  if (!TARGET_ILP32 && aarch64_branch_protection_string == NULL)
 {
 #ifdef TARGET_ENABLE_PAC_RET
   aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
index 5b96ff4c2e8..cbc7f68a8bf 100644
--- a/gcc/config/arm/aarch-common.cc
+++ b/gcc/config/arm/aarch-common.cc
@@ -659,9 +659,6 @@ arm_md_asm_adjust (vec , vec & /*inputs*/,
   return saw_asm_flag ? seq : NULL;
 }
 
-#define BRANCH_PROTECT_STR_MAX 255
-extern char *accepted_branch_protection_string;
-
 static enum aarch_parse_opt_result
 aarch_handle_no_branch_protection (char* str, char* rest)
 {
@@ -812,19 +809,6 @@ aarch_parse_branch_protection (const char *const_str, 
char** last_str)
   else
*last_str = NULL;
 }
-
-  if (res == AARCH_PARSE_OK)
-{
-  /* If needed, alloc the accepted string then copy in const_str.
-   Used by override_option_after_change_1.  */
-  if (!accepted_branch_protection_string)
-   accepted_branch_protection_string
- = (char *) xmalloc (BRANCH_PROTECT_STR_MAX + 1);
-  strncpy (accepted_branch_protection_string, const_str,
-  BRANCH_PROTECT_STR_MAX + 1);
-  /* Forcibly null-terminate.  */
-  accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
-}
   return res;
 }
 
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 6e933c80183..f49312cace0 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -2424,8 +2424,6 @@ const struct tune_params arm_fa726te_tune =
   tune_params::SCHED_AUTOPREF_OFF
 };
 
-char *accepted_branch_protection_string = NULL;
-
 /* Auto-generated CPU, FPU and architecture tables.  */
 #include "arm-cpu-data.h"
 
-- 
2.25.1



[PATCH 07/11] aarch64: Disable branch-protection for pcs tests

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
The tests manipulate the return address in abitest-2.h and thus not
compatible with -mbranch-protection=pac-ret+leaf or
-mbranch-protection=gcs.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/aapcs64/func-ret-1.c: Disable branch-protection.
* gcc.target/aarch64/aapcs64/func-ret-2.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-3.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-4.c: Likewise.
* gcc.target/aarch64/aapcs64/func-ret-64x1_1.c: Likewise.
---
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c  | 1 +
 gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c | 1 +
 5 files changed, 5 insertions(+)

diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
index 5405e1e4920..7bd7757efe6 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
@@ -4,6 +4,7 @@
AAPCS64 \S 4.1.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
index 6b171c46fbb..85a822ace4a 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-2.c
@@ -4,6 +4,7 @@
Homogeneous floating-point aggregate types are covered in func-ret-3.c.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
index ad312b675b9..1d35ebf14b4 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
@@ -4,6 +4,7 @@
in AAPCS64 \S 4.3.5.  */
 
 /* { dg-do run { target aarch64-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 /* { dg-require-effective-target aarch64_big_endian } */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
index af05fbe9fdf..15e1408c62d 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-4.c
@@ -5,6 +5,7 @@
are treated as general composite types.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 /* { dg-require-effective-target aarch64_big_endian } */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c 
b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
index 05957e2dcae..fe7bbb6a835 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-64x1_1.c
@@ -3,6 +3,7 @@
   Test 64-bit singleton vector types which should be in FP/SIMD registers.  */
 
 /* { dg-do run { target aarch64*-*-* } } */
+/* { dg-additional-options "-mbranch-protection=none" } */
 /* { dg-additional-sources "abitest.S" } */
 
 #ifndef IN_FRAMEWORK
-- 
2.25.1



[PATCH 06/11] aarch64: Fix pac-ret eh_return tests

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
This is needed since eh_return no longer prevents pac-ret in the
normal return path.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/return_address_sign_1.c: Move func4 to ...
* gcc.target/aarch64/return_address_sign_2.c: ... here and fix the
scan asm check.
* gcc.target/aarch64/return_address_sign_b_1.c: Move func4 to ...
* gcc.target/aarch64/return_address_sign_b_2.c: ... here and fix the
scan asm check.
---
 .../gcc.target/aarch64/return_address_sign_1.c  | 13 +
 .../gcc.target/aarch64/return_address_sign_2.c  | 17 +++--
 .../aarch64/return_address_sign_b_1.c   | 11 ---
 .../aarch64/return_address_sign_b_2.c   | 17 +++--
 4 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c 
b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
index 232ba67ade0..114a9dacb3f 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -37,16 +37,5 @@ func3 (int a, int b, int c)
   /* autiasp */
 }
 
-/* eh_return.  */
-void __attribute__ ((target ("arch=armv8.3-a")))
-func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
-{
-  /* no paciasp */
-  *ptr = imm1 + foo (imm1) + imm2;
-  __builtin_eh_return (offset, handler);
-  /* no autiasp */
-  return;
-}
-
-/* { dg-final { scan-assembler-times "autiasp" 3 } } */
 /* { dg-final { scan-assembler-times "paciasp" 3 } } */
+/* { dg-final { scan-assembler-times "autiasp" 3 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c 
b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
index a4bc5b45333..d93492c3c43 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_2.c
@@ -14,5 +14,18 @@ func1 (int a, int b, int c)
   /* retaa */
 }
 
-/* { dg-final { scan-assembler-times "paciasp" 1 } } */
-/* { dg-final { scan-assembler-times "retaa" 1 } } */
+/* eh_return.  */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+  /* paciasp */
+  *ptr = imm1 + foo (imm1) + imm2;
+  if (handler)
+/* br */
+__builtin_eh_return (offset, handler);
+  /* retaa */
+  return;
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 2 } } */
+/* { dg-final { scan-assembler-times "retaa" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c 
b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
index 43e32ab6cb7..697fa30dc5a 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
@@ -37,16 +37,5 @@ func3 (int a, int b, int c)
   /* autibsp */
 }
 
-/* eh_return.  */
-void __attribute__ ((target ("arch=armv8.3-a")))
-func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
-{
-  /* no pacibsp */
-  *ptr = imm1 + foo (imm1) + imm2;
-  __builtin_eh_return (offset, handler);
-  /* no autibsp */
-  return;
-}
-
 /* { dg-final { scan-assembler-times "pacibsp" 3 } } */
 /* { dg-final { scan-assembler-times "autibsp" 3 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c 
b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
index 9ed64ce0591..748924c72f3 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
@@ -14,5 +14,18 @@ func1 (int a, int b, int c)
   /* retab */
 }
 
-/* { dg-final { scan-assembler-times "pacibsp" 1 } } */
-/* { dg-final { scan-assembler-times "retab" 1 } } */
+/* eh_return.  */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+  /* paciasp */
+  *ptr = imm1 + foo (imm1) + imm2;
+  if (handler)
+/* br */
+__builtin_eh_return (offset, handler);
+  /* retab */
+  return;
+}
+
+/* { dg-final { scan-assembler-times "pacibsp" 2 } } */
+/* { dg-final { scan-assembler-times "retab" 2 } } */
-- 
2.25.1



[PATCH 01/11] aarch64: AARCH64_ISA_RCPC was defined twice

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
gcc/ChangeLog:

* config/aarch64/aarch64.h (AARCH64_ISA_RCPC): Remove dup.
---
 gcc/config/aarch64/aarch64.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 2b0fc97bb71..c783cb96c48 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -222,7 +222,6 @@ enum class aarch64_feature : unsigned char {
 #define AARCH64_ISA_MOPS  (aarch64_isa_flags & AARCH64_FL_MOPS)
 #define AARCH64_ISA_LS64  (aarch64_isa_flags & AARCH64_FL_LS64)
 #define AARCH64_ISA_CSSC  (aarch64_isa_flags & AARCH64_FL_CSSC)
-#define AARCH64_ISA_RCPC   (aarch64_isa_flags & AARCH64_FL_RCPC)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (AARCH64_ISA_CRYPTO)
-- 
2.25.1



[PATCH 00/11] aarch64 GCS preliminary patches

2023-08-22 Thread Szabolcs Nagy via Gcc-patches
I'm working on Guarded Control Stack support for aarch64 and have a
set of patches that are needed for GCS but seem useful without it so
makes sense to review them separately from the rest of the GCS work.

GCS support will depend on the linux ABI that is under discussion at
https://lore.kernel.org/lkml/20230807-arm64-gcs-v4-0-68cfa37f9...@kernel.org/
so it will come later.

Richard Sandiford (1):
  Handle epilogues that contain jumps

Szabolcs Nagy (10):
  aarch64: AARCH64_ISA_RCPC was defined twice
  aarch64: Use br instead of ret for eh_return
  aarch64: Do not force a stack frame for EH returns
  aarch64: Add eh_return compile tests
  aarch64: Fix pac-ret eh_return tests
  aarch64: Disable branch-protection for pcs tests
  aarch64,arm: Remove accepted_branch_protection_string
  aarch64,arm: Fix branch-protection= parsing
  aarch64: Fix branch-protection error message tests
  aarch64,arm: Move branch-protection data to targets

 gcc/config/aarch64/aarch64-opts.h |   6 +-
 gcc/config/aarch64/aarch64-protos.h   |   2 +-
 gcc/config/aarch64/aarch64.cc | 211 +---
 gcc/config/aarch64/aarch64.h  |  12 +-
 gcc/config/aarch64/aarch64.md |   8 +
 gcc/config/arm/aarch-common-protos.h  |   5 +-
 gcc/config/arm/aarch-common.cc| 229 +-
 gcc/config/arm/aarch-common.h |  25 +-
 gcc/config/arm/arm-c.cc   |   2 -
 gcc/config/arm/arm.cc |  57 -
 gcc/config/arm/arm.opt|   3 -
 gcc/function.cc   |  10 +
 .../gcc.target/aarch64/aapcs64/func-ret-1.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-2.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-3.c   |   1 +
 .../gcc.target/aarch64/aapcs64/func-ret-4.c   |   1 +
 .../aarch64/aapcs64/func-ret-64x1_1.c |   1 +
 .../aarch64/branch-protection-attr.c  |   6 +-
 .../aarch64/branch-protection-option.c|   2 +-
 .../gcc.target/aarch64/eh_return-2.c  |   9 +
 .../gcc.target/aarch64/eh_return-3.c  |  14 ++
 .../aarch64/return_address_sign_1.c   |  13 +-
 .../aarch64/return_address_sign_2.c   |  17 +-
 .../aarch64/return_address_sign_b_1.c |  11 -
 .../aarch64/return_address_sign_b_2.c |  17 +-
 25 files changed, 338 insertions(+), 326 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/eh_return-3.c

-- 
2.25.1



Re: [PATCH] aarch64: Fix warnings during libgcc build

2023-07-12 Thread Szabolcs Nagy via Gcc-patches
The 07/11/2023 17:20, Florian Weimer wrote:
> * Richard Earnshaw:
> 
> > On 11/07/2023 10:37, Florian Weimer via Gcc-patches wrote:
> >> libgcc/
> >>* config/aarch64/aarch64-unwind.h
> >> (aarch64_cie_signed_with_b_key):
> >>Add missing const qualifier.  Cast from const unsigned char *
> >>to const char *.  Use __builtin_strchr to avoid an implicit
> >>function declaration.
> >>* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
> >>Add missing cast.
> >> ---
> >> diff --git a/libgcc/config/aarch64/linux-unwind.h 
> >> b/libgcc/config/aarch64/linux-unwind.h
> >> index 00eba866049..93da7a9537d 100644
> >> --- a/libgcc/config/aarch64/linux-unwind.h
> >> +++ b/libgcc/config/aarch64/linux-unwind.h
> >> @@ -77,7 +77,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context 
> >> *context,
> >>   }
> >>   rt_ = context->cfa;
> >> -  sc = _->uc.uc_mcontext;
> >> +  sc = (struct sigcontext *) _->uc.uc_mcontext;
> >> /* This define duplicates the definition in aarch64.md */
> >>   #define SP_REGNUM 31
> >> 
> >
> > This looks somewhat dubious.  I'm not particularly familiar with the
> > kernel headers, but a quick look suggests an mcontext_t is nothing
> > like a sigcontext_t.  So isn't the cast just papering over some more
> > fundamental problem?
> 
> I agree it looks dubious.  Note that it's struct sigcontext, not
> (not-struct) sigcontext_t.  I don't know why the uc_mcontext members
> aren't accessed directly, so I can't really write a good comment about
> it.

historically glibc typedefed mcontext_t to linux struct sigcontext
so this used to work fine. (i dont know about other os-es)

then at some point glibc fixed the namespace polluting fields
when building for posix which required a separate mcontext_t.

i guess either fix works: moving to the correct mcontext_t or to
cast to struct sigcontext, but the former means the fields must
be changed when building in a posix conforming mode (i guess
libgcc is built with _GNU_SOURCE so may not be an issue) and
they may be different across different libcs (or even different
versions of glibc) then.

> 
> Obviously it works quite well as-is. 8-)  Similar code is present in
> many, many Linux targets.
> 
> Thanks,
> Florian
> 


Re: [PATCH] libgcc: Fix uninitialized RA signing on AArch64 [PR107678]

2023-01-05 Thread Szabolcs Nagy via Gcc-patches
The 01/03/2023 17:27, Wilco Dijkstra wrote:
> 
> > Also, if I understood correctly, the reason we use REG_UNSAVED is to
> > ensure that state from one frame isn't carried across to a parent frame,
> > in cases where the parent frame lacks any signing.  That is, each frame
> > should start out with a zero bit even if a child frame is unwound while
> > it has a set bit.
> 
> This works fine since all registers are initialized to REG_UNSAVED every 
> frame.
> 
> In v2 I've removed some clutter and encode the signing state in REG_UNSAVED/
> REG_UNDEFINED.

this looks good to me.


> @@ -1206,8 +1205,10 @@ execute_cfa_program (const unsigned char *insn_ptr,
>   /* This CFA is multiplexed with Sparc.  On AArch64 it's used to 
> toggle
>  return address signing status.  */
>   reg = DWARF_REGNUM_AARCH64_RA_STATE;
> - gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
> - fs->regs.reg[reg].loc.offset ^= 1;
> + if (fs->regs.how[reg] == REG_UNSAVED)
> +   fs->regs.how[reg] = REG_UNDEFINED;
> + else
> +   fs->regs.how[reg] = REG_UNSAVED;
>  #else
>   /* ??? Hardcoded for SPARC register window configuration.  */
>   if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)

i would keep the assert: how[reg] must be either UNSAVED or UNDEFINED
here, other how[reg] means the toggle cfi instruction is mixed with
incompatible instructions for the pseudo reg.

and i would add a comment about this e.g. saying that UNSAVED/UNDEFINED
how[reg] is used for tracking the return address signing status and
other how[reg] is not allowed here.

otherwise the patch looks good.



Re: [PATCH] libgcc: Fix uninitialized RA signing on AArch64 [PR107678]

2022-12-06 Thread Szabolcs Nagy via Gcc-patches
The 12/06/2022 11:58, Wilco Dijkstra wrote:
> > i don't think how[*RA_STATE] can ever be set to REG_SAVED_OFFSET,
> > this pseudo reg is not spilled to the stack, it is reset to 0 in
> > each frame and then toggled within a frame.
> 
> It's is just a state, we can use any state we want since it is a pseudo reg.
> These registers are global and shared across all functions in an unwind,
> so their state or value isn't reset for each frame. So if we want to reset
> it in each frame then using a virtual register to hold per-function data
> seems like a bad design. I'm surprised nobody has ever tested it...

it was tested (and worked when the frame state was initialized).

in principle the CIE can contain instructions to initialize the
register state for a frame. the RA_STATE pseudo reg behaves as if
the CIE always set its value to 0 at the start of the frame.

the design has issues, but this is what we have now.

the toggle instruction for RA_STATE does not really fit the dwarf
model: the CFI instruction sequence is evaluated with a context
that is valid at the end of the sequence so an unwinder only wants
to evaluate a register's state at the end, not intermediate values
(where the context might not even be valid). so we limited the
instructions allowed for RA_STATE: only remember_/restore_state,
toggle and val_expression are supported and the latter two cannot
be mixed. we still have to use the existing struct for keeping
track of this hence reg[RA_STATE].loc.offset.

and of course the RA_STATE pseudo reg is only used for computing
the return address not propagated to the previous frame so it is
special in many ways. so we will need target hooks to fix this
and i think the cleanest is to initialize RA_STATE per frame and
leave the rest as is.



Re: [PATCH] libgcc: Fix uninitialized RA signing on AArch64 [PR107678]

2022-12-06 Thread Szabolcs Nagy via Gcc-patches
The 12/05/2022 19:04, Richard Sandiford wrote:
> Wilco Dijkstra  writes:
> > A recent change only initializes the regs.how[] during Dwarf unwinding
> > which resulted in an uninitialized offset used in return address signing
> > and random failures during unwinding.  The fix is to use REG_SAVED_OFFSET
> > as the state where the return address signing bit is valid, and if the
> > state is REG_UNSAVED, initialize it to 0.
> >
> > Passes bootstrap & regress, OK for commit?
> >
> > libgcc/
> > PR target/107678
> > * unwind-dw2.c (execute_cfa_program): Initialize offset of
> > DWARF_REGNUM_AARCH64_RA_STATE if in REG_UNSAVED state.
> > * config/aarch64/aarch64-unwind.h (aarch64_frob_update_contex):
> > Check state is REG_SAVED_OFFSET before using offset for RA state.
> >
> > ---
> >
> > diff --git a/libgcc/config/aarch64/aarch64-unwind.h 
> > b/libgcc/config/aarch64/aarch64-unwind.h
> > index 
> > 26db9cbd9e5c526e0c410a4fc6be2bedb7d261cf..597133b3d708a50a366c8bfeff57475f5522b3f6
> >  100644
> > --- a/libgcc/config/aarch64/aarch64-unwind.h
> > +++ b/libgcc/config/aarch64/aarch64-unwind.h
> > @@ -71,21 +71,15 @@ aarch64_demangle_return_addr (struct _Unwind_Context 
> > *context,
> >  }
> >  
> >  /* Do AArch64 private initialization on CONTEXT based on frame info FS.  
> > Mark
> > -   CONTEXT as return address signed if bit 0 of 
> > DWARF_REGNUM_AARCH64_RA_STATE is
> > -   set.  */
> > +   CONTEXT as having a signed return address if 
> > DWARF_REGNUM_AARCH64_RA_STATE
> > +   is initialized (REG_SAVED_OFFSET state) and the offset has bit 0 set.  
> > */
> >  
> >  static inline void
> >  aarch64_frob_update_context (struct _Unwind_Context *context,
> >  _Unwind_FrameState *fs)
> >  {
> > -  const int reg = DWARF_REGNUM_AARCH64_RA_STATE;
> > -  int ra_signed;
> > -  if (fs->regs.how[reg] == REG_UNSAVED)
> > -ra_signed = fs->regs.reg[reg].loc.offset & 0x1;
> > -  else
> > -ra_signed = _Unwind_GetGR (context, reg) & 0x1;
> > -  if (ra_signed)
> > -/* The flag is used for re-authenticating EH handler's address.  */
> > +  if (fs->regs.how[DWARF_REGNUM_AARCH64_RA_STATE] == REG_SAVED_OFFSET
> > +  && (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 1) != 0)
> >  context->flags |= RA_SIGNED_BIT;
> >else
> >  context->flags &= ~RA_SIGNED_BIT;
> 
> Hmm, but the point of the original patch was to support code generators
> that emit DW_CFA_val_expression instead of DW_CFA_AARCH64_negate_ra_state.
> Doesn't this patch undo that?
> 
> Also, if I understood correctly, the reason we use REG_UNSAVED is to
> ensure that state from one frame isn't carried across to a parent frame,
> in cases where the parent frame lacks any signing.  That is, each frame
> should start out with a zero bit even if a child frame is unwound while
> it has a set bit.

yes.

i don't think how[*RA_STATE] can ever be set to REG_SAVED_OFFSET,
this pseudo reg is not spilled to the stack, it is reset to 0 in
each frame and then toggled within a frame.

unwind-dw2.c has

case DW_CFA_GNU_window_save:
#if defined (__aarch64__) && !defined (__ILP32__)
  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
 return address signing status.  */
  reg = DWARF_REGNUM_AARCH64_RA_STATE;
  gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
  fs->regs.reg[reg].loc.offset ^= 1;

for this to work, loc.offset must be reset in uw_frame_state_for.
we may need a new hook for that.


> 
> Thanks,
> Richard
> 
> > diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
> > index 
> > eaceace20298b9b13344aff9d1fe9ee5f9c7bd73..87f2ae065b67982ce48f74e45523d9c754a7661c
> >  100644
> > --- a/libgcc/unwind-dw2.c
> > +++ b/libgcc/unwind-dw2.c
> > @@ -1203,11 +1203,16 @@ execute_cfa_program (const unsigned char *insn_ptr,
> >  
> > case DW_CFA_GNU_window_save:
> >  #if defined (__aarch64__) && !defined (__ILP32__)
> > - /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
> > -return address signing status.  */
> > - reg = DWARF_REGNUM_AARCH64_RA_STATE;
> > - gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
> > - fs->regs.reg[reg].loc.offset ^= 1;
> > +/* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
> > +   the return address signing status.  It is initialized at the first
> > +   use and the state is stored in bit 0 of the offset.  */
> > +reg = DWARF_REGNUM_AARCH64_RA_STATE;
> > +if (fs->regs.how[reg] == REG_UNSAVED)
> > +  {
> > +fs->regs.how[reg] = REG_SAVED_OFFSET;
> > +fs->regs.reg[reg].loc.offset = 0;
> > +  }
> > +fs->regs.reg[reg].loc.offset ^= 1;
> >  #else
> >   /* ??? Hardcoded for SPARC register window configuration.  */
> >   if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)


Re: [PATCH] aarch64: Fix pac-ret with unusual dwarf in libgcc unwinder [PR104689]

2022-05-24 Thread Szabolcs Nagy via Gcc-patches
The 05/13/2022 16:35, Richard Sandiford wrote:
> Szabolcs Nagy via Gcc-patches  writes:
> > The RA_SIGN_STATE dwarf pseudo-register is normally only set using the
> > DW_CFA_AARCH64_negate_ra_state (== DW_CFA_window_save) operation which
> > toggles the return address signedness state (the default state is 0).
> > (It may be set by remember/restore_state CFI too, those save/restore
> > the state of all registers.)
> >
> > However RA_SIGN_STATE can be set directly via DW_CFA_val_expression too.
> > GCC does not generate such CFI but some other compilers reportedly do.
> >
> > Note: the toggle operation must not be mixed with other dwarf register
> > rule CFI within the same CIE and FDE.
> >
> > In libgcc we assume REG_UNSAVED means the RA_STATE is set using toggle
> > operations, otherwise we assume its value is set by other CFI.
> 
> AFAIK, this is the first time I've looked at the RA_SIGN_STATE code,
> so this is probably a naive point/question, but: it seems a bit
> underhand for the existing code to be using REG_UNSAVED and
> loc.offset to hold the toggle state.  Would it make sense to add
> a new enum value for known, pre-evaluated constants?  _Unwind_GetGR
> would then DTRT for both cases.
> 
> That's a comment about the pre-existing code though.  I agree this
> patch looks like the right fix if we keep to the current approach.

yes, this is a hack. i looked at introducing a generic REG_*
enum to deal with RA_SIGN_STATE now, but it's a bit awkward:

normally frame state for a reg starts out REG_UNSAVED, which
should mean 0 value for the RA_SIGN_STATE pseudo register.

when moving up frames the uw context gets copied and updated
according to the frame state (where REG_UNSAVED normally means
unmodified copy), this is not right for RA_SIGN_STATE which
should be reset in the absence of related dwarf ops. we can
fix this up in target hooks for update context, but we still
have to special case REG_UNSAVED.

i think introducing a new REG_CONST does not simplify the
aarch64 target code (we might need further changes to get
a clean solution).


[PATCH] aarch64: Fix pac-ret with unusual dwarf in libgcc unwinder [PR104689]

2022-05-10 Thread Szabolcs Nagy via Gcc-patches
The RA_SIGN_STATE dwarf pseudo-register is normally only set using the
DW_CFA_AARCH64_negate_ra_state (== DW_CFA_window_save) operation which
toggles the return address signedness state (the default state is 0).
(It may be set by remember/restore_state CFI too, those save/restore
the state of all registers.)

However RA_SIGN_STATE can be set directly via DW_CFA_val_expression too.
GCC does not generate such CFI but some other compilers reportedly do.

Note: the toggle operation must not be mixed with other dwarf register
rule CFI within the same CIE and FDE.

In libgcc we assume REG_UNSAVED means the RA_STATE is set using toggle
operations, otherwise we assume its value is set by other CFI.

libgcc/ChangeLog:

PR target/104689
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Handle the !REG_UNSAVED case.
* unwind-dw2.c (execute_cfa_program): Fail toggle if !REG_UNSAVED.

gcc/testsuite/ChangeLog:

PR target/104689
* gcc.target/aarch64/pr104689.c: New test.
---
 gcc/testsuite/gcc.target/aarch64/pr104689.c | 149 
 libgcc/config/aarch64/aarch64-unwind.h  |   8 +-
 libgcc/unwind-dw2.c |   4 +-
 3 files changed, 159 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr104689.c

diff --git a/gcc/testsuite/gcc.target/aarch64/pr104689.c 
b/gcc/testsuite/gcc.target/aarch64/pr104689.c
new file mode 100644
index 000..3b7adbdfe7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr104689.c
@@ -0,0 +1,149 @@
+/* PR target/104689. Unwind across pac-ret frames with unusual dwarf.  */
+/* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-fexceptions -O2" } */
+
+#include 
+#include 
+#include 
+
+#define die() \
+  do { \
+printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \
+fflush (stdout); \
+abort (); \
+  } while (0)
+
+
+/* Code to invoke unwinding with a logging callback.  */
+
+static struct _Unwind_Exception exc;
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+   _Unwind_Exception_Class exc_class,
+   struct _Unwind_Exception *exc_obj,
+   struct _Unwind_Context *context,
+   void *stop_parameter)
+{
+  printf ("%s: CFA: %p PC: %p actions: %d\n",
+ __func__,
+ (void *)_Unwind_GetCFA (context),
+ (void *)_Unwind_GetIP (context),
+ (int)actions);
+  if (actions & _UA_END_OF_STACK)
+die ();
+  return _URC_NO_REASON;
+}
+
+static void force_unwind (void)
+{
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (, force_unwind_stop, 0);
+#endif
+}
+
+
+/* Define functions with unusual pac-ret dwarf via top level asm.  */
+
+#define STR(x) #x
+#define DW_CFA_val_expression 0x16
+#define RA_SIGN_STATE 34
+#define DW_OP_lit0 0x30
+#define DW_OP_lit1 0x31
+
+#define cfi_escape(a1, a2, a3, a4) \
+  ".cfi_escape " STR(a1) ", " STR(a2) ", " STR(a3) ", " STR(a4)
+
+/* Bytes: 0x16 0x22 0x01 0x30  */
+#define SET_RA_STATE_0 \
+  cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit0)
+
+/* Bytes: 0x16 0x22 0x01 0x31  */
+#define SET_RA_STATE_1 \
+  cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit1)
+
+/* These function call their argument.  */
+void unusual_pac_ret (void *);
+void unusual_no_pac_ret (void *);
+
+asm(""
+".global unusual_pac_ret\n"
+".type unusual_pac_ret, %function\n"
+"unusual_pac_ret:\n"
+"  .cfi_startproc\n"
+"  " SET_RA_STATE_0 "\n"
+"  hint25 // paciasp\n"
+"  " SET_RA_STATE_1 "\n"
+"  stp x29, x30, [sp, -16]!\n"
+"  .cfi_def_cfa_offset 16\n"
+"  .cfi_offset 29, -16\n"
+"  .cfi_offset 30, -8\n"
+"  mov x29, sp\n"
+"  blr x0\n"
+"  ldp x29, x30, [sp], 16\n"
+"  .cfi_restore 30\n"
+"  .cfi_restore 29\n"
+"  .cfi_def_cfa_offset 0\n"
+"  hint29 // autiasp\n"
+"  " SET_RA_STATE_0 "\n"
+"  ret\n"
+"  .cfi_endproc\n");
+
+asm(""
+".global unusual_no_pac_ret\n"
+".type unusual_no_pac_ret, %function\n"
+"unusual_no_pac_ret:\n"
+"  .cfi_startproc\n"
+"  " SET_RA_STATE_0 "\n"
+"  stp x29, x30, [sp, -16]!\n"
+"  .cfi_def_cfa_offset 16\n"
+"  .cfi_offset 29, -16\n"
+"  .cfi_offset 30, -8\n"
+"  mov x29, sp\n"
+"  blr x0\n"
+"  ldp x29, x30, [sp], 16\n"
+"  .cfi_restore 30\n"
+"  .cfi_restore 29\n"
+"  .cfi_def_cfa_offset 0\n"
+"  ret\n"
+"  .cfi_endproc\n");
+
+
+/* Functions to create a call chain with mixed pac-ret dwarf.  */
+
+__attribute__((target("branch-protection=pac-ret")))
+static void f2_pac_ret (void)
+{
+  force_unwind ();
+  die ();
+}
+
+__attribute__((target("branch-protection=none")))
+static void f1_no_pac_ret (void)
+{
+  unusual_pac_ret (f2_pac_ret);
+  die ();
+}
+
+__attribute__((noinline, 

Re: [PATCH] [RFC][PR102768] aarch64: Add compiler support for Shadow Call Stack

2021-11-23 Thread Szabolcs Nagy via Gcc-patches
The 11/23/2021 16:32, Dan Li wrote:
> On 11/3/21 8:00 PM, Szabolcs Nagy wrote:
> > i assume exception handling info has to change for scs to
> > work (to pop the shadow stack when transferring control),
> > so either scs must require -fno-exceptions or the eh info
> > changes must be implemented.
> > 
> > i think the kernel does not require exceptions and does
> > not depend on the unwinder runtime in libgcc, so this
> > is optional for the linux kernel use-case.
> > 
> I recompiled a glibc and gcc runtime library with -ffixed-x18 enabled.
> As you said, the scs stack needs to be popped at the same time during
> exception handling.
> 
> I saw that Clang is processed by adding
> ".cfi_escape 0x16, 0x12, 0x02, 0x82, 0x78"
> directive (x18 -= 8;) after each emit of scs push[2].
> 
> But this directive has problems when executed in libgcc:
> 1)context->reg[x] in uw_init_context_1 are all based on cfa, most
>   registers have no initial values by default.
> 2)Address of shadow call stack (x18) cannot(and should not) be calculated
>   based on cfa, and I did not yet find a way to assign hardware register
>   x18 to context->reg[18].
> 3)This causes libgcc to crash when parsing .cfi_escape exp because of 0
>   address dereference (* x18)
>   (execute_stack_op => case DW_OP_breg18: _Unwind_GetGR)
> 4)uw_install_context_1 does not restore all hardware registers by default
>   before eh return, so context->reg[18] can't write directly to hw x18.
>   (In clang, __unw_getcontext/__unw_resume will save/restore all hardware
>   registers, so this directive works fine in my libunwind test.)
> 
> I tried to fix this problem through a patch[3], the exception handling
> works fine in my test environment, but I'm not sure if this fix is
> ppropriate for two reasons:
> 1)libgcc does not push/pop all registers by default during exception
>   handling. Is this change appropriate?
> 2)The test case may not be able to test this patch, because the test
>   environment requires at least on glibc/gcc runtime compiled with
>   -ffixed-x18.
> 
> May be it's better to rely on -fno-exceptions for this patch first? and If
> the glibc/gcc runtime also supports SCS later, the problem can be fixed
> at the same time.

i did not look at the exception handling in detail (that's
difficult to understand for me too).

to use scs, non-default abi is required anyway, so not
supporting exceptions sounds fine to me. however it should
be documented and ideally enforced (-fexceptions should
be rejected, just like -fno-fixed-x18).

i assume the linux kernel does not require -fexceptions.

> 
> PS:
> I'm still not familiar enough with exception handling in libgcc/libunwind,
> please correct me if there are any mistakes :)
> 
> [1] 
> https://github.com/llvm/llvm-project/commit/f11eb3ebe77729426e562d7d4d7ebb1d5ff2e7c8
> [2] https://reviews.llvm.org/D54609
> [3] https://gcc.gnu.org/bugzilla/attachment.cgi?id=51854=diff
> 


Re: [PATCH] [RFC][PR102768] aarch64: Add compiler support for Shadow Call Stack

2021-11-03 Thread Szabolcs Nagy via Gcc-patches
The 11/03/2021 00:24, Dan Li wrote:
> On 11/2/21 9:04 PM, Szabolcs Nagy wrote:
> > The 11/02/2021 00:06, Dan Li via Gcc-patches wrote:
> > > Shadow Call Stack can be used to protect the return address of a
> > > function at runtime, and clang already supports this feature[1].
> > > 
> > > To enable SCS in user mode, in addition to compiler, other support
> > > is also required (as described in [2]). This patch only adds basic
> > > support for SCS from the compiler side, and provides convenience
> > > for users to enable SCS.
> > > 
> > > For linux kernel, only the support of the compiler is required.
> > > 
> > > [1] https://clang.llvm.org/docs/ShadowCallStack.html
> > > [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102768
> > 
> > i'm not a gcc maintainer, but i prefer such feature
> > to be in upstream gcc instead of in a plugin.
> > 
> > it will require update to the documentation:
> > 
> > which should mention that it depends on -ffixed-x18
> > (probably that should be enforced too) which is an
> > important abi issue: functions following the normal
> > pcs can clobber x18 and break scs.
> > 
> Thanks Szabolcs, I will update the documentation in next version.
> 
> It sounds reasonable to enforced -ffixed-x18 with scs, but I see
> that clang doesn’t do that. Maybe it is better to be consistent
> with clang here?

i mean gcc can issue a diagnostic if -ffixed-x18 is not passed.
(it seems clang rejects scs too without -ffixed-x18)

> > and that there is no unwinder support.
> > 
> Ok, let me try to add a support for this.

i assume exception handling info has to change for scs to
work (to pop the shadow stack when transferring control),
so either scs must require -fno-exceptions or the eh info
changes must be implemented.

i think the kernel does not require exceptions and does
not depend on the unwinder runtime in libgcc, so this
is optional for the linux kernel use-case.


Re: [PATCH] [RFC][PR102768] aarch64: Add compiler support for Shadow Call Stack

2021-11-02 Thread Szabolcs Nagy via Gcc-patches
The 11/02/2021 00:06, Dan Li via Gcc-patches wrote:
> Shadow Call Stack can be used to protect the return address of a
> function at runtime, and clang already supports this feature[1].
> 
> To enable SCS in user mode, in addition to compiler, other support
> is also required (as described in [2]). This patch only adds basic
> support for SCS from the compiler side, and provides convenience
> for users to enable SCS.
> 
> For linux kernel, only the support of the compiler is required.
> 
> [1] https://clang.llvm.org/docs/ShadowCallStack.html
> [2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102768

i'm not a gcc maintainer, but i prefer such feature
to be in upstream gcc instead of in a plugin.

it will require update to the documentation:

which should mention that it depends on -ffixed-x18
(probably that should be enforced too) which is an
important abi issue: functions following the normal
pcs can clobber x18 and break scs.

and that there is no unwinder support.

the abi issue means it is unlikely to be useful in
linux user space (even if libc and unwinder support
is implemented), but it can be still useful in
freestanding code such as the linux kernel.

thanks.

> 
> gcc/c-family/ChangeLog:
> 
>   * c-attribs.c (handle_no_sanitize_shadow_call_stack_attribute):
> 
> gcc/ChangeLog:
> 
>   * config/aarch64/aarch64-protos.h (aarch64_shadow_call_stack_enabled):
>   * config/aarch64/aarch64.c (aarch64_shadow_call_stack_enabled):
>   (aarch64_expand_prologue):
>   (aarch64_expand_epilogue):
>   * config/aarch64/aarch64.h (TARGET_SUPPORT_SHADOW_CALL_STACK):
>   * config/aarch64/aarch64.md (scs_push):
>   (scs_pop):
>   * defaults.h (TARGET_SUPPORT_SHADOW_CALL_STACK):
>   * flag-types.h (enum sanitize_code):
>   * opts.c (finish_options):
> 
> Signed-off-by: Dan Li 
> ---
>  gcc/c-family/c-attribs.c| 21 +
>  gcc/config/aarch64/aarch64-protos.h |  1 +
>  gcc/config/aarch64/aarch64.c| 27 +++
>  gcc/config/aarch64/aarch64.h|  4 
>  gcc/config/aarch64/aarch64.md   | 18 ++
>  gcc/defaults.h  |  4 
>  gcc/flag-types.h|  2 ++
>  gcc/opts.c  |  6 ++
>  8 files changed, 83 insertions(+)
> 
> diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
> index 007b928c54b..9b3a35c06bf 100644
> --- a/gcc/c-family/c-attribs.c
> +++ b/gcc/c-family/c-attribs.c
> @@ -56,6 +56,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
> bool *);
>  static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
>  static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
> int, bool *);
> +static tree handle_no_sanitize_shadow_call_stack_attribute (tree *, tree,
> +   tree, int, bool *);
>  static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
>int, bool *);
>  static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
> @@ -454,6 +456,10 @@ const struct attribute_spec c_common_attribute_table[] =
> handle_no_sanitize_attribute, NULL },
>{ "no_sanitize_address",0, 0, true, false, false, false,
> handle_no_sanitize_address_attribute, NULL },
> +  { "no_sanitize_shadow_call_stack",
> +   0, 0, true, false, false, false,
> +   handle_no_sanitize_shadow_call_stack_attribute,
> +   NULL },
>{ "no_sanitize_thread", 0, 0, true, false, false, false,
> handle_no_sanitize_thread_attribute, NULL },
>{ "no_sanitize_undefined",  0, 0, true, false, false, false,
> @@ -1175,6 +1181,21 @@ handle_no_sanitize_address_attribute (tree *node, tree 
> name, tree, int,
>return NULL_TREE;
>  }
>  
> +/* Handle a "no_sanitize_shadow_call_stack" attribute; arguments as in
> +   struct attribute_spec.handler.  */
> +static tree
> +handle_no_sanitize_shadow_call_stack_attribute (tree *node, tree name,
> +   tree, int, bool *no_add_attrs)
> +{
> +  *no_add_attrs = true;
> +  if (TREE_CODE (*node) != FUNCTION_DECL)
> +warning (OPT_Wattributes, "%qE attribute ignored", name);
> +  else
> +add_no_sanitize_value (*node, SANITIZE_SHADOW_CALL_STACK);
> +
> +  return NULL_TREE;
> +}
> +
>  /* Handle a "no_sanitize_thread" attribute; arguments as in
> struct attribute_spec.handler.  */
>  
> diff --git a/gcc/config/aarch64/aarch64-protos.h 
> b/gcc/config/aarch64/aarch64-protos.h
> index 768e8fae136..150c015df21 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -893,6 +893,7 @@ void aarch64_register_pragmas (void);
>  void aarch64_relayout_simd_types (void);
>  void 

Re: Fix handling of stores in modref_summary::useful_p

2020-10-06 Thread Szabolcs Nagy via Gcc-patches
The 10/05/2020 23:45, Jan Hubicka wrote:
> > The 10/05/2020 17:28, Szabolcs Nagy via Gcc-patches wrote:
> > minimal reproducer:
> > 
> > #include 
> > int main()
> > {
> > int r,t;
> > r = sscanf("01", "%2x", );
> > printf("scanf: %d  %02x\n", r, t);
> > return 0;
> > }
> > 
> > should print
> > 
> > scanf: 1  01
> > 
> > but when glibc is compiled with gcc trunk on aarch64 it prints
> > 
> > scanf: 0  00
> > 
> > i will continute the debugging from here tomorrow.
> 
> There is a report on glibc issue here 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97264
> it turned out to be a latent glibc bug type punning const char * and
> const unsigned char *.
> 
> I wonder if it is same as problem you are seeing?

thanks, that indeed looks very similar, i'll comment on the glibc bug.


Re: Fix handling of stores in modref_summary::useful_p

2020-10-05 Thread Szabolcs Nagy via Gcc-patches
The 10/05/2020 17:28, Szabolcs Nagy via Gcc-patches wrote:
> The 10/05/2020 12:52, Vaseeharan Vinayagamoorthy wrote:
> > Hi,
> > 
> > After this patch, I am noticing that some glibc crypto tests get stuck in 
> > scanf which goes into busy loop.
> > 
> > My build/host/target setup is:
> > Build: aarch64-none-linux-gnu
> > Host: aarch64-none-linux-gnu
> > Target: aarch64-none-linux-gnu
> 
> i can reproduce this on aarch64, i'm looking at it:
> 
> if i compile glibc with gcc trunk after this commit i see
> 
> $ ./testrun.sh crypt/cert < $glibcsrc/crypt/cert.input
>  K:  P:  C:  Encrypt FAIL
>  K:  P:  C:  Encrypt FAIL
>  K:  P:  C:  Encrypt FAIL
>  K:  P:  C:  Encrypt FAIL
>  K:  P:  C:  Encrypt FAIL
>  K:  P:  C:  Encrypt FAIL
> ...
> 
> it just keeps printing this.
> 
> same test binary with glibc code compiled with an
> older gcc works, so something in glibc gets miscompiled.
> 
> i will have to do more digging to figure out what.

minimal reproducer:

#include 
int main()
{
int r,t;
r = sscanf("01", "%2x", );
printf("scanf: %d  %02x\n", r, t);
return 0;
}

should print

scanf: 1  01

but when glibc is compiled with gcc trunk on aarch64 it prints

scanf: 0  00

i will continute the debugging from here tomorrow.


> > On 27/09/2020, 22:46, "Gcc-patches on behalf of Jan Hubicka" 
> >  wrote:
> > 
> > Hi,
> > this patch fixes a pasto in modref_summary::useful_p that made
> > ipa-modref to give up on tracking stores when all load info got lost.
> > 
> > Bootstrapped/regtested x86_64-linux, comitted.
> > 
> > gcc/ChangeLog:
> > 
> > 2020-09-27  Jan Hubicka  
> > 
> > * ipa-modref.c (modref_summary::useful_p): Fix testing of stores.
> > 
> > diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
> > index 728c6c1523d..6225552e41a 100644
> > --- a/gcc/ipa-modref.c
> > +++ b/gcc/ipa-modref.c
> > @@ -135,7 +135,7 @@ modref_summary::useful_p (int ecf_flags)
> >  return true;
> >if (ecf_flags & ECF_PURE)
> >  return false;
> > -  return stores && !loads->every_base;
> > +  return stores && !stores->every_base;
> >  }
> > 
> >  /* Dump A to OUT.  */
> > 


Re: Fix handling of stores in modref_summary::useful_p

2020-10-05 Thread Szabolcs Nagy via Gcc-patches
The 10/05/2020 12:52, Vaseeharan Vinayagamoorthy wrote:
> Hi,
> 
> After this patch, I am noticing that some glibc crypto tests get stuck in 
> scanf which goes into busy loop.
> 
> My build/host/target setup is:
> Build: aarch64-none-linux-gnu
> Host: aarch64-none-linux-gnu
> Target: aarch64-none-linux-gnu

i can reproduce this on aarch64, i'm looking at it:

if i compile glibc with gcc trunk after this commit i see

$ ./testrun.sh crypt/cert < $glibcsrc/crypt/cert.input
 K:  P:  C:  Encrypt FAIL
 K:  P:  C:  Encrypt FAIL
 K:  P:  C:  Encrypt FAIL
 K:  P:  C:  Encrypt FAIL
 K:  P:  C:  Encrypt FAIL
 K:  P:  C:  Encrypt FAIL
...

it just keeps printing this.

same test binary with glibc code compiled with an
older gcc works, so something in glibc gets miscompiled.

i will have to do more digging to figure out what.




> 
> 
> 
> Kind regards
> Vasee
> 
> 
> On 27/09/2020, 22:46, "Gcc-patches on behalf of Jan Hubicka" 
>  wrote:
> 
> Hi,
> this patch fixes a pasto in modref_summary::useful_p that made
> ipa-modref to give up on tracking stores when all load info got lost.
> 
> Bootstrapped/regtested x86_64-linux, comitted.
> 
> gcc/ChangeLog:
> 
> 2020-09-27  Jan Hubicka  
> 
> * ipa-modref.c (modref_summary::useful_p): Fix testing of stores.
> 
> diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
> index 728c6c1523d..6225552e41a 100644
> --- a/gcc/ipa-modref.c
> +++ b/gcc/ipa-modref.c
> @@ -135,7 +135,7 @@ modref_summary::useful_p (int ecf_flags)
>  return true;
>if (ecf_flags & ECF_PURE)
>  return false;
> -  return stores && !loads->every_base;
> +  return stores && !stores->every_base;
>  }
> 
>  /* Dump A to OUT.  */
> 

-- 


Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-10-05 Thread Szabolcs Nagy via Gcc-patches
The 09/23/2020 21:45, Jeff Law wrote:
> On 9/23/20 11:45 AM, Martin Sebor via Gcc-patches wrote:
> > On 9/23/20 9:44 AM, Szabolcs Nagy wrote:
> > > The 09/23/2020 09:22, Szabolcs Nagy wrote:
> > > > The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> > > > > On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > > > > > After this patch, I am seeing this -Warray-parameter error:
> > > > > > 
> > > > > > In file included from ../include/pthread.h:1,
> > > > > >    from ../sysdeps/nptl/thread_db.h:25,
> > > > > >    from ../nptl/descr.h:32,
> > > > > >    from ../sysdeps/aarch64/nptl/tls.h:44,
> > > > > >    from ../include/errno.h:25,
> > > > > >    from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > > > > >    from :1:
> > > > > > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of
> > > > > > type ‘struct __jmp_buf_tag *’ declared as a pointer
> > > > > > [-Werror=array-parameter=]
> > > > > >     734 | extern int __sigsetjmp (struct __jmp_buf_tag
> > > > > > *__env, int __savemask) __THROWNL;
> > > > > >     | ~~^
> > > > > > In file included from ../include/setjmp.h:2,
> > > > > >    from ../nptl/descr.h:24,
> > > > > >    from ../sysdeps/aarch64/nptl/tls.h:44,
> > > > > >    from ../include/errno.h:25,
> > > > > >    from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > > > > >    from
> > > > > > ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > > > > >    from :1:
> > > > > > ../setjmp/setjmp.h:54:46: note: previously declared as
> > > > > > an array ‘struct __jmp_buf_tag[1]’
> > > > > >  54 | extern int __sigsetjmp (struct __jmp_buf_tag
> > > > > > __env[1], int __savemask) __THROWNL;
> > > > > >     | ~^~~~
> > > > > > cc1: all warnings being treated as errors
> > > > > 
> > > > > The warning flags differences between the forms of array parameters
> > > > > in redeclarations of the same function, including pointers vs arrays
> > > > > as in this instance.  It needs to be suppressed in glibc, either by
> > > > > making the function declarations consistent, or by #pragma diagnostic.
> > > > > (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> > > > > been defined so simply using the array form there doesn't work without
> > > > > defining the type first.)
> > > > > 
> > > > > I would expect the warning to be suppressed when using the installed
> > > > > library thanks to -Wno-system-headers.
> > > > 
> > > > why is this a warning? i'm not convinced it
> > > > should be in -Wall.
> > 
> > The main motivation for the warning is to detect unintentional
> > inconsistencies between function redeclarations that make deriving
> > true true intent difficult or impossible  (e.g, T[3] vs T[1], or
> > T[] vs T[1], or equivalently T* vs T[1]).
> > 
> > One goal is to support the convention where a constant array bound
> > in a function array parameter is used in lieu of the [static N]
> > notation (i.e., the minimum number of elements the caller is
> > expected to  make available).  The [static N] notation is little
> > known, used only exceedingly rarely, and isn't available in C++.
> > The array notation is used more often, although by no means common.
> > 
> > The ultimate goal is to motivate users to take advantage of GCC's
> > ability to check ordinary functions for out-of-bounds accesses to
> > array arguments.  The checking is only feasible if all declarations
> > of the same function, including its definition, use a consistent
> > notation to specify the same bound.  Including th

Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Szabolcs Nagy
The 09/23/2020 09:22, Szabolcs Nagy wrote:
> The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> > On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > > After this patch, I am seeing this -Warray-parameter error:
> > > 
> > > In file included from ../include/pthread.h:1,
> > >   from ../sysdeps/nptl/thread_db.h:25,
> > >   from ../nptl/descr.h:32,
> > >   from ../sysdeps/aarch64/nptl/tls.h:44,
> > >   from ../include/errno.h:25,
> > >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > >   from :1:
> > > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
> > > __jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
> > >734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int 
> > > __savemask) __THROWNL;
> > >| ~~^
> > > In file included from ../include/setjmp.h:2,
> > >   from ../nptl/descr.h:24,
> > >   from ../sysdeps/aarch64/nptl/tls.h:44,
> > >   from ../include/errno.h:25,
> > >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> > >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> > >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> > >   from :1:
> > > ../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
> > > __jmp_buf_tag[1]’
> > > 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int 
> > > __savemask) __THROWNL;
> > >| ~^~~~
> > > cc1: all warnings being treated as errors
> > 
> > The warning flags differences between the forms of array parameters
> > in redeclarations of the same function, including pointers vs arrays
> > as in this instance.  It needs to be suppressed in glibc, either by
> > making the function declarations consistent, or by #pragma diagnostic.
> > (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> > been defined so simply using the array form there doesn't work without
> > defining the type first.)
> > 
> > I would expect the warning to be suppressed when using the installed
> > library thanks to -Wno-system-headers.
> 
> why is this a warning? i'm not convinced it
> should be in -Wall.
> 
> this is a warning with false positives that
> have no portable workaround and does not
> really help catching bugs (at least i doubt
> inconsistent array vs pointer declaration
> is causing common problems).
> 
> what gcc should warn about is if there is an
> array style argument declaration and a caller
> passes an array that's provably shorter than
> that.

i take this back: such warning only makes
sense when the static keyword is used in
the array declarator.

i really think this issue should be fixed
in gcc and not in glibc: it's not true that
the argument has array type, the standard
requires the parameter type to be adjusted:

  A declaration of a parameter as "array of type"
  shall be adjusted to "qualified pointer to type"

this warning will just confuse users and
make them believe that the two declaration
styles for pointer arguments are somehow
different.


Re: [PING 2][PATCH 2/5] C front end support to detect out-of-bounds accesses to array parameters

2020-09-23 Thread Szabolcs Nagy
The 09/21/2020 12:45, Martin Sebor via Gcc-patches wrote:
> On 9/21/20 12:20 PM, Vaseeharan Vinayagamoorthy wrote:
> > After this patch, I am seeing this -Warray-parameter error:
> > 
> > In file included from ../include/pthread.h:1,
> >   from ../sysdeps/nptl/thread_db.h:25,
> >   from ../nptl/descr.h:32,
> >   from ../sysdeps/aarch64/nptl/tls.h:44,
> >   from ../include/errno.h:25,
> >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> >   from :1:
> > ../sysdeps/nptl/pthread.h:734:47: error: argument 1 of type ‘struct 
> > __jmp_buf_tag *’ declared as a pointer [-Werror=array-parameter=]
> >734 | extern int __sigsetjmp (struct __jmp_buf_tag *__env, int 
> > __savemask) __THROWNL;
> >| ~~^
> > In file included from ../include/setjmp.h:2,
> >   from ../nptl/descr.h:24,
> >   from ../sysdeps/aarch64/nptl/tls.h:44,
> >   from ../include/errno.h:25,
> >   from ../sysdeps/unix/sysv/linux/sysdep.h:23,
> >   from ../sysdeps/unix/sysv/linux/generic/sysdep.h:22,
> >   from ../sysdeps/unix/sysv/linux/aarch64/sysdep.h:24,
> >   from :1:
> > ../setjmp/setjmp.h:54:46: note: previously declared as an array ‘struct 
> > __jmp_buf_tag[1]’
> > 54 | extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int 
> > __savemask) __THROWNL;
> >| ~^~~~
> > cc1: all warnings being treated as errors
> 
> The warning flags differences between the forms of array parameters
> in redeclarations of the same function, including pointers vs arrays
> as in this instance.  It needs to be suppressed in glibc, either by
> making the function declarations consistent, or by #pragma diagnostic.
> (IIRC, the pointer declaration comes before struct __jmp_buf_tag has
> been defined so simply using the array form there doesn't work without
> defining the type first.)
> 
> I would expect the warning to be suppressed when using the installed
> library thanks to -Wno-system-headers.

why is this a warning? i'm not convinced it
should be in -Wall.

this is a warning with false positives that
have no portable workaround and does not
really help catching bugs (at least i doubt
inconsistent array vs pointer declaration
is causing common problems).

what gcc should warn about is if there is an
array style argument declaration and a caller
passes an array that's provably shorter than
that.

pointer style declaration should be possible
to mix with array style (this is important
for standard headers but any api with multiple
implementations can end up in situations where
both array and pointer style decl will be
present).



Re: [PATCH] configure: Require C++11 for building code generation tools

2020-08-20 Thread Szabolcs Nagy
The 08/20/2020 13:59, Vasee Vinayagamoorthy wrote:
> +# Also require C++11 for building code generation tools.
> +# Do nothing if "${build}" = "${host}", because in this case
> +# CXX_FOR_BUILD="\$(CXX)", and $CXX is already set to the correct value 
> above.
> +if test "${build}" != "${host}"; then
> +  saved_CXX=$CXX
> +  saved_CXXCPP=$CXXCPP
> +  CXX=$CXX_FOR_BUILD
> +  CXXCPP=
> +  AX_CXX_COMPILE_STDCXX(11)
> +  CXX="$CXX -std=c++11"
> +  CXX_FOR_BUILD=$CXX
> +  CXX=$saved_CXX
> +  CXXCPP=$saved_CXXCPP
> +fi

i think AX_CXX_COMPILE_STDCXX(11) should
set CXX correctly (it seems it would set
it to "g++ -std=gnu++11" instead of
"g++ -std=c++11" but either should work)

please look at the top level config.log
i think you should look for

"checking whether g++ supports C++11 features with -std=gnu++11"

and that check should be successful.


[PATCH 2/2] aarch64: add PAC-RET protection to libitm sjlj.S

2020-07-23 Thread Szabolcs Nagy
_ITM_beginTransaction is a 'returns_twice' function that saves x30
on the stack as part of gtm_jmpbuf (that is passed down to
GTM_begin_transaction), but the saved x30 is also used for return.

The return path should be protected so we don't leave an
  ldp x29, x30, [sp]
  ret
gadget in the code, so x30 is signed on function entry. This
exposes the signed address in the gtm_jmpbuf too. The jmpbuf does
not need a signed address since GTM_longjmp uses
  ldp x29, x30, [x1]
  br x30
and with BTI there is a BTI j at the _ITM_beginTransaction call site
where this jump returns. Using PAC does not hurt: the gtm_jmpbuf is
internal to libitm and its layout is only used by sjlj.S so the
signed address does not escape. Saving signed x30 into gtm_jmpbuf
provides a bit of extra protection, but more importantly it allows
adding the PAC-RET support without changing the existing code much.

In theory bti and pac-ret protection can be added unconditionally
since the instructions are in the nop space, in practice they
can cause trouble if some tooling does not understand the gnu
property note (e.g. old binutils) or some unwinder or debugger
does not understand the new dwarf op code used for pac-ret (e.g
old gdb). So the code is written to only support branch-protection
according to the code generation options.

libitm/ChangeLog:

* config/aarch64/sjlj.S: Add conditional pac-ret protection.
---
 libitm/config/aarch64/sjlj.S | 56 ++--
 1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S
index e2093ca1a97..c84e98aecad 100644
--- a/libitm/config/aarch64/sjlj.S
+++ b/libitm/config/aarch64/sjlj.S
@@ -25,6 +25,35 @@
 #include "asmcfi.h"
 
 #define BTI_C  hint34
+#define PACIASPhint25
+#define AUTIASPhint29
+#define PACIBSPhint27
+#define AUTIBSPhint31
+
+#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
+# define cfi_window_save .cfi_window_save
+# define cfi_b_key_frame .cfi_b_key_frame
+#else
+# define cfi_window_save
+# define cfi_b_key_frame
+#endif
+
+#if __ARM_FEATURE_PAC_DEFAULT & 1
+# define CFI_PAC_TOGGLEcfi_window_save
+# define CFI_PAC_KEY
+# define PAC_AND_BTI   PACIASP
+# define AUT   AUTIASP
+#elif __ARM_FEATURE_PAC_DEFAULT & 2
+# define CFI_PAC_TOGGLEcfi_window_save
+# define CFI_PAC_KEY   cfi_b_key_frame
+# define PAC_AND_BTI   PACIBSP
+# define AUT   AUTIBSP
+#else
+# define CFI_PAC_TOGGLE
+# define CFI_PAC_KEY
+# define PAC_AND_BTI   BTI_C
+# define AUT
+#endif
 
.text
.align  2
@@ -33,7 +62,9 @@
 
 _ITM_beginTransaction:
cfi_startproc
-   BTI_C
+   CFI_PAC_KEY
+   PAC_AND_BTI
+   CFI_PAC_TOGGLE
mov x1, sp
stp x29, x30, [sp, -11*16]!
cfi_adjust_cfa_offset(11*16)
@@ -60,6 +91,8 @@ _ITM_beginTransaction:
cfi_adjust_cfa_offset(-11*16)
cfi_restore(x29)
cfi_restore(x30)
+   AUT
+   CFI_PAC_TOGGLE
ret
cfi_endproc
.size   _ITM_beginTransaction, . - _ITM_beginTransaction
@@ -73,6 +106,7 @@ GTM_longjmp:
/* The first parameter becomes the return value (x0).
   The third parameter is ignored for now.  */
cfi_startproc
+   CFI_PAC_KEY
BTI_C
ldp x19, x20, [x1, 1*16]
ldp x21, x22, [x1, 2*16]
@@ -86,7 +120,10 @@ GTM_longjmp:
ldr x3, [x1, 10*16]
ldp x29, x30, [x1]
cfi_def_cfa(x1, 0)
+   CFI_PAC_TOGGLE
mov sp, x3
+   AUT
+   CFI_PAC_TOGGLE
br  x30
cfi_endproc
.size   GTM_longjmp, . - GTM_longjmp
@@ -96,6 +133,19 @@ GTM_longjmp:
 #define FEATURE_1_BTI 1
 #define FEATURE_1_PAC 2
 
+/* Supported features based on the code generation options.  */
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+# define BTI_FLAG FEATURE_1_BTI
+#else
+# define BTI_FLAG 0
+#endif
+
+#if __ARM_FEATURE_PAC_DEFAULT & 3
+# define PAC_FLAG FEATURE_1_PAC
+#else
+# define PAC_FLAG 0
+#endif
+
 /* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
 #define GNU_PROPERTY(type, value)  \
   .section .note.gnu.property, "a";\
@@ -113,7 +163,7 @@ GTM_longjmp:
 .section .note.GNU-stack, "", %progbits
 
 /* Add GNU property note if built with branch protection.  */
-# ifdef __ARM_FEATURE_BTI_DEFAULT
-GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
+# if (BTI_FLAG|PAC_FLAG) != 0
+GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
 # endif
 #endif
-- 
2.17.1



[PATCH 1/2] aarch64: add PAC GNU property note to libgcc lse.S

2020-07-23 Thread Szabolcs Nagy
This note is not used anywhere currently but it is supposed to mark
objects if the return address is protected with PAC on the stack.
Since lse.S only has leaf functions the return address is never
saved on the stack so we can add the note.

The note is only added if pac-ret is enabled because it can cause
problems with old linkers and we don't have checks for that. This
can be changed later to be unconditional, for now it is consistent
with how gcc generates the notes.

libgcc/ChangeLog:

* config/aarch64/lse.S: Add PAC property note.
---
 libgcc/config/aarch64/lse.S | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index 64691c601c1..aa3e3dc4f2d 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -283,6 +283,19 @@ ENDFN  NAME(LDNM)
 #define FEATURE_1_BTI 1
 #define FEATURE_1_PAC 2
 
+/* Supported features based on the code generation options.  */
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+# define BTI_FLAG FEATURE_1_BTI
+#else
+# define BTI_FLAG 0
+#endif
+
+#if __ARM_FEATURE_PAC_DEFAULT & 3
+# define PAC_FLAG FEATURE_1_PAC
+#else
+# define PAC_FLAG 0
+#endif
+
 /* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
 #define GNU_PROPERTY(type, value)  \
   .section .note.gnu.property, "a";\
@@ -300,7 +313,7 @@ ENDFN   NAME(LDNM)
 .section .note.GNU-stack, "", %progbits
 
 /* Add GNU property note if built with branch protection.  */
-# ifdef __ARM_FEATURE_BTI_DEFAULT
-GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
+# if (BTI_FLAG|PAC_FLAG) != 0
+GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
 # endif
 #endif
-- 
2.17.1



Re: [PATCH 4/4] doc: Clarify __builtin_return_address [PR94891]

2020-07-13 Thread Szabolcs Nagy
The 07/13/2020 12:24, Richard Sandiford wrote:
> Szabolcs Nagy  writes:
> > The expected semantics and valid usage of __builtin_return_address is
> > not clear since it exposes implementation internals that are normally
> > not meaningful to portable c code.
> >
> > This documentation change tries to clarify the semantics in case the
> > return address is stored in a mangled form. This affects AArch64 when
> > pointer authentication is used for the return address signing (i.e.
> > -mbranch-protection=pac-ret).
> >
> > gcc/ChangeLog:
> >
> > 2020-06-04  Szabolcs Nagy  
> >
> > * doc/extend.texi: Update the text for  __builtin_return_address.
> 
> LGTM apart from minor nits:
...
> OK for trunk and branches with those changes.

thanks, committed with those changes
and backported to gcc-10 now.

(i will backport to gcc-9 and gcc-8
a bit later.)


[PATCH 6/6] aarch64: Fix BTI support in libitm

2020-07-08 Thread Szabolcs Nagy
sjlj.S did not have the GNU property note markup and the BTI c
instructions that are necessary when it is built with branch
protection.

The notes are only added when libitm is built with branch
protection, because old linkers mishandle the note (merge
them incorrectly or emit warnings), the BTI instructions
are added unconditionally.

libitm/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/sjlj.S: Add BTI marking and related definitions,
and add BTI c to function entries.

---
Note: there is some redundancy: the libgcc fixup patch needed
the same macro definitions, but i did not find a convenient
place from where both libgcc and libitm can include them. Since
this is a common problem i expect a change in the assembler
that will be able to add the note without doing this manually,
until then i think we can live with the code duplication.
---
 libitm/config/aarch64/sjlj.S | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S
index 5b97b973e27..e2093ca1a97 100644
--- a/libitm/config/aarch64/sjlj.S
+++ b/libitm/config/aarch64/sjlj.S
@@ -24,6 +24,8 @@
 
 #include "asmcfi.h"
 
+#define BTI_C  hint34
+
.text
.align  2
.global _ITM_beginTransaction
@@ -31,6 +33,7 @@
 
 _ITM_beginTransaction:
cfi_startproc
+   BTI_C
mov x1, sp
stp x29, x30, [sp, -11*16]!
cfi_adjust_cfa_offset(11*16)
@@ -70,6 +73,7 @@ GTM_longjmp:
/* The first parameter becomes the return value (x0).
   The third parameter is ignored for now.  */
cfi_startproc
+   BTI_C
ldp x19, x20, [x1, 1*16]
ldp x21, x22, [x1, 2*16]
ldp x23, x24, [x1, 3*16]
@@ -87,6 +91,29 @@ GTM_longjmp:
cfi_endproc
.size   GTM_longjmp, . - GTM_longjmp
 
+/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
+#define FEATURE_1_AND 0xc000
+#define FEATURE_1_BTI 1
+#define FEATURE_1_PAC 2
+
+/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
+#define GNU_PROPERTY(type, value)  \
+  .section .note.gnu.property, "a";\
+  .p2align 3;  \
+  .word 4; \
+  .word 16;\
+  .word 5; \
+  .asciz "GNU";\
+  .word type;  \
+  .word 4; \
+  .word value; \
+  .word 0;
+
 #if defined(__linux__) || defined(__FreeBSD__)
 .section .note.GNU-stack, "", %progbits
+
+/* Add GNU property note if built with branch protection.  */
+# ifdef __ARM_FEATURE_BTI_DEFAULT
+GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
+# endif
 #endif
-- 
2.17.1



[PATCH 4/6] aarch64: Fix noexecstack note in libgcc

2020-07-08 Thread Szabolcs Nagy
lse.S did not have GNU stack note, this may cause missing
PT_GNU_STACK in binaries on Linux and FreeBSD.

libgcc/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/lse.S: Add stack note.
---
 libgcc/config/aarch64/lse.S | 4 
 1 file changed, 4 insertions(+)

diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index f3ccf5cf543..9e2acae806b 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -274,3 +274,7 @@ STARTFN NAME(LDNM)
 
 ENDFN  NAME(LDNM)
 #endif
+
+#if defined(__linux__) || defined(__FreeBSD__)
+.section .note.GNU-stack, "", %progbits
+#endif
-- 
2.17.1



[PATCH 3/6] aarch64: Fix noexecstack note in libitm

2020-07-08 Thread Szabolcs Nagy
sjlj.S only had the note on Linux, but it is supposed
to have it on FreeBSD too.

libitm/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/sjlj.S: Add stack note if __FreeBSD__ is defined.

---
Note: this is a minor change to make the asm consistent with
gcc code generation (which emits the note on freebsd too).
the linker defaults to noexecstack on aarch64 so this should
not matter much in practice.
---
 libitm/config/aarch64/sjlj.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S
index 27626c1f378..5b97b973e27 100644
--- a/libitm/config/aarch64/sjlj.S
+++ b/libitm/config/aarch64/sjlj.S
@@ -87,6 +87,6 @@ GTM_longjmp:
cfi_endproc
.size   GTM_longjmp, . - GTM_longjmp
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
 .section .note.GNU-stack, "", %progbits
 #endif
-- 
2.17.1



[PATCH 5/6] aarch64: Fix BTI support in libgcc

2020-07-08 Thread Szabolcs Nagy
lse.S did not have the GNU property note markup and the BTI c
instructions that are necessary when it is built with branch
protection.

The notes are only added when libgcc is built with branch
protection, because old linkers mishandle the note (merge
them incorrectly or emit warnings), the BTI instructions
are added unconditionally.

Note: BTI c is only necessary at function entry if the function
may be called indirectly, currently lse functions are not called
indirectly, but BTI is added for ABI reasons e.g. to allow
linkers later to emit stub code with indirect jump.

libgcc/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/lse.S: Add BTI marking and related definitions,
and add BTI c to function entries.
---
 libgcc/config/aarch64/lse.S | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index 9e2acae806b..64691c601c1 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -136,6 +136,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #define tmp1   17
 #define tmp2   15
 
+#define BTI_C  hint34
+
 /* Start and end a function.  */
 .macro STARTFN name
.text
@@ -145,6 +147,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
.type   \name, %function
.cfi_startproc
 \name:
+   BTI_C
 .endm
 
 .macro ENDFN name
@@ -275,6 +278,29 @@ STARTFNNAME(LDNM)
 ENDFN  NAME(LDNM)
 #endif
 
+/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
+#define FEATURE_1_AND 0xc000
+#define FEATURE_1_BTI 1
+#define FEATURE_1_PAC 2
+
+/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
+#define GNU_PROPERTY(type, value)  \
+  .section .note.gnu.property, "a";\
+  .p2align 3;  \
+  .word 4; \
+  .word 16;\
+  .word 5; \
+  .asciz "GNU";\
+  .word type;  \
+  .word 4; \
+  .word value; \
+  .word 0;
+
 #if defined(__linux__) || defined(__FreeBSD__)
 .section .note.GNU-stack, "", %progbits
+
+/* Add GNU property note if built with branch protection.  */
+# ifdef __ARM_FEATURE_BTI_DEFAULT
+GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
+# endif
 #endif
-- 
2.17.1



[PATCH 1/6] aarch64: Add missing ACLE support for BTI

2020-07-08 Thread Szabolcs Nagy
Define the __ARM_FEATURE_BTI_DEFAULT feature test
macro when BTI branch protection is enabled.

gcc/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Add
__ARM_FEATURE_BTI_DEFAULT support.
---
 gcc/config/aarch64/aarch64-c.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index e1c1cd415dc..1882288af8d 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -178,6 +178,9 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   aarch64_def_or_undef (TARGET_RNG, "__ARM_FEATURE_RNG", pfile);
   aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile);
 
+  aarch64_def_or_undef (aarch64_bti_enabled (),
+   "__ARM_FEATURE_BTI_DEFAULT", pfile);
+
   aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile);
   aarch64_def_or_undef (TARGET_BF16_SIMD,
"__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile);
-- 
2.17.1



[PATCH 2/6] aarch64: Add missing ACLE support for PAC-RET

2020-07-08 Thread Szabolcs Nagy
Define the __ARM_FEATURE_PAC_DEFAULT feature test
macro when PAC-RET branch protection is enabled.

gcc/ChangeLog:

2020-07-08  Szabolcs Nagy  

* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Add
__ARM_FEATURE_PAC_DEFAULT support.

---
Note: i expect to push this patch after the pac-ret
__builtin_return_address and unwinder patches are
resolved so we only advertise pac-ret support in a
fixed gcc which makes it possible to configure test
for __builtin_return_address behaviour.
---
 gcc/config/aarch64/aarch64-c.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 1882288af8d..1a1f4ecef04 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -181,6 +181,19 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   aarch64_def_or_undef (aarch64_bti_enabled (),
"__ARM_FEATURE_BTI_DEFAULT", pfile);
 
+  cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
+  if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+{
+  int v = 0;
+  if (aarch64_ra_sign_key == AARCH64_KEY_A)
+   v |= 1;
+  if (aarch64_ra_sign_key == AARCH64_KEY_B)
+   v |= 2;
+  if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL)
+   v |= 4;
+  builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v);
+}
+
   aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile);
   aarch64_def_or_undef (TARGET_BF16_SIMD,
"__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile);
-- 
2.17.1



[PATCH 0/6] aarch64: Fix target libraries for BTI [PR96001]

2020-07-08 Thread Szabolcs Nagy
Some asm files in target libraries were not branch protected
and gcc missed preprocessor macros when it is generating
branch protection code (which is needed to fix the asm files).

Szabolcs Nagy (6):
  aarch64: Add missing ACLE support for BTI
  aarch64: Add missing ACLE support for PAC-RET
  aarch64: Fix noexecstack note in libitm
  aarch64: Fix noexecstack note in libgcc
  aarch64: Fix BTI support in libgcc
  aarch64: Fix BTI support in libitm

 gcc/config/aarch64/aarch64-c.c | 16 
 libgcc/config/aarch64/lse.S| 30 ++
 libitm/config/aarch64/sjlj.S   | 29 -
 3 files changed, 74 insertions(+), 1 deletion(-)

-- 
2.17.1



Re: [PATCH 2/4] aarch64: fix __builtin_eh_return with pac-ret [PR94891]

2020-07-08 Thread Szabolcs Nagy
The 07/08/2020 13:24, Kyrylo Tkachov wrote:
> Hi Szabolcs,
> > The 06/05/2020 17:51, Szabolcs Nagy wrote:
> > > --- a/gcc/config/aarch64/aarch64.c
> > > +++ b/gcc/config/aarch64/aarch64.c
> > > @@ -6954,6 +6954,10 @@ aarch64_return_address_signing_enabled (void)
> > >/* This function should only be called after frame laid out.   */
> > >gcc_assert (cfun->machine->frame.laid_out);
> > >
> > > +  /* TODO: Big hammer handling of __builtin_eh_return.  */
> 
> ... I don't think this comment is very useful. Please make it a bit more 
> descriptive. If you want to leave the TODO here, please give a more concrete 
> action plan.

see attached patch with more detailed comment and commit message.

>From e0f4b9b94be1b59c3141abc136ea387bb43fcdce Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy 
Date: Thu, 4 Jun 2020 13:42:16 +0100
Subject: [PATCH v2] aarch64: fix __builtin_eh_return with pac-ret [PR94891]

The handler argument must not be signed since that may come from
outside the current module and exposing signed addresses is a pointer
ABI break. (The signed address also may not be representable as void *
which is why pac-ret is currently broken on ilp32.)

There is no point protecting the eh return path with pointer auth
since arbitrary target can be reached with the instruction sequence
in the caller function anyway, however this is a big hammer solution
that turns off pac-ret for the caller completely not just on the eh
return path. A proper fix would change eh return to use an indirect
branch instead of ret (and ensure BTI j landing pads are in place),
this is not attempted so the patch remains small and backportable.

2020-07-08  Szabolcs Nagy  

gcc/ChangeLog:

	PR target/94891
	* config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
	Disable return address signing if __builtin_eh_return is used.

gcc/testsuite/ChangeLog:

	PR target/94891
	* gcc.target/aarch64/return_address_sign_1.c: Update test.
	* gcc.target/aarch64/return_address_sign_b_1.c: Likewise.
---
 gcc/config/aarch64/aarch64.c  | 11 +++
 .../gcc.target/aarch64/return_address_sign_1.c|  8 
 .../gcc.target/aarch64/return_address_sign_b_1.c  |  8 
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 5865d1d7b78..3ad96e07b7b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -6957,6 +6957,17 @@ aarch64_return_address_signing_enabled (void)
   /* This function should only be called after frame laid out.   */
   gcc_assert (cfun->machine->frame.laid_out);
 
+  /* Turn return address signing off in any function that uses
+ __builtin_eh_return.  The address passed to __builtin_eh_return
+ is not signed so either it has to be signed (with original sp)
+ or the code path that uses it has to avoid authenticating it.
+ Currently eh return introduces a return to anywhere gadget, no
+ matter what we do here since it uses ret with user provided
+ address. An ideal fix for that is to use indirect branch which
+ can be protected with BTI j (to some extent).  */
+  if (crtl->calls_eh_return)
+return false;
+
   /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
  if its LR is pushed onto stack.  */
   return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
index 0140bee194f..232ba67ade0 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_1.c
@@ -41,12 +41,12 @@ func3 (int a, int b, int c)
 void __attribute__ ((target ("arch=armv8.3-a")))
 func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
 {
-  /* paciasp */
+  /* no paciasp */
   *ptr = imm1 + foo (imm1) + imm2;
   __builtin_eh_return (offset, handler);
-  /* autiasp */
+  /* no autiasp */
   return;
 }
 
-/* { dg-final { scan-assembler-times "autiasp" 4 } } */
-/* { dg-final { scan-assembler-times "paciasp" 4 } } */
+/* { dg-final { scan-assembler-times "autiasp" 3 } } */
+/* { dg-final { scan-assembler-times "paciasp" 3 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
index 32d788ddf3f..43e32ab6cb7 100644
--- a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
@@ -41,12 +41,12 @@ func3 (int a, int b, int c)
 void __attribute__ ((target ("arch=armv8.3-a")))
 func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
 {
-  /* pacibsp */
+  /* no pacibsp */
   *ptr = imm1 + foo (imm1) + imm2;
   __builtin_eh_return (offset, hand

Re: [PATCH 3/4] libgcc: fix the handling of return address mangling [PR94891]

2020-06-26 Thread Szabolcs Nagy
The 06/05/2020 17:51, Szabolcs Nagy wrote:
> Mangling, currently only used on AArch64 for return address signing,
> is an internal representation that should not be exposed via
> 
>   __builtin_return_address return value,
>   __builtin_eh_return handler argument,
>   _Unwind_DebugHook handler argument.
> 
> Note that a mangled address might not even fit into a void *, e.g.
> with AArch64 ilp32 ABI the return address is stored as 64bit, so
> the mangled return address cannot be accessed via _Unwind_GetPtr.
> 
> This patch changes the unwinder hooks as follows:
> 
> MD_POST_EXTRACT_ROOT_ADDR is removed: root address comes from
> __builtin_return_address which is not mangled.
> 
> MD_POST_EXTRACT_FRAME_ADDR is renamed to MD_DEMANGLE_RETURN_ADDR,
> it now operates on _Unwind_Word instead of void *, so the hook
> should work when return address signing is enabled on AArch64 ilp32.
> (But for that __builtin_aarch64_autia1716 should be fixed to operate
> on 64bit input instead of a void *.)
> 
> MD_POST_FROB_EH_HANDLER_ADDR is removed: it is the responsibility of
> __builtin_eh_return to do the mangling if necessary.
> 
> libgcc/ChangeLog:
> 
> 2020-06-04  Szabolcs Nagy  
> 
>   * config/aarch64/aarch64-unwind.h (MD_POST_EXTRACT_ROOT_ADDR): Remove.
>   (MD_POST_FROB_EH_HANDLER_ADDR): Remove.
>   (MD_POST_EXTRACT_FRAME_ADDR): Rename to ...
>   (MD_DEMANGLE_RETURN_ADDR): This.
>   (aarch64_post_extract_frame_addr): Rename to ...
>   (aarch64_demangle_return_addr): This.
>   (aarch64_post_frob_eh_handler_addr): Remove.
>   * unwind-dw2.c (uw_update_context): Demangle return address.
>   (uw_frob_return_addr): Remove.

ping. (adding Ian on cc)

tested without regressions on aarch64 with pac-ret.

> ---
>  libgcc/config/aarch64/aarch64-unwind.h | 34 --
>  libgcc/unwind-dw2.c| 34 ++
>  2 files changed, 13 insertions(+), 55 deletions(-)
> 
> diff --git a/libgcc/config/aarch64/aarch64-unwind.h 
> b/libgcc/config/aarch64/aarch64-unwind.h
> index ed84a96db41..b1d732e0b2d 100644
> --- a/libgcc/config/aarch64/aarch64-unwind.h
> +++ b/libgcc/config/aarch64/aarch64-unwind.h
> @@ -27,11 +27,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
> If not, see
>  
>  #define DWARF_REGNUM_AARCH64_RA_STATE 34
>  
> -#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
> -#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
> -  aarch64_post_extract_frame_addr (context, fs, addr)
> -#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
> -  aarch64_post_frob_eh_handler_addr (current, target, addr)
> +#define MD_DEMANGLE_RETURN_ADDR(context, fs, addr) \
> +  aarch64_demangle_return_addr (context, fs, addr)
>  #define MD_FROB_UPDATE_CONTEXT(context, fs) \
>aarch64_frob_update_context (context, fs)
>  
> @@ -57,9 +54,10 @@ aarch64_cie_signed_with_b_key (struct _Unwind_Context 
> *context)
> using CFA of current frame.  */
>  
>  static inline void *
> -aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
> -  _Unwind_FrameState *fs, void *addr)
> +aarch64_demangle_return_addr (struct _Unwind_Context *context,
> +   _Unwind_FrameState *fs, _Unwind_Word addr_word)
>  {
> +  void *addr = (void *)addr_word;
>if (context->flags & RA_SIGNED_BIT)
>  {
>_Unwind_Word salt = (_Unwind_Word) context->cfa;
> @@ -71,28 +69,6 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context 
> *context,
>  return addr;
>  }
>  
> -/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
> -   installing it into current context CURRENT.  TARGET is currently not used.
> -   We need to sign exception handler's address if CURRENT itself is signed.  
> */
> -
> -static inline void *
> -aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
> -struct _Unwind_Context *target
> -ATTRIBUTE_UNUSED,
> -void *handler_addr)
> -{
> -  if (current->flags & RA_SIGNED_BIT)
> -{
> -  if (aarch64_cie_signed_with_b_key (current))
> - return __builtin_aarch64_pacib1716 (handler_addr,
> - (_Unwind_Word) current->cfa);
> -  return __builtin_aarch64_pacia1716 (handler_addr,
> - (_Unwind_Word) current->cfa);
> -}
> -  else
> -return handler_addr;
> -}
> -
>  /* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
> CONTEXT as return address signed if bi

Re: [PATCH 2/4] aarch64: fix __builtin_eh_return with pac-ret [PR94891]

2020-06-26 Thread Szabolcs Nagy
The 06/05/2020 17:51, Szabolcs Nagy wrote:
> The handler argument must not be signed since that may come from
> outside the current module and exposing signed addresses is a pointer
> ABI break. (The signed address also may not be representable as void *
> which is why pac-ret is currently broken on ilp32.)
> 
> There is no point protecting the eh return path with pointer auth
> since arbitrary target can be reached with the instruction sequence
> in the caller function anyway, however this is a big hammer solution
> that turns off pac-ret for the caller completely not just on the eh
> return path.
> 
> 2020-06-04  Szabolcs Nagy  
> 
>   * config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
>   Disable return address signing if __builtin_eh_return is used.

ping.

this fixes a correctness bug in pac-ret, tested
on aarch64, with only the following regressions:

FAIL: gcc.target/aarch64/return_address_sign_1.c scan-assembler-times autiasp 4
FAIL: gcc.target/aarch64/return_address_sign_1.c scan-assembler-times paciasp 4
FAIL: gcc.target/aarch64/return_address_sign_b_1.c scan-assembler-times autibsp 
4
FAIL: gcc.target/aarch64/return_address_sign_b_1.c scan-assembler-times pacibsp 
4

which can be fixed by

-/* { dg-final { scan-assembler-times "autiasp" 4 } } */
-/* { dg-final { scan-assembler-times "paciasp" 4 } } */
+/* { dg-final { scan-assembler-times "autiasp" 3 } } */
+/* { dg-final { scan-assembler-times "paciasp" 3 } } */

since __builtin_eh_return path no longer uses pac/aut.

> ---
>  gcc/config/aarch64/aarch64.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 6a2f85c4af7..d9557f7c0a2 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -6954,6 +6954,10 @@ aarch64_return_address_signing_enabled (void)
>/* This function should only be called after frame laid out.   */
>gcc_assert (cfun->machine->frame.laid_out);
>  
> +  /* TODO: Big hammer handling of __builtin_eh_return.  */
> +  if (crtl->calls_eh_return)
> +return false;
> +
>/* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf 
> function
>   if its LR is pushed onto stack.  */
>return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
> -- 
> 2.17.1
> 

-- 


Re: [PATCH 1/4] aarch64: fix return address access with pac [PR94891][PR94791]

2020-06-26 Thread Szabolcs Nagy
The 06/05/2020 17:51, Szabolcs Nagy wrote:
> This is a big hammer fix for __builtin_return_address (PR target/94891)
> returning signed addresses (sometimes, depending on wether lr happens
> to be signed or not at the time of call which depends on optimizations),
> and similarly -pg may pass signed return address to _mcount
> (PR target/94791).
> 
> At the time of return address expansion we don't know if it's signed or
> not so it is done unconditionally.
> 
> I wonder if allocate_initial_value for the lr reg may solve this better
> such that get_hard_reg_initial_val just gives the right (unsigned) value?
> 
> 2020-06-04  Szabolcs Nagy  
> 
>   * config/aarch64/aarch64-protos.h (aarch64_return_addr_rtx): Declare.
>   * config/aarch64/aarch64.c (aarch64_return_addr_rtx): New.
>   (aarch64_return_addr): Use aarch64_return_addr_rtx.
>   * config/aarch64/aarch64.h (PROFILE_HOOK): Likewise.

ping.

(this fixes a correctness bug in pac-ret, tested with no regressions).

> ---
>  gcc/config/aarch64/aarch64-protos.h |  1 +
>  gcc/config/aarch64/aarch64.c| 20 +++-
>  gcc/config/aarch64/aarch64.h|  2 +-
>  3 files changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/config/aarch64/aarch64-protos.h 
> b/gcc/config/aarch64/aarch64-protos.h
> index 9e43adb7db0..723d9ba6ac6 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -578,6 +578,7 @@ int aarch64_vec_fpconst_pow_of_2 (rtx);
>  rtx aarch64_eh_return_handler_rtx (void);
>  rtx aarch64_mask_from_zextract_ops (rtx, rtx);
>  const char *aarch64_output_move_struct (rtx *operands);
> +rtx aarch64_return_addr_rtx (void);
>  rtx aarch64_return_addr (int, rtx);
>  rtx aarch64_simd_gen_const_vector_dup (machine_mode, HOST_WIDE_INT);
>  bool aarch64_simd_mem_operand_p (rtx);
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 6352d4ff78a..6a2f85c4af7 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -10819,6 +10819,24 @@ aarch64_initial_elimination_offset (unsigned from, 
> unsigned to)
>return cfun->machine->frame.frame_size;
>  }
>  
> +
> +/* Get return address without mangling.  */
> +
> +rtx
> +aarch64_return_addr_rtx (void)
> +{
> +  rtx val = get_hard_reg_initial_val (Pmode, LR_REGNUM);
> +  /* Note: aarch64_return_address_signing_enabled only
> + works after cfun->machine->frame.laid_out is set,
> + so here we don't know if the return address will
> + be signed or not.  */
> +  rtx lr = gen_rtx_REG (Pmode, LR_REGNUM);
> +  emit_move_insn (lr, val);
> +  emit_insn (GEN_FCN (CODE_FOR_xpaclri) ());
> +  return lr;
> +}
> +
> +
>  /* Implement RETURN_ADDR_RTX.  We do not support moving back to a
> previous frame.  */
>  
> @@ -10827,7 +10845,7 @@ aarch64_return_addr (int count, rtx frame 
> ATTRIBUTE_UNUSED)
>  {
>if (count != 0)
>  return const0_rtx;
> -  return get_hard_reg_initial_val (Pmode, LR_REGNUM);
> +  return aarch64_return_addr_rtx ();
>  }
>  
>  
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index 2be52fd4d73..f11941bbc86 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -1112,7 +1112,7 @@ typedef struct
>  #define PROFILE_HOOK(LABEL)  \
>{  \
>  rtx fun, lr; \
> -lr = get_hard_reg_initial_val (Pmode, LR_REGNUM);
> \
> +lr = aarch64_return_addr_rtx (); \
>  fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME);   \
>  emit_library_call (fun, LCT_NORMAL, VOIDmode, lr, Pmode);
> \
>}
> -- 
> 2.17.1
> 

-- 


Re: [PATCH 3/4] libgcc: fix the handling of return address mangling [PR94891]

2020-06-08 Thread Szabolcs Nagy
The 06/08/2020 09:12, Luis Machado wrote:
> Hi Szabolcs,
> 
> Just to confirm, this is a "unwinder debugger hook ABI" change only in the
> sense that the generated DWARF will be changed, right? So no further action
> from DWARF consumers will be needed. Is that understanding correct?

the _Unwind_DebugHook can currently be called
with a handler argument that's signed (see below),
i don't know how gdb uses this api (e.g. if it
uses DWARF info to check if the argument is signed),
but i plan to change all apis not to pass signed
pointers around since they can cause ABI issues.
(the debugger is special in that it has to know about
pointer auth anyway so it's not critical to change
this api, but i think it's better to do for consistency)

> On 6/5/20 1:51 PM, Szabolcs Nagy wrote:
> > Mangling, currently only used on AArch64 for return address signing,
> > is an internal representation that should not be exposed via
> > 
> >__builtin_return_address return value,
> >__builtin_eh_return handler argument,
> >_Unwind_DebugHook handler argument.
...
> > -static inline void *
> > -uw_frob_return_addr (struct _Unwind_Context *current
> > -__attribute__ ((__unused__)),
> > -struct _Unwind_Context *target)
> > -{
> > -  void *ret_addr = __builtin_frob_return_addr (target->ra);
> > -#ifdef MD_POST_FROB_EH_HANDLER_ADDR
> > -  ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
> > -#endif
> > -  return ret_addr;
> > -}
> > -
> >   /* Install TARGET into CURRENT so that we can return to it.  This is a
> >  macro because __builtin_eh_return must be invoked in the context of
> >  our caller.  FRAMES is a number of frames to be unwind.
> > @@ -1667,7 +1649,7 @@ uw_frob_return_addr (struct _Unwind_Context *current
> > do  
> > \
> >   { 
> > \
> > long offset = uw_install_context_1 ((CURRENT), (TARGET));   
> > \
> > -  void *handler = uw_frob_return_addr ((CURRENT), (TARGET));   \
> > +  void *handler = __builtin_frob_return_addr ((TARGET)->ra);   \
> > _Unwind_DebugHook ((TARGET)->cfa, handler); \
> > _Unwind_Frames_Extra (FRAMES);  
> > \
> > __builtin_eh_return (offset, handler);  
> > \

handler is no longer signed after my patch.
(if signing is necessary then __builtin_eh_return
should deal with that.)


[PATCH 1/4] aarch64: fix return address access with pac [PR94891][PR94791]

2020-06-05 Thread Szabolcs Nagy
This is a big hammer fix for __builtin_return_address (PR target/94891)
returning signed addresses (sometimes, depending on wether lr happens
to be signed or not at the time of call which depends on optimizations),
and similarly -pg may pass signed return address to _mcount
(PR target/94791).

At the time of return address expansion we don't know if it's signed or
not so it is done unconditionally.

I wonder if allocate_initial_value for the lr reg may solve this better
such that get_hard_reg_initial_val just gives the right (unsigned) value?

2020-06-04  Szabolcs Nagy  

* config/aarch64/aarch64-protos.h (aarch64_return_addr_rtx): Declare.
* config/aarch64/aarch64.c (aarch64_return_addr_rtx): New.
(aarch64_return_addr): Use aarch64_return_addr_rtx.
* config/aarch64/aarch64.h (PROFILE_HOOK): Likewise.
---
 gcc/config/aarch64/aarch64-protos.h |  1 +
 gcc/config/aarch64/aarch64.c| 20 +++-
 gcc/config/aarch64/aarch64.h|  2 +-
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 9e43adb7db0..723d9ba6ac6 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -578,6 +578,7 @@ int aarch64_vec_fpconst_pow_of_2 (rtx);
 rtx aarch64_eh_return_handler_rtx (void);
 rtx aarch64_mask_from_zextract_ops (rtx, rtx);
 const char *aarch64_output_move_struct (rtx *operands);
+rtx aarch64_return_addr_rtx (void);
 rtx aarch64_return_addr (int, rtx);
 rtx aarch64_simd_gen_const_vector_dup (machine_mode, HOST_WIDE_INT);
 bool aarch64_simd_mem_operand_p (rtx);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6352d4ff78a..6a2f85c4af7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10819,6 +10819,24 @@ aarch64_initial_elimination_offset (unsigned from, 
unsigned to)
   return cfun->machine->frame.frame_size;
 }
 
+
+/* Get return address without mangling.  */
+
+rtx
+aarch64_return_addr_rtx (void)
+{
+  rtx val = get_hard_reg_initial_val (Pmode, LR_REGNUM);
+  /* Note: aarch64_return_address_signing_enabled only
+ works after cfun->machine->frame.laid_out is set,
+ so here we don't know if the return address will
+ be signed or not.  */
+  rtx lr = gen_rtx_REG (Pmode, LR_REGNUM);
+  emit_move_insn (lr, val);
+  emit_insn (GEN_FCN (CODE_FOR_xpaclri) ());
+  return lr;
+}
+
+
 /* Implement RETURN_ADDR_RTX.  We do not support moving back to a
previous frame.  */
 
@@ -10827,7 +10845,7 @@ aarch64_return_addr (int count, rtx frame 
ATTRIBUTE_UNUSED)
 {
   if (count != 0)
 return const0_rtx;
-  return get_hard_reg_initial_val (Pmode, LR_REGNUM);
+  return aarch64_return_addr_rtx ();
 }
 
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 2be52fd4d73..f11941bbc86 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -1112,7 +1112,7 @@ typedef struct
 #define PROFILE_HOOK(LABEL)\
   {\
 rtx fun, lr;   \
-lr = get_hard_reg_initial_val (Pmode, LR_REGNUM);  \
+lr = aarch64_return_addr_rtx ();   \
 fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME); \
 emit_library_call (fun, LCT_NORMAL, VOIDmode, lr, Pmode);  \
   }
-- 
2.17.1



[PATCH 3/4] libgcc: fix the handling of return address mangling [PR94891]

2020-06-05 Thread Szabolcs Nagy
Mangling, currently only used on AArch64 for return address signing,
is an internal representation that should not be exposed via

  __builtin_return_address return value,
  __builtin_eh_return handler argument,
  _Unwind_DebugHook handler argument.

Note that a mangled address might not even fit into a void *, e.g.
with AArch64 ilp32 ABI the return address is stored as 64bit, so
the mangled return address cannot be accessed via _Unwind_GetPtr.

This patch changes the unwinder hooks as follows:

MD_POST_EXTRACT_ROOT_ADDR is removed: root address comes from
__builtin_return_address which is not mangled.

MD_POST_EXTRACT_FRAME_ADDR is renamed to MD_DEMANGLE_RETURN_ADDR,
it now operates on _Unwind_Word instead of void *, so the hook
should work when return address signing is enabled on AArch64 ilp32.
(But for that __builtin_aarch64_autia1716 should be fixed to operate
on 64bit input instead of a void *.)

MD_POST_FROB_EH_HANDLER_ADDR is removed: it is the responsibility of
__builtin_eh_return to do the mangling if necessary.

libgcc/ChangeLog:

2020-06-04  Szabolcs Nagy  

* config/aarch64/aarch64-unwind.h (MD_POST_EXTRACT_ROOT_ADDR): Remove.
(MD_POST_FROB_EH_HANDLER_ADDR): Remove.
(MD_POST_EXTRACT_FRAME_ADDR): Rename to ...
(MD_DEMANGLE_RETURN_ADDR): This.
(aarch64_post_extract_frame_addr): Rename to ...
(aarch64_demangle_return_addr): This.
(aarch64_post_frob_eh_handler_addr): Remove.
* unwind-dw2.c (uw_update_context): Demangle return address.
(uw_frob_return_addr): Remove.
---
 libgcc/config/aarch64/aarch64-unwind.h | 34 --
 libgcc/unwind-dw2.c| 34 ++
 2 files changed, 13 insertions(+), 55 deletions(-)

diff --git a/libgcc/config/aarch64/aarch64-unwind.h 
b/libgcc/config/aarch64/aarch64-unwind.h
index ed84a96db41..b1d732e0b2d 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -27,11 +27,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 
 #define DWARF_REGNUM_AARCH64_RA_STATE 34
 
-#define MD_POST_EXTRACT_ROOT_ADDR(addr)  __builtin_aarch64_xpaclri (addr)
-#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
-  aarch64_post_extract_frame_addr (context, fs, addr)
-#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
-  aarch64_post_frob_eh_handler_addr (current, target, addr)
+#define MD_DEMANGLE_RETURN_ADDR(context, fs, addr) \
+  aarch64_demangle_return_addr (context, fs, addr)
 #define MD_FROB_UPDATE_CONTEXT(context, fs) \
   aarch64_frob_update_context (context, fs)
 
@@ -57,9 +54,10 @@ aarch64_cie_signed_with_b_key (struct _Unwind_Context 
*context)
using CFA of current frame.  */
 
 static inline void *
-aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
-_Unwind_FrameState *fs, void *addr)
+aarch64_demangle_return_addr (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs, _Unwind_Word addr_word)
 {
+  void *addr = (void *)addr_word;
   if (context->flags & RA_SIGNED_BIT)
 {
   _Unwind_Word salt = (_Unwind_Word) context->cfa;
@@ -71,28 +69,6 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context 
*context,
 return addr;
 }
 
-/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
-   installing it into current context CURRENT.  TARGET is currently not used.
-   We need to sign exception handler's address if CURRENT itself is signed.  */
-
-static inline void *
-aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
-  struct _Unwind_Context *target
-  ATTRIBUTE_UNUSED,
-  void *handler_addr)
-{
-  if (current->flags & RA_SIGNED_BIT)
-{
-  if (aarch64_cie_signed_with_b_key (current))
-   return __builtin_aarch64_pacib1716 (handler_addr,
-   (_Unwind_Word) current->cfa);
-  return __builtin_aarch64_pacia1716 (handler_addr,
-   (_Unwind_Word) current->cfa);
-}
-  else
-return handler_addr;
-}
-
 /* Do AArch64 private initialization on CONTEXT based on frame info FS.  Mark
CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE 
is
set.  */
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 62d4a3d29a2..fe896565d2e 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -1538,11 +1538,14 @@ uw_update_context (struct _Unwind_Context *context, 
_Unwind_FrameState *fs)
 {
   /* Compute the return address now, since the return address column
 can change from frame to frame.  */
-  context->ra = __builtin_extract_return_addr
-   (_Unwind_GetPtr (context, fs->retaddr_column));
-#ifdef MD_POST_EXTRACT_FRAME_ADDR
-  context->ra = MD_POST_EXTRACT_FRAM

[PATCH 4/4] doc: Clarify __builtin_return_address [PR94891]

2020-06-05 Thread Szabolcs Nagy
The expected semantics and valid usage of __builtin_return_address is
not clear since it exposes implementation internals that are normally
not meaningful to portable c code.

This documentation change tries to clarify the semantics in case the
return address is stored in a mangled form. This affects AArch64 when
pointer authentication is used for the return address signing (i.e.
-mbranch-protection=pac-ret).

gcc/ChangeLog:

2020-06-04  Szabolcs Nagy  

* doc/extend.texi: Update the text for  __builtin_return_address.
---
 gcc/doc/extend.texi | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index cced19d2018..0fd32a22599 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -11151,18 +11151,30 @@ The @var{level} argument must be a constant integer.
 
 On some machines it may be impossible to determine the return address of
 any function other than the current one; in such cases, or when the top
-of the stack has been reached, this function returns @code{0} or a
-random value.  In addition, @code{__builtin_frame_address} may be used
+of the stack has been reached, this function returns an unspecified
+value.  In addition, @code{__builtin_frame_address} may be used
 to determine if the top of the stack has been reached.
 
 Additional post-processing of the returned value may be needed, see
 @code{__builtin_extract_return_addr}.
 
+The stored representation of the return address in memory may be different
+from the address returned by @code{__builtin_return_address}.  For example
+on AArch64 the stored address may be mangled with return address signing.
+
 Calling this function with a nonzero argument can have unpredictable
 effects, including crashing the calling program.  As a result, calls
 that are considered unsafe are diagnosed when the @option{-Wframe-address}
 option is in effect.  Such calls should only be made in debugging
 situations.
+
+On targets where code addresses are representable as @code{void *},
+@smallexample
+void *addr = __builtin_extract_return_addr (__builtin_return_address (0))
+@end smallexample
+gives the code address where the current function would return.  For example
+such address may be used with @code{dladdr} or other interfaces that work
+with code addresses.
 @end deftypefn
 
 @deftypefn {Built-in Function} {void *} __builtin_extract_return_addr (void 
*@var{addr})
-- 
2.17.1



[PATCH 2/4] aarch64: fix __builtin_eh_return with pac-ret [PR94891]

2020-06-05 Thread Szabolcs Nagy
The handler argument must not be signed since that may come from
outside the current module and exposing signed addresses is a pointer
ABI break. (The signed address also may not be representable as void *
which is why pac-ret is currently broken on ilp32.)

There is no point protecting the eh return path with pointer auth
since arbitrary target can be reached with the instruction sequence
in the caller function anyway, however this is a big hammer solution
that turns off pac-ret for the caller completely not just on the eh
return path.

2020-06-04  Szabolcs Nagy  

* config/aarch64/aarch64.c (aarch64_return_address_signing_enabled):
Disable return address signing if __builtin_eh_return is used.
---
 gcc/config/aarch64/aarch64.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6a2f85c4af7..d9557f7c0a2 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -6954,6 +6954,10 @@ aarch64_return_address_signing_enabled (void)
   /* This function should only be called after frame laid out.   */
   gcc_assert (cfun->machine->frame.laid_out);
 
+  /* TODO: Big hammer handling of __builtin_eh_return.  */
+  if (crtl->calls_eh_return)
+return false;
+
   /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf 
function
  if its LR is pushed onto stack.  */
   return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
-- 
2.17.1



[PATCH 0/4] aarch64: avoid exposing signed return addresses [PR94891]

2020-06-05 Thread Szabolcs Nagy
I'm not familiar with gcc internals enough to fix this the
right way, this is a big hammer fix to avoid exposing mangled
pointer representation to user code when pointer signing is
used on aarch64. I.e. this is not an optimal fix just to show
how i would want the ABI to work.

This touches unwinder ABI, unwinder debugger hook ABI (patch 3/4),
__builtin_return_address (1/4), __builtin_eh_return (2/4) usage and
updates the documentation a bit in this area (4/4).

Tests are still running. (I expect some existing target tests will
need to be updated.) The last patch is same as I sent before
(just with changelog this time).

Szabolcs Nagy (4):
  aarch64: fix return address access with pac [PR94891][PR94791]
  aarch64: fix __builtin_eh_return with pac-ret [PR94891]
  libgcc: fix the handling of return address mangling [PR94891]
  doc: Clarify __builtin_return_address [PR94891]

 gcc/config/aarch64/aarch64-protos.h|  1 +
 gcc/config/aarch64/aarch64.c   | 24 +-
 gcc/config/aarch64/aarch64.h   |  2 +-
 gcc/doc/extend.texi| 16 ++--
 libgcc/config/aarch64/aarch64-unwind.h | 34 --
 libgcc/unwind-dw2.c| 34 ++
 6 files changed, 52 insertions(+), 59 deletions(-)

-- 
2.17.1



[PATCH] doc: Clarify __builtin_return_address [PR94891]

2020-05-28 Thread Szabolcs Nagy
The expected semantics and valid usage of __builtin_return_address is
not clear since it exposes implementation internals that are normally
not meaningful to portable c code.

This documentation change tries to clarify the semantics in case the
return address is stored in a mangled form in memory which affects
AArch64 when pointer authentication is used for the return address
(i.e. -mbranch-protection=pac-ret).

---

This is an RFC patch trying to address PR target/94891:

AArch64 __builtin_return_address is currently returning the mangled
address even though user code cannot generally use such address or
tell if it is mangled. (So this patch will require aarch64 backend
changes.)

__builtin_extract_return_addr returns its argument unchanged on
AArch64. This can be changed but the assumption that this operation
can be reversed by __builtin_frob_return_addr makes it unsuitable
for general unmangling (return address signing requires additional
input other than the code address).

On AArch64 the return address mangling is ABI between the compiler
and unwinder / debugger: the unwind / debug info describes when and
how to unmangle the return address. This information may not be
available at runtime (e.g. without unwind tables) so user code cannot
handle a mangled return address in general. Currently the xpaclri
instruction always works and gives an unmangled address, but exposing
the mangled address to users means breaking existing code using
__builtin_return_address and constrains the mangling ABI.

On AArch64 with ILP32 ABI the return address is stored as 64bit in
memory but __builtin_return_address returns 32bit void* so it cannot
be the same as the stored value if the top bits are used for mangling.

It seems only the
  __builtin_extract_return_addr (__builtin_return_address (0))
usage was ever useful in portable code so i think this should be
documented and otherwise leave the semantics to the target to decide.
---
 gcc/doc/extend.texi | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index cced19d2018..0fd32a22599 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -11151,18 +11151,30 @@ The @var{level} argument must be a constant integer.
 
 On some machines it may be impossible to determine the return address of
 any function other than the current one; in such cases, or when the top
-of the stack has been reached, this function returns @code{0} or a
-random value.  In addition, @code{__builtin_frame_address} may be used
+of the stack has been reached, this function returns an unspecified
+value.  In addition, @code{__builtin_frame_address} may be used
 to determine if the top of the stack has been reached.
 
 Additional post-processing of the returned value may be needed, see
 @code{__builtin_extract_return_addr}.
 
+The stored representation of the return address in memory may be different
+from the address returned by @code{__builtin_return_address}.  For example
+on AArch64 the stored address may be mangled with return address signing.
+
 Calling this function with a nonzero argument can have unpredictable
 effects, including crashing the calling program.  As a result, calls
 that are considered unsafe are diagnosed when the @option{-Wframe-address}
 option is in effect.  Such calls should only be made in debugging
 situations.
+
+On targets where code addresses are representable as @code{void *},
+@smallexample
+void *addr = __builtin_extract_return_addr (__builtin_return_address (0))
+@end smallexample
+gives the code address where the current function would return.  For example
+such address may be used with @code{dladdr} or other interfaces that work
+with code addresses.
 @end deftypefn
 
 @deftypefn {Built-in Function} {void *} __builtin_extract_return_addr (void 
*@var{addr})
-- 
2.17.1



Re: Should ARMv8-A generic tuning default to -moutline-atomics

2020-05-14 Thread Szabolcs Nagy
The 04/30/2020 12:26, Kyrylo Tkachov wrote:
> > > From: Gcc  On Behalf Of Andrew Pinski via Gcc
> > > On Wed, Apr 29, 2020 at 6:25 AM Florian Weimer via Gcc 
> > > wrote:
> > > > Distributions are receiving requests to build things with
> > > > -moutline-atomics:
> > > >
> > > >   
> > > >
> > > > Should this be reflected in the GCC upstream defaults for ARMv8-A
> > > > generic tuning?  It does not make much sense to me if every distribution
> > > > has to overide these flags, either in their build system or by patching
> > > > GCC.
> > >
> > > At least we should make it a configure option.
> > > I do want the ability to default it for our (Marvell) toolchain for
> > > Linux (our bare metal toolchain will be defaulting to ARMv8.2-a
> > > anyways).
> > 
> > After some internal discussions, I am open to having it on as a default.
> > Here are two versions. One has it as a tuning setting that CPUs can 
> > override,
> > the other just switches it on by default always unless overridden by -mno-
> > outline-atomics.
> > I slightly prefer the second one as it's cleaner and simpler, but happy to 
> > take
> > either.
> > Any preferences?
> > Thanks,
> > Kyrill
> > 
> > ChangeLogs:
> > 
> > 2020-04-30  Kyrylo Tkachov  
> > 
> > * config/aarch64/aarch64-tuning-flags.def (no_outline_atomics):
> > Declare.
> > * config/aarch64/aarch64.h (TARGET_OUTLINE_ATOMICS): Define.
> > * config/aarch64/aarch64.opt (moutline-atomics): Change to Int
> > variable.
> > 
> > 2020-04-30  Kyrylo Tkachov  
> > 
> > * config/aarch64/aarch64.h (TARGET_OUTLINE_ATOMICS): Define.
> > * config/aarch64/aarch64.opt (moutline-atomics): Change to Int
> > variable.
> > * doc/invoke.texi (moutline-atomics): Document as on by default.
> 
> I've pushed this second variant after bootstrap and testing on 
> aarch64-none-linux-gnu.
> Compiled a simple atomic-using testcase with all relevant combinations of 
> -moutline-atomics and LSE and no-LSE -march options.
> Before the results were (as expected):
>  |-moutline-atomics | -mno-outline-atomics |  option
> 
> LSE  |  inline LSE  | inline LSE| inline LSE
> no-LSE   |  outline | inline LDXR/STXR  | inline LDX/STXR
> 
> 
> with this patch they are:
>  -moutline-atomics  | -mno-outline-atomics |  option>
> 
> LSE  |  inline LSE  | inline LSE   | inline LSE
> no-LSE   |  outline | inline LDXR/STXR | outline

note that this change affects all aarch64 targets not just *-gnu,
(baremetal, freebsd, musl,..), however on non-gnu targets the
initializer with __getauxval is missing so the outlined calls
always use baseline LDXR/STXR.

in a given elf module the libgcc initializer may not run first
(e.g. it runs after ifunc resolvers, other initializers or
signal handler) and different objects may be compiled with
different outline-atomics setting so the outlined calls must
be abi compatible with LDXR/STXR atomics (i.e. outlining is not
an atomics abi change).

so presumably non-gnu targets want to build gcc with outline
atomics turned off by default or want a mechanism to propagate
the lse hwcap to libgcc that works other than in glibc.

I opened
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95128
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95129


Re: [PATCH][AArch64] Use __getauxval instead of getauxval in LSE detection code in libgcc

2020-05-06 Thread Szabolcs Nagy
The 05/06/2020 11:39, Kyrylo Tkachov wrote:
> > -Original Message-
> > From: Florian Weimer 
> > Sent: 06 May 2020 11:28
> >
> > Is __gnu_linux__ defined with musl?  It's not really GNU/Linux, after
> > all.  musl doesn't have __getauxval IIRC, so it would break the build
> > there.
> 
> I don't think it does (at least not with a git grep for it in the musl code).
> GCC doesn't define it for musl targets either. I see it defined for uclinux 
> for arm, not aarch64 though.

__gnu_linux__ is not defined on musl.

it would be better if there was a mechanism to
introduce namespace clean abi symbols across libc
implementations that a compiler can use, instead
of tying it to the glibc version, but currently
there is no such mechanism and only glibc has this
particular symbol, so the patch looks ok to me.


Re: [PATCH][AArch64] Use __getauxval instead of getauxval in LSE detection code in libgcc

2020-05-05 Thread Szabolcs Nagy
The 05/04/2020 20:02, Joseph Myers wrote:
> On Mon, 4 May 2020, Szabolcs Nagy wrote:
> > i think __getauxval needs to be declared where it is used.
> 
> Yes.
> 
> > and libgcc should do a link test in configure becasuse a
> > libc may provide sys/auxv.h but not have __getauxval e.g.
> > musl libc does not export __getauxval, only getauxval.
> 
> libgcc can't do link tests, since it's built before libc.  It can use the 
> glibc version number ($glibc_version_major and $glibc_version_minor) 
> already computed in libgcc/configure.ac, which uses --with-glibc-version 
> or target headers if available and otherwise defaults to 0.0.
> 
> A design principle is that glibc built with libgcc configured without 
> glibc headers but with --with-glibc-version should produce an identical 
> stripped binary to the glibc resulting from a longer alternating sequence 
> of GCC and glibc builds.  So it is not correct for any libgcc 
> functionality that would end up being linked into glibc binaries to depend 
> on glibc headers or libraries being available when libgcc is configured.
> 
> Thus, this libgcc code should not actually be conditional on 
> !inhibit_libc, without a fallback when configured using 
> --with-glibc-version to specify a glibc version with __getauxval, because 
> that would mean the modern process for bootstrapping a cross glibc build 
> produces a glibc binary that quietly differs from one produced by a longer 
> alternating sequence of builds (missing this constructor).

i.e. libgcc needs to replicate definitions from sys/auxv.h?
like

_Bool flag = 0;

#if GLIBC_VERSION_OK
# define AT_HWCAP ...
# define HWCAP_ATOMICS ...
unsigned long __getauxval (unsigned long);

__attribute__ ((constructor)) static void
init ()
{
  flag = (__getauxval(AT_HWCAP) & HWCAP_ATOMICS) != 0;
}
#endif


Re: [PATCH][AArch64] Use __getauxval instead of getauxval in LSE detection code in libgcc

2020-05-04 Thread Szabolcs Nagy
The 05/04/2020 11:34, Kyrylo Tkachov wrote:
> > -Original Message-
> > From: Florian Weimer 
> > Sent: 04 May 2020 11:40
> > To: Kyrylo Tkachov 
> > Cc: gcc-patches@gcc.gnu.org; Joseph Myers 
> > Subject: Re: [PATCH][AArch64] Use __getauxval instead of getauxval in LSE
> > detection code in libgcc
> > 
> > * Kyrylo Tkachov:
> > 
> > > This patch fixes https://gcc.gnu.org/pipermail/gcc-patches/2020-
> > May/545004.html by using __getauxval in the libgcc code.
> > > Bootstrap and testing on aarch64-none-linux-gnu shows no problem.
> > > From what I could gather from my glibc testing the elf/check-localplt test
> > passes.
> > >
> > > Joseph, Florian, does this fix look like what you had in mind?
> > > If I commit it to trunk and the branches will glibc be fine with it?
> > 
> > Doesn't this cause an implicit function declaration warning?
> 
> I don't get such a warning during bootstrap.

i think __getauxval needs to be declared where it is used.

and libgcc should do a link test in configure becasuse a
libc may provide sys/auxv.h but not have __getauxval e.g.
musl libc does not export __getauxval, only getauxval.


[PATCH] aarch64: don't emit bti j after NOTE_INSN_DELETED_LABEL [PR94748]

2020-04-28 Thread Szabolcs Nagy
It was previously discussed that indirect branches cannot go to
NOTE_INSN_DELETED_LABEL so inserting a landing pad is unnecessary.
See https://gcc.gnu.org/pipermail/gcc-patches/2019-May/522625.html

Before the patch a bti j was inserted after the label in

  __attribute__((target("branch-protection=bti")))
  int foo (void)
  {
  label:
return 0;
  }

This is not necessary and weakens the security protection.

gcc/ChangeLog:

2020-04-28  Szabolcs Nagy  

PR target/94748
* config/aarch64/aarch64-bti-insert.c (rest_of_insert_bti): Remove
the check for NOTE_INSN_DELETED_LABEL.

gcc/testsuite/ChangeLog:

2020-04-28  Szabolcs Nagy  

PR target/94748
* gcc.target/aarch64/pr94748.c: New test.
---
 gcc/config/aarch64/aarch64-bti-insert.c|  8 ++--
 gcc/testsuite/gcc.target/aarch64/pr94748.c | 10 ++
 2 files changed, 12 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr94748.c

diff --git a/gcc/config/aarch64/aarch64-bti-insert.c 
b/gcc/config/aarch64/aarch64-bti-insert.c
index aa091c308f6..57663ee23b4 100644
--- a/gcc/config/aarch64/aarch64-bti-insert.c
+++ b/gcc/config/aarch64/aarch64-bti-insert.c
@@ -139,14 +139,10 @@ rest_of_insert_bti (void)
   insn = NEXT_INSN (insn))
{
  /* If a label is marked to be preserved or can be a non-local goto
-target, it must be protected with a BTI J.  The same applies to
-NOTE_INSN_DELETED_LABEL since they are basically labels that might
-be referenced via variables or constant pool.  */
- if ((LABEL_P (insn)
+target, it must be protected with a BTI J.  */
+ if (LABEL_P (insn)
   && (LABEL_PRESERVE_P (insn)
   || bb->flags & BB_NON_LOCAL_GOTO_TARGET))
- || (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
{
  bti_insn = gen_bti_j ();
  emit_insn_after (bti_insn, insn);
diff --git a/gcc/testsuite/gcc.target/aarch64/pr94748.c 
b/gcc/testsuite/gcc.target/aarch64/pr94748.c
new file mode 100644
index 000..2a2850d2fac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr94748.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+__attribute__ ((target("branch-protection=bti")))
+int foo ()
+{
+label:
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not {hint (36|38) // bti (j|jc)} } } */
-- 
2.17.1



[committed] aarch64: disable test on ilp32 [PR94697]

2020-04-27 Thread Szabolcs Nagy
branch-protection=pac-ret is not supported on ilp32 now and
the test requires it via branch-protection=standard.

committed as obvious.

gcc/testsuite/ChangeLog:

PR target/94697
* gcc.target/aarch64/pr94697.c: Require lp64.
---
 gcc/testsuite/ChangeLog| 5 +
 gcc/testsuite/gcc.target/aarch64/pr94697.c | 1 +
 2 files changed, 6 insertions(+)

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5a85af479c8..8b23374c591 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-04-27  Szabolcs Nagy  
+
+   PR target/94697
+   * gcc.target/aarch64/pr94697.c: Require lp64.
+
 2020-04-27  Jakub Jelinek  
 
PR c/94755
diff --git a/gcc/testsuite/gcc.target/aarch64/pr94697.c 
b/gcc/testsuite/gcc.target/aarch64/pr94697.c
index e6069d22ece..fcc9ab87f15 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr94697.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr94697.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
 /* { dg-options "-O2 -mbranch-protection=standard" } */
 /* { dg-final { check-function-bodies "**" "" } } */
 
-- 
2.17.1



Re: [PATCH v2] aarch64: Fix .cfi_window_save with pac-ret [PR94515]

2020-04-24 Thread Szabolcs Nagy
The 04/24/2020 15:17, Richard Sandiford wrote:
> Szabolcs Nagy  writes:
> > @@ -2221,6 +2239,14 @@ change_cfi_row (dw_cfi_row *old_row, dw_cfi_row 
> > *new_row)
> >cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
> >add_cfi (cfi);
> >  }
> > +
> > +  if (old_row->ra_mangled != new_row->ra_mangled)
> > +{
> > +  dw_cfi_ref cfi = new_cfi ();
> > +  /* DW_CFA_GNU_window_save is reused for toggling RA mangle state.  */
> > +  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
> > +  add_cfi (cfi);
> > +}
> >  }
> >  
> >  /* Examine CFI and return true if a cfi label and set_loc is needed
> 
> I wonder if it would be worth asserting:
> 
>   gcc_assert (!old_row->ra_mangled && !new_row->ra_mangled);
> 
> in the "SPARC" block and:
> 
>   gcc_assert (!old_row->window_save && !new_row->window_save);
> 
> in the "aarch64" block?

makes sense.
i'll fix it.

> > diff --git a/gcc/testsuite/g++.target/aarch64/pr94515-2.C 
> > b/gcc/testsuite/g++.target/aarch64/pr94515-2.C
> > new file mode 100644
> > index 000..1f13e1200ad
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/aarch64/pr94515-2.C
> > @@ -0,0 +1,41 @@
> > +/* PR target/94515. Check .cfi_window_save with multiple return paths.  */
> > +/* { dg-do run } */
> > +/* { dg-require-effective-target lp64 } */
> > +/* { dg-additional-options "-O2 -mbranch-protection=pac-ret" } */
> > +
> > +volatile int zero = 0;
> > +int global = 0;
> > +
> > +__attribute__((noinline))
> > +int bar(void)
> > +{
> > +  if (zero == 0) return 3;
> > +  return 0;
> > +}
> > +
> > +__attribute__((noinline, noreturn))
> > +void unwind (void)
> > +{
> > +  throw 42;
> > +}
> > +
> > +__attribute__((noinline, noipa, target("branch-protection=pac-ret")))
> 
> I'm probably just showing my ignorance, but is this target attribute
> needed?  It looks like all functions in the test are compiled with pac-ret.

no, that's left over before i added it to the cflags,
i'll fix it.

> 
> LGTM otherwise, but please give others 24 hrs to object.

thanks.

> 
> Thanks,
> Richard

-- 


[PATCH v2] aarch64: Fix .cfi_window_save with pac-ret [PR94515]

2020-04-24 Thread Szabolcs Nagy
On aarch64 -mbranch-protection=pac-ret reuses the dwarf
opcode for window_save to mean "toggle the return address
mangle state", but in the dwarf2cfi internal logic the
state was not updated when an opcode was emitted, the
currently present update logic is only valid for the
original sparc use of window_save so a separate bool is
used on aarch64 to track the state.

This bug can cause the unwinder not to authenticate return
addresses that were signed (or vice versa) which means a
runtime crash on a pauth enabled system.

Currently only aarch64 pac-ret uses REG_CFA_TOGGLE_RA_MANGLE.

This should be backported to gcc-9 and gcc-8 branches.

gcc/ChangeLog:

2020-04-23  Szabolcs Nagy  

PR target/94515
* dwarf2cfi.c (struct GTY): Add ra_mangled.
(cfi_row_equal_p): Check ra_mangled.
(dwarf2out_frame_debug_cfa_window_save): Remove the argument,
this only handles the sparc logic now.
(dwarf2out_frame_debug_cfa_toggle_ra_mangle): New function for
the aarch64 specific logic.
(dwarf2out_frame_debug): Update to use the new subroutines.
(change_cfi_row): Check ra_mangled.

gcc/testsuite/ChangeLog:

2020-04-23  Szabolcs Nagy  

PR target/94515
* g++.target/aarch64/pr94515-1.C: New test.
* g++.target/aarch64/pr94515-2.C: New test.
---
 gcc/dwarf2cfi.c  | 40 ++
 gcc/testsuite/g++.target/aarch64/pr94515-1.C | 44 
 gcc/testsuite/g++.target/aarch64/pr94515-2.C | 41 ++
 3 files changed, 118 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515-1.C
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515-2.C

diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 229fbfacc30..fa9e6089b2a 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -71,6 +71,9 @@ struct GTY(()) dw_cfi_row
 
   /* True if the register window is saved.  */
   bool window_save;
+
+  /* True if the return address is in a mangled state.  */
+  bool ra_mangled;
 };
 
 /* The caller's ORIG_REG is saved in SAVED_IN_REG.  */
@@ -772,6 +775,9 @@ cfi_row_equal_p (dw_cfi_row *a, dw_cfi_row *b)
   if (a->window_save != b->window_save)
 return false;
 
+  if (a->ra_mangled != b->ra_mangled)
+return false;
+
   return true;
 }
 
@@ -1370,20 +1376,33 @@ dwarf2out_frame_debug_cfa_restore (rtx reg)
 }
 
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_WINDOW_SAVE.
-   FAKE is true if this is not really a window save but something else.
 
??? Perhaps we should note in the CIE where windows are saved (instead
of assuming 0(cfa)) and what registers are in the window.  */
 
 static void
-dwarf2out_frame_debug_cfa_window_save (bool fake)
+dwarf2out_frame_debug_cfa_window_save (void)
+{
+  dw_cfi_ref cfi = new_cfi ();
+
+  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+  add_cfi (cfi);
+  cur_row->window_save = true;
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_TOGGLE_RA_MANGLE.
+   Note: DW_CFA_GNU_window_save dwarf opcode is reused for toggling RA mangle
+   state, this is a target specific operation on AArch64 and can only be used
+   on other targets if they don't use the window save operation otherwise.  */
+
+static void
+dwarf2out_frame_debug_cfa_toggle_ra_mangle (void)
 {
   dw_cfi_ref cfi = new_cfi ();
 
   cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
   add_cfi (cfi);
-  if (!fake)
-cur_row->window_save = true;
+  cur_row->ra_mangled = !cur_row->ra_mangled;
 }
 
 /* Record call frame debugging information for an expression EXPR,
@@ -2143,13 +2162,12 @@ dwarf2out_frame_debug (rtx_insn *insn)
break;
 
   case REG_CFA_TOGGLE_RA_MANGLE:
-   /* This uses the same DWARF opcode as the next operation.  */
-   dwarf2out_frame_debug_cfa_window_save (true);
+   dwarf2out_frame_debug_cfa_toggle_ra_mangle ();
handled_one = true;
break;
 
   case REG_CFA_WINDOW_SAVE:
-   dwarf2out_frame_debug_cfa_window_save (false);
+   dwarf2out_frame_debug_cfa_window_save ();
handled_one = true;
break;
 
@@ -2221,6 +2239,14 @@ change_cfi_row (dw_cfi_row *old_row, dw_cfi_row *new_row)
   cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
   add_cfi (cfi);
 }
+
+  if (old_row->ra_mangled != new_row->ra_mangled)
+{
+  dw_cfi_ref cfi = new_cfi ();
+  /* DW_CFA_GNU_window_save is reused for toggling RA mangle state.  */
+  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+  add_cfi (cfi);
+}
 }
 
 /* Examine CFI and return true if a cfi label and set_loc is needed
diff --git a/gcc/testsuite/g++.target/aarch64/pr94515-1.C 
b/gcc/testsuite/g++.target/aarch64/pr94515-1.C
new file mode 100644
index 000..cd63f4fb259
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr94515-1.C
@@ -0,0 +1,44 @@
+/* PR target/94515. Check .cfi_window_save with multiple return paths.  */
+/* { dg-do run } */

[PATCH] aarch64: ensure bti c is emitted at function start [PR94697]

2020-04-23 Thread Szabolcs Nagy
The bti pass currently first emits bti c at function start
if there is no paciasp (which also acts as indirect call
landing pad), then bti j is emitted at jump labels, however
if there is a label right before paciasp then the function
start can end up like

  foo:
  label:
bti j
paciasp
...

This patch is a minimal fix that just moves the bti c handling
after the bti j handling so we end up with

  foo:
bti c
  label:
bti j
paciasp
...

This could be improved by emitting bti jc in this case, or by
detecting that the label is not in fact an indirect jump target
and then this situation would be much less common.

Needs to be backported to gcc-9 branch.

gcc/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94697
* config/aarch64/aarch64-bti-insert.c (rest_of_insert_bti): Swap
bti c and bti j handling.

gcc/testsuite/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94697
* gcc.target/aarch64/pr94697.c: New test.
---
 gcc/config/aarch64/aarch64-bti-insert.c| 32 +++---
 gcc/testsuite/gcc.target/aarch64/pr94697.c | 19 +
 2 files changed, 35 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr94697.c

diff --git a/gcc/config/aarch64/aarch64-bti-insert.c 
b/gcc/config/aarch64/aarch64-bti-insert.c
index 295d18acab8..aa091c308f6 100644
--- a/gcc/config/aarch64/aarch64-bti-insert.c
+++ b/gcc/config/aarch64/aarch64-bti-insert.c
@@ -132,22 +132,6 @@ rest_of_insert_bti (void)
   rtx_insn *insn;
   basic_block bb;
 
-  /* Since a Branch Target Exception can only be triggered by an indirect call,
- we exempt function that are only called directly.  We also exempt
- functions that are already protected by Return Address Signing (PACIASP/
- PACIBSP).  For all other cases insert a BTI C at the beginning of the
- function.  */
-  if (!cgraph_node::get (cfun->decl)->only_called_directly_p ())
-{
-  bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
-  insn = BB_HEAD (bb);
-  if (!aarch64_pac_insn_p (get_first_nonnote_insn ()))
-   {
- bti_insn = gen_bti_c ();
- emit_insn_before (bti_insn, insn);
-   }
-}
-
   bb = 0;
   FOR_EACH_BB_FN (bb, cfun)
 {
@@ -203,6 +187,22 @@ rest_of_insert_bti (void)
}
 }
 
+  /* Since a Branch Target Exception can only be triggered by an indirect call,
+ we exempt function that are only called directly.  We also exempt
+ functions that are already protected by Return Address Signing (PACIASP/
+ PACIBSP).  For all other cases insert a BTI C at the beginning of the
+ function.  */
+  if (!cgraph_node::get (cfun->decl)->only_called_directly_p ())
+{
+  bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+  insn = BB_HEAD (bb);
+  if (!aarch64_pac_insn_p (get_first_nonnote_insn ()))
+   {
+ bti_insn = gen_bti_c ();
+ emit_insn_before (bti_insn, insn);
+   }
+}
+
   timevar_pop (TV_MACH_DEP);
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/aarch64/pr94697.c 
b/gcc/testsuite/gcc.target/aarch64/pr94697.c
new file mode 100644
index 000..e6069d22ece
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr94697.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=standard" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+void bar (int *);
+void *addr;
+
+/*
+** foo:
+** hint(25|34|38) // (paciasp|bti c|bti jc)
+** ...
+*/
+int foo (int x)
+{
+label:
+  addr = &
+  bar ();
+  return x;
+}
-- 
2.17.1




Re: [PATCH] aarch64, libgcc: Fix unwinding from pac-ret to normal frames [PR94514]

2020-04-23 Thread Szabolcs Nagy
The 04/22/2020 15:22, Christophe Lyon wrote:
> The new test fails with ilp32, not sure if that's supposed to work?
> 
> FAIL: gcc.target/aarch64/pr94514.c (test for excess errors)
> Excess errors:
> /gcc/testsuite/gcc.target/aarch64/pr94514.c:27:4: warning: cast to
> pointer from integer of different size [-Wint-to-pointer-cast]
> 
> spawn 
> /aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-elf/invoke-foundation-v8-bare-metal.sh
> ./pr94514.exe
> force_unwind_stop: CFA: 0xef80 PC: 0x80001304 actions: 10
> force_unwind_stop: CFA: 0xef90 PC: 0x8000133c actions: 10
> Terminated by exception.
> 
> *** EXIT code 126
> gcc.target/aarch64/pr94514.c execution test (reason: TCL LOOKUP CHANNEL exp7)
> FAIL: gcc.target/aarch64/pr94514.c execution test
> 
> (executed using the Foundation Model)
> 
> 
> The C++ test compiles without warnings, but fails at execution too
...
> Maybe you just want to skip the test for ilp32?

i didn't test ilp32, i would expect a compile time error for

__attribute__((target("branch-protection=pac-ret")))

on ilp32, or just ignoring it (which would have worked),
runtime error for this on a pac-enabled system is nasty.

i disabled the test on ilp32 as an obvious fix (attached),
and raised PR94729 for the attribute handling in ilp32.

thanks for catching this.
>From 744b3e4478df83f54543964b8eb7250eb9bb6d40 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy 
Date: Thu, 23 Apr 2020 11:26:10 +0100
Subject: [PATCH] aarch64: disable tests on ilp32 [PR94514]

branch-protection=pac-ret is only supported with lp64 abi.

gcc/testsuite/ChangeLog:

	PR target/94514
	* g++.target/aarch64/pr94514.C: Require lp64.
	* gcc.target/aarch64/pr94514.c: Likewise.
---
 gcc/testsuite/ChangeLog| 6 ++
 gcc/testsuite/g++.target/aarch64/pr94514.C | 1 +
 gcc/testsuite/gcc.target/aarch64/pr94514.c | 1 +
 3 files changed, 8 insertions(+)

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 245c1512c76..7e676f053a5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-23  Szabolcs Nagy  
+
+	PR target/94514
+	* g++.target/aarch64/pr94514.C: Require lp64.
+	* gcc.target/aarch64/pr94514.c: Likewise.
+
 2020-04-23  Jakub Jelinek  
 
 	PR target/94707
diff --git a/gcc/testsuite/g++.target/aarch64/pr94514.C b/gcc/testsuite/g++.target/aarch64/pr94514.C
index 2a8c949ba30..ae925cafeb6 100644
--- a/gcc/testsuite/g++.target/aarch64/pr94514.C
+++ b/gcc/testsuite/g++.target/aarch64/pr94514.C
@@ -1,5 +1,6 @@
 /* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames.  */
 /* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
 
 __attribute__((noinline, target("branch-protection=pac-ret")))
 static void do_throw (void)
diff --git a/gcc/testsuite/gcc.target/aarch64/pr94514.c b/gcc/testsuite/gcc.target/aarch64/pr94514.c
index bbbf5a6b0b3..cbc940421d2 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr94514.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr94514.c
@@ -1,5 +1,6 @@
 /* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames.  */
 /* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
 /* { dg-options "-fexceptions -O2" } */
 
 #include 
-- 
2.17.1



Re: [PATCH] aarch64, libgcc: Fix unwinding from pac-ret to normal frames [PR94514]

2020-04-21 Thread Szabolcs Nagy
The 04/17/2020 11:05, Kyrylo Tkachov wrote:
> Hi Szabolcs,
> 
> > -Original Message-
> > From: Szabolcs Nagy 
> > Sent: 09 April 2020 15:20
> > To: gcc-patches@gcc.gnu.org
> > Cc: Richard Earnshaw ; Richard Sandiford
> > ; Kyrylo Tkachov 
> > Subject: [PATCH] aarch64, libgcc: Fix unwinding from pac-ret to normal
> > frames [PR94514]
> >
> > With -mbranch-protection=pac-ret the debug info toggles the
> > signedness state of the return address so the unwinder knows when
> > the return address needs pointer authentication.
> >
> > The unwind context flags were not updated according to the dwarf
> > frame info.
> >
> > This causes unwinding across frames that were built without pac-ret
> > to incorrectly authenticate the return address wich corrupts the
> > return address on a system where PAuth is enabled.
> >
> > Note: This even affects systems where all code use pac-ret because
> > unwinding across a signal frame the return address is not signed.
> >
> 
> Ok, I'm guessing this needs backporting?

committed now,

yes i think it has to go back to gcc-9 and gcc-8,
i will do that later. thanks.


Re: [PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]

2020-04-21 Thread Szabolcs Nagy
The 04/17/2020 15:26, Jason Merrill wrote:
> On 4/17/20 1:55 PM, Szabolcs Nagy wrote:
> > The 04/17/2020 12:50, Jason Merrill wrote:
> > > On 4/17/20 6:08 AM, Kyrylo Tkachov wrote:
> > > > Hi Szabolcs,
> > > > 
> > > > > -Original Message-
> > > > > From: Szabolcs Nagy 
> > > > > Sent: 09 April 2020 15:20
> > > > > To: gcc-patches@gcc.gnu.org
> > > > > Cc: Richard Earnshaw ; Richard Sandiford
> > > > > ; Kyrylo Tkachov 
> > > > > Subject: [PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]
> > > > > 
> > > > > On aarch64 -mbranch-protection=pac-ret reuses the dwarf
> > > > > opcode for window_save to mean "toggle the return address
> > > > > mangle state", but in the dwarf2cfi internal logic the
> > > > > state was not properly recorded so the remember/restore
> > > > > logic was broken.
> > > > > 
> > > > > This can cause the unwinder not to authenticate return
> > > > > addresses that were signed (or vice versa) which means
> > > > > a runtime crash on a pauth enabled system.
> > > > > 
> > > > > Currently only aarch64 pac-ret uses REG_CFA_TOGGLE_RA_MANGLE.
> > > > 
> > > > I think this is ok, but this code is in the midend so I've CC'ed Jason 
> > > > who, from what I gather from MAINTAINERS, is maintainer for this file.
> > > > Thanks,
> > > > Kyrill
> > > > 
> > > > > 
> > > > > gcc/ChangeLog:
> > > > > 
> > > > > 2020-04-XX  Szabolcs Nagy  
> > > > > 
> > > > >   PR target/94515
> > > > >   * dwarf2cfi.c (dwarf2out_frame_debug): Record RA
> > > > >   mangle state in cur_row->window_save.
> > > > > 
> > > > > gcc/testsuite/ChangeLog:
> > > > > 
> > > > > 2020-04-XX  Szabolcs Nagy  
> > > > > 
> > > > >   PR target/94515
> > > > >   * g++.target/aarch64/pr94515.C: New test.
> > > > > ---
> > > > >gcc/dwarf2cfi.c|  3 ++
> > > > >gcc/testsuite/g++.target/aarch64/pr94515.C | 43 
> > > > > ++
> > > > >2 files changed, 46 insertions(+)
> > > > >create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515.C
> > > > > 
> > > > > diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> > > > > index 229fbfacc30..22989a6c2fb 100644
> > > > > --- a/gcc/dwarf2cfi.c
> > > > > +++ b/gcc/dwarf2cfi.c
> > > > > @@ -2145,6 +2145,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
> > > > >  case REG_CFA_TOGGLE_RA_MANGLE:
> > > > >   /* This uses the same DWARF opcode as the next operation.  */
> > > > >   dwarf2out_frame_debug_cfa_window_save (true);
> > > > > + /* Keep track of RA mangle state by toggling the window_save 
> > > > > bit.
> > > > > +This is needed so .cfi_window_save is emitted correctly.  */
> > > > > + cur_row->window_save = !cur_row->window_save;
> > > 
> > > It looks like passing 'true' to dwarf2out_frame_debug_cfa_window_save
> > > prevents that function from messing with the window_safe flag.  Does
> > > changing the argument to 'false' get the behavior you want?
> > 
> > we want the state = !state toggling.
> > it might make more sense to do that in
> > dwarf2out_frame_debug_cfa_window_save(true)
> > or to inline that entire logic into the two
> > places where it is used (instead of
> > dispatching with a bool argument).
> 
> I think that inlining and dropping the parameter would be cleaner.
> 
> > for the bug fix i'd like a minimal change
> > (so it can be backported), doing the fix in
> > dwarf2out_frame_debug_cfa_window_save
> > is fine with me, would you prefer that?
> 
> No, thanks.  If you want to commit your patch as is for backporting and then
> do the inlining in a separate commit, that works  for me.

i spoted failing execution tests that expected to pass,
it turns out change_cfi_row() needs something like

-  if (!old_row->window_save && new_row->window_save)
+  if (old_row->window_save != new_row->window_save)

to generate .cfi_window_save that correctly tracks the
toggled state on aarch64, but i assume sparc wants
something else, i added Eric to CC he might know what's
right for the old&&!new case on sparc, any help is
welcome, the logic was added in

commit dfe1fe91dbc7f068bb3efcee40237caacc0c53ae

i can imagine adding a new bool flag in dw_cfi_row
for aarch64 or making the logic target specific
(depending on if the target uses REG_CFA_WINDOW_SAVE
or REG_CFA_TOGGLE_RA_MANGLE for cfi_window_save)

i added a test to the bug report that fails with
my original patch, but works if change_cfi_row is
updated.


Re: [PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]

2020-04-17 Thread Szabolcs Nagy
The 04/17/2020 12:50, Jason Merrill wrote:
> On 4/17/20 6:08 AM, Kyrylo Tkachov wrote:
> > Hi Szabolcs,
> > 
> > > -Original Message-----
> > > From: Szabolcs Nagy 
> > > Sent: 09 April 2020 15:20
> > > To: gcc-patches@gcc.gnu.org
> > > Cc: Richard Earnshaw ; Richard Sandiford
> > > ; Kyrylo Tkachov 
> > > Subject: [PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]
> > > 
> > > On aarch64 -mbranch-protection=pac-ret reuses the dwarf
> > > opcode for window_save to mean "toggle the return address
> > > mangle state", but in the dwarf2cfi internal logic the
> > > state was not properly recorded so the remember/restore
> > > logic was broken.
> > > 
> > > This can cause the unwinder not to authenticate return
> > > addresses that were signed (or vice versa) which means
> > > a runtime crash on a pauth enabled system.
> > > 
> > > Currently only aarch64 pac-ret uses REG_CFA_TOGGLE_RA_MANGLE.
> > 
> > I think this is ok, but this code is in the midend so I've CC'ed Jason who, 
> > from what I gather from MAINTAINERS, is maintainer for this file.
> > Thanks,
> > Kyrill
> > 
> > > 
> > > gcc/ChangeLog:
> > > 
> > > 2020-04-XX  Szabolcs Nagy  
> > > 
> > >   PR target/94515
> > >   * dwarf2cfi.c (dwarf2out_frame_debug): Record RA
> > >   mangle state in cur_row->window_save.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > > 2020-04-XX  Szabolcs Nagy  
> > > 
> > >   PR target/94515
> > >   * g++.target/aarch64/pr94515.C: New test.
> > > ---
> > >   gcc/dwarf2cfi.c|  3 ++
> > >   gcc/testsuite/g++.target/aarch64/pr94515.C | 43 ++
> > >   2 files changed, 46 insertions(+)
> > >   create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515.C
> > > 
> > > diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> > > index 229fbfacc30..22989a6c2fb 100644
> > > --- a/gcc/dwarf2cfi.c
> > > +++ b/gcc/dwarf2cfi.c
> > > @@ -2145,6 +2145,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
> > > case REG_CFA_TOGGLE_RA_MANGLE:
> > >   /* This uses the same DWARF opcode as the next operation.  */
> > >   dwarf2out_frame_debug_cfa_window_save (true);
> > > + /* Keep track of RA mangle state by toggling the window_save bit.
> > > +This is needed so .cfi_window_save is emitted correctly.  */
> > > + cur_row->window_save = !cur_row->window_save;
> 
> It looks like passing 'true' to dwarf2out_frame_debug_cfa_window_save
> prevents that function from messing with the window_safe flag.  Does
> changing the argument to 'false' get the behavior you want?

we want the state = !state toggling.
it might make more sense to do that in
dwarf2out_frame_debug_cfa_window_save(true)
or to inline that entire logic into the two
places where it is used (instead of
dispatching with a bool argument).

for the bug fix i'd like a minimal change
(so it can be backported), doing the fix in
dwarf2out_frame_debug_cfa_window_save
is fine with me, would you prefer that?

> 
> > >   handled_one = true;
> > >   break;
> > > 
> > > diff --git a/gcc/testsuite/g++.target/aarch64/pr94515.C
> > > b/gcc/testsuite/g++.target/aarch64/pr94515.C
> > > new file mode 100644
> > > index 000..7707c773a72
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.target/aarch64/pr94515.C
> > > @@ -0,0 +1,43 @@
> > > +/* PR target/94515. Check .cfi_window_save with multiple return paths.  
> > > */
> > > +/* { dg-do run } */
> > > +/* { dg-additional-options "-O2 -mbranch-protection=pac-ret 
> > > --save-temps" }
> > > */
> > > +
> > > +volatile int zero = 0;
> > > +
> > > +__attribute__((noinline, target("branch-protection=none")))
> > > +void unwind (void)
> > > +{
> > > +  if (zero == 0)
> > > +throw 42;
> > > +}
> > > +
> > > +__attribute__((noinline, noipa, target("branch-protection=pac-ret")))
> > > +int test (int z)
> > > +{
> > > +  if (z) {
> > > +asm volatile ("":::"x20","x21");
> > > +unwind ();
> > > +return 1;
> > > +  } else {
> > > +unwind ();
> > > +return 2;
> > > +  }
> > > +}
> > > +
> > > +__attribute__((target("branch-protection=none")))
> > > +int main ()
> > > +{
> > > +  try {
> > > +test (zero);
> > > +__builtin_abort ();
> > > +  } catch (...) {
> > > +return 0;
> > > +  }
> > > +  __builtin_abort ();
> > > +}
> > > +
> > > +/* This check only works if there are two return paths in test and
> > > +   cfi_window_save is used for both instead of cfi_remember_state
> > > +   plus cfi_restore_state.  This is currently the case with -O2.  */
> > > +
> > > +/* { dg-final { scan-assembler-times {\t\.cfi_window_save\n} 4 } } */
> > > --
> > > 2.17.1
> > 
> 

-- 


[PATCH] aarch64, libgcc: Fix unwinding from pac-ret to normal frames [PR94514]

2020-04-09 Thread Szabolcs Nagy
With -mbranch-protection=pac-ret the debug info toggles the
signedness state of the return address so the unwinder knows when
the return address needs pointer authentication.

The unwind context flags were not updated according to the dwarf
frame info.

This causes unwinding across frames that were built without pac-ret
to incorrectly authenticate the return address wich corrupts the
return address on a system where PAuth is enabled.

Note: This even affects systems where all code use pac-ret because
unwinding across a signal frame the return address is not signed.

gcc/testsuite/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94514
* g++.target/aarch64/pr94514.C: New test.
* gcc.target/aarch64/pr94514.c: New test.

libgcc/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94514
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Update context->flags accroding to the frame state.
---
 gcc/testsuite/g++.target/aarch64/pr94514.C | 26 
 gcc/testsuite/gcc.target/aarch64/pr94514.c | 76 ++
 libgcc/config/aarch64/aarch64-unwind.h |  2 +
 3 files changed, 104 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr94514.C
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr94514.c

diff --git a/gcc/testsuite/g++.target/aarch64/pr94514.C 
b/gcc/testsuite/g++.target/aarch64/pr94514.C
new file mode 100644
index 000..2a8c949ba30
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr94514.C
@@ -0,0 +1,26 @@
+/* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames.  */
+/* { dg-do run } */
+
+__attribute__((noinline, target("branch-protection=pac-ret")))
+static void do_throw (void)
+{
+  throw 42;
+  __builtin_abort ();
+}
+
+__attribute__((noinline, target("branch-protection=none")))
+static void no_pac_ret (void)
+{
+  do_throw ();
+  __builtin_abort ();
+}
+
+int main ()
+{
+  try {
+no_pac_ret ();
+  } catch (...) {
+return 0;
+  }
+  __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr94514.c 
b/gcc/testsuite/gcc.target/aarch64/pr94514.c
new file mode 100644
index 000..bbbf5a6b0b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr94514.c
@@ -0,0 +1,76 @@
+/* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames.  */
+/* { dg-do run } */
+/* { dg-options "-fexceptions -O2" } */
+
+#include 
+#include 
+#include 
+
+#define die() \
+  do { \
+printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \
+fflush (stdout); \
+abort (); \
+  } while (0)
+
+static struct _Unwind_Exception exc;
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+   _Unwind_Exception_Class exc_class,
+   struct _Unwind_Exception *exc_obj,
+   struct _Unwind_Context *context,
+   void *stop_parameter)
+{
+  printf ("%s: CFA: %p PC: %p actions: %d\n",
+ __func__,
+ (void *)_Unwind_GetCFA (context),
+ (void *)_Unwind_GetIP (context),
+ (int)actions);
+  if (actions & _UA_END_OF_STACK)
+die ();
+  return _URC_NO_REASON;
+}
+
+static void force_unwind (void)
+{
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (, force_unwind_stop, 0);
+#endif
+}
+
+__attribute__((noinline, target("branch-protection=pac-ret")))
+static void f2_pac_ret (void)
+{
+  force_unwind ();
+  die ();
+}
+
+__attribute__((noinline, target("branch-protection=none")))
+static void f1_no_pac_ret (void)
+{
+  f2_pac_ret ();
+  die ();
+}
+
+__attribute__((noinline, target("branch-protection=pac-ret")))
+static void f0_pac_ret (void)
+{
+  f1_no_pac_ret ();
+  die ();
+}
+
+static void cleanup_handler (void *p)
+{
+  printf ("%s: Success.\n", __func__);
+  exit (0);
+}
+
+int main ()
+{
+  char dummy __attribute__((cleanup (cleanup_handler)));
+  f0_pac_ret ();
+  die ();
+}
diff --git a/libgcc/config/aarch64/aarch64-unwind.h 
b/libgcc/config/aarch64/aarch64-unwind.h
index 4c8790bae67..ed84a96db41 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -104,6 +104,8 @@ aarch64_frob_update_context (struct _Unwind_Context 
*context,
   if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
 /* The flag is used for re-authenticating EH handler's address.  */
 context->flags |= RA_SIGNED_BIT;
+  else
+context->flags &= ~RA_SIGNED_BIT;
 
   return;
 }
-- 
2.17.1



[PATCH] aarch64: Fix .cfi_window_save with pac-ret [PR94515]

2020-04-09 Thread Szabolcs Nagy
On aarch64 -mbranch-protection=pac-ret reuses the dwarf
opcode for window_save to mean "toggle the return address
mangle state", but in the dwarf2cfi internal logic the
state was not properly recorded so the remember/restore
logic was broken.

This can cause the unwinder not to authenticate return
addresses that were signed (or vice versa) which means
a runtime crash on a pauth enabled system.

Currently only aarch64 pac-ret uses REG_CFA_TOGGLE_RA_MANGLE.

gcc/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94515
* dwarf2cfi.c (dwarf2out_frame_debug): Record RA
mangle state in cur_row->window_save.

gcc/testsuite/ChangeLog:

2020-04-XX  Szabolcs Nagy  

PR target/94515
* g++.target/aarch64/pr94515.C: New test.
---
 gcc/dwarf2cfi.c|  3 ++
 gcc/testsuite/g++.target/aarch64/pr94515.C | 43 ++
 2 files changed, 46 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/aarch64/pr94515.C

diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 229fbfacc30..22989a6c2fb 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2145,6 +2145,9 @@ dwarf2out_frame_debug (rtx_insn *insn)
   case REG_CFA_TOGGLE_RA_MANGLE:
/* This uses the same DWARF opcode as the next operation.  */
dwarf2out_frame_debug_cfa_window_save (true);
+   /* Keep track of RA mangle state by toggling the window_save bit.
+  This is needed so .cfi_window_save is emitted correctly.  */
+   cur_row->window_save = !cur_row->window_save;
handled_one = true;
break;
 
diff --git a/gcc/testsuite/g++.target/aarch64/pr94515.C 
b/gcc/testsuite/g++.target/aarch64/pr94515.C
new file mode 100644
index 000..7707c773a72
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/pr94515.C
@@ -0,0 +1,43 @@
+/* PR target/94515. Check .cfi_window_save with multiple return paths.  */
+/* { dg-do run } */
+/* { dg-additional-options "-O2 -mbranch-protection=pac-ret --save-temps" } */
+
+volatile int zero = 0;
+
+__attribute__((noinline, target("branch-protection=none")))
+void unwind (void)
+{
+  if (zero == 0)
+throw 42;
+}
+
+__attribute__((noinline, noipa, target("branch-protection=pac-ret")))
+int test (int z)
+{
+  if (z) {
+asm volatile ("":::"x20","x21");
+unwind ();
+return 1;
+  } else {
+unwind ();
+return 2;
+  }
+}
+
+__attribute__((target("branch-protection=none")))
+int main ()
+{
+  try {
+test (zero);
+__builtin_abort ();
+  } catch (...) {
+return 0;
+  }
+  __builtin_abort ();
+}
+
+/* This check only works if there are two return paths in test and
+   cfi_window_save is used for both instead of cfi_remember_state
+   plus cfi_restore_state.  This is currently the case with -O2.  */
+
+/* { dg-final { scan-assembler-times {\t\.cfi_window_save\n} 4 } } */
-- 
2.17.1



Re: [PATCH] avoid treating more incompatible redeclarations as builtin-ins [PR94040]

2020-03-18 Thread Szabolcs Nagy
The 03/13/2020 10:45, Martin Sebor via Gcc-patches wrote:
> On 3/12/20 7:17 PM, Joseph Myers wrote:
> > On Thu, 5 Mar 2020, Martin Sebor wrote:
> > 
> > > Tested on x86_64-linux.  Is this acceptable for GCC 10?  How about 9?
> > 
> > OK for GCC 10.
> 
> Thank you.  I committed it to trunk in r10-7162.

i see glibc build failure on arm since this commit:

../sysdeps/ieee754/dbl-64/s_modf.c:84:28: error: conflicting types for built-in 
function 'modfl'; expected 'long double(long double,  long double *)' 
[-Werror=builtin-declaration-mismatch]
   84 | libm_alias_double (__modf, modf)
  |^~~~

it seems this used to compile:

double modf (double x, double *p) { return x; }
extern __typeof (modf) modfl __attribute__ ((weak, alias ("modf"))) 
__attribute__ ((__copy__ (modf)));


Re: [PATCH] avoid treating more incompatible redeclarations as builtin-ins [PR94040]

2020-03-18 Thread Szabolcs Nagy
The 03/13/2020 10:45, Martin Sebor via Gcc-patches wrote:
> On 3/12/20 7:17 PM, Joseph Myers wrote:
> > On Thu, 5 Mar 2020, Martin Sebor wrote:
> > 
> > > Tested on x86_64-linux.  Is this acceptable for GCC 10?  How about 9?
> > 
> > OK for GCC 10.
> 
> Thank you.  I committed it to trunk in r10-7162.

arm glibc build fails for me since this commit.

../sysdeps/ieee754/dbl-64/s_modf.c:84:28: error: conflicting types for built-in 
function 'modfl'; expected 'long double(long double,  long double *)' 
[-Werror=builtin-declaration-mismatch]
   84 | libm_alias_double (__modf, modf)
  |^~~~

it seems this used to compile but not any more:

double modf (double x, double *p) { return x; }
extern __typeof (modf) modfl __attribute__ ((weak, alias ("modf"))) 
__attribute__ ((__copy__ (modf)));


  1   2   3   4   >