From 3d06d20bab37ad4e3bd86cbbfe2aeefac7dee2d9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 27 Sep 1999 10:58:45 +0000 Subject: [PATCH] Moved all signal support to a new platform-specific file. Make use of the per-thread signal stack (Juergen Lock). Fixed %fs in signal handler for non FS_sig case (Ulrich Weigand). --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/exception.c | 367 +-------------------- dlls/ntdll/signal_i386.c | 680 +++++++++++++++++++++++++++++++++++++++ graphics/ddraw.c | 8 +- include/debugger.h | 1 - include/dosexe.h | 1 - include/miscemu.h | 4 - include/sig_context.h | 268 --------------- include/wine/exception.h | 2 +- loader/Makefile.in | 1 - loader/main.c | 3 - loader/signal.c | 161 --------- scheduler/process.c | 3 + scheduler/sysdeps.c | 12 +- 14 files changed, 704 insertions(+), 808 deletions(-) create mode 100644 dlls/ntdll/signal_i386.c delete mode 100644 include/sig_context.h delete mode 100644 loader/signal.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 6374ca7311..8a88bdcb8e 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ rtl.c \ rtlstr.c \ sec.c \ + signal_i386.c \ sync.c \ time.c diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index ef578fb7b4..15adadb912 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -12,7 +12,6 @@ #include "global.h" #include "wine/exception.h" #include "stackframe.h" -#include "sig_context.h" #include "miscemu.h" #include "debugtools.h" @@ -25,10 +24,11 @@ typedef struct EXCEPTION_FRAME *prevFrame; } EXC_NESTED_FRAME; + #ifdef __i386__ -# define GET_IP(context) ((LPVOID)EIP_reg(context)) +# define GET_IP(context) ((LPVOID)(context)->Eip) #else -# define GET_IP(context) ((LPVOID)0) +# error You must define GET_IP for this CPU #endif /* __i386__ */ /* Default hook for built-in debugger */ @@ -224,7 +224,7 @@ void WINAPI REGS_FUNC(RtlUnwind)( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip, PEXCEPTION_FRAME frame, dispatch; #ifdef __i386__ - EAX_reg(context) = returnEax; + context->Eax = returnEax; #endif /* build an exception record, if we do not have one */ @@ -343,362 +343,3 @@ void WINAPI DebugBreak16( CONTEXT86 *context ) REGS_FUNC(DebugBreak)( context ); #endif /* defined(__i386__) */ } - - -/*********************************************************************** - * EXC_SaveContext - * - * Set the register values from a sigcontext. - */ -static void EXC_SaveContext( CONTEXT *context, const SIGCONTEXT *sigcontext ) -{ -#ifdef __i386__ - EAX_reg(context) = EAX_sig(sigcontext); - EBX_reg(context) = EBX_sig(sigcontext); - ECX_reg(context) = ECX_sig(sigcontext); - EDX_reg(context) = EDX_sig(sigcontext); - ESI_reg(context) = ESI_sig(sigcontext); - EDI_reg(context) = EDI_sig(sigcontext); - EBP_reg(context) = EBP_sig(sigcontext); - EFL_reg(context) = EFL_sig(sigcontext); - EIP_reg(context) = EIP_sig(sigcontext); - ESP_reg(context) = ESP_sig(sigcontext); - CS_reg(context) = LOWORD(CS_sig(sigcontext)); - DS_reg(context) = LOWORD(DS_sig(sigcontext)); - ES_reg(context) = LOWORD(ES_sig(sigcontext)); - SS_reg(context) = LOWORD(SS_sig(sigcontext)); -#ifdef FS_sig - FS_reg(context) = LOWORD(FS_sig(sigcontext)); -#else - GET_FS( FS_reg(context) ); - FS_reg(context) &= 0xffff; -#endif -#ifdef GS_sig - GS_reg(context) = LOWORD(GS_sig(sigcontext)); -#else - GET_GS( GS_reg(context) ); - GS_reg(context) &= 0xffff; -#endif - if (ISV86(context)) V86BASE(context) = (DWORD)DOSMEM_MemoryBase(0); -#endif /* __i386__ */ -} - - -/*********************************************************************** - * EXC_RestoreContext - * - * Build a sigcontext from the register values. - */ -static void EXC_RestoreContext( const CONTEXT *context, SIGCONTEXT *sigcontext ) -{ -#ifdef __i386__ - EAX_sig(sigcontext) = EAX_reg(context); - EBX_sig(sigcontext) = EBX_reg(context); - ECX_sig(sigcontext) = ECX_reg(context); - EDX_sig(sigcontext) = EDX_reg(context); - ESI_sig(sigcontext) = ESI_reg(context); - EDI_sig(sigcontext) = EDI_reg(context); - EBP_sig(sigcontext) = EBP_reg(context); - EFL_sig(sigcontext) = EFL_reg(context); - EIP_sig(sigcontext) = EIP_reg(context); - ESP_sig(sigcontext) = ESP_reg(context); - CS_sig(sigcontext) = CS_reg(context); - DS_sig(sigcontext) = DS_reg(context); - ES_sig(sigcontext) = ES_reg(context); - SS_sig(sigcontext) = SS_reg(context); -#ifdef FS_sig - FS_sig(sigcontext) = FS_reg(context); -#else - SET_FS( FS_reg(context) ); -#endif -#ifdef GS_sig - GS_sig(sigcontext) = GS_reg(context); -#else - SET_GS( GS_reg(context) ); -#endif -#endif /* __i386__ */ -} - - -/********************************************************************** - * EXC_segv - * - * Handler for SIGSEGV and related errors. - */ -static HANDLER_DEF(EXC_segv) -{ - EXCEPTION_RECORD rec; - CONTEXT context; - - HANDLER_INIT(); - -#if defined(TRAP_sig) && defined(CR2_sig) - /* we want the page-fault case to be fast */ - if (TRAP_sig(HANDLER_CONTEXT) == 14) - if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return; -#endif - - EXC_SaveContext( &context, HANDLER_CONTEXT ); - rec.ExceptionRecord = NULL; - rec.ExceptionFlags = 0; - rec.ExceptionAddress = GET_IP(&context); - rec.NumberParameters = 0; - -#ifdef TRAP_sig - switch(TRAP_sig(HANDLER_CONTEXT)) - { - case 4: /* Overflow exception */ - rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; - break; - case 5: /* Bound range exception */ - rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; - break; - case 6: /* Invalid opcode exception */ - rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; - break; - case 12: /* Stack fault */ - rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; - break; - case 11: /* Segment not present exception */ - case 13: /* General protection fault */ - if (INSTR_EmulateInstruction( &context )) goto restore; - rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; - break; - case 14: /* Page fault */ -#ifdef CR2_sig - rec.NumberParameters = 2; -#ifdef ERROR_sig - rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0; -#else - rec.ExceptionInformation[0] = 0; -#endif /* ERROR_sig */ - rec.ExceptionInformation[1] = CR2_sig(HANDLER_CONTEXT); -#endif /* CR2_sig */ - rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; - break; - case 17: /* Alignment check exception */ - /* FIXME: pass through exception handler first? */ - if (EFL_reg(&context) & 0x00040000) - { - /* Disable AC flag, return */ - EFL_reg(&context) &= ~0x00040000; - goto restore; - } - rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; - break; - default: - ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) ); - /* fall through */ - case 2: /* NMI interrupt */ - case 7: /* Device not available exception */ - case 8: /* Double fault exception */ - case 10: /* Invalid TSS exception */ - case 15: /* Unknown exception */ - case 18: /* Machine check exception */ - case 19: /* Cache flush exception */ - rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; - break; - } -#else /* TRAP_sig */ -# ifdef __i386__ - if (INSTR_EmulateInstruction( &context )) goto restore; -# endif - rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; /* generic error */ -#endif /* TRAP_sig */ - - REGS_FUNC(RtlRaiseException)( &rec, &context ); - restore: - EXC_RestoreContext( &context, HANDLER_CONTEXT ); -} - - -/********************************************************************** - * EXC_trap - * - * Handler for SIGTRAP. - */ -static HANDLER_DEF(EXC_trap) -{ - EXCEPTION_RECORD rec; - CONTEXT context; - - HANDLER_INIT(); - -#ifdef TRAP_sig - rec.ExceptionCode = (TRAP_sig(HANDLER_CONTEXT) == 1) ? - EXCEPTION_SINGLE_STEP : EXCEPTION_BREAKPOINT; -#else - rec.ExceptionCode = EXCEPTION_BREAKPOINT; -#endif /* TRAP_sig */ - - EXC_SaveContext( &context, HANDLER_CONTEXT ); - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = GET_IP(&context); - rec.NumberParameters = 0; - REGS_FUNC(RtlRaiseException)( &rec, &context ); - EXC_RestoreContext( &context, HANDLER_CONTEXT ); -} - - -/*********************************************************************** - * EXC_SaveFPU - * - * Set the FPU context from a sigcontext. - */ -static void inline EXC_SaveFPU( CONTEXT *context, const SIGCONTEXT *sigcontext ) -{ -#ifdef __i386__ -# ifdef FPU_sig - if (FPU_sig(sigcontext)) - { - context->FloatSave = *FPU_sig(sigcontext); - return; - } -# endif /* FPU_sig */ -# ifdef __GNUC__ - __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); -# endif /* __GNUC__ */ -#endif /* __i386__ */ -} - - -/*********************************************************************** - * EXC_RestoreFPU - * - * Restore the FPU context to a sigcontext. - */ -static void inline EXC_RestoreFPU( CONTEXT *context, const SIGCONTEXT *sigcontext ) -{ -#ifdef __i386__ -# ifdef FPU_sig - if (FPU_sig(sigcontext)) - { - *FPU_sig(sigcontext) = context->FloatSave; - return; - } -# endif /* FPU_sig */ -# ifdef __GNUC__ - /* avoid nested exceptions */ - context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80; - __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) ); -# endif /* __GNUC__ */ -#endif /* __i386__ */ -} - - -/********************************************************************** - * EXC_GetFPUCode - * - * Get the FPU exception code from the FPU status. - */ -static inline DWORD EXC_GetFPUCode( const CONTEXT *context ) -{ -#ifdef __i386__ - DWORD status = context->FloatSave.StatusWord; - - if (status & 0x01) /* IE */ - { - if (status & 0x40) /* SF */ - return EXCEPTION_FLT_STACK_CHECK; - else - return EXCEPTION_FLT_INVALID_OPERATION; - } - if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND; /* DE flag */ - if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO; /* ZE flag */ - if (status & 0x08) return EXCEPTION_FLT_OVERFLOW; /* OE flag */ - if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */ - if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */ -#endif /* __i386__ */ - return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ -} - - -/********************************************************************** - * EXC_fpe - * - * Handler for SIGFPE. - */ -static HANDLER_DEF(EXC_fpe) -{ - EXCEPTION_RECORD rec; - CONTEXT context; - - HANDLER_INIT(); - - EXC_SaveFPU( &context, HANDLER_CONTEXT ); - -#ifdef TRAP_sig - switch(TRAP_sig(HANDLER_CONTEXT)) - { - case 0: /* Division by zero exception */ - rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; - break; - case 9: /* Coprocessor segment overrun */ - rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; - break; - case 16: /* Floating point exception */ - rec.ExceptionCode = EXC_GetFPUCode( &context ); - break; - default: - ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) ); - rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; - break; - } -#else /* TRAP_sig */ - rec.ExceptionCode = EXC_GetFPUCode( &context ); -#endif /* TRAP_sig */ - - EXC_SaveContext( &context, HANDLER_CONTEXT ); - rec.ExceptionFlags = 0; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = GET_IP(&context); - rec.NumberParameters = 0; - REGS_FUNC(RtlRaiseException)( &rec, &context ); - EXC_RestoreContext( &context, HANDLER_CONTEXT ); - EXC_RestoreFPU( &context, HANDLER_CONTEXT ); -} - - -/********************************************************************** - * EXC_int - * - * Handler for SIGINT. - */ -static HANDLER_DEF(EXC_int) -{ - EXCEPTION_RECORD rec; - CONTEXT context; - - HANDLER_INIT(); - - EXC_SaveContext( &context, HANDLER_CONTEXT ); - rec.ExceptionCode = CONTROL_C_EXIT; - rec.ExceptionFlags = 0; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = GET_IP(&context); - rec.NumberParameters = 0; - REGS_FUNC(RtlRaiseException)( &rec, &context ); - EXC_RestoreContext( &context, HANDLER_CONTEXT ); -} - - -/********************************************************************** - * EXC_InitHandlers - * - * Initialize the signal handlers for exception handling. - */ -void EXC_InitHandlers(void) -{ - SIGNAL_SetHandler( SIGINT, (void (*)())EXC_int ); - SIGNAL_SetHandler( SIGFPE, (void (*)())EXC_fpe ); - SIGNAL_SetHandler( SIGSEGV, (void (*)())EXC_segv ); - SIGNAL_SetHandler( SIGILL, (void (*)())EXC_segv ); -#ifdef SIGBUS - SIGNAL_SetHandler( SIGBUS, (void (*)())EXC_segv ); -#endif -#ifdef SIGTRAP - SIGNAL_SetHandler( SIGTRAP, (void (*)())EXC_trap ); -#endif - return; -} diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c new file mode 100644 index 0000000000..37e7563669 --- /dev/null +++ b/dlls/ntdll/signal_i386.c @@ -0,0 +1,680 @@ +/* + * i386 signal handling routines + * + * Copyright 1999 Alexandre Julliard + */ + +#ifdef __i386__ + +#include "config.h" + +#include +#include +#include +#include + +#ifdef HAVE_SYS_PARAM_H +# include +#endif +#ifdef HAVE_SYSCALL_H +# include +#else +# ifdef HAVE_SYS_SYSCALL_H +# include +# endif +#endif + +#include "winnt.h" +#include "stackframe.h" +#include "global.h" +#include "miscemu.h" +#include "ntddk.h" +#include "syslevel.h" +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(seh) + +/*********************************************************************** + * signal context platform-specific definitions + */ + +#ifdef linux +typedef struct +{ + unsigned short sc_gs, __gsh; + unsigned short sc_fs, __fsh; + unsigned short sc_es, __esh; + unsigned short sc_ds, __dsh; + unsigned long sc_edi; + unsigned long sc_esi; + unsigned long sc_ebp; + unsigned long sc_esp; + unsigned long sc_ebx; + unsigned long sc_edx; + unsigned long sc_ecx; + unsigned long sc_eax; + unsigned long sc_trapno; + unsigned long sc_err; + unsigned long sc_eip; + unsigned short sc_cs, __csh; + unsigned long sc_eflags; + unsigned long esp_at_signal; + unsigned short sc_ss, __ssh; + unsigned long i387; + unsigned long oldmask; + unsigned long cr2; +} SIGCONTEXT; + +#define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context ) +#define HANDLER_CONTEXT (&__context) + +/* this is the sigaction structure from the Linux 2.1.20 kernel. */ +#undef sa_handler +struct kernel_sigaction +{ + void (*sa_handler)(); + unsigned long sa_mask; + unsigned long sa_flags; + void *sa_restorer; +}; + +/* Similar to the sigaction function in libc, except it leaves alone the + restorer field, which is used to specify the signal stack address */ +static inline int wine_sigaction( int sig, struct kernel_sigaction *new, + struct kernel_sigaction *old ) +{ + __asm__ __volatile__( "pushl %%ebx\n\t" + "movl %2,%%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (sig) + : "0" (SYS_sigaction), "r" (sig), "c" (new), "d" (old) ); + if (sig>=0) return 0; + errno = -sig; + return -1; +} + +#endif /* linux */ + +#ifdef BSDI + +#define EAX_sig(context) ((context)->tf_eax) +#define EBX_sig(context) ((context)->tf_ebx) +#define ECX_sig(context) ((context)->tf_ecx) +#define EDX_sig(context) ((context)->tf_edx) +#define ESI_sig(context) ((context)->tf_esi) +#define EDI_sig(context) ((context)->tf_edi) +#define EBP_sig(context) ((context)->tf_ebp) + +#define CS_sig(context) ((context)->tf_cs) +#define DS_sig(context) ((context)->tf_ds) +#define ES_sig(context) ((context)->tf_es) +#define SS_sig(context) ((context)->tf_ss) + +#include +typedef struct trapframe SIGCONTEXT; + +#define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context ) +#define HANDLER_CONTEXT __context + +#define EFL_sig(context) ((context)->tf_eflags) + +#define EIP_sig(context) (*((unsigned long*)&(context)->tf_eip)) +#define ESP_sig(context) (*((unsigned long*)&(context)->tf_esp)) + +#endif /* bsdi */ + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + +#include +typedef struct sigcontext SIGCONTEXT; + +#define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context ) +#define HANDLER_CONTEXT __context + +#endif /* FreeBSD */ + +#if defined(__svr4__) || defined(_SCO_DS) || defined(__sun) + +#include +#ifdef _SCO_DS +#include +#endif +/* Solaris kludge */ +#undef ERR +#include +#undef ERR +typedef struct ucontext SIGCONTEXT; + +#define HANDLER_DEF(name) void name( int __signal, void *__siginfo, SIGCONTEXT *__context ) +#define HANDLER_CONTEXT __context + +#endif /* svr4 || SCO_DS */ + +#ifdef __EMX__ + +typedef struct +{ + unsigned long ContextFlags; + FLOATING_SAVE_AREA sc_float; + unsigned long sc_gs; + unsigned long sc_fs; + unsigned long sc_es; + unsigned long sc_ds; + unsigned long sc_edi; + unsigned long sc_esi; + unsigned long sc_eax; + unsigned long sc_ebx; + unsigned long sc_ecx; + unsigned long sc_edx; + unsigned long sc_ebp; + unsigned long sc_eip; + unsigned long sc_cs; + unsigned long sc_eflags; + unsigned long sc_esp; + unsigned long sc_ss; +} SIGCONTEXT; + +#endif /* __EMX__ */ + + +#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) \ + || defined(__OpenBSD__) || defined(__EMX__) + +#define EAX_sig(context) ((context)->sc_eax) +#define EBX_sig(context) ((context)->sc_ebx) +#define ECX_sig(context) ((context)->sc_ecx) +#define EDX_sig(context) ((context)->sc_edx) +#define ESI_sig(context) ((context)->sc_esi) +#define EDI_sig(context) ((context)->sc_edi) +#define EBP_sig(context) ((context)->sc_ebp) + +#define CS_sig(context) ((context)->sc_cs) +#define DS_sig(context) ((context)->sc_ds) +#define ES_sig(context) ((context)->sc_es) +#define SS_sig(context) ((context)->sc_ss) + +#ifdef linux +/* FS and GS are now in the sigcontext struct of FreeBSD, but not + * saved by the exception handling. duh. + */ +#define FS_sig(context) ((context)->sc_fs) +#define GS_sig(context) ((context)->sc_gs) +#define CR2_sig(context) ((context)->cr2) +#define TRAP_sig(context) ((context)->sc_trapno) +#define ERROR_sig(context) ((context)->sc_err) +#define FPU_sig(context) ((FLOATING_SAVE_AREA*)((context)->i387)) +#endif + +#ifndef __FreeBSD__ +#define EFL_sig(context) ((context)->sc_eflags) +#else +#define EFL_sig(context) ((context)->sc_efl) +/* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge */ +#define CR2_sig(context) ((context)->sc_err) +#endif + +#define EIP_sig(context) (*((unsigned long*)&(context)->sc_eip)) +#define ESP_sig(context) (*((unsigned long*)&(context)->sc_esp)) + +#endif /* linux || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + +#if defined(__svr4__) || defined(_SCO_DS) || defined(__sun) + +#ifdef _SCO_DS +#define gregs regs +#endif + +#define EAX_sig(context) ((context)->uc_mcontext.gregs[EAX]) +#define EBX_sig(context) ((context)->uc_mcontext.gregs[EBX]) +#define ECX_sig(context) ((context)->uc_mcontext.gregs[ECX]) +#define EDX_sig(context) ((context)->uc_mcontext.gregs[EDX]) +#define ESI_sig(context) ((context)->uc_mcontext.gregs[ESI]) +#define EDI_sig(context) ((context)->uc_mcontext.gregs[EDI]) +#define EBP_sig(context) ((context)->uc_mcontext.gregs[EBP]) + +#define CS_sig(context) ((context)->uc_mcontext.gregs[CS]) +#define DS_sig(context) ((context)->uc_mcontext.gregs[DS]) +#define ES_sig(context) ((context)->uc_mcontext.gregs[ES]) +#define SS_sig(context) ((context)->uc_mcontext.gregs[SS]) + +#define FS_sig(context) ((context)->uc_mcontext.gregs[FS]) +#define GS_sig(context) ((context)->uc_mcontext.gregs[GS]) + +#define EFL_sig(context) ((context)->uc_mcontext.gregs[EFL]) + +#define EIP_sig(context) ((context)->uc_mcontext.gregs[EIP]) +#ifdef R_ESP +#define ESP_sig(context) ((context)->uc_mcontext.gregs[R_ESP]) +#else +#define ESP_sig(context) ((context)->uc_mcontext.gregs[ESP]) +#endif +#ifdef TRAPNO +#define TRAP_sig(context) ((context)->uc_mcontext.gregs[TRAPNO]) +#endif + +#endif /* svr4 || SCO_DS */ + + +extern void WINAPI REGS_FUNC(RtlRaiseException)( EXCEPTION_RECORD *rec, CONTEXT *context ); + + +/*********************************************************************** + * handler_init + * + * Initialization code for a signal handler. + * Restores the proper %fs value for the current thread. + */ +static inline void handler_init( CONTEXT *context, const SIGCONTEXT *sigcontext ) +{ + WORD fs; + /* get %fs at time of the fault */ +#ifdef FS_sig + fs = FS_sig(sigcontext); +#else + GET_FS(fs); +#endif + context->SegFs = fs; + /* now restore a proper %fs for the fault handler */ + if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext))) fs = SYSLEVEL_Win16CurrentTeb; + if (!fs) fs = SYSLEVEL_EmergencyTeb; + SET_FS(fs); +} + + +/*********************************************************************** + * save_context + * + * Set the register values from a sigcontext. + */ +static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext ) +{ + context->Eax = EAX_sig(sigcontext); + context->Ebx = EBX_sig(sigcontext); + context->Ecx = ECX_sig(sigcontext); + context->Edx = EDX_sig(sigcontext); + context->Esi = ESI_sig(sigcontext); + context->Edi = EDI_sig(sigcontext); + context->Ebp = EBP_sig(sigcontext); + context->EFlags = EFL_sig(sigcontext); + context->Eip = EIP_sig(sigcontext); + context->Esp = ESP_sig(sigcontext); + context->SegCs = LOWORD(CS_sig(sigcontext)); + context->SegDs = LOWORD(DS_sig(sigcontext)); + context->SegEs = LOWORD(ES_sig(sigcontext)); + context->SegSs = LOWORD(SS_sig(sigcontext)); + /* %fs already handled in handler_init */ +#ifdef GS_sig + context->SegGs = LOWORD(GS_sig(sigcontext)); +#else + GET_GS( context->SegGs ); + context->SegGs &= 0xffff; +#endif + if (ISV86(context)) V86BASE(context) = (DWORD)DOSMEM_MemoryBase(0); +} + + +/*********************************************************************** + * restore_context + * + * Build a sigcontext from the register values. + */ +static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext ) +{ + EAX_sig(sigcontext) = context->Eax; + EBX_sig(sigcontext) = context->Ebx; + ECX_sig(sigcontext) = context->Ecx; + EDX_sig(sigcontext) = context->Edx; + ESI_sig(sigcontext) = context->Esi; + EDI_sig(sigcontext) = context->Edi; + EBP_sig(sigcontext) = context->Ebp; + EFL_sig(sigcontext) = context->EFlags; + EIP_sig(sigcontext) = context->Eip; + ESP_sig(sigcontext) = context->Esp; + CS_sig(sigcontext) = context->SegCs; + DS_sig(sigcontext) = context->SegDs; + ES_sig(sigcontext) = context->SegEs; + SS_sig(sigcontext) = context->SegSs; +#ifdef FS_sig + FS_sig(sigcontext) = context->SegFs; +#else + SET_FS( context->SegFs ); +#endif +#ifdef GS_sig + GS_sig(sigcontext) = context->SegGs; +#else + SET_GS( context->SegGs ); +#endif +} + + +/*********************************************************************** + * save_fpu + * + * Set the FPU context from a sigcontext. + */ +static void inline save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) +{ +#ifdef FPU_sig + if (FPU_sig(sigcontext)) + { + context->FloatSave = *FPU_sig(sigcontext); + return; + } +#endif /* FPU_sig */ +#ifdef __GNUC__ + __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); +#endif /* __GNUC__ */ +} + + +/*********************************************************************** + * restore_fpu + * + * Restore the FPU context to a sigcontext. + */ +static void inline restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) +{ +#ifdef FPU_sig + if (FPU_sig(sigcontext)) + { + *FPU_sig(sigcontext) = context->FloatSave; + return; + } +#endif /* FPU_sig */ +#ifdef __GNUC__ + /* avoid nested exceptions */ + context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80; + __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) ); +#endif /* __GNUC__ */ +} + + +/********************************************************************** + * get_fpu_code + * + * Get the FPU exception code from the FPU status. + */ +static inline DWORD get_fpu_code( const CONTEXT *context ) +{ + DWORD status = context->FloatSave.StatusWord; + + if (status & 0x01) /* IE */ + { + if (status & 0x40) /* SF */ + return EXCEPTION_FLT_STACK_CHECK; + else + return EXCEPTION_FLT_INVALID_OPERATION; + } + if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND; /* DE flag */ + if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO; /* ZE flag */ + if (status & 0x08) return EXCEPTION_FLT_OVERFLOW; /* OE flag */ + if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */ + if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */ + return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ +} + + +/********************************************************************** + * segv_handler + * + * Handler for SIGSEGV and related errors. + */ +static HANDLER_DEF(segv_handler) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + + handler_init( &context, HANDLER_CONTEXT ); + +#if defined(TRAP_sig) && defined(CR2_sig) + /* we want the page-fault case to be fast */ + if (TRAP_sig(HANDLER_CONTEXT) == 14) + if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return; +#endif + + save_context( &context, HANDLER_CONTEXT ); + rec.ExceptionRecord = NULL; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionAddress = (LPVOID)context.Eip; + rec.NumberParameters = 0; + +#ifdef TRAP_sig + switch(TRAP_sig(HANDLER_CONTEXT)) + { + case 4: /* Overflow exception */ + rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + break; + case 5: /* Bound range exception */ + rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + break; + case 6: /* Invalid opcode exception */ + rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + case 12: /* Stack fault */ + rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; + break; + case 11: /* Segment not present exception */ + case 13: /* General protection fault */ + if (INSTR_EmulateInstruction( &context )) goto restore; + rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; + break; + case 14: /* Page fault */ +#ifdef CR2_sig + rec.NumberParameters = 2; +#ifdef ERROR_sig + rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0; +#else + rec.ExceptionInformation[0] = 0; +#endif /* ERROR_sig */ + rec.ExceptionInformation[1] = CR2_sig(HANDLER_CONTEXT); +#endif /* CR2_sig */ + rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + break; + case 17: /* Alignment check exception */ + /* FIXME: pass through exception handler first? */ + if (context.EFlags & 0x00040000) + { + /* Disable AC flag, return */ + context.EFlags &= ~0x00040000; + goto restore; + } + rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; + break; + default: + ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) ); + /* fall through */ + case 2: /* NMI interrupt */ + case 7: /* Device not available exception */ + case 8: /* Double fault exception */ + case 10: /* Invalid TSS exception */ + case 15: /* Unknown exception */ + case 18: /* Machine check exception */ + case 19: /* Cache flush exception */ + rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; + break; + } +#else /* TRAP_sig */ + if (INSTR_EmulateInstruction( &context )) return; + rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; /* generic error */ +#endif /* TRAP_sig */ + + REGS_FUNC(RtlRaiseException)( &rec, &context ); + restore: + restore_context( &context, HANDLER_CONTEXT ); +} + + +/********************************************************************** + * trap_handler + * + * Handler for SIGTRAP. + */ +static HANDLER_DEF(trap_handler) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + + handler_init( &context, HANDLER_CONTEXT ); + +#ifdef TRAP_sig + rec.ExceptionCode = (TRAP_sig(HANDLER_CONTEXT) == 1) ? + EXCEPTION_SINGLE_STEP : EXCEPTION_BREAKPOINT; +#else + rec.ExceptionCode = EXCEPTION_BREAKPOINT; +#endif /* TRAP_sig */ + + save_context( &context, HANDLER_CONTEXT ); + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Eip; + rec.NumberParameters = 0; + REGS_FUNC(RtlRaiseException)( &rec, &context ); + restore_context( &context, HANDLER_CONTEXT ); +} + + +/********************************************************************** + * fpe_handler + * + * Handler for SIGFPE. + */ +static HANDLER_DEF(fpe_handler) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + + handler_init( &context, HANDLER_CONTEXT ); + + save_fpu( &context, HANDLER_CONTEXT ); + +#ifdef TRAP_sig + switch(TRAP_sig(HANDLER_CONTEXT)) + { + case 0: /* Division by zero exception */ + rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + break; + case 9: /* Coprocessor segment overrun */ + rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + break; + case 16: /* Floating point exception */ + rec.ExceptionCode = get_fpu_code( &context ); + break; + default: + ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) ); + rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + break; + } +#else /* TRAP_sig */ + rec.ExceptionCode = get_fpu_code( &context ); +#endif /* TRAP_sig */ + + save_context( &context, HANDLER_CONTEXT ); + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Eip; + rec.NumberParameters = 0; + REGS_FUNC(RtlRaiseException)( &rec, &context ); + restore_context( &context, HANDLER_CONTEXT ); + restore_fpu( &context, HANDLER_CONTEXT ); +} + + +/********************************************************************** + * int_handler + * + * Handler for SIGINT. + */ +static HANDLER_DEF(int_handler) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + + handler_init( &context, HANDLER_CONTEXT ); + save_context( &context, HANDLER_CONTEXT ); + rec.ExceptionCode = CONTROL_C_EXIT; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Eip; + rec.NumberParameters = 0; + REGS_FUNC(RtlRaiseException)( &rec, &context ); + restore_context( &context, HANDLER_CONTEXT ); +} + + +/*********************************************************************** + * set_handler + * + * Set a signal handler + */ +static int set_handler( int sig, void (*func)() ) +{ +#ifdef linux + struct kernel_sigaction sig_act; + sig_act.sa_handler = func; + sig_act.sa_flags = SA_RESTART | SA_NOMASK; + sig_act.sa_mask = 0; + /* point to the top of the stack */ + sig_act.sa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE; + return wine_sigaction( sig, &sig_act, NULL ); +#else /* linux */ + struct sigaction sig_act; + sig_act.sa_handler = func; + sigemptyset( &sig_act.sa_mask ); + +# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + sig_act.sa_flags = SA_ONSTACK; +# elif defined (__svr4__) || defined(_SCO_DS) + sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; +# elif defined(__EMX__) + sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */ +# else + sig_act.sa_flags = 0; +# endif + return sigaction( sig, &sig_act, NULL ); +#endif /* linux */ +} + + +/********************************************************************** + * SIGNAL_Init + */ +BOOL SIGNAL_Init(void) +{ +#ifdef HAVE_WORKING_SIGALTSTACK + struct sigaltstack ss; + if ((ss.ss_sp = NtCurrentTeb()->signal_stack)) + { + ss.ss_size = SIGNAL_STACK_SIZE; + ss.ss_flags = 0; + if (sigaltstack(&ss, NULL) < 0) + { + perror("sigaltstack"); + /* fall through on error and try it differently */ + } + } +#endif /* HAVE_SIGALTSTACK */ + + /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */ + signal( SIGPIPE, SIG_IGN ); + /* automatic child reaping to avoid zombies */ + signal( SIGCHLD, SIG_IGN ); + + if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error; + if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error; + if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error; + if (set_handler( SIGILL, (void (*)())segv_handler ) == -1) goto error; +#ifdef SIGBUS + if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error; +#endif +#ifdef SIGTRAP + if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error; +#endif + return TRUE; + + error: + perror("sigaction"); + return FALSE; +} + +#endif /* __i386__ */ diff --git a/graphics/ddraw.c b/graphics/ddraw.c index 45a453440e..853bef0268 100644 --- a/graphics/ddraw.c +++ b/graphics/ddraw.c @@ -3516,7 +3516,7 @@ static HRESULT WINAPI DGA_IDirectDrawImpl_SetDisplayMode( TSXF86DGASetViewPort(display,DefaultScreen(display),0,0); #ifdef RESTORE_SIGNALS - EXC_InitHandlers(); + SIGNAL_Init(); #endif return DD_OK; } @@ -3918,7 +3918,7 @@ static HRESULT WINAPI DGA_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 ifac Sleep(1000); TSXF86DGADirectVideo(display,DefaultScreen(display),0); #ifdef RESTORE_SIGNALS - EXC_InitHandlers(); + SIGNAL_Init(); #endif return DD_OK; } @@ -3969,7 +3969,7 @@ static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) { #endif #ifdef RESTORE_SIGNALS - EXC_InitHandlers(); + SIGNAL_Init(); #endif HeapFree(GetProcessHeap(),0,This); return 0; @@ -4958,7 +4958,7 @@ static HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnk depth = DefaultDepthOfScreen(X11DRV_GetXScreen()); _common_depth_to_pixelformat(depth, &((*ilplpDD)->d.directdraw_pixelformat), &((*ilplpDD)->d.screen_pixelformat), NULL); #ifdef RESTORE_SIGNALS - EXC_InitHandlers(); + SIGNAL_Init(); #endif return DD_OK; diff --git a/include/debugger.h b/include/debugger.h index fd11fdafe4..bcbded2e3e 100644 --- a/include/debugger.h +++ b/include/debugger.h @@ -9,7 +9,6 @@ #include /* u_long ... */ #include "windef.h" -#include "sig_context.h" #include "miscemu.h" #define STEP_FLAG 0x100 /* single step flag */ diff --git a/include/dosexe.h b/include/dosexe.h index 9c2700313c..f8e365ffe3 100644 --- a/include/dosexe.h +++ b/include/dosexe.h @@ -10,7 +10,6 @@ #include /* pid_t */ #include "winbase.h" /* for LPSTARTUPINFO32A */ #include "winnt.h" /* for PCONTEXT */ -#include "sig_context.h" typedef struct _DOSSYSTEM { int id; diff --git a/include/miscemu.h b/include/miscemu.h index d6648a6ca0..c91bb59066 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -184,10 +184,6 @@ extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int); /* msdos/xms.c */ extern void WINAPI XMS_Handler(CONTEXT86*); -/* loader/signal.c */ -extern BOOL SIGNAL_Init(void); -extern void SIGNAL_SetHandler( int sig, void (*func)() ); - /* misc/aspi.c */ extern void ASPI_DOS_HandleInt(CONTEXT86 *context); diff --git a/include/sig_context.h b/include/sig_context.h deleted file mode 100644 index 393e0c223c..0000000000 --- a/include/sig_context.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Signal context definitions - * - * Copyright 1995 Alexandre Julliard - */ - -#ifndef __WINE_SIG_CONTEXT_H -#define __WINE_SIG_CONTEXT_H - -#ifdef __i386__ - -#ifdef linux -typedef struct -{ - unsigned short sc_gs, __gsh; - unsigned short sc_fs, __fsh; - unsigned short sc_es, __esh; - unsigned short sc_ds, __dsh; - unsigned long sc_edi; - unsigned long sc_esi; - unsigned long sc_ebp; - unsigned long sc_esp; - unsigned long sc_ebx; - unsigned long sc_edx; - unsigned long sc_ecx; - unsigned long sc_eax; - unsigned long sc_trapno; - unsigned long sc_err; - unsigned long sc_eip; - unsigned short sc_cs, __csh; - unsigned long sc_eflags; - unsigned long esp_at_signal; - unsigned short sc_ss, __ssh; - unsigned long i387; - unsigned long oldmask; - unsigned long cr2; -} SIGCONTEXT; -#define __HAVE_SIGCONTEXT - -#define HANDLER_DEF(name) void name (int signal, SIGCONTEXT __context) -#define HANDLER_CONTEXT (&__context) - -#endif /* linux */ - -#ifdef BSDI - -#define EAX_sig(context) ((context)->tf_eax) -#define EBX_sig(context) ((context)->tf_ebx) -#define ECX_sig(context) ((context)->tf_ecx) -#define EDX_sig(context) ((context)->tf_edx) -#define ESI_sig(context) ((context)->tf_esi) -#define EDI_sig(context) ((context)->tf_edi) -#define EBP_sig(context) ((context)->tf_ebp) - -#define CS_sig(context) ((context)->tf_cs) -#define DS_sig(context) ((context)->tf_ds) -#define ES_sig(context) ((context)->tf_es) -#define SS_sig(context) ((context)->tf_ss) - -#include -typedef struct trapframe SIGCONTEXT; -#define __HAVE_SIGCONTEXT - -#define HANDLER_DEF(name) void name(int signal, int code, SIGCONTEXT *__context) -#define HANDLER_CONTEXT __context - -#define EFL_sig(context) ((context)->tf_eflags) - -#define EIP_sig(context) (*((unsigned long*)&(context)->tf_eip)) -#define ESP_sig(context) (*((unsigned long*)&(context)->tf_esp)) - -#endif /* bsdi */ - -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - -#include -typedef struct sigcontext SIGCONTEXT; -#define __HAVE_SIGCONTEXT - -#define HANDLER_DEF(name) void name(int signal, int code, SIGCONTEXT *__context) -#define HANDLER_CONTEXT __context - -#endif /* FreeBSD */ - -#if defined(__svr4__) || defined(_SCO_DS) || defined(__sun) - -#include -#ifdef _SCO_DS -#include -#endif -/* Solaris kludge */ -#undef ERR -#include -#undef ERR -typedef struct ucontext SIGCONTEXT; -#define __HAVE_SIGCONTEXT - -#define HANDLER_DEF(name) void name(int signal, void *siginfo, SIGCONTEXT *__context) -#define HANDLER_CONTEXT __context - -#endif /* svr4 || SCO_DS */ - -#ifdef __EMX__ -typedef struct _fpreg /* Note 1 */ -{ - ULONG losig; - ULONG hisig; - USHORT signexp; -} FPREG; -typedef FPREG *PFPREG; - -typedef struct _CONTEXT /* Note 1 */ -{ - ULONG ContextFlags; - ULONG ctx_env[7]; - FPREG ctx_stack[8]; - ULONG ctx_SegGs; - ULONG ctx_SegFs; - ULONG ctx_SegEs; - ULONG ctx_SegDs; - ULONG ctx_RegEdi; - ULONG ctx_RegEsi; - ULONG ctx_RegEax; - ULONG ctx_RegEbx; - ULONG ctx_RegEcx; - ULONG ctx_RegEdx; - ULONG ctx_RegEbp; - ULONG ctx_RegEip; - ULONG ctx_SegCs; - ULONG ctx_EFlags; - ULONG ctx_RegEsp; - ULONG ctx_SegSs; -} SIGCONTEXT; -#define __HAVE_SIGCONTEXT -/*typedef CONTEXTRECORD *PCONTEXTRECORD;*/ - -#endif /* __EMX__ */ - - -#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) \ - || defined(__OpenBSD__) - -#define EAX_sig(context) ((context)->sc_eax) -#define EBX_sig(context) ((context)->sc_ebx) -#define ECX_sig(context) ((context)->sc_ecx) -#define EDX_sig(context) ((context)->sc_edx) -#define ESI_sig(context) ((context)->sc_esi) -#define EDI_sig(context) ((context)->sc_edi) -#define EBP_sig(context) ((context)->sc_ebp) - -#define CS_sig(context) ((context)->sc_cs) -#define DS_sig(context) ((context)->sc_ds) -#define ES_sig(context) ((context)->sc_es) -#define SS_sig(context) ((context)->sc_ss) - -#ifdef linux -/* FS and GS are now in the sigcontext struct of FreeBSD, but not - * saved by the exception handling. duh. - */ -#define FS_sig(context) ((context)->sc_fs) -#define GS_sig(context) ((context)->sc_gs) -#define CR2_sig(context) ((context)->cr2) -#define TRAP_sig(context) ((context)->sc_trapno) -#define ERROR_sig(context) ((context)->sc_err) -#define FPU_sig(context) ((FLOATING_SAVE_AREA*)((context)->i387)) -#endif - -#ifndef __FreeBSD__ -#define EFL_sig(context) ((context)->sc_eflags) -#else -#define EFL_sig(context) ((context)->sc_efl) -/* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge */ -#define CR2_sig(context) ((context)->sc_err) -#endif - - -#define EIP_sig(context) (*((unsigned long*)&(context)->sc_eip)) -#define ESP_sig(context) (*((unsigned long*)&(context)->sc_esp)) - -#endif /* linux || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ - -#if defined(__svr4__) || defined(_SCO_DS) || defined(__sun) - -#ifdef _SCO_DS -#define gregs regs -#endif - -#define EAX_sig(context) ((context)->uc_mcontext.gregs[EAX]) -#define EBX_sig(context) ((context)->uc_mcontext.gregs[EBX]) -#define ECX_sig(context) ((context)->uc_mcontext.gregs[ECX]) -#define EDX_sig(context) ((context)->uc_mcontext.gregs[EDX]) -#define ESI_sig(context) ((context)->uc_mcontext.gregs[ESI]) -#define EDI_sig(context) ((context)->uc_mcontext.gregs[EDI]) -#define EBP_sig(context) ((context)->uc_mcontext.gregs[EBP]) - -#define CS_sig(context) ((context)->uc_mcontext.gregs[CS]) -#define DS_sig(context) ((context)->uc_mcontext.gregs[DS]) -#define ES_sig(context) ((context)->uc_mcontext.gregs[ES]) -#define SS_sig(context) ((context)->uc_mcontext.gregs[SS]) - -#define FS_sig(context) ((context)->uc_mcontext.gregs[FS]) -#define GS_sig(context) ((context)->uc_mcontext.gregs[GS]) - -#define EFL_sig(context) ((context)->uc_mcontext.gregs[EFL]) - -#define EIP_sig(context) ((context)->uc_mcontext.gregs[EIP]) -#ifdef R_ESP -#define ESP_sig(context) ((context)->uc_mcontext.gregs[R_ESP]) -#else -#define ESP_sig(context) ((context)->uc_mcontext.gregs[ESP]) -#endif -#ifdef TRAPNO -#define TRAP_sig(context) ((context)->uc_mcontext.gregs[TRAPNO]) -#endif - -#endif /* svr4 || SCO_DS */ - -#ifdef __EMX__ - -#define EAX_sig(context) ((context)->ctx_RegEax) -#define EBX_sig(context) ((context)->ctx_RegEbx) -#define ECX_sig(context) ((context)->ctx_RegEcx) -#define EDX_sig(context) ((context)->ctx_RegEdx) -#define ESI_sig(context) ((context)->ctx_RegEsi) -#define EDI_sig(context) ((context)->ctx_RegEdi) -#define EBP_sig(context) ((context)->ctx_RegEbp) -#define ESP_sig(context) ((context)->ctx_RegEsp) -#define CS_sig(context) ((context)->ctx_SegCs) -#define DS_sig(context) ((context)->ctx_SegDs) -#define ES_sig(context) ((context)->ctx_SegEs) -#define SS_sig(context) ((context)->ctx_SegSs) -#define FS_sig(context) ((context)->ctx_SegFs) -#define GS_sig(context) ((context)->ctx_SegGs) -#define EFL_sig(context) ((context)->ctx_EFlags) -#define EIP_sig(context) ((context)->ctx_RegEip) - -#endif /* __EMX__ */ - -#ifdef FS_sig -#include "syslevel.h" -#define HANDLER_INIT() \ - do { int fs = IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT)) ? \ - FS_sig(HANDLER_CONTEXT) : SYSLEVEL_Win16CurrentTeb; \ - if (!fs) fs = SYSLEVEL_EmergencyTeb; \ - SET_FS(fs); } while (0) -#else -#define HANDLER_INIT() \ - do { int fs; GET_FS(fs); fs &= 0xffff; \ - if (!IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT))) \ - fs = SYSLEVEL_Win16CurrentTeb; \ - if (!fs) fs = SYSLEVEL_EmergencyTeb; \ - SET_FS(fs); } while (0) -#endif - -#else /* __i386__ */ - -#define HANDLER_DEF(name) void name (int signal) -#define HANDLER_INIT() /* nothing */ - -#endif /* __i386__ */ - -#ifndef __HAVE_SIGCONTEXT -/* empty entry for non x86 architectures mostly. */ -typedef DWORD SIGCONTEXT; -#define HANDLER_CONTEXT 0 -#endif - -#endif /* __WINE_SIG_CONTEXT_H */ diff --git a/include/wine/exception.h b/include/wine/exception.h index caa20b83d4..79c437afd2 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -169,7 +169,7 @@ static inline EXCEPTION_FRAME * WINE_UNUSED EXC_pop_frame( EXCEPTION_FRAME *fram typedef DWORD (*DEBUGHOOK)( EXCEPTION_RECORD *, CONTEXT *, BOOL ); extern void EXC_SetDebugEventHook( DEBUGHOOK hook ); extern DEBUGHOOK EXC_GetDebugEventHook(void); -extern void EXC_InitHandlers(void); +extern BOOL SIGNAL_Init(void); #endif #endif /* __WINE_WINE_EXCEPTION_H */ diff --git a/loader/Makefile.in b/loader/Makefile.in index 448f98464c..67d1bd8afc 100644 --- a/loader/Makefile.in +++ b/loader/Makefile.in @@ -15,7 +15,6 @@ C_SRCS = \ pe_image.c \ pe_resource.c \ resource.c \ - signal.c \ task.c GLUE = task.c diff --git a/loader/main.c b/loader/main.c index dea1b95762..a4a6815787 100644 --- a/loader/main.c +++ b/loader/main.c @@ -65,9 +65,6 @@ BOOL MAIN_MainInit(void) /* Initialize syslevel handling */ SYSLEVEL_Init(); - /* Initialize signal handling */ - if (!SIGNAL_Init()) return FALSE; - /* Load the configuration file */ if (!PROFILE_LoadWineIni()) return FALSE; diff --git a/loader/signal.c b/loader/signal.c deleted file mode 100644 index ab67c24180..0000000000 --- a/loader/signal.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Wine signal handling - * - * Copyright 1995 Alexandre Julliard - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef HAVE_SYS_PARAM_H -# include -#endif -#ifdef HAVE_SYSCALL_H -# include -#else -# ifdef HAVE_SYS_SYSCALL_H -# include -# endif -#endif - -#include "winsock.h" -#include "global.h" -#include "options.h" -#include "miscemu.h" -#include "dosexe.h" -#include "thread.h" -#include "wine/exception.h" -#include "debugtools.h" - - -/* Linux sigaction function */ - -#if defined(linux) && defined(__i386__) -/* This is the sigaction structure from the Linux 2.1.20 kernel. */ - -#undef sa_handler -struct kernel_sigaction -{ - void (*sa_handler)(); - unsigned long sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(); -}; - -/* Similar to the sigaction function in libc, except it leaves alone the - restorer field, which is used to specify the signal stack address */ -static inline int wine_sigaction( int sig, struct kernel_sigaction *new, - struct kernel_sigaction *old ) -{ -#ifdef __PIC__ - __asm__ __volatile__( "pushl %%ebx\n\t" - "movl %2,%%ebx\n\t" - "int $0x80\n\t" - "popl %%ebx" - : "=a" (sig) - : "0" (SYS_sigaction), - "r" (sig), - "c" (new), - "d" (old) ); -#else - __asm__ __volatile__( "int $0x80" - : "=a" (sig) - : "0" (SYS_sigaction), - "b" (sig), - "c" (new), - "d" (old) ); -#endif /* __PIC__ */ - if (sig>=0) - return 0; - errno = -sig; - return -1; -} -#endif /* linux && __i386__ */ - -/* Signal stack */ - -static char SIGNAL_Stack[16384]; - - -/********************************************************************** - * SIGNAL_SetHandler - */ -void SIGNAL_SetHandler( int sig, void (*func)() ) -{ - int ret; - -#if defined(linux) && defined(__i386__) - - struct kernel_sigaction sig_act; - sig_act.sa_handler = func; - sig_act.sa_flags = SA_RESTART | SA_NOMASK; - sig_act.sa_mask = 0; - /* Point to the top of the stack, minus 4 just in case, and make - it aligned */ - sig_act.sa_restorer = - (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3); - ret = wine_sigaction( sig, &sig_act, NULL ); - -#else /* linux && __i386__ */ - - struct sigaction sig_act; - sig_act.sa_handler = func; - sigemptyset( &sig_act.sa_mask ); - -# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - sig_act.sa_flags = SA_ONSTACK; -# elif defined (__svr4__) || defined(_SCO_DS) - sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; -# elif defined(__EMX__) - sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */ -# else - sig_act.sa_flags = 0; -# endif - ret = sigaction( sig, &sig_act, NULL ); - -#endif /* linux && __i386__ */ - - if (ret < 0) - { - perror( "sigaction" ); - exit(1); - } -} - - -/********************************************************************** - * SIGNAL_Init - */ -BOOL SIGNAL_Init(void) -{ -#ifdef HAVE_WORKING_SIGALTSTACK - struct sigaltstack ss; - ss.ss_sp = SIGNAL_Stack; - ss.ss_size = sizeof(SIGNAL_Stack); - ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) - { - perror("sigaltstack"); - /* fall through on error and try it differently */ - } -#endif /* HAVE_SIGALTSTACK */ - - /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */ - signal (SIGPIPE, SIG_IGN); - /* automatic child reaping to avoid zombies */ - signal (SIGCHLD, SIG_IGN); - EXC_InitHandlers(); - return TRUE; -} diff --git a/scheduler/process.c b/scheduler/process.c index db423d9793..1e0bb8a7bb 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -362,6 +362,9 @@ BOOL PROCESS_Init(void) if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE; initial_pdb.system_heap = initial_pdb.heap = SystemHeap; + /* Initialize signal handling */ + if (!SIGNAL_Init()) return FALSE; + /* Create the environment DB of the first process */ if (!PROCESS_CreateEnvDB()) return FALSE; diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c index 6086a38518..c9ea1b0e9a 100644 --- a/scheduler/sysdeps.c +++ b/scheduler/sysdeps.c @@ -28,6 +28,7 @@ static int *ph_errno = &h_errno; #include "thread.h" #include "server.h" #include "winbase.h" +#include "wine/exception.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(thread) @@ -130,7 +131,16 @@ static void SYSDEPS_StartThread( TEB *teb ) { SYSDEPS_SetCurThread( teb ); CLIENT_InitThread(); - teb->startup(); + SIGNAL_Init(); + __TRY + { + teb->startup(); + } + __EXCEPT(UnhandledExceptionFilter) + { + TerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY SYSDEPS_ExitThread(); /* should never get here */ }