diff options
author | Alexandre Oliva <oliva@adacore.com> | 2020-02-06 03:59:45 -0300 |
---|---|---|
committer | Alexandre Oliva <oliva@gnu.org> | 2020-02-06 03:59:45 -0300 |
commit | 006eeaa819d2a58395ef448807025730939d165d (patch) | |
tree | d005df5fd0545457831114726f9330f059cb9496 /gcc/ada | |
parent | 3774c0b934c4fe13c2d527b757002bdea09f7039 (diff) | |
download | gcc-006eeaa819d2a58395ef448807025730939d165d.zip gcc-006eeaa819d2a58395ef448807025730939d165d.tar.gz gcc-006eeaa819d2a58395ef448807025730939d165d.tar.bz2 |
Initialize barrier_cache for ARM EH ABI compliance
The ARM Exception Handling ABI requires personality functions in
phase1 to initialize barrier_cache before returning
_URC_HANDLER_FOUND, and we don't.
Although our own ARM personality function does not use barrier_cache
at all, other languages' ARM personality functions, during phase2, are
allowed and expected to test barrier_cache.sp to check whether the
handler frame was reached, which implies that personality functions is
in charge of the frame, and the remaining fields of barrier_cache hold
whatever values it put there in phase1.
Since we did not set barrier_cache.sp, an earlier exception, already
handled by a non-Ada handler and then released, may have its storage
reused for a new exception, that phase1 matches to an Ada frame, but
if that leaves barrier_cache.sp alone, the phase2 personality function
that handled the earlier exception, upon reaching the frame that
handled the earlier exception, may believe the information in
barrier_cache applies to the current exception. The C++ personality
function, for example, would take the information in the barrier_cache
and end up activating the handler that handled the earlier exception:
try {
throw 1;
} catch (int i) {
std::cout << "caught " << i << " by c++" << std::endl;
}
raise_ada_exception (); // might loop back to the handler above
for gcc/ada/ChangeLog
* raise-gcc.c (personality_body) [__ARM_EABI_UNWINDER__]:
Initialize barrier_cache.sp when ending phase1.
Diffstat (limited to 'gcc/ada')
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/raise-gcc.c | 10 |
2 files changed, 15 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7601fe2..64b2572 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2020-02-06 Alexandre Oliva <oliva@adacore.com> + + * raise-gcc.c (personality_body) [__ARM_EABI_UNWINDER__]: + Initialize barrier_cache.sp when ending phase1. + 2020-01-04 Eric Botcazou <ebotcazou@adacore.com> * gnatvsn.ads: Bump copyright year. diff --git a/gcc/ada/raise-gcc.c b/gcc/ada/raise-gcc.c index 1ba8af1..3b6c21f 100644 --- a/gcc/ada/raise-gcc.c +++ b/gcc/ada/raise-gcc.c @@ -1211,6 +1211,16 @@ personality_body (_Unwind_Action uw_phases, } else { +#ifdef __ARM_EABI_UNWINDER__ + /* Though we do not use this field ourselves, initializing + it is required by the ARM EH ABI before a personality + function in phase1 returns _URC_HANDLER_FOUND, so that + any personality function can use it in phase2 to test + whether the handler frame was reached. */ + uw_exception->barrier_cache.sp + = _Unwind_GetGR (uw_context, UNWIND_STACK_REG); +#endif + #ifndef CERT /* Trigger the appropriate notification routines before the second phase starts, when the stack is still intact. First install what |