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.
This commit is contained in:
Alexandre Julliard 2003-08-25 23:48:30 +00:00
parent a203421581
commit a5b961c2b0
3 changed files with 98 additions and 50 deletions

View File

@ -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 (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);
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;
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)

View File

@ -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 */

View File

@ -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 );