mirror of
https://github.com/reactos/reactos
synced 2025-10-06 00:12:51 +02:00
[CRT_APITEST] Add more tests for _setjmp
This commit is contained in:
@@ -126,6 +126,7 @@
|
||||
@ cdecl __initialize_lconv_for_unsigned_char()
|
||||
@ cdecl -stub __intrinsic_abnormal_termination() # CHECKME
|
||||
@ cdecl -stub -norelay __intrinsic_setjmp(ptr) # _setjmp
|
||||
@ cdecl -impsym _setjmp(long ptr) __intrinsic_setjmp
|
||||
@ cdecl -stub -arch=!i386 -norelay __intrinsic_setjmpex(ptr ptr) # _setjmpex
|
||||
@ cdecl __isascii(long)
|
||||
@ cdecl __iscsym(long)
|
||||
|
143
modules/rostests/apitests/crt/amd64/setjmp_helper.s
Normal file
143
modules/rostests/apitests/crt/amd64/setjmp_helper.s
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Test helper for x64 setjmp
|
||||
* COPYRIGHT: Copyright 2025 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <ksamd64.inc>
|
||||
|
||||
#ifdef TEST_UCRTBASE
|
||||
#define _setjmp __intrinsic_setjmp
|
||||
#define _setjmpex __intrinsic_setjmpex
|
||||
#endif
|
||||
|
||||
.const
|
||||
|
||||
.align 16
|
||||
xmm6_data:
|
||||
.quad HEX(0606060606060606), HEX(1616161616161616)
|
||||
xmm7_data:
|
||||
.quad HEX(0707070707070707), HEX(1717171717171717)
|
||||
xmm8_data:
|
||||
.quad HEX(0808080808080808), HEX(1818181818181818)
|
||||
xmm9_data:
|
||||
.quad HEX(0909090909090909), HEX(1919191919191919)
|
||||
xmm10_data:
|
||||
.quad HEX(0A0A0A0A0A0A0A0A), HEX(1A1A1A1A1A1A1A1A)
|
||||
xmm11_data:
|
||||
.quad HEX(0B0B0B0B0B0B0B0B), HEX(1B1B1B1B1B1B1B1B)
|
||||
xmm12_data:
|
||||
.quad HEX(0C0C0C0C0C0C0C0C), HEX(1C1C1C1C1C1C1C1C)
|
||||
xmm13_data:
|
||||
.quad HEX(0D0D0D0D0D0D0D0D), HEX(1D1D1D1D1D1D1D1D)
|
||||
xmm14_data:
|
||||
.quad HEX(0E0E0E0E0E0E0E0E), HEX(1E1E1E1E1E1E1E1E)
|
||||
xmm15_data:
|
||||
.quad HEX(0F0F0F0F0F0F0F0F), HEX(1F1F1F1F1F1F1F1F)
|
||||
|
||||
|
||||
.code64
|
||||
|
||||
PUBLIC get_sp
|
||||
get_sp:
|
||||
lea rax, [rsp + 8]
|
||||
ret
|
||||
|
||||
|
||||
EXTERN _setjmp:PROC
|
||||
EXTERN _setjmpex:PROC
|
||||
PUBLIC setjmp_return_address
|
||||
|
||||
PUBLIC call_setjmp
|
||||
call_setjmp:
|
||||
lea r10, _setjmp[rip]
|
||||
jmp call_setjmp_common
|
||||
|
||||
PUBLIC call_setjmpex
|
||||
call_setjmpex:
|
||||
lea r10, _setjmpex[rip]
|
||||
jmp call_setjmp_common
|
||||
|
||||
.PROC call_setjmp_common
|
||||
|
||||
// Allocate space for non-volatile (normal+xmm) registers on the stack
|
||||
sub rsp, 8 * 8 + 10 * 16 + 8 // +8 to align the stack to 16 bytes
|
||||
|
||||
// Save non-volatile registers
|
||||
mov [rsp + 0 * 8], rbx
|
||||
mov [rsp + 1 * 8], rbp
|
||||
mov [rsp + 2 * 8], rsi
|
||||
mov [rsp + 3 * 8], rdi
|
||||
mov [rsp + 4 * 8], r12
|
||||
mov [rsp + 5 * 8], r13
|
||||
mov [rsp + 6 * 8], r14
|
||||
mov [rsp + 7 * 8], r15
|
||||
|
||||
// Save non-volatile xmm registers
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 0 * 16], xmm6
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 1 * 16], xmm7
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 2 * 16], xmm8
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 3 * 16], xmm9
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 4 * 16], xmm10
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 5 * 16], xmm11
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 6 * 16], xmm12
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 7 * 16], xmm13
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 8 * 16], xmm14
|
||||
movdqa xmmword ptr [rsp + 8 * 8 + 9 * 16], xmm15
|
||||
|
||||
.ENDPROLOG
|
||||
|
||||
// Set up a register state
|
||||
mov rbx, HEX(A1A1A1A1A1A1A1A1)
|
||||
mov rbp, HEX(A2A2A2A2A2A2A2A2)
|
||||
mov rsi, HEX(A3A3A3A3A3A3A3A3)
|
||||
mov rdi, HEX(A4A4A4A4A4A4A4A4)
|
||||
mov r12, HEX(ACACACACACACACAC)
|
||||
mov r13, HEX(ADADADADADADADAD)
|
||||
mov r14, HEX(AEAEAEAEAEAEAEAE)
|
||||
mov r15, HEX(AFAFAFAFAFAFAFAF)
|
||||
movdqa xmm6, xmmword ptr xmm6_data[rip]
|
||||
movdqa xmm7, xmmword ptr xmm7_data[rip]
|
||||
movdqa xmm8, xmmword ptr xmm8_data[rip]
|
||||
movdqa xmm9, xmmword ptr xmm9_data[rip]
|
||||
movdqa xmm10, xmmword ptr xmm10_data[rip]
|
||||
movdqa xmm11, xmmword ptr xmm11_data[rip]
|
||||
movdqa xmm12, xmmword ptr xmm12_data[rip]
|
||||
movdqa xmm13, xmmword ptr xmm13_data[rip]
|
||||
movdqa xmm14, xmmword ptr xmm14_data[rip]
|
||||
movdqa xmm15, xmmword ptr xmm15_data[rip]
|
||||
|
||||
mov rdx, rsp
|
||||
call r10 // _setjmp or _setjmpex
|
||||
GLOBAL_LABEL setjmp_return_address
|
||||
|
||||
// Restore non-volatile registers
|
||||
mov rbx, [rsp + 0 * 8]
|
||||
mov rbp, [rsp + 1 * 8]
|
||||
mov rsi, [rsp + 2 * 8]
|
||||
mov rdi, [rsp + 3 * 8]
|
||||
mov r12, [rsp + 4 * 8]
|
||||
mov r13, [rsp + 5 * 8]
|
||||
mov r14, [rsp + 6 * 8]
|
||||
mov r15, [rsp + 7 * 8]
|
||||
|
||||
// Restore non-volatile xmm registers
|
||||
movdqa xmm6, xmmword ptr [rsp + 8 * 8 + 0 * 16]
|
||||
movdqa xmm7, xmmword ptr [rsp + 8 * 8 + 1 * 16]
|
||||
movdqa xmm8, xmmword ptr [rsp + 8 * 8 + 2 * 16]
|
||||
movdqa xmm9, xmmword ptr [rsp + 8 * 8 + 3 * 16]
|
||||
movdqa xmm10, xmmword ptr [rsp + 8 * 8 + 4 * 16]
|
||||
movdqa xmm11, xmmword ptr [rsp + 8 * 8 + 5 * 16]
|
||||
movdqa xmm12, xmmword ptr [rsp + 8 * 8 + 6 * 16]
|
||||
movdqa xmm13, xmmword ptr [rsp + 8 * 8 + 7 * 16]
|
||||
movdqa xmm14, xmmword ptr [rsp + 8 * 8 + 8 * 16]
|
||||
movdqa xmm15, xmmword ptr [rsp + 8 * 8 + 9 * 16]
|
||||
|
||||
add rsp, 8 * 8 + 10 * 16 + 8 // Restore stack pointer
|
||||
ret
|
||||
|
||||
.ENDP
|
||||
|
||||
END
|
79
modules/rostests/apitests/crt/i386/setjmp_helper.s
Normal file
79
modules/rostests/apitests/crt/i386/setjmp_helper.s
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Test helper for x86 setjmp
|
||||
* COPYRIGHT: Copyright 2025 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
#ifdef TEST_UCRTBASE
|
||||
#define __setjmp ___intrinsic_setjmp
|
||||
#endif
|
||||
|
||||
.code
|
||||
|
||||
PUBLIC _get_sp
|
||||
_get_sp:
|
||||
lea eax, [esp + 4]
|
||||
ret
|
||||
|
||||
EXTERN __setjmp:PROC
|
||||
PUBLIC _setjmp_return_address
|
||||
EXTERN __setjmp3:PROC
|
||||
|
||||
PUBLIC __setjmp1
|
||||
__setjmp1:
|
||||
jmp __setjmp
|
||||
|
||||
PUBLIC _call_setjmp
|
||||
_call_setjmp:
|
||||
push offset __setjmp
|
||||
jmp _call_setjmp_common
|
||||
|
||||
PUBLIC _call_setjmp3
|
||||
_call_setjmp3:
|
||||
push offset __setjmp3
|
||||
jmp _call_setjmp_common
|
||||
|
||||
|
||||
_call_setjmp_common:
|
||||
// Save non-volatile registers
|
||||
push ebp
|
||||
push ebx
|
||||
push edi
|
||||
push esi
|
||||
|
||||
// Set up a register state
|
||||
mov ebp, HEX(A1A1A1A1)
|
||||
mov ebx, HEX(A2A2A2A2)
|
||||
mov edi, HEX(A3A3A3A3)
|
||||
mov esi, HEX(A4A4A4A4)
|
||||
|
||||
// First push parameters for _setjmp3
|
||||
push HEX(3456789A) // Param 3
|
||||
push HEX(23456789) // Param 2
|
||||
push HEX(12345678) // Param 1
|
||||
push HEX(00000007) // TryLevel
|
||||
push HEX(00012345) // UnwindFunc
|
||||
push HEX(00000005) // Count
|
||||
|
||||
// Common parameter for both _setjmp and _setjmp3
|
||||
push dword ptr [esp + 48]
|
||||
call dword ptr [esp + 44]
|
||||
_setjmp_return_address:
|
||||
|
||||
add esp, 28
|
||||
|
||||
// Restore non-volatile registers
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
pop ebp
|
||||
|
||||
// Clean up the stack
|
||||
add esp, 4
|
||||
|
||||
ret
|
||||
|
||||
END
|
@@ -13,6 +13,12 @@
|
||||
#include <assert.h>
|
||||
#include <rtlfuncs.h>
|
||||
|
||||
#if defined(_M_IX86) && !defined(_MSC_VER)
|
||||
#define todo_pseh todo_if(1)
|
||||
#else
|
||||
#define todo_pseh
|
||||
#endif
|
||||
|
||||
static jmp_buf g_jmp_buf;
|
||||
|
||||
static void TEST_setjmp_normal(void)
|
||||
@@ -193,6 +199,362 @@ static void TEST_setjmp_zero_longjmp_check(void)
|
||||
}
|
||||
}
|
||||
|
||||
void call_setjmp(_JUMP_BUFFER *Buf);
|
||||
ULONG_PTR get_sp(void);
|
||||
extern char setjmp_return_address;
|
||||
#ifdef _M_AMD64
|
||||
void call_setjmpex(_JUMP_BUFFER *Buf);
|
||||
#elif defined(_M_IX86)
|
||||
int _setjmp3(jmp_buf env, int count, /* void* UnwindFunc, unsigned TryLevel, */ ...);
|
||||
int _setjmp1(jmp_buf env); // ASM call wrapper around _setjmp, which is an intrinsic on MSVC
|
||||
void call_setjmp3(_JUMP_BUFFER *Buf);
|
||||
#endif
|
||||
|
||||
static void check_buffer_registers_(ULONG Line, _JUMP_BUFFER* Buf, ULONG_PTR Sp, void* Pc)
|
||||
{
|
||||
#ifdef _M_AMD64
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Frame, Sp - 0xF0);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rbx, 0xA1A1A1A1A1A1A1A1ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rsp, Sp - 0xF0);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rbp, 0xA2A2A2A2A2A2A2A2ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rsi, 0xA3A3A3A3A3A3A3A3ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rdi, 0xA4A4A4A4A4A4A4A4ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->R12, 0xACACACACACACACACULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->R13, 0xADADADADADADADADULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->R14, 0xAEAEAEAEAEAEAEAEULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->R15, 0xAFAFAFAFAFAFAFAFULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Rip, (ULONG64)Pc);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->MxCsr, 0x00001f80);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->FpCsr, 0x27F);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Spare, 0xCCCC);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm6.Part[0], 0x0606060606060606ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm6.Part[1], 0x1616161616161616ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm7.Part[0], 0x0707070707070707ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm7.Part[1], 0x1717171717171717ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm8.Part[0], 0x0808080808080808ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm8.Part[1], 0x1818181818181818ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm9.Part[0], 0x0909090909090909ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm9.Part[1], 0x1919191919191919ULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm10.Part[0], 0x0A0A0A0A0A0A0A0AULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm10.Part[1], 0x1A1A1A1A1A1A1A1AULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm11.Part[0], 0x0B0B0B0B0B0B0B0BULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm11.Part[1], 0x1B1B1B1B1B1B1B1BULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm12.Part[0], 0x0C0C0C0C0C0C0C0CULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm12.Part[1], 0x1C1C1C1C1C1C1C1CULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm13.Part[0], 0x0D0D0D0D0D0D0D0DULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm13.Part[1], 0x1D1D1D1D1D1D1D1DULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm14.Part[0], 0x0E0E0E0E0E0E0E0EULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm14.Part[1], 0x1E1E1E1E1E1E1E1EULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm15.Part[0], 0x0F0F0F0F0F0F0F0FULL);
|
||||
ok_eq_hex64_(__FILE__, Line, Buf->Xmm15.Part[1], 0x1F1F1F1F1F1F1F1FULL);
|
||||
#elif defined(_M_IX86)
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Ebp, 0xA1A1A1A1ul);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Ebx, 0xA2A2A2A2ul);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Edi, 0xA3A3A3A3ul);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Esi, 0xA4A4A4A4ul);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Esp, Sp - 0x38);
|
||||
ok_eq_hex_(__FILE__, Line, Buf->Eip, (ULONG)Pc);
|
||||
#endif
|
||||
}
|
||||
#define check_buffer_registers(Buf, Sp, Pc) \
|
||||
check_buffer_registers_(__LINE__, Buf, Sp, Pc)
|
||||
|
||||
static void TEST_buffer_contents(void)
|
||||
{
|
||||
_JUMP_BUFFER buf;
|
||||
|
||||
memset(&buf, 0xCC, sizeof(buf));
|
||||
call_setjmp(&buf);
|
||||
check_buffer_registers(&buf, get_sp(), &setjmp_return_address);
|
||||
|
||||
#ifdef _M_AMD64
|
||||
|
||||
memset(&buf, 0xCC, sizeof(buf));
|
||||
call_setjmpex(&buf);
|
||||
check_buffer_registers(&buf, get_sp(), &setjmp_return_address);
|
||||
|
||||
#elif defined(_M_IX86)
|
||||
|
||||
ok_eq_hex(buf.Registration, __readfsdword(0));
|
||||
todo_pseh ok_eq_hex(buf.TryLevel, 0xFFFFFFFF);
|
||||
ok_eq_hex(buf.Cookie, 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindFunc, 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[0], 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[1], 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[2], 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[3], 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[4], 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindData[5], 0xCCCCCCCC);
|
||||
|
||||
// Temporarily remove the SEH registration (__writefsdword(0, ...) is not allowed with MSVC)
|
||||
PULONG ExceptionRegistrationPtr = (PULONG)NtCurrentTeb();
|
||||
ULONG Registration = *ExceptionRegistrationPtr;
|
||||
*ExceptionRegistrationPtr = 0xFFFFFFFF;
|
||||
|
||||
memset(&buf, 0xCC, sizeof(buf));
|
||||
call_setjmp(&buf);
|
||||
ok_eq_hex(buf.Registration, 0xFFFFFFFF);
|
||||
ok_eq_hex(buf.TryLevel, 0xFFFFFFFF);
|
||||
ok_eq_hex(buf.Cookie, 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindFunc, 0xCCCCCCCC);
|
||||
|
||||
// Restore the SEH registration
|
||||
*ExceptionRegistrationPtr = Registration;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Registration = __readfsdword(0);
|
||||
_SEH2_TRY
|
||||
{
|
||||
ok_eq_hex(Registration, __readfsdword(0));
|
||||
memset(&buf, 0xCC, sizeof(buf));
|
||||
call_setjmp(&buf);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* This is to ensure that the exception handler is not optimized out. */
|
||||
ok_int(GetExceptionCode(), 0);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* This is to ensure that the exception handler is not optimized out. */
|
||||
ok_int(GetExceptionCode(), 0);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
ok_eq_hex(buf.Registration, Registration);
|
||||
todo_pseh ok_eq_hex(buf.TryLevel, 1);
|
||||
ok_eq_hex(buf.Cookie, 0xCCCCCCCC);
|
||||
ok_eq_hex(buf.UnwindFunc, 0xCCCCCCCC);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _M_IX86
|
||||
|
||||
__declspec(noinline)
|
||||
static void Test_setjmp1_longjmp_inside_SEH(void)
|
||||
{
|
||||
jmp_buf buf;
|
||||
int finally_called = 0;
|
||||
|
||||
// Use the legacy _setjmp
|
||||
int longjmp_value = _setjmp1(buf);
|
||||
if (longjmp_value == 0)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
longjmp(buf, 0x12345678);
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
finally_called = 1;
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
ok_eq_int(longjmp_value, 0x12345678);
|
||||
ok_eq_int(finally_called, 1);
|
||||
}
|
||||
|
||||
__declspec(noinline)
|
||||
static int Test_setjmp1_inner(void)
|
||||
{
|
||||
jmp_buf buf;
|
||||
|
||||
int longjmp_value = _setjmp1(buf);
|
||||
if (longjmp_value == 0)
|
||||
{
|
||||
longjmp(buf, 0x12345678);
|
||||
}
|
||||
return longjmp_value;
|
||||
}
|
||||
|
||||
__declspec(noinline)
|
||||
static void Test_setjmp1_external_inside_SEH(void)
|
||||
{
|
||||
volatile int ret = 0;
|
||||
_SEH2_TRY
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ret = Test_setjmp1_inner();
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
if (_SEH2_AbnormalTermination())
|
||||
ret = -1;
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ret = -2;
|
||||
}
|
||||
_SEH2_END;
|
||||
ok_eq_int(ret, 0x12345678);
|
||||
}
|
||||
|
||||
#if 0 // This actually crashes on Windows!
|
||||
__declspec(noinline)
|
||||
void Test_setjmp1_no_SEH_registration(void)
|
||||
{
|
||||
jmp_buf buf;
|
||||
|
||||
// Temporarily remove the SEH registration
|
||||
PULONG ExceptionRegistrationPtr = (PULONG)NtCurrentTeb();
|
||||
ULONG Registration = *ExceptionRegistrationPtr;
|
||||
*ExceptionRegistrationPtr = 0xFFFFFFFF;
|
||||
|
||||
// This will save 0xFFFFFFFF in the Registration field
|
||||
int longjmp_value = _setjmp1(buf);
|
||||
if (longjmp_value == 0)
|
||||
{
|
||||
// This will check if Registration is 0(!) and if not, it will
|
||||
// call _local_unwind2, which will dereference the Registration
|
||||
// and crash.
|
||||
longjmp(buf, 1);
|
||||
}
|
||||
|
||||
ok_eq_int(longjmp_value, 1);
|
||||
|
||||
// Restore the SEH registration
|
||||
*ExceptionRegistrationPtr = Registration;
|
||||
}
|
||||
#endif
|
||||
|
||||
__declspec(noinline)
|
||||
static void Test_setjmp3(void)
|
||||
{
|
||||
ULONG BufferData[18];
|
||||
_JUMP_BUFFER* Buf = (_JUMP_BUFFER*)&BufferData;
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
call_setjmp3(Buf);
|
||||
check_buffer_registers(Buf, get_sp(), &setjmp_return_address);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 7);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, 0x00012345);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0x12345678);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0x23456789);
|
||||
ok_eq_hex(Buf->UnwindData[2], 0x3456789a);
|
||||
ok_eq_hex(Buf->UnwindData[3], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[4], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[5], 0xCCCCCCCC);
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 0, (void*)0x12345, 3, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 0);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, 0x00000000);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[2], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[3], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[4], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[5], 0xCCCCCCCC);
|
||||
|
||||
static ULONG Data[4] = { 0x0123, 0x1234, 0x2345, 0x3456 };
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 1, Data, 7, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 0x00003456);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, (ULONG)Data);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xCCCCCCCC);
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 2, Data, 7, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 7);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, (ULONG)Data);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xCCCCCCCC);
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 3, Data, 7, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 7);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, (ULONG)Data);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xA1A1A1A1);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0xCCCCCCCC);
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 11, (PVOID)0xdeadbeef, 7, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4, 0xA5A5A5A5, 0xA6A6A6A6, 0xA7A7A7A7, 0xA8A8A8A8, 0xA9A9A9A9);
|
||||
ok_eq_hex(Buf->Registration, __readfsdword(0));
|
||||
ok_eq_hex(Buf->TryLevel, 7);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, 0xdeadbeef);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xA1A1A1A1);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0xA2A2A2A2);
|
||||
ok_eq_hex(Buf->UnwindData[2], 0xA3A3A3A3);
|
||||
ok_eq_hex(Buf->UnwindData[3], 0xA4A4A4A4);
|
||||
ok_eq_hex(Buf->UnwindData[4], 0xA5A5A5A5);
|
||||
ok_eq_hex(Buf->UnwindData[5], 0xA6A6A6A6);
|
||||
ok_eq_hex(BufferData[16], 0xCCCCCCCC);
|
||||
ok_eq_hex(BufferData[17], 0xCCCCCCCC);
|
||||
|
||||
// Temporarily remove the SEH registration
|
||||
PULONG ExceptionRegistrationPtr = (PULONG)NtCurrentTeb();
|
||||
ULONG Registration = *ExceptionRegistrationPtr;
|
||||
*ExceptionRegistrationPtr = 0xFFFFFFFF;
|
||||
|
||||
memset(&BufferData, 0xCC, sizeof(BufferData));
|
||||
_setjmp3((int*)Buf, 11, (PVOID)0xdeadbeef, 7, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4, 0xA5A5A5A5, 0xA6A6A6A6, 0xA7A7A7A7, 0xA8A8A8A8, 0xA9A9A9A9);
|
||||
ok_eq_hex(Buf->Registration, 0xFFFFFFFF);
|
||||
ok_eq_hex(Buf->TryLevel, 0xFFFFFFFF);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, 0x00000000);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0xCCCCCCCC);
|
||||
|
||||
int value = _setjmp3((int*)Buf, 0);
|
||||
if (value == 0)
|
||||
{
|
||||
ok_eq_hex(Buf->Registration, 0xFFFFFFFF);
|
||||
ok_eq_hex(Buf->TryLevel, 0xFFFFFFFF);
|
||||
ok_eq_hex(Buf->Cookie, 0x56433230);
|
||||
ok_eq_hex(Buf->UnwindFunc, 0x00000000);
|
||||
ok_eq_hex(Buf->UnwindData[0], 0xCCCCCCCC);
|
||||
ok_eq_hex(Buf->UnwindData[1], 0xCCCCCCCC);
|
||||
longjmp((int*)Buf, 0xBEEFCAFE);
|
||||
ok(0, "Should not get here\n");
|
||||
}
|
||||
ok_int(value, 0xBEEFCAFE);
|
||||
|
||||
// Restore the SEH registration
|
||||
*ExceptionRegistrationPtr = Registration;
|
||||
}
|
||||
|
||||
__declspec(noinline)
|
||||
void Test_setjmp3_with_SEH(void)
|
||||
{
|
||||
_JUMP_BUFFER buf;
|
||||
volatile int dummy;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
dummy = 0;
|
||||
(void)dummy;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
memset(&buf, 0xCC, sizeof(buf));
|
||||
_setjmp3((int*)& buf, 0, (void*)0x12345, 3, 0xA1A1A1A1, 0xA2A2A2A2, 0xA3A3A3A3, 0xA4A4A4A4);
|
||||
ok_eq_hex(buf.Registration, __readfsdword(0));
|
||||
todo_pseh ok_eq_hex(buf.TryLevel, 0xffffffff);
|
||||
}
|
||||
|
||||
#endif // _M_IX86
|
||||
|
||||
#undef setjmp
|
||||
START_TEST(setjmp)
|
||||
{
|
||||
ZeroMemory(&s_check_points, sizeof(s_check_points));
|
||||
@@ -202,6 +564,14 @@ START_TEST(setjmp)
|
||||
TEST_setjmp_return_check();
|
||||
TEST_setjmp_longjmp_integration();
|
||||
TEST_setjmp_zero_longjmp_check();
|
||||
TEST_buffer_contents();
|
||||
#ifdef _M_IX86
|
||||
Test_setjmp1_longjmp_inside_SEH();
|
||||
Test_setjmp1_external_inside_SEH();
|
||||
//Test_setjmp1_no_SEH_registration();
|
||||
Test_setjmp3();
|
||||
Test_setjmp3_with_SEH();
|
||||
#endif /* _M_IX86 */
|
||||
|
||||
#define DO_COME(number) \
|
||||
ok(s_check_points[number], "CheckPoint #%d: Didn't reach\n", number)
|
||||
|
@@ -40,9 +40,20 @@ elseif(ARCH STREQUAL "arm")
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(static_crt_apitest EXCLUDE_FROM_ALL testlist.c ${SOURCE_STATIC})
|
||||
if(ARCH STREQUAL "i386")
|
||||
list(APPEND ASM_SOURCE_STATIC
|
||||
i386/setjmp_helper.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
list(APPEND ASM_SOURCE_STATIC
|
||||
amd64/setjmp_helper.s
|
||||
)
|
||||
endif()
|
||||
add_asm_files(crt_test_asm ${ASM_SOURCE_STATIC})
|
||||
|
||||
add_executable(static_crt_apitest EXCLUDE_FROM_ALL testlist.c ${SOURCE_STATIC} ${crt_test_asm})
|
||||
target_compile_definitions(static_crt_apitest PRIVATE TEST_STATIC_CRT _CRTBLD wine_dbgstr_an=wine_dbgstr_an_ wine_dbgstr_wn=wine_dbgstr_wn_)
|
||||
target_link_libraries(static_crt_apitest crt wine ${PSEH_LIB})
|
||||
target_link_libraries(static_crt_apitest setjmp crt wine ${PSEH_LIB})
|
||||
set_module_type(static_crt_apitest win32cui)
|
||||
add_importlibs(static_crt_apitest kernel32 ntdll)
|
||||
add_rostests_file(TARGET static_crt_apitest)
|
||||
|
@@ -19,7 +19,17 @@ list(APPEND SOURCE_CRTDLL
|
||||
../crt/wctomb.c
|
||||
)
|
||||
|
||||
add_executable(crtdll_apitest testlist.c ${SOURCE_CRTDLL})
|
||||
if(ARCH STREQUAL "i386")
|
||||
add_asm_files(crtdll_apitest_asm
|
||||
../crt/i386/setjmp_helper.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
add_asm_files(crtdll_apitest_asm
|
||||
../crt/amd64/setjmp_helper.s
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(crtdll_apitest testlist.c ${SOURCE_CRTDLL} ${crtdll_apitest_asm})
|
||||
target_compile_definitions(crtdll_apitest PRIVATE TEST_CRTDLL)
|
||||
target_link_libraries(crtdll_apitest wine ${PSEH_LIB})
|
||||
set_module_type(crtdll_apitest win32cui)
|
||||
|
@@ -54,6 +54,13 @@ if(ARCH STREQUAL "i386")
|
||||
list(APPEND SOURCE_CRT_TESTS
|
||||
../crt/__getmainargs.c # FIXME: Moved here because it doesn't work on x64
|
||||
)
|
||||
list(APPEND ASM_SOURCE_CRT_TESTS
|
||||
../crt/i386/setjmp_helper.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
list(APPEND ASM_SOURCE_CRT_TESTS
|
||||
../crt/amd64/setjmp_helper.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "arm")
|
||||
list(APPEND SOURCE_CRT_TESTS
|
||||
../crt/__rt_div.c
|
||||
@@ -61,9 +68,11 @@ elseif(ARCH STREQUAL "arm")
|
||||
../crt/__64tof.c
|
||||
)
|
||||
endif()
|
||||
add_asm_files(crt_asm ${ASM_SOURCE_CRT_TESTS})
|
||||
|
||||
list(APPEND SOURCE
|
||||
${SOURCE_CRT_TESTS}
|
||||
${crt_asm}
|
||||
CommandLine.c
|
||||
ieee.c
|
||||
popen.c
|
||||
@@ -71,6 +80,7 @@ list(APPEND SOURCE
|
||||
testlist.c)
|
||||
|
||||
add_executable(msvcrt_apitest ${SOURCE})
|
||||
add_dependencies(msvcrt_apitest asm)
|
||||
target_compile_definitions(msvcrt_apitest PRIVATE TEST_MSVCRT)
|
||||
target_link_libraries(msvcrt_apitest wine ${PSEH_LIB})
|
||||
set_module_type(msvcrt_apitest win32cui)
|
||||
|
@@ -139,9 +139,15 @@ list(APPEND SOURCE
|
||||
precomp.h)
|
||||
|
||||
if(ARCH STREQUAL "i386")
|
||||
add_asm_files(ntdll_apitest_asm i386/NtContinue.S)
|
||||
add_asm_files(ntdll_apitest_asm
|
||||
../crt/i386/setjmp_helper.s
|
||||
i386/NtContinue.S
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
add_asm_files(ntdll_apitest_asm amd64/NtContinue.S)
|
||||
add_asm_files(ntdll_apitest_asm
|
||||
../crt/amd64/setjmp_helper.s
|
||||
amd64/NtContinue.S
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
|
@@ -22,13 +22,24 @@ list(APPEND SOURCE
|
||||
../crt/log.c
|
||||
../crt/log10.c
|
||||
../crt/round.c
|
||||
../crt/setjmp.c
|
||||
../crt/sin.c
|
||||
../crt/sqrt.c
|
||||
../crt/tan.c
|
||||
testlist.c
|
||||
)
|
||||
|
||||
add_executable(ucrtbase_apitest ${SOURCE})
|
||||
if(ARCH STREQUAL "i386")
|
||||
add_asm_files(ucrtbase_apitest_asm
|
||||
../crt/i386/setjmp_helper.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
add_asm_files(ucrtbase_apitest_asm
|
||||
../crt/amd64/setjmp_helper.s
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(ucrtbase_apitest ${SOURCE} ${ucrtbase_apitest_asm})
|
||||
set_module_type(ucrtbase_apitest win32cui)
|
||||
|
||||
target_link_libraries(ucrtbase_apitest ${PSEH_LIB} chkstk)
|
||||
@@ -37,5 +48,5 @@ if(NOT MSVC)
|
||||
target_link_libraries(ucrtbase_apitest -lgcc)
|
||||
endif()
|
||||
|
||||
add_importlibs(ucrtbase_apitest ucrtbase kernel32 ntdll)
|
||||
add_importlibs(ucrtbase_apitest ucrtbase kernel32)
|
||||
add_rostests_file(TARGET ucrtbase_apitest)
|
||||
|
@@ -14,6 +14,7 @@ extern void func_exp(void);
|
||||
extern void func_log(void);
|
||||
extern void func_log10(void);
|
||||
extern void func_round(void);
|
||||
extern void func_setjmp(void);
|
||||
extern void func_sin(void);
|
||||
extern void func_sqrt(void);
|
||||
extern void func_tan(void);
|
||||
@@ -32,6 +33,7 @@ const struct test winetest_testlist[] =
|
||||
{ "log", func_log },
|
||||
{ "log10", func_log10 },
|
||||
{ "round", func_round },
|
||||
{ "setjmp", func_setjmp },
|
||||
{ "sin", func_sin },
|
||||
{ "sqrt", func_sqrt },
|
||||
{ "tan", func_tan },
|
||||
|
Reference in New Issue
Block a user