diff mbox

[Ping~] Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version)

Message ID a242b032-db02-244f-eafe-cd36ee608a86@foss.arm.com
State New
Headers show

Commit Message

Jiong Wang Jan. 12, 2017, 6:10 p.m. UTC
On 06/01/17 11:47, Jiong Wang wrote:
> This is the update on libgcc unwinder support according to new DWARF 

> proposal.

>

> As Joseph commented, duplication of unwind-dw2.c is not encouraged in 

> libgcc,

> But from this patch, you can see there are a few places we need to 

> modify for

> AArch64 in unwind-aarch64.c, so the file duplication approach is 

> acceptable?

>

>

> libgcc/

>

> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>

>

>         * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,

>         RA_A_SIGNED_BIT): New macros.

>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on 

> AArch64.

>         (uw_frame_state_for): Clear bit[0] of 

> DWARF_REGNUM_AARCH64_RA_STATE.

>         (uw_update_context): Authenticate return address according to

>         DWARF_REGNUM_AARCH64_RA_STATE.

>         (uw_init_context_1): Strip signature of seed address.

>         (uw_install_context): Re-authenticate EH handler's address.

>

Ping~

For comparision, I have also attached the patch using the target macros.

Four new target macros are introduced:

   MD_POST_EXTRACT_ROOT_ADDR
   MD_POST_EXTRACT_FRAME_ADDR
   MD_POST_FROB_EH_HANDLER_ADDR
   MD_POST_INIT_CONTEXT

MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on the address
inside _Unwind* functions, they are serving as root address to start the
unwinding.  MD_POST_EXTRACT_FRAME_ADDR is to do target private post processing
on th address inside the real user program which throws the exceptions.

MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH handler's
address before we install it into current context.

MD_POST_INIT_CONTEXT it to do target private initialization on the context
structure after common initialization.

One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save.

libgcc/ChangeLog:

2017-01-11  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-unwind.h: New file.
         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
         (MD_POST_EXTRACT_ROOT_ADDR): Define.
         (MD_POST_EXTRACT_FRAME_ADDR): Define.
         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
         (MD_POST_INIT_CONTEXT): Define.
         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*):
         Initialize md_unwind_header to include aarch64-unwind.h.
         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__.
         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR and
         MD_POST_INIT_CONTEXT.
         (uw_frob_return_addr): New function.
         (_Unwind_DebugHook): Use uw_frob_return_addr.

Comments

James Greenhalgh Jan. 13, 2017, 2:12 p.m. UTC | #1
On Thu, Jan 12, 2017 at 06:10:36PM +0000, Jiong Wang wrote:
> On 06/01/17 11:47, Jiong Wang wrote:

> >This is the update on libgcc unwinder support according to new

> >DWARF proposal.

> >

> >As Joseph commented, duplication of unwind-dw2.c is not encouraged

> >in libgcc,

> >But from this patch, you can see there are a few places we need to

> >modify for

> >AArch64 in unwind-aarch64.c, so the file duplication approach is

> >acceptable?

> >

> >

> >libgcc/

> >

> >2017-01-06  Jiong Wang  <jiong.wang@arm.com>

> >

> >        * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE,

> >        RA_A_SIGNED_BIT): New macros.

