mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 06:06:13 +00:00
wow64cpu: Add a custom 32->64 thunk for Unix calls.
This commit is contained in:
parent
a6bb3662dc
commit
7e680152d4
3 changed files with 92 additions and 9 deletions
|
@ -94,6 +94,7 @@ static void * (WINAPI *pBTCpuGetBopCode)(void);
|
||||||
static void (WINAPI *pBTCpuProcessInit)(void);
|
static void (WINAPI *pBTCpuProcessInit)(void);
|
||||||
static void (WINAPI *pBTCpuSimulate)(void);
|
static void (WINAPI *pBTCpuSimulate)(void);
|
||||||
static NTSTATUS (WINAPI *pBTCpuResetToConsistentState)( EXCEPTION_POINTERS * );
|
static NTSTATUS (WINAPI *pBTCpuResetToConsistentState)( EXCEPTION_POINTERS * );
|
||||||
|
static void * (WINAPI *p__wine_get_unix_opcode)(void);
|
||||||
|
|
||||||
|
|
||||||
void *dummy = RtlUnwind;
|
void *dummy = RtlUnwind;
|
||||||
|
@ -588,6 +589,7 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex
|
||||||
GET_PTR( BTCpuProcessInit );
|
GET_PTR( BTCpuProcessInit );
|
||||||
GET_PTR( BTCpuResetToConsistentState );
|
GET_PTR( BTCpuResetToConsistentState );
|
||||||
GET_PTR( BTCpuSimulate );
|
GET_PTR( BTCpuSimulate );
|
||||||
|
GET_PTR( __wine_get_unix_opcode );
|
||||||
|
|
||||||
module = load_64bit_module( L"wow64win.dll" );
|
module = load_64bit_module( L"wow64win.dll" );
|
||||||
GET_PTR( sdwhwin32 );
|
GET_PTR( sdwhwin32 );
|
||||||
|
@ -598,6 +600,7 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex
|
||||||
init_image_mapping( module );
|
init_image_mapping( module );
|
||||||
init_syscall_table( module, 0, &ntdll_syscall_table );
|
init_syscall_table( module, 0, &ntdll_syscall_table );
|
||||||
*(void **)RtlFindExportedRoutineByName( module, "__wine_syscall_dispatcher" ) = pBTCpuGetBopCode();
|
*(void **)RtlFindExportedRoutineByName( module, "__wine_syscall_dispatcher" ) = pBTCpuGetBopCode();
|
||||||
|
*(void **)RtlFindExportedRoutineByName( module, "__wine_unix_call_dispatcher" ) = p__wine_get_unix_opcode();
|
||||||
|
|
||||||
module = load_32bit_module( L"win32u.dll" );
|
module = load_32bit_module( L"win32u.dll" );
|
||||||
init_syscall_table( module, 1, psdwhwin32 );
|
init_syscall_table( module, 1, psdwhwin32 );
|
||||||
|
|
|
@ -39,6 +39,18 @@ struct thunk_32to64
|
||||||
DWORD addr;
|
DWORD addr;
|
||||||
WORD cs;
|
WORD cs;
|
||||||
};
|
};
|
||||||
|
struct thunk_opcodes
|
||||||
|
{
|
||||||
|
struct thunk_32to64 syscall_thunk;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
BYTE pushl; /* pushl $dispatcher_high */
|
||||||
|
DWORD dispatcher_high;
|
||||||
|
BYTE pushl2; /* pushl $dispatcher_low */
|
||||||
|
DWORD dispatcher_low;
|
||||||
|
struct thunk_32to64 t;
|
||||||
|
} unix_thunk;
|
||||||
|
};
|
||||||
#include "poppack.h"
|
#include "poppack.h"
|
||||||
|
|
||||||
static BYTE DECLSPEC_ALIGN(4096) code_buffer[0x1000];
|
static BYTE DECLSPEC_ALIGN(4096) code_buffer[0x1000];
|
||||||
|
@ -187,7 +199,7 @@ __ASM_GLOBAL_FUNC( syscall_32to64,
|
||||||
"movl 0xa4(%r13),%ebx\n\t" /* context->Ebx */
|
"movl 0xa4(%r13),%ebx\n\t" /* context->Ebx */
|
||||||
"movl 0xb4(%r13),%ebp\n\t" /* context->Ebp */
|
"movl 0xb4(%r13),%ebp\n\t" /* context->Ebp */
|
||||||
"btrl $0,-4(%r13)\n\t" /* cpu->Flags & WOW64_CPURESERVED_FLAG_RESET_STATE */
|
"btrl $0,-4(%r13)\n\t" /* cpu->Flags & WOW64_CPURESERVED_FLAG_RESET_STATE */
|
||||||
"jc 1f\n\t"
|
"jc .Lsyscall_32to64_return\n\t"
|
||||||
"movl 0xb8(%r13),%edx\n\t" /* context->Eip */
|
"movl 0xb8(%r13),%edx\n\t" /* context->Eip */
|
||||||
"movl %edx,(%rsp)\n\t"
|
"movl %edx,(%rsp)\n\t"
|
||||||
"movl 0xbc(%r13),%edx\n\t" /* context->SegCs */
|
"movl 0xbc(%r13),%edx\n\t" /* context->SegCs */
|
||||||
|
@ -195,7 +207,8 @@ __ASM_GLOBAL_FUNC( syscall_32to64,
|
||||||
"movl 0xc4(%r13),%r14d\n\t" /* context->Esp */
|
"movl 0xc4(%r13),%r14d\n\t" /* context->Esp */
|
||||||
"xchgq %r14,%rsp\n\t"
|
"xchgq %r14,%rsp\n\t"
|
||||||
"ljmp *(%r14)\n"
|
"ljmp *(%r14)\n"
|
||||||
"1:\tmovq %rsp,%r14\n\t"
|
".Lsyscall_32to64_return:\n\t"
|
||||||
|
"movq %rsp,%r14\n\t"
|
||||||
"movl 0xa8(%r13),%edx\n\t" /* context->Edx */
|
"movl 0xa8(%r13),%edx\n\t" /* context->Edx */
|
||||||
"movl 0xac(%r13),%ecx\n\t" /* context->Ecx */
|
"movl 0xac(%r13),%ecx\n\t" /* context->Ecx */
|
||||||
"movl 0xc8(%r13),%eax\n\t" /* context->SegSs */
|
"movl 0xc8(%r13),%eax\n\t" /* context->SegSs */
|
||||||
|
@ -215,6 +228,41 @@ __ASM_GLOBAL_FUNC( syscall_32to64,
|
||||||
"iretq" )
|
"iretq" )
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* unix_call_32to64
|
||||||
|
*
|
||||||
|
* Execute a 64-bit Unix call from 32-bit code, then return to 32-bit.
|
||||||
|
*/
|
||||||
|
extern void WINAPI unix_call_32to64(void) DECLSPEC_HIDDEN;
|
||||||
|
__ASM_GLOBAL_FUNC( unix_call_32to64,
|
||||||
|
/* cf. BTCpuSimulate prolog */
|
||||||
|
__ASM_SEH(".seh_stackalloc 0x28\n\t")
|
||||||
|
__ASM_SEH(".seh_endprologue\n\t")
|
||||||
|
__ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
|
||||||
|
"xchgq %r14,%rsp\n\t"
|
||||||
|
"movl %edi,0x9c(%r13)\n\t" /* context->Edi */
|
||||||
|
"movl %esi,0xa0(%r13)\n\t" /* context->Esi */
|
||||||
|
"movl %ebx,0xa4(%r13)\n\t" /* context->Ebx */
|
||||||
|
"movl %ebp,0xb4(%r13)\n\t" /* context->Ebp */
|
||||||
|
"movl 8(%r14),%edx\n\t"
|
||||||
|
"movl %edx,0xb8(%r13)\n\t" /* context->Eip */
|
||||||
|
"leaq 28(%r14),%rdx\n\t"
|
||||||
|
"movl %edx,0xc4(%r13)\n\t" /* context->Esp */
|
||||||
|
"movq 12(%r14),%rcx\n\t" /* handle */
|
||||||
|
"movl 20(%r14),%edx\n\t" /* code */
|
||||||
|
"movl 24(%r14),%r8d\n\t" /* args */
|
||||||
|
"callq *(%r14)\n\t"
|
||||||
|
"btrl $0,-4(%r13)\n\t" /* cpu->Flags & WOW64_CPURESERVED_FLAG_RESET_STATE */
|
||||||
|
"jc .Lsyscall_32to64_return\n\t"
|
||||||
|
"movl 0xb8(%r13),%edx\n\t" /* context->Eip */
|
||||||
|
"movl %edx,(%rsp)\n\t"
|
||||||
|
"movl 0xbc(%r13),%edx\n\t" /* context->SegCs */
|
||||||
|
"movl %edx,4(%rsp)\n\t"
|
||||||
|
"movl 0xc4(%r13),%r14d\n\t" /* context->Esp */
|
||||||
|
"xchgq %r14,%rsp\n\t"
|
||||||
|
"ljmp *(%r14)" )
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* BTCpuSimulate (wow64cpu.@)
|
* BTCpuSimulate (wow64cpu.@)
|
||||||
*/
|
*/
|
||||||
|
@ -234,10 +282,13 @@ __ASM_STDCALL_FUNC( BTCpuSimulate, 0,
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI BTCpuProcessInit(void)
|
NTSTATUS WINAPI BTCpuProcessInit(void)
|
||||||
{
|
{
|
||||||
struct thunk_32to64 *thunk = (struct thunk_32to64 *)code_buffer;
|
struct thunk_opcodes *thunk = (struct thunk_opcodes *)code_buffer;
|
||||||
SIZE_T size = sizeof(*thunk);
|
SIZE_T size = sizeof(*thunk);
|
||||||
ULONG old_prot;
|
ULONG old_prot;
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
|
HMODULE module;
|
||||||
|
UNICODE_STRING str;
|
||||||
|
void **p__wine_unix_call_dispatcher;
|
||||||
|
|
||||||
if ((ULONG_PTR)syscall_32to64 >> 32)
|
if ((ULONG_PTR)syscall_32to64 >> 32)
|
||||||
{
|
{
|
||||||
|
@ -245,16 +296,31 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
|
||||||
return STATUS_INVALID_ADDRESS;
|
return STATUS_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString( &str, L"ntdll.dll" );
|
||||||
|
LdrGetDllHandle( NULL, 0, &str, &module );
|
||||||
|
p__wine_unix_call_dispatcher = RtlFindExportedRoutineByName( module, "__wine_unix_call_dispatcher" );
|
||||||
|
|
||||||
RtlCaptureContext( &context );
|
RtlCaptureContext( &context );
|
||||||
cs64_sel = context.SegCs;
|
cs64_sel = context.SegCs;
|
||||||
ds64_sel = context.SegDs;
|
ds64_sel = context.SegDs;
|
||||||
fs32_sel = context.SegFs;
|
fs32_sel = context.SegFs;
|
||||||
|
|
||||||
thunk->ljmp = 0xff;
|
thunk->syscall_thunk.ljmp = 0xff;
|
||||||
thunk->modrm = 0x2d;
|
thunk->syscall_thunk.modrm = 0x2d;
|
||||||
thunk->op = PtrToUlong( &thunk->addr );
|
thunk->syscall_thunk.op = PtrToUlong( &thunk->syscall_thunk.addr );
|
||||||
thunk->addr = PtrToUlong( syscall_32to64 );
|
thunk->syscall_thunk.addr = PtrToUlong( syscall_32to64 );
|
||||||
thunk->cs = cs64_sel;
|
thunk->syscall_thunk.cs = cs64_sel;
|
||||||
|
|
||||||
|
thunk->unix_thunk.pushl = 0x68;
|
||||||
|
thunk->unix_thunk.dispatcher_high = (ULONG_PTR)*p__wine_unix_call_dispatcher >> 32;
|
||||||
|
thunk->unix_thunk.pushl2 = 0x68;
|
||||||
|
thunk->unix_thunk.dispatcher_low = (ULONG_PTR)*p__wine_unix_call_dispatcher;
|
||||||
|
thunk->unix_thunk.t.ljmp = 0xff;
|
||||||
|
thunk->unix_thunk.t.modrm = 0x2d;
|
||||||
|
thunk->unix_thunk.t.op = PtrToUlong( &thunk->unix_thunk.t.addr );
|
||||||
|
thunk->unix_thunk.t.addr = PtrToUlong( unix_call_32to64 );
|
||||||
|
thunk->unix_thunk.t.cs = cs64_sel;
|
||||||
|
|
||||||
NtProtectVirtualMemory( GetCurrentProcess(), (void **)&thunk, &size, PAGE_EXECUTE_READ, &old_prot );
|
NtProtectVirtualMemory( GetCurrentProcess(), (void **)&thunk, &size, PAGE_EXECUTE_READ, &old_prot );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +331,20 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
|
||||||
*/
|
*/
|
||||||
void * WINAPI BTCpuGetBopCode(void)
|
void * WINAPI BTCpuGetBopCode(void)
|
||||||
{
|
{
|
||||||
return code_buffer;
|
struct thunk_opcodes *thunk = (struct thunk_opcodes *)code_buffer;
|
||||||
|
|
||||||
|
return &thunk->syscall_thunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* __wine_get_unix_opcode (wow64cpu.@)
|
||||||
|
*/
|
||||||
|
void * WINAPI __wine_get_unix_opcode(void)
|
||||||
|
{
|
||||||
|
struct thunk_opcodes *thunk = (struct thunk_opcodes *)code_buffer;
|
||||||
|
|
||||||
|
return &thunk->unix_thunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
@ stdcall BTCpuTurboThunkControl(long)
|
@ stdcall BTCpuTurboThunkControl(long)
|
||||||
#@ stub TurboDispatchJumpAddressEnd
|
#@ stub TurboDispatchJumpAddressEnd
|
||||||
#@ stub TurboDispatchJumpAddressStart
|
#@ stub TurboDispatchJumpAddressStart
|
||||||
|
@ stdcall __wine_get_unix_opcode()
|
||||||
|
|
Loading…
Reference in a new issue