ntdll: Go through the syscall return path for syscall faults.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-06-21 15:43:22 +02:00
parent 5b47e4ac0b
commit db26df5934
6 changed files with 54 additions and 66 deletions

View File

@ -600,19 +600,9 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec )
else
{
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->pc, rec->ExceptionCode );
REGn_sig(0, context) = rec->ExceptionCode;
REGn_sig(4, context) = frame->r4;
REGn_sig(5, context) = frame->r5;
REGn_sig(6, context) = frame->r6;
REGn_sig(7, context) = frame->r7;
REGn_sig(8, context) = frame->r8;
REGn_sig(9, context) = frame->r9;
REGn_sig(10, context) = frame->r10;
FP_sig(context) = frame->r11;
LR_sig(context) = frame->lr;
SP_sig(context) = frame->sp;
PC_sig(context) = frame->pc;
CPSR_sig(context) = frame->cpsr;
REGn_sig(0, context) = (DWORD)frame;
REGn_sig(1, context) = rec->ExceptionCode;
PC_sig(context) = (DWORD)__wine_syscall_dispatcher_return;
}
return TRUE;
}

View File

@ -756,12 +756,9 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec )
else
{
TRACE( "returning to user mode ip=%p ret=%08x\n", (void *)frame->pc, rec->ExceptionCode );
for (i = 18; i < 29; i++) REGn_sig( i, context ) = frame->x[i];
REGn_sig(0, context) = rec->ExceptionCode;
FP_sig(context) = frame->fp;
LR_sig(context) = frame->lr;
SP_sig(context) = frame->sp;
PC_sig(context) = frame->pc;
REGn_sig(0, context) = (ULONG_PTR)frame;
REGn_sig(1, context) = rec->ExceptionCode;
PC_sig(context) = (ULONG_PTR)__wine_syscall_dispatcher_return;
}
return TRUE;
}

View File

@ -480,7 +480,8 @@ struct syscall_frame
DWORD edi; /* 02c */
DWORD esi; /* 030 */
DWORD ebp; /* 034 */
DWORD align[2]; /* 038 */
DWORD syscall_flags; /* 038 */
DWORD align; /* 03c */
union /* 040 */
{
XSAVE_FORMAT xsave;
@ -1709,7 +1710,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
EXCEPTION_RECORD *rec, CONTEXT *context )
{
struct syscall_frame *frame = x86_thread_data()->syscall_frame;
DWORD i;
DWORD i, *stack;
if (!is_inside_syscall( sigcontext )) return FALSE;
@ -1727,10 +1728,9 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
if (ntdll_get_thread_data()->jmp_buf)
{
DWORD *stack = stack_ptr;
TRACE( "returning to handler\n" );
/* push stack frame for calling __wine_longjmp */
stack = stack_ptr;
*(--stack) = 1;
*(--stack) = (DWORD)ntdll_get_thread_data()->jmp_buf;
*(--stack) = 0xdeadbabe; /* return address */
@ -1741,13 +1741,12 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr,
else
{
TRACE( "returning to user mode ip=%08x ret=%08x\n", frame->eip, rec->ExceptionCode );
EAX_sig(sigcontext) = rec->ExceptionCode;
EBX_sig(sigcontext) = frame->ebx;
ESI_sig(sigcontext) = frame->esi;
EDI_sig(sigcontext) = frame->edi;
EBP_sig(sigcontext) = frame->ebp;
ESP_sig(sigcontext) = frame->esp;
EIP_sig(sigcontext) = frame->eip;
stack = (DWORD *)frame;
*(--stack) = rec->ExceptionCode;
*(--stack) = (DWORD)frame;
*(--stack) = 0xdeadbabe; /* return address */
ESP_sig(sigcontext) = (DWORD)stack;
EIP_sig(sigcontext) = (DWORD)__wine_syscall_dispatcher_return;
}
return TRUE;
}
@ -2401,6 +2400,8 @@ static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry,
*/
PCONTEXT DECLSPEC_HIDDEN get_initial_context( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb )
{
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
struct syscall_frame *frame = thread_data->syscall_frame;
CONTEXT *ctx;
if (suspend)
@ -2417,6 +2418,7 @@ PCONTEXT DECLSPEC_HIDDEN get_initial_context( LPTHREAD_START_ROUTINE entry, void
ctx = (CONTEXT *)((char *)teb->Tib.StackBase - 16) - 1;
init_thread_context( ctx, entry, arg, teb );
}
frame->syscall_flags = __wine_syscall_flags;
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
return ctx;

View File

@ -2182,21 +2182,10 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec,
}
else
{
XMM_SAVE_AREA32 *fpu = FPU_sig(sigcontext);
TRACE( "returning to user mode ip=%016lx ret=%08x\n", frame->rip, rec->ExceptionCode );
RAX_sig(sigcontext) = rec->ExceptionCode;
RBX_sig(sigcontext) = frame->rbx;
RSI_sig(sigcontext) = frame->rsi;
RDI_sig(sigcontext) = frame->rdi;
RBP_sig(sigcontext) = frame->rbp;
R12_sig(sigcontext) = frame->r12;
R13_sig(sigcontext) = frame->r13;
R14_sig(sigcontext) = frame->r14;
R15_sig(sigcontext) = frame->r15;
RSP_sig(sigcontext) = frame->rsp;
RIP_sig(sigcontext) = frame->rip;
if (fpu) *fpu = frame->xsave;
RCX_sig(sigcontext) = (ULONG_PTR)frame;
RDX_sig(sigcontext) = rec->ExceptionCode;
RIP_sig(sigcontext) = (ULONG_PTR)__wine_syscall_dispatcher_return;
}
return TRUE;
}

