Commit 60067579 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 1166dc73
......@@ -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))
{
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
wine_frame->u.finally_func( FALSE );
}
return ExceptionContinueSearch;
}
if (!(record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
return ExceptionContinueSearch;
wine_frame->u.finally_func( FALSE );
/*************************************************************
* __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 */
fprintf( outfile, ".Lwine_call_to_16_%s:\n", name );
if (!reg_func && short_ret) return; /* call_to_16_word uses call_to_16_long backend routine */
/* Complete STACK32FRAME */
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
fprintf( outfile, ".Lwine_call_to_16_%s:\n", name );
/* 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 */
......
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