> >        (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on

> >AArch64.

> >        (uw_frame_state_for): Clear bit[0] of

> >DWARF_REGNUM_AARCH64_RA_STATE.

> >        (uw_update_context): Authenticate return address according to

> >        DWARF_REGNUM_AARCH64_RA_STATE.

> >        (uw_init_context_1): Strip signature of seed address.

> >        (uw_install_context): Re-authenticate EH handler's address.

> >

> Ping~

> 

> For comparision, I have also attached the patch using the target macros.


Personally, I much prefer this approach.

I haven't looked at your patch in detail, I'll leave that for after a
libgcc maintainer has commented on whether these macros would be
acceptable.

Thanks,
James
Richard Earnshaw (lists) Jan. 19, 2017, 2:18 p.m. UTC | #2
On 18/01/17 17:07, Jiong Wang wrote:
> On 12/01/17 18:10, Jiong Wang wrote:

>> On 06/01/17 11:47, Jiong Wang wrote:

>>> This is the update on libgcc unwinder support according to new DWARF

>>> proposal.

>>>

>>> As Joseph commented, duplication of unwind-dw2.c is not encouraged in

>>> libgcc,

>>> But from this patch, you can see there are a few places we need to

>>> modify for

>>> AArch64 in unwind-aarch64.c, so the file duplication approach is

>>> acceptable?

>>>

>>>

>>> libgcc/

>>>

>>> 2017-01-06  Jiong Wang  <jiong.wang@arm.com>

>>>

>>>         * config/aarch64/unwind-aarch64.c

>>> (DWARF_REGNUM_AARCH64_RA_STATE,

>>>         RA_A_SIGNED_BIT): New macros.

>>>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on

>>> AArch64.

>>>         (uw_frame_state_for): Clear bit[0] of

>>> DWARF_REGNUM_AARCH64_RA_STATE.

>>>         (uw_update_context): Authenticate return address according to

>>>         DWARF_REGNUM_AARCH64_RA_STATE.

>>>         (uw_init_context_1): Strip signature of seed address.

>>>         (uw_install_context): Re-authenticate EH handler's address.

>>>

>> Ping~

>>

>> For comparision, I have also attached the patch using the target macros.

>>

>> Four new target macros are introduced:

>>

>>   MD_POST_EXTRACT_ROOT_ADDR

>>   MD_POST_EXTRACT_FRAME_ADDR

>>   MD_POST_FROB_EH_HANDLER_ADDR

>>   MD_POST_INIT_CONTEXT

>>

>> MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on

>> the address

>> inside _Unwind* functions, they are serving as root address to start the

>> unwinding.  MD_POST_EXTRACT_FRAME_ADDR is to do target private post

>> processing

>> on th address inside the real user program which throws the exceptions.

>>

>> MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH

>> handler's

>> address before we install it into current context.

>>

>> MD_POST_INIT_CONTEXT it to do target private initialization on the

>> context

>> structure after common initialization.

>>

>> One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save.

> 

> Ping ~

> 

> Could global reviewers or libgcc maintainers please give a review on the

> generic

> part change?

> 

> One small change is I removed MD_POST_INIT_CONTEXT as I found there is

> MD_FROB_UPDATE_CONTEXT which serve the same purpose.  I still need to

> define

> 

>    MD_POST_EXTRACT_ROOT_ADDR

>    MD_POST_EXTRACT_FRAME_ADDR

>    MD_POST_FROB_EH_HANDLER_ADDR

> 

> And do one __aarch64__ check to multiplexing DW_CFA_GNU_window_save.

> 

> Thanks.

> 

> libgcc/ChangeLog:

> 

> 2017-01-18  Jiong Wang  <jiong.wang@arm.com>

> 

>         * config/aarch64/aarch64-unwind.h: New file.

>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.

>         (MD_POST_EXTRACT_ROOT_ADDR): Define.

>         (MD_POST_EXTRACT_FRAME_ADDR): Define.

>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.

>         (MD_FROB_UPDATE_CONTEXT): Define.

>         (aarch64_post_extract_frame_addr): New function.

>         (aarch64_post_frob_eh_handler_addr): New function.

>         (aarch64_frob_update_context): New function.

>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h

>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,

> aarch64*-*-freebsd*):

>         Initialize md_unwind_header to include aarch64-unwind.h.

>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".

>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for

> __aarch64__.

>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.

>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.

>         (uw_frob_return_addr): New function.

>         (_Unwind_DebugHook): Use uw_frob_return_addr.

> 

> 


Comments inline.

> 1.patch

> 

> 

> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

> index 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2 100644

> --- a/libgcc/unwind-dw2.c

> +++ b/libgcc/unwind-dw2.c

> @@ -136,6 +136,8 @@ struct _Unwind_Context

>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>    /* Context which has version/args_size/by_value fields.  */

>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

> +  /* Bit reserved on AArch64, return address has been signed with A key.  */

> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)


Why is this here?   It appears to only be used within the
AArch64-specific header file.

>    _Unwind_Word flags;

>    /* 0 for now, can be increased when further fields are added to

>       struct _Unwind_Context.  */

> @@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,

>  	  break;

>  

>  	case DW_CFA_GNU_window_save:

> +#ifdef __aarch64__

> +	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle

> +	     return address signing status.  */

> +	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

> +#else

>  	  /* ??? Hardcoded for SPARC register window configuration.  */

>  	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)

>  	    for (reg = 16; reg < 32; ++reg)

> @@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,

>  		fs->regs.reg[reg].how = REG_SAVED_OFFSET;

>  		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);

>  	      }

> +#endif

>  	  break;

>  

>  	case DW_CFA_GNU_args_size:

> @@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)

>         stack frame.  */

>      context->ra = 0;

>    else

> -    /* 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));

> +    {

> +      /* 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_FRAME_ADDR (context, fs, context->ra);

> +#endif

> +    }

>  }

>  

>  static void

> @@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,

>  		   void *outer_cfa, void *outer_ra)

>  {

>    void *ra = __builtin_extract_return_addr (__builtin_return_address (0));

> +#ifdef MD_POST_EXTRACT_ROOT_ADDR

> +  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);

> +#endif

>    _Unwind_FrameState fs;

>    _Unwind_SpTmp sp_slot;

>    _Unwind_Reason_Code code;

> @@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Context *context,

>       initialization context, then we can't see it in the given

>       call frame data.  So have the initialization context tell us.  */

>    context->ra = __builtin_extract_return_addr (outer_ra);

> +#ifdef MD_POST_EXTRACT_ROOT_ADDR

> +  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);

> +#endif

>  }

>  

>  static void _Unwind_DebugHook (void *, void *)

> @@ -1608,6 +1627,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),

>  #endif

>  }

>  

> +/* Frob exception handler's address kept in TARGET before installing into

> +   CURRENT context.  */

> +

> +static void *

> +uw_frob_return_addr (struct _Unwind_Context *current,

> +		     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;

> +}

> +


I think this function should be marked inline.  The optimizers would
probably inline it anyway, but it seems wrong for us to rely on that.

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

> @@ -1616,7 +1649,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),

>    do									\

>      {									\

>        long offset = uw_install_context_1 ((CURRENT), (TARGET));		\

> -      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\

> +      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\

>        _Unwind_DebugHook ((TARGET)->cfa, handler);			\

>        __builtin_eh_return (offset, handler);				\

>      }									\

