Moved stack switch handling (large stack) to sysdeps.c
Enable exception dispatch while on large stack.
This commit is contained in:
parent
66331a73c0
commit
7e85ea7c86
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue