Setup exception frame around 16-bit calls to unwind stack properly.

This commit is contained in:
Alexandre Julliard 2002-08-13 03:29:17 +00:00
parent 1166dc733a
commit 6006757996
4 changed files with 72 additions and 36 deletions

View File

@ -27,6 +27,7 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winerror.h" #include "winerror.h"
#include "ntddk.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -2091,6 +2092,7 @@ void WINAPI Throw16( LPCATCHBUF lpbuf, INT16 retval, CONTEXT86 *context )
} }
frame32 = ((STACK16FRAME *)MapSL(frame32->frame16))->frame32; frame32 = ((STACK16FRAME *)MapSL(frame32->frame16))->frame32;
} }
RtlUnwind( &pFrame->frame32->frame, NULL, NULL, 0 );
context->Eip = lpbuf[0]; context->Eip = lpbuf[0];
context->SegCs = lpbuf[1]; context->SegCs = lpbuf[1];

View File

@ -402,11 +402,30 @@ DWORD __wine_exception_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame
*/ */
DWORD __wine_finally_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame, DWORD __wine_finally_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher ) CONTEXT *context, LPVOID pdispatcher )
{
if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{ {
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame; __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
if (!(record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
return ExceptionContinueSearch;
wine_frame->u.finally_func( FALSE ); wine_frame->u.finally_func( FALSE );
}
return ExceptionContinueSearch;
}
/*************************************************************
* __wine_callto16_handler
*
* Handler for exceptions occuring in 16-bit code.
*/
DWORD __wine_callto16_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher )
{
if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{
/* unwinding: restore the stack pointer in the TEB, and leave the Win16 mutex */
STACK32FRAME *frame32 = (STACK32FRAME *)((char *)frame - offsetof(STACK32FRAME,frame));
NtCurrentTeb()->cur_stack = frame32->frame16;
_LeaveWin16Lock();
}
return ExceptionContinueSearch; return ExceptionContinueSearch;
} }

View File

@ -32,18 +32,19 @@
/* 32-bit stack layout after CallTo16() */ /* 32-bit stack layout after CallTo16() */
typedef struct _STACK32FRAME typedef struct _STACK32FRAME
{ {
SEGPTR frame16; /* 00 16-bit frame from last CallFrom16() */ DWORD restore_addr; /* 00 return address for restoring code selector */
DWORD restore_addr; /* 04 return address for restoring code selector */ DWORD codeselector; /* 04 code selector to restore */
DWORD codeselector; /* 08 code selector to restore */ EXCEPTION_FRAME frame; /* 08 Exception frame */
DWORD edi; /* 0c saved registers */ SEGPTR frame16; /* 10 16-bit frame from last CallFrom16() */
DWORD esi; /* 10 */ DWORD edi; /* 14 saved registers */
DWORD edx; /* 14 */ DWORD esi; /* 18 */
DWORD ecx; /* 18 */ DWORD edx; /* 1c */
DWORD ebx; /* 1c */ DWORD ecx; /* 20 */
DWORD ebp; /* 20 saved 32-bit frame pointer */ DWORD ebx; /* 24 */
DWORD retaddr; /* 24 return address */ DWORD ebp; /* 28 saved 32-bit frame pointer */
DWORD target; /* 28 target address / CONTEXT86 pointer */ DWORD retaddr; /* 2c return address */
DWORD nb_args; /* 2c number of 16-bit argument bytes */ DWORD target; /* 30 target address / CONTEXT86 pointer */
DWORD nb_args; /* 34 number of 16-bit argument bytes */
} STACK32FRAME; } STACK32FRAME;
/* 16-bit stack layout after CallFrom16() */ /* 16-bit stack layout after CallFrom16() */

View File

@ -501,12 +501,6 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.Lwine_call_to_16_%s.getgot1], %%ebx\n", name ); fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.Lwine_call_to_16_%s.getgot1], %%ebx\n", name );
} }
/* Enter Win16 Mutex */
if ( UsePIC )
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock@PLT") "\n" );
else
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock") "\n" );
/* Print debugging info */ /* Print debugging info */
if (debugging) if (debugging)
{ {
@ -523,6 +517,21 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
fprintf( outfile, "\taddl $12, %%esp\n" ); fprintf( outfile, "\taddl $12, %%esp\n" );
} }
/* Enter Win16 Mutex */
if ( UsePIC )
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock@PLT") "\n" );
else
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock") "\n" );
/* Setup exception frame */
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
if (UsePIC)
fprintf( outfile, "\tpushl " __ASM_NAME("__wine_callto16_handler@GOT") "(%%ebx)\n" );
else
fprintf( outfile, "\tpushl $" __ASM_NAME("__wine_callto16_handler") "\n" );
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STRUCTOFFSET(TEB,except) );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%esp,(%d)\n", STRUCTOFFSET(TEB,except) );
/* Get return address */ /* Get return address */
if ( UsePIC ) if ( UsePIC )
{ {
@ -534,7 +543,12 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
/* Call the actual CallTo16 routine (simulate a lcall) */ /* Call the actual CallTo16 routine (simulate a lcall) */
fprintf( outfile, "\tpushl %%cs\n" ); fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall .Lwine_call_to_16_%s\n", name ); fprintf( outfile, "\tcall .Lwine_call_to_16_%s\n", reg_func ? name : "long" );
/* Remove exception frame */
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STRUCTOFFSET(TEB,except) );
fprintf( outfile, "\taddl $4, %%esp\n" );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
if ( !reg_func ) if ( !reg_func )
{ {
@ -563,7 +577,9 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
* at the cost of a somewhat less efficient return path.] * at the cost of a somewhat less efficient return path.]
*/ */
fprintf( outfile, "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target)-12 ); fprintf( outfile, "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target) - STACK32OFFSET(edi));
/* everything above edi has been popped already */
fprintf( outfile, "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) ); fprintf( outfile, "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) ); fprintf( outfile, "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) ); fprintf( outfile, "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) );
@ -584,6 +600,12 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.Lwine_call_to_16_%s.getgot2], %%ebx\n", name ); fprintf( outfile, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-.Lwine_call_to_16_%s.getgot2], %%ebx\n", name );
} }
/* Leave Win16 Mutex */
if ( UsePIC )
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock@PLT") "\n" );
else
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock") "\n" );
/* Print debugging info */ /* Print debugging info */
if (debugging) if (debugging)
{ {
@ -597,12 +619,6 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
fprintf( outfile, "\taddl $4, %%esp\n" ); fprintf( outfile, "\taddl $4, %%esp\n" );
} }
/* Leave Win16 Mutex */
if ( UsePIC )
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock@PLT") "\n" );
else
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock") "\n" );
/* Get return value */ /* Get return value */
fprintf( outfile, "\tpopl %%eax\n" ); fprintf( outfile, "\tpopl %%eax\n" );
@ -620,13 +636,12 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
/* Start of the actual CallTo16 routine */ /* Start of the actual CallTo16 routine */
if (!reg_func && short_ret) return; /* call_to_16_word uses call_to_16_long backend routine */
fprintf( outfile, ".Lwine_call_to_16_%s:\n", name ); fprintf( outfile, ".Lwine_call_to_16_%s:\n", name );
/* Complete STACK32FRAME */
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
/* Switch to the 16-bit stack */ /* Switch to the 16-bit stack */
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
#ifdef __svr4__ #ifdef __svr4__
fprintf( outfile,"\tdata16\n"); fprintf( outfile,"\tdata16\n");
#endif #endif
@ -739,7 +754,6 @@ static void BuildRet16Func( FILE *outfile )
#endif #endif
fprintf( outfile, "\tmovw %%di,%%ss\n" ); fprintf( outfile, "\tmovw %%di,%%ss\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET ); fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Return to caller */ /* Return to caller */