diff options
author | Ryan Prichard <rprichard@google.com> | 2022-03-15 01:43:50 +0300 |
---|---|---|
committer | Ryan Prichard <rprichard@google.com> | 2022-03-15 01:44:35 +0300 |
commit | 659029302dfb16a29219f931f66e9ad483ad1445 (patch) | |
tree | e35fe546a94cb669d25e58c0f7681400d54d6c48 /libcxxabi/src | |
parent | 56e7d6bd444cef8d879adc35dcf461cb4d2ed6d5 (diff) |
[ARM] __cxa_end_cleanup: avoid clobbering r4
The fix for D111703 clobbered r4 both to:
- Save/restore the original lr.
- Load the address of _Unwind_Resume for LIBCXXABI_BAREMETAL.
This patch saves and restores lr without clobbering any extra
registers.
For LIBCXXABI_BAREMETAL, it is still necessary to clobber one extra
register to hold the address of _Unwind_Resume, but it seems better to
use ip/r12 (intended for linker veneers/trampolines) than r4 for this
purpose.
The function also clobbers r0 for the _Unwind_Resume function's
parameter, but that is unavoidable.
Reviewed By: danielkiss, logan, MaskRay
Differential Revision: https://reviews.llvm.org/D121432
Diffstat (limited to 'libcxxabi/src')
-rw-r--r-- | libcxxabi/src/cxa_exception.cpp | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 36388d50dad2..059d75ca2ab4 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -341,10 +341,11 @@ unwinding with _Unwind_Resume. According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any register, thus we have to write this function in assembly so that we can save {r1, r2, r3}. We don't have to save r0 because it is the return value and the -first argument to _Unwind_Resume(). In addition, we are saving lr in order to -align the stack to 16 bytes and lr will be used to identify the caller and its -frame information. _Unwind_Resume never return and we need to keep the original -lr so just branch to it. +first argument to _Unwind_Resume(). The function also saves/restores r4 to +keep the stack aligned and to provide a temp register. _Unwind_Resume never +returns and we need to keep the original lr so just branch to it. When +targeting bare metal, the function also clobbers ip/r12 to hold the address of +_Unwind_Resume, which may be too far away for an ordinary branch. */ __attribute__((used)) static _Unwind_Exception * __cxa_end_cleanup_impl() @@ -381,15 +382,19 @@ asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n" #if defined(__ARM_FEATURE_BTI_DEFAULT) " bti\n" #endif - " push {r1, r2, r3, lr}\n" + " push {r1, r2, r3, r4}\n" + " mov r4, lr\n" " bl __cxa_end_cleanup_impl\n" - " pop {r1, r2, r3, r4}\n" " mov lr, r4\n" #if defined(LIBCXXABI_BAREMETAL) " ldr r4, =_Unwind_Resume\n" - " bx r4\n" + " mov ip, r4\n" +#endif + " pop {r1, r2, r3, r4}\n" +#if defined(LIBCXXABI_BAREMETAL) + " bx ip\n" #else - " b _Unwind_Resume\n" + " b _Unwind_Resume\n" #endif " .popsection"); #endif // defined(_LIBCXXABI_ARM_EHABI) |