diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2020-06-02 16:44:41 +0100 |
---|---|---|
committer | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2020-07-13 13:49:20 +0100 |
commit | 463a54e5d4956143f81c1f23b91cbd2d93855741 (patch) | |
tree | ac8776c9326fc4198a1c32126981329a3e9a1a0d | |
parent | 5834e96a08fd8b86a42428f38a95903d2f1de202 (diff) | |
download | gcc-463a54e5d4956143f81c1f23b91cbd2d93855741.zip gcc-463a54e5d4956143f81c1f23b91cbd2d93855741.tar.gz gcc-463a54e5d4956143f81c1f23b91cbd2d93855741.tar.bz2 |
aarch64: fix return address access with pac [PR94891][PR94791]
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.
2020-07-13 Szabolcs Nagy <szabolcs.nagy@arm.com>
gcc/ChangeLog:
PR target/94891
PR target/94791
* 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.
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 20 | ||||
-rw-r--r-- | 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 865ad67..839f801 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 17dbe67..26cbeff 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10825,6 +10825,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. */ @@ -10833,7 +10851,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 (); } static void diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 4534e37..d3e89d1 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -1133,7 +1133,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); \ } |