> diff --git a/libgcc/config.host b/libgcc/config.host

> index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644

> --- a/libgcc/config.host

> +++ b/libgcc/config.host

> @@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)

>  	extra_parts="$extra_parts crtfastmath.o"

>  	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"

>  	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"

> +	md_unwind_header=aarch64/aarch64-unwind.h

>  	;;

>  aarch64*-*-freebsd*)

>  	extra_parts="$extra_parts crtfastmath.o"

>  	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"

>  	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"

> +	md_unwind_header=aarch64/aarch64-unwind.h

>  	;;

>  aarch64*-*-linux*)

>  	extra_parts="$extra_parts crtfastmath.o"

> diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h

> new file mode 100644

> index 0000000000000000000000000000000000000000..a57cae0ff54ea7e11c32362677c0b51501a9f727

> --- /dev/null

> +++ b/libgcc/config/aarch64/aarch64-unwind.h

> @@ -0,0 +1,87 @@

> +/* Copyright (C) 2017 Free Software Foundation, Inc.

> +   Contributed by ARM Ltd.

> +

> +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

> +<http://www.gnu.org/licenses/>.  */

> +

> +#ifndef AARCH64_UNWIND_H

> +#define AARCH64_UNWIND_H

> +

> +#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_FROB_UPDATE_CONTEXT(context, fs) \

> +  aarch64_frob_update_context (context, fs)

> +

> +/* Do AArch64 private extraction on ADDR based on context info CONTEXT and

> +   unwind frame info FS.  If ADDR is signed, we do address authentication on it

> +   using CFA of current frame.  */

> +


All the functions in this HEADER file should be marked inline.

> +static void *

> +aarch64_post_extract_frame_addr (struct _Unwind_Context *context,

> +				 _Unwind_FrameState *fs, void *addr)

> +{

> +  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)

> +    {

> +      _Unwind_Word salt = (_Unwind_Word) context->cfa;

> +      return __builtin_aarch64_autia1716 (addr, salt);

> +    }

> +  else

> +    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 void *

> +aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,

> +				   struct _Unwind_Context *target

> +				   ATTRIBUTE_UNUSED,

> +				   void *handler_addr)

> +{

> +  if (current->flags & RA_A_SIGNED_BIT)

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

> +

> +static void

> +aarch64_frob_update_context (struct _Unwind_Context *context,

> +			     _Unwind_FrameState *fs)

> +{

> +  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_A_SIGNED_BIT;

> +

> +  return;

> +}

> +

> +#endif /* defined AARCH64_UNWIND_H */

> diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h

> index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644

> --- a/libgcc/config/aarch64/linux-unwind.h

> +++ b/libgcc/config/aarch64/linux-unwind.h

> @@ -24,6 +24,7 @@

>  

>  #include <signal.h>

>  #include <sys/ucontext.h>

> +#include "aarch64-unwind.h"

>  

>  

>  /* Since insns are always stored LE, on a BE system the opcodes will

> 


R.
Jiong Wang Jan. 19, 2017, 2:46 p.m. UTC | #3
Thanks for the review.

On 19/01/17 14:18, Richard Earnshaw (lists) wrote:
>

>>

>>

>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

>> index 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2 100644

>> --- a/libgcc/unwind-dw2.c

>> +++ b/libgcc/unwind-dw2.c

>> @@ -136,6 +136,8 @@ struct _Unwind_Context

>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>>    /* Context which has version/args_size/by_value fields.  */

>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

>> +  /* Bit reserved on AArch64, return address has been signed with A key.  */

>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

>

> Why is this here?   It appears to only be used within the

> AArch64-specific header file.


I was putting it here so that when we allocate the next general purpose bit, we
know clearly that bit 3 is allocated to AArch64 already, and the new general bit
needs to go to the next one.  This can avoid bit collision.

>

>> ...

>>

>> +/* Frob exception handler's address kept in TARGET before installing into

>> +   CURRENT context.  */

>> +

>> +static void *

>> +uw_frob_return_addr (struct _Unwind_Context *current,

>> +                 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;

>> +}

>> +

>

> I think this function should be marked inline.  The optimizers would

> probably inline it anyway, but it seems wrong for us to rely on that.


Thanks, fixed.

Does the updated patch looks OK to you know?

libgcc/

2017-01-19  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/aarch64-unwind.h: New file.
         (DWARF_REGNUM_AARCH64_RA_STATE): Define.
         (MD_POST_EXTRACT_ROOT_ADDR): Define.
         (MD_POST_EXTRACT_FRAME_ADDR): Define.
         (MD_POST_FROB_EH_HANDLER_ADDR): Define.
         (MD_FROB_UPDATE_CONTEXT): Define.
         (aarch64_post_extract_frame_addr): New function.
         (aarch64_post_frob_eh_handler_addr): New function.
         (aarch64_frob_update_context): New function.
         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h
         * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*):
         Initialize md_unwind_header to include aarch64-unwind.h.
         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".
         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__.
         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.
         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.
         (uw_frob_return_addr): New function.
         (_Unwind_DebugHook): Use uw_frob_return_addr.diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
new file mode 100644
index 0000000000000000000000000000000000000000..a43d965b358f3e830b85fc42c7bceacf7d41a671
--- /dev/null
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+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
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_UNWIND_H
+#define AARCH64_UNWIND_H
+
+#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_FROB_UPDATE_CONTEXT(context, fs) \
+  aarch64_frob_update_context (context, fs)
+
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
+   unwind frame info FS.  If ADDR is signed, we do address authentication on it
+   using CFA of current frame.  */
+
+static inline void *
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
+				 _Unwind_FrameState *fs, void *addr)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    {
+      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      return __builtin_aarch64_autia1716 (addr, salt);
+    }
+  else
+    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_A_SIGNED_BIT)
+    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.  */
+
+static inline void
+aarch64_frob_update_context (struct _Unwind_Context *context,
+			     _Unwind_FrameState *fs)
+{
+  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_A_SIGNED_BIT;
+
+  return;
+}
+
+#endif /* defined AARCH64_UNWIND_H */
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -24,6 +24,7 @@
 
 #include <signal.h>
 #include <sys/ucontext.h>
+#include "aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace15d53f4cb0c6681717012d906a6d47..f2e5ce832190ff3ee69f31e3b6d44b68395f68df 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,6 +136,8 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
+#ifdef __aarch64__
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
 	  /* ??? Hardcoded for SPARC register window configuration.  */
 	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
 	    for (reg = 16; reg < 32; ++reg)
@@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
 		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
 		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
 	      }
