winebuild-Fake_Dlls: Fix __wine_syscall_dispatcher to return to the ntdll syscall thunk on i386.

Based on a patch by Andrew Wesie.

League of Legends hooks the RET instruction in some cases, so we need to
return to that frame.

Fixes https://bugs.winehq.org/show_bug.cgi?id=45573
This commit is contained in:
Zebediah Figura 2018-08-08 23:54:55 -05:00
parent f45bfd8af7
commit eb5196c132
2 changed files with 88 additions and 64 deletions

View File

@ -1,26 +1,26 @@
From d90e665acff3eb52f000d00fc846f8be6be3a751 Mon Sep 17 00:00:00 2001
From 90f3317910fccc6cf7fc8126fa5d3ff8616df9de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 11 May 2017 05:32:55 +0200
Subject: winebuild: Generate syscall thunks for ntdll exports.
Based on a patch by Erich E. Hoover.
---
dlls/ntdll/signal_i386.c | 6 +++-
dlls/ntdll/tests/exception.c | 2 ++
dlls/ntdll/signal_i386.c | 6 ++-
dlls/ntdll/tests/exception.c | 2 +
include/winternl.h | 2 +-
tools/winebuild/build.h | 6 ++++
tools/winebuild/import.c | 10 ++++---
tools/winebuild/parser.c | 59 ++++++++++++++++++++++++++++++++++++++
tools/winebuild/spec16.c | 22 +-------------
tools/winebuild/spec32.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
tools/winebuild/utils.c | 21 ++++++++++++++
9 files changed, 169 insertions(+), 27 deletions(-)
tools/winebuild/build.h | 6 +++
tools/winebuild/import.c | 10 +++--
tools/winebuild/parser.c | 59 +++++++++++++++++++++++++++
tools/winebuild/spec16.c | 22 +----------
tools/winebuild/spec32.c | 94 ++++++++++++++++++++++++++++++++++++++++++++
tools/winebuild/utils.c | 21 ++++++++++
9 files changed, 195 insertions(+), 27 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 09a37f242f1..6a37bd68228 100644
index 0ad5e1a..9acf8ec 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -480,6 +480,9 @@ static wine_signal_handler handlers[256];
@@ -429,6 +429,9 @@ static wine_signal_handler handlers[256];
static BOOL fpux_support; /* whether the CPU supports extended fpu context */
@ -30,7 +30,7 @@ index 09a37f242f1..6a37bd68228 100644
enum i386_trap_code
{
TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */
@@ -1553,7 +1556,7 @@ NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi,
@@ -1404,7 +1407,7 @@ NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi,
{
context->Ebp = ebp;
context->Esp = (DWORD)&retaddr;
@ -39,7 +39,7 @@ index 09a37f242f1..6a37bd68228 100644
context->SegCs = wine_get_cs();
context->SegSs = wine_get_ss();
context->EFlags = eflags;
@@ -2488,6 +2491,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
@@ -2290,6 +2293,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
*teb = addr;
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
@ -48,10 +48,10 @@ index 09a37f242f1..6a37bd68228 100644
if (!(thread_data->fs = wine_ldt_alloc_fs()))
{
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 7cb704c2644..ac57f8de667 100644
index 5998f54..5925aee 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -1569,6 +1569,8 @@ static void test_thread_context(void)
@@ -1612,6 +1612,8 @@ static void test_thread_context(void)
ok( (char *)context.Eip >= (char *)pNtGetContextThread - 0x10000 &&
(char *)context.Eip <= (char *)pNtGetContextThread + 0x10000,
"wrong Eip %08x/%08x\n", context.Eip, (DWORD)pNtGetContextThread );
@ -61,10 +61,10 @@ index 7cb704c2644..ac57f8de667 100644
ok( context.SegCs == LOWORD(expect.SegCs), "wrong SegCs %08x/%08x\n", context.SegCs, expect.SegCs );
ok( context.SegDs == LOWORD(expect.SegDs), "wrong SegDs %08x/%08x\n", context.SegDs, expect.SegDs );
diff --git a/include/winternl.h b/include/winternl.h
index 52087b1bd85..5e38f853b76 100644
index f4dd7ca..9cb9a77 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -322,7 +322,7 @@ typedef struct _TEB
@@ -357,7 +357,7 @@ typedef struct _TEB
PVOID CsrClientThread; /* 03c/0070 */
PVOID Win32ThreadInfo; /* 040/0078 */
ULONG Win32ClientInfo[31]; /* 044/0080 used for user32 private data in Wine */
@ -74,10 +74,10 @@ index 52087b1bd85..5e38f853b76 100644
ULONG FpSoftwareStatusRegister; /* 0c8/010c */
PVOID SystemReserved1[54]; /* 0cc/0110 used for krnl386.exe16 private data in Wine */
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index f01ae4f04ff..588fbfb7f05 100644
index 90e8e34..df04ef5 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -102,6 +102,7 @@ typedef struct
@@ -103,6 +103,7 @@ typedef struct
int flags;
char *name; /* public name of this function */
char *link_name; /* name of the C symbol to link to */
@ -85,7 +85,7 @@ index f01ae4f04ff..588fbfb7f05 100644
char *export_name; /* name exported under for noname exports */
union
{
@@ -128,6 +129,7 @@ typedef struct
@@ -129,6 +130,7 @@ typedef struct
int alloc_entry_points; /* number of allocated entry points */
int nb_names; /* number of entry points with names */
unsigned int nb_resources; /* number of resources */
@ -93,7 +93,7 @@ index f01ae4f04ff..588fbfb7f05 100644
int characteristics; /* characteristics for the PE header */
int dll_characteristics;/* DLL characteristics for the PE header */
int subsystem; /* subsystem id */
@@ -137,6 +139,7 @@ typedef struct
@@ -138,6 +140,7 @@ typedef struct
ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
@ -101,7 +101,7 @@ index f01ae4f04ff..588fbfb7f05 100644
} DLLSPEC;
enum target_cpu
@@ -176,6 +179,7 @@ struct strarray
@@ -177,6 +180,7 @@ struct strarray
#define FLAG_FORWARD 0x100 /* function is a forwarded name */
#define FLAG_EXT_LINK 0x200 /* function links to an external symbol */
#define FLAG_EXPORT32 0x400 /* 32-bit export in 16-bit spec file */
@ -109,7 +109,7 @@ index f01ae4f04ff..588fbfb7f05 100644
#define FLAG_CPU(cpu) (0x01000 << (cpu))
#define FLAG_CPU_MASK (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0))
@@ -312,6 +316,8 @@ extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
@@ -313,6 +317,8 @@ extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec );
@ -119,7 +119,7 @@ index f01ae4f04ff..588fbfb7f05 100644
extern int byte_swapped;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index e7bad72c37b..cc8c422a33c 100644
index 5e5866c..ad970c1 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -451,6 +451,7 @@ static void check_undefined_forwards( DLLSPEC *spec )
@ -159,7 +159,7 @@ index e7bad72c37b..cc8c422a33c 100644
}
}
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index ad996547a5b..c4b9abfc9fc 100644
index ad99654..c4b9abf 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -519,6 +519,24 @@ static const char *parse_spec_flags( DLLSPEC *spec, ORDDEF *odp )
@ -250,7 +250,7 @@ index ad996547a5b..c4b9abfc9fc 100644
}
diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c
index 85bcf099999..54aad5d95b4 100644
index 85bcf09..54aad5d 100644
--- a/tools/winebuild/spec16.c
+++ b/tools/winebuild/spec16.c
@@ -494,27 +494,6 @@ static int relay_type_compare( const void *e1, const void *e2 )
@ -290,10 +290,10 @@ index 85bcf099999..54aad5d95b4 100644
entry_point->u.func.nb_args = 0;
assert( !spec->ordinals[0] );
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 4a01238e0fb..e4bc1c603b2 100644
index 3552eca..d851537 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -299,6 +299,73 @@ static void output_relay_debug( DLLSPEC *spec )
@@ -342,6 +342,99 @@ static void output_relay_debug( DLLSPEC *spec )
}
/*******************************************************************
@ -344,21 +344,47 @@ index 4a01238e0fb..e4bc1c603b2 100644
+ output ("\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->impl_name) );
+ }
+
+ output( "\n/* syscall argument stack size table */\n\n" );
+ output( "\t.data\n" );
+ output( "%s\n", asm_globl("__wine_syscall_stack_size") );
+ for (i = 0; i < spec->nb_syscalls; i++)
+ {
+ ORDDEF *odp = spec->syscalls[i];
+ output( "\t.byte %d\n", get_args_size(odp) );
+ }
+
+ output( "\n/* syscall dispatcher */\n\n" );
+ output( "\t.text\n" );
+ output( "\t.align %d\n", get_alignment(16) );
+ output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") );
+ output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
+ output_cfi( ".cfi_startproc" );
+ output( "\tadd $4, %%esp\n" );
+ output( "\tpushl %%ebp\n" );
+ output( "\tmovl %%esp,%%ebp\n" );
+ output( "\tpushl %%esi\n" );
+ output( "\tpushl %%edi\n" );
+ output( "\tmovl %%edx,%%esi\n" );
+ if (UsePIC)
+ {
+ output( "\tcall 1f\n" );
+ output( "1:\tpopl %%ecx\n" );
+ output( "\tjmpl *(%s-1b)(%%ecx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ output( "1:\tpopl %%edx\n" );
+ output( "movzbl (%s-1b)(%%edx,%%eax,1),%%ecx\n", asm_name("__wine_syscall_stack_size") );
+ }
+ else output( "\tjmpl *%s(,%%eax,4)\n", asm_name("__wine_syscall_table") );
+ output( "\tret\n" );
+ else
+ output( "movzbl %s(%%eax),%%ecx\n", asm_name("__wine_syscall_stack_size") );
+
+ output( "\tsubl %%ecx,%%esp\n" );
+ output( "\tmovl %%esp,%%edi\n" );
+ output( "\tshrl $2,%%ecx\n" );
+ output( "\trep; movsl\n" );
+ if (UsePIC)
+ output( "\tcall *(%s-1b)(%%edx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ else
+ output( "\tcall *%s(,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ output( "\tpop %%edi\n" );
+ output( "\tpop %%esi\n" );
+ output( "\tleave\n" );
+ output( "\tjmp *(%%esp)\n" );
+ output_cfi( ".cfi_endproc" );
+ output_function_size( "__wine_syscall_dispatcher" );
+}
@ -367,7 +393,7 @@ index 4a01238e0fb..e4bc1c603b2 100644
* output_exports
*
* Output the export table for a Win32 module.
@@ -648,6 +715,7 @@ void BuildSpec32File( DLLSPEC *spec )
@@ -691,6 +784,7 @@ void BuildSpec32File( DLLSPEC *spec )
resolve_imports( spec );
output_standard_file_header();
output_module( spec );
@ -376,7 +402,7 @@ index 4a01238e0fb..e4bc1c603b2 100644
output_exports( spec );
output_imports( spec );
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 6e01f1a5268..925054b8bb7 100644
index 6e01f1a..925054b 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -792,6 +792,7 @@ void free_dll_spec( DLLSPEC *spec )
@ -419,5 +445,5 @@ index 6e01f1a5268..925054b8bb7 100644
+ return j + 1;
+}
--
2.13.1
2.7.4

View File

@ -1,4 +1,4 @@
From 5f1d9ae2d65ad4567ea75d1a73b28b197e237e9b Mon Sep 17 00:00:00 2001
From ef61dd7d4ec04dba8d5fd2fbd67eb605088ebfa9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 7 Sep 2017 00:38:09 +0200
Subject: [PATCH] tools/winebuild: Add syscall thunks for 64 bit.
@ -9,8 +9,8 @@ Subject: [PATCH] tools/winebuild: Add syscall thunks for 64 bit.
dlls/ntdll/thread.c | 7 +-
libs/wine/loader.c | 4 +
tools/winebuild/parser.c | 2 +-
tools/winebuild/spec32.c | 211 +++++++++++++++++++++++++++++++++++++++++--
6 files changed, 224 insertions(+), 10 deletions(-)
tools/winebuild/spec32.c | 209 +++++++++++++++++++++++++++++++++++++++++--
6 files changed, 223 insertions(+), 9 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index c9af524..1ddd0f4 100644
@ -40,7 +40,7 @@ index c9af524..1ddd0f4 100644
todo_wine ok(0, "%s: Export is a stub-function, skipping\n", func_name);
continue;
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 8ba09fe..bf21b42 100644
index 2bd3f6e..3818f65 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -328,6 +328,8 @@ static inline struct amd64_thread_data *amd64_thread_data(void)
@ -61,7 +61,7 @@ index 8ba09fe..bf21b42 100644
return status;
}
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index f807b53..40304db 100644
index 24369fd..54f98a2 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -60,6 +60,8 @@ struct _KUSER_SHARED_DATA *user_shared_data_external;
@ -122,7 +122,7 @@ index c4b9abf..064019c 100644
if (odp->flags & (FLAG_FORWARD | FLAG_REGISTER))
return 0;
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 430c7a5..48a9abe 100644
index d2fd6a6..403aad5 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -342,11 +342,11 @@ static void output_relay_debug( DLLSPEC *spec )
@ -139,18 +139,10 @@ index 430c7a5..48a9abe 100644
{
const unsigned int page_size = get_page_size();
int i;
@@ -412,7 +412,91 @@ static void output_syscall_thunks( DLLSPEC *spec )
output( "1:\tpopl %%ecx\n" );
output( "\tjmpl *(%s-1b)(%%ecx,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
}
- else output( "\tjmpl *%s(,%%eax,4)\n", asm_name("__wine_syscall_table") );
+ else output( "\tjmpl *%s(,%%eax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ output( "\tret\n" );
+ output_cfi( ".cfi_endproc" );
+ output_function_size( "__wine_syscall_dispatcher" );
+}
+
+/*******************************************************************
@@ -445,6 +445,90 @@ static void output_syscall_thunks( DLLSPEC *spec )
}
/*******************************************************************
+ * output_syscall_thunks_x64
+ *
+ * Output entry points for system call functions
@ -229,10 +221,16 @@ index 430c7a5..48a9abe 100644
+ output( "1:\tjmpq *(%s-1b)(%%r10,%%rax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
+ }
+ else output( "\tjmpq *%s(,%%rax,%d)\n", asm_name("__wine_syscall_table"), get_ptr_size() );
output( "\tret\n" );
output_cfi( ".cfi_endproc" );
output_function_size( "__wine_syscall_dispatcher" );
@@ -775,7 +859,10 @@ void BuildSpec32File( DLLSPEC *spec )
+ output( "\tret\n" );
+ output_cfi( ".cfi_endproc" );
+ output_function_size( "__wine_syscall_dispatcher" );
+}
+
+/*******************************************************************
* output_exports
*
* Output the export table for a Win32 module.
@@ -801,7 +885,10 @@ void BuildSpec32File( DLLSPEC *spec )
resolve_imports( spec );
output_standard_file_header();
output_module( spec );
@ -244,7 +242,7 @@ index 430c7a5..48a9abe 100644
output_stubs( spec );
output_exports( spec );
output_imports( spec );
@@ -787,7 +874,7 @@ void BuildSpec32File( DLLSPEC *spec )
@@ -813,7 +900,7 @@ void BuildSpec32File( DLLSPEC *spec )
static int needs_stub_exports( DLLSPEC *spec )
{
@ -253,7 +251,7 @@ index 430c7a5..48a9abe 100644
return 0;
if (!(spec->characteristics & IMAGE_FILE_DLL))
return 0;
@@ -797,7 +884,7 @@ static int needs_stub_exports( DLLSPEC *spec )
@@ -823,7 +910,7 @@ static int needs_stub_exports( DLLSPEC *spec )
}
@ -262,7 +260,7 @@ index 430c7a5..48a9abe 100644
{
int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
size_t rva, thunk;
@@ -959,6 +1046,113 @@ static void create_stub_exports_text( DLLSPEC *spec )
@@ -985,6 +1072,113 @@ static void create_stub_exports_text( DLLSPEC *spec )
}
@ -376,7 +374,7 @@ index 430c7a5..48a9abe 100644
static void create_stub_exports_data( DLLSPEC *spec )
{
int i;
@@ -1158,7 +1352,10 @@ static void output_fake_module_pass( DLLSPEC *spec )
@@ -1184,7 +1378,10 @@ static void output_fake_module_pass( DLLSPEC *spec )
if (needs_stub_exports( spec ))
{
put_label( "text_start" );
@ -389,5 +387,5 @@ index 430c7a5..48a9abe 100644
}
else
--
1.9.1
2.7.4