wow64cpu: Implement 32<->64 bit code switching.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3dd6cafe3d
commit
f60fd0e9ae
|
@ -1 +1,6 @@
|
|||
MODULE = wow64cpu.dll
|
||||
IMPORTS = wow64 ntdll winecrt0
|
||||
|
||||
EXTRADLLFLAGS = -nodefaultlibs -mno-cygwin -Wl,--image-base,0x6f100000
|
||||
|
||||
C_SRCS = cpu.c
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* WoW64 CPU support
|
||||
*
|
||||
* Copyright 2021 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winnt.h"
|
||||
#include "winternl.h"
|
||||
#include "wine/asm.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wow);
|
||||
|
||||
#include "pshpack1.h"
|
||||
struct thunk_32to64
|
||||
{
|
||||
BYTE ljmp; /* ljmp %cs:1f */
|
||||
DWORD addr;
|
||||
WORD cs;
|
||||
};
|
||||
#include "poppack.h"
|
||||
|
||||
static BYTE DECLSPEC_ALIGN(4096) code_buffer[0x1000];
|
||||
|
||||
|
||||
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved )
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* syscall_32to64
|
||||
*
|
||||
* Execute a 64-bit syscall from 32-bit code, then return to 32-bit.
|
||||
*/
|
||||
extern void WINAPI syscall_32to64(void) DECLSPEC_HIDDEN;
|
||||
__ASM_GLOBAL_FUNC( syscall_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 (%r14),%edx\n\t"
|
||||
"movl %edx,0xb8(%r13)\n\t" /* context->Eip */
|
||||
"pushfq\n\t"
|
||||
"popq %rdx\n\t"
|
||||
"movl %edx,0xc0(%r13)\n\t" /* context->EFlags */
|
||||
"leaq 4(%r14),%rdx\n\t"
|
||||
"movl %edx,0xc4(%r13)\n\t" /* context->Esp */
|
||||
"movq %rax,%rcx\n\t" /* syscall number */
|
||||
"leaq 8(%r14),%rdx\n\t" /* parameters */
|
||||
"call " __ASM_NAME("Wow64SystemServiceEx") "\n\t"
|
||||
|
||||
"syscall_32to64_return:\n\t"
|
||||
"movl 0x9c(%r13),%edi\n\t" /* context->Edi */
|
||||
"movl 0xa0(%r13),%esi\n\t" /* context->Esi */
|
||||
"movl 0xa4(%r13),%ebx\n\t" /* context->Ebx */
|
||||
"movl 0xb4(%r13),%ebp\n\t" /* context->Ebp */
|
||||
"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.@)
|
||||
*/
|
||||
__ASM_STDCALL_FUNC( BTCpuSimulate, 0,
|
||||
"subq $0x28,%rsp\n"
|
||||
__ASM_SEH(".seh_stackalloc 0x28\n\t")
|
||||
__ASM_SEH(".seh_endprologue\n\t")
|
||||
__ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
|
||||
"movq %gs:0x30,%r12\n\t"
|
||||
"movq 0x1488(%r12),%rcx\n\t" /* NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED] */
|
||||
"leaq 4(%rcx),%r13\n" /* cpu->Context */
|
||||
"jmp syscall_32to64_return\n" )
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* BTCpuProcessInit (wow64cpu.@)
|
||||
*/
|
||||
NTSTATUS WINAPI BTCpuProcessInit(void)
|
||||
{
|
||||
struct thunk_32to64 *thunk = (struct thunk_32to64 *)code_buffer;
|
||||
SIZE_T size = sizeof(*thunk);
|
||||
ULONG old_prot;
|
||||
CONTEXT context;
|
||||
|
||||
if ((ULONG_PTR)syscall_32to64 >> 32)
|
||||
{
|
||||
ERR( "wow64cpu loaded above 4G, disabling\n" );
|
||||
return STATUS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
RtlCaptureContext( &context );
|
||||
thunk->ljmp = 0xea;
|
||||
thunk->addr = PtrToUlong( syscall_32to64 );
|
||||
thunk->cs = context.SegCs;
|
||||
NtProtectVirtualMemory( GetCurrentProcess(), (void **)&thunk, &size, PAGE_EXECUTE_READ, &old_prot );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* BTCpuGetBopCode (wow64cpu.@)
|
||||
*/
|
||||
void * WINAPI BTCpuGetBopCode(void)
|
||||
{
|
||||
return code_buffer;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
@ stub BTCpuGetBopCode
|
||||
@ stub BTCpuGetContext
|
||||
@ stub BTCpuProcessInit
|
||||
@ stub BTCpuResetToConsistentState
|
||||
@ stub BTCpuSetContext
|
||||
@ stub BTCpuSimulate
|
||||
@ stub BTCpuTurboThunkControl
|
||||
@ stub TurboDispatchJumpAddressEnd
|
||||
@ stub TurboDispatchJumpAddressStart
|
||||
@ stdcall BTCpuGetBopCode()
|
||||
#@ stub BTCpuGetContext
|
||||
@ stdcall BTCpuProcessInit()
|
||||
#@ stub BTCpuResetToConsistentState
|
||||
#@ stub BTCpuSetContext
|
||||
@ stdcall BTCpuSimulate()
|
||||
#@ stub BTCpuTurboThunkControl
|
||||
#@ stub TurboDispatchJumpAddressEnd
|
||||
#@ stub TurboDispatchJumpAddressStart
|
||||
|
|
Loading…
Reference in New Issue