+#endif
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1513,10 +1521,15 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* 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));
+    {
+      /* 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_FRAME_ADDR (context, fs, context->ra);
+#endif
+    }
 }
 
 static void
@@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
+#endif
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1602,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
+#endif
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1608,6 +1627,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 #endif
 }
 
+/* Frob exception handler's address kept in TARGET before installing into
+   CURRENT context.  */
+
+static inline void *
+uw_frob_return_addr (struct _Unwind_Context *current,
+		     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.  */
@@ -1616,7 +1649,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\

Richard Earnshaw (lists) Jan. 19, 2017, 7:02 p.m. UTC | #4
On 19/01/17 14:46, Jiong Wang wrote:
> Thanks for the review.

> 

> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:

>>

>>>

>>>

>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

>>> index

>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2

>>> 100644

>>> --- a/libgcc/unwind-dw2.c

>>> +++ b/libgcc/unwind-dw2.c

>>> @@ -136,6 +136,8 @@ struct _Unwind_Context

>>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>>>    /* Context which has version/args_size/by_value fields.  */

>>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

>>> +  /* Bit reserved on AArch64, return address has been signed with A

>>> key.  */

>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

>>

>> Why is this here?   It appears to only be used within the

>> AArch64-specific header file.

> 

> I was putting it here so that when we allocate the next general purpose

> bit, we

> know clearly that bit 3 is allocated to AArch64 already, and the new

> general bit

> needs to go to the next one.  This can avoid bit collision.

> 


Fair enough.
>>

>>> ...

>>>

>>> +/* Frob exception handler's address kept in TARGET before installing

>>> into

>>> +   CURRENT context.  */

>>> +

>>> +static void *

>>> +uw_frob_return_addr (struct _Unwind_Context *current,

>>> +                 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;

>>> +}

>>> +

>>

>> I think this function should be marked inline.  The optimizers would

>> probably inline it anyway, but it seems wrong for us to rely on that.

> 

> Thanks, fixed.

> 

> Does the updated patch looks OK to you know?

> 

> libgcc/

> 

> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>

> 

>         * config/aarch64/aarch64-unwind.h: New file.

>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.

>         (MD_POST_EXTRACT_ROOT_ADDR): Define.

>         (MD_POST_EXTRACT_FRAME_ADDR): Define.

>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.

>         (MD_FROB_UPDATE_CONTEXT): Define.

>         (aarch64_post_extract_frame_addr): New function.

>         (aarch64_post_frob_eh_handler_addr): New function.

>         (aarch64_frob_update_context): New function.

>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h

>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,

> aarch64*-*-freebsd*):

>         Initialize md_unwind_header to include aarch64-unwind.h.

>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".

>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for

> __aarch64__.

>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.

>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.

>         (uw_frob_return_addr): New function.

>         (_Unwind_DebugHook): Use uw_frob_return_addr.

> 


OK.

R.
Christophe Lyon Jan. 20, 2017, 8:41 a.m. UTC | #5
Hi Jiong,

On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> Thanks for the review.

>

> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:

>>

>>

>>>

>>>

>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

>>> index

>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2

>>> 100644

>>> --- a/libgcc/unwind-dw2.c

>>> +++ b/libgcc/unwind-dw2.c

>>> @@ -136,6 +136,8 @@ struct _Unwind_Context

>>>  #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>>>    /* Context which has version/args_size/by_value fields.  */

>>>  #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

>>> +  /* Bit reserved on AArch64, return address has been signed with A key.

>>> */

>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

>>

>>

>> Why is this here?   It appears to only be used within the

>> AArch64-specific header file.

>

>

> I was putting it here so that when we allocate the next general purpose bit,

> we

> know clearly that bit 3 is allocated to AArch64 already, and the new general

> bit

> needs to go to the next one.  This can avoid bit collision.

>

>>

>>> ...

>>>

>>> +/* Frob exception handler's address kept in TARGET before installing

>>> into

>>> +   CURRENT context.  */

>>> +

>>> +static void *

>>> +uw_frob_return_addr (struct _Unwind_Context *current,

>>> +                 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;

>>> +}

>>> +

>>

>>

>> I think this function should be marked inline.  The optimizers would

>> probably inline it anyway, but it seems wrong for us to rely on that.

>

>

> Thanks, fixed.

>

> Does the updated patch looks OK to you know?

>

> libgcc/

>

> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>

>

>

>         * config/aarch64/aarch64-unwind.h: New file.

>         (DWARF_REGNUM_AARCH64_RA_STATE): Define.

>         (MD_POST_EXTRACT_ROOT_ADDR): Define.

>         (MD_POST_EXTRACT_FRAME_ADDR): Define.

>         (MD_POST_FROB_EH_HANDLER_ADDR): Define.

>         (MD_FROB_UPDATE_CONTEXT): Define.

>         (aarch64_post_extract_frame_addr): New function.

>         (aarch64_post_frob_eh_handler_addr): New function.

>         (aarch64_frob_update_context): New function.

>         * config/aarch64/linux-unwind.h: Include aarch64-unwind.h

>         * config.host (aarch64*-*-elf, aarch64*-*-rtems*,

> aarch64*-*-freebsd*):

>         Initialize md_unwind_header to include aarch64-unwind.h.

>         * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".

>         (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for

> __aarch64__.

>         (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.

>         (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.

>         (uw_frob_return_addr): New function.

>         (_Unwind_DebugHook): Use uw_frob_return_addr.

>


Since you committed this (r244673), GCC fails to build for AArch64:
/tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:
In function 'execute_cfa_program':
/tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:
error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this
function)
    fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Christophe
Jiong Wang Jan. 20, 2017, 9:44 a.m. UTC | #6
On 20/01/17 08:41, Christophe Lyon wrote:
> Hi Jiong,

>

> On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:

>> Thanks for the review.

>>

>> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:

>>>

>>>>

>>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

>>>> index

>>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2

>>>> 100644

>>>> --- a/libgcc/unwind-dw2.c

>>>> +++ b/libgcc/unwind-dw2.c

>>>> @@ -136,6 +136,8 @@ struct _Unwind_Context

>>>>   #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>>>>     /* Context which has version/args_size/by_value fields.  */

>>>>   #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

>>>> +  /* Bit reserved on AArch64, return address has been signed with A key.

>>>> */

>>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

>>>

>>> Why is this here?   It appears to only be used within the

>>> AArch64-specific header file.

>>

>> I was putting it here so that when we allocate the next general purpose bit,

>> we

>> know clearly that bit 3 is allocated to AArch64 already, and the new general

>> bit

>> needs to go to the next one.  This can avoid bit collision.

>>

>>>> ...

>>>>

>>>> +/* Frob exception handler's address kept in TARGET before installing

>>>> into

>>>> +   CURRENT context.  */

>>>> +

>>>> +static void *

>>>> +uw_frob_return_addr (struct _Unwind_Context *current,

>>>> +                 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;

>>>> +}

>>>> +

>>>

>>> I think this function should be marked inline.  The optimizers would

>>> probably inline it anyway, but it seems wrong for us to rely on that.

>>

>> Thanks, fixed.

>>

>> Does the updated patch looks OK to you know?

>>

>> libgcc/

>>

>> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>

>>

>>

>>          * config/aarch64/aarch64-unwind.h: New file.

>>          (DWARF_REGNUM_AARCH64_RA_STATE): Define.

>>          (MD_POST_EXTRACT_ROOT_ADDR): Define.

>>          (MD_POST_EXTRACT_FRAME_ADDR): Define.

>>          (MD_POST_FROB_EH_HANDLER_ADDR): Define.

>>          (MD_FROB_UPDATE_CONTEXT): Define.

>>          (aarch64_post_extract_frame_addr): New function.

>>          (aarch64_post_frob_eh_handler_addr): New function.

>>          (aarch64_frob_update_context): New function.

>>          * config/aarch64/linux-unwind.h: Include aarch64-unwind.h

>>          * config.host (aarch64*-*-elf, aarch64*-*-rtems*,

>> aarch64*-*-freebsd*):

>>          Initialize md_unwind_header to include aarch64-unwind.h.

>>          * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT".

>>          (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for

>> __aarch64__.

>>          (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.

>>          (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.

>>          (uw_frob_return_addr): New function.

>>          (_Unwind_DebugHook): Use uw_frob_return_addr.

>>

> Since you committed this (r244673), GCC fails to build for AArch64:

> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:

> In function 'execute_cfa_program':

> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:

> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

> function)

>      fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Hi Christophe, could you please confirm you svn revision please?

I do have done bootstrap and regression on both x86 and aarch64 before 
commit this patch.  I had forgotten to "svn add" one header file, but 
add it later.

Thanks.

> Christophe
Christophe Lyon Jan. 20, 2017, 10:11 a.m. UTC | #7
On 20 January 2017 at 10:44, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>

>

> On 20/01/17 08:41, Christophe Lyon wrote:

>>

>> Hi Jiong,

>>

>> On 19 January 2017 at 15:46, Jiong Wang <jiong.wang@foss.arm.com> wrote:

>>>

>>> Thanks for the review.

>>>

>>> On 19/01/17 14:18, Richard Earnshaw (lists) wrote:

>>>>

>>>>

>>>>>

>>>>> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c

>>>>> index

>>>>>

>>>>> 8085a42ace15d53f4cb0c6681717012d906a6d47..cf640135275deb76b820f8209fa51eacfd64c4a2

>>>>> 100644

>>>>> --- a/libgcc/unwind-dw2.c

>>>>> +++ b/libgcc/unwind-dw2.c

>>>>> @@ -136,6 +136,8 @@ struct _Unwind_Context

>>>>>   #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)

>>>>>     /* Context which has version/args_size/by_value fields.  */

>>>>>   #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)

>>>>> +  /* Bit reserved on AArch64, return address has been signed with A

>>>>> key.

>>>>> */

>>>>> +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)

>>>>

>>>>

>>>> Why is this here?   It appears to only be used within the

>>>> AArch64-specific header file.

>>>

>>>

>>> I was putting it here so that when we allocate the next general purpose

>>> bit,

>>> we

>>> know clearly that bit 3 is allocated to AArch64 already, and the new

>>> general

>>> bit

>>> needs to go to the next one.  This can avoid bit collision.

>>>

>>>>> ...

>>>>>

>>>>> +/* Frob exception handler's address kept in TARGET before installing

>>>>> into

>>>>> +   CURRENT context.  */

>>>>> +

>>>>> +static void *

>>>>> +uw_frob_return_addr (struct _Unwind_Context *current,

>>>>> +                 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;

>>>>> +}

>>>>> +

>>>>

>>>>

>>>> I think this function should be marked inline.  The optimizers would

>>>> probably inline it anyway, but it seems wrong for us to rely on that.

>>>

>>>

>>> Thanks, fixed.

>>>

>>> Does the updated patch looks OK to you know?

>>>

>>> libgcc/

>>>

>>> 2017-01-19  Jiong Wang  <jiong.wang@arm.com>

>>>

>>>

>>>          * config/aarch64/aarch64-unwind.h: New file.

>>>          (DWARF_REGNUM_AARCH64_RA_STATE): Define.

>>>          (MD_POST_EXTRACT_ROOT_ADDR): Define.

>>>          (MD_POST_EXTRACT_FRAME_ADDR): Define.

>>>          (MD_POST_FROB_EH_HANDLER_ADDR): Define.

>>>          (MD_FROB_UPDATE_CONTEXT): Define.

>>>          (aarch64_post_extract_frame_addr): New function.

>>>          (aarch64_post_frob_eh_handler_addr): New function.

>>>          (aarch64_frob_update_context): New function.

>>>          * config/aarch64/linux-unwind.h: Include aarch64-unwind.h

>>>          * config.host (aarch64*-*-elf, aarch64*-*-rtems*,

>>> aarch64*-*-freebsd*):

>>>          Initialize md_unwind_header to include aarch64-unwind.h.

>>>          * unwind-dw2.c (struct _Unwind_Context): Define

>>> "RA_A_SIGNED_BIT".

>>>          (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for

>>> __aarch64__.

>>>          (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR.

>>>          (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR.

>>>          (uw_frob_return_addr): New function.

>>>          (_Unwind_DebugHook): Use uw_frob_return_addr.

>>>

>> Since you committed this (r244673), GCC fails to build for AArch64:

>>

>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:

>> In function 'execute_cfa_program':

>>

>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:

>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>> function)

>>      fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>

>

> Hi Christophe, could you please confirm you svn revision please?

>

> I do have done bootstrap and regression on both x86 and aarch64 before

> commit this patch.  I had forgotten to "svn add" one header file, but add it

> later.

>


The failures started with r244673, and are still present with r244687.
When did you add the missing file?

> Thanks.

>

>> Christophe

>

>
Jiong Wang Jan. 20, 2017, 10:18 a.m. UTC | #8
On 20/01/17 10:11, Christophe Lyon wrote:
>

>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:

>>> In function 'execute_cfa_program':

>>>

>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:

>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>>> function)

>>>       fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>>

>> Hi Christophe, could you please confirm you svn revision please?

>>

>> I do have done bootstrap and regression on both x86 and aarch64 before

>> commit this patch.  I had forgotten to "svn add" one header file, but add it

>> later.

>>

> The failures started with r244673, and are still present with r244687.

> When did you add the missing file?


It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  
so should have been included in your code.  The faliure looks strange to 
me then,  I will svn up and re-start a fresh bootstrap on AArch64.

>

>> Thanks.

>>

>>> Christophe

>>
Christophe Lyon Jan. 20, 2017, 10:30 a.m. UTC | #9
On 20 January 2017 at 11:18, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>

>

> On 20/01/17 10:11, Christophe Lyon wrote:

>>

>>

>>>>

>>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:

>>>> In function 'execute_cfa_program':

>>>>

>>>>

>>>> /tmp/8132498_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libgcc/unwind-dw2.c:1193:17:

>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>>>> function)

>>>>       fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>>>                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>>>

>>>

>>> Hi Christophe, could you please confirm you svn revision please?

>>>

>>> I do have done bootstrap and regression on both x86 and aarch64 before

>>> commit this patch.  I had forgotten to "svn add" one header file, but add

>>> it

>>> later.

>>>

>> The failures started with r244673, and are still present with r244687.

>> When did you add the missing file?

>

>

> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so

> should have been included in your code.  The faliure looks strange to me

> then,  I will svn up and re-start a fresh bootstrap on AArch64.

>


The file is present in my git clone.
I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,
but it shouldn't matter.

>>

>>> Thanks.

>>>

>>>> Christophe

>>>

>>>

>
Jiong Wang Jan. 20, 2017, 11:54 a.m. UTC | #10
On 20/01/17 10:30, Christophe Lyon wrote:
>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>>>>> function)

>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>>>>

>>>> Hi Christophe, could you please confirm you svn revision please?

>>>>

>>>> I do have done bootstrap and regression on both x86 and aarch64 before

>>>> commit this patch.  I had forgotten to "svn add" one header file, but add

>>>> it

>>>> later.

>>>>

>>> The failures started with r244673, and are still present with r244687.

>>> When did you add the missing file?

>>

>> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so

>> should have been included in your code.  The faliure looks strange to me

>> then,  I will svn up and re-start a fresh bootstrap on AArch64.

>>

> The file is present in my git clone.

> I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,

> but it shouldn't matter.


Hi Christophe,

   Thanks, I reproduced this on cross linux environment, the reason is the header file is not included because of the inhabit_libc guard, while the unwinder header file should always be included.

    I will committed the attached patch as obvious, once I finished a fresh bootstrap, cross elf, cross linux.

    Thanks.

libgcc/

2017-01-20  Jiong Wang  <jiong.wang@arm.com>

         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index a8fa1d5..70e5a8a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -20,11 +20,13 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+/* Always include AArch64 unwinder header file.  */
+#include "config/aarch64/aarch64-unwind.h"
+
 #ifndef inhibit_libc
 
 #include <signal.h>
 #include <sys/ucontext.h>
-#include "config/aarch64/aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will

Richard Earnshaw (lists) Jan. 20, 2017, 12:07 p.m. UTC | #11
On 20/01/17 11:54, Jiong Wang wrote:
> On 20/01/17 10:30, Christophe Lyon wrote:

>>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>>>>>> function)

>>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>>>>>

>>>>> Hi Christophe, could you please confirm you svn revision please?

>>>>>

>>>>> I do have done bootstrap and regression on both x86 and aarch64 before

>>>>> commit this patch.  I had forgotten to "svn add" one header file,

>>>>> but add

>>>>> it

>>>>> later.

>>>>>

>>>> The failures started with r244673, and are still present with r244687.

>>>> When did you add the missing file?

>>>

>>> It was r244674,

>>> https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so

>>> should have been included in your code.  The faliure looks strange to me

>>> then,  I will svn up and re-start a fresh bootstrap on AArch64.

>>>

>> The file is present in my git clone.

>> I'm not bootstrapping on AArch64, I'm building a cross-compiler on

>> x86_64,

>> but it shouldn't matter.

> 

> Hi Christophe,

> 

>   Thanks, I reproduced this on cross linux environment, the reason is

> the header file is not included because of the inhabit_libc guard, while

> the unwinder header file should always be included.

> 

>    I will committed the attached patch as obvious, once I finished a

> fresh bootstrap, cross elf, cross linux.

> 


If this survives a cross-build, please just commit it.  It's very
unlikely that a native build will throw up any problems.

R.

>    Thanks.

> 

> libgcc/

> 

> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>

> 

>         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.

> 

> 

> 

> k.patch

> 

> 

> diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h

> index a8fa1d5..70e5a8a 100644

> --- a/libgcc/config/aarch64/linux-unwind.h

> +++ b/libgcc/config/aarch64/linux-unwind.h

> @@ -20,11 +20,13 @@

>     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see

>     <http://www.gnu.org/licenses/>.  */

>  

> +/* Always include AArch64 unwinder header file.  */

> +#include "config/aarch64/aarch64-unwind.h"

> +

>  #ifndef inhibit_libc

>  

>  #include <signal.h>

>  #include <sys/ucontext.h>

> -#include "config/aarch64/aarch64-unwind.h"

>  

>  

>  /* Since insns are always stored LE, on a BE system the opcodes will

>
Christophe Lyon Jan. 20, 2017, 2:30 p.m. UTC | #12
On 20 January 2017 at 12:54, Jiong Wang <jiong.wang@foss.arm.com> wrote:
> On 20/01/17 10:30, Christophe Lyon wrote:

>>>>>>

>>>>>> error: 'DWARF_REGNUM_AARCH64_RA_STATE' undeclared (first use in this

>>>>>> function)

>>>>>>        fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;

>>>>>>                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>>>>>

>>>>>

>>>>> Hi Christophe, could you please confirm you svn revision please?

>>>>>

>>>>> I do have done bootstrap and regression on both x86 and aarch64 before

>>>>> commit this patch.  I had forgotten to "svn add" one header file, but

>>>>> add

>>>>> it

>>>>> later.

>>>>>

>>>> The failures started with r244673, and are still present with r244687.

>>>> When did you add the missing file?

>>>

>>>

>>> It was r244674, https://gcc.gnu.org/ml/gcc-cvs/2017-01/msg00689.html,  so

>>> should have been included in your code.  The faliure looks strange to me

>>> then,  I will svn up and re-start a fresh bootstrap on AArch64.

>>>

>> The file is present in my git clone.

>> I'm not bootstrapping on AArch64, I'm building a cross-compiler on x86_64,

>> but it shouldn't matter.

>

>

> Hi Christophe,

>

>   Thanks, I reproduced this on cross linux environment, the reason is the

> header file is not included because of the inhabit_libc guard, while the

> unwinder header file should always be included.

>

>    I will committed the attached patch as obvious, once I finished a fresh

> bootstrap, cross elf, cross linux.

>


After you committed this (r244710), my cross build for aarch64-linux-gnu
now passes.

I'm now left with the build failure reported by Andrew on aarch64(_be)-none-elf.

Thanks for the fix.

Christophe.

>    Thanks.

>

> libgcc/

>

> 2017-01-20  Jiong Wang  <jiong.wang@arm.com>

>

>         * config/aarch64/linux-unwind.h: Always include aarch64-unwind.h.

>

>
diff mbox

Patch

diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 8085a42ace15d53f4cb0c6681717012d906a6d47..35010a4065bb83f706701cb05392193f0ffa1f11 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -136,6 +136,8 @@  struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A key.  */
+#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -1185,6 +1187,11 @@  execute_cfa_program (const unsigned char *insn_ptr,
 	  break;
 
 	case DW_CFA_GNU_window_save:
+#ifdef __aarch64__
+	  /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+	     return address signing status.  */
+	  fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
 	  /* ??? Hardcoded for SPARC register window configuration.  */
 	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
 	    for (reg = 16; reg < 32; ++reg)
@@ -1192,6 +1199,7 @@  execute_cfa_program (const unsigned char *insn_ptr,
 		fs->regs.reg[reg].how = REG_SAVED_OFFSET;
 		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
 	      }
+#endif
 	  break;
 
 	case DW_CFA_GNU_args_size:
@@ -1513,10 +1521,15 @@  uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* 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));
+    {
+      /* 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_FRAME_ADDR (context, fs, context->ra);
+#endif
+    }
 }
 
 static void
@@ -1550,6 +1563,9 @@  uw_init_context_1 (struct _Unwind_Context *context,
 		   void *outer_cfa, void *outer_ra)
 {
   void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
+#endif
   _Unwind_FrameState fs;
   _Unwind_SpTmp sp_slot;
   _Unwind_Reason_Code code;
@@ -1586,6 +1602,12 @@  uw_init_context_1 (struct _Unwind_Context *context,
      initialization context, then we can't see it in the given
      call frame data.  So have the initialization context tell us.  */
   context->ra = __builtin_extract_return_addr (outer_ra);
+#ifdef MD_POST_EXTRACT_ROOT_ADDR
+  context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
+#endif
+#ifdef MD_POST_INIT_CONTEXT
+  MD_POST_INIT_CONTEXT (context, &fs);
+#endif
 }
 
 static void _Unwind_DebugHook (void *, void *)
