Merge pull request #5272 from milescoviello/carry/siglongjmp-stack-windows-5270
fix(libkernel): switch the host stack bounds in siglongjmp on Windows
This commit is contained in:
commit
c101c91bbb
|
|
@ -109,6 +109,16 @@ asm(".text\n"
|
|||
" popq %rsi\n"
|
||||
" popq %rdi\n"
|
||||
"2:\n"
|
||||
#ifdef _WIN32
|
||||
" pushq %rdi\n"
|
||||
" pushq %rsi\n"
|
||||
" movq 16(%rdi), %rdi\n"
|
||||
" subq $8, %rsp\n"
|
||||
" call GuestStackSwitch_nid_no_patch\n"
|
||||
" addq $8, %rsp\n"
|
||||
" popq %rsi\n"
|
||||
" popq %rdi\n"
|
||||
#endif
|
||||
" movq %rdi, %rdx\n"
|
||||
" movl %esi, %eax\n"
|
||||
" movq 0(%rdx), %rcx\n"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ int APS5_VABI setcontext_nid_postfix(const UserUcontext* context);
|
|||
void APS5_VABI makecontext_nid_postfix(UserUcontext* context, ContextEntry entry, int count, ...);
|
||||
[[gnu::returns_twice]] int APS5_VABI setjmp_nid_postfix(std::uint64_t* buffer);
|
||||
[[noreturn]] void APS5_VABI longjmp_nid_postfix(std::uint64_t* buffer, int value);
|
||||
[[gnu::returns_twice]] int APS5_VABI sigsetjmp_nid_postfix(std::uint64_t* buffer, int saveMask);
|
||||
[[noreturn]] void APS5_VABI siglongjmp_nid_postfix(std::uint64_t* buffer, int value);
|
||||
int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet);
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
|
||||
|
|
@ -150,6 +152,7 @@ int g_entries = 0;
|
|||
Fibre g_dispatcher = {};
|
||||
Fibre g_job = {};
|
||||
int g_jobRuns = 0;
|
||||
bool g_signalJumps = false;
|
||||
|
||||
void Require(bool value, const char* what) {
|
||||
if (!value) {
|
||||
|
|
@ -348,6 +351,14 @@ namespace {
|
|||
|
||||
[[gnu::noinline]] void Switch(Fibre* from, Fibre* to) {
|
||||
from->started = 1;
|
||||
if (g_signalJumps) {
|
||||
if (sigsetjmp_nid_postfix(from->jump, 1) == 0) {
|
||||
if (to->started) siglongjmp_nid_postfix(to->jump, 1);
|
||||
setcontext_nid_postfix(&to->context);
|
||||
Require(false, "setcontext into the job returned");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (setjmp_nid_postfix(from->jump) == 0) {
|
||||
if (to->started) longjmp_nid_postfix(to->jump, 1);
|
||||
setcontext_nid_postfix(&to->context);
|
||||
|
|
@ -360,7 +371,7 @@ namespace {
|
|||
extern "C" void APS5_VABI JobEntry() {
|
||||
for (;;) {
|
||||
++g_jobRuns;
|
||||
CheckStackBounds(&g_jobStack, "the stack bounds follow longjmp onto the job stack");
|
||||
CheckStackBounds(&g_jobStack, g_signalJumps ? "the stack bounds follow siglongjmp onto the job stack" : "the stack bounds follow longjmp onto the job stack");
|
||||
ThrowAndCatch();
|
||||
Switch(&g_job, &g_dispatcher);
|
||||
}
|
||||
|
|
@ -402,7 +413,11 @@ void CheckMakecontext() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void CheckJumpBuffers() {
|
||||
void CheckJumpBuffers(bool signalJumps) {
|
||||
g_signalJumps = signalJumps;
|
||||
g_jobRuns = 0;
|
||||
g_dispatcher = {};
|
||||
g_job = {};
|
||||
#ifdef _WIN32
|
||||
ULONG_PTR threadLow = 0;
|
||||
ULONG_PTR threadHigh = 0;
|
||||
|
|
@ -420,7 +435,7 @@ void CheckJumpBuffers() {
|
|||
ULONG_PTR low = 0;
|
||||
ULONG_PTR high = 0;
|
||||
GetCurrentThreadStackLimits(&low, &high);
|
||||
Require(low == threadLow && high == threadHigh, "the stack bounds follow longjmp back to the thread stack");
|
||||
Require(low == threadLow && high == threadHigh, signalJumps ? "the stack bounds follow siglongjmp back to the thread stack" : "the stack bounds follow longjmp back to the thread stack");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -466,7 +481,8 @@ int main(int argc, char** argv) {
|
|||
CheckSignalMask();
|
||||
std::thread([] {
|
||||
CheckMakecontext();
|
||||
CheckJumpBuffers();
|
||||
CheckJumpBuffers(false);
|
||||
CheckJumpBuffers(true);
|
||||
GrowStack(32);
|
||||
}).join();
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue