[PATCH v9 0/1] MR4720: Implement test_continue() for amd64
Currently there is `NtContinue()` test only for `aarch64` so implement it for amd64 aswell. This implementation is very similar to `aarch64` and it's very basic test. It doesn't change/test `ContextFlags` so it won't catch https://bugs.winehq.org/show_bug.cgi?id=56050 but that can be implemented later on top of this. -- v9: ntdll/tests: Implement test_continue() for amd64 https://gitlab.winehq.org/wine/wine/-/merge_requests/4720
From: Dāvis Mosāns <davispuh(a)gmail.com> --- dlls/ntdll/tests/exception.c | 165 +++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 76190aef75a..0c69287c15b 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -4413,6 +4413,170 @@ static void test_thread_context(void) #undef COMPARE } +static void test_continue(void) +{ + struct context_pair { + CONTEXT before; + CONTEXT after; + } contexts; + NTSTATUS (*func_ptr)( struct context_pair *, BOOL alertable, void *continue_func, void *capture_func ) = code_mem; + int i; + + static const BYTE call_func[] = + { + /* ret at 8*9(rsp) */ + + /* need to preserve these */ + 0x53, /* push %rbx; 8*8(rsp) */ + 0x55, /* push %rbp; 8*7(rsp) */ + 0x56, /* push %rsi; 8*6(rsp) */ + 0x57, /* push %rdi; 8*5(rsp) */ + 0x41, 0x54, /* push %r12; 8*4(rsp) */ + 0x41, 0x55, /* push %r13; 8*3(rsp) */ + 0x41, 0x56, /* push %r14; 8*2(rsp) */ + 0x41, 0x57, /* push %r15; 8*1(rsp) */ + + 0x48, 0x83, 0xec, 0x08, /* sub $0x8, %rsp; reserve space for rsp */ + 0x48, 0x89, 0x24, 0x24, /* mov %rsp, (%rsp); for stack validation */ + + /* save args */ + 0x48, 0x89, 0x4c, 0x24, 0x50, /* mov %rcx, 8*10(%rsp) */ + 0x48, 0x89, 0x54, 0x24, 0x58, /* mov %rdx, 8*11(%rsp) */ + 0x4c, 0x89, 0x44, 0x24, 0x60, /* mov %r8, 8*12(%rsp) */ + 0x4c, 0x89, 0x4c, 0x24, 0x68, /* mov %r9, 8*13(%rsp) */ + + /* invoke capture context */ + 0x41, 0xff, 0xd1, /* call *%r9 */ + + /* overwrite general registers */ + 0x48, 0xb8, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, /* movabs $0xdeadbeefdeadbeef, %rax */ + 0x48, 0x89, 0xc1, /* mov %rax, %rcx */ + 0x48, 0x89, 0xc2, /* mov %rax, %rdx */ + 0x48, 0x89, 0xc3, /* mov %rax, %rbx */ + 0x48, 0x89, 0xc5, /* mov %rax, %rbp */ + 0x48, 0x89, 0xc6, /* mov %rax, %rsi */ + 0x48, 0x89, 0xc7, /* mov %rax, %rdi */ + 0x49, 0x89, 0xc0, /* mov %rax, %r8 */ + 0x49, 0x89, 0xc1, /* mov %rax, %r9 */ + 0x49, 0x89, 0xc2, /* mov %rax, %r10 */ + 0x49, 0x89, 0xc3, /* mov %rax, %r11 */ + 0x49, 0x89, 0xc4, /* mov %rax, %r12 */ + 0x49, 0x89, 0xc5, /* mov %rax, %r13 */ + 0x49, 0x89, 0xc6, /* mov %rax, %r14 */ + 0x49, 0x89, 0xc7, /* mov %rax, %r15 */ + + /* overwrite SSE registers */ + 0x66, 0x48, 0x0f, 0x6e, 0xc0, /* movq %rax, %xmm0 */ + 0x66, 0x0f, 0x6c, 0xc0, /* punpcklqdq %xmm0, %xmm0; extend to high quadword */ + 0x0f, 0x28, 0xc8, /* movaps %xmm0, %xmm1 */ + 0x0f, 0x28, 0xd0, /* movaps %xmm0, %xmm2 */ + 0x0f, 0x28, 0xd8, /* movaps %xmm0, %xmm3 */ + 0x0f, 0x28, 0xe0, /* movaps %xmm0, %xmm4 */ + 0x0f, 0x28, 0xe8, /* movaps %xmm0, %xmm5 */ + 0x0f, 0x28, 0xf0, /* movaps %xmm0, %xmm6 */ + 0x0f, 0x28, 0xf8, /* movaps %xmm0, %xmm7 */ + 0x44, 0x0f, 0x28, 0xc0, /* movaps %xmm0, %xmm8 */ + 0x44, 0x0f, 0x28, 0xc8, /* movaps %xmm0, %xmm9 */ + 0x44, 0x0f, 0x28, 0xd0, /* movaps %xmm0, %xmm10 */ + 0x44, 0x0f, 0x28, 0xd8, /* movaps %xmm0, %xmm11 */ + 0x44, 0x0f, 0x28, 0xe0, /* movaps %xmm0, %xmm12 */ + 0x44, 0x0f, 0x28, 0xe8, /* movaps %xmm0, %xmm13 */ + 0x44, 0x0f, 0x28, 0xf0, /* movaps %xmm0, %xmm14 */ + 0x44, 0x0f, 0x28, 0xf8, /* movaps %xmm0, %xmm15 */ + + /* FIXME: overwrite debug, x87 FPU and AVX registers to test those */ + + /* load args */ + 0x48, 0x8b, 0x4c, 0x24, 0x50, /* mov 8*10(%rsp), %rcx; context */ + 0x48, 0x8b, 0x54, 0x24, 0x58, /* mov 8*11(%rsp), %rdx; alertable */ + 0x48, 0x83, 0xec, 0x70, /* sub $0x70, %rsp; change stack */ + + /* setup context to return to label 1 */ + 0x48, 0x8d, 0x05, 0x18, 0x00, 0x00, 0x00, /* lea 1f(%rip), %rax */ + 0x48, 0x89, 0x81, 0xf8, 0x00, 0x00, 0x00, /* mov %rax, 0xf8(%rcx); context.Rip */ + + /* flip some EFLAGS */ + 0x9c, /* pushf */ + /* + 0x0001 Carry flag + 0x0004 Parity flag + 0x0010 Auxiliary Carry flag + 0x0040 Zero flag + 0x0080 Sign flag + FIXME: 0x0400 Direction flag - not changing as it breaks Wine + 0x0800 Overflow flag + ~0x4000~ Nested task flag - not changing - breaks Wine + = 0x8d5 + */ + 0x48, 0x81, 0x34, 0x24, 0xd5, 0x08, 0x00, 0x00, /* xorq $0x8d5, (%rsp) */ + 0x9d, /* popf */ + + /* invoke NtContinue... */ + 0xff, 0x94, 0x24, 0xd0, 0x00, 0x00, 0x00, /* call *8*12+0x70(%rsp) */ + + /* validate stack pointer */ + 0x48, 0x8b, 0x0c, 0x24, /* 1: mov (%rsp), %rcx */ + 0x48, 0x39, 0xe1, /* cmp %rsp, %rcx */ + 0x74, 0x02, /* je 2f; jump over ud2 */ + 0x0f, 0x0b, /* ud2; stack pointer invalid, let's crash */ + + /* invoke capture context */ + 0x48, 0x8b, 0x4c, 0x24, 0x50, /* 2: mov 8*10(%rsp), %rcx; context */ + 0x48, 0x81, 0xc1, 0xd0, 0x04, 0x00, 0x00, /* add $0x4d0, %rcx; +sizeof(CONTEXT) to get context->after */ + 0xff, 0x54, 0x24, 0x68, /* call *8*13(%rsp) */ + + /* free stack */ + 0x48, 0x83, 0xc4, 0x08, /* add $0x8, %rsp */ + + /* restore back */ + 0x41, 0x5f, /* pop %r15 */ + 0x41, 0x5e, /* pop %r14 */ + 0x41, 0x5d, /* pop %r13 */ + 0x41, 0x5c, /* pop %r12 */ + 0x5f, /* pop %rdi */ + 0x5e, /* pop %rsi */ + 0x5d, /* pop %rbp */ + 0x5b, /* pop %rbx */ + 0xc3 /* ret */ + }; + + if (!pRtlCaptureContext) + { + win_skip("RtlCaptureContext is not available.\n"); + return; + } + + memcpy( func_ptr, call_func, sizeof(call_func) ); + FlushInstructionCache( GetCurrentProcess(), func_ptr, sizeof(call_func) ); + + func_ptr( &contexts, FALSE, NtContinue, pRtlCaptureContext ); + +#define COMPARE(reg) \ + ok( contexts.before.reg == contexts.after.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)contexts.before.reg, (void *)(ULONG64)contexts.after.reg ) + + COMPARE( Rax ); + COMPARE( Rdx ); + COMPARE( Rbx ); + COMPARE( Rbp ); + COMPARE( Rsi ); + COMPARE( Rdi ); + COMPARE( R8 ); + COMPARE( R9 ); + COMPARE( R10 ); + COMPARE( R11 ); + COMPARE( R12 ); + COMPARE( R13 ); + COMPARE( R14 ); + COMPARE( R15 ); + + for (i = 0; i < 16; i++) + ok( !memcmp( &contexts.before.Xmm0 + i, &contexts.after.Xmm0 + i, sizeof(contexts.before.Xmm0) ), + "wrong xmm%u %08I64x%08I64x/%08I64x%08I64x\n", i, *(&contexts.before.Xmm0.High + i*2), *(&contexts.before.Xmm0.Low + i*2), + *(&contexts.after.Xmm0.High + i*2), *(&contexts.after.Xmm0.Low + i*2) ); + +#undef COMPARE +} + static void test_wow64_context(void) { const char appname[] = "C:\\windows\\syswow64\\cmd.exe"; @@ -12459,6 +12623,7 @@ START_TEST(exception) test_debug_registers_wow64(); test_debug_service(1); test_simd_exceptions(); + test_continue(); test_virtual_unwind(); test___C_specific_handler(); test_restore_context(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4720
On Thu Jan 4 15:28:37 2024 +0000, Jinoh Kang wrote:
Nested Task surely breaks Wine; however, I cannot reproduce such breakage with Direction Flag. <https://testbot.winehq.org/JobDetails.pl?Key=141583> Therefore, I suggest that DF be included in the mask as well. (Did you make sure to test each flag separately?) Hmm that's weird, it fails 100% of time for me if I include it:
```diff diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 0c69287c15b..c938dbe37c4 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -4508,7 +4508,7 @@ static void test_continue(void) ~0x4000~ Nested task flag - not changing - breaks Wine = 0x8d5 */ - 0x48, 0x81, 0x34, 0x24, 0xd5, 0x08, 0x00, 0x00, /* xorq $0x8d5, (%rsp) */ + 0x48, 0x81, 0x34, 0x24, 0xd5, 0x0c, 0x00, 0x00, /* xorq $0xcd5, (%rsp) */ 0x9d, /* popf */ /* invoke NtContinue... */ @@ -4540,6 +4540,8 @@ static void test_continue(void) 0xc3 /* ret */ }; + printf("entering test_continue()\n"); + if (!pRtlCaptureContext) { win_skip("RtlCaptureContext is not available.\n"); @@ -4574,6 +4576,7 @@ static void test_continue(void) "wrong xmm%u %08I64x%08I64x/%08I64x%08I64x\n", i, *(&contexts.before.Xmm0.High + i*2), *(&contexts.before.Xmm0.Low + i*2), *(&contexts.after.Xmm0.High + i*2), *(&contexts.after.Xmm0.Low + i*2) ); + printf("leaving test_continue()\n"); #undef COMPARE } ``` ``` $ ./wine64 dlls/ntdll/tests/x86_64-windows/ntdll_test.exe exception exception.c:3849: exception: 00012345 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: 80000003 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: c0000008 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called entering test_continue() 0154:err:seh:call_stack_handlers invalid frame 00007FFFFE0FDE78 (00007FFFFE102000-00007FFFFE300000) 0154:err:seh:call_stack_handlers invalid frame 00007FFFFE0FCB28 (00007FFFFE102000-00007FFFFE300000) 0154:err:seh:NtRaiseException Exception frame is not in stack limits => unable to dispatch exception. ``` and without it ``` exception.c:3849: exception: 00012345 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: 80000003 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: c0000008 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called entering test_continue() leaving test_continue() [...] ``` Maybe it's some compiler flag? I'm on Arch Linux with mingw-w64-gcc 13.1.0 and it builds with ``` x86_64-w64-mingw32-gcc -c -o dlls/ntdll/tests/x86_64-windows/exception.o ../dlls/ntdll/tests/exception.c -Idlls/ntdll/tests -I../dlls/ntdll/tests \ -Iinclude -I../include -I../include/msvcrt -D_MSVCR_VER=0 -D__WINESRC__ -D__WINE_PE_BUILD -Wall \ -fno-strict-aliasing -Wdeclaration-after-statement -Wempty-body -Wignored-qualifiers -Winit-self \ -Wno-packed-not-aligned -Wshift-overflow=2 -Wstrict-prototypes -Wtype-limits \ -Wunused-but-set-parameter -Wvla -Wwrite-strings -Wpointer-arith -Wlogical-op -Wabsolute-value \ -Wenum-conversion -Wformat-overflow -Wnonnull -mcx16 -mcmodel=small -gdwarf-4 -g -O2 ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4720#note_57335
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=141827 Your paranoid android. === build (build log) === error: corrupt patch at line 39 Task: Patch failed to apply === debian11 (build log) === error: corrupt patch at line 39 Task: Patch failed to apply === debian11b (build log) === error: corrupt patch at line 39 Task: Patch failed to apply
On Sun Jan 14 16:10:35 2024 +0000, Dāvis Mosāns (davispuh) wrote:
Hmm that's weird, it fails 100% of time for me if I include it: ```diff diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 0c69287c15b..c938dbe37c4 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -4508,7 +4508,7 @@ static void test_continue(void) ~0x4000~ Nested task flag - not changing - breaks Wine = 0x8d5 */ - 0x48, 0x81, 0x34, 0x24, 0xd5, 0x08, 0x00, 0x00, /* xorq $0x8d5, (%rsp) */ + 0x48, 0x81, 0x34, 0x24, 0xd5, 0x0c, 0x00, 0x00, /* xorq $0xcd5, (%rsp) */ 0x9d, /* popf */ /* invoke NtContinue... */ @@ -4540,6 +4540,8 @@ static void test_continue(void) 0xc3 /* ret */ }; + printf("entering test_continue()\n"); + if (!pRtlCaptureContext) { win_skip("RtlCaptureContext is not available.\n"); @@ -4574,6 +4576,7 @@ static void test_continue(void) "wrong xmm%u %08I64x%08I64x/%08I64x%08I64x\n", i, *(&contexts.before.Xmm0.High + i*2), *(&contexts.before.Xmm0.Low + i*2), *(&contexts.after.Xmm0.High + i*2), *(&contexts.after.Xmm0.Low + i*2) ); + printf("leaving test_continue()\n"); #undef COMPARE } ``` ``` $ ./wine64 dlls/ntdll/tests/x86_64-windows/ntdll_test.exe exception exception.c:3849: exception: 00012345 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: 80000003 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: c0000008 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called entering test_continue() 0154:err:seh:call_stack_handlers invalid frame 00007FFFFE0FDE78 (00007FFFFE102000-00007FFFFE300000) 0154:err:seh:call_stack_handlers invalid frame 00007FFFFE0FCB28 (00007FFFFE102000-00007FFFFE300000) 0154:err:seh:NtRaiseException Exception frame is not in stack limits => unable to dispatch exception. ``` and without it ``` exception.c:3849: exception: 00012345 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: 80000003 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called exception.c:3849: exception: c0000008 flags:0 addr:00007FFFFEAA0010 context: Rip:00007FFFFEAA0010 exception.c:3960: Test marked todo: Frame handler called exception.c:3962: Test marked todo: UnhandledExceptionFilter wasn't called entering test_continue() leaving test_continue() [...] ``` Maybe it's some compiler flag? I'm on Arch Linux with mingw-w64-gcc 13.1.0 and it builds with ``` x86_64-w64-mingw32-gcc -c -o dlls/ntdll/tests/x86_64-windows/exception.o ../dlls/ntdll/tests/exception.c -Idlls/ntdll/tests -I../dlls/ntdll/tests \ -Iinclude -I../include -I../include/msvcrt -D_MSVCR_VER=0 -D__WINESRC__ -D__WINE_PE_BUILD -Wall \ -fno-strict-aliasing -Wdeclaration-after-statement -Wempty-body -Wignored-qualifiers -Winit-self \ -Wno-packed-not-aligned -Wshift-overflow=2 -Wstrict-prototypes -Wtype-limits \ -Wunused-but-set-parameter -Wvla -Wwrite-strings -Wpointer-arith -Wlogical-op -Wabsolute-value \ -Wenum-conversion -Wformat-overflow -Wnonnull -mcx16 -mcmodel=small -gdwarf-4 -g -O2 ``` You're right. My test was flawed. sorry.
This is actually a wine bug. `__wine_syscall_dispatcher` does execute `cld` but only for NT syscalls with 7 or mlre arguments. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4720#note_57372
Jinoh Kang (@iamahuman) commented about dlls/ntdll/tests/exception.c:
+ 0x0f, 0x28, 0xf0, /* movaps %xmm0, %xmm6 */ + 0x0f, 0x28, 0xf8, /* movaps %xmm0, %xmm7 */ + 0x44, 0x0f, 0x28, 0xc0, /* movaps %xmm0, %xmm8 */ + 0x44, 0x0f, 0x28, 0xc8, /* movaps %xmm0, %xmm9 */ + 0x44, 0x0f, 0x28, 0xd0, /* movaps %xmm0, %xmm10 */ + 0x44, 0x0f, 0x28, 0xd8, /* movaps %xmm0, %xmm11 */ + 0x44, 0x0f, 0x28, 0xe0, /* movaps %xmm0, %xmm12 */ + 0x44, 0x0f, 0x28, 0xe8, /* movaps %xmm0, %xmm13 */ + 0x44, 0x0f, 0x28, 0xf0, /* movaps %xmm0, %xmm14 */ + 0x44, 0x0f, 0x28, 0xf8, /* movaps %xmm0, %xmm15 */ + + /* FIXME: overwrite debug, x87 FPU and AVX registers to test those */ + + /* load args */ + 0x48, 0x8b, 0x4c, 0x24, 0x50, /* mov 8*10(%rsp), %rcx; context */ + 0x48, 0x8b, 0x54, 0x24, 0x58, /* mov 8*11(%rsp), %rdx; alertable */ Ditto.
```suggestion:-1+0 0x48, 0x8b, 0x4c, 0x24, 0x70, /* mov 8*14(%rsp), %rcx; context */ 0x48, 0x8b, 0x54, 0x24, 0x78, /* mov 8*15(%rsp), %rdx; alertable */ ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4720#note_57512
Jinoh Kang (@iamahuman) commented about dlls/ntdll/tests/exception.c:
+ 0x55, /* push %rbp; 8*7(rsp) */ + 0x56, /* push %rsi; 8*6(rsp) */ + 0x57, /* push %rdi; 8*5(rsp) */ + 0x41, 0x54, /* push %r12; 8*4(rsp) */ + 0x41, 0x55, /* push %r13; 8*3(rsp) */ + 0x41, 0x56, /* push %r14; 8*2(rsp) */ + 0x41, 0x57, /* push %r15; 8*1(rsp) */ + + 0x48, 0x83, 0xec, 0x08, /* sub $0x8, %rsp; reserve space for rsp */ + 0x48, 0x89, 0x24, 0x24, /* mov %rsp, (%rsp); for stack validation */ + + /* save args */ + 0x48, 0x89, 0x4c, 0x24, 0x50, /* mov %rcx, 8*10(%rsp) */ + 0x48, 0x89, 0x54, 0x24, 0x58, /* mov %rdx, 8*11(%rsp) */ + 0x4c, 0x89, 0x44, 0x24, 0x60, /* mov %r8, 8*12(%rsp) */ + 0x4c, 0x89, 0x4c, 0x24, 0x68, /* mov %r9, 8*13(%rsp) */ We still need to reserve outgoing register parameter save area for our callees (RtlCaptureContext, NtContinue).[^note] All non-leaf functions are required by x64 MS ABI to reserve home area for callees.
```suggestion:-19+0 /* ret at 8*13(rsp) */ /* need to preserve these */ 0x53, /* push %rbx; 8*12(rsp) */ 0x55, /* push %rbp; 8*11(rsp) */ 0x56, /* push %rsi; 8*10(rsp) */ 0x57, /* push %rdi; 8*9(rsp) */ 0x41, 0x54, /* push %r12; 8*8(rsp) */ 0x41, 0x55, /* push %r13; 8*7(rsp) */ 0x41, 0x56, /* push %r14; 8*6(rsp) */ 0x41, 0x57, /* push %r15; 8*5(rsp) */ 0x48, 0x83, 0xec, 0x28, /* sub $0x28, %rsp; reserve space for rsp and outgoing reg params */ 0x48, 0x89, 0x64, 0x24, 0x20, /* mov %rsp, 8*4(%rsp); for stack validation */ /* save args */ 0x48, 0x89, 0x4c, 0x24, 0x70, /* mov %rcx, 8*14(%rsp) */ 0x48, 0x89, 0x54, 0x24, 0x78, /* mov %rdx, 8*15(%rsp) */ 0x4c, 0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00, /* mov %r8, 8*16(%rsp) */ 0x4c, 0x89, 0x8c, 0x24, 0x88, 0x00, 0x00, 0x00, /* mov %r9, 8*17(%rsp) */ ``` [^note]: Yes, neither functions rarely ever need to modify its home area, but this is never guaranteed by future Windows versions. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4720#note_57511
Jinoh Kang (@iamahuman) commented about dlls/ntdll/tests/exception.c:
+ /* invoke NtContinue... */ + 0xff, 0x94, 0x24, 0xd0, 0x00, 0x00, 0x00, /* call *8*12+0x70(%rsp) */ + + /* validate stack pointer */ + 0x48, 0x8b, 0x0c, 0x24, /* 1: mov (%rsp), %rcx */ + 0x48, 0x39, 0xe1, /* cmp %rsp, %rcx */ + 0x74, 0x02, /* je 2f; jump over ud2 */ + 0x0f, 0x0b, /* ud2; stack pointer invalid, let's crash */ + + /* invoke capture context */ + 0x48, 0x8b, 0x4c, 0x24, 0x50, /* 2: mov 8*10(%rsp), %rcx; context */ + 0x48, 0x81, 0xc1, 0xd0, 0x04, 0x00, 0x00, /* add $0x4d0, %rcx; +sizeof(CONTEXT) to get context->after */ + 0xff, 0x54, 0x24, 0x68, /* call *8*13(%rsp) */ + + /* free stack */ + 0x48, 0x83, 0xc4, 0x08, /* add $0x8, %rsp */ Ditto.
```suggestion:-15+0 /* invoke NtContinue... */ 0xff, 0x94, 0x24, 0xf0, 0x00, 0x00, 0x00, /* call *8*16+0x70(%rsp) */ /* validate stack pointer */ 0x48, 0x3b, 0x64, 0x24, 0x20, /* 1: cmp 0x20(%rsp), %rsp */ 0x74, 0x02, /* je 2f; jump over ud2 */ 0x0f, 0x0b, /* ud2; stack pointer invalid, let's crash */ /* invoke capture context */ 0x48, 0x8b, 0x4c, 0x24, 0x70, /* 2: mov 8*14(%rsp), %rcx; context */ 0x48, 0x81, 0xc1, 0xd0, 0x04, 0x00, 0x00, /* add $0x4d0, %rcx; +sizeof(CONTEXT) to get context->after */ 0xff, 0x94, 0x24, 0x88, 0x00, 0x00, 0x00, /* call *8*17(%rsp) */ /* free stack */ 0x48, 0x83, 0xc4, 0x28, /* add $0x28, %rsp */ ``` While we're at it, I've consolidated mov-cmp sequence into just one cmp. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4720#note_57513
participants (3)
-
Dāvis Mosāns -
Jinoh Kang (@iamahuman) -
Marvin