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 "wingdi.h"
|
||||||
#include "wine/winuser16.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) \
|
#define CALL_LARGE_STACK( func, arg ) \
|
||||||
(IF1632_CallLargeStack ? \
|
SYSDEPS_CallOnLargeStack( (int (*)(void *))(func), (void *)(arg) )
|
||||||
IF1632_CallLargeStack( (int(*)())(func), (void *)(arg) ) : \
|
|
||||||
((int(*)())(func))((void *)arg))
|
|
||||||
|
|
||||||
typedef void (*RELAY)();
|
typedef void (*RELAY)();
|
||||||
extern FARPROC THUNK_Alloc( FARPROC16 func, RELAY 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 BOOL THUNK_Init(void);
|
||||||
extern void THUNK_InitCallout(void);
|
extern void THUNK_InitCallout(void);
|
||||||
|
|
||||||
extern void CALL32_Init( void *func, void *target, void *stack ) WINE_NORETURN;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT86 *, INT );
|
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT86 *, INT );
|
||||||
|
|
|
@ -43,8 +43,6 @@ DECLARE_DEBUG_CHANNEL(toolhelp)
|
||||||
/* Min. number of thunks allocated when creating a new segment */
|
/* Min. number of thunks allocated when creating a new segment */
|
||||||
#define MIN_THUNKS 32
|
#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 };
|
static THHOOK DefaultThhook = { 0 };
|
||||||
THHOOK *pThhook = &DefaultThhook;
|
THHOOK *pThhook = &DefaultThhook;
|
||||||
|
|
|
@ -413,7 +413,7 @@ static void PROCESS_Start( HMODULE main_module, LPCSTR filename )
|
||||||
SIGNAL_Init(); /* reinitialize signal stack */
|
SIGNAL_Init(); /* reinitialize signal stack */
|
||||||
|
|
||||||
/* switch to the new 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 <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#ifdef HAVE_SYS_SYSCALL_H
|
#ifdef HAVE_SYS_SYSCALL_H
|
||||||
# include <sys/syscall.h>
|
# include <sys/syscall.h>
|
||||||
#endif
|
#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)
|
* 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
|
* BuildCallFrom32Regs
|
||||||
|
@ -3269,10 +3174,6 @@ static void BuildCall32( FILE *outfile )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Build the 32-bit large stack callback */
|
|
||||||
|
|
||||||
BuildCallTo32LargeStack( outfile );
|
|
||||||
|
|
||||||
/* Build the register callback function */
|
/* Build the register callback function */
|
||||||
|
|
||||||
BuildCallFrom32Regs( outfile );
|
BuildCallFrom32Regs( outfile );
|
||||||
|
|
Loading…
Reference in New Issue