Reactos

[NTDLL_APITEST] Implement NtContinue test for x64

+122 -18
+2
modules/rostests/apitests/ntdll/CMakeLists.txt
··· 100 100 101 101 if(ARCH STREQUAL "i386") 102 102 add_asm_files(ntdll_apitest_asm i386/NtContinue.S) 103 + elseif(ARCH STREQUAL "amd64") 104 + add_asm_files(ntdll_apitest_asm amd64/NtContinue.S) 103 105 endif() 104 106 105 107 list(APPEND PCH_SKIP_SOURCE
+82 -18
modules/rostests/apitests/ntdll/NtContinue.c
··· 10 10 #include <setjmp.h> 11 11 #include <time.h> 12 12 13 + #ifdef _MSC_VER 14 + #pragma runtime_checks("s", off) 15 + #endif 16 + 17 + #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected) 18 + #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "%lx") 19 + #define ok_eq_hex64(value, expected) ok_eq_print(value, expected, "%I64x") 20 + #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) 21 + 13 22 #ifdef _M_IX86 14 23 #define NTC_SEGMENT_BITS (0xFFFF) 15 24 #define NTC_EFLAGS_BITS (0x3C0CD5) ··· 121 130 ok((pContext->SegSs & NTC_SEGMENT_BITS) == 122 131 (continueContext.SegSs & NTC_SEGMENT_BITS), 123 132 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs); 133 + #else 134 + ok_eq_hex64(pContext->ContextFlags, CONTEXT_FULL | CONTEXT_SEGMENTS); 135 + ok_eq_hex(pContext->MxCsr, continueContext.MxCsr); 136 + ok_eq_hex(pContext->SegCs, continueContext.SegCs); 137 + ok_eq_hex(pContext->SegDs, 0x2B); 138 + ok_eq_hex(pContext->SegEs, 0x2B); 139 + ok_eq_hex(pContext->SegFs, 0x53); 140 + ok_eq_hex(pContext->SegGs, 0x2B); 141 + ok_eq_hex(pContext->SegSs, continueContext.SegSs); 142 + ok_eq_hex(pContext->EFlags, (continueContext.EFlags & ~0x1C0000) | 0x202); 143 + 144 + ok_eq_hex64(pContext->Rax, continueContext.Rax); 145 + ok_eq_hex64(pContext->Rdx, continueContext.Rdx); 146 + ok_eq_hex64(pContext->Rbx, continueContext.Rbx); 147 + ok_eq_hex64(pContext->Rsp, continueContext.Rsp); 148 + ok_eq_hex64(pContext->Rbp, continueContext.Rbp); 149 + ok_eq_hex64(pContext->Rsi, continueContext.Rsi); 150 + ok_eq_hex64(pContext->Rdi, continueContext.Rdi); 151 + ok_eq_hex64(pContext->R8, continueContext.R8); 152 + ok_eq_hex64(pContext->R9, continueContext.R9); 153 + ok_eq_hex64(pContext->R10, continueContext.R10); 154 + ok_eq_hex64(pContext->R11, continueContext.R11); 155 + ok_eq_hex64(pContext->R12, continueContext.R12); 156 + ok_eq_hex64(pContext->R13, continueContext.R13); 157 + ok_eq_hex64(pContext->R14, continueContext.R14); 158 + ok_eq_hex64(pContext->R15, continueContext.R15); 159 + ok_eq_xmm(pContext->Xmm0, continueContext.Xmm0); 160 + ok_eq_xmm(pContext->Xmm1, continueContext.Xmm1); 161 + ok_eq_xmm(pContext->Xmm2, continueContext.Xmm2); 162 + ok_eq_xmm(pContext->Xmm3, continueContext.Xmm3); 163 + ok_eq_xmm(pContext->Xmm4, continueContext.Xmm4); 164 + ok_eq_xmm(pContext->Xmm5, continueContext.Xmm5); 165 + ok_eq_xmm(pContext->Xmm6, continueContext.Xmm6); 166 + ok_eq_xmm(pContext->Xmm7, continueContext.Xmm7); 167 + ok_eq_xmm(pContext->Xmm8, continueContext.Xmm8); 168 + ok_eq_xmm(pContext->Xmm9, continueContext.Xmm9); 169 + ok_eq_xmm(pContext->Xmm10, continueContext.Xmm10); 170 + ok_eq_xmm(pContext->Xmm11, continueContext.Xmm11); 171 + ok_eq_xmm(pContext->Xmm12, continueContext.Xmm12); 172 + ok_eq_xmm(pContext->Xmm13, continueContext.Xmm13); 173 + ok_eq_xmm(pContext->Xmm14, continueContext.Xmm14); 174 + ok_eq_xmm(pContext->Xmm15, continueContext.Xmm15); 175 + 176 + // Clear the frame register to prevent unwinding, which is broken 177 + ((_JUMP_BUFFER*)&jmpbuf)->Frame = 0; 124 178 #endif 125 179 126 180 /* Return where we came from */ ··· 129 183 130 184 START_TEST(NtContinue) 131 185 { 132 - #ifdef __RUNTIME_CHECKS__ 133 - skip("This test breaks MSVC runtime checks!\n"); 134 - return; 135 - #endif /* __RUNTIME_CHECKS__ */ 136 186 initrand(); 187 + 188 + RtlFillMemory(&continueContext, sizeof(continueContext), 0xBBBBBBBB); 137 189 138 190 /* First time */ 139 191 if(setjmp(jmpbuf) == 0) 140 192 { 141 - CONTEXT bogus; 193 + CONTEXT bogus[2]; 194 + 195 + RtlFillMemory(&bogus, sizeof(bogus), 0xCCCCCCCC); 142 196 143 197 continueContext.ContextFlags = CONTEXT_FULL; 144 198 GetThreadContext(GetCurrentThread(), &continueContext); ··· 167 221 168 222 /* Can't do a lot about segments */ 169 223 #elif defined(_M_AMD64) 170 - continueContext.ContextFlags = CONTEXT_FULL; 224 + continueContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 171 225 172 226 /* Fill the integer registers with random values */ 173 - continueContext.Rdi = randULONG64(); 174 - continueContext.Rsi = randULONG64(); 175 - continueContext.Rbx = randULONG64(); 176 - continueContext.Rdx = randULONG64(); 177 - continueContext.Rcx = randULONG64(); 178 - continueContext.Rax = randULONG64(); 179 - continueContext.Rbp = randULONG64(); 227 + PULONG64 Registers = &continueContext.Rax; 228 + for (ULONG i = 0; i < 16; i++) 229 + { 230 + Registers[i] = randULONG64(); 231 + } 232 + 233 + /* Fill the XMM registers with random values */ 234 + Registers = (PULONG64)&continueContext.Xmm0; 235 + for (ULONG i = 0; i < 32; i++) 236 + { 237 + Registers[i] = randULONG64(); 238 + } 239 + 240 + continueContext.Dr0 = randULONG64() & 0xFFFF; 241 + continueContext.Dr1 = randULONG64() & 0xFFFF; 242 + continueContext.Dr2 = randULONG64() & 0xFFFF; 243 + continueContext.Dr3 = randULONG64() & 0xFFFF; 244 + continueContext.Dr6 = randULONG64() & 0xFFFF; 245 + continueContext.Dr7 = randULONG64() & 0xFFFF; 180 246 181 247 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 182 248 continueContext.EFlags = randULONG64() & 0x3C0CD5; 183 249 184 250 /* Randomize the stack pointer as much as possible */ 185 - continueContext.Rsp = (((ULONG_PTR)&bogus)) + 186 - sizeof(bogus) - (randULONG() & 0xF) * 4; 251 + continueContext.Rsp = (((ULONG_PTR)&bogus)) + (randULONG() & 0xF) * 16; 252 + continueContext.Rsp = ALIGN_DOWN_BY(continueContext.Rsp, 16); 187 253 188 254 /* continuePoint() is implemented in assembler */ 189 - //continueContext.Rip = ((ULONG_PTR)continuePoint); 190 - skip("NtContinue test does not yet work on x64."); 191 - return; 255 + continueContext.Rip = ((ULONG_PTR)continuePoint); 192 256 #endif 193 257 194 258 NtContinue(&continueContext, FALSE);
+38
modules/rostests/apitests/ntdll/amd64/NtContinue.S
··· 1 + /* 2 + * PROJECT: ReactOS API tests 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Helper functions for NtContinue test 5 + * COPYRIGHT: Copyright 2022 Timo Kreuzer (timo.kreuzer@reactos.org) 6 + */ 7 + 8 + #include <asm.inc> 9 + #include <ksamd64.inc> 10 + 11 + .code64 12 + 13 + EXTERN RtlCaptureContext:PROC 14 + EXTERN check:PROC 15 + 16 + PUBLIC continuePoint 17 + .PROC continuePoint 18 + 19 + // Allocate space for a CONTEXT structure 20 + .ALLOCSTACK CONTEXT_FRAME_LENGTH + 8 21 + .ENDPROLOG 22 + 23 + // Capture the current CONTEXT 24 + mov rcx, rsp 25 + call RtlCaptureContext 26 + 27 + // Call the function that will compare the current context with the expected one 28 + cld 29 + mov rcx, rsp 30 + call check 31 + 32 + // check() must not return 33 + int 3 34 + 35 + .ENDP 36 + 37 + // EOF 38 + END