ntdll: Go through the syscall return path for syscall faults.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5b47e4ac0b
commit
db26df5934
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue