diff --git a/include/callback.h b/include/callback.h index 75603d3c93e..df369eb424d 100644 --- a/include/callback.h +++ b/include/callback.h @@ -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 ); diff --git a/loader/task.c b/loader/task.c index 693d3eca275..7ba3c2011d0 100644 --- a/loader/task.c +++ b/loader/task.c @@ -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; diff --git a/scheduler/process.c b/scheduler/process.c index c189b9ca557..861c0440e02 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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 ); } diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c index 9e74f822fed..e3f0b056093 100644 --- a/scheduler/sysdeps.c +++ b/scheduler/sysdeps.c @@ -16,6 +16,7 @@ static int *ph_errno = &h_errno; #include #include #include +#include #ifdef HAVE_SYS_SYSCALL_H # include #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) * diff --git a/tools/build.c b/tools/build.c index a42f8f16832..4b7cdfb5df3 100644 --- a/tools/build.c +++ b/tools/build.c @@ -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 );