https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6744368755d3ae2ab0d2af5bd3cbd27679b62e3e

commit 6744368755d3ae2ab0d2af5bd3cbd27679b62e3e
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sun Aug 21 16:21:10 2022 +0200
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Thu Nov 24 21:17:58 2022 +0200

    [NTDLL_APITEST] Implement NtContinue test for x64
---
 modules/rostests/apitests/ntdll/CMakeLists.txt     |   2 +
 modules/rostests/apitests/ntdll/NtContinue.c       | 100 +++++++++++++++++----
 modules/rostests/apitests/ntdll/amd64/NtContinue.S |  38 ++++++++
 3 files changed, 122 insertions(+), 18 deletions(-)

diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt 
b/modules/rostests/apitests/ntdll/CMakeLists.txt
index c2ec474a5a0..2e38c4ec7b5 100644
--- a/modules/rostests/apitests/ntdll/CMakeLists.txt
+++ b/modules/rostests/apitests/ntdll/CMakeLists.txt
@@ -100,6 +100,8 @@ list(APPEND SOURCE
 
 if(ARCH STREQUAL "i386")
     add_asm_files(ntdll_apitest_asm i386/NtContinue.S)
+elseif(ARCH STREQUAL "amd64")
+    add_asm_files(ntdll_apitest_asm amd64/NtContinue.S)
 endif()
 
 list(APPEND PCH_SKIP_SOURCE
diff --git a/modules/rostests/apitests/ntdll/NtContinue.c 
b/modules/rostests/apitests/ntdll/NtContinue.c
index 334c85056a2..f159c7bf3f7 100644
--- a/modules/rostests/apitests/ntdll/NtContinue.c
+++ b/modules/rostests/apitests/ntdll/NtContinue.c
@@ -10,6 +10,15 @@
 #include <setjmp.h>
 #include <time.h>
 
+#ifdef _MSC_VER
+#pragma runtime_checks("s", off)
+#endif
+
+#define ok_eq_print(value, expected, spec)  ok((value) == (expected), #value " 
= " spec ", expected " spec "\n", value, expected)
+#define ok_eq_hex(value, expected)          ok_eq_print(value, expected, "%lx")
+#define ok_eq_hex64(value, expected)        ok_eq_print(value, expected, 
"%I64x")
+#define ok_eq_xmm(value, expected)          ok((value).Low == (expected).Low, 
#value " = %I64x'%08I64x, expected %I64x'%08I64x\n", (value).Low, (value).High, 
(expected).Low, (expected).High)
+
 #ifdef _M_IX86
 #define NTC_SEGMENT_BITS (0xFFFF)
 #define NTC_EFLAGS_BITS  (0x3C0CD5)
