mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 19:49:50 +00:00
ntdll: Store the syscall table in the syscall frame on all platforms.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
77f5e2963f
commit
847db3c1d3
8 changed files with 122 additions and 107 deletions
|
@ -115,6 +115,11 @@ SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
|
|||
|
||||
static NTSTATUS (CDECL *p__wine_set_unix_funcs)( int version, const struct unix_funcs *funcs );
|
||||
|
||||
extern SYSTEM_SERVICE_TABLE __wine_syscall_table DECLSPEC_HIDDEN;
|
||||
|
||||
SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
|
||||
#endif
|
||||
|
@ -1939,6 +1944,7 @@ static void start_main_thread(void)
|
|||
NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
|
||||
load_ntdll();
|
||||
if (main_image_info.Machine != current_machine) load_wow64_ntdll( main_image_info.Machine );
|
||||
KeServiceDescriptorTable[0] = __wine_syscall_table;
|
||||
status = p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
|
||||
if (status == STATUS_REVISION_MISMATCH)
|
||||
{
|
||||
|
|
|
@ -192,10 +192,12 @@ struct syscall_frame
|
|||
DWORD restore_flags; /* 044 */
|
||||
DWORD fpscr; /* 048 */
|
||||
struct syscall_frame *prev_frame; /* 04c */
|
||||
ULONGLONG d[32]; /* 050 */
|
||||
SYSTEM_SERVICE_TABLE *syscall_table; /* 050 */
|
||||
DWORD align[3]; /* 054 */
|
||||
ULONGLONG d[32]; /* 060 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x150);
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x160);
|
||||
|
||||
struct arm_thread_data
|
||||
{
|
||||
|
@ -607,6 +609,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
|
|||
callback_frame.frame.sp = (ULONG_PTR)args_data;
|
||||
callback_frame.frame.pc = (ULONG_PTR)pKiUserCallbackDispatcher;
|
||||
callback_frame.frame.restore_flags = CONTEXT_INTEGER;
|
||||
callback_frame.frame.syscall_table = frame->syscall_table;
|
||||
callback_frame.frame.prev_frame = frame;
|
||||
arm_thread_data()->syscall_frame = &callback_frame.frame;
|
||||
|
||||
|
@ -993,6 +996,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
|
|||
frame->r0 = (DWORD)ctx;
|
||||
frame->prev_frame = NULL;
|
||||
frame->restore_flags |= CONTEXT_INTEGER;
|
||||
frame->syscall_table = KeServiceDescriptorTable;
|
||||
|
||||
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
||||
__wine_syscall_dispatcher_return( frame, 0 );
|
||||
|
@ -1009,7 +1013,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
/* set syscall frame */
|
||||
"ldr r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */
|
||||
"cbnz r6, 1f\n\t"
|
||||
"sub r6, sp, #0x150\n\t" /* sizeof(struct syscall_frame) */
|
||||
"sub r6, sp, #0x160\n\t" /* sizeof(struct syscall_frame) */
|
||||
"str r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */
|
||||
"1:\tmov sp, r6\n\t"
|
||||
"bl " __ASM_NAME("call_init_thunk") )
|
||||
|
|
|
@ -142,12 +142,14 @@ struct syscall_frame
|
|||
ULONG cpsr; /* 108 */
|
||||
ULONG restore_flags; /* 10c */
|
||||
struct syscall_frame *prev_frame; /* 110 */
|
||||
ULONG fpcr; /* 118 */
|
||||
ULONG fpsr; /* 11c */
|
||||
NEON128 v[32]; /* 120 */
|
||||
SYSTEM_SERVICE_TABLE *syscall_table; /* 118 */
|
||||
ULONG64 align; /* 120 */
|
||||
ULONG fpcr; /* 128 */
|
||||
ULONG fpsr; /* 12c */
|
||||
NEON128 v[32]; /* 130 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x320 );
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x330 );
|
||||
|
||||
struct arm64_thread_data
|
||||
{
|
||||
|
@ -756,6 +758,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
|
|||
callback_frame.frame.sp = (ULONG_PTR)args_data;
|
||||
callback_frame.frame.pc = (ULONG_PTR)pKiUserCallbackDispatcher;
|
||||
callback_frame.frame.restore_flags = CONTEXT_INTEGER;
|
||||
callback_frame.frame.syscall_table = frame->syscall_table;
|
||||
callback_frame.frame.prev_frame = frame;
|
||||
arm64_thread_data()->syscall_frame = &callback_frame.frame;
|
||||
|
||||
|
@ -1186,6 +1189,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
|
|||
frame->x[18] = (ULONG64)teb;
|
||||
frame->prev_frame = NULL;
|
||||
frame->restore_flags |= CONTEXT_INTEGER;
|
||||
frame->syscall_table = KeServiceDescriptorTable;
|
||||
|
||||
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
||||
__wine_syscall_dispatcher_return( frame, 0 );
|
||||
|
@ -1203,7 +1207,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
/* set syscall frame */
|
||||
"ldr x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */
|
||||
"cbnz x8, 1f\n\t"
|
||||
"sub x8, sp, #0x320\n\t" /* sizeof(struct syscall_frame) */
|
||||
"sub x8, sp, #0x330\n\t" /* sizeof(struct syscall_frame) */
|
||||
"str x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */
|
||||
"1:\tmov sp, x8\n\t"
|
||||
"bl " __ASM_NAME("call_init_thunk") )
|
||||
|
|
|
@ -463,26 +463,27 @@ enum i386_trap_code
|
|||
|
||||
struct syscall_frame
|
||||
{
|
||||
DWORD restore_flags; /* 000 */
|
||||
DWORD eflags; /* 004 */
|
||||
DWORD eip; /* 008 */
|
||||
DWORD esp; /* 00c */
|
||||
WORD cs; /* 010 */
|
||||
WORD ss; /* 012 */
|
||||
WORD ds; /* 014 */
|
||||
WORD es; /* 016 */
|
||||
WORD fs; /* 018 */
|
||||
WORD gs; /* 01a */
|
||||
DWORD eax; /* 01c */
|
||||
DWORD ebx; /* 020 */
|
||||
DWORD ecx; /* 024 */
|
||||
DWORD edx; /* 028 */
|
||||
DWORD edi; /* 02c */
|
||||
DWORD esi; /* 030 */
|
||||
DWORD ebp; /* 034 */
|
||||
DWORD syscall_flags; /* 038 */
|
||||
struct syscall_frame *prev_frame; /* 03c */
|
||||
union /* 040 */
|
||||
WORD syscall_flags; /* 000 */
|
||||
WORD restore_flags; /* 002 */
|
||||
DWORD eflags; /* 004 */
|
||||
DWORD eip; /* 008 */
|
||||
DWORD esp; /* 00c */
|
||||
WORD cs; /* 010 */
|
||||
WORD ss; /* 012 */
|
||||
WORD ds; /* 014 */
|
||||
WORD es; /* 016 */
|
||||
WORD fs; /* 018 */
|
||||
WORD gs; /* 01a */
|
||||
DWORD eax; /* 01c */
|
||||
DWORD ebx; /* 020 */
|
||||
DWORD ecx; /* 024 */
|
||||
DWORD edx; /* 028 */
|
||||
DWORD edi; /* 02c */
|
||||
DWORD esi; /* 030 */
|
||||
DWORD ebp; /* 034 */
|
||||
SYSTEM_SERVICE_TABLE *syscall_table; /* 038 */
|
||||
struct syscall_frame *prev_frame; /* 03c */
|
||||
union /* 040 */
|
||||
{
|
||||
XSAVE_FORMAT xsave;
|
||||
FLOATING_SAVE_AREA fsave;
|
||||
|
@ -490,7 +491,7 @@ struct syscall_frame
|
|||
/* Leave space for the whole set of YMM registers. They're not used in
|
||||
* 32-bit mode, but some processors fault if they're not in writable memory.
|
||||
*/
|
||||
DECLSPEC_ALIGN(64) XSTATE xstate; /* 240 */
|
||||
DECLSPEC_ALIGN(64) XSTATE xstate; /* 240 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct syscall_frame) == 0x380 );
|
||||
|
@ -873,7 +874,7 @@ NTSTATUS signal_set_full_context( CONTEXT *context )
|
|||
NTSTATUS status = NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
|
||||
x86_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER;
|
||||
x86_thread_data()->syscall_frame->restore_flags |= LOWORD(CONTEXT_INTEGER);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1617,6 +1618,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
|
|||
callback_frame.frame.eip = (ULONG_PTR)pKiUserCallbackDispatcher;
|
||||
callback_frame.frame.eflags = 0x202;
|
||||
callback_frame.frame.syscall_flags = frame->syscall_flags;
|
||||
callback_frame.frame.syscall_table = frame->syscall_table;
|
||||
callback_frame.frame.prev_frame = frame;
|
||||
x86_thread_data()->syscall_frame = &callback_frame.frame;
|
||||
|
||||
|
@ -1779,7 +1781,7 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext )
|
|||
|
||||
frame->eip = *(ULONG *)ESP_sig( sigcontext );
|
||||
frame->eflags = EFL_sig(sigcontext);
|
||||
frame->restore_flags = CONTEXT_CONTROL;
|
||||
frame->restore_flags = LOWORD(CONTEXT_CONTROL);
|
||||
|
||||
EIP_sig( sigcontext ) = (ULONG)__wine_syscall_dispatcher_prolog_end;
|
||||
ECX_sig( sigcontext ) = (ULONG)frame;
|
||||
|
@ -2420,7 +2422,8 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
|
|||
frame->eip = (DWORD)pLdrInitializeThunk;
|
||||
frame->prev_frame = NULL;
|
||||
frame->syscall_flags = syscall_flags;
|
||||
frame->restore_flags |= CONTEXT_INTEGER;
|
||||
frame->syscall_table = KeServiceDescriptorTable;
|
||||
frame->restore_flags |= LOWORD(CONTEXT_INTEGER);
|
||||
|
||||
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
||||
__wine_syscall_dispatcher_return( frame, 0 );
|
||||
|
|
|
@ -327,8 +327,9 @@ struct syscall_frame
|
|||
DWORD restore_flags; /* 0094 */
|
||||
ULONG64 rbp; /* 0098 */
|
||||
struct syscall_frame *prev_frame; /* 00a0 */
|
||||
DWORD syscall_flags; /* 00a8 */
|
||||
DWORD align[5]; /* 00ac */
|
||||
SYSTEM_SERVICE_TABLE *syscall_table; /* 00a8 */
|
||||
DWORD syscall_flags; /* 00b0 */
|
||||
DWORD align[3]; /* 00b4 */
|
||||
XMM_SAVE_AREA32 xsave; /* 00c0 */
|
||||
DECLSPEC_ALIGN(64) XSTATE xstate; /* 02c0 */
|
||||
};
|
||||
|
@ -2318,6 +2319,7 @@ NTSTATUS WINAPI KeUserModeCallback( ULONG id, const void *args, ULONG len, void
|
|||
callback_frame.frame.restore_flags = CONTEXT_CONTROL | CONTEXT_INTEGER;
|
||||
callback_frame.frame.prev_frame = frame;
|
||||
callback_frame.frame.syscall_flags = frame->syscall_flags;
|
||||
callback_frame.frame.syscall_table = frame->syscall_table;
|
||||
amd64_thread_data()->syscall_frame = &callback_frame.frame;
|
||||
|
||||
__wine_syscall_dispatcher_return( &callback_frame.frame, 0 );
|
||||
|
@ -3043,6 +3045,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
|
|||
frame->prev_frame = NULL;
|
||||
frame->restore_flags |= CONTEXT_INTEGER;
|
||||
frame->syscall_flags = syscall_flags;
|
||||
frame->syscall_table = KeServiceDescriptorTable;
|
||||
|
||||
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
|
||||
__wine_syscall_dispatcher_return( frame, 0 );
|
||||
|
|
|
@ -26,6 +26,8 @@ typedef UINT64 unixlib_handle_t;
|
|||
|
||||
extern NTSTATUS WINAPI __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args );
|
||||
|
||||
extern SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
|
||||
|
||||
/* some useful helpers from ntdll */
|
||||
extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen );
|
||||
extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict );
|
||||
|
|
|
@ -3761,6 +3761,14 @@ typedef struct
|
|||
} SYSTEM_DLL_INIT_BLOCK;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG_PTR *ServiceTable;
|
||||
ULONG_PTR *CounterTable;
|
||||
ULONG_PTR ServiceLimit;
|
||||
BYTE *ArgumentTable;
|
||||
} SYSTEM_SERVICE_TABLE;
|
||||
|
||||
/***********************************************************************
|
||||
* Function declarations
|
||||
*/
|
||||
|
|
|
@ -1434,7 +1434,7 @@ static void output_syscall_dispatcher(void)
|
|||
{
|
||||
case CPU_x86:
|
||||
output( "\tmovl %%fs:0x1f8,%%ecx\n" ); /* x86_thread_data()->syscall_frame */
|
||||
output( "\tmovl $0,0x00(%%ecx)\n" ); /* frame->restore_flags */
|
||||
output( "\tmovw $0,0x02(%%ecx)\n" ); /* frame->restore_flags */
|
||||
output( "\tpopl 0x08(%%ecx)\n" ); /* frame->eip */
|
||||
output( "\tpushfl\n" );
|
||||
output( "\tpopl 0x04(%%ecx)\n" ); /* frame->eflags */
|
||||
|
@ -1453,29 +1453,23 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\tmovl %%ebp,0x34(%%ecx)\n" );
|
||||
output( "\tleal 0x34(%%ecx),%%ebp\n" );
|
||||
output( "\tleal 4(%%esp),%%esi\n" ); /* first argument */
|
||||
output( "\tmovl %%eax,%%edx\n" );
|
||||
output( "\tshrl $8,%%edx\n" );
|
||||
output( "\tandl $0x30,%%edx\n" ); /* syscall table number */
|
||||
if (UsePIC)
|
||||
{
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tleal %s-1b(%%eax,%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||
needs_get_pc_thunk = 1;
|
||||
}
|
||||
else output( "\tleal %s(%%edx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||
output( "\ttestl $3,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tmovl %%eax,%%ebx\n" );
|
||||
output( "\tshrl $8,%%ebx\n" );
|
||||
output( "\tandl $0x30,%%ebx\n" ); /* syscall table number */
|
||||
output( "\taddl 0x38(%%ecx),%%ebx\n" ); /* frame->syscall_table */
|
||||
output( "\ttestl $3,(%%ecx)\n" ); /* frame->syscall_flags & (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,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_XSAVEC */
|
||||
output( "\ttestl $2,(%%ecx)\n" ); /* frame->syscall_flags & 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,0x38(%%ecx)\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "2:\ttestl $4,(%%ecx)\n" ); /* frame->syscall_flags & SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\tfxsave 0x40(%%ecx)\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
|
@ -1497,10 +1491,10 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\trep; movsl\n" );
|
||||
output( "\tcall *(%%eax,%%edx,4)\n" );
|
||||
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( "5:\tmovl 0(%%esp),%%ecx\n" ); /* frame->syscall_flags + (frame->restore_flags << 16) */
|
||||
output( "\ttestl $0x68 << 16,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\ttestl $3,0x38(%%esp)\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\ttestl $3,%%ecx\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovl %%eax,%%esi\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
|
@ -1508,7 +1502,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,0x38(%%esp)\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "1:\ttestl $4,%%ecx\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tfxrstor 0x40(%%esp)\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
|
@ -1517,13 +1511,13 @@ static void output_syscall_dispatcher(void)
|
|||
output( "3:\tmovl 0x2c(%%esp),%%edi\n" );
|
||||
output( "\tmovl 0x30(%%esp),%%esi\n" );
|
||||
output( "\tmovl 0x34(%%esp),%%ebp\n" );
|
||||
output( "\ttestl $0x7,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */
|
||||
output( "\ttestl $0x7 << 16,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */
|
||||
output( "\tjnz 1f\n" );
|
||||
output( "\tmovl 0x20(%%esp),%%ebx\n" );
|
||||
output( "\tmovl 0x08(%%esp),%%ecx\n" ); /* frame->eip */
|
||||
output( "\tmovl 0x0c(%%esp),%%esp\n" ); /* frame->esp */
|
||||
output( "\tjmpl *%%ecx\n" );
|
||||
output( "1:\ttestl $0x2,%%ecx\n" ); /* CONTEXT_INTEGER */
|
||||
output( "1:\ttestl $0x2 << 16,%%ecx\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovl 0x1c(%%esp),%%eax\n" );
|
||||
output( "\tmovl 0x24(%%esp),%%ecx\n" );
|
||||
|
@ -1576,7 +1570,7 @@ static void output_syscall_dispatcher(void)
|
|||
/* Legends of Runeterra hooks the first system call return instruction, and
|
||||
* depends on us returning to it. Adjust the return address accordingly. */
|
||||
output( "\tsubq $0xb,0x70(%%rcx)\n" );
|
||||
output( "\tmovl 0xa8(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\tmovl 0xb0(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
|
@ -1619,7 +1613,7 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\tmovl %%eax,%%ebx\n" );
|
||||
output( "\tshrl $8,%%ebx\n" );
|
||||
output( "\tandl $0x30,%%ebx\n" ); /* syscall table number */
|
||||
output( "\tleaq %s(%%rip),%%rcx\n", asm_name("KeServiceDescriptorTable") );
|
||||
output( "\tmovq 0xa8(%%rcx),%%rcx\n" ); /* frame->syscall_table */
|
||||
output( "\tleaq (%%rcx,%%rbx,2),%%rbx\n" );
|
||||
output( "\tandl $0xfff,%%eax\n" ); /* syscall number */
|
||||
output( "\tcmpq 16(%%rbx),%%rax\n" ); /* table->ServiceLimit */
|
||||
|
@ -1685,7 +1679,7 @@ static void output_syscall_dispatcher(void)
|
|||
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 0xa8(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\tmovl 0xb0(%%rcx),%%r14d\n" ); /* frame->syscall_flags */
|
||||
output( "\tmovq %%rdx,%%rax\n" );
|
||||
output( "\tjmp 2b\n" );
|
||||
break;
|
||||
|
@ -1705,14 +1699,13 @@ static void output_syscall_dispatcher(void)
|
|||
{
|
||||
output( "\tvmrs r0, fpscr\n" );
|
||||
output( "\tstr r0, [r1, #0x48]\n" );
|
||||
output( "\tadd r0, r1, #0x50\n" );
|
||||
output( "\tadd r0, r1, #0x60\n" );
|
||||
output( "\tvstm r0, {d0-d15}\n" );
|
||||
}
|
||||
output( "\tmov r6, sp\n" );
|
||||
output( "\tmov sp, r1\n" );
|
||||
output( "\tmov r8, r1\n" );
|
||||
output( "\tldr r5, 6f\n");
|
||||
if (UsePIC) output( "1:\tadd r5, pc\n");
|
||||
output( "\tldr r5, [r1, #0x50]\n"); /* frame->syscall_table */
|
||||
output( "\tubfx r4, ip, #12, #2\n" ); /* syscall table number */
|
||||
output( "\tbfc ip, #12, #20\n" ); /* syscall number */
|
||||
output( "\tadd r4, r5, r4, lsl #4\n" );
|
||||
|
@ -1742,7 +1735,7 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\tbeq 3f\n" );
|
||||
output( "\tldr r4, [r8, #0x48]\n" );
|
||||
output( "\tvmsr fpscr, r4\n" );
|
||||
output( "\tadd r4, r8, #0x50\n" );
|
||||
output( "\tadd r4, r8, #0x60\n" );
|
||||
output( "\tvldm r4, {d0-d15}\n" );
|
||||
output( "3:\n" );
|
||||
}
|
||||
|
@ -1760,10 +1753,6 @@ static void output_syscall_dispatcher(void)
|
|||
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
|
||||
output( "6:\t.long %s\n", asm_name("KeServiceDescriptorTable") );
|
||||
break;
|
||||
case CPU_ARM64:
|
||||
/* FIXME: use x18 directly instead */
|
||||
|
@ -1794,30 +1783,29 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\tmrs x9, NZCV\n" );
|
||||
output( "\tstp x30, x9, [x10, #0x100]\n" );
|
||||
output( "\tmrs x9, FPCR\n" );
|
||||
output( "\tstr w9, [x10, #0x118]\n" );
|
||||
output( "\tstr w9, [x10, #0x128]\n" );
|
||||
output( "\tmrs x9, FPSR\n" );
|
||||
output( "\tstr w9, [x10, #0x11c]\n" );
|
||||
output( "\tstp q0, q1, [x10, #0x120]\n" );
|
||||
output( "\tstp q2, q3, [x10, #0x140]\n" );
|
||||
output( "\tstp q4, q5, [x10, #0x160]\n" );
|
||||
output( "\tstp q6, q7, [x10, #0x180]\n" );
|
||||
output( "\tstp q8, q9, [x10, #0x1a0]\n" );
|
||||
output( "\tstp q10, q11, [x10, #0x1c0]\n" );
|
||||
output( "\tstp q12, q13, [x10, #0x1e0]\n" );
|
||||
output( "\tstp q14, q15, [x10, #0x200]\n" );
|
||||
output( "\tstp q16, q17, [x10, #0x220]\n" );
|
||||
output( "\tstp q18, q19, [x10, #0x240]\n" );
|
||||
output( "\tstp q20, q21, [x10, #0x260]\n" );
|
||||
output( "\tstp q22, q23, [x10, #0x280]\n" );
|
||||
output( "\tstp q24, q25, [x10, #0x2a0]\n" );
|
||||
output( "\tstp q26, q27, [x10, #0x2c0]\n" );
|
||||
output( "\tstp q28, q29, [x10, #0x2e0]\n" );
|
||||
output( "\tstp q30, q31, [x10, #0x300]\n" );
|
||||
output( "\tstr w9, [x10, #0x12c]\n" );
|
||||
output( "\tstp q0, q1, [x10, #0x130]\n" );
|
||||
output( "\tstp q2, q3, [x10, #0x150]\n" );
|
||||
output( "\tstp q4, q5, [x10, #0x170]\n" );
|
||||
output( "\tstp q6, q7, [x10, #0x190]\n" );
|
||||
output( "\tstp q8, q9, [x10, #0x1b0]\n" );
|
||||
output( "\tstp q10, q11, [x10, #0x1d0]\n" );
|
||||
output( "\tstp q12, q13, [x10, #0x1f0]\n" );
|
||||
output( "\tstp q14, q15, [x10, #0x210]\n" );
|
||||
output( "\tstp q16, q17, [x10, #0x230]\n" );
|
||||
output( "\tstp q18, q19, [x10, #0x250]\n" );
|
||||
output( "\tstp q20, q21, [x10, #0x270]\n" );
|
||||
output( "\tstp q22, q23, [x10, #0x290]\n" );
|
||||
output( "\tstp q24, q25, [x10, #0x2b0]\n" );
|
||||
output( "\tstp q26, q27, [x10, #0x2d0]\n" );
|
||||
output( "\tstp q28, q29, [x10, #0x2f0]\n" );
|
||||
output( "\tstp q30, q31, [x10, #0x310]\n" );
|
||||
output( "\tmov sp, x10\n" );
|
||||
output( "\tand x20, x8, #0xfff\n" ); /* syscall number */
|
||||
output( "\tubfx x21, x8, #12, #2\n" ); /* syscall table number */
|
||||
output( "\tadrp x16, %s\n", arm64_page(asm_name("KeServiceDescriptorTable")) );
|
||||
output( "\tadd x16, x16, #%s\n", arm64_pageoff(asm_name("KeServiceDescriptorTable")) );
|
||||
output( "\tldr x16, [x10, #0x118]\n" );/* frame->syscall_table */
|
||||
output( "\tadd x21, x16, x21, lsl #5\n" );
|
||||
output( "\tldr x16, [x21, #16]\n" ); /* table->ServiceLimit */
|
||||
output( "\tcmp x20, x16\n" );
|
||||
|
@ -1846,25 +1834,25 @@ static void output_syscall_dispatcher(void)
|
|||
output( "\tldp x28, x29, [sp, #0xe0]\n" );
|
||||
output( "\tldr w16, [sp, #0x10c]\n" ); /* frame->restore_flags */
|
||||
output( "\ttbz x16, #2, 1f\n" ); /* CONTEXT_FLOATING_POINT */
|
||||
output( "\tldp q0, q1, [sp, #0x120]\n" );
|
||||
output( "\tldp q2, q3, [sp, #0x140]\n" );
|
||||
output( "\tldp q4, q5, [sp, #0x160]\n" );
|
||||
output( "\tldp q6, q7, [sp, #0x180]\n" );
|
||||
output( "\tldp q8, q9, [sp, #0x1a0]\n" );
|
||||
output( "\tldp q10, q11, [sp, #0x1c0]\n" );
|
||||
output( "\tldp q12, q13, [sp, #0x1e0]\n" );
|
||||
output( "\tldp q14, q15, [sp, #0x200]\n" );
|
||||
output( "\tldp q16, q17, [sp, #0x220]\n" );
|
||||
output( "\tldp q18, q19, [sp, #0x240]\n" );
|
||||
output( "\tldp q20, q21, [sp, #0x260]\n" );
|
||||
output( "\tldp q22, q23, [sp, #0x280]\n" );
|
||||
output( "\tldp q24, q25, [sp, #0x2a0]\n" );
|
||||
output( "\tldp q26, q27, [sp, #0x2c0]\n" );
|
||||
output( "\tldp q28, q29, [sp, #0x2e0]\n" );
|
||||
output( "\tldp q30, q31, [sp, #0x300]\n" );
|
||||
output( "\tldr w9, [sp, #0x118]\n" );
|
||||
output( "\tldp q0, q1, [sp, #0x130]\n" );
|
||||
output( "\tldp q2, q3, [sp, #0x150]\n" );
|
||||
output( "\tldp q4, q5, [sp, #0x170]\n" );
|
||||
output( "\tldp q6, q7, [sp, #0x190]\n" );
|
||||
output( "\tldp q8, q9, [sp, #0x1b0]\n" );
|
||||
output( "\tldp q10, q11, [sp, #0x1d0]\n" );
|
||||
output( "\tldp q12, q13, [sp, #0x1f0]\n" );
|
||||
output( "\tldp q14, q15, [sp, #0x210]\n" );
|
||||
output( "\tldp q16, q17, [sp, #0x230]\n" );
|
||||
output( "\tldp q18, q19, [sp, #0x250]\n" );
|
||||
output( "\tldp q20, q21, [sp, #0x270]\n" );
|
||||
output( "\tldp q22, q23, [sp, #0x290]\n" );
|
||||
output( "\tldp q24, q25, [sp, #0x2b0]\n" );
|
||||
output( "\tldp q26, q27, [sp, #0x2d0]\n" );
|
||||
output( "\tldp q28, q29, [sp, #0x2f0]\n" );
|
||||
output( "\tldp q30, q31, [sp, #0x310]\n" );
|
||||
output( "\tldr w9, [sp, #0x128]\n" );
|
||||
output( "\tmsr FPCR, x9\n" );
|
||||
output( "\tldr w9, [sp, #0x11c]\n" );
|
||||
output( "\tldr w9, [sp, #0x12c]\n" );
|
||||
output( "\tmsr FPSR, x9\n" );
|
||||
output( "1:\ttbz x16, #1, 1f\n" ); /* CONTEXT_INTEGER */
|
||||
output( "\tldp x0, x1, [sp, #0x00]\n" );
|
||||
|
@ -1921,11 +1909,8 @@ void output_syscalls( DLLSPEC *spec )
|
|||
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
|
||||
output( "%s\n", asm_globl("KeServiceDescriptorTable") );
|
||||
output( "%s\n", asm_globl("__wine_syscall_table") );
|
||||
output( "\t%s .Lsyscall_table, 0, %u, .Lsyscall_args\n", get_asm_ptr_keyword(), count );
|
||||
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
|
||||
output( "\t%s 0, 0, 0, 0\n", get_asm_ptr_keyword() );
|
||||
output( ".Lsyscall_table:\n" );
|
||||
for (i = 0; i < count; i++)
|
||||
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( syscalls[i] )));
|
||||
|
|
Loading…
Reference in a new issue