aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gcc.gnu.org>2018-11-26 17:27:34 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2018-11-26 17:27:34 +0000
commite20145f12ca3ecd913f28619d5f1b04ee91a18e8 (patch)
tree04572dc92a8c39a8c2aa204bc4e855af4590b308 /libphobos
parentef6e6914c8245ca24dae952bc054ae2328e751ab (diff)
downloadgcc-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.d38
-rw-r--r--libphobos/libdruntime/core/threadasm.S24
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