Windows: Rise a non-continuable excetpion for STATUS_STACK_BUFFER_OVERRUN

This commit is contained in:
Jacek Caban committed 2026-09-06 15:20:30 +02:00
1 parent 9f511d5d78
commit d704bd3cef
5 files changed
+20 -3

No files matched your search

+1
View File
@@ -121,6 +121,7 @@ ExitFunctionSuspendPoint:
// Allows for continuing from a full native context, as the NTDLL NtContinue export takes in an x64 context with EC and
// the conversion to that loses the ARM64EC ABI-disallowed registers that FEX uses.
DIRECT_SYSCALL_WRAPPER("#NtContinueNative", WineNtContinueSyscallId, 0x43)
DIRECT_SYSCALL_WRAPPER("#NtRaiseExceptionNative", WineNtRaiseExceptionSyscallId, 0x174)
// Both of these are wrapped as FEX needs them to setup its call checker at startup time and their NTDLL thunks could
// already be patched by then (and because the call checker isn't installed, their patched x86 versions would be invoked
+9 -1
View File
@@ -87,10 +87,12 @@ void* WineSyscallDispatcher;
uint64_t WineNtContinueSyscallId;
uint64_t WineNtAllocateVirtualMemorySyscallId;
uint64_t WineNtProtectVirtualMemorySyscallId;
uint64_t WineNtRaiseExceptionSyscallId;
NTSTATUS NtContinueNative(ARM64_NT_CONTEXT* NativeContext, BOOLEAN Alert);
NTSTATUS NtAllocateVirtualMemoryNative(HANDLE, PVOID*, ULONG_PTR, SIZE_T*, ULONG, ULONG);
NTSTATUS NtProtectVirtualMemoryNative(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG*);
NTSTATUS NtRaiseExceptionNative(EXCEPTION_RECORD*, ARM64_NT_CONTEXT*, BOOL);
static fextl::string AppConfigName {};
[[noreturn]]
@@ -260,6 +262,8 @@ void ParseWineSyscallNumbers(HMODULE NtDll) {
WineNtAllocateVirtualMemorySyscallId = CurSyscallId;
} else if (strcmp(it->Name, "NtProtectVirtualMemory") == 0) {
WineNtProtectVirtualMemorySyscallId = CurSyscallId;
} else if (strcmp(it->Name, "NtRaiseException") == 0) {
WineNtRaiseExceptionSyscallId = CurSyscallId;
}
}
}
@@ -500,7 +504,8 @@ static void RethrowGuestException(const EXCEPTION_RECORD& Rec, ARM64_NT_CONTEXT&
EFlags &= ~(1 << FEXCore::X86State::RFLAG_TF_RAW_LOC);
CTX->SetFlagsFromCompactedEFLAGS(Thread, EFlags);
Args->Rec = FEX::Windows::HandleGuestException(Fault, Rec, Args->Context.Pc, Args->Context.X8, Args->Context.X0);
BOOL FirstChance = TRUE;
Args->Rec = FEX::Windows::HandleGuestException(Fault, Rec, Args->Context.Pc, Args->Context.X8, Args->Context.X0, FirstChance);
if (Args->Rec.ExceptionCode == EXCEPTION_SINGLE_STEP) {
Args->Context.Cpsr &= ~(1 << 21); // PSTATE.SS
} else if (Args->Rec.ExceptionCode == EXCEPTION_BREAKPOINT) {
@@ -508,6 +513,9 @@ static void RethrowGuestException(const EXCEPTION_RECORD& Rec, ARM64_NT_CONTEXT&
Args->Context.Pc -= 1;
}
if (!FirstChance) {
NtRaiseExceptionNative(&Args->Rec, &Args->Context, FirstChance);
}
Context.Sp = reinterpret_cast<uint64_t>(Args);
Context.Pc = KiUserExceptionDispatcher;
}
+3 -1
View File
@@ -11,7 +11,7 @@
namespace FEX::Windows {
template<typename TReg>
static inline EXCEPTION_RECORD HandleGuestException(FEXCore::Core::CpuStateFrame::SynchronousFaultDataStruct& Fault,
const EXCEPTION_RECORD& Src, TReg& Rip, TReg Rax, TReg Cx) {
const EXCEPTION_RECORD& Src, TReg& Rip, TReg Rax, TReg Cx, BOOL& FirstChance) {
EXCEPTION_RECORD Dst = Src;
Dst.ExceptionAddress = reinterpret_cast<void*>(Rip);
@@ -51,9 +51,11 @@ static inline EXCEPTION_RECORD HandleGuestException(FEXCore::Core::CpuStateFrame
return Dst;
case 0x29:
Dst.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
Dst.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
Dst.ExceptionAddress = reinterpret_cast<void*>(Rip);
Dst.NumberParameters = 1;
Dst.ExceptionInformation[0] = Cx;
FirstChance = FALSE;
return Dst;
case 0x2c: Dst.ExceptionCode = STATUS_ASSERTION_FAILURE; return Dst;
case 0x2d:
+6 -1
View File
@@ -942,7 +942,8 @@ bool BTCpuResetToConsistentStateImpl(EXCEPTION_POINTERS* Ptrs) {
LogMan::Msg::DFmt("pc: {:X} eip: {:X}", Context->Pc, WowContext.Eip);
auto& Fault = Thread->CurrentFrame->SynchronousFaultData;
*Exception = FEX::Windows::HandleGuestException(Fault, *Exception, WowContext.Eip, WowContext.Eax, WowContext.Ecx);
BOOL FirstChance = TRUE;
*Exception = FEX::Windows::HandleGuestException(Fault, *Exception, WowContext.Eip, WowContext.Eax, WowContext.Ecx, FirstChance);
if (Exception->ExceptionCode == EXCEPTION_SINGLE_STEP) {
WowContext.EFlags &= ~(1 << FEXCore::X86State::RFLAG_TF_RAW_LOC);
}
@@ -951,6 +952,10 @@ bool BTCpuResetToConsistentStateImpl(EXCEPTION_POINTERS* Ptrs) {
BTCpuSetContext(GetCurrentThread(), GetCurrentProcess(), nullptr, &WowContext);
Context::UnlockJITContext(TLS);
if (!FirstChance) {
NtRaiseException(Exception, TLS.EntryContext(), FirstChance);
}
// Replace the host context with one captured before JIT entry so host code can unwind
memcpy(Context, TLS.EntryContext(), sizeof(*Context));
+1
View File
@@ -557,6 +557,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO
BOOLEAN, PUNICODE_STRING, BOOLEAN);
NTSTATUS WINAPI NtQueryValueKey(HANDLE, const UNICODE_STRING*, KEY_VALUE_INFORMATION_CLASS, void*, DWORD, DWORD*);
NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS, PVOID, SIZE_T, SIZE_T*);
NTSTATUS WINAPI NtRaiseException(EXCEPTION_RECORD*, CONTEXT*, BOOL);
NTSTATUS WINAPI NtReadFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
NTSTATUS WINAPI NtSetContextThread(HANDLE, const CONTEXT*);
NTSTATUS WINAPI NtSuspendThread(HANDLE, PULONG);