Commit 7e85ea7c authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Moved stack switch handling (large stack) to sysdeps.c

Enable exception dispatch while on large stack.
parent 66331a73
......@@ -12,12 +12,11 @@
#include "wingdi.h"
#include "wine/winuser16.h"
extern int (*IF1632_CallLargeStack)( int (*func)(void), void *arg );
extern void SYSDEPS_SwitchToThreadStack( void (*func)(void) ) WINE_NORETURN;
extern int SYSDEPS_CallOnLargeStack( int (*func)(void *), void *arg );
#define CALL_LARGE_STACK(func,arg) \
(IF1632_CallLargeStack ? \
IF1632_CallLargeStack( (int(*)())(func), (void *)(arg) ) : \
((int(*)())(func))((void *)arg))
#define CALL_LARGE_STACK( func, arg ) \
SYSDEPS_CallOnLargeStack( (int (*)(void *))(func), (void *)(arg) )
typedef void (*RELAY)();
extern FARPROC THUNK_Alloc( FARPROC16 func, RELAY relay );
......@@ -25,8 +24,6 @@ extern void THUNK_Free( FARPROC thunk );
extern BOOL THUNK_Init(void);
extern void THUNK_InitCallout(void);
extern void CALL32_Init( void *func, void *target, void *stack ) WINE_NORETURN;
typedef struct
{
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT86 *, INT );
......
......@@ -43,8 +43,6 @@ DECLARE_DEBUG_CHANNEL(toolhelp)
/* Min. number of thunks allocated when creating a new segment */
#define MIN_THUNKS 32
/* Pointer to function to switch to a larger stack */
int (*IF1632_CallLargeStack)( int (*func)(), void *arg ) = NULL;
static THHOOK DefaultThhook = { 0 };
THHOOK *pThhook = &DefaultThhook;
......
......@@ -413,7 +413,7 @@ static void PROCESS_Start( HMODULE main_module, LPCSTR filename )
SIGNAL_Init(); /* reinitialize signal stack */
/* switch to the new stack */
CALL32_Init( &IF1632_CallLargeStack, start_process, NtCurrentTeb()->stack_top );
SYSDEPS_SwitchToThreadStack( start_process );
}
......
......@@ -16,6 +16,7 @@ static int *ph_errno = &h_errno;
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
......@@ -221,6 +222,103 @@ void SYSDEPS_ExitThread( int status )
}
/***********************************************************************
* SYSDEPS_CallOnStack
*/
static int SYSDEPS_DoCallOnStack( int (*func)(LPVOID), LPVOID arg ) WINE_UNUSED;
static int SYSDEPS_DoCallOnStack( int (*func)(LPVOID), LPVOID arg )
{
int retv = 0;
__TRY
{
retv = func( arg );
}
__EXCEPT(UnhandledExceptionFilter)
{
TerminateThread( GetCurrentThread(), GetExceptionCode() );
return 0;
}
__ENDTRY
return retv;
}
#ifdef __i386__
int SYSDEPS_CallOnStack( LPVOID stackTop, LPVOID stackLow,
int (*func)(LPVOID), LPVOID arg );
__ASM_GLOBAL_FUNC( SYSDEPS_CallOnStack,
"pushl %ebp\n\t"
"movl %esp, %ebp\n\t"
".byte 0x64; pushl 0x04\n\t"
".byte 0x64; pushl 0x08\n\t"
"movl 8(%ebp), %esp\n\t"
"movl 12(%ebp), %eax\n\t"
".byte 0x64; movl %esp, 0x04\n\t"
".byte 0x64; movl %eax, 0x08\n\t"
"pushl 20(%ebp)\n\t"
"pushl 16(%ebp)\n\t"
"call " __ASM_NAME("SYSDEPS_DoCallOnStack") "\n\t"
"leal -8(%ebp), %esp\n\t"
".byte 0x64; popl 0x08\n\t"
".byte 0x64; popl 0x04\n\t"
"popl %ebp\n\t"
"ret" );
#else
int SYSDEPS_CallOnStack( LPVOID stackTop, LPVOID stackLow,
int (*func)(LPVOID), LPVOID arg )
{
return SYSDEPS_DoCallOnStack( func, arg );
}
#endif
/***********************************************************************
* SYSDEPS_SwitchToThreadStack
*/
static LPVOID SYSDEPS_LargeStackTop = NULL;
static LPVOID SYSDEPS_LargeStackLow = NULL;
void SYSDEPS_SwitchToThreadStack( void (*func)(void) )
{
TEB *teb = NtCurrentTeb();
LPVOID stackTop = teb->stack_top;
LPVOID stackLow = teb->stack_low;
struct rlimit rl;
if ( getrlimit(RLIMIT_STACK, &rl) < 0 )
{
WARN("Can't get rlimit\n");
rl.rlim_cur = 8*1024*1024;
}
SYSDEPS_LargeStackTop = teb->stack_top = &func - 128;
SYSDEPS_LargeStackLow = teb->stack_low = teb->stack_top - rl.rlim_cur;
SYSDEPS_CallOnStack( stackTop, stackLow,
(int (*)(void *))func, NULL );
}
/***********************************************************************
* SYSDEPS_CallOnLargeStack
*/
int SYSDEPS_CallOnLargeStack( int (*func)(LPVOID), LPVOID arg )
{
static int recurse = 0;
int retv;
if ( recurse++ == 0 && SYSDEPS_LargeStackTop )
retv = SYSDEPS_CallOnStack( SYSDEPS_LargeStackTop,
SYSDEPS_LargeStackLow, func, arg );
else
retv = func( arg );
recurse--;
return retv;
}
/**********************************************************************
* NtCurrentTeb (NTDLL.89)
*
......
......@@ -2845,101 +2845,6 @@ static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
}
/*******************************************************************
* BuildCallTo32LargeStack
*
* Build the function used to switch to the original 32-bit stack
* before calling a 32-bit function from 32-bit code. This is used for
* functions that need a large stack, like X bitmaps functions.
*
* The generated function has the following prototype:
* int xxx( int (*func)(), void *arg );
*
* The pointer to the function can be retrieved by calling CALL32_Init,
* which also takes care of saving the current 32-bit stack pointer.
* Furthermore, CALL32_Init switches to a new stack and jumps to the
* specified target address.
*
* NOTE: The CALL32_LargeStack routine may be recursively entered by the
* same thread, but not concurrently entered by several threads.
*
* Stack layout of CALL32_Init:
*
* (esp+12) new stack address
* (esp+8) target address
* (esp+4) pointer to variable to receive CALL32_LargeStack address
* (esp) ret addr
*
* Stack layout of CALL32_LargeStack:
* ... ...
* (ebp+12) arg
* (ebp+8) func
* (ebp+4) ret addr
* (ebp) ebp
*/
static void BuildCallTo32LargeStack( FILE *outfile )
{
/* Initialization function */
fprintf( outfile, "\n\t.align 4\n" );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CALL32_Init:F1\",36,0,0," PREFIX "CALL32_Init\n");
#endif
fprintf( outfile, "\t.globl " PREFIX "CALL32_Init\n" );
fprintf( outfile, "\t.type " PREFIX "CALL32_Init,@function\n" );
fprintf( outfile, PREFIX "CALL32_Init:\n" );
fprintf( outfile, "\tmovl %%esp,CALL32_Original32_esp\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tmovl $CALL32_LargeStack,(%%eax)\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%esp\n" );
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tret\n" );
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CALL32_LargeStack:F1\",36,0,0,CALL32_LargeStack\n");
#endif
fprintf( outfile, "CALL32_LargeStack:\n" );
/* Entry code */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
/* Switch to the original 32-bit stack pointer */
fprintf( outfile, "\tcmpl $0, CALL32_RecursionCount\n" );
fprintf( outfile, "\tjne CALL32_skip\n" );
fprintf( outfile, "\tmovl CALL32_Original32_esp, %%esp\n" );
fprintf( outfile, "CALL32_skip:\n" );
fprintf( outfile, "\tincl CALL32_RecursionCount\n" );
/* Transfer the argument and call the function */
fprintf( outfile, "\tpushl 12(%%ebp)\n" );
fprintf( outfile, "\tcall *8(%%ebp)\n" );
/* Restore registers and return */
fprintf( outfile, "\tdecl CALL32_RecursionCount\n" );
fprintf( outfile, "\tmovl %%ebp,%%esp\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret\n" );
/* Data */
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "CALL32_Original32_esp:\t.long 0\n" );
fprintf( outfile, "CALL32_RecursionCount:\t.long 0\n" );
fprintf( outfile, "\t.text\n" );
}
/*******************************************************************
* BuildCallFrom32Regs
......@@ -3269,10 +3174,6 @@ static void BuildCall32( FILE *outfile )
}
#endif
/* Build the 32-bit large stack callback */
BuildCallTo32LargeStack( outfile );
/* Build the register callback function */
BuildCallFrom32Regs( outfile );
......
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