25#define WIN32_NO_STATUS
26#define NONAMELESSUNION
57#if defined(__x86_64__)
75 PRUNTIME_FUNCTION FunctionEntry;
79 void* LanguageHandler;
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;
118static BOOLEAN (
CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
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 );
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");
979 sizeof(code_mem_address), &size_read);
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");
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);
1099 sizeof(stage), &size_read);
1111 if (stage == 3 || stage == 4)
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;
1666 RUNTIME_FUNCTION runtime_func;
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[] =
1786 1 | (UNW_FLAG_EHANDLER << 3),
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[] =
1838 1 | (UNW_FLAG_EHANDLER << 3),
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;
1908 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext || !p_setjmp)
1910 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext/_setjmp not found\n");
1919 pRtlCaptureContext(&
ctx);
1922 pRtlRestoreContext(&
ctx,
NULL);
1923 ok(0,
"shouldn't be reached\n");
1942 pRtlRestoreContext(&
ctx, &rec);
1943 ok(0,
"shouldn't be reached\n");
1947 ok(
buf.Rbx ==
ctx.Rbx,
"longjmp failed for Rbx, expected: %lx, got: %lx\n",
buf.Rbx,
ctx.Rbx);
1948 ok(
buf.Rsp ==
ctx.Rsp,
"longjmp failed for Rsp, expected: %lx, got: %lx\n",
buf.Rsp,
ctx.Rsp);
1949 ok(
buf.Rbp ==
ctx.Rbp,
"longjmp failed for Rbp, expected: %lx, got: %lx\n",
buf.Rbp,
ctx.Rbp);
1950 ok(
buf.Rsi ==
ctx.Rsi,
"longjmp failed for Rsi, expected: %lx, got: %lx\n",
buf.Rsi,
ctx.Rsi);
1951 ok(
buf.Rdi ==
ctx.Rdi,
"longjmp failed for Rdi, expected: %lx, got: %lx\n",
buf.Rdi,
ctx.Rdi);
1952 ok(
buf.R12 ==
ctx.R12,
"longjmp failed for R12, expected: %lx, got: %lx\n",
buf.R12,
ctx.R12);
1953 ok(
buf.R13 ==
ctx.R13,
"longjmp failed for R13, expected: %lx, got: %lx\n",
buf.R13,
ctx.R13);
1954 ok(
buf.R14 ==
ctx.R14,
"longjmp failed for R14, expected: %lx, got: %lx\n",
buf.R14,
ctx.R14);
1955 ok(
buf.R15 ==
ctx.R15,
"longjmp failed for R15, expected: %lx, got: %lx\n",
buf.R15,
ctx.R15);
1957 fltsave = &
buf.Xmm6;
1958 for (
i = 0;
i < 10;
i++)
1960 ok(fltsave[
i].Part[0] ==
ctx.u.FltSave.XmmRegisters[
i + 6].Low,
1961 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1962 fltsave[
i].Part[0],
ctx.u.FltSave.XmmRegisters[
i + 6].Low);
1964 ok(fltsave[
i].Part[1] ==
ctx.u.FltSave.XmmRegisters[
i + 6].High,
1965 "longjmp failed for Xmm%d, expected %lx, got %lx\n",
i + 6,
1966 fltsave[
i].Part[1],
ctx.u.FltSave.XmmRegisters[
i + 6].High);
1970 ok(0,
"unexpected pass %d\n",
pass);
1975 pRtlCaptureContext(&
ctx);
1986 pRtlUnwindEx((
void*)
buf.Rsp, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
1987 ok(0,
"shouldn't be reached\n");
2005 ctx.Rip = 0xdeadbeef;
2007 pRtlRestoreContext(&
ctx, &rec);
2008 ok(0,
"shouldn't be reached\n");
2011 ok(consolidate_dummy_called,
"test_consolidate_dummy not called\n");
2013 ok(0,
"unexpected pass %d\n",
pass);
2018 static const int code_offset = 1024;
2019 static RUNTIME_FUNCTION runtime_func;
2022 runtime_func.BeginAddress = code_offset + 16;
2023 runtime_func.EndAddress = code_offset + 32;
2024 runtime_func.UnwindData = 0;
2025 return &runtime_func;
2028static void test_dynamic_unwind(
void)
2030 static const int code_offset = 1024;
2031 char buf[
sizeof(RUNTIME_FUNCTION) + 4];
2032 RUNTIME_FUNCTION *runtime_func, *
func;
2037 runtime_func = (RUNTIME_FUNCTION *)
buf;
2038 runtime_func->BeginAddress = code_offset;
2039 runtime_func->EndAddress = code_offset + 16;
2040 runtime_func->UnwindData = 0;
2042 "RtlAddFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2048 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2050 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2055 ok(
func == runtime_func,
2056 "RtlLookupFunctionEntry didn't return expected function, expected: %p, got: %p\n", runtime_func,
func );
2058 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2061 ok( pRtlDeleteFunctionTable( runtime_func ),
2062 "RtlDeleteFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
2063 ok( !pRtlDeleteFunctionTable( runtime_func ),
2064 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2067 runtime_func = (RUNTIME_FUNCTION *)((
ULONG_PTR)
buf | 0x3);
2068 runtime_func->BeginAddress = code_offset;
2069 runtime_func->EndAddress = code_offset + 16;
2070 runtime_func->UnwindData = 0;
2072 "RtlAddFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2073 ok( pRtlDeleteFunctionTable( runtime_func ),
2074 "RtlDeleteFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
2077 runtime_func = (RUNTIME_FUNCTION *)
buf;
2078 runtime_func->BeginAddress = code_offset;
2079 runtime_func->EndAddress = code_offset + 16;
2080 runtime_func->UnwindData = 0;
2082 "RtlAddFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2084 "RtlAddFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2085 ok( pRtlDeleteFunctionTable( runtime_func ),
2086 "RtlDeleteFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
2087 ok( pRtlDeleteFunctionTable( runtime_func ),
2088 "RtlDeleteFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
2089 ok( !pRtlDeleteFunctionTable( runtime_func ),
2090 "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
2095 "RtlInstallFunctionTableCallback returned success for table = %lx\n",
table );
2100 "RtlInstallFunctionTableCallback failed for table = %lx\n",
table );
2107 "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n",
func );
2109 "RtlLookupFunctionEntry modified base address, expected: 0, got: %lx\n",
base );
2111 "RtlLookupFunctionEntry issued %d unexpected calls to dynamic_unwind_callback\n",
count );
2117 ok(
func !=
NULL &&
func->BeginAddress == code_offset + 16 &&
func->EndAddress == code_offset + 32,
2118 "RtlLookupFunctionEntry didn't return expected function, got: %p\n",
func );
2120 "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (
ULONG_PTR)
code_mem,
base );
2122 "RtlLookupFunctionEntry issued %d calls to dynamic_unwind_callback, expected: 1\n",
count );
2125 ok( pRtlDeleteFunctionTable( (PRUNTIME_FUNCTION)
table ),
2126 "RtlDeleteFunctionTable failed for table = %p\n", (
PVOID)
table );
2127 ok( !pRtlDeleteFunctionTable( (PRUNTIME_FUNCTION)
table ),
2128 "RtlDeleteFunctionTable returned success for nonexistent table = %p\n", (
PVOID)
table );
2132static int termination_handler_called;
2135 termination_handler_called++;
2138 ok(frame == 0x1234,
"frame = %p\n", (
void*)frame);
2141static void test___C_specific_handler(
void)
2148 SCOPE_TABLE scope_table;
2150 if (!p__C_specific_handler)
2152 win_skip(
"__C_specific_handler not available\n");
2156 memset(&rec, 0,
sizeof(rec));
2162 dispatch.HandlerData = &scope_table;
2164 scope_table.Count = 1;
2165 scope_table.ScopeRecord[0].BeginAddress = 0x200;
2166 scope_table.ScopeRecord[0].EndAddress = 0x400;
2168 scope_table.ScopeRecord[0].HandlerAddress = (
ULONG_PTR)termination_handler-
dispatch.ImageBase;
2172 scope_table.ScopeRecord[0].JumpTarget = 0;
2175 termination_handler_called = 0;
2178 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2179 termination_handler_called);
2184 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2185 termination_handler_called);
2191#if defined(__i386__) || defined(__x86_64__)
2213static void test_debug_registers(
void)
2221 { 0x42424240, 0, 0x126bb070, 0x0badbad0, 0, 0xffff0115 },
2222 { 0x42424242, 0, 0x100f0fe7, 0x0abebabe, 0, 0x115 },
2258 ctx.Dr0 = 0xffffffff;
2259 ctx.Dr1 = 0xffffffff;
2260 ctx.Dr2 = 0xffffffff;
2261 ctx.Dr3 = 0xffffffff;
2262 ctx.Dr6 = 0xffffffff;
2263 ctx.Dr7 = 0x00000400;
2285static DWORD outputdebugstring_exceptions;
2297 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
2299 outputdebugstring_exceptions++;
2303static void test_outputdebugstring(
DWORD numexc)
2305 PVOID vectored_handler;
2307 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
2309 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2313 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &outputdebugstring_vectored_handler);
2314 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2316 outputdebugstring_exceptions = 0;
2319 ok(outputdebugstring_exceptions == numexc,
"OutputDebugStringA generated %d exceptions, expected %d\n",
2320 outputdebugstring_exceptions, numexc);
2322 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2325static DWORD ripevent_exceptions;
2340 ripevent_exceptions++;
2344static void test_ripevent(
DWORD numexc)
2347 PVOID vectored_handler;
2349 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2351 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2355 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &ripevent_vectored_handler);
2356 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2359 record.ExceptionFlags = 0;
2362 record.NumberParameters = 2;
2363 record.ExceptionInformation[0] = 0x11223344;
2364 record.ExceptionInformation[1] = 0x55667788;
2366 ripevent_exceptions = 0;
2367 pRtlRaiseException(&
record);
2368 ok(ripevent_exceptions == numexc,
"RtlRaiseException generated %d exceptions, expected %d\n",
2369 ripevent_exceptions, numexc);
2371 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2374static DWORD debug_service_exceptions;
2390 "expected ExceptionInformation[0] = %x, got %lx\n",
2405 "expected ExceptionInformation[0] = %lx, got %lx\n",
2409 debug_service_exceptions++;
2418 0x8b, 0x44, 0x24, 0x0c,
2419 0xb9, 0x11, 0x11, 0x11, 0x11,
2420 0xba, 0x22, 0x22, 0x22, 0x22,
2421 0xbb, 0x33, 0x33, 0x33, 0x33,
2422 0xbf, 0x44, 0x44, 0x44, 0x44,
2428 0x90, 0x90, 0x90, 0x90,
2429 0x90, 0x90, 0x90, 0x90,
2444 0x48, 0xb9, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
2445 0x48, 0xba, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
2446 0x48, 0xbb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
2447 0x48, 0xbf, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
2453 0x90, 0x90, 0x90, 0x90,
2454 0x90, 0x90, 0x90, 0x90,
2464static void test_debug_service(
DWORD numexc)
2467 DWORD expected_exc, expected_ret;
2468 void *vectored_handler;
2474 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &debug_service_handler);
2475 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2477 expected_exc = numexc;
2478 expected_ret = (numexc != 0);
2481 debug_service_exceptions = 0;
2483 ok(debug_service_exceptions == expected_exc,
2484 "BREAKPOINT_BREAK generated %u exceptions, expected %u\n",
2485 debug_service_exceptions, expected_exc);
2486 ok(
ret == expected_ret,
2487 "BREAKPOINT_BREAK returned %u, expected %u\n",
ret, expected_ret);
2490 debug_service_exceptions = 0;
2492 ok(debug_service_exceptions == expected_exc,
2493 "BREAKPOINT_PROMPT generated %u exceptions, expected %u\n",
2494 debug_service_exceptions, expected_exc);
2495 ok(
ret == expected_ret,
2496 "BREAKPOINT_PROMPT returned %u, expected %u\n",
ret, expected_ret);
2499 debug_service_exceptions = 0;
2501 ok(debug_service_exceptions == expected_exc,
2502 "invalid debug service generated %u exceptions, expected %u\n",
2503 debug_service_exceptions, expected_exc);
2504 ok(
ret == expected_ret,
2505 "invalid debug service returned %u, expected %u\n",
ret, expected_ret);
2507 expected_exc = (
is_wow64 ? numexc : 0);
2508 expected_ret = (
is_wow64 && numexc);
2511 debug_service_exceptions = 0;
2513 ok(debug_service_exceptions == expected_exc,
2514 "BREAKPOINT_PRINT generated %u exceptions, expected %u\n",
2515 debug_service_exceptions, expected_exc);
2516 ok(
ret == expected_ret,
2517 "BREAKPOINT_PRINT returned %u, expected %u\n",
ret, expected_ret);
2520 debug_service_exceptions = 0;
2522 ok(debug_service_exceptions == expected_exc,
2523 "BREAKPOINT_LOAD_SYMBOLS generated %u exceptions, expected %u\n",
2524 debug_service_exceptions, expected_exc);
2525 ok(
ret == expected_ret,
2526 "BREAKPOINT_LOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2529 debug_service_exceptions = 0;
2531 ok(debug_service_exceptions == expected_exc,
2532 "BREAKPOINT_UNLOAD_SYMBOLS generated %u exceptions, expected %u\n",
2533 debug_service_exceptions, expected_exc);
2534 ok(
ret == expected_ret,
2535 "BREAKPOINT_UNLOAD_SYMBOLS returned %u, expected %u\n",
ret, expected_ret);
2538 debug_service_exceptions = 0;
2540 ok(debug_service_exceptions == expected_exc ||
broken(debug_service_exceptions == numexc),
2541 "BREAKPOINT_COMMAND_STRING generated %u exceptions, expected %u\n",
2542 debug_service_exceptions, expected_exc);
2544 "BREAKPOINT_COMMAND_STRING returned %u, expected %u\n",
ret, expected_ret);
2546 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2549static DWORD breakpoint_exceptions;
2577 breakpoint_exceptions++;
2581static const BYTE breakpoint_code[] = {
2586static void test_breakpoint(
DWORD numexc)
2589 void *vectored_handler;
2593 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &breakpoint_handler);
2594 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2596 breakpoint_exceptions = 0;
2598 ok(breakpoint_exceptions == numexc,
"int $0x3 generated %u exceptions, expected %u\n",
2599 breakpoint_exceptions, numexc);
2601 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2604static DWORD invalid_handle_exceptions;
2615 invalid_handle_exceptions++;
2619static void test_closehandle(
DWORD numexc)
2621 PVOID vectored_handler;
2625 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
2627 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
2631 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &invalid_handle_vectored_handler);
2632 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
2634 invalid_handle_exceptions = 0;
2636 ok(!
res,
"CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
2639 ok(invalid_handle_exceptions == numexc,
"CloseHandle generated %d exceptions, expected %d\n",
2640 invalid_handle_exceptions, numexc);
2642 invalid_handle_exceptions = 0;
2645 ok(invalid_handle_exceptions == numexc,
"NtClose generated %d exceptions, expected %d\n",
2646 invalid_handle_exceptions, numexc);
2648 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2651static void test_vectored_continue_handler(
void)
2653 PVOID handler1, handler2;
2656 if (!pRtlAddVectoredContinueHandler || !pRtlRemoveVectoredContinueHandler)
2658 skip(
"RtlAddVectoredContinueHandler or RtlRemoveVectoredContinueHandler not found\n");
2662 handler1 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2663 ok(handler1 != 0,
"RtlAddVectoredContinueHandler failed\n");
2665 handler2 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
2666 ok(handler2 != 0,
"RtlAddVectoredContinueHandler failed\n");
2667 ok(handler1 != handler2,
"RtlAddVectoredContinueHandler returned same handler\n");
2669 if (pRtlRemoveVectoredExceptionHandler)
2671 ret = pRtlRemoveVectoredExceptionHandler(handler1);
2672 ok(!
ret,
"RtlRemoveVectoredExceptionHandler succeeded\n");
2675 ret = pRtlRemoveVectoredContinueHandler(handler1);
2676 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2678 ret = pRtlRemoveVectoredContinueHandler(handler2);
2679 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
2681 ret = pRtlRemoveVectoredContinueHandler(handler1);
2682 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2684 ret = pRtlRemoveVectoredContinueHandler((
void *)0x11223344);
2685 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
2692#if defined(__x86_64__)
2696#if defined(__REACTOS__) && !defined(_M_AMD64)
2700 skip(
"ROSTESTS-240: Skipping ntdll_winetest:exception because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
2706 trace(
"VirtualAlloc failed\n");
2719 "RtlAddVectoredExceptionHandler" );
2721 "RtlRemoveVectoredExceptionHandler" );
2723 "RtlAddVectoredContinueHandler" );
2725 "RtlRemoveVectoredContinueHandler" );
2727 "NtQueryInformationProcess" );
2729 "NtSetInformationProcess" );
2735 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
2736 have_vectored_api =
TRUE;
2738 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
2746 if (
addr != &test_stage)
2748 skip(
"child process not mapped at same address (%p/%p)\n", &test_stage,
addr);
2755 ok(
FALSE,
"child process not being debugged?\n");
2759 if (pRtlRaiseException)
2762 run_rtlraiseexception_test(0x12345);
2766 run_rtlraiseexception_test(0x12345);
2770 test_outputdebugstring(0);
2772 test_outputdebugstring(2);
2778 test_debug_service(0);
2780 test_debug_service(1);
2786 test_closehandle(0);
2788 test_closehandle(1);
2791 skip(
"RtlRaiseException not found\n" );
2799 test_rtlraiseexception();
2800 test_debug_registers();
2801 test_outputdebugstring(1);
2803 test_debug_service(1);
2805 test_closehandle(0);
2806 test_vectored_continue_handler();
2808 test_simd_exceptions();
2809 test_fpu_exceptions();
2810 test_dpe_exceptions();
2812 test_thread_context();
2814#elif defined(__x86_64__)
2816 "RtlAddFunctionTable" );
2818 "RtlDeleteFunctionTable" );
2820 "RtlInstallFunctionTableCallback" );
2822 "RtlLookupFunctionEntry" );
2824 "__C_specific_handler" );
2826 "RtlCaptureContext" );
2828 "RtlRestoreContext" );
2834 test_debug_registers();
2835 test_outputdebugstring(1);
2837 test_debug_service(1);
2839 test_closehandle(0);
2840 test_vectored_continue_handler();
2841 test_virtual_unwind();
2842 test___C_specific_handler();
2843 test_restore_context();
2845 if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
2846 test_dynamic_unwind();
2848 skip(
"Dynamic unwind functions not found\n" );
static struct _test_info results[8]
#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)
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)
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
UINT(* handler)(MSIPACKAGE *)
#define DECLSPEC_ALIGN(x)
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
_ACRTIMP char *__cdecl strstr(const char *, const char *)
_ACRTIMP int __cdecl strcmp(const char *, const char *)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
#define STATUS_ACCESS_VIOLATION
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)
#define EXCEPTION_CONTINUE_SEARCH
#define EXCEPTION_CONTINUE_EXECUTION
const char * winetest_platform
#define EXCEPTION_SINGLE_STEP
#define EXCEPTION_FLT_STACK_CHECK
#define CREATE_PROCESS_DEBUG_EVENT
#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
#define memcpy(s1, s2, n)
static struct test_info tests[]
static const BYTE call_debug_service_code[]
static void test_debugger(const char *argv0)
static PROCESS_INFORMATION pi
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
_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 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" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\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 $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
NTSYSAPI PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind(ULONG, ULONG_PTR, ULONG_PTR, RUNTIME_FUNCTION *, CONTEXT *, void **, ULONG_PTR *, KNONVOLATILE_CONTEXT_POINTERS *)
PRUNTIME_FUNCTION(CALLBACK * PGET_RUNTIME_FUNCTION_CALLBACK)(DWORD_PTR, PVOID)
int winetest_get_mainargs(char ***pargv)
void winetest_wait_child_process(HANDLE process)
#define EXCEPTION_EXECUTE_FAULT
#define EXCEPTION_READ_FAULT
OUTPUT_DEBUG_STRING_INFO DebugString
EXCEPTION_DEBUG_INFO Exception
union _DEBUG_EVENT::@3268 u
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
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)
DWORD WINAPI GetLastError(void)
HANDLE WINAPI GetCurrentThread(void)