diff --git a/druntime/src/core/thread/osthread.d b/druntime/src/core/thread/osthread.d index 827b19b61df9..c89b441ab5b5 100644 --- a/druntime/src/core/thread/osthread.d +++ b/druntime/src/core/thread/osthread.d @@ -941,16 +941,10 @@ in (fn) * writefln("Current process id: %s", getpid()); * --- */ -version (Posix) -{ - alias getpid = imported!"core.sys.posix.unistd".getpid; -} -else version (Windows) +version (CoreDdoc) { - alias getpid = imported!"core.sys.windows.winbase".GetCurrentProcessId; + size_t getpid() nothrow @nogc { return 0; } } -else - static assert(0, "unsupported os"); extern (C) @nogc nothrow { @@ -1111,316 +1105,6 @@ private extern (D) bool suspend( Thread t ) nothrow @nogc return true; } -private void loadStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc -{ - version (Windows) - { - CONTEXT context = void; - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - - if ( !GetThreadContext( t.m_tdescr.hndl, &context ) ) - onThreadError( "Unable to load thread context" ); - version (X86) - { - if ( !t.m_lock ) - t.m_curr.tstack = cast(void*) context.Esp; - // eax,ebx,ecx,edx,edi,esi,ebp,esp - t.m_reg[0] = context.Eax; - t.m_reg[1] = context.Ebx; - t.m_reg[2] = context.Ecx; - t.m_reg[3] = context.Edx; - t.m_reg[4] = context.Edi; - t.m_reg[5] = context.Esi; - t.m_reg[6] = context.Ebp; - t.m_reg[7] = context.Esp; - } - else version (X86_64) - { - if ( !t.m_lock ) - t.m_curr.tstack = cast(void*) context.Rsp; - // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp - t.m_reg[0] = context.Rax; - t.m_reg[1] = context.Rbx; - t.m_reg[2] = context.Rcx; - t.m_reg[3] = context.Rdx; - t.m_reg[4] = context.Rdi; - t.m_reg[5] = context.Rsi; - t.m_reg[6] = context.Rbp; - t.m_reg[7] = context.Rsp; - // r8,r9,r10,r11,r12,r13,r14,r15 - t.m_reg[8] = context.R8; - t.m_reg[9] = context.R9; - t.m_reg[10] = context.R10; - t.m_reg[11] = context.R11; - t.m_reg[12] = context.R12; - t.m_reg[13] = context.R13; - t.m_reg[14] = context.R14; - t.m_reg[15] = context.R15; - } - else - { - static assert(false, "Architecture not supported." ); - } - // a thread might change the stack, e.g. using non-D fibers, so we must not - // rely on the stack bottom saved when attaching/starting. Multiple fiber stacks cannot be - // captured, but make sure scanning does not crash accessing invalid memory ranges - // between stacks - if ( !t.m_lock ) - t.m_curr.bstack = getThreadStackBottom( t.m_tdescr.hndl ); - } - else version (Darwin) - { - version (X86) - { - x86_thread_state32_t state = void; - mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT; - - if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS ) - onThreadError( "Unable to load thread state" ); - if ( !t.m_lock ) - t.m_curr.tstack = cast(void*) state.esp; - // eax,ebx,ecx,edx,edi,esi,ebp,esp - t.m_reg[0] = state.eax; - t.m_reg[1] = state.ebx; - t.m_reg[2] = state.ecx; - t.m_reg[3] = state.edx; - t.m_reg[4] = state.edi; - t.m_reg[5] = state.esi; - t.m_reg[6] = state.ebp; - t.m_reg[7] = state.esp; - } - else version (X86_64) - { - x86_thread_state64_t state = void; - mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; - - if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS ) - onThreadError( "Unable to load thread state" ); - if ( !t.m_lock ) - t.m_curr.tstack = cast(void*) state.rsp; - // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp - t.m_reg[0] = state.rax; - t.m_reg[1] = state.rbx; - t.m_reg[2] = state.rcx; - t.m_reg[3] = state.rdx; - t.m_reg[4] = state.rdi; - t.m_reg[5] = state.rsi; - t.m_reg[6] = state.rbp; - t.m_reg[7] = state.rsp; - // r8,r9,r10,r11,r12,r13,r14,r15 - t.m_reg[8] = state.r8; - t.m_reg[9] = state.r9; - t.m_reg[10] = state.r10; - t.m_reg[11] = state.r11; - t.m_reg[12] = state.r12; - t.m_reg[13] = state.r13; - t.m_reg[14] = state.r14; - t.m_reg[15] = state.r15; - } - else version (AArch64) - { - arm_thread_state64_t state = void; - mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT; - - if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE64, &state, &count) != KERN_SUCCESS) - onThreadError("Unable to load thread state"); - // TODO: ThreadException here recurses forever! Does it - //still using onThreadError? - //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE64_COUNT); - if (!t.m_lock) - t.m_curr.tstack = cast(void*) state.sp; - - t.m_reg[0..29] = state.x; // x0-x28 - t.m_reg[29] = state.fp; // x29 - t.m_reg[30] = state.lr; // x30 - t.m_reg[31] = state.sp; // x31 - t.m_reg[32] = state.pc; - } - else version (ARM) - { - arm_thread_state32_t state = void; - mach_msg_type_number_t count = ARM_THREAD_STATE32_COUNT; - - // Thought this would be ARM_THREAD_STATE32, but that fails. - // Mystery - if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE, &state, &count) != KERN_SUCCESS) - onThreadError("Unable to load thread state"); - // TODO: in past, ThreadException here recurses forever! Does it - //still using onThreadError? - //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE32_COUNT); - if (!t.m_lock) - t.m_curr.tstack = cast(void*) state.sp; - - t.m_reg[0..13] = state.r; // r0 - r13 - t.m_reg[13] = state.sp; - t.m_reg[14] = state.lr; - t.m_reg[15] = state.pc; - } - else version (PPC) - { - ppc_thread_state_t state = void; - mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT; - - if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE, &state, &count) != KERN_SUCCESS) - onThreadError("Unable to load thread state"); - if (!t.m_lock) - t.m_curr.tstack = cast(void*) state.r[1]; - t.m_reg[] = state.r[]; - } - else version (PPC64) - { - ppc_thread_state64_t state = void; - mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT; - - if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE64, &state, &count) != KERN_SUCCESS) - onThreadError("Unable to load thread state"); - if (!t.m_lock) - t.m_curr.tstack = cast(void*) state.r[1]; - t.m_reg[] = state.r[]; - } - else - { - static assert(false, "Architecture not supported." ); - } - } - else version (Solaris) - { - if (!sameThread) - { - static int getLwpStatus(ulong lwpid, out lwpstatus_t status) - { - import core.sys.posix.fcntl : open, O_RDONLY; - import core.sys.posix.unistd : pread, close; - import core.internal.string : unsignedToTempString; - - char[100] path = void; - auto pslice = path[0 .. $]; - immutable n = unsignedToTempString(lwpid); - immutable ndigits = n.length; - - // Construct path "/proc/self/lwp/%u/lwpstatus" - pslice[0 .. 15] = "/proc/self/lwp/"; - pslice = pslice[15 .. $]; - pslice[0 .. ndigits] = n[]; - pslice = pslice[ndigits .. $]; - pslice[0 .. 10] = "/lwpstatus"; - pslice[10] = '\0'; - - // Read in lwpstatus data - int fd = open(path.ptr, O_RDONLY, 0); - if (fd >= 0) - { - while (pread(fd, &status, status.sizeof, 0) == status.sizeof) - { - // Should only attempt to read the thread state once it - // has been stopped by thr_suspend - if (status.pr_flags & PR_STOPPED) - { - close(fd); - return 0; - } - // Give it a chance to stop - thread_yield(); - } - close(fd); - } - return -1; - } - - lwpstatus_t status = void; - if (getLwpStatus(t.m_tdescr.tid, status) != 0) - onThreadError("Unable to load thread state"); - - version (X86) - { - import core.sys.solaris.sys.regset; // REG_xxx - - if (!t.m_lock) - t.m_curr.tstack = cast(void*) status.pr_reg[REG_ESP]; - // eax,ebx,ecx,edx,edi,esi,ebp,esp - t.m_reg[0] = status.pr_reg[REG_EAX]; - t.m_reg[1] = status.pr_reg[REG_EBX]; - t.m_reg[2] = status.pr_reg[REG_ECX]; - t.m_reg[3] = status.pr_reg[REG_EDX]; - t.m_reg[4] = status.pr_reg[REG_EDI]; - t.m_reg[5] = status.pr_reg[REG_ESI]; - t.m_reg[6] = status.pr_reg[REG_EBP]; - t.m_reg[7] = status.pr_reg[REG_ESP]; - } - else version (X86_64) - { - import core.sys.solaris.sys.regset; // REG_xxx - - if (!t.m_lock) - t.m_curr.tstack = cast(void*) status.pr_reg[REG_RSP]; - // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp - t.m_reg[0] = status.pr_reg[REG_RAX]; - t.m_reg[1] = status.pr_reg[REG_RBX]; - t.m_reg[2] = status.pr_reg[REG_RCX]; - t.m_reg[3] = status.pr_reg[REG_RDX]; - t.m_reg[4] = status.pr_reg[REG_RDI]; - t.m_reg[5] = status.pr_reg[REG_RSI]; - t.m_reg[6] = status.pr_reg[REG_RBP]; - t.m_reg[7] = status.pr_reg[REG_RSP]; - // r8,r9,r10,r11,r12,r13,r14,r15 - t.m_reg[8] = status.pr_reg[REG_R8]; - t.m_reg[9] = status.pr_reg[REG_R9]; - t.m_reg[10] = status.pr_reg[REG_R10]; - t.m_reg[11] = status.pr_reg[REG_R11]; - t.m_reg[12] = status.pr_reg[REG_R12]; - t.m_reg[13] = status.pr_reg[REG_R13]; - t.m_reg[14] = status.pr_reg[REG_R14]; - t.m_reg[15] = status.pr_reg[REG_R15]; - } - else version (SPARC) - { - import core.sys.solaris.sys.procfs : R_SP, R_PC; - - if (!t.m_lock) - t.m_curr.tstack = cast(void*) status.pr_reg[R_SP]; - // g0..g7, o0..o7, l0..l7, i0..i7 - t.m_reg[0 .. 32] = status.pr_reg[0 .. 32]; - // pc - t.m_reg[32] = status.pr_reg[R_PC]; - } - else version (SPARC64) - { - import core.sys.solaris.sys.procfs : R_SP, R_PC; - - if (!t.m_lock) - { - // SPARC V9 has a stack bias of 2047 bytes which must be added to get - // the actual data of the stack frame. - auto tstack = status.pr_reg[R_SP] + 2047; - assert(tstack % 16 == 0); - t.m_curr.tstack = cast(void*) tstack; - } - // g0..g7, o0..o7, l0..l7, i0..i7 - t.m_reg[0 .. 32] = status.pr_reg[0 .. 32]; - // pc - t.m_reg[32] = status.pr_reg[R_PC]; - } - else - { - static assert(false, "Architecture not supported."); - } - } - else if (!t.m_lock) - { - t.m_curr.tstack = getStackTop(); - } - } - else version (Posix) - { - if (sameThread && !t.m_lock) - { - t.m_curr.tstack = getStackTop(); - } - } - else - static assert(0, "unsupported os"); -} - /** * Runs the necessary operations required before stopping the world. */ @@ -1549,33 +1233,6 @@ private extern (D) void resume(ThreadBase _t) nothrow @nogc purgeStackAndRegInfo(t, sameThread); } -private void purgeStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc -{ - version (Windows) - { - t.unloadStackInfo(); - t.m_reg[0 .. $] = 0; - } - else version (Darwin) - { - t.unloadStackInfo(); - t.m_reg[0 .. $] = 0; - } - else version (Solaris) - { - t.unloadStackInfo(); - t.m_reg[0 .. $] = 0; - } - else version (Posix) - { - if (sameThread) - t.unloadStackInfo(); - } - else - static assert(false, "Platform not supported."); -} - - /** * Initializes the thread module. This function must be called by the * garbage collector on startup and before any other thread routines diff --git a/druntime/src/core/thread/posix_impl.d b/druntime/src/core/thread/posix_impl.d index 284acc404194..d2bb8b11e778 100644 --- a/druntime/src/core/thread/posix_impl.d +++ b/druntime/src/core/thread/posix_impl.d @@ -815,6 +815,281 @@ package bool resumeThreadImpl(Thread t) @nogc nothrow return pthread_kill(t.m_tdescr.tid, resumeSignalNumber) == 0; } +package void loadStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc +{ + version (Darwin) + { + version (X86) + { + x86_thread_state32_t state = void; + mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT; + + if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS ) + onThreadError( "Unable to load thread state" ); + if ( !t.m_lock ) + t.m_curr.tstack = cast(void*) state.esp; + // eax,ebx,ecx,edx,edi,esi,ebp,esp + t.m_reg[0] = state.eax; + t.m_reg[1] = state.ebx; + t.m_reg[2] = state.ecx; + t.m_reg[3] = state.edx; + t.m_reg[4] = state.edi; + t.m_reg[5] = state.esi; + t.m_reg[6] = state.ebp; + t.m_reg[7] = state.esp; + } + else version (X86_64) + { + x86_thread_state64_t state = void; + mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; + + if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS ) + onThreadError( "Unable to load thread state" ); + if ( !t.m_lock ) + t.m_curr.tstack = cast(void*) state.rsp; + // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp + t.m_reg[0] = state.rax; + t.m_reg[1] = state.rbx; + t.m_reg[2] = state.rcx; + t.m_reg[3] = state.rdx; + t.m_reg[4] = state.rdi; + t.m_reg[5] = state.rsi; + t.m_reg[6] = state.rbp; + t.m_reg[7] = state.rsp; + // r8,r9,r10,r11,r12,r13,r14,r15 + t.m_reg[8] = state.r8; + t.m_reg[9] = state.r9; + t.m_reg[10] = state.r10; + t.m_reg[11] = state.r11; + t.m_reg[12] = state.r12; + t.m_reg[13] = state.r13; + t.m_reg[14] = state.r14; + t.m_reg[15] = state.r15; + } + else version (AArch64) + { + arm_thread_state64_t state = void; + mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT; + + if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE64, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + // TODO: ThreadException here recurses forever! Does it + //still using onThreadError? + //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE64_COUNT); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.sp; + + t.m_reg[0..29] = state.x; // x0-x28 + t.m_reg[29] = state.fp; // x29 + t.m_reg[30] = state.lr; // x30 + t.m_reg[31] = state.sp; // x31 + t.m_reg[32] = state.pc; + } + else version (ARM) + { + arm_thread_state32_t state = void; + mach_msg_type_number_t count = ARM_THREAD_STATE32_COUNT; + + // Thought this would be ARM_THREAD_STATE32, but that fails. + // Mystery + if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + // TODO: in past, ThreadException here recurses forever! Does it + //still using onThreadError? + //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE32_COUNT); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.sp; + + t.m_reg[0..13] = state.r; // r0 - r13 + t.m_reg[13] = state.sp; + t.m_reg[14] = state.lr; + t.m_reg[15] = state.pc; + } + else version (PPC) + { + ppc_thread_state_t state = void; + mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT; + + if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.r[1]; + t.m_reg[] = state.r[]; + } + else version (PPC64) + { + ppc_thread_state64_t state = void; + mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT; + + if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE64, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.r[1]; + t.m_reg[] = state.r[]; + } + else + { + static assert(false, "Architecture not supported." ); + } + } + else version (Solaris) + { + if (!sameThread) + { + static int getLwpStatus(ulong lwpid, out lwpstatus_t status) + { + import core.sys.posix.fcntl : open, O_RDONLY; + import core.sys.posix.unistd : pread, close; + import core.internal.string : unsignedToTempString; + + char[100] path = void; + auto pslice = path[0 .. $]; + immutable n = unsignedToTempString(lwpid); + immutable ndigits = n.length; + + // Construct path "/proc/self/lwp/%u/lwpstatus" + pslice[0 .. 15] = "/proc/self/lwp/"; + pslice = pslice[15 .. $]; + pslice[0 .. ndigits] = n[]; + pslice = pslice[ndigits .. $]; + pslice[0 .. 10] = "/lwpstatus"; + pslice[10] = '\0'; + + // Read in lwpstatus data + int fd = open(path.ptr, O_RDONLY, 0); + if (fd >= 0) + { + while (pread(fd, &status, status.sizeof, 0) == status.sizeof) + { + // Should only attempt to read the thread state once it + // has been stopped by thr_suspend + if (status.pr_flags & PR_STOPPED) + { + close(fd); + return 0; + } + // Give it a chance to stop + thread_yield(); + } + close(fd); + } + return -1; + } + + lwpstatus_t status = void; + if (getLwpStatus(t.m_tdescr.tid, status) != 0) + onThreadError("Unable to load thread state"); + + version (X86) + { + import core.sys.solaris.sys.regset; // REG_xxx + + if (!t.m_lock) + t.m_curr.tstack = cast(void*) status.pr_reg[REG_ESP]; + // eax,ebx,ecx,edx,edi,esi,ebp,esp + t.m_reg[0] = status.pr_reg[REG_EAX]; + t.m_reg[1] = status.pr_reg[REG_EBX]; + t.m_reg[2] = status.pr_reg[REG_ECX]; + t.m_reg[3] = status.pr_reg[REG_EDX]; + t.m_reg[4] = status.pr_reg[REG_EDI]; + t.m_reg[5] = status.pr_reg[REG_ESI]; + t.m_reg[6] = status.pr_reg[REG_EBP]; + t.m_reg[7] = status.pr_reg[REG_ESP]; + } + else version (X86_64) + { + import core.sys.solaris.sys.regset; // REG_xxx + + if (!t.m_lock) + t.m_curr.tstack = cast(void*) status.pr_reg[REG_RSP]; + // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp + t.m_reg[0] = status.pr_reg[REG_RAX]; + t.m_reg[1] = status.pr_reg[REG_RBX]; + t.m_reg[2] = status.pr_reg[REG_RCX]; + t.m_reg[3] = status.pr_reg[REG_RDX]; + t.m_reg[4] = status.pr_reg[REG_RDI]; + t.m_reg[5] = status.pr_reg[REG_RSI]; + t.m_reg[6] = status.pr_reg[REG_RBP]; + t.m_reg[7] = status.pr_reg[REG_RSP]; + // r8,r9,r10,r11,r12,r13,r14,r15 + t.m_reg[8] = status.pr_reg[REG_R8]; + t.m_reg[9] = status.pr_reg[REG_R9]; + t.m_reg[10] = status.pr_reg[REG_R10]; + t.m_reg[11] = status.pr_reg[REG_R11]; + t.m_reg[12] = status.pr_reg[REG_R12]; + t.m_reg[13] = status.pr_reg[REG_R13]; + t.m_reg[14] = status.pr_reg[REG_R14]; + t.m_reg[15] = status.pr_reg[REG_R15]; + } + else version (SPARC) + { + import core.sys.solaris.sys.procfs : R_SP, R_PC; + + if (!t.m_lock) + t.m_curr.tstack = cast(void*) status.pr_reg[R_SP]; + // g0..g7, o0..o7, l0..l7, i0..i7 + t.m_reg[0 .. 32] = status.pr_reg[0 .. 32]; + // pc + t.m_reg[32] = status.pr_reg[R_PC]; + } + else version (SPARC64) + { + import core.sys.solaris.sys.procfs : R_SP, R_PC; + + if (!t.m_lock) + { + // SPARC V9 has a stack bias of 2047 bytes which must be added to get + // the actual data of the stack frame. + auto tstack = status.pr_reg[R_SP] + 2047; + assert(tstack % 16 == 0); + t.m_curr.tstack = cast(void*) tstack; + } + // g0..g7, o0..o7, l0..l7, i0..i7 + t.m_reg[0 .. 32] = status.pr_reg[0 .. 32]; + // pc + t.m_reg[32] = status.pr_reg[R_PC]; + } + else + { + static assert(false, "Architecture not supported."); + } + } + else if (!t.m_lock) + { + t.m_curr.tstack = getStackTop(); + } + } + else // other Posix + { + if (sameThread && !t.m_lock) + { + t.m_curr.tstack = getStackTop(); + } + } +} + +package void purgeStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc +{ + version (Darwin) + { + t.unloadStackInfo(); + t.m_reg[0 .. $] = 0; + } + else version (Solaris) + { + t.unloadStackInfo(); + t.m_reg[0 .. $] = 0; + } + else + { + if (sameThread) + t.unloadStackInfo(); + } +} + +version (CoreDdoc) {} else +public alias getpid = imported!"core.sys.posix.unistd".getpid; + package alias gettid = imported!"core.sys.posix.pthread".pthread_self; package struct LLThreadProperties diff --git a/druntime/src/core/thread/windows_impl.d b/druntime/src/core/thread/windows_impl.d index 0254cc07e879..072c7d2a3f0f 100644 --- a/druntime/src/core/thread/windows_impl.d +++ b/druntime/src/core/thread/windows_impl.d @@ -256,6 +256,9 @@ class Thread : ThreadBase package static void afterDeploy() nothrow @nogc { /* do nothing */ } } +version (CoreDdoc) {} else +public alias getpid = imported!"core.sys.windows.winbase".GetCurrentProcessId; + package alias gettid = imported!"core.sys.windows.winbase".GetCurrentThreadId; // Returns true on success @@ -270,6 +273,68 @@ package bool resumeThreadImpl(Thread t) @nogc nothrow return ResumeThread(t.m_tdescr.hndl) != 0xFFFFFFFF; } +package void loadStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc +{ + CONTEXT context = void; + context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; + + if ( !GetThreadContext( t.m_tdescr.hndl, &context ) ) + onThreadError( "Unable to load thread context" ); + version (X86) + { + if ( !t.m_lock ) + t.m_curr.tstack = cast(void*) context.Esp; + // eax,ebx,ecx,edx,edi,esi,ebp,esp + t.m_reg[0] = context.Eax; + t.m_reg[1] = context.Ebx; + t.m_reg[2] = context.Ecx; + t.m_reg[3] = context.Edx; + t.m_reg[4] = context.Edi; + t.m_reg[5] = context.Esi; + t.m_reg[6] = context.Ebp; + t.m_reg[7] = context.Esp; + } + else version (X86_64) + { + if ( !t.m_lock ) + t.m_curr.tstack = cast(void*) context.Rsp; + // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp + t.m_reg[0] = context.Rax; + t.m_reg[1] = context.Rbx; + t.m_reg[2] = context.Rcx; + t.m_reg[3] = context.Rdx; + t.m_reg[4] = context.Rdi; + t.m_reg[5] = context.Rsi; + t.m_reg[6] = context.Rbp; + t.m_reg[7] = context.Rsp; + // r8,r9,r10,r11,r12,r13,r14,r15 + t.m_reg[8] = context.R8; + t.m_reg[9] = context.R9; + t.m_reg[10] = context.R10; + t.m_reg[11] = context.R11; + t.m_reg[12] = context.R12; + t.m_reg[13] = context.R13; + t.m_reg[14] = context.R14; + t.m_reg[15] = context.R15; + } + else + { + static assert(false, "Architecture not supported." ); + } + // a thread might change the stack, e.g. using non-D fibers, so we must not + // rely on the stack bottom saved when attaching/starting. Multiple fiber stacks cannot be + // captured, but make sure scanning does not crash accessing invalid memory ranges + // between stacks + if ( !t.m_lock ) + t.m_curr.bstack = getThreadStackBottom( t.m_tdescr.hndl ); +} + +package void purgeStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc +{ + t.unloadStackInfo(); + t.m_reg[0 .. $] = 0; +} + private { // If the runtime is dynamically loaded as a DLL, there is a problem with