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 "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];
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue