aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2023-04-26 14:28:32 +0100
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2023-11-27 15:52:48 +0000
commit426fddcbdad6746fe70e031f707fb07f55dfb405 (patch)
tree6f85235a7ed39cc6db684cee66bc635bfa3c681e /libcpp
parentf723f72061a7c76fbd6d44adbfff8cb3ed7391d5 (diff)
downloadgcc-426fddcbdad6746fe70e031f707fb07f55dfb405.zip
gcc-426fddcbdad6746fe70e031f707fb07f55dfb405.tar.gz
gcc-426fddcbdad6746fe70e031f707fb07f55dfb405.tar.bz2
aarch64: Use br instead of ret for eh_return
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.
Diffstat (limited to 'libcpp')
0 files changed, 0 insertions, 0 deletions