ntdll: Store the syscall argument table on the PE side.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-08-30 12:27:08 +02:00
parent d017c704f0
commit 7ae1c396ac
2 changed files with 22 additions and 6 deletions

View File

@ -118,6 +118,8 @@ static void *p__wine_syscall_dispatcher;
extern SYSTEM_SERVICE_TABLE __wine_syscall_table DECLSPEC_HIDDEN; extern SYSTEM_SERVICE_TABLE __wine_syscall_table DECLSPEC_HIDDEN;
static BYTE syscall_args[4096];
SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4]; SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4];
@ -1148,8 +1150,21 @@ static NTSTATUS CDECL init_unix_lib( void *module, DWORD reason, const void *ptr
*/ */
NTSTATUS ntdll_init_syscalls( ULONG id, SYSTEM_SERVICE_TABLE *table, void **dispatcher ) NTSTATUS ntdll_init_syscalls( ULONG id, SYSTEM_SERVICE_TABLE *table, void **dispatcher )
{ {
struct syscall_info
{
void *dispatcher;
USHORT limit;
BYTE args[1];
} *info = (struct syscall_info *)dispatcher;
if (id > 3) return STATUS_INVALID_PARAMETER; if (id > 3) return STATUS_INVALID_PARAMETER;
*dispatcher = __wine_syscall_dispatcher; if (info->limit != table->ServiceLimit)
{
ERR( "syscall count mismatch %u / %lu\n", info->limit, table->ServiceLimit );
NtTerminateProcess( GetCurrentProcess(), STATUS_INVALID_PARAMETER );
}
info->dispatcher = __wine_syscall_dispatcher;
memcpy( table->ArgumentTable, info->args, table->ServiceLimit );
KeServiceDescriptorTable[id] = *table; KeServiceDescriptorTable[id] = *table;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1932,6 +1947,7 @@ static struct unix_funcs unix_funcs =
*/ */
static void start_main_thread(void) static void start_main_thread(void)
{ {
SYSTEM_SERVICE_TABLE syscall_table = __wine_syscall_table;
NTSTATUS status; NTSTATUS status;
TEB *teb = virtual_alloc_first_teb(); TEB *teb = virtual_alloc_first_teb();
@ -1954,7 +1970,8 @@ static void start_main_thread(void)
NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 ); NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
load_ntdll(); load_ntdll();
if (main_image_info.Machine != current_machine) load_wow64_ntdll( main_image_info.Machine ); if (main_image_info.Machine != current_machine) load_wow64_ntdll( main_image_info.Machine );
ntdll_init_syscalls( 0, &__wine_syscall_table, p__wine_syscall_dispatcher ); syscall_table.ArgumentTable = syscall_args;
ntdll_init_syscalls( 0, &syscall_table, p__wine_syscall_dispatcher );
status = p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs ); status = p__wine_set_unix_funcs( NTDLL_UNIXLIB_VERSION, &unix_funcs );
if (status == STATUS_REVISION_MISMATCH) if (status == STATUS_REVISION_MISMATCH)
{ {

View File

@ -1444,13 +1444,10 @@ void output_syscalls( DLLSPEC *spec )
output( "\t.data\n" ); output( "\t.data\n" );
output( "\t.align %d\n", get_alignment( get_ptr_size() ) ); output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
output( "%s\n", asm_globl("__wine_syscall_table") ); 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 .Lsyscall_table, 0, %u, 0\n", get_asm_ptr_keyword(), count );
output( ".Lsyscall_table:\n" ); output( ".Lsyscall_table:\n" );
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( syscalls[i] ))); output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( syscalls[i] )));
output( ".Lsyscall_args:\n" );
for (i = 0; i < count; i++)
output( "\t.byte %u\n", get_args_size( syscalls[i] ));
return; return;
} }
@ -1574,6 +1571,8 @@ void output_syscalls( DLLSPEC *spec )
output( "\t.align %d\n", get_alignment( get_ptr_size() ) ); output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
output( "%s\n", asm_globl("__wine_syscall_dispatcher") ); output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
output( "\t%s 0\n", get_asm_ptr_keyword() ); output( "\t%s 0\n", get_asm_ptr_keyword() );
output( "\t.short %u\n", count );
for (i = 0; i < count; i++) output( "\t.byte %u\n", get_args_size( syscalls[i] ));
} }