Paul Gofman : ntdll/tests: Test AVX context with debugger.

Alexandre Julliard julliard at winehq.org
Tue Oct 13 15:42:05 CDT 2020


Module: wine
Branch: master
Commit: fa409a91b0f13e478a43c9adc84d3c870bbae432
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fa409a91b0f13e478a43c9adc84d3c870bbae432

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Fri Oct  9 16:03:56 2020 +0300

ntdll/tests: Test AVX context with debugger.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/tests/exception.c | 144 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 127 insertions(+), 17 deletions(-)

diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 07b813ac1f..b2331b739a 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -189,6 +189,67 @@ static BOOL     is_wow64;
 static BOOL have_vectored_api;
 static int test_stage;
 
+#if defined(__i386__) || defined(__x86_64__)
+static void test_debugger_xstate(HANDLE thread, CONTEXT *ctx, int stage)
+{
+    char context_buffer[sizeof(CONTEXT) + sizeof(CONTEXT_EX) + sizeof(XSTATE) + 63];
+    CONTEXT_EX *c_ex;
+    NTSTATUS status;
+    YMMCONTEXT *ymm;
+    CONTEXT *xctx;
+    DWORD length;
+    XSTATE *xs;
+    M128A *xmm;
+    BOOL bret;
+
+    if (!pRtlGetEnabledExtendedFeatures || !pRtlGetEnabledExtendedFeatures(1 << XSTATE_AVX))
+        return;
+
+    if (stage == 14)
+        return;
+
+    length = sizeof(context_buffer);
+    bret = pInitializeContext(context_buffer, ctx->ContextFlags | CONTEXT_XSTATE, &xctx, &length);
+    ok(bret, "Got unexpected bret %#x, GetLastError() %u.\n", bret, GetLastError());
+
+    ymm = pLocateXStateFeature(xctx, XSTATE_AVX, &length);
+    ok(!!ymm, "Got zero ymm.\n");
+    memset(ymm, 0xcc, sizeof(*ymm));
+
+    xmm = pLocateXStateFeature(xctx, XSTATE_LEGACY_SSE, &length);
+    ok(length == sizeof(*xmm) * (sizeof(void *) == 8 ? 16 : 8), "Got unexpected length %#x.\n", length);
+    ok(!!xmm, "Got zero xmm.\n");
+    memset(xmm, 0xcc, length);
+
+    status = pNtGetContextThread(thread, xctx);
+    ok(!status, "NtSetContextThread failed with 0x%x\n", status);
+
+    c_ex = (CONTEXT_EX *)(xctx + 1);
+    xs = (XSTATE *)((char *)c_ex + c_ex->XState.Offset);
+    ok((xs->Mask & 7) == 4 || broken(!xs->Mask) /* Win7 */,
+            "Got unexpected xs->Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+
+    ok(xmm[0].Low == 0x200000001, "Got unexpected data %s.\n", wine_dbgstr_longlong(xmm[0].Low));
+    ok(xmm[0].High == 0x400000003, "Got unexpected data %s.\n", wine_dbgstr_longlong(xmm[0].High));
+
+    ok(ymm->Ymm0.Low == 0x600000005 || broken(!xs->Mask && ymm->Ymm0.Low == 0xcccccccccccccccc) /* Win7 */,
+            "Got unexpected data %s.\n", wine_dbgstr_longlong(ymm->Ymm0.Low));
+    ok(ymm->Ymm0.High == 0x800000007 || broken(!xs->Mask && ymm->Ymm0.High == 0xcccccccccccccccc) /* Win7 */,
+            "Got unexpected data %s.\n", wine_dbgstr_longlong(ymm->Ymm0.High));
+
+    xmm = pLocateXStateFeature(ctx, XSTATE_LEGACY_SSE, &length);
+    ok(!!xmm, "Got zero xmm.\n");
+
+    xmm[0].Low = 0x2828282828282828;
+    xmm[0].High = xmm[0].Low;
+    ymm->Ymm0.Low = 0x4848484848484848;
+    ymm->Ymm0.High = ymm->Ymm0.Low;
+
+    status = pNtSetContextThread(thread, xctx);
+    ok(!status, "NtSetContextThread failed with 0x%x\n", status);
+}
+#endif
+
 #ifdef __i386__
 
 #ifndef __WINE_WINTRNL_H
@@ -1055,7 +1116,7 @@ static void test_debugger(void)
                                           sizeof(stage), &size_read);
             ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
 
