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

Enable exception dispatch while on large stack.
This commit is contained in:
Ulrich Weigand 2000-06-04 01:35:43 +00:00 committed by Alexandre Julliard
parent 66331a73c0
commit 7e85ea7c86
5 changed files with 103 additions and 109 deletions

View File

@ -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 );

View File

@ -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;

View File

@ -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 );
}

View File

@ -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)
*

View File

@ -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 );