Commit a5b961c2 authored by Alexandre Julliard's avatar Alexandre Julliard

Moved selector fixup for the relay code to the callto16 exception

handler. Make sure to only use pop instructions to modify segment registers in the relay code to simplify the selector fixup.
parent a2034215
......@@ -74,6 +74,7 @@ static DWORD CALLBACK start_thread16( LPVOID threadArgs )
#ifdef __i386__
/* symbols exported from relay16.s */
extern DWORD WINAPI wine_call_to_16( FARPROC16 target, DWORD cbArgs, PEXCEPTION_HANDLER handler );
extern void WINAPI wine_call_to_16_regs( CONTEXT86 *context, DWORD cbArgs, PEXCEPTION_HANDLER handler );
......@@ -84,16 +85,16 @@ extern void CALL32_CBClientEx_Ret();
extern DWORD CallTo16_DataSelector;
extern SEGPTR CALL32_CBClient_RetAddr;
extern SEGPTR CALL32_CBClientEx_RetAddr;
extern BYTE Call16_Start;
extern BYTE Call16_End;
static SEGPTR call16_ret_addr; /* segptr to CallTo16_Ret routine */
#endif
/***********************************************************************
* WOWTHUNK_Init
*/
BOOL WOWTHUNK_Init(void)
{
#ifdef __i386__
/* allocate the code selector for CallTo16 routines */
WORD codesel = SELECTOR_AllocBlock( (void *)Call16_Ret_Start,
(char *)Call16_Ret_End - (char *)Call16_Ret_Start,
......@@ -108,7 +109,48 @@ BOOL WOWTHUNK_Init(void)
MAKESEGPTR( codesel, (char*)CALL32_CBClient_Ret - (char*)Call16_Ret_Start );
CALL32_CBClientEx_RetAddr =
MAKESEGPTR( codesel, (char*)CALL32_CBClientEx_Ret - (char*)Call16_Ret_Start );
#endif
return TRUE;
}
/*************************************************************
* fix_selector
*
* Fix a selector load that caused an exception if it's in the
* 16-bit relay code.
*/
static BOOL fix_selector( CONTEXT *context )
{
WORD *stack;
BYTE *instr = (BYTE *)context->Eip;
if (instr < &Call16_Start || instr >= &Call16_End) return FALSE;
/* skip prefixes */
while (*instr == 0x66 || *instr == 0x67) instr++;
switch(instr[0])
{
case 0x07: /* pop es */
case 0x17: /* pop ss */
case 0x1f: /* pop ds */
break;
case 0x0f: /* extended instruction */
switch(instr[1])
{
case 0xa1: /* pop fs */
case 0xa9: /* pop gs */
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
stack = wine_ldt_get_ptr( context->SegSs, context->Esp );
TRACE( "fixing up selector %x for pop instruction\n", *stack );
*stack = 0;
return TRUE;
}
......@@ -128,29 +170,45 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
NtCurrentTeb()->cur_stack = frame32->frame16;
_LeaveWin16Lock();
}
else if (!IS_SELECTOR_SYSTEM(context->SegCs)) /* check for Win16 __GP handler */
else
{
SEGPTR gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) );
if (gpHandler)
if (IS_SELECTOR_SYSTEM(context->SegCs))
{
WORD *stack = wine_ldt_get_ptr( context->SegSs, context->Esp );
*--stack = context->SegCs;
*--stack = context->Eip;
if (!IS_SELECTOR_32BIT(context->SegSs))
context->Esp = MAKELONG( LOWORD(context->Esp - 2*sizeof(WORD)),
HIWORD(context->Esp) );
else
context->Esp -= 2*sizeof(WORD);
context->SegCs = SELECTOROF( gpHandler );
context->Eip = OFFSETOF( gpHandler );
return ExceptionContinueExecution;
if (fix_selector( context )) return ExceptionContinueExecution;
}
else /* check for Win16 __GP handler */
{
SEGPTR gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) );
if (gpHandler)
{
WORD *stack = wine_ldt_get_ptr( context->SegSs, context->Esp );
*--stack = context->SegCs;
*--stack = context->Eip;
if (!IS_SELECTOR_32BIT(context->SegSs))
context->Esp = MAKELONG( LOWORD(context->Esp - 2*sizeof(WORD)),
HIWORD(context->Esp) );
else
context->Esp -= 2*sizeof(WORD);
context->SegCs = SELECTOROF( gpHandler );
context->Eip = OFFSETOF( gpHandler );
return ExceptionContinueExecution;
}
}
}
return ExceptionContinueSearch;
}
#else /* __i386__ */
BOOL WOWTHUNK_Init(void)
{
return TRUE;
}
#endif /* __i386__ */
/*
* 32-bit WOW routines (in WOW32, but actually forwarded to KERNEL32)
......
......@@ -87,18 +87,6 @@ static DWORD CALLBACK timer_thread( void *dummy )
*/
static BOOL INSTR_ReplaceSelector( CONTEXT86 *context, WORD *sel )
{
extern char Call16_Start, Call16_End;
if (IS_SELECTOR_SYSTEM(context->SegCs))
if ( (char *)context->Eip >= &Call16_Start
&& (char *)context->Eip < &Call16_End )
{
/* Saved selector may have become invalid when the relay code */
/* tries to restore it. We simply clear it. */
*sel = 0;
return TRUE;
}
if (*sel == 0x40)
{
#if 0 /* hack until this is moved to kernel */
......
......@@ -401,9 +401,12 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovw %d(%%ebx), %%es\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovw %d(%%ebx), %%fs\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovw %d(%%ebx), %%gs\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%ebx), %%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%ebx), %%esi\n", CONTEXTOFFSET(Esi) );
......@@ -565,12 +568,12 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
/* Get the registers */
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tmovw %%ax,%%gs\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
......@@ -588,10 +591,10 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
/* Set %fs and %gs to the value saved by the last CallFrom16 */
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tmovw %%ax,%%gs\n" );
fprintf( outfile, "\tpushw %d(%%ebp)\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpushw %d(%%ebp)\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tpopw %%gs\n" );
/* Set %ds and %es (and %ax just in case) equal to %ss */
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
......@@ -1020,12 +1023,12 @@ static void BuildCallFrom32Regs( FILE *outfile )
/* Note: we don't bother to restore %cs, %ds and %ss
* changing them in 32-bit code is a recipe for disaster anyway
*/
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", CONTEXTOFFSET(SegEs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", CONTEXTOFFSET(SegFs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", CONTEXTOFFSET(SegGs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ax,%%gs\n" );
fprintf( outfile, "\tpushl %d(%%ebp)\n", CONTEXTOFFSET(SegEs) - STACK_SPACE );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%ebp)\n", CONTEXTOFFSET(SegFs) - STACK_SPACE );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%ebp)\n", CONTEXTOFFSET(SegGs) - STACK_SPACE );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%ebp),%%edi\n", CONTEXTOFFSET(Edi) - STACK_SPACE );
fprintf( outfile, "\tmovl %d(%%ebp),%%esi\n", CONTEXTOFFSET(Esi) - STACK_SPACE );
......@@ -1033,8 +1036,7 @@ static void BuildCallFrom32Regs( FILE *outfile )
fprintf( outfile, "\tmovl %d(%%ebp),%%ecx\n", CONTEXTOFFSET(Ecx) - STACK_SPACE );
fprintf( outfile, "\tmovl %d(%%ebp),%%ebx\n", CONTEXTOFFSET(Ebx) - STACK_SPACE );
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", CONTEXTOFFSET(EFlags) - STACK_SPACE );
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tpushl %d(%%ebp)\n", CONTEXTOFFSET(EFlags) - STACK_SPACE );
fprintf( outfile, "\tpopfl\n" );
fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", CONTEXTOFFSET(Eax) - STACK_SPACE );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment