steam web browsing on OS X
Jacek Caban
jacek at codeweavers.com
Mon Nov 2 08:43:07 CST 2015
On 11/02/15 13:15, Jacek Caban wrote:
> Hi Sebastian,
>
> On 11/02/15 12:16, Sebastian Lackner wrote:
>> On 02.11.2015 11:12, Jacek Caban wrote:
>>> Sure. The idea is to pass relative addresses instead to
>>> call_syscall_func and let it handle that. Calling call_syscall_func
>>> itself may use a constant address if we let it live in user shared data.
>>> Did you try that? That's one of those things that one has to try to see
>>> if it works in practice.
>> Yes, I also looked at this approach. The difficult part to get this correct
>> is to initialize user shared data as early as possible, without any call to
>> a wrapper function before that. Please note that its not sufficient to wrap
>> calls from other dlls, even some ntdll-internal calls have to go through the
>> wrappers (for example when loading a library). Those are implemented in
>> ntdll usermode on Windows.
>>
>>> Also I believe that using winebuild for that is the right way.
>> I already tried it out in practice and partially disagree. As mentioned above,
>> its not sufficient to put autogenerated wrappers between the implementation
>> and the ntdll exports. Exactly the same wrappers have to be used from inside
>> of the ntdll loader code for example. This means, even if the thunks are
>> generated somewhere else, we still have to add them to one of the wine header
>> files. If we do not want to generate thunks for all architectures, we might
>> even have to add them twice, one time as typedef, and the second time a #define
>> as fallback for unsupported architectures.
>>
>> I'm not saying that its impossible to do it this way, but compared to thiscalls,
>> which could easily be generated by winebuild, a macro is similar good here imho.
>> If you want to look into the idea to autogenerate thunks, here is one of my
>> work-in-progress patches (based on Erichs work): http://ix.io/lLz
> See attached patches. On the quick look it seems similar to the one you
> mentioned, except it avoids text relocations. The patch is definitely
> not finished nor ready for proper review, but it's enough to get things
> to build and run. I haven't even tested that with Chromium nor other
> apps that need it (well, I haven't tested it at all, really).
>
> Patch 1 is the interesting one. Patch 2 just marks needed functions as
> syscalls.
>
> Patch 3 is to show how to address your concerns about going through
> thunks from inside ntdll. Those use macros from your patch except their
> meaning is reverted. I chose two calls that I know will need to be fixed
> for Office. I don't know how much more calls will need to be changed. In
> general, we can't avoid such problems: we will either need to explicitly
> mark calls that need to go through the thunk or those that don't. I
> chose the first variant because it seems cleaner and more in line with
> how winebuild works. I do believe that implementing things to work the
> other way around is also possible in winebuild.
>
> Cheers,
> Jacek
It seems that my mail didn't make it to wine-devel, probably due to
attachment size. I'm resending without patch 2.
Cheers,
Jacek
-------------- next part --------------
From c872a68cf0329f84ae39d6ac7f0cc64878698cc4 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Mon, 2 Nov 2015 12:50:36 +0100
Subject: [PATCH 1/3] winebuild: Added support for syscall wrapper thunks.
To: wine-patches <wine-patches at winehq.org>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
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
-------------- next part --------------
From 6f085b2fbcb13a87e1078c421e4a9f6b2e6d421b Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Mon, 2 Nov 2015 12:58:48 +0100
Subject: [PATCH 3/3] ntdll: Call NtOpenFile via syscall wrapper in loader.
To: wine-patches <wine-patches at winehq.org>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/ntdll/loader.c | 4 ++--
dlls/ntdll/ntdll_misc.h | 11 +++++++++++
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 831f049..e009f0e 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2149,7 +2149,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
attr.ObjectName = &nt_name;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
- if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE )) *handle = 0;
+ if (SYSCALL(NtOpenFile)( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE )) *handle = 0;
goto found;
}
@@ -2184,7 +2184,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
attr.ObjectName = &nt_name;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
- if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE )) *handle = 0;
+ if (SYSCALL(NtOpenFile)( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE )) *handle = 0;
}
found:
RtlFreeUnicodeString( &nt_name );
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index cbd19db..7d5331f 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -260,8 +260,19 @@ extern HANDLE keyed_event DECLSPEC_HIDDEN;
".byte 0x6a," #args "\n\t" /* pushl $args */ \
"call " __ASM_NAME("__wine_call_from_regs") "\n\t" \
"ret $(4*" #args ")" ) /* fake ret to make copy protections happy */
+
+#define SYSCALL( name ) __syscall_ ## name
+#define DECLARE_SYSCALL_ENTRYPOINT( name ) extern typeof( name ) SYSCALL( name )
+
+#else
+
+#define SYSCALL( name ) name
+#define DECLARE_SYSCALL_ENTRYPOINT( name )
+
#endif
+DECLARE_SYSCALL_ENTRYPOINT(NtOpenFile);
+
#define HASH_STRING_ALGORITHM_DEFAULT 0
#define HASH_STRING_ALGORITHM_X65599 1
#define HASH_STRING_ALGORITHM_INVALID 0xffffffff
--
2.4.9
More information about the wine-devel
mailing list