From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/loader.c | 2 ++ dlls/ntdll/unix/signal_i386.c | 18 ++++++++++++++++-- dlls/ntdll/unix/signal_x86_64.c | 13 +++++++++++-- dlls/ntdll/unix/unix_private.h | 1 + tools/winebuild/import.c | 1 + 5 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index ffd0bdf57a1..378410ff760 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1340,6 +1340,7 @@ NTSTATUS ntdll_init_syscalls( ULONG id, SYSTEM_SERVICE_TABLE *table, void **disp { BYTE syscall_args; BYTE syscall_nofpu; + BYTE syscall_unix; }; struct syscall_table_info { @@ -1361,6 +1362,7 @@ NTSTATUS ntdll_init_syscalls( ULONG id, SYSTEM_SERVICE_TABLE *table, void **disp { table->ArgumentTable[i] = table_info->info[i].syscall_args; if (table_info->info[i].syscall_nofpu) table->CounterTable[i] |= SYSCALL_FLAG_NOFPU; + if (table_info->info[i].syscall_unix) table->CounterTable[i] |= SYSCALL_FLAG_UNIX; }
KeServiceDescriptorTable[id] = *table; diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index e599ed1898d..4bf5cc0517b 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1627,7 +1627,7 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "movl %ebp,0x380(%esp)\n\t" "movl 0x1f8(%edx),%ecx\n\t" /* x86_thread_data()->syscall_frame */ "movl (%ecx),%eax\n\t" /* frame->syscall_flags */ - "andl $~0x80000000,%eax\n\t" /* syscall_flags &= ~SYSCALL_FLAG_NOFPU */ + "andl $~0xc0000000,%eax\n\t" /* syscall_flags &= ~(SYSCALL_FLAG_NOFPU | SYSCALL_FLAG_UNIX) */ "movl %eax,(%esp)\n\t" "movl 0x38(%ecx),%eax\n\t" /* frame->syscall_table */ "movl %eax,0x38(%esp)\n\t" @@ -2614,6 +2614,8 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "orl %edx,(%ecx)\n\t" /* frame->syscall_flags |= syscall_flags */ "testl $0x80000000,(%ecx)\n\t" /* frame->syscall_flags & SYSCALL_FLAG_NOFPU */ "jz .L__wine_syscall_dispatcher_save_fpu\n\t" + "testl $0x40000000,(%ecx)\n\t" /* frame->syscall_flags & SYSCALL_FLAG_UNIX */ + "jnz .L__wine_unix_call\n\t" "jmp .L__wine_syscall_dispatcher_fpu_saved\n\t"
"\n.L__wine_syscall_dispatcher_save_fpu:\n\t" @@ -2668,6 +2670,18 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "cld\n\t" "rep; movsl\n\t" "call *(%edx,%eax,4)\n\t" + "jmp .L__wine_syscall_dispatcher_restore\n\t" + + "\n.L__wine_unix_call:\n\t" + "leal 4(%esp),%esi\n\t" /* first argument */ + "movl %ecx,%esp\n\t" + "subl $4,%esp\n\t" + "andl $~15,%esp\n\t" + "movl 0xc(%esi),%eax\n\t" + "movl %eax,(%esp)\n\t" + "movl 0x8(%esi),%eax\n\t" + "movl (%esi),%edx\n\t" + "call *(%edx,%eax,4)\n\t"
"\n.L__wine_syscall_dispatcher_restore:\n\t" "leal -0x34(%ebp),%esp\n\t" @@ -2703,7 +2717,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "fwait\n\t"
"\n.L__wine_syscall_dispatcher_fpu_restored:\n\t" - "andl $~0x80000000,0(%esp)\n\t" /* frame->syscall_flags &= ~SYSCALL_FLAG_NOFPU */ + "andl $~0xc0000000,0(%esp)\n\t" /* frame->syscall_flags &= ~(SYSCALL_FLAG_NOFPU | SYSCALL_FLAG_UNIX) */ "movl 0x2c(%esp),%edi\n\t" __ASM_CFI(".cfi_same_value %edi\n\t") "movl 0x30(%esp),%esi\n\t" diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 6b8def37a7d..c3de1e040b6 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1633,7 +1633,7 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "movq 0xa8(%r10),%rax\n\t" /* prev_frame->syscall_table */ "movq %rax,0xa8(%rsp)\n\t" /* frame->syscall_table */ "movl 0xb0(%r10),%r14d\n\t" /* prev_frame->syscall_flags */ - "andl $~0x80000000,%r14d\n\t" /* syscall_flags &= ~SYSCALL_FLAG_NOFPU */ + "andl $~0xc0000000,%r14d\n\t" /* syscall_flags &= ~(SYSCALL_FLAG_NOFPU | SYSCALL_FLAG_UNIX) */ "movl %r14d,0xb0(%rsp)\n\t" /* frame->syscall_flags */ "movq %r10,0xa0(%rsp)\n\t" /* frame->prev_frame */ "movq %rsp,0x328(%r11)\n\t" /* amd64_thread_data()->syscall_frame */ @@ -2763,6 +2763,8 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "movq %rcx,%rsp\n\t" "movq 0x00(%rcx),%rax\n\t" "movq 0x18(%rcx),%rdx\n\t" + "testl $0x40000000,%r14d\n\t" /* SYSCALL_FLAG_UNIX */ + "jnz .L__wine_unix_call\n\t" "andl $0xfff,%eax\n\t" /* syscall number */ "movq 24(%rbx),%rcx\n\t" /* table->ArgumentTable */ "movzbl (%rcx,%rax),%ecx\n\t" @@ -2779,6 +2781,13 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "subq $0x20,%rsp\n\t" "movq (%rbx),%r10\n\t" /* table->ServiceTable */ "callq *(%r10,%rax,8)\n\t" + "jmp .L__wine_syscall_dispatcher_restore\n" + + "\n.L__wine_unix_call:\n\t" + "movq %r8,%rdi\n\t" + "subq $0x20,%rsp\n\t" + "andq $~15,%rsp\n\t" + "callq *(%r10,%rdx,8)\n\t"
"\n.L__wine_syscall_dispatcher_restore:\n\t" "leaq -0x98(%rbp),%rcx\n\t" @@ -2821,7 +2830,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "fxrstor64 0xc0(%rcx)\n\t"
"\n.L__wine_syscall_dispatcher_fpu_restored:\n\t" - "andl $~0x80000000,0xb0(%rcx)\n\t" /* frame->syscall_flags &= ~SYSCALL_FLAG_NOFPU */ + "andl $~0xc0000000,0xb0(%rcx)\n\t" /* frame->syscall_flags &= ~(SYSCALL_FLAG_NOFPU | SYSCALL_FLAG_UNIX) */ "movq 0x98(%rcx),%rbp\n\t" __ASM_CFI(".cfi_same_value rbp\n\t") "movq 0x68(%rcx),%r15\n\t" diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index c34ce872930..44e63502505 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -97,6 +97,7 @@ static const LONG teb_offset = 0x2000; #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
#define SYSCALL_FLAG_NOFPU 0x80000000 +#define SYSCALL_FLAG_UNIX 0x40000000
/* callbacks to PE ntdll from the Unix side */ extern void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN; diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 905e6262650..ea48b6ea9ff 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1507,6 +1507,7 @@ void output_syscalls( DLLSPEC *spec ) { output( "\t.byte %u\n", get_args_size( syscalls[i] )); /* syscall_args */ output( "\t.byte %u\n", !!(syscalls[i]->flags & FLAG_NOFPU) ); /* syscall_nofpu */ + output( "\t.byte %u\n", !!(strstr( get_link_name( syscalls[i] ), "__wine_unix_call" )) ); /* syscall_unix */ } }