-            ctx.ContextFlags = CONTEXT_FULL;
+            ctx.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS;
             status = pNtGetContextThread(pi.hThread, &ctx);
             ok(!status, "NtGetContextThread failed with 0x%x\n", status);
 
@@ -1156,6 +1217,10 @@ static void test_debugger(void)
 
                     if (stage == 12|| stage == 13) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
                 }
+                else if (stage == 14 || stage == 15)
+                {
+                    test_debugger_xstate(pi.hThread, &ctx, stage);
+                }
                 else
                     ok(FALSE, "unexpected stage %x\n", stage);
 
@@ -3331,6 +3396,10 @@ static void test_debugger(void)
 
                     if (stage == 12|| stage == 13) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
                 }
+                else if (stage == 14 || stage == 15)
+                {
+                    test_debugger_xstate(pi.hThread, &ctx, stage);
+                }
                 else
                     ok(FALSE, "unexpected stage %x\n", stage);
 
@@ -5957,6 +6026,57 @@ static void test_breakpoint(DWORD numexc)
     pRtlRemoveVectoredExceptionHandler(vectored_handler);
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+static BYTE except_code_set_ymm0[] =
+{
+#ifdef __x86_64__
+    0x48,
+#endif
+    0xb8,                         /* mov imm,%ax */
+    0x00, 0x00, 0x00, 0x00,
+#ifdef __x86_64__
+    0x00, 0x00, 0x00, 0x00,
+#endif
+
+    0xc5, 0xfc, 0x10, 0x00,       /* vmovups (%ax),%ymm0 */
+    0xcc,                         /* int3 */
+    0xc5, 0xfc, 0x11, 0x00,       /* vmovups %ymm0,(%ax) */
+    0xc3,                         /* ret  */
+};
+
+static void test_debuggee_xstate(void)
+{
+    void (CDECL *func)(void) = code_mem;
+    unsigned int address_offset, i;
+    unsigned int data[8];
+
+    if (!pRtlGetEnabledExtendedFeatures || !pRtlGetEnabledExtendedFeatures(1 << XSTATE_AVX))
+    {
+        memcpy(code_mem, breakpoint_code, sizeof(breakpoint_code));
+        func();
+        return;
+    }
+
+    memcpy(code_mem, except_code_set_ymm0, sizeof(except_code_set_ymm0));
+    address_offset = sizeof(void *) == 8 ? 2 : 1;
+    *(void **)((BYTE *)code_mem + address_offset) = data;
+
+    for (i = 0; i < ARRAY_SIZE(data); ++i)
+        data[i] = i + 1;
+
+    func();
+
+    for (i = 0; i < 4; ++i)
+        ok(data[i] == (test_stage == 14 ? i + 1 : 0x28282828),
+                "Got unexpected data %#x, test_stage %u, i %u.\n", data[i], test_stage, i);
+
+    for (     ; i < ARRAY_SIZE(data); ++i)
+        ok(data[i] == (test_stage == 14 ? i + 1 : 0x48484848)
+                || broken(test_stage == 15 && data[i] == i + 1) /* Win7 */,
+                "Got unexpected data %#x, test_stage %u, i %u.\n", data[i], test_stage, i);
+}
+#endif
+
 static DWORD invalid_handle_exceptions;
 
 static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
@@ -6593,22 +6713,6 @@ static void wait_for_thread_next_suspend(HANDLE thread)
 
 static void test_extended_context(void)
 {
-    static BYTE except_code_set_ymm0[] =
-    {
-#ifdef __x86_64__
-        0x48,
-#endif
-        0xb8,                         /* mov imm,%ax */
-        0x00, 0x00, 0x00, 0x00,
-#ifdef __x86_64__
-        0x00, 0x00, 0x00, 0x00,
-#endif
-
-        0xc5, 0xfc, 0x10, 0x00,       /* vmovups (%ax),%ymm0 */
-        0xcc,                         /* int3 */
-        0xc5, 0xfc, 0x11, 0x00,       /* vmovups %ymm0,(%ax) */
-        0xc3,                         /* ret  */
-    };
     static BYTE except_code_reset_ymm_state[] =
     {
 #ifdef __x86_64__
@@ -8029,6 +8133,12 @@ START_TEST(exception)
         test_closehandle(1, (HANDLE)0xdeadbeef);
         test_stage = 13;
         test_closehandle(0, 0); /* Special case. */
+#if defined(__i386__) || defined(__x86_64__)
+        test_stage = 14;
+        test_debuggee_xstate();
+        test_stage = 15;
+        test_debuggee_xstate();
+#endif
 
         /* rest of tests only run in parent */
         return;




More information about the wine-cvs mailing list