@@ -1608,6 +1630,20 @@  _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 #endif
 }
 
+/* Frob exception handler's address kept in TARGET before installing into
+   CURRENT context.  */
+
+static void *
+uw_frob_return_addr (struct _Unwind_Context *current,
+		     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.  */
@@ -1616,7 +1652,7 @@  _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
   do									\
     {									\
       long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
+      void *handler = uw_frob_return_addr ((CURRENT), (TARGET));	\
       _Unwind_DebugHook ((TARGET)->cfa, handler);			\
       __builtin_eh_return (offset, handler);				\
     }									\
diff --git a/libgcc/config.host b/libgcc/config.host
index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -331,11 +331,13 @@  aarch64*-*-elf | aarch64*-*-rtems*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd20feb0ce061c82c9134609438c84bc161670f9
--- /dev/null
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -0,0 +1,87 @@ 
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+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
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_UNWIND_H
+#define AARCH64_UNWIND_H
+
+#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_POST_INIT_CONTEXT(context, fs) \
+  aarch64_post_init_context (context, fs)
+
+/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
+   unwind frame info FS.  If ADDR is signed, we do address authentication on it
+   using CFA of current frame.  */
+
+static void *
+aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
+				 _Unwind_FrameState *fs, void *addr)
+{
+  if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
+    {
+      _Unwind_Word salt = (_Unwind_Word) context->cfa;
+      return __builtin_aarch64_autia1716 (addr, salt);
+    }
+  else
+    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 void *
+aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
+				   struct _Unwind_Context *target
+				   ATTRIBUTE_UNUSED,
+				   void *handler_addr)
+{
+  if (current->flags & RA_A_SIGNED_BIT)
+    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.  */
+
+static void
+aarch64_post_init_context (struct _Unwind_Context *context,
+			   _Unwind_FrameState *fs)
+{
+  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_A_SIGNED_BIT;
+
+  return;
+}
+
+#endif /* defined AARCH64_UNWIND_H */
diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h
index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644
--- a/libgcc/config/aarch64/linux-unwind.h
+++ b/libgcc/config/aarch64/linux-unwind.h
@@ -24,6 +24,7 @@ 
 
 #include <signal.h>
 #include <sys/ucontext.h>
+#include "aarch64-unwind.h"
 
 
 /* Since insns are always stored LE, on a BE system the opcodes will