ntdll: Allocate a 32-bit %fs selector on Linux in Wow64 mode.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cec3db10f4
commit
a7b6b4f0d0
|
@ -88,6 +88,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||||
#include <asm/prctl.h>
|
#include <asm/prctl.h>
|
||||||
static inline int arch_prctl( int func, void *ptr ) { return syscall( __NR_arch_prctl, func, ptr ); }
|
static inline int arch_prctl( int func, void *ptr ) { return syscall( __NR_arch_prctl, func, ptr ); }
|
||||||
|
|
||||||
|
extern int CDECL alloc_fs_sel( int sel, void *base );
|
||||||
|
__ASM_GLOBAL_FUNC( alloc_fs_sel,
|
||||||
|
/* switch to 32-bit stack */
|
||||||
|
"pushq %rbx\n\t"
|
||||||
|
"pushq %rdi\n\t"
|
||||||
|
"movq %rsp,%rdi\n\t"
|
||||||
|
"movq %gs:0x8,%rsp\n\t" /* NtCurrentTeb()->Tib.StackBase */
|
||||||
|
"subl $0x10,%esp\n\t"
|
||||||
|
/* setup modify_ldt struct on 32-bit stack */
|
||||||
|
"movl %ecx,(%rsp)\n\t" /* entry_number */
|
||||||
|
"movl %edx,4(%rsp)\n\t" /* base */
|
||||||
|
"movl $~0,8(%rsp)\n\t" /* limit */
|
||||||
|
"movl $0x41,12(%rsp)\n\t" /* seg_32bit | usable */
|
||||||
|
/* invoke 32-bit syscall */
|
||||||
|
"movl %esp,%ebx\n\t"
|
||||||
|
"movl $0xf3,%eax\n\t" /* SYS_set_thread_area */
|
||||||
|
"int $0x80\n\t"
|
||||||
|
/* restore stack */
|
||||||
|
"movl (%rsp),%eax\n\t" /* entry_number */
|
||||||
|
"movq %rdi,%rsp\n\t"
|
||||||
|
"popq %rdi\n\t"
|
||||||
|
"popq %rbx\n\t"
|
||||||
|
"ret" );
|
||||||
|
|
||||||
#ifndef FP_XSTATE_MAGIC1
|
#ifndef FP_XSTATE_MAGIC1
|
||||||
#define FP_XSTATE_MAGIC1 0x46505853
|
#define FP_XSTATE_MAGIC1 0x46505853
|
||||||
#endif
|
#endif
|
||||||
|
@ -367,6 +391,7 @@ static inline void context_init_xstate( CONTEXT *context, void *xstate_buffer )
|
||||||
static USHORT cs32_sel; /* selector for %cs in 32-bit mode */
|
static USHORT cs32_sel; /* selector for %cs in 32-bit mode */
|
||||||
static USHORT cs64_sel; /* selector for %cs in 64-bit mode */
|
static USHORT cs64_sel; /* selector for %cs in 64-bit mode */
|
||||||
static USHORT ds64_sel; /* selector for %ds/%es/%ss in 64-bit mode */
|
static USHORT ds64_sel; /* selector for %ds/%es/%ss in 64-bit mode */
|
||||||
|
static USHORT fs32_sel; /* selector for %fs in 32-bit mode */
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Definitions for Dwarf unwind tables
|
* Definitions for Dwarf unwind tables
|
||||||
|
@ -1911,7 +1936,7 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size )
|
||||||
{
|
{
|
||||||
wow_frame->SegDs = ds64_sel;
|
wow_frame->SegDs = ds64_sel;
|
||||||
wow_frame->SegEs = ds64_sel;
|
wow_frame->SegEs = ds64_sel;
|
||||||
wow_frame->SegFs = 0; /* FIXME */
|
wow_frame->SegFs = fs32_sel;
|
||||||
wow_frame->SegGs = ds64_sel;
|
wow_frame->SegGs = ds64_sel;
|
||||||
}
|
}
|
||||||
if (flags & CONTEXT_I386_DEBUG_REGISTERS)
|
if (flags & CONTEXT_I386_DEBUG_REGISTERS)
|
||||||
|
@ -2743,6 +2768,7 @@ void signal_init_thread( TEB *teb )
|
||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
arch_prctl( ARCH_SET_GS, teb );
|
arch_prctl( ARCH_SET_GS, teb );
|
||||||
arch_prctl( ARCH_GET_FS, &amd64_thread_data()->pthread_teb );
|
arch_prctl( ARCH_GET_FS, &amd64_thread_data()->pthread_teb );
|
||||||
|
if (fs32_sel) alloc_fs_sel( fs32_sel >> 3, (char *)teb + teb->WowTebOffset );
|
||||||
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||||
amd64_set_gsbase( teb );
|
amd64_set_gsbase( teb );
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
|
@ -2793,7 +2819,15 @@ void signal_init_process(void)
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (NtCurrentTeb()->WowTebOffset)
|
if (NtCurrentTeb()->WowTebOffset)
|
||||||
{
|
{
|
||||||
|
void *teb32 = (char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset;
|
||||||
|
int sel;
|
||||||
|
|
||||||
cs32_sel = 0x23;
|
cs32_sel = 0x23;
|
||||||
|
if ((sel = alloc_fs_sel( -1, teb32 )) != -1)
|
||||||
|
{
|
||||||
|
fs32_sel = (sel << 3) | 3;
|
||||||
|
}
|
||||||
|
else ERR( "failed to allocate %%fs selector\n" );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2842,6 +2876,7 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B
|
||||||
context.SegCs = cs64_sel;
|
context.SegCs = cs64_sel;
|
||||||
context.SegDs = ds64_sel;
|
context.SegDs = ds64_sel;
|
||||||
context.SegEs = ds64_sel;
|
context.SegEs = ds64_sel;
|
||||||
|
context.SegFs = fs32_sel;
|
||||||
context.SegGs = ds64_sel;
|
context.SegGs = ds64_sel;
|
||||||
context.SegSs = ds64_sel;
|
context.SegSs = ds64_sel;
|
||||||
context.EFlags = 0x200;
|
context.EFlags = 0x200;
|
||||||
|
|
Loading…
Reference in New Issue