From c872a68cf0329f84ae39d6ac7f0cc64878698cc4 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 2 Nov 2015 12:50:36 +0100 Subject: [PATCH 1/3] winebuild: Added support for syscall wrapper thunks. To: wine-patches Signed-off-by: Jacek Caban --- dlls/ntdll/thread.c | 25 ++++++++++++++++++++-- tools/winebuild/build.h | 1 + tools/winebuild/parser.c | 1 + tools/winebuild/spec32.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index aaf7a71..88b5fbe 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -202,6 +202,25 @@ static ULONG64 get_dyld_image_info_addr(void) } #endif /* __APPLE__ */ +extern char *__wine_spec_nt_header; + +#include "pshpack1.h" +static struct { + BYTE add_esp[3]; + BYTE add_eax; + DWORD module_base; + BYTE mov_eax_eax[2]; + BYTE jmp_eax[2]; + WORD ret; +} thunk = { + {0x83,0xc4,0x04}, /* addl $4,%esp */ + 0x05, 0, /* addl __wine_spec_nt_header,%eax */ + {0x8b,0x00}, /* movl 0(%eax),%eax */ + {0xff,0xe0}, /* jmp *%eax */ + 0xc3 /* ret */ +}; +#include "poppack.h" + /*********************************************************************** * thread_init * @@ -230,7 +249,7 @@ HANDLE thread_init(void) addr = (void *)0x7ffe0000; size = 0x10000; status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, - MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); + MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (status) { MESSAGE( "wine: failed to map the shared user data: %08x\n", status ); @@ -238,8 +257,10 @@ HANDLE thread_init(void) } user_shared_data = addr; - /* allocate and initialize the PEB */ + thunk.module_base = (DWORD)&__wine_spec_nt_header; + memcpy(&user_shared_data->SystemCall, &thunk, sizeof(thunk)); + /* allocate and initialize the PEB */ addr = NULL; size = sizeof(*peb); NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 1, &size, diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 4a71eed..e67896c 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -171,6 +171,7 @@ struct strarray #define FLAG_REGISTER 0x10 /* use register calling convention */ #define FLAG_PRIVATE 0x20 /* function is private (cannot be imported) */ #define FLAG_ORDINAL 0x40 /* function should be imported by ordinal */ +#define FLAG_SYSCALL 0x80 /* function implements NT syscall */ #define FLAG_FORWARD 0x100 /* function is a forwarded name */ #define FLAG_EXT_LINK 0x200 /* function links to an external symbol */ diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 1d7b84e..021356f 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -69,6 +69,7 @@ static const char * const FlagNames[] = "register", /* FLAG_REGISTER */ "private", /* FLAG_PRIVATE */ "ordinal", /* FLAG_ORDINAL */ + "syscall", /* FLAG_SYSCALL */ NULL }; diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index cb56abe..d375706 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -270,6 +270,55 @@ static void output_relay_debug( DLLSPEC *spec ) } } +static void output_syscall_wrappers( DLLSPEC *spec ) +{ + int i, emited_syscalls = 0, syscall_cnt = 0; + char **syscall_entries, *sym_name; + ORDDEF *odp; + + for (odp = spec->entry_points; odp < spec->entry_points + spec->nb_entry_points; odp++) + if(odp->flags & FLAG_SYSCALL) + syscall_cnt++; + + if(!syscall_cnt) + return; + + syscall_entries = xmalloc(syscall_cnt*sizeof(*syscall_entries)); + + output("\t.text\n"); + + for (odp = spec->entry_points; odp < spec->entry_points + spec->nb_entry_points; odp++) { + if(!(odp->flags & FLAG_SYSCALL)) + continue; + + for(i=0; i < emited_syscalls; i++) { + if(!strcmp(odp->link_name, syscall_entries[i])) + break; + } + if(i < emited_syscalls) + continue; /* already emited */ + + syscall_entries[emited_syscalls] = odp->link_name; + + sym_name = strmake("__syscall_%s", odp->link_name); + output( "%s\n", asm_globl(sym_name) ); + output( "\tmovl $.L__wine_spec_syscalls+%u-.L__wine_spec_rva_base,%%eax\n", emited_syscalls*4); + output( "\tmovl $0x7ffe0300,%%edx\n" ); + output( "\tcall *%%edx\n" ); + output( "\tret $%u\n", get_args_size(odp)); + free(sym_name); + emited_syscalls++; + } + + output( "\n\t.data\n" ); + output( ".L__wine_spec_syscalls:\n" ); + + for (i=0; i < emited_syscalls; i++) + output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(syscall_entries[i]) ); + + free(syscall_entries); +} + /******************************************************************* * output_exports * @@ -332,6 +381,10 @@ void output_exports( DLLSPEC *spec ) output( "\t%s %s_%s\n", get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name ); } + else if (odp->flags & FLAG_SYSCALL) + { + output( "\t%s %s_%s\n", get_asm_ptr_keyword(), asm_name("__syscall"), odp->link_name ); + } else { output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) ); @@ -622,6 +675,7 @@ void BuildSpec32File( DLLSPEC *spec ) output_stubs( spec ); output_exports( spec ); output_imports( spec ); + output_syscall_wrappers( spec ); if (is_undefined( "__wine_call_from_regs" )) output_asm_relays(); output_resources( spec ); output_gnu_stack_note(); -- 2.4.9