View File

@ -239,6 +239,7 @@ extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE ent
BOOL suspend, void *thunk, TEB *teb ) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int), TEB *teb ) DECLSPEC_HIDDEN;
extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN;
extern void WINAPI DECLSPEC_NORETURN __wine_syscall_dispatcher_return( void *frame, ULONG_PTR retval ) DECLSPEC_HIDDEN;
extern unsigned int __wine_syscall_flags DECLSPEC_HIDDEN;
extern NTSTATUS signal_set_full_context( CONTEXT *context ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) DECLSPEC_HIDDEN;

View File

@ -1460,27 +1460,22 @@ static void output_syscall_dispatcher(void)
{
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal %s-1b(%%eax,%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
output( "\tmovl %s-1b(%%eax),%%edi\n", asm_name("__wine_syscall_flags") );
needs_get_pc_thunk = 1;
}
else
{
output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
output( "\tmovl %s,%%edi\n", asm_name("__wine_syscall_flags") );
}
output( "\ttestl $3,%%edi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
else output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
output( "\ttestl $3,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
output( "\tjz 2f\n" );
output( "\tmovl $7,%%eax\n" );
output( "\txorl %%edx,%%edx\n" );
for (i = 0; i < 6; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
output( "\ttestl $2,%%edi\n" ); /* SYSCALL_HAVE_XSAVEC */
output( "\ttestl $2,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVEC */
output( "\tjz 1f\n" );
for (i = 6; i < 16; i++) output( "\tmovl %%edx,0x%x(%%ecx)\n", 0x240 + i * 4 );
output( "\txsavec 0x40(%%ecx)\n" );
output( "\tjmp 4f\n" );
output( "1:\txsave 0x40(%%ecx)\n" );
output( "\tjmp 4f\n" );
output( "2:\ttestl $4,%%edi\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "2:\ttestl $4,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "\tjz 3f\n" );
output( "\tfxsave 0x40(%%ecx)\n" );
output( "\tjmp 4f\n" );
@ -1494,20 +1489,18 @@ static void output_syscall_dispatcher(void)
output( "\tmovl 12(%%ebx),%%eax\n" ); /* table->ArgumentTable */
output( "\tmovzbl (%%eax,%%edx,1),%%ecx\n" );
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
output( "\tmovl %%edi,%%ebx\n" );
output( "\tsubl %%ecx,%%esp\n" );
output( "\tshrl $2,%%ecx\n" );
output( "\tandl $~15,%%esp\n" );
output( "\tmovl %%esp,%%edi\n" );
output( "\tcld\n" );
output( "\trep; movsl\n" );
output( "\tmovl %%ebx,%%edi\n" );
output( "\tcall *(%%eax,%%edx,4)\n" );
output( "5:\tleal -0x34(%%ebp),%%esp\n" );
output( "\tmovl (%%esp),%%ecx\n" ); /* frame->restore_flags */
output( "\tleal -0x34(%%ebp),%%esp\n" );
output( "5:\tmovl (%%esp),%%ecx\n" ); /* frame->restore_flags */
output( "\ttestl $0x68,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
output( "\tjz 3f\n" );
output( "\ttestl $3,%%edi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
output( "\ttestl $3,0x38(%%esp)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
output( "\tjz 1f\n" );
output( "\tmovl %%eax,%%esi\n" );
output( "\tmovl $7,%%eax\n" );
@ -1515,7 +1508,7 @@ static void output_syscall_dispatcher(void)
output( "\txrstor 0x40(%%esp)\n" );
output( "\tmovl %%esi,%%eax\n" );
output( "\tjmp 3f\n" );
output( "1:\ttestl $4,%%edi\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "1:\ttestl $4,0x38(%%esp)\n" ); /* SYSCALL_HAVE_FXSAVE */
output( "\tjz 2f\n" );
output( "\tfxrstor 0x40(%%esp)\n" );
output( "\tjmp 3f\n" );
@ -1550,6 +1543,10 @@ static void output_syscall_dispatcher(void)
output( "\tiret\n" );
output( "6:\tmovl $0x%x,%%eax\n", invalid_param );
output( "\tjmp 5b\n" );
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
output( "\tmovl 8(%%esp),%%eax\n" );
output( "\tmovl 4(%%esp),%%esp\n" );
output( "\tjmp 5b\n" );
break;
case CPU_x86_64:
output( "\tmovq %%gs:0x30,%%rcx\n" );
@ -1626,8 +1623,8 @@ static void output_syscall_dispatcher(void)
output( "\tsubq $0x20,%%rsp\n" );
output( "\tmovq (%%rbx),%%r10\n" ); /* table->ServiceTable */
output( "\tcallq *(%%r10,%%rax,8)\n" );
output( "2:\tleaq -0x98(%%rbp),%%rcx\n" );
output( "\tmovl 0x94(%%rcx),%%edx\n" ); /* frame->restore_flags */
output( "\tleaq -0x98(%%rbp),%%rcx\n" );
output( "2:\tmovl 0x94(%%rcx),%%edx\n" ); /* frame->restore_flags */
output( "\ttestl $0x48,%%edx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
output( "\tjz 4f\n" );
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
@ -1663,7 +1660,11 @@ static void output_syscall_dispatcher(void)
output( "\tmovq 0x48(%%rcx),%%r11\n" );
output( "\tmovq 0x10(%%rcx),%%rcx\n" );
output( "1:\tiretq\n" );
output( "5:\tmovl $0x%x,%%eax\n", invalid_param );
output( "5:\tmovl $0x%x,%%edx\n", invalid_param );
output( "\tmovq %%rsp,%%rcx\n" );
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
output( "\tmovl %s(%%rip),%%r14d\n", asm_name("__wine_syscall_flags") );
output( "\tmovq %%rdx,%%rax\n" );
output( "\tjmp 2b\n" );
break;
case CPU_ARM:
@ -1712,7 +1713,7 @@ static void output_syscall_dispatcher(void)
output( "\tldr r5, [r4]\n"); /* table->ServiceTable */
output( "\tldr ip, [r5, ip, lsl #2]\n");
output( "\tblx ip\n");
output( "\tldr ip, [r8, #0x44]\n" ); /* frame->restore_flags */
output( "4:\tldr ip, [r8, #0x44]\n" ); /* frame->restore_flags */
if (strcmp( float_abi_option, "soft" ))
{
output( "\ttst ip, #4\n" ); /* CONTEXT_FLOATING_POINT */
@ -1726,13 +1727,17 @@ static void output_syscall_dispatcher(void)
output( "\ttst ip, #2\n" ); /* CONTEXT_INTEGER */
output( "\tit ne\n" );
output( "\tldmne r8, {r0-r3}\n" );
output( "4:\tldr lr, [r8, #0x3c]\n" );
output( "\tldr lr, [r8, #0x3c]\n" );
output( "\tldr sp, [r8, #0x38]\n" );
output( "\tadd r8, r8, #0x10\n" );
output( "\tldm r8, {r4-r12,pc}\n" );
output( "5:\tmovw r0, #0x%x\n", invalid_param & 0xffff );
output( "\tmovt r0, #0x%x\n", invalid_param >> 16 );
output( "\tb 4b\n" );
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
output( "\tmov r8, r0\n" );
output( "\tmov r0, r1\n" );
output( "\tb 4b\n" );
if (UsePIC)
output( "6:\t.long %s-1b-%u\n", asm_name("KeServiceDescriptorTable"), thumb_mode ? 4 : 8 );
else
@ -1836,9 +1841,9 @@ static void output_syscall_dispatcher(void)
output( "\tldp q26, q27, [sp, #0x2c0]\n" );
output( "\tldp q28, q29, [sp, #0x2e0]\n" );
output( "\tldp q30, q31, [sp, #0x300]\n" );
output( "\tldr w9, [x10, #0x118]\n" );
output( "\tldr w9, [sp, #0x118]\n" );
output( "\tmsr FPCR, x9\n" );
output( "\tldr w9, [x10, #0x11c]\n" );
output( "\tldr w9, [sp, #0x11c]\n" );
output( "\tmsr FPSR, x9\n" );
output( "1:\ttbz x16, #1, 1f\n" ); /* CONTEXT_INTEGER */
output( "\tldp x0, x1, [sp, #0x00]\n" );
@ -1857,6 +1862,10 @@ static void output_syscall_dispatcher(void)
output( "4:\tmov x0, #0x%x\n", invalid_param & 0xffff0000 );
output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
output( "\tb 3b\n" );
output( "%s\n", asm_globl("__wine_syscall_dispatcher_return") );
output( "\tmov sp, x0\n" );
output( "\tmov x0, x1\n" );
output( "\tb 3b\n" );
break;
default:
assert(0);