@@ -121,6 +130,51 @@ void check(CONTEXT * pContext)
     ok((pContext->SegSs & NTC_SEGMENT_BITS) ==
        (continueContext.SegSs & NTC_SEGMENT_BITS),
        "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs);
+#else
+    ok_eq_hex64(pContext->ContextFlags, CONTEXT_FULL | CONTEXT_SEGMENTS);
+    ok_eq_hex(pContext->MxCsr, continueContext.MxCsr);
+    ok_eq_hex(pContext->SegCs, continueContext.SegCs);
+    ok_eq_hex(pContext->SegDs, 0x2B);
+    ok_eq_hex(pContext->SegEs, 0x2B);
+    ok_eq_hex(pContext->SegFs, 0x53);
+    ok_eq_hex(pContext->SegGs, 0x2B);
+    ok_eq_hex(pContext->SegSs, continueContext.SegSs);
+    ok_eq_hex(pContext->EFlags, (continueContext.EFlags & ~0x1C0000) | 0x202);
+
+    ok_eq_hex64(pContext->Rax, continueContext.Rax);
+    ok_eq_hex64(pContext->Rdx, continueContext.Rdx);
+    ok_eq_hex64(pContext->Rbx, continueContext.Rbx);
+    ok_eq_hex64(pContext->Rsp, continueContext.Rsp);
+    ok_eq_hex64(pContext->Rbp, continueContext.Rbp);
+    ok_eq_hex64(pContext->Rsi, continueContext.Rsi);
+    ok_eq_hex64(pContext->Rdi, continueContext.Rdi);
+    ok_eq_hex64(pContext->R8, continueContext.R8);
+    ok_eq_hex64(pContext->R9, continueContext.R9);
+    ok_eq_hex64(pContext->R10, continueContext.R10);
+    ok_eq_hex64(pContext->R11, continueContext.R11);
+    ok_eq_hex64(pContext->R12, continueContext.R12);
+    ok_eq_hex64(pContext->R13, continueContext.R13);
+    ok_eq_hex64(pContext->R14, continueContext.R14);
+    ok_eq_hex64(pContext->R15, continueContext.R15);
+    ok_eq_xmm(pContext->Xmm0, continueContext.Xmm0);
+    ok_eq_xmm(pContext->Xmm1, continueContext.Xmm1);
+    ok_eq_xmm(pContext->Xmm2, continueContext.Xmm2);
+    ok_eq_xmm(pContext->Xmm3, continueContext.Xmm3);
+    ok_eq_xmm(pContext->Xmm4, continueContext.Xmm4);
+    ok_eq_xmm(pContext->Xmm5, continueContext.Xmm5);
+    ok_eq_xmm(pContext->Xmm6, continueContext.Xmm6);
+    ok_eq_xmm(pContext->Xmm7, continueContext.Xmm7);
+    ok_eq_xmm(pContext->Xmm8, continueContext.Xmm8);
+    ok_eq_xmm(pContext->Xmm9, continueContext.Xmm9);
+    ok_eq_xmm(pContext->Xmm10, continueContext.Xmm10);
+    ok_eq_xmm(pContext->Xmm11, continueContext.Xmm11);
+    ok_eq_xmm(pContext->Xmm12, continueContext.Xmm12);
+    ok_eq_xmm(pContext->Xmm13, continueContext.Xmm13);
+    ok_eq_xmm(pContext->Xmm14, continueContext.Xmm14);
+    ok_eq_xmm(pContext->Xmm15, continueContext.Xmm15);
+
+    // Clear the frame register to prevent unwinding, which is broken
+    ((_JUMP_BUFFER*)&jmpbuf)->Frame = 0;
 #endif
 
     /* Return where we came from */
@@ -129,16 +183,16 @@ void check(CONTEXT * pContext)
 
 START_TEST(NtContinue)
 {
-#ifdef __RUNTIME_CHECKS__
-    skip("This test breaks MSVC runtime checks!\n");
-    return;
-#endif /* __RUNTIME_CHECKS__ */
     initrand();
 
+    RtlFillMemory(&continueContext, sizeof(continueContext), 0xBBBBBBBB);
+
     /* First time */
     if(setjmp(jmpbuf) == 0)
     {
-        CONTEXT bogus;
+        CONTEXT bogus[2];
+
+        RtlFillMemory(&bogus, sizeof(bogus), 0xCCCCCCCC);
 
         continueContext.ContextFlags = CONTEXT_FULL;
         GetThreadContext(GetCurrentThread(), &continueContext);
@@ -167,28 +221,38 @@ START_TEST(NtContinue)
 
         /* Can't do a lot about segments */
 #elif defined(_M_AMD64)
-        continueContext.ContextFlags = CONTEXT_FULL;
+        continueContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
 
         /* Fill the integer registers with random values */
-        continueContext.Rdi = randULONG64();
-        continueContext.Rsi = randULONG64();
-        continueContext.Rbx = randULONG64();
-        continueContext.Rdx = randULONG64();
-        continueContext.Rcx = randULONG64();
-        continueContext.Rax = randULONG64();
-        continueContext.Rbp = randULONG64();
+        PULONG64 Registers = &continueContext.Rax;
+        for (ULONG i = 0; i < 16; i++)
+        {
+            Registers[i] = randULONG64();
+        }
+
+        /* Fill the XMM registers with random values */
+        Registers = (PULONG64)&continueContext.Xmm0;
+        for (ULONG i = 0; i < 32; i++)
+        {
+            Registers[i] = randULONG64();
+        }
+
+        continueContext.Dr0 = randULONG64() & 0xFFFF;
+        continueContext.Dr1 = randULONG64() & 0xFFFF;
+        continueContext.Dr2 = randULONG64() & 0xFFFF;
+        continueContext.Dr3 = randULONG64() & 0xFFFF;
+        continueContext.Dr6 = randULONG64() & 0xFFFF;
+        continueContext.Dr7 = randULONG64() & 0xFFFF;
 
         /* Randomize all the allowed flags (determined experimentally with 
WinDbg) */
         continueContext.EFlags = randULONG64() & 0x3C0CD5;
 
         /* Randomize the stack pointer as much as possible */
-        continueContext.Rsp = (((ULONG_PTR)&bogus)) +
-            sizeof(bogus) - (randULONG() & 0xF) * 4;
+        continueContext.Rsp = (((ULONG_PTR)&bogus)) + (randULONG() & 0xF) * 16;
+        continueContext.Rsp = ALIGN_DOWN_BY(continueContext.Rsp, 16);
 
         /* continuePoint() is implemented in assembler */
-        //continueContext.Rip = ((ULONG_PTR)continuePoint);
-        skip("NtContinue test does not yet work on x64.");
-        return;
+        continueContext.Rip = ((ULONG_PTR)continuePoint);
 #endif
 
         NtContinue(&continueContext, FALSE);
diff --git a/modules/rostests/apitests/ntdll/amd64/NtContinue.S 
b/modules/rostests/apitests/ntdll/amd64/NtContinue.S
new file mode 100644
index 00000000000..40304d94122
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/amd64/NtContinue.S
@@ -0,0 +1,38 @@
+/*
+ * PROJECT:     ReactOS API tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Helper functions for NtContinue test
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer ([email protected])
+ */
+
+#include <asm.inc>
+#include <ksamd64.inc>
+
+.code64
+
+EXTERN RtlCaptureContext:PROC
+EXTERN check:PROC
+
+PUBLIC continuePoint
+.PROC continuePoint
+
+    // Allocate space for a CONTEXT structure
+    .ALLOCSTACK CONTEXT_FRAME_LENGTH + 8
+    .ENDPROLOG
+
+    // Capture the current CONTEXT
+    mov rcx, rsp
+    call RtlCaptureContext
+
+    // Call the function that will compare the current context with the 
expected one
+    cld
+    mov rcx, rsp
+    call check
+
+    // check() must not return
+    int 3
+
+.ENDP
+
+// EOF
+END

Reply via email to