25 #define WIN32_NO_STATUS 26 #define NONAMELESSUNION 57 #if defined(__x86_64__) 79 void* LanguageHandler;
81 PUNWIND_HISTORY_TABLE HistoryTable;
85 typedef struct _SETJMP_FLOAT128
90 typedef
struct _JUMP_BUFFER
104 SETJMP_FLOAT128 Xmm6;
105 SETJMP_FLOAT128 Xmm7;
106 SETJMP_FLOAT128 Xmm8;
107 SETJMP_FLOAT128 Xmm9;
108 SETJMP_FLOAT128 Xmm10;
109 SETJMP_FLOAT128 Xmm11;
110 SETJMP_FLOAT128 Xmm12;
111 SETJMP_FLOAT128 Xmm13;
112 SETJMP_FLOAT128 Xmm14;
113 SETJMP_FLOAT128 Xmm15;
115 #endif // __REACTOS__ 125 static int (
CDECL *p_setjmp)(_JUMP_BUFFER*);
130 #ifndef __WINE_WINTRNL_H 131 #define ProcessExecuteFlags 0x22 132 #define MEM_EXECUTE_OPTION_DISABLE 0x01 133 #define MEM_EXECUTE_OPTION_ENABLE 0x02 134 #define MEM_EXECUTE_OPTION_PERMANENT 0x08 138 static char** my_argv;
139 static int test_stage;
174 { { 0xe4, 0x11, 0xc3 },
176 { { 0xe5, 0x11, 0xc3 },
178 { { 0xe6, 0x11, 0xc3 },
180 { { 0xe7, 0x11, 0xc3 },
195 { { 0xea, 0, 0, 0, 0, 0, 0, 0xc3 },
200 { { 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xcf, 0x83, 0xc4, 0x0c, 0xc3 },
205 { { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 },
209 { { 0x06, 0x31, 0xc0, 0x8e, 0xc0, 0x26, 0xa1, 0, 0, 0, 0, 0x07, 0xc3 },
212 { { 0x0f, 0xa8, 0x31, 0xc0, 0x8e, 0xe8, 0x65, 0xa1, 0, 0, 0, 0, 0x0f, 0xa9, 0xc3 },
217 { { 0x0e, 0x17, 0x58, 0xc3 },
222 { { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
225 { { 0x64,0x64,0x64,0x64,0xfa,0xc3 },
229 { { 0xcd, 0xff, 0xc3 },
233 { { 0x0f, 0x20, 0xc0, 0xc3 },
235 { { 0x0f, 0x20, 0xe0, 0xc3 },
238 { { 0x0f, 0x22, 0xc0, 0xc3 },
240 { { 0x0f, 0x22, 0xe0, 0xc3 },
244 { { 0x0f, 0x21, 0xc0, 0xc3 },
246 { { 0x0f, 0x21, 0xc8, 0xc3 },
248 { { 0x0f, 0x21, 0xf8, 0xc3 },
251 { { 0x0f, 0x23, 0xc0, 0xc3 },
253 { { 0x0f, 0x23, 0xc8, 0xc3 },
255 { { 0x0f, 0x23, 0xf8, 0xc3 },
259 { { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xc3 },
261 { { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xc3 },
264 { { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xc3 },
266 { { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xc3 },
270 { { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xc3 },
272 { { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xc3 },
274 { { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xc3 },
277 { { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xc3 },
281 { { 0x1e, 0x06, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfa, 0x07, 0x1f, 0xc3 },
285 { { 0xf1, 0x90, 0xc3 },
287 { { 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
288 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
289 0xba, 0xba, 0xba, 0xba, 0xba,
294 static int got_exception;
295 static BOOL have_vectored_api;
297 static void run_exception_test(
void *
handler,
const void*
context,
298 const void *
code,
unsigned int code_size,
306 DWORD oldaccess, oldaccess2;
308 exc_frame.frame.Handler =
handler;
309 exc_frame.frame.Prev =
NtCurrentTeb()->Tib.ExceptionList;
318 NtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
335 ok((
void *)
context->Eax == pRtlRaiseException ||
337 "debugger managed to modify Eax to %x should be %p\n",
338 context->Eax, pRtlRaiseException);
347 "Eip at %x instead of %x or %x\n",
context->Eip,
364 trace(
"exception: %08x flags:%x addr:%p context: Eip:%x\n",
377 "Eip at %x instead of %x or %x\n",
context->Eip,
386 if(have_vectored_api)
387 ok(
context->Eax == 0xf00f00f0,
"Eax is %x, should have been set to 0xf00f00f0 in vectored handler\n",
403 static const BYTE call_one_arg_code[] = {
404 0x8b, 0x44, 0x24, 0x08,
406 0x8b, 0x44, 0x24, 0x08,
416 static void run_rtlraiseexception_test(
DWORD exceptioncode)
424 record.ExceptionCode = exceptioncode;
425 record.ExceptionFlags = 0;
428 record.NumberParameters = 0;
430 frame.
Handler = rtlraiseexception_handler;
436 if (have_vectored_api)
438 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &rtlraiseexception_vectored_handler);
439 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
444 "address set to %p instead of %p\n",
record.ExceptionAddress, (
char *)
code_mem + 0x0b );
446 if (have_vectored_api)
447 pRtlRemoveVectoredExceptionHandler(vectored_handler);
451 static void test_rtlraiseexception(
void)
453 if (!pRtlRaiseException)
455 skip(
"RtlRaiseException not found\n");
460 run_rtlraiseexception_test(0x12345);
465 static DWORD unwind_expected_eax;
470 trace(
"exception: %08x flags:%x addr:%p context: Eip:%x\n",
477 ok(
context->Eax == unwind_expected_eax,
"context->Eax is %08x instead of %08x\n",
478 context->Eax, unwind_expected_eax);
484 static const BYTE call_unwind_code[] = {
489 0xe8, 0x00, 0x00, 0x00, 0x00,
491 0x05, 0x1e, 0x00, 0x00, 0x00,
492 0xff, 0x74, 0x24, 0x20,
493 0xff, 0x74, 0x24, 0x20,
495 0xff, 0x74, 0x24, 0x24,
496 0x8B, 0x44, 0x24, 0x24,
506 static void test_unwind(
void)
515 frame1->Handler = unwind_handler;
520 frame2->
Handler = unwind_handler;
525 unwind_expected_eax = 0xDEAD0000;
526 retval =
func(pRtlUnwind, frame2,
NULL, 0xDEAD0000);
527 ok(retval == 0xDEAD0000,
"RtlUnwind returned eax %08x instead of %08x\n", retval, 0xDEAD0000);
528 ok(
NtCurrentTeb()->Tib.ExceptionList == frame2,
"Exception record points to %p instead of %p\n",
532 unwind_expected_eax = 0xDEAD0000;
533 retval =
func(pRtlUnwind, frame1,
NULL, 0xDEAD0000);
534 ok(retval == 0xDEAD0001,
"RtlUnwind returned eax %08x instead of %08x\n", retval, 0xDEAD0001);
535 ok(
NtCurrentTeb()->Tib.ExceptionList == frame1,
"Exception record points to %p instead of %p\n",
546 unsigned int i, parameter_count,
entry =
except - exceptions;
549 trace(
"exception %u: %x flags:%x addr:%p\n",
556 "%u: Unexpected eip %#x/%#lx\n",
entry,
560 "%u: Unexpected exception address %p/%p\n",
entry,
566 parameter_count =
except->nb_params;
568 parameter_count =
except->alt_nb_params;
575 if (
except->nb_params == 2 &&
except->params[1] >= 0xfffffffd)
593 "%u: Wrong parameter %d: %lx/%x\n",
600 "%u: Wrong parameter %d: %lx/%x\n",
612 static void test_prot_fault(
void)
616 for (
i = 0;
i <
sizeof(exceptions)/
sizeof(exceptions[0]);
i++)
620 skip(
"Exception %u broken on Wow64\n",
i );
624 run_exception_test(
handler, &exceptions[
i], &exceptions[
i].
code,
625 sizeof(exceptions[
i].
code), 0);
626 if (!
i && !got_exception)
628 trace(
"No exception, assuming win9x, no point in testing further\n" );
631 ok( got_exception == (exceptions[
i].
status != 0),
632 "%u: bad exception count %d\n",
i, got_exception );
637 DWORD dr0, dr1, dr2, dr3, dr6, dr7;
644 const struct dbgreg_test *
test = *(
const struct dbgreg_test **)(frame + 1);
656 #define CHECK_DEBUG_REG(n, m) \ 657 ok((ctx.Dr##n & m) == test->dr##n, "(%d) failed to set debug register " #n " to %x, got %x\n", \ 658 test_num, test->dr##n, ctx.Dr##n) 660 static void check_debug_registers(
int test_num,
const struct dbgreg_test *
test)
669 CHECK_DEBUG_REG(0, ~0);
670 CHECK_DEBUG_REG(1, ~0);
671 CHECK_DEBUG_REG(2, ~0);
672 CHECK_DEBUG_REG(3, ~0);
673 CHECK_DEBUG_REG(6, 0x0f);
674 CHECK_DEBUG_REG(7, ~0xdc00);
677 static const BYTE segfault_code[5] = {
688 ok (!(
context->EFlags & 0x100),
"eflags has single stepping bit set\n");
690 if( got_exception < 3)
696 "exception is not EXCEPTION_SINGLE_STEP: %x\n", rec->
ExceptionCode);
702 static const BYTE single_stepcode[] = {
715 static const BYTE align_check_code[] = {
737 ok (!(
context->EFlags & 0x40000),
"eflags has AC bit set\n");
743 static const BYTE direction_flag_code[] = {
759 if (
flags & 0x400)
trace(
"eflags has DF bit set\n" );
761 ok(
context->EFlags & 0x400,
"context eflags has DF bit cleared\n" );
776 if(got_exception == 1) {
780 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
782 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
785 }
else if( got_exception == 2) {
789 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
793 }
else if( got_exception == 3) {
797 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
798 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
805 ok( (
context->Dr6 & 0xf) == 0,
"B0...3 flags in Dr6 shouldn't be set\n");
806 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
813 static const BYTE dummy_code[] = { 0x90, 0x90, 0xc3 };
827 static const BYTE int3_code[] = { 0xCC, 0xc3 };
833 run_exception_test( bpx_handler,
NULL, dummy_code,
sizeof(dummy_code), 0 );
834 ok( got_exception ==
expect,
"expected %u exceptions, got %d\n",
expect, got_exception );
838 static void test_exceptions(
void)
842 struct dbgreg_test dreg_test;
845 if (!pNtGetContextThread || !pNtSetContextThread)
847 skip(
"NtGetContextThread/NtSetContextThread not found\n" );
852 memset(&dreg_test, 0,
sizeof(dreg_test));
854 dreg_test.dr0 = 0x42424240;
855 dreg_test.dr2 = 0x126bb070;
856 dreg_test.dr3 = 0x0badbad0;
857 dreg_test.dr7 = 0xffff0115;
858 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
859 check_debug_registers(1, &dreg_test);
861 dreg_test.dr0 = 0x42424242;
862 dreg_test.dr2 = 0x100f0fe7;
863 dreg_test.dr3 = 0x0abebabe;
864 dreg_test.dr7 = 0x115;
865 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
866 check_debug_registers(2, &dreg_test);
870 run_exception_test(single_step_handler,
NULL, &single_stepcode,
sizeof(single_stepcode), 0);
871 ok(got_exception == 3,
"expected 3 single step exceptions, got %d\n", got_exception);
875 run_exception_test(align_check_handler,
NULL, align_check_code,
sizeof(align_check_code), 0);
876 ok(got_exception == 0,
"got %d alignment faults, expected 0\n", got_exception);
880 run_exception_test(direction_flag_handler,
NULL, direction_flag_code,
sizeof(direction_flag_code), 0);
881 ok(got_exception == 1,
"got %d exceptions, expected 1\n", got_exception);
892 run_exception_test(bpx_handler,
NULL, dummy_code,
sizeof(dummy_code), 0);
893 ok( got_exception == 4,
"expected 4 exceptions, got %d\n", got_exception);
896 run_exception_test(int3_handler,
NULL, int3_code,
sizeof(int3_code), 0);
908 res = pNtGetContextThread(
h, &
ctx );
910 ok(
ctx.Dr0 == 0,
"dr0 %x\n",
ctx.Dr0 );
911 ok(
ctx.Dr7 == 0,
"dr7 %x\n",
ctx.Dr7 );
914 res = pNtSetContextThread(
h, &
ctx );
926 static void test_debugger(
void)
932 DWORD continuestatus;
940 if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
942 skip(
"NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n");
946 sprintf(
cmdline,
"%s %s %s %p", my_argv[0], my_argv[1],
"debuggee", &test_stage);
968 skip(
"child process loaded at different address, terminating it\n");
969 pNtTerminateProcess(
pi.hProcess, 0);
979 sizeof(code_mem_address), &size_read);
981 status = pNtReadVirtualMemory(
pi.hProcess, &test_stage, &stage,
982 sizeof(stage), &size_read);
989 trace(
"exception 0x%x at %p firstchance=%d Eip=0x%x, Eax=0x%x\n",
995 ok(
FALSE,
"got way too many exceptions, probably caught in an infinite loop, terminating child\n");
996 pNtTerminateProcess(
pi.hProcess, 1);
1002 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb,
"Eip at %x instead of %p\n",
1003 ctx.Eip, (
char *)code_mem_address + 0xb);
1007 ctx.Eax = 0xf00f00f1;
1012 else if (stage == 2)
1017 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb,
"Eip at 0x%x instead of %p\n",
1018 ctx.Eip, (
char *)code_mem_address + 0xb);
1023 ctx.Eax = 0xf00f00f1;
1036 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xa ||
1038 "Eip at 0x%x instead of %p\n",
1039 ctx.Eip, (
char *)code_mem_address + 0xa);
1041 if ((
char *)
ctx.Eip == (
char *)code_mem_address + 0xa)
1045 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb,
"Eip at 0x%x instead of %p\n",
1046 ctx.Eip, (
char *)code_mem_address + 0xb);
1050 else if (stage == 7 || stage == 8)
1054 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0x1d,
1055 "expected Eip = %p, got 0x%x\n", (
char *)code_mem_address + 0x1d,
ctx.Eip);
1059 else if (stage == 9 || stage == 10)
1063 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 2,
1064 "expected Eip = %p, got 0x%x\n", (
char *)code_mem_address + 2,
ctx.Eip);
1068 else if (stage == 11 || stage == 12)
1079 ok(
FALSE,
"unexpected stage %x\n", stage);
1098 status = pNtReadVirtualMemory(
pi.hProcess, &test_stage, &stage,
1099 sizeof(stage), &size_read);
1111 if (stage == 3 || stage == 4)
1122 status = pNtReadVirtualMemory(
pi.hProcess, &test_stage, &stage,
1123 sizeof(stage), &size_read);
1126 if (stage == 5 || stage == 6)
1128 ok(de.
u.
RipInfo.
dwError == 0x11223344,
"got unexpected rip error code %08x, expected %08x\n",
1130 ok(de.
u.
RipInfo.
dwType == 0x55667788,
"got unexpected rip type %08x, expected %08x\n",
1134 ok(
FALSE,
"unexpected stage %x\n", stage);
1155 int *stage = *(
int **)(frame + 1);
1164 else if ( *stage == 2 || *stage == 3 ) {
1168 skip(
"system doesn't support SIMD exceptions\n");
1171 "exception code: %#x, should be %#x\n",
1174 "# of params: %i, should be 1\n",
1182 ok(
FALSE,
"unexpected stage %x\n", *stage);
1187 static const BYTE simd_exception_test[] = {
1189 0x0f, 0xae, 0x1c, 0x24,
1191 0x66, 0x81, 0x24, 0x24, 0xff, 0xfd,
1192 0x0f, 0xae, 0x14, 0x24,
1197 0x0f, 0x10, 0x0c, 0x24,
1202 0x0f, 0xae, 0x14, 0x24,
1207 static const BYTE simd_exception_test2[] = {
1209 0x0f, 0xae, 0x1c, 0x24,
1211 0x66, 0x81, 0x24, 0x24, 0x7f, 0xff,
1212 0x0f, 0xae, 0x14, 0x24,
1217 0x0f, 0xae, 0x14, 0x24,
1222 static const BYTE sse_check[] = {
1227 static void test_simd_exceptions(
void)
1234 run_exception_test(simd_fault_handler, &stage, sse_check,
sizeof(sse_check), 0);
1236 skip(
"system doesn't support SSE\n");
1243 run_exception_test(simd_fault_handler, &stage, simd_exception_test,
1244 sizeof(simd_exception_test), 0);
1245 ok(got_exception == 1,
"got exception: %i, should be 1\n", got_exception);
1250 run_exception_test(simd_fault_handler, &stage, simd_exception_test2,
1251 sizeof(simd_exception_test2), 0);
1252 ok(got_exception == 1,
"got exception: %i, should be 1\n", got_exception);
1255 struct fpu_exception_info
1257 DWORD exception_code;
1258 DWORD exception_offset;
1265 struct fpu_exception_info *
info = *(
struct fpu_exception_info **)(frame + 1);
1275 static void test_fpu_exceptions(
void)
1277 static const BYTE fpu_exception_test_ie[] =
1280 0x66, 0xc7, 0x04, 0x24, 0xfe, 0x03,
1281 0x9b, 0xd9, 0x7c, 0x24, 0x02,
1290 0xd9, 0x6c, 0x24, 0x02,
1295 static const BYTE fpu_exception_test_de[] =
1298 0x66, 0xc7, 0x04, 0x24, 0xfb, 0x03,
1299 0x9b, 0xd9, 0x7c, 0x24, 0x02,
1309 0xd9, 0x6c, 0x24, 0x02,
1314 struct fpu_exception_info
info;
1317 run_exception_test(fpu_exception_handler, &
info, fpu_exception_test_ie,
sizeof(fpu_exception_test_ie), 0);
1319 "Got exception code %#x, expected EXCEPTION_FLT_STACK_CHECK\n",
info.exception_code);
1320 ok(
info.exception_offset == 0x19 ||
1322 "Got exception offset %#x, expected 0x19\n",
info.exception_offset);
1323 ok(
info.eip_offset == 0x1b,
"Got EIP offset %#x, expected 0x1b\n",
info.eip_offset);
1326 run_exception_test(fpu_exception_handler, &
info, fpu_exception_test_de,
sizeof(fpu_exception_test_de), 0);
1328 "Got exception code %#x, expected EXCEPTION_FLT_DIVIDE_BY_ZERO\n",
info.exception_code);
1329 ok(
info.exception_offset == 0x17 ||
1331 "Got exception offset %#x, expected 0x17\n",
info.exception_offset);
1332 ok(
info.eip_offset == 0x19,
"Got EIP offset %#x, expected 0x19\n",
info.eip_offset);
1335 struct dpe_exception_info {
1336 BOOL exception_caught;
1337 DWORD exception_info;
1344 struct dpe_exception_info *
info = *(
struct dpe_exception_info **)(frame + 1);
1351 "Exception address: %p, expected %p\n",
1361 static void test_dpe_exceptions(
void)
1363 static const BYTE single_ret[] = {0xC3};
1364 struct dpe_exception_info
info;
1366 BOOL has_hw_support;
1375 skip(
"This software platform does not support DEP\n");
1385 ok(
len ==
sizeof val,
"returned length: %d\n",
len);
1388 skip(
"toggling DEP impossible - status locked\n");
1389 is_permanent =
TRUE;
1391 can_test_without =
FALSE;
1393 can_test_with =
FALSE;
1409 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_NOACCESS);
1410 ok(
info.exception_caught ==
TRUE,
"Execution of disabled memory succeeded\n");
1413 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1415 trace(
"DEP hardware support: %s\n", has_hw_support?
"Yes":
"No");
1419 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_READWRITE);
1422 ok(
info.exception_caught ==
TRUE,
"Execution of data memory succeeded\n");
1424 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1427 ok(
info.exception_caught ==
FALSE,
"Execution trapped without hardware support\n");
1430 skip(
"DEP is in AlwaysOff state\n");
1441 if(can_test_without)
1445 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_READWRITE);
1446 ok(
info.exception_caught ==
FALSE,
"Execution trapped with DEP turned off\n");
1451 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_NOACCESS);
1452 ok(
info.exception_caught ==
TRUE,
"Execution of disabled memory succeeded\n");
1454 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1457 skip(
"DEP is in AlwaysOn state\n");
1478 static void test_thread_context(
void)
1484 DWORD Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp, Esp, Eip,
1485 SegCs, SegDs, SegEs, SegFs, SegGs, SegSs, EFlags, prev_frame;
1489 static const BYTE call_func[] =
1528 #define COMPARE(reg) \ 1529 ok( context.reg == expect.reg, "wrong " #reg " %08x/%08x\n", context.reg, expect.reg ) 1534 trace(
"expect: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x esp=%08x " 1535 "eip=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x flags=%08x prev=%08x\n",
1539 trace(
"actual: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x esp=%08x " 1540 "eip=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x flags=%08x\n",
1547 "wrong flags %08x\n",
context.ContextFlags );
1572 trace(
"expect: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x esp=%08x " 1573 "eip=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x flags=%08x prev=%08x\n",
1577 trace(
"actual: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x esp=%08x " 1578 "eip=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x flags=%08x\n",
1591 ok( (
char *)
context.Eip >= (
char *)pNtGetContextThread - 0x10000 &&
1592 (
char *)
context.Eip <= (
char *)pNtGetContextThread + 0x10000,
1593 "wrong Eip %08x/%08x\n",
context.Eip, (
DWORD)pNtGetContextThread );
1595 "expected 0xc483 or 0x08c2 or 0x8dc3, got %04x\n", *(
WORD *)
context.Eip );
1606 #elif defined(__x86_64__) 1611 #define UNW_FLAG_NHANDLER 0 1612 #define UNW_FLAG_EHANDLER 1 1613 #define UNW_FLAG_UHANDLER 2 1614 #define UNW_FLAG_CHAININFO 4 1615 #endif // __REACTOS__ 1617 #define UWOP_PUSH_NONVOL 0 1618 #define UWOP_ALLOC_LARGE 1 1619 #define UWOP_ALLOC_SMALL 2 1620 #define UWOP_SET_FPREG 3 1621 #define UWOP_SAVE_NONVOL 4 1622 #define UWOP_SAVE_NONVOL_FAR 5 1623 #define UWOP_SAVE_XMM128 8 1624 #define UWOP_SAVE_XMM128_FAR 9 1625 #define UWOP_PUSH_MACHFRAME 10 1639 const BYTE *
function;
1640 size_t function_size;
1643 unsigned int nb_results;
1648 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
1649 r8, r9, r10, r11, r12, r13, r14, r15
1652 static const char *
const reg_names[16] =
1654 "rax",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
1655 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15" 1658 #define UWOP(code,info) (UWOP_##code | ((info) << 4)) 1660 static void call_virtual_unwind(
int testnum,
const struct unwind_test *
test )
1662 static const int code_offset = 1024;
1663 static const int unwind_offset = 2048;
1667 KNONVOLATILE_CONTEXT_POINTERS ctx_ptr;
1670 ULONG64 frame, orig_rip, orig_rbp, unset_reg;
1671 UINT unwind_size = 4 + 2 *
test->unwind_info[2] + 8;
1676 runtime_func.BeginAddress = code_offset;
1677 runtime_func.EndAddress = code_offset +
test->function_size;
1678 runtime_func.UnwindData = unwind_offset;
1682 for (
i = 0;
i <
test->nb_results;
i++)
1684 memset( &ctx_ptr, 0,
sizeof(ctx_ptr) );
1686 memset( &unset_reg, 0x55,
sizeof(unset_reg) );
1687 for (
j = 0;
j < 256;
j++) fake_stack[
j] =
j * 8;
1695 (
void *)orig_rip, *(
BYTE *)orig_rip, (
void *)orig_rbp, (
void *)
context.Rsp );
1697 data = (
void *)0xdeadbeef;
1699 &runtime_func, &
context, &
data, &frame, &ctx_ptr );
1700 if (
test->results[
i].handler)
1710 ok(
data == (
void *)0xdeadbeef,
"%u/%u: handler data set to %p\n",
testnum,
i,
data );
1713 ok(
context.Rip ==
test->results[
i].rip,
"%u/%u: wrong rip %p/%x\n",
1715 ok( frame == (
ULONG64)fake_stack +
test->results[
i].frame,
"%u/%u: wrong frame %p/%p\n",
1716 testnum,
i, (
void *)frame, (
char *)fake_stack +
test->results[
i].frame );
1718 for (
j = 0;
j < 16;
j++)
1720 static const UINT nb_regs =
sizeof(
test->results[
i].regs) /
sizeof(
test->results[
i].regs[0]);
1722 for (
k = 0;
k < nb_regs;
k++)
1724 if (
test->results[
i].regs[
k][0] == -1)
1729 if (
test->results[
i].regs[
k][0] ==
j)
break;
1735 ok( !ctx_ptr.u2.IntegerContext[
j],
1736 "%u/%u: rsp should not be set in ctx_ptr\n",
testnum,
i );
1738 ok(!ctx_ptr.IntegerContext[
j],
1739 "%u/%u: rsp should not be set in ctx_ptr\n",
testnum,
i);
1740 #endif // __REACTOS__ 1743 "%u/%u: register rsp wrong %p/%p\n",
1749 if (ctx_ptr.u2.IntegerContext[
j])
1751 if (ctx_ptr.IntegerContext[
j])
1752 #endif // __REACTOS__ 1754 ok(
k < nb_regs,
"%u/%u: register %s should not be set to %lx\n",
1758 "%u/%u: register %s wrong %p/%x\n",
1763 ok(
k == nb_regs,
"%u/%u: register %s should be set\n",
testnum,
i, reg_names[
j] );
1765 ok(
context.Rbp == orig_rbp,
"%u/%u: register rbp wrong %p/unset\n",
1769 "%u/%u: register %s wrong %p/unset\n",
1776 static void test_virtual_unwind(
void)
1778 static const BYTE function_0[] =
1781 0x48, 0x81, 0xec, 0x10, 0x01, 0x00, 0x00,
1782 0x48, 0x8d, 0x6c, 0x24, 0x30,
1783 0x48, 0x89, 0x9d, 0xf0, 0x00, 0x00, 0x00,
1784 0x48, 0x89, 0xb5, 0xf8, 0x00, 0x00, 0x00,
1786 0x48, 0x8b, 0x9d, 0xf0, 0x00, 0x00, 0x00,
1787 0x48, 0x8b, 0xb5, 0xf8, 0x00, 0x00, 0x00,
1788 0x48, 0x8d, 0xa5, 0xe0, 0x00, 0x00, 0x00,
1793 static const BYTE unwind_info_0[] =
1800 0x1c, UWOP(SAVE_NONVOL, rsi), 0x25, 0,
1801 0x15, UWOP(SAVE_NONVOL, rbx), 0x24, 0,
1802 0x0e, UWOP(SET_FPREG, rbp),
1803 0x09, UWOP(ALLOC_LARGE, 0), 0x22, 0,
1804 0x02, UWOP(PUSH_NONVOL, rbp),
1806 0x00, 0x02, 0x00, 0x00,
1807 0x05, 0x06, 0x07, 0x08,
1810 static const struct results results_0[] =
1813 { 0x00, 0x40,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1814 { 0x02, 0x40,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbp,0x000}, {-1,-1} }},
1815 { 0x09, 0x40,
FALSE, 0x118, 0x000, { {rsp,0x120}, {rbp,0x110}, {-1,-1} }},
1816 { 0x0e, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {-1,-1} }},
1817 { 0x15, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {-1,-1} }},
1818 { 0x1c, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1819 { 0x1d, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1820 { 0x24, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1821 { 0x2b, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {-1,-1}}},
1822 { 0x32, 0x40,
FALSE, 0x008, 0x010, { {rsp,0x010}, {rbp,0x000}, {-1,-1}}},
1823 { 0x33, 0x40,
FALSE, 0x000, 0x010, { {rsp,0x008}, {-1,-1}}},
1827 static const BYTE function_1[] =
1834 0x48, 0x83, 0xec, 0x30,
1836 0x48, 0x83, 0xc4, 0x30,
1845 static const BYTE unwind_info_1[] =
1852 0x0a, UWOP(ALLOC_SMALL, 5),
1853 0x06, UWOP(PUSH_NONVOL, r12),
1854 0x04, UWOP(PUSH_NONVOL, rdi),
1855 0x03, UWOP(PUSH_NONVOL, rsi),
1856 0x02, UWOP(PUSH_NONVOL, rbp),
1857 0x01, UWOP(PUSH_NONVOL, rbx),
1859 0x00, 0x02, 0x00, 0x00,
1860 0x05, 0x06, 0x07, 0x08,
1863 static const struct results results_1[] =
1866 { 0x00, 0x50,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1867 { 0x01, 0x50,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbx,0x000}, {-1,-1} }},
1868 { 0x02, 0x50,
FALSE, 0x010, 0x000, { {rsp,0x018}, {rbx,0x008}, {rbp,0x000}, {-1,-1} }},
1869 { 0x03, 0x50,
FALSE, 0x018, 0x000, { {rsp,0x020}, {rbx,0x010}, {rbp,0x008}, {rsi,0x000}, {-1,-1} }},
1870 { 0x04, 0x50,
FALSE, 0x020, 0x000, { {rsp,0x028}, {rbx,0x018}, {rbp,0x010}, {rsi,0x008}, {rdi,0x000}, {-1,-1} }},
1871 { 0x06, 0x50,
FALSE, 0x028, 0x000, { {rsp,0x030}, {rbx,0x020}, {rbp,0x018}, {rsi,0x010}, {rdi,0x008}, {r12,0x000}, {-1,-1} }},
1872 { 0x0a, 0x50,
TRUE, 0x058, 0x000, { {rsp,0x060}, {rbx,0x050}, {rbp,0x048}, {rsi,0x040}, {rdi,0x038}, {r12,0x030}, {-1,-1} }},
1873 { 0x0c, 0x50,
FALSE, 0x058, 0x000, { {rsp,0x060}, {rbx,0x050}, {rbp,0x048}, {rsi,0x040}, {rdi,0x038}, {r12,0x030}, {-1,-1} }},
1874 { 0x10, 0x50,
FALSE, 0x028, 0x000, { {rsp,0x030}, {rbx,0x020}, {rbp,0x018}, {rsi,0x010}, {rdi,0x008}, {r12,0x000}, {-1,-1} }},
1875 { 0x12, 0x50,
FALSE, 0x020, 0x000, { {rsp,0x028}, {rbx,0x018}, {rbp,0x010}, {rsi,0x008}, {rdi,0x000}, {-1,-1} }},
1876 { 0x13, 0x50,
FALSE, 0x018, 0x000, { {rsp,0x020}, {rbx,0x010}, {rbp,0x008}, {rsi,0x000}, {-1,-1} }},
1877 { 0x14, 0x50,
FALSE, 0x010, 0x000, { {rsp,0x018}, {rbx,0x008}, {rbp,0x000}, {-1,-1} }},
1878 { 0x15, 0x50,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbx,0x000}, {-1,-1} }},
1879 { 0x16, 0x50,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1882 static const struct unwind_test
tests[] =
1884 { function_0,
sizeof(function_0), unwind_info_0,
1885 results_0,
sizeof(results_0)/
sizeof(results_0[0]) },
1886 { function_1,
sizeof(function_1), unwind_info_1,
1887 results_1,
sizeof(results_1)/
sizeof(results_1[0]) }
1892 call_virtual_unwind(
i, &
tests[
i] );
1895 static int consolidate_dummy_called;
1899 consolidate_dummy_called = 1;
1900 ok(
ctx->Rip == 0xdeadbeef,
"test_consolidate_dummy failed for Rip, expected: 0xdeadbeef, got: %lx\n",
ctx->Rip);
1904 static void test_restore_context(
void)
1906 SETJMP_FLOAT128 *fltsave;
1912 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext || !p_setjmp)
1914 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext/_setjmp not found\n");
1923 pRtlCaptureContext(&
ctx);
1926 pRtlRestoreContext(&
ctx,
NULL);
1927 ok(0,
"shouldn't be reached\n");
1946 pRtlRestoreContext(&
ctx, &rec);
1947 ok(0,
"shouldn't be reached\n");
1951 ok(
buf.Rbx ==
ctx.Rbx,
"longjmp failed for Rbx, expected: %lx, got: %lx\n",
buf.Rbx,
ctx.Rbx);
1952 ok(
buf.Rsp ==
ctx.Rsp,
"longjmp failed for Rsp, expected: %lx, got: %lx\n",
buf.Rsp,
ctx.Rsp);
1953 ok(
buf.Rbp ==
ctx.Rbp,
"longjmp failed for Rbp, expected: %lx, got: %lx\n",
buf.Rbp,
ctx.Rbp);
1954 ok(
buf.Rsi ==
ctx.Rsi,
"longjmp failed for Rsi, expected: %lx, got: %lx\n",
buf.Rsi,
ctx.Rsi);
1955 ok(
buf.Rdi ==
ctx.Rdi,
"longjmp failed for Rdi, expected: %lx, got: %lx\n",
buf.Rdi,
ctx.Rdi);
1956 ok(
buf.R12 ==
ctx.R12,
"longjmp failed for R12, expected: %lx, got: %lx\n",
buf.R12,
ctx.R12);
1957 ok(
buf.R13 ==
ctx.R13,
"longjmp failed for R13, expected: %lx, got: %lx\n",
buf.R13,
ctx.R13);
1958 ok(
buf.R14 ==
ctx.R14,
"longjmp failed for R14, expected: %lx, got: %lx\n",
buf.R14,
ctx.R14);
1959 ok(
buf.R15 ==
ctx.R15,
"longjmp failed for R15, expected: %lx, got: %lx\n",
buf.R15,
ctx.R15);
1961 fltsave = &
buf.Xmm6;
1962 for (
i = 0;
i < 10;
i++)
1965 ok(fltsave[
i].Part[0] ==
ctx.u.FltSave.XmmRegisters[
i + 6].Low,
1966 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1967 fltsave[
i].Part[0],
ctx.u.FltSave.XmmRegisters[
i + 6].Low);
1969 ok(fltsave[
i].Part[1] ==
ctx.u.FltSave.XmmRegisters[
i + 6].High,
1970 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1971 fltsave[
i].Part[1],
ctx.u.FltSave.XmmRegisters[
i + 6].High);
1973 ok(fltsave[
i].Part[0] ==
ctx.FltSave.XmmRegisters[
i + 6].Low,
1974 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1975 fltsave[
i].Part[0],
ctx.FltSave.XmmRegisters[
i + 6].Low);
1977 ok(fltsave[
i].Part[1] ==
ctx.FltSave.XmmRegisters[
i + 6].High,
1978 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1979 fltsave[
i].Part[1],
ctx.FltSave.XmmRegisters[
i + 6].High);
1984 ok(0,
"unexpected pass %d\n",
pass);
1989 pRtlCaptureContext(&
ctx);
2000 pRtlUnwindEx((
void*)
buf.Rsp, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
2001 ok(0,
"shouldn't be reached\n");
2019 ctx.Rip = 0xdeadbeef;
2021 pRtlRestoreContext(&
ctx, &rec);
2022 ok(0,
"shouldn't be reached\n");
2025 ok(consolidate_dummy_called,
"test_consolidate_dummy not called\n");
2027 ok(0,
"unexpected pass %d\n",
pass);
2032 static const int code_offset = 1024;
2036 runtime_func.BeginAddress = code_offset + 16;
2037 runtime_func.EndAddress = code_offset + 32;
2038 runtime_func.UnwindData = 0;
2039 return &runtime_func;
2042 static void test_dynamic_unwind(
void)
2044 static const int code_offset = 1024;
2052 runtime_func->BeginAddress = code_offset;
2053 runtime_func->EndAddress = code_offset + 16;
2054 runtime_func->UnwindData = 0;
2056 "RtlAddFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2062 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2064 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2069 ok(
func == runtime_func,
2070 "RtlLookupFunctionEntry didn't return expected function, expected: %p, got: %p\n", runtime_func,
func );
2072 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2075 ok( pRtlDeleteFunctionTable( runtime_func ),
2076 "RtlDeleteFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2077 ok( !pRtlDeleteFunctionTable( runtime_func ),
2078 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2082 runtime_func->BeginAddress = code_offset;
2083 runtime_func->EndAddress = code_offset + 16;
2084 runtime_func->UnwindData = 0;
2086 "RtlAddFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2087 ok( pRtlDeleteFunctionTable( runtime_func ),
2088 "RtlDeleteFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2092 runtime_func->BeginAddress = code_offset;
2093 runtime_func->EndAddress = code_offset + 16;
2094 runtime_func->UnwindData = 0;
2096 "RtlAddFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2098 "RtlAddFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2099 ok( pRtlDeleteFunctionTable( runtime_func ),
2100 "RtlDeleteFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2101 ok( pRtlDeleteFunctionTable( runtime_func ),
2102 "RtlDeleteFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2103 ok( !pRtlDeleteFunctionTable( runtime_func ),
2104 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2109 "RtlInstallFunctionTableCallback returned success for table = %lx\n",
table );
2114 "RtlInstallFunctionTableCallback failed for table = %lx\n",
table );
2121 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2123 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2125 "RtlLookupFunctionEntry issued %d unexpected calls to dynamic_unwind_callback\n",
count );
2131 ok(
func !=
NULL &&
func->BeginAddress == code_offset + 16 &&
func->EndAddress == code_offset + 32,
2132 "RtlLookupFunctionEntry didn't return expected function, got: %p\n",
func );
2134 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2136 "RtlLookupFunctionEntry issued %d calls to dynamic_unwind_callback, expected: 1\n",
count );
2140 "RtlDeleteFunctionTable failed for table = %p\n", (
PVOID)
table );
2142 "RtlDeleteFunctionTable returned success for nonexistent table = %p\n", (
PVOID)
table );
2146 static int termination_handler_called;
2149 termination_handler_called++;
2152 ok(frame == 0x1234,
"frame = %p\n", (
void*)frame);
2155 static void test___C_specific_handler(
void)
2162 SCOPE_TABLE scope_table;
2164 if (!p__C_specific_handler)
2166 win_skip(
"__C_specific_handler not available\n");
2170 memset(&rec, 0,
sizeof(rec));
2181 dispatch.HandlerData = &scope_table;
2183 scope_table.Count = 1;
2184 scope_table.ScopeRecord[0].BeginAddress = 0x200;
2185 scope_table.ScopeRecord[0].EndAddress = 0x400;
2187 scope_table.ScopeRecord[0].HandlerAddress = (
ULONG_PTR)termination_handler-
dispatch.ImageBase;
2191 scope_table.ScopeRecord[0].JumpTarget = 0;
2194 termination_handler_called = 0;
2197 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2198 termination_handler_called);
2203 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2204 termination_handler_called);
2210 #if defined(__i386__) || defined(__x86_64__) 2232 static void test_debug_registers(
void)
2240 { 0x42424240, 0, 0x126bb070, 0x0badbad0, 0, 0xffff0115 },
2241 { 0x42424242, 0, 0x100f0fe7, 0x0abebabe, 0, 0x115 },
2277 ctx.Dr0 = 0xffffffff;
2278 ctx.Dr1 = 0xffffffff;
2279 ctx.Dr2 = 0xffffffff;
2280 ctx.Dr3 = 0xffffffff;
2281 ctx.Dr6 = 0xffffffff;
2282 ctx.Dr7 = 0x00000400;
2304 static DWORD outputdebugstring_exceptions;
2316 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
2318 outputdebugstring_exceptions++;
2322 static void test_outputdebugstring(
DWORD numexc)
2324 PVOID vectored_handler;
2326 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
2328 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2332 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &outputdebugstring_vectored_handler);
2333 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2335 outputdebugstring_exceptions = 0;
2338 ok(outputdebugstring_exceptions == numexc,
"OutputDebugStringA generated %d exceptions, expected %d\n",
2339 outputdebugstring_exceptions, numexc);
2341 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2344 static DWORD ripevent_exceptions;
2359 ripevent_exceptions++;
2363 static void test_ripevent(
DWORD numexc)
2366 PVOID vectored_handler;
2368 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2370 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2374 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &ripevent_vectored_handler);
2375 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2378 record.ExceptionFlags = 0;
2381 record.NumberParameters = 2;
2382 record.ExceptionInformation[0] = 0x11223344;
2383 record.ExceptionInformation[1] = 0x55667788;
2385 ripevent_exceptions = 0;
2386 pRtlRaiseException(&
record);
2387 ok(ripevent_exceptions == numexc,
"RtlRaiseException generated %d exceptions, expected %d\n",
2388 ripevent_exceptions, numexc);
2390 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2393 static DWORD debug_service_exceptions;
2409 "expected ExceptionInformation[0] = %x, got %lx\n",
2424 "expected ExceptionInformation[0] = %lx, got %lx\n",
2428 debug_service_exceptions++;
2434 static const BYTE call_debug_service_code[] = {
2437 0x8b, 0x44, 0x24, 0x0c,
2438 0xb9, 0x11, 0x11, 0x11, 0x11,
2439 0xba, 0x22, 0x22, 0x22, 0x22,
2440 0xbb, 0x33, 0x33, 0x33, 0x33,
2441 0xbf, 0x44, 0x44, 0x44, 0x44,
2447 0x90, 0x90, 0x90, 0x90,
2448 0x90, 0x90, 0x90, 0x90,
2459 static const BYTE call_debug_service_code[] = {
2463 0x48, 0xb9, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2464 0x48, 0xba, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2465 0x48, 0xbb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
2466 0x48, 0xbf, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2472 0x90, 0x90, 0x90, 0x90,
2473 0x90, 0x90, 0x90, 0x90,
2483 static void test_debug_service(
DWORD numexc)
2486 DWORD expected_exc, expected_ret;
2487 void *vectored_handler;
2491 memcpy(
code_mem, call_debug_service_code,
sizeof(call_debug_service_code));
2493 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &debug_service_handler);
2494 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2496 expected_exc = numexc;
2497 expected_ret = (numexc != 0);
2500 debug_service_exceptions = 0;
2502 ok(debug_service_exceptions == expected_exc,
2503 "BREAKPOINT_BREAK generated %u exceptions, expected %u\n",
2504 debug_service_exceptions, expected_exc);
2505 ok(
ret == expected_ret,
2506 "BREAKPOINT_BREAK returned %u, expected %u\n",
ret, expected_ret);
2509 debug_service_exceptions = 0;
2511 ok(debug_service_exceptions == expected_exc,
2512 "BREAKPOINT_PROMPT generated %u exceptions, expected %u\n",
2513 debug_service_exceptions, expected_exc);
2514 ok(
ret == expected_ret,
2515 "BREAKPOINT_PROMPT returned %u, expected %u\n",
ret, expected_ret);
2518 debug_service_exceptions = 0;
2520 ok(debug_service_exceptions == expected_exc,
2521 "invalid debug service generated %u exceptions, expected %u\n",
2522 debug_service_exceptions, expected_exc);
2523 ok(
ret == expected_ret,
2524 "invalid debug service returned %u, expected %u\n",
ret, expected_ret);
2526 expected_exc = (
is_wow64 ? numexc : 0);
2527 expected_ret = (
is_wow64 && numexc);
2530 debug_service_exceptions = 0;
2532 ok(debug_service_exceptions == expected_exc,
2533 "BREAKPOINT_PRINT generated %u exceptions, expected %u\n",
2534 debug_service_exceptions, expected_exc);
2535 ok(
ret == expected_ret,
2536 "BREAKPOINT_PRINT returned %u, expected %u\n",
ret, expected_ret);
2539 debug_service_exceptions = 0;
2541 ok(debug_service_exceptions == expected_exc,
2542 "BREAKPOINT_LOAD_SYMBOLS generated %u exceptions, expected %u\n",
2543 debug_service_exceptions, expected_exc);
2544 ok(
ret == expected_ret,
2545 "BREAKPOINT_LOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2548 debug_service_exceptions = 0;
2550 ok(debug_service_exceptions == expected_exc,
2551 "BREAKPOINT_UNLOAD_SYMBOLS generated %u exceptions, expected %u\n",
2552 debug_service_exceptions, expected_exc);
2553 ok(
ret == expected_ret,
2554 "BREAKPOINT_UNLOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2557 debug_service_exceptions = 0;
2559 ok(debug_service_exceptions == expected_exc ||
broken(debug_service_exceptions == numexc),
2560 "BREAKPOINT_COMMAND_STRING generated %u exceptions, expected %u\n",
2561 debug_service_exceptions, expected_exc);
2563 "BREAKPOINT_COMMAND_STRING returned %u, expected %u\n",
ret, expected_ret);
2565 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2568 static DWORD breakpoint_exceptions;
2596 breakpoint_exceptions++;
2600 static const BYTE breakpoint_code[] = {
2605 static void test_breakpoint(
DWORD numexc)
2608 void *vectored_handler;
2612 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &breakpoint_handler);
2613 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2615 breakpoint_exceptions = 0;
2617 ok(breakpoint_exceptions == numexc,
"int $0x3 generated %u exceptions, expected %u\n",
2618 breakpoint_exceptions, numexc);
2620 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2623 static DWORD invalid_handle_exceptions;
2634 invalid_handle_exceptions++;
2638 static void test_closehandle(
DWORD numexc)
2640 PVOID vectored_handler;
2644 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2646 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2650 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &invalid_handle_vectored_handler);
2651 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2653 invalid_handle_exceptions = 0;
2655 ok(!
res,
"CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
2658 ok(invalid_handle_exceptions == numexc,
"CloseHandle generated %d exceptions, expected %d\n",
2659 invalid_handle_exceptions, numexc);
2661 invalid_handle_exceptions = 0;
2664 ok(invalid_handle_exceptions == numexc,
"NtClose generated %d exceptions, expected %d\n",
2665 invalid_handle_exceptions, numexc);
2667 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2670 static void test_vectored_continue_handler(
void)
2672 PVOID handler1, handler2;
2675 if (!pRtlAddVectoredContinueHandler || !pRtlRemoveVectoredContinueHandler)
2677 skip(
"RtlAddVectoredContinueHandler or RtlRemoveVectoredContinueHandler not found\n");
2681 handler1 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2682 ok(handler1 != 0,
"RtlAddVectoredContinueHandler failed\n");
2684 handler2 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2685 ok(handler2 != 0,
"RtlAddVectoredContinueHandler failed\n");
2686 ok(handler1 != handler2,
"RtlAddVectoredContinueHandler returned same handler\n");
2688 if (pRtlRemoveVectoredExceptionHandler)
2690 ret = pRtlRemoveVectoredExceptionHandler(handler1);
2691 ok(!
ret,
"RtlRemoveVectoredExceptionHandler succeeded\n");
2694 ret = pRtlRemoveVectoredContinueHandler(handler1);
2695 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2697 ret = pRtlRemoveVectoredContinueHandler(handler2);
2698 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2700 ret = pRtlRemoveVectoredContinueHandler(handler1);
2701 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2703 ret = pRtlRemoveVectoredContinueHandler((
void *)0x11223344);
2704 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2711 #if defined(__x86_64__) 2719 skip(
"ROSTESTS-240: Skipping ntdll_winetest:exception because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
2725 trace(
"VirtualAlloc failed\n");
2738 "RtlAddVectoredExceptionHandler" );
2740 "RtlRemoveVectoredExceptionHandler" );
2742 "RtlAddVectoredContinueHandler" );
2744 "RtlRemoveVectoredContinueHandler" );
2746 "NtQueryInformationProcess" );
2748 "NtSetInformationProcess" );
2754 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2755 have_vectored_api =
TRUE;
2757 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2765 if (
addr != &test_stage)
2767 skip(
"child process not mapped at same address (%p/%p)\n", &test_stage,
addr);
2774 ok(
FALSE,
"child process not being debugged?\n");
2778 if (pRtlRaiseException)
2781 run_rtlraiseexception_test(0x12345);
2785 run_rtlraiseexception_test(0x12345);
2789 test_outputdebugstring(0);
2791 test_outputdebugstring(2);
2797 test_debug_service(0);
2799 test_debug_service(1);
2805 test_closehandle(0);
2807 test_closehandle(1);
2810 skip(
"RtlRaiseException not found\n" );
2818 test_rtlraiseexception();
2819 test_debug_registers();
2820 test_outputdebugstring(1);
2822 test_debug_service(1);
2824 test_closehandle(0);
2825 test_vectored_continue_handler();
2827 test_simd_exceptions();
2828 test_fpu_exceptions();
2829 test_dpe_exceptions();
2831 test_thread_context();
2833 #elif defined(__x86_64__) 2835 "RtlAddFunctionTable" );
2837 "RtlDeleteFunctionTable" );
2839 "RtlInstallFunctionTableCallback" );
2841 "RtlLookupFunctionEntry" );
2843 "__C_specific_handler" );
2845 "RtlCaptureContext" );
2847 "RtlRestoreContext" );
2853 test_debug_registers();
2854 test_outputdebugstring(1);
2856 test_debug_service(1);
2858 test_closehandle(0);
2859 test_vectored_continue_handler();
2860 test_virtual_unwind();
2861 test___C_specific_handler();
2862 test_restore_context();
2864 if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
2865 test_dynamic_unwind();
2867 skip(
"Dynamic unwind functions not found\n" );
#define STATUS_UNWIND_CONSOLIDATE
#define STATUS_ILLEGAL_INSTRUCTION
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
#define STATUS_INFO_LENGTH_MISMATCH
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
LONG(NTAPI * PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionPointers)
static struct test_info tests[]
char * strstr(char *String1, char *String2)
#define EXCEPTION_ACCESS_VIOLATION
GLuint GLuint GLsizei count
#define ERROR_INVALID_HANDLE
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
#define STATUS_SINGLE_STEP
static const void void SIZE_T
#define EXCEPTION_INVALID_HANDLE
#define INVALID_HANDLE_VALUE
DWORD WINAPI GetLastError(VOID)
GLenum GLsizei GLenum GLenum const GLvoid * table
#define EXCEPTION_SINGLE_STEP
#define DECLSPEC_ALIGN(x)
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
#define STATUS_INVALID_HANDLE
PEXCEPTION_ROUTINE Handler
GLfloat GLfloat GLfloat GLfloat h
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
#define sprintf(buf, format,...)
GLenum GLuint GLenum GLsizei const GLchar * buf
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
#define EXCEPTION_CONTINUE_SEARCH
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
GLenum const GLfloat * params
HANDLE WINAPI GetCurrentThread(VOID)
__asm__("\t.globl GetPhys\n" "GetPhys:\t\n" "mflr 0\n\t" "stwu 0,-16(1)\n\t" "mfmsr 5\n\t" "andi. 6,5,0xffef\n\t" "mtmsr 6\n\t" "isync\n\t" "sync\n\t" "lwz 3,0(3)\n\t" "mtmsr 5\n\t" "isync\n\t" "sync\n\t" "lwz 0,0(1)\n\t" "addi 1,1,16\n\t" "mtlr 0\n\t" "blr")
GLuint GLuint GLuint GLuint arg1
OUTPUT_DEBUG_STRING_INFO DebugString
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
GLenum GLuint GLenum GLsizei length
EXCEPTION_DEBUG_INFO Exception
union _DEBUG_EVENT::@3237 u
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
#define STATUS_BREAKPOINT
const char * winetest_platform
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
#define EXCEPTION_EXECUTE_FAULT
#define MEM_EXECUTE_OPTION_ENABLE
static BOOL(WINAPI *pIsWow64Process)(HANDLE
#define EXIT_PROCESS_DEBUG_EVENT
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
static VOID(WINAPI *pRtlCaptureContext)(CONTEXT *)
#define EXCEPTION_FLT_DIVIDE_BY_ZERO
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
static const void void SIZE_T *static LONG exit_code
#define EXCEPTION_READ_FAULT
#define EXCEPTION_BREAKPOINT
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
#define STATUS_ACCESS_DENIED
struct _RUNTIME_FUNCTION RUNTIME_FUNCTION
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
struct _test_info results[8]
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
int winetest_get_mainargs(char ***pargv)
struct _RUNTIME_FUNCTION * PRUNTIME_FUNCTION
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
#define DBG_EXCEPTION_NOT_HANDLED
GLenum const GLvoid * addr
#define STATUS_INVALID_INFO_CLASS
EXCEPTION_RECORD ExceptionRecord
#define CONTEXT_DEBUG_REGISTERS
PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind(_In_ ULONG HandlerType, _In_ ULONG64 ImageBase, _In_ ULONG64 ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, _Inout_ PCONTEXT Context, _Outptr_ PVOID *HandlerData, _Out_ PULONG64 EstablisherFrame, _Inout_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
#define memcpy(s1, s2, n)
struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
#define GetCurrentProcess()
#define MEM_EXECUTE_OPTION_DISABLE
#define STATUS_PRIVILEGED_INSTRUCTION
#define DBG_PRINTEXCEPTION_C
#define STATUS_FLOAT_MULTIPLE_TRAPS
struct __unwind_info unwind_info
void dispatch(HANDLE hStopEvent)
static NTSTATUS(WINAPI *pNtGetContextThread)(HANDLE
void winetest_wait_child_process(HANDLE process)
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
#define InterlockedIncrement
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
#define STATUS_ACCESS_VIOLATION
GLuint GLint GLboolean GLint GLenum access
#define EXCEPTION_DEBUG_EVENT
#define EXCEPTION_FLT_STACK_CHECK
#define expect(expected, got)
#define MEM_EXECUTE_OPTION_PERMANENT
#define EXCEPTION_ILLEGAL_INSTRUCTION
DWORD WINAPI ResumeThread(IN HANDLE hThread)
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
int strcmp(const char *String1, const char *String2)
#define OUTPUT_DEBUG_STRING_EVENT
#define GetProcAddress(x, y)
#define CREATE_PROCESS_DEBUG_EVENT
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
PEXCEPTION_RECORD ExceptionRecord
#define PAGE_EXECUTE_READWRITE
UINT(* handler)(MSIPACKAGE *)
static SERVICE_STATUS status
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
struct _EXCEPTION_REGISTRATION_RECORD * Prev
static PVECTORED_EXCEPTION_HANDLER func
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
#define EXCEPTION_CONTINUE_EXECUTION