diff options
author | Iain Buclaw <ibuclaw@gcc.gnu.org> | 2018-11-26 17:27:34 +0000 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gcc.gnu.org> | 2018-11-26 17:27:34 +0000 |
commit | e20145f12ca3ecd913f28619d5f1b04ee91a18e8 (patch) | |
tree | 04572dc92a8c39a8c2aa204bc4e855af4590b308 /libphobos | |
parent | ef6e6914c8245ca24dae952bc054ae2328e751ab (diff) | |
download | gcc-e20145f12ca3ecd913f28619d5f1b04ee91a18e8.zip gcc-e20145f12ca3ecd913f28619d5f1b04ee91a18e8.tar.gz gcc-e20145f12ca3ecd913f28619d5f1b04ee91a18e8.tar.bz2 |
libphobos: Fix backtraces in Fibers on AArch64.
When throwing an Exception in the Fiber the backtrace generation
crashes. This happens because backtrace does not func the stack bottom.
Using '.cfi_undefined x30' tells the debug info that the value in the lr
is unknown, which seems to be the nicest way to stop the unwinder.
Setting x30 to 0 is another option, however it still creates one invalid
frame in gdb, so the .cfi variant is used here instead.
Backport from upstream druntime 2.083.
Reviewed-on: https://github.com/dlang/druntime/pull/2308
From-SVN: r266470
Diffstat (limited to 'libphobos')
-rw-r--r-- | libphobos/libdruntime/core/thread.d | 38 | ||||
-rw-r--r-- | libphobos/libdruntime/core/threadasm.S | 24 |
2 files changed, 61 insertions, 1 deletions
diff --git a/libphobos/libdruntime/core/thread.d b/libphobos/libdruntime/core/thread.d index b524471..ff15d06 100644 --- a/libphobos/libdruntime/core/thread.d +++ b/libphobos/libdruntime/core/thread.d @@ -3582,6 +3582,15 @@ private version = AsmExternal; } } + else version (AArch64) + { + version (Posix) + { + version = AsmAArch64_Posix; + version = AsmExternal; + version = AlignFiberStackTo16Byte; + } + } else version (ARM) { version (Posix) @@ -3673,7 +3682,11 @@ private // Look above the definition of 'class Fiber' for some information about the implementation of this routine version (AsmExternal) - extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc; + { + extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc; + version (AArch64) + extern (C) void fiber_trampoline() nothrow; + } else extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc { @@ -4909,6 +4922,29 @@ private: pstack -= ABOVE; *cast(size_t*)(pstack - SZ_RA) = cast(size_t)&fiber_entryPoint; } + else version (AsmAArch64_Posix) + { + // Like others, FP registers and return address (lr) are kept + // below the saved stack top (tstack) to hide from GC scanning. + // fiber_switchContext expects newp sp to look like this: + // 19: x19 + // ... + // 9: x29 (fp) <-- newp tstack + // 8: x30 (lr) [&fiber_entryPoint] + // 7: d8 + // ... + // 0: d15 + + version (StackGrowsDown) {} + else + static assert(false, "Only full descending stacks supported on AArch64"); + + // Only need to set return address (lr). Everything else is fine + // zero initialized. + pstack -= size_t.sizeof * 11; // skip past x19-x29 + push(cast(size_t) &fiber_trampoline); // see threadasm.S for docs + pstack += size_t.sizeof; // adjust sp (newp) above lr + } else version (AsmARM_Posix) { /* We keep the FP registers and the return address below diff --git a/libphobos/libdruntime/core/threadasm.S b/libphobos/libdruntime/core/threadasm.S index 02bd756..140e5f9 100644 --- a/libphobos/libdruntime/core/threadasm.S +++ b/libphobos/libdruntime/core/threadasm.S @@ -487,6 +487,7 @@ fiber_switchContext: */ .text .global CSYM(fiber_switchContext) + .type fiber_switchContext, %function .p2align 2 CSYM(fiber_switchContext): stp d15, d14, [sp, #-20*8]! @@ -518,6 +519,29 @@ CSYM(fiber_switchContext): ldp d15, d14, [sp], #20*8 ret + +/** + * When generating any kind of backtrace (gdb, exception handling) for + * a function called in a Fiber, we need to tell the unwinder to stop + * at our Fiber main entry point, i.e. we need to mark the bottom of + * the call stack. This can be done by clearing the link register lr + * prior to calling fiber_entryPoint (i.e. in fiber_switchContext) or + * using a .cfi_undefined directive for the link register in the + * Fiber entry point. cfi_undefined seems to yield better results in gdb. + * Unfortunately we can't place it into fiber_entryPoint using inline + * asm, so we use this trampoline instead. + */ + .text + .global CSYM(fiber_trampoline) + .p2align 2 + .type fiber_trampoline, %function +CSYM(fiber_trampoline): + .cfi_startproc + .cfi_undefined x30 + // fiber_entryPoint never returns + bl fiber_entryPoint + .cfi_endproc + #elif defined(__MINGW32__) /************************************************************************************ * GDC MinGW ASM BITS |