25#define WIN32_NO_STATUS
26#define NONAMELESSUNION
57#if defined(__x86_64__)
79 void* LanguageHandler;
81 PUNWIND_HISTORY_TABLE HistoryTable;
85typedef struct _SETJMP_FLOAT128
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;
125static 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
138static char** my_argv;
139static 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,
294static int got_exception;
295static BOOL have_vectored_api;
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",
403static const BYTE call_one_arg_code[] = {
404 0x8b, 0x44, 0x24, 0x08,
406 0x8b, 0x44, 0x24, 0x08,
416static 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);
451static void test_rtlraiseexception(
void)
453 if (!pRtlRaiseException)
455 skip(
"RtlRaiseException not found\n");
460 run_rtlraiseexception_test(0x12345);
465static 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);
484static 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,
506static void test_unwind(
void)
515 frame1->Handler = unwind_handler;
520 frame2->
Handler = unwind_handler;
525 unwind_expected_eax = 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;
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",
612static 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)
660static 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);
677static 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);
702static const BYTE single_stepcode[] = {
715static const BYTE align_check_code[] = {
737 ok (!(
context->EFlags & 0x40000),
"eflags has AC bit set\n");
743static 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");
813static const BYTE dummy_code[] = { 0x90, 0x90, 0xc3 };
827static 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 );
838static 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 );
926static 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);
1187static 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,
1207static 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,
1222static const BYTE sse_check[] = {
1227static 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);
1255struct fpu_exception_info
1258 DWORD exception_offset;
1265 struct fpu_exception_info *
info = *(
struct fpu_exception_info **)(frame + 1);
1275static 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);
1335struct dpe_exception_info {
1336 BOOL exception_caught;
1344 struct dpe_exception_info *
info = *(
struct dpe_exception_info **)(frame + 1);
1351 "Exception address: %p, expected %p\n",
1361static 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");
1478static 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
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
1652static 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))
1660static 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;
1734 ok( !ctx_ptr.u2.IntegerContext[
j],
1735 "%u/%u: rsp should not be set in ctx_ptr\n",
testnum,
i );
1738 "%u/%u: register rsp wrong %p/%p\n",
1743 if (ctx_ptr.u2.IntegerContext[
j])
1745 ok(
k < nb_regs,
"%u/%u: register %s should not be set to %lx\n",
1749 "%u/%u: register %s wrong %p/%x\n",
1754 ok(
k == nb_regs,
"%u/%u: register %s should be set\n",
testnum,
i, reg_names[
j] );
1756 ok(
context.Rbp == orig_rbp,
"%u/%u: register rbp wrong %p/unset\n",
1760 "%u/%u: register %s wrong %p/unset\n",
1767static void test_virtual_unwind(
void)
1769 static const BYTE function_0[] =
1772 0x48, 0x81, 0xec, 0x10, 0x01, 0x00, 0x00,
1773 0x48, 0x8d, 0x6c, 0x24, 0x30,
1774 0x48, 0x89, 0x9d, 0xf0, 0x00, 0x00, 0x00,
1775 0x48, 0x89, 0xb5, 0xf8, 0x00, 0x00, 0x00,
1777 0x48, 0x8b, 0x9d, 0xf0, 0x00, 0x00, 0x00,
1778 0x48, 0x8b, 0xb5, 0xf8, 0x00, 0x00, 0x00,
1779 0x48, 0x8d, 0xa5, 0xe0, 0x00, 0x00, 0x00,
1784 static const BYTE unwind_info_0[] =
1791 0x1c, UWOP(SAVE_NONVOL, rsi), 0x25, 0,
1792 0x15, UWOP(SAVE_NONVOL, rbx), 0x24, 0,
1793 0x0e, UWOP(SET_FPREG, rbp),
1794 0x09, UWOP(ALLOC_LARGE, 0), 0x22, 0,
1795 0x02, UWOP(PUSH_NONVOL, rbp),
1797 0x00, 0x02, 0x00, 0x00,
1798 0x05, 0x06, 0x07, 0x08,
1801 static const struct results results_0[] =
1804 { 0x00, 0x40,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1805 { 0x02, 0x40,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbp,0x000}, {-1,-1} }},
1806 { 0x09, 0x40,
FALSE, 0x118, 0x000, { {rsp,0x120}, {rbp,0x110}, {-1,-1} }},
1807 { 0x0e, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {-1,-1} }},
1808 { 0x15, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {-1,-1} }},
1809 { 0x1c, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1810 { 0x1d, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1811 { 0x24, 0x40,
TRUE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {rbx,0x130}, {rsi,0x138}, {-1,-1}}},
1812 { 0x2b, 0x40,
FALSE, 0x128, 0x010, { {rsp,0x130}, {rbp,0x120}, {-1,-1}}},
1813 { 0x32, 0x40,
FALSE, 0x008, 0x010, { {rsp,0x010}, {rbp,0x000}, {-1,-1}}},
1814 { 0x33, 0x40,
FALSE, 0x000, 0x010, { {rsp,0x008}, {-1,-1}}},
1818 static const BYTE function_1[] =
1825 0x48, 0x83, 0xec, 0x30,
1827 0x48, 0x83, 0xc4, 0x30,
1836 static const BYTE unwind_info_1[] =
1843 0x0a, UWOP(ALLOC_SMALL, 5),
1844 0x06, UWOP(PUSH_NONVOL, r12),
1845 0x04, UWOP(PUSH_NONVOL, rdi),
1846 0x03, UWOP(PUSH_NONVOL, rsi),
1847 0x02, UWOP(PUSH_NONVOL, rbp),
1848 0x01, UWOP(PUSH_NONVOL, rbx),
1850 0x00, 0x02, 0x00, 0x00,
1851 0x05, 0x06, 0x07, 0x08,
1854 static const struct results results_1[] =
1857 { 0x00, 0x50,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1858 { 0x01, 0x50,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbx,0x000}, {-1,-1} }},
1859 { 0x02, 0x50,
FALSE, 0x010, 0x000, { {rsp,0x018}, {rbx,0x008}, {rbp,0x000}, {-1,-1} }},
1860 { 0x03, 0x50,
FALSE, 0x018, 0x000, { {rsp,0x020}, {rbx,0x010}, {rbp,0x008}, {rsi,0x000}, {-1,-1} }},
1861 { 0x04, 0x50,
FALSE, 0x020, 0x000, { {rsp,0x028}, {rbx,0x018}, {rbp,0x010}, {rsi,0x008}, {rdi,0x000}, {-1,-1} }},
1862 { 0x06, 0x50,
FALSE, 0x028, 0x000, { {rsp,0x030}, {rbx,0x020}, {rbp,0x018}, {rsi,0x010}, {rdi,0x008}, {r12,0x000}, {-1,-1} }},
1863 { 0x0a, 0x50,
TRUE, 0x058, 0x000, { {rsp,0x060}, {rbx,0x050}, {rbp,0x048}, {rsi,0x040}, {rdi,0x038}, {r12,0x030}, {-1,-1} }},
1864 { 0x0c, 0x50,
FALSE, 0x058, 0x000, { {rsp,0x060}, {rbx,0x050}, {rbp,0x048}, {rsi,0x040}, {rdi,0x038}, {r12,0x030}, {-1,-1} }},
1865 { 0x10, 0x50,
FALSE, 0x028, 0x000, { {rsp,0x030}, {rbx,0x020}, {rbp,0x018}, {rsi,0x010}, {rdi,0x008}, {r12,0x000}, {-1,-1} }},
1866 { 0x12, 0x50,
FALSE, 0x020, 0x000, { {rsp,0x028}, {rbx,0x018}, {rbp,0x010}, {rsi,0x008}, {rdi,0x000}, {-1,-1} }},
1867 { 0x13, 0x50,
FALSE, 0x018, 0x000, { {rsp,0x020}, {rbx,0x010}, {rbp,0x008}, {rsi,0x000}, {-1,-1} }},
1868 { 0x14, 0x50,
FALSE, 0x010, 0x000, { {rsp,0x018}, {rbx,0x008}, {rbp,0x000}, {-1,-1} }},
1869 { 0x15, 0x50,
FALSE, 0x008, 0x000, { {rsp,0x010}, {rbx,0x000}, {-1,-1} }},
1870 { 0x16, 0x50,
FALSE, 0x000, 0x000, { {rsp,0x008}, {-1,-1} }},
1873 static const struct unwind_test
tests[] =
1875 { function_0,
sizeof(function_0), unwind_info_0,
1876 results_0,
sizeof(results_0)/
sizeof(results_0[0]) },
1877 { function_1,
sizeof(function_1), unwind_info_1,
1878 results_1,
sizeof(results_1)/
sizeof(results_1[0]) }
1883 call_virtual_unwind(
i, &
tests[
i] );
1886static int consolidate_dummy_called;
1890 consolidate_dummy_called = 1;
1891 ok(
ctx->Rip == 0xdeadbeef,
"test_consolidate_dummy failed for Rip, expected: 0xdeadbeef, got: %lx\n",
ctx->Rip);
1895static void test_restore_context(
void)
1897 SETJMP_FLOAT128 *fltsave;
1903 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext || !p_setjmp)
1905 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext/_setjmp not found\n");
1914 pRtlCaptureContext(&
ctx);
1917 pRtlRestoreContext(&
ctx,
NULL);
1918 ok(0,
"shouldn't be reached\n");
1937 pRtlRestoreContext(&
ctx, &rec);
1938 ok(0,
"shouldn't be reached\n");
1942 ok(
buf.Rbx ==
ctx.Rbx,
"longjmp failed for Rbx, expected: %lx, got: %lx\n",
buf.Rbx,
ctx.Rbx);
1943 ok(
buf.Rsp ==
ctx.Rsp,
"longjmp failed for Rsp, expected: %lx, got: %lx\n",
buf.Rsp,
ctx.Rsp);
1944 ok(
buf.Rbp ==
ctx.Rbp,
"longjmp failed for Rbp, expected: %lx, got: %lx\n",
buf.Rbp,
ctx.Rbp);
1945 ok(
buf.Rsi ==
ctx.Rsi,
"longjmp failed for Rsi, expected: %lx, got: %lx\n",
buf.Rsi,
ctx.Rsi);
1946 ok(
buf.Rdi ==
ctx.Rdi,
"longjmp failed for Rdi, expected: %lx, got: %lx\n",
buf.Rdi,
ctx.Rdi);
1947 ok(
buf.R12 ==
ctx.R12,
"longjmp failed for R12, expected: %lx, got: %lx\n",
buf.R12,
ctx.R12);
1948 ok(
buf.R13 ==
ctx.R13,
"longjmp failed for R13, expected: %lx, got: %lx\n",
buf.R13,
ctx.R13);
1949 ok(
buf.R14 ==
ctx.R14,
"longjmp failed for R14, expected: %lx, got: %lx\n",
buf.R14,
ctx.R14);
1950 ok(
buf.R15 ==
ctx.R15,
"longjmp failed for R15, expected: %lx, got: %lx\n",
buf.R15,
ctx.R15);
1952 fltsave = &
buf.Xmm6;
1953 for (
i = 0;
i < 10;
i++)
1955 ok(fltsave[
i].Part[0] ==
ctx.u.FltSave.XmmRegisters[
i + 6].Low,
1956 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1957 fltsave[
i].Part[0],
ctx.u.FltSave.XmmRegisters[
i + 6].Low);
1959 ok(fltsave[
i].Part[1] ==
ctx.u.FltSave.XmmRegisters[
i + 6].High,
1960 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1961 fltsave[
i].Part[1],
ctx.u.FltSave.XmmRegisters[
i + 6].High);
1965 ok(0,
"unexpected pass %d\n",
pass);
1970 pRtlCaptureContext(&
ctx);
1981 pRtlUnwindEx((
void*)
buf.Rsp, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
1982 ok(0,
"shouldn't be reached\n");
2000 ctx.Rip = 0xdeadbeef;
2002 pRtlRestoreContext(&
ctx, &rec);
2003 ok(0,
"shouldn't be reached\n");
2006 ok(consolidate_dummy_called,
"test_consolidate_dummy not called\n");
2008 ok(0,
"unexpected pass %d\n",
pass);
2013 static const int code_offset = 1024;
2017 runtime_func.BeginAddress = code_offset + 16;
2018 runtime_func.EndAddress = code_offset + 32;
2019 runtime_func.UnwindData = 0;
2020 return &runtime_func;
2023static void test_dynamic_unwind(
void)
2025 static const int code_offset = 1024;
2033 runtime_func->BeginAddress = code_offset;
2034 runtime_func->EndAddress = code_offset + 16;
2035 runtime_func->UnwindData = 0;
2037 "RtlAddFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2043 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2045 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2050 ok(
func == runtime_func,
2051 "RtlLookupFunctionEntry didn't return expected function, expected: %p, got: %p\n", runtime_func,
func );
2053 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2056 ok( pRtlDeleteFunctionTable( runtime_func ),
2057 "RtlDeleteFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2058 ok( !pRtlDeleteFunctionTable( runtime_func ),
2059 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2063 runtime_func->BeginAddress = code_offset;
2064 runtime_func->EndAddress = code_offset + 16;
2065 runtime_func->UnwindData = 0;
2067 "RtlAddFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2068 ok( pRtlDeleteFunctionTable( runtime_func ),
2069 "RtlDeleteFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2073 runtime_func->BeginAddress = code_offset;
2074 runtime_func->EndAddress = code_offset + 16;
2075 runtime_func->UnwindData = 0;
2077 "RtlAddFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2079 "RtlAddFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2080 ok( pRtlDeleteFunctionTable( runtime_func ),
2081 "RtlDeleteFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2082 ok( pRtlDeleteFunctionTable( runtime_func ),
2083 "RtlDeleteFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2084 ok( !pRtlDeleteFunctionTable( runtime_func ),
2085 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2090 "RtlInstallFunctionTableCallback returned success for table = %lx\n",
table );
2095 "RtlInstallFunctionTableCallback failed for table = %lx\n",
table );
2102 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2104 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2106 "RtlLookupFunctionEntry issued %d unexpected calls to dynamic_unwind_callback\n",
count );
2112 ok(
func !=
NULL &&
func->BeginAddress == code_offset + 16 &&
func->EndAddress == code_offset + 32,
2113 "RtlLookupFunctionEntry didn't return expected function, got: %p\n",
func );
2115 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2117 "RtlLookupFunctionEntry issued %d calls to dynamic_unwind_callback, expected: 1\n",
count );
2121 "RtlDeleteFunctionTable failed for table = %p\n", (
PVOID)
table );
2123 "RtlDeleteFunctionTable returned success for nonexistent table = %p\n", (
PVOID)
table );
2127static int termination_handler_called;
2130 termination_handler_called++;
2133 ok(frame == 0x1234,
"frame = %p\n", (
void*)frame);
2136static void test___C_specific_handler(
void)
2143 SCOPE_TABLE scope_table;
2145 if (!p__C_specific_handler)
2147 win_skip(
"__C_specific_handler not available\n");
2151 memset(&rec, 0,
sizeof(rec));
2157 dispatch.HandlerData = &scope_table;
2159 scope_table.Count = 1;
2160 scope_table.ScopeRecord[0].BeginAddress = 0x200;
2161 scope_table.ScopeRecord[0].EndAddress = 0x400;
2163 scope_table.ScopeRecord[0].HandlerAddress = (
ULONG_PTR)termination_handler-
dispatch.ImageBase;
2167 scope_table.ScopeRecord[0].JumpTarget = 0;
2170 termination_handler_called = 0;
2173 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2174 termination_handler_called);
2179 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2180 termination_handler_called);
2186#if defined(__i386__) || defined(__x86_64__)
2208static void test_debug_registers(
void)
2216 { 0x42424240, 0, 0x126bb070, 0x0badbad0, 0, 0xffff0115 },
2217 { 0x42424242, 0, 0x100f0fe7, 0x0abebabe, 0, 0x115 },
2253 ctx.Dr0 = 0xffffffff;
2254 ctx.Dr1 = 0xffffffff;
2255 ctx.Dr2 = 0xffffffff;
2256 ctx.Dr3 = 0xffffffff;
2257 ctx.Dr6 = 0xffffffff;
2258 ctx.Dr7 = 0x00000400;
2280static DWORD outputdebugstring_exceptions;
2292 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
2294 outputdebugstring_exceptions++;
2298static void test_outputdebugstring(
DWORD numexc)
2300 PVOID vectored_handler;
2302 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
2304 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2308 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &outputdebugstring_vectored_handler);
2309 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2311 outputdebugstring_exceptions = 0;
2314 ok(outputdebugstring_exceptions == numexc,
"OutputDebugStringA generated %d exceptions, expected %d\n",
2315 outputdebugstring_exceptions, numexc);
2317 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2320static DWORD ripevent_exceptions;
2335 ripevent_exceptions++;
2339static void test_ripevent(
DWORD numexc)
2342 PVOID vectored_handler;
2344 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2346 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2350 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &ripevent_vectored_handler);
2351 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2354 record.ExceptionFlags = 0;
2357 record.NumberParameters = 2;
2358 record.ExceptionInformation[0] = 0x11223344;
2359 record.ExceptionInformation[1] = 0x55667788;
2361 ripevent_exceptions = 0;
2362 pRtlRaiseException(&
record);
2363 ok(ripevent_exceptions == numexc,
"RtlRaiseException generated %d exceptions, expected %d\n",
2364 ripevent_exceptions, numexc);
2366 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2369static DWORD debug_service_exceptions;
2385 "expected ExceptionInformation[0] = %x, got %lx\n",
2400 "expected ExceptionInformation[0] = %lx, got %lx\n",
2404 debug_service_exceptions++;
2410static const BYTE call_debug_service_code[] = {
2413 0x8b, 0x44, 0x24, 0x0c,
2414 0xb9, 0x11, 0x11, 0x11, 0x11,
2415 0xba, 0x22, 0x22, 0x22, 0x22,
2416 0xbb, 0x33, 0x33, 0x33, 0x33,
2417 0xbf, 0x44, 0x44, 0x44, 0x44,
2423 0x90, 0x90, 0x90, 0x90,
2424 0x90, 0x90, 0x90, 0x90,
2435static const BYTE call_debug_service_code[] = {
2439 0x48, 0xb9, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2440 0x48, 0xba, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2441 0x48, 0xbb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
2442 0x48, 0xbf, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2448 0x90, 0x90, 0x90, 0x90,
2449 0x90, 0x90, 0x90, 0x90,
2459static void test_debug_service(
DWORD numexc)
2462 DWORD expected_exc, expected_ret;
2463 void *vectored_handler;
2467 memcpy(
code_mem, call_debug_service_code,
sizeof(call_debug_service_code));
2469 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &debug_service_handler);
2470 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2472 expected_exc = numexc;
2473 expected_ret = (numexc != 0);
2476 debug_service_exceptions = 0;
2478 ok(debug_service_exceptions == expected_exc,
2479 "BREAKPOINT_BREAK generated %u exceptions, expected %u\n",
2480 debug_service_exceptions, expected_exc);
2481 ok(
ret == expected_ret,
2482 "BREAKPOINT_BREAK returned %u, expected %u\n",
ret, expected_ret);
2485 debug_service_exceptions = 0;
2487 ok(debug_service_exceptions == expected_exc,
2488 "BREAKPOINT_PROMPT generated %u exceptions, expected %u\n",
2489 debug_service_exceptions, expected_exc);
2490 ok(
ret == expected_ret,
2491 "BREAKPOINT_PROMPT returned %u, expected %u\n",
ret, expected_ret);
2494 debug_service_exceptions = 0;
2496 ok(debug_service_exceptions == expected_exc,
2497 "invalid debug service generated %u exceptions, expected %u\n",
2498 debug_service_exceptions, expected_exc);
2499 ok(
ret == expected_ret,
2500 "invalid debug service returned %u, expected %u\n",
ret, expected_ret);
2502 expected_exc = (
is_wow64 ? numexc : 0);
2503 expected_ret = (
is_wow64 && numexc);
2506 debug_service_exceptions = 0;
2508 ok(debug_service_exceptions == expected_exc,
2509 "BREAKPOINT_PRINT generated %u exceptions, expected %u\n",
2510 debug_service_exceptions, expected_exc);
2511 ok(
ret == expected_ret,
2512 "BREAKPOINT_PRINT returned %u, expected %u\n",
ret, expected_ret);
2515 debug_service_exceptions = 0;
2517 ok(debug_service_exceptions == expected_exc,
2518 "BREAKPOINT_LOAD_SYMBOLS generated %u exceptions, expected %u\n",
2519 debug_service_exceptions, expected_exc);
2520 ok(
ret == expected_ret,
2521 "BREAKPOINT_LOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2524 debug_service_exceptions = 0;
2526 ok(debug_service_exceptions == expected_exc,
2527 "BREAKPOINT_UNLOAD_SYMBOLS generated %u exceptions, expected %u\n",
2528 debug_service_exceptions, expected_exc);
2529 ok(
ret == expected_ret,
2530 "BREAKPOINT_UNLOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2533 debug_service_exceptions = 0;
2535 ok(debug_service_exceptions == expected_exc ||
broken(debug_service_exceptions == numexc),
2536 "BREAKPOINT_COMMAND_STRING generated %u exceptions, expected %u\n",
2537 debug_service_exceptions, expected_exc);
2539 "BREAKPOINT_COMMAND_STRING returned %u, expected %u\n",
ret, expected_ret);
2541 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2544static DWORD breakpoint_exceptions;
2572 breakpoint_exceptions++;
2576static const BYTE breakpoint_code[] = {
2581static void test_breakpoint(
DWORD numexc)
2584 void *vectored_handler;
2588 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &breakpoint_handler);
2589 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2591 breakpoint_exceptions = 0;
2593 ok(breakpoint_exceptions == numexc,
"int $0x3 generated %u exceptions, expected %u\n",
2594 breakpoint_exceptions, numexc);
2596 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2599static DWORD invalid_handle_exceptions;
2610 invalid_handle_exceptions++;
2614static void test_closehandle(
DWORD numexc)
2616 PVOID vectored_handler;
2620 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2622 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2626 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &invalid_handle_vectored_handler);
2627 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2629 invalid_handle_exceptions = 0;
2631 ok(!
res,
"CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
2634 ok(invalid_handle_exceptions == numexc,
"CloseHandle generated %d exceptions, expected %d\n",
2635 invalid_handle_exceptions, numexc);
2637 invalid_handle_exceptions = 0;
2640 ok(invalid_handle_exceptions == numexc,
"NtClose generated %d exceptions, expected %d\n",
2641 invalid_handle_exceptions, numexc);
2643 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2646static void test_vectored_continue_handler(
void)
2648 PVOID handler1, handler2;
2651 if (!pRtlAddVectoredContinueHandler || !pRtlRemoveVectoredContinueHandler)
2653 skip(
"RtlAddVectoredContinueHandler or RtlRemoveVectoredContinueHandler not found\n");
2657 handler1 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2658 ok(handler1 != 0,
"RtlAddVectoredContinueHandler failed\n");
2660 handler2 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2661 ok(handler2 != 0,
"RtlAddVectoredContinueHandler failed\n");
2662 ok(handler1 != handler2,
"RtlAddVectoredContinueHandler returned same handler\n");
2664 if (pRtlRemoveVectoredExceptionHandler)
2666 ret = pRtlRemoveVectoredExceptionHandler(handler1);
2667 ok(!
ret,
"RtlRemoveVectoredExceptionHandler succeeded\n");
2670 ret = pRtlRemoveVectoredContinueHandler(handler1);
2671 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2673 ret = pRtlRemoveVectoredContinueHandler(handler2);
2674 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2676 ret = pRtlRemoveVectoredContinueHandler(handler1);
2677 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2679 ret = pRtlRemoveVectoredContinueHandler((
void *)0x11223344);
2680 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2687#if defined(__x86_64__)
2691#if defined(__REACTOS__) && !defined(_M_AMD64)
2695 skip(
"ROSTESTS-240: Skipping ntdll_winetest:exception because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
2701 trace(
"VirtualAlloc failed\n");
2714 "RtlAddVectoredExceptionHandler" );
2716 "RtlRemoveVectoredExceptionHandler" );
2718 "RtlAddVectoredContinueHandler" );
2720 "RtlRemoveVectoredContinueHandler" );
2722 "NtQueryInformationProcess" );
2724 "NtSetInformationProcess" );
2730 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2731 have_vectored_api =
TRUE;
2733 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2741 if (
addr != &test_stage)
2743 skip(
"child process not mapped at same address (%p/%p)\n", &test_stage,
addr);
2750 ok(
FALSE,
"child process not being debugged?\n");
2754 if (pRtlRaiseException)
2757 run_rtlraiseexception_test(0x12345);
2761 run_rtlraiseexception_test(0x12345);
2765 test_outputdebugstring(0);
2767 test_outputdebugstring(2);
2773 test_debug_service(0);
2775 test_debug_service(1);
2781 test_closehandle(0);
2783 test_closehandle(1);
2786 skip(
"RtlRaiseException not found\n" );
2794 test_rtlraiseexception();
2795 test_debug_registers();
2796 test_outputdebugstring(1);
2798 test_debug_service(1);
2800 test_closehandle(0);
2801 test_vectored_continue_handler();
2803 test_simd_exceptions();
2804 test_fpu_exceptions();
2805 test_dpe_exceptions();
2807 test_thread_context();
2809#elif defined(__x86_64__)
2811 "RtlAddFunctionTable" );
2813 "RtlDeleteFunctionTable" );
2815 "RtlInstallFunctionTableCallback" );
2817 "RtlLookupFunctionEntry" );
2819 "__C_specific_handler" );
2821 "RtlCaptureContext" );
2823 "RtlRestoreContext" );
2829 test_debug_registers();
2830 test_outputdebugstring(1);
2832 test_debug_service(1);
2834 test_closehandle(0);
2835 test_vectored_continue_handler();
2836 test_virtual_unwind();
2837 test___C_specific_handler();
2838 test_restore_context();
2840 if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
2841 test_dynamic_unwind();
2843 skip(
"Dynamic unwind functions not found\n" );
static struct _test_info results[8]
int strcmp(const char *String1, const char *String2)
char * strstr(char *String1, char *String2)
#define InterlockedIncrement
void dispatch(HANDLE hStopEvent)
#define STATUS_ILLEGAL_INSTRUCTION
#define STATUS_INVALID_HANDLE
@ ExceptionContinueSearch
@ ExceptionContinueExecution
#define GetProcAddress(x, y)
#define INVALID_HANDLE_VALUE
#define GetCurrentProcess()
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
#define ERROR_INVALID_HANDLE
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
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)
DWORD WINAPI ResumeThread(IN HANDLE hThread)
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)
UINT(* handler)(MSIPACKAGE *)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint GLuint GLuint GLuint arg1
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
GLenum const GLfloat * params
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei GLsizei * length
GLenum const GLvoid * addr
GLuint GLint GLboolean GLint GLenum access
GLfloat GLfloat GLfloat GLfloat h
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
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
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
struct __unwind_info unwind_info
#define EXCEPTION_CONTINUE_SEARCH
#define EXCEPTION_CONTINUE_EXECUTION
#define memcpy(s1, s2, n)
static struct test_info tests[]
#define sprintf(buf, format,...)
static const void void SIZE_T *static LONG exit_code
static PVECTORED_EXCEPTION_HANDLER func
static const void void SIZE_T
struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT
#define MEM_EXECUTE_OPTION_DISABLE
#define MEM_EXECUTE_OPTION_PERMANENT
#define MEM_EXECUTE_OPTION_ENABLE
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
LONG(NTAPI * PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionPointers)
#define CONTEXT_DEBUG_REGISTERS
#define PAGE_EXECUTE_READWRITE
#define DECLSPEC_ALIGN(x)
_IRQL_requires_same_ _In_ PVOID EstablisherFrame
_IRQL_requires_same_ _In_ PVOID _Inout_ struct _CONTEXT * ContextRecord
#define STATUS_SINGLE_STEP
#define STATUS_UNWIND_CONSOLIDATE
#define STATUS_PRIVILEGED_INSTRUCTION
#define STATUS_BREAKPOINT
#define STATUS_FLOAT_MULTIPLE_TRAPS
#define STATUS_ACCESS_VIOLATION
#define DBG_PRINTEXCEPTION_C
#define DBG_EXCEPTION_NOT_HANDLED
#define STATUS_INVALID_INFO_CLASS
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
struct _RUNTIME_FUNCTION * PRUNTIME_FUNCTION
struct _RUNTIME_FUNCTION RUNTIME_FUNCTION
const char * winetest_platform
int winetest_get_mainargs(char ***pargv)
void winetest_wait_child_process(HANDLE process)
#define EXCEPTION_EXECUTE_FAULT
#define EXCEPTION_READ_FAULT
union _DEBUG_EVENT::@3276 u
OUTPUT_DEBUG_STRING_INFO DebugString
EXCEPTION_DEBUG_INFO Exception
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo
EXCEPTION_RECORD ExceptionRecord
PEXCEPTION_RECORD ExceptionRecord
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
PEXCEPTION_ROUTINE Handler
struct _EXCEPTION_REGISTRATION_RECORD * Prev
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
#define STATUS_ACCESS_DENIED
#define STATUS_INFO_LENGTH_MISMATCH
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_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
#define EXCEPTION_SINGLE_STEP
#define EXCEPTION_FLT_STACK_CHECK
DWORD WINAPI GetLastError(void)
#define CREATE_PROCESS_DEBUG_EVENT
HANDLE WINAPI GetCurrentThread(void)
#define EXIT_PROCESS_DEBUG_EVENT
#define EXCEPTION_INVALID_HANDLE
#define OUTPUT_DEBUG_STRING_EVENT
#define EXCEPTION_DEBUG_EVENT
#define EXCEPTION_ILLEGAL_INSTRUCTION
#define EXCEPTION_ACCESS_VIOLATION
#define EXCEPTION_BREAKPOINT
#define EXCEPTION_FLT_DIVIDE_BY_ZERO