Setup exception frame around 16-bit calls to unwind stack properly.
This commit is contained in:
parent
1166dc733a
commit
6006757996
|
@ -27,6 +27,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "ntddk.h"
|
||||
#include "wine/winbase16.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
@ -2091,6 +2092,7 @@ void WINAPI Throw16( LPCATCHBUF lpbuf, INT16 retval, CONTEXT86 *context )
|
|||
}
|
||||
frame32 = ((STACK16FRAME *)MapSL(frame32->frame16))->frame32;
|
||||
}
|
||||
RtlUnwind( &pFrame->frame32->frame, NULL, NULL, 0 );
|
||||
|
||||
context->Eip = lpbuf[0];
|
||||
context->SegCs = lpbuf[1];
|
||||
|
|
|
@ -403,10 +403,29 @@ DWORD __wine_exception_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame
|
|||
DWORD __wine_finally_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
|
||||
CONTEXT *context, LPVOID pdispatcher )
|
||||
{
|
||||
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
|
||||
|
||||
if (!(record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
|
||||
return ExceptionContinueSearch;
|
||||
wine_frame->u.finally_func( FALSE );
|
||||
if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
|
||||
{
|
||||
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -32,18 +32,19 @@
|
|||
/* 32-bit stack layout after CallTo16() */
|
||||
typedef struct _STACK32FRAME
|
||||
{
|
||||
SEGPTR frame16; /* 00 16-bit frame from last CallFrom16() */
|
||||
DWORD restore_addr; /* 04 return address for restoring code selector */
|
||||
DWORD codeselector; /* 08 code selector to restore */
|
||||
DWORD edi; /* 0c saved registers */
|
||||
DWORD esi; /* 10 */
|
||||
DWORD edx; /* 14 */
|
||||
DWORD ecx; /* 18 */
|
||||
DWORD ebx; /* 1c */
|
||||
DWORD ebp; /* 20 saved 32-bit frame pointer */
|
||||
DWORD retaddr; /* 24 return address */
|
||||
DWORD target; /* 28 target address / CONTEXT86 pointer */
|
||||
DWORD nb_args; /* 2c number of 16-bit argument bytes */
|
||||
DWORD restore_addr; /* 00 return address for restoring code selector */
|
||||
DWORD codeselector; /* 04 code selector to restore */
|
||||
EXCEPTION_FRAME frame; /* 08 Exception frame */
|
||||
SEGPTR frame16; /* 10 16-bit frame from last CallFrom16() */
|
||||
DWORD edi; /* 14 saved registers */
|
||||
DWORD esi; /* 18 */
|
||||
DWORD edx; /* 1c */
|
||||
DWORD ecx; /* 20 */
|
||||
DWORD ebx; /* 24 */
|
||||
DWORD ebp; /* 28 saved 32-bit frame pointer */
|
||||
DWORD retaddr; /* 2c return address */
|
||||
DWORD target; /* 30 target address / CONTEXT86 pointer */
|
||||
DWORD nb_args; /* 34 number of 16-bit argument bytes */
|
||||
} STACK32FRAME;
|
||||
|
||||
/* 16-bit stack layout after CallFrom16() */
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/* Enter Win16 Mutex */
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_EnterWin16Lock") "\n" );
|
||||
|
||||
/* Print debugging info */
|
||||
if (debugging)
|
||||
{
|
||||
|
@ -523,6 +517,21 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
|
|||
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 */
|
||||
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) */
|
||||
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 )
|
||||
{
|
||||
|
@ -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.]
|
||||
*/
|
||||
|
||||
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 %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
|
||||
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 );
|
||||
}
|
||||
|
||||
/* Leave Win16 Mutex */
|
||||
if ( UsePIC )
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock@PLT") "\n" );
|
||||
else
|
||||
fprintf( outfile, "\tcall " __ASM_NAME("_LeaveWin16Lock") "\n" );
|
||||
|
||||
/* Print debugging info */
|
||||
if (debugging)
|
||||
{
|
||||
|
@ -597,12 +619,6 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
|
|||
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 */
|
||||
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 */
|
||||
|
||||
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 );
|
||||
|
||||
/* Complete STACK32FRAME */
|
||||
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
|
||||
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
|
||||
|
||||
/* Switch to the 16-bit stack */
|
||||
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
|
||||
#ifdef __svr4__
|
||||
fprintf( outfile,"\tdata16\n");
|
||||
#endif
|
||||
|
@ -739,7 +754,6 @@ static void BuildRet16Func( FILE *outfile )
|
|||
#endif
|
||||
fprintf( outfile, "\tmovw %%di,%%ss\n" );
|
||||
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
|
||||
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
|
||||
|
||||
/* Return to caller */
|
||||
|
||||
|
|
Loading…
Reference in New Issue