Commit 9968d849 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Use standard siginfo signal handlers on all platforms.

parent 3d7eb3d4
......@@ -69,11 +69,6 @@ static pthread_key_t teb_key;
*/
#ifdef linux
typedef struct ucontext SIGCONTEXT;
# define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
# define HANDLER_CONTEXT (__context)
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
......@@ -104,15 +99,7 @@ typedef struct ucontext SIGCONTEXT;
#ifdef __APPLE__
# include <sys/ucontext.h>
# include <sys/types.h>
typedef siginfo_t siginfo;
typedef struct ucontext SIGCONTEXT;
# define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context )
# define HANDLER_CONTEXT (__context)
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
......@@ -180,7 +167,7 @@ static inline int dispatch_signal(unsigned int sig)
*
* Set the register values from a sigcontext.
*/
static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
{
#define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
......@@ -211,7 +198,7 @@ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
*
* Build a sigcontext from the register values.
*/
static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
{
#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
......@@ -241,7 +228,7 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
*
* Set the FPU context from a sigcontext.
*/
static inline void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
static inline void save_fpu( CONTEXT *context, const ucontext_t *sigcontext )
{
#define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
......@@ -258,7 +245,7 @@ static inline void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
*
* Restore the FPU context to a sigcontext.
*/
static inline void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
static inline void restore_fpu( CONTEXT *context, const ucontext_t *sigcontext )
{
#define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
......@@ -694,37 +681,44 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
/**********************************************************************
* do_segv
* segv_handler
*
* Implementation of SIGSEGV handler.
* Handler for SIGSEGV and related errors.
*/
static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr )
static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, sigcontext );
rec.ExceptionRecord = NULL;
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionAddress = addr;
rec.ExceptionAddress = (LPVOID)context.Iar;
rec.NumberParameters = 0;
switch (trap) {
switch (signal)
{
case SIGSEGV:
switch ( code & 0xffff ) {
switch (siginfo->si_code & 0xffff)
{
case SEGV_MAPERR:
case SEGV_ACCERR:
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = 0; /* FIXME ? */
rec.ExceptionInformation[1] = (ULONG_PTR)addr;
if (!(rec.ExceptionCode = virtual_handle_fault(addr, rec.ExceptionInformation[0])))
return;
rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0])))
goto done;
break;
default:FIXME("Unhandled SIGSEGV/%x\n",code);
default:
FIXME("Unhandled SIGSEGV/%x\n",siginfo->si_code);
break;
}
break;
case SIGBUS:
switch ( code & 0xffff ) {
switch (siginfo->si_code & 0xffff)
{
case BUS_ADRALN:
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break;
......@@ -736,17 +730,19 @@ static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr
/* FIXME: correct for all cases ? */
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = 0; /* FIXME ? */
rec.ExceptionInformation[1] = (ULONG_PTR)addr;
if (!(rec.ExceptionCode = virtual_handle_fault(addr, rec.ExceptionInformation[0])))
return;
rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0])))
goto done;
break;
#endif
default:FIXME("Unhandled SIGBUS/%x\n",code);
default:
FIXME("Unhandled SIGBUS/%x\n",siginfo->si_code);
break;
}
break;
case SIGILL:
switch ( code & 0xffff ) {
switch (siginfo->si_code & 0xffff)
{
case ILL_ILLOPC: /* illegal opcode */
#ifdef ILL_ILLOPN
case ILL_ILLOPN: /* illegal operand */
......@@ -773,32 +769,39 @@ static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr
rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
break;
#endif
default:FIXME("Unhandled SIGILL/%x\n", code);
default:
FIXME("Unhandled SIGILL/%x\n", siginfo->si_code);
break;
}
break;
}
status = raise_exception( &rec, context, TRUE );
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
done:
restore_context( &context, sigcontext );
}
/**********************************************************************
* do_trap
* trap_handler
*
* Implementation of SIGTRAP handler.
* Handler for SIGTRAP.
*/
static void do_trap( CONTEXT *context, int code, void * addr )
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, sigcontext );
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
rec.ExceptionAddress = addr;
rec.ExceptionAddress = (LPVOID)context.Iar;
rec.NumberParameters = 0;
/* FIXME: check if we might need to modify PC */
switch (code & 0xffff) {
switch (siginfo->si_code & 0xffff)
{
#ifdef TRAP_BRKPT
case TRAP_BRKPT:
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
......@@ -809,24 +812,31 @@ static void do_trap( CONTEXT *context, int code, void * addr )
rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
break;
#endif
default:FIXME("Unhandled SIGTRAP/%x\n", code);
default:
FIXME("Unhandled SIGTRAP/%x\n", siginfo->si_code);
break;
}
status = raise_exception( &rec, context, TRUE );
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, sigcontext );
}
/**********************************************************************
* do_trap
* fpe_handler
*
* Implementation of SIGFPE handler.
* Handler for SIGFPE.
*/
static void do_fpe( CONTEXT *context, int code, void * addr )
static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
switch ( code & 0xffff ) {
save_fpu( &context, sigcontext );
save_context( &context, sigcontext );
switch (siginfo->si_code & 0xffff )
{
#ifdef FPE_FLTSUB
case FPE_FLTSUB:
rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
......@@ -871,51 +881,13 @@ static void do_fpe( CONTEXT *context, int code, void * addr )
}
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
rec.ExceptionAddress = addr;
rec.ExceptionAddress = (LPVOID)context.Iar;
rec.NumberParameters = 0;
status = raise_exception( &rec, context, TRUE );
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
}
/**********************************************************************
* segv_handler
*
* Handler for SIGSEGV and related errors.
*/
static HANDLER_DEF(segv_handler)
{
CONTEXT context;
save_context( &context, HANDLER_CONTEXT );
do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr );
restore_context( &context, HANDLER_CONTEXT );
}
/**********************************************************************
* trap_handler
*
* Handler for SIGTRAP.
*/
static HANDLER_DEF(trap_handler)
{
CONTEXT context;
save_context( &context, HANDLER_CONTEXT );
do_trap( &context, __siginfo->si_code, __siginfo->si_addr );
restore_context( &context, HANDLER_CONTEXT );
}
/**********************************************************************
* fpe_handler
*
* Handler for SIGFPE.
*/
static HANDLER_DEF(fpe_handler)
{
CONTEXT context;
save_fpu( &context, HANDLER_CONTEXT );
save_context( &context, HANDLER_CONTEXT );
do_fpe( &context, __siginfo->si_code, __siginfo->si_addr );
restore_context( &context, HANDLER_CONTEXT );
restore_fpu( &context, HANDLER_CONTEXT );
restore_context( &context, sigcontext );
restore_fpu( &context, sigcontext );
}
/**********************************************************************
......@@ -923,7 +895,7 @@ static HANDLER_DEF(fpe_handler)
*
* Handler for SIGINT.
*/
static HANDLER_DEF(int_handler)
static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
if (!dispatch_signal(SIGINT))
{
......@@ -931,7 +903,7 @@ static HANDLER_DEF(int_handler)
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, sigcontext );
rec.ExceptionCode = CONTROL_C_EXIT;
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
......@@ -939,7 +911,7 @@ static HANDLER_DEF(int_handler)
rec.NumberParameters = 0;
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, sigcontext );
}
}
......@@ -949,13 +921,13 @@ static HANDLER_DEF(int_handler)
*
* Handler for SIGABRT.
*/
static HANDLER_DEF(abrt_handler)
static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, sigcontext );
rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionRecord = NULL;
......@@ -963,7 +935,7 @@ static HANDLER_DEF(abrt_handler)
rec.NumberParameters = 0;
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, sigcontext );
}
......@@ -972,7 +944,7 @@ static HANDLER_DEF(abrt_handler)
*
* Handler for SIGQUIT.
*/
static HANDLER_DEF(quit_handler)
static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
abort_thread(0);
}
......@@ -983,13 +955,13 @@ static HANDLER_DEF(quit_handler)
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
CONTEXT context;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, sigcontext );
wait_suspend( &context );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, sigcontext );
}
......@@ -1007,22 +979,6 @@ size_t get_signal_stack_total_size(void)
/***********************************************************************
* set_handler
*
* Set a signal handler
*/
static int set_handler( int sig, void (*func)() )
{
struct sigaction sig_act;
sig_act.sa_sigaction = func;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
return sigaction( sig, &sig_act, NULL );
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
......@@ -1055,18 +1011,32 @@ void signal_init_thread( TEB *teb )
*/
void signal_init_process(void)
{
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;
if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
struct sigaction sig_act;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
sig_act.sa_sigaction = int_handler;
if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = fpe_handler;
if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = abrt_handler;
if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = quit_handler;
if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = usr1_handler;
if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = segv_handler;
if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error;
if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error;
#ifdef SIGBUS
if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error;
if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
#endif
#ifdef SIGTRAP
if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
sig_act.sa_sigaction = trap_handler;
if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
#endif
return;
......
......@@ -48,9 +48,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
static pthread_key_t teb_key;
#define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, ucontext_t *__context )
#define HANDLER_CONTEXT (__context)
typedef int (*wine_signal_handler)(unsigned int sig);
static wine_signal_handler handlers[256];
......@@ -449,7 +446,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
*
* Handler for SIGSEGV.
*/
static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void segv_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
......@@ -479,7 +476,7 @@ static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGBUS.
*/
static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void bus_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
......@@ -506,7 +503,7 @@ static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGILL.
*/
static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void ill_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
......@@ -548,7 +545,7 @@ static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGTRAP.
*/
static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void trap_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
......@@ -581,7 +578,7 @@ static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGFPE.
*/
static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void fpe_handler( int signal, siginfo_t *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
......@@ -634,7 +631,7 @@ static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGINT.
*/
static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
static void int_handler( int signal, siginfo_t *info, void *ucontext )
{
if (!dispatch_signal(SIGINT))
{
......@@ -659,13 +656,13 @@ static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
*
* Handler for SIGABRT.
*/
static HANDLER_DEF(abrt_handler)
static void abrt_handler( int signal, struct siginfo *info, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionRecord = NULL;
......@@ -673,7 +670,7 @@ static HANDLER_DEF(abrt_handler)
rec.NumberParameters = 0;
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
......@@ -682,7 +679,7 @@ static HANDLER_DEF(abrt_handler)
*
* Handler for SIGQUIT.
*/
static HANDLER_DEF(quit_handler)
static void quit_handler( int signal, struct siginfo *info, void *ucontext )
{
abort_thread(0);
}
......@@ -693,13 +690,13 @@ static HANDLER_DEF(quit_handler)
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
static void usr1_handler( int signal, struct siginfo *info, void *ucontext )
{
CONTEXT context;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
wait_suspend( &context );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
......@@ -717,23 +714,6 @@ size_t get_signal_stack_total_size(void)
/***********************************************************************
* set_handler
*
* Set a signal handler
*/
static int set_handler( int sig, void (*func)() )
{
struct sigaction sig_act;
sig_act.sa_sigaction = func;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_SIGINFO;
return sigaction( sig, &sig_act, NULL );
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
......@@ -766,15 +746,34 @@ void signal_init_thread( TEB *teb )
*/
void signal_init_process(void)
{
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 (*)())ill_handler ) == -1) goto error;
if (set_handler( SIGBUS, (void (*)())bus_handler ) == -1) goto error;
if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
struct sigaction sig_act;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
sig_act.sa_sigaction = int_handler;
if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = fpe_handler;
if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = abrt_handler;
if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = quit_handler;
if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = usr1_handler;
if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = segv_handler;
if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error;
if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error;
#ifdef SIGBUS
if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
#endif
#ifdef SIGTRAP
sig_act.sa_sigaction = trap_handler;
if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
#endif
/* 'ta 6' tells the kernel to synthesize any unaligned accesses this
process makes, instead of just signalling an error and terminating
the process. wine-devel did not reach a conclusion on whether
......
......@@ -60,11 +60,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
#include <asm/prctl.h>
extern int arch_prctl(int func, void *ptr);
typedef struct ucontext SIGCONTEXT;
# define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
# define HANDLER_CONTEXT (__context)
#define RAX_sig(context) ((context)->uc_mcontext.gregs[REG_RAX])
#define RBX_sig(context) ((context)->uc_mcontext.gregs[REG_RBX])
#define RCX_sig(context) ((context)->uc_mcontext.gregs[REG_RCX])
......@@ -93,9 +88,6 @@ typedef struct ucontext SIGCONTEXT;
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
#define FAULT_CODE (__siginfo->si_code)
#define FAULT_ADDRESS (__siginfo->si_addr)
#endif /* linux */
#if defined(__NetBSD__)
......@@ -103,8 +95,6 @@ typedef struct ucontext SIGCONTEXT;
# include <sys/types.h>
# include <signal.h>
typedef ucontext_t SIGCONTEXT;
#define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
#define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
#define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
......@@ -136,12 +126,6 @@ typedef ucontext_t SIGCONTEXT;
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define FAULT_CODE (__siginfo->si_code)
#define FAULT_ADDRESS (__siginfo->si_addr)
#define HANDLER_DEF(name) void name( int __signal, siginfo_t *__siginfo, SIGCONTEXT *__context )
#define HANDLER_CONTEXT (__context)
#define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
#endif /* __NetBSD__ */
......@@ -187,7 +171,7 @@ static inline int dispatch_signal(unsigned int sig)
*
* Set the register values from a sigcontext.
*/
static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
{
context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
context->Rax = RAX_sig(sigcontext);
......@@ -228,7 +212,7 @@ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
*
* Build a sigcontext from the register values.
*/
static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
{
RAX_sig(sigcontext) = context->Rax;
RCX_sig(sigcontext) = context->Rcx;
......@@ -562,20 +546,21 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
*
* Handler for SIGSEGV and related errors.
*/
static HANDLER_DEF(segv_handler)
static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
ucontext_t *ucontext = sigcontext;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionRecord = NULL;
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionAddress = (LPVOID)context.Rip;
rec.NumberParameters = 0;
switch(TRAP_sig(HANDLER_CONTEXT))
switch(TRAP_sig(ucontext))
{
case TRAP_x86_OFLOW: /* Overflow exception */
rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
......@@ -592,24 +577,22 @@ static HANDLER_DEF(segv_handler)
case TRAP_x86_SEGNPFLT: /* Segment not present exception */
case TRAP_x86_PROTFLT: /* General protection fault */
case TRAP_x86_UNKNOWN: /* Unknown fault code */
rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
rec.ExceptionCode = ERROR_sig(ucontext) ? EXCEPTION_ACCESS_VIOLATION
: EXCEPTION_PRIV_INSTRUCTION;
break;
case TRAP_x86_PAGEFLT: /* Page fault */
rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
#ifdef FAULT_ADDRESS
rec.NumberParameters = 2;
rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
if (!(rec.ExceptionCode = virtual_handle_fault( FAULT_ADDRESS, rec.ExceptionInformation[0] )))
rec.ExceptionInformation[0] = (ERROR_sig(ucontext) & 2) != 0;
rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
if (!(rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, rec.ExceptionInformation[0] )))
goto done;
#endif
break;
case TRAP_x86_ALIGNFLT: /* Alignment check exception */
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break;
default:
ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
ERR( "Got unexpected trap %ld\n", TRAP_sig(ucontext) );
/* fall through */
case TRAP_x86_NMI: /* NMI interrupt */
case TRAP_x86_DNA: /* Device not available exception */
......@@ -624,7 +607,7 @@ static HANDLER_DEF(segv_handler)
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
done:
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
/**********************************************************************
......@@ -632,23 +615,24 @@ done:
*
* Handler for SIGTRAP.
*/
static HANDLER_DEF(trap_handler)
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
ucontext_t *ucontext = sigcontext;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
rec.ExceptionAddress = (LPVOID)context.Rip;
rec.NumberParameters = 0;
switch(FAULT_CODE)
switch (siginfo->si_code)
{
case TRAP_TRACE: /* Single-step exception */
rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
EFL_sig(HANDLER_CONTEXT) &= ~0x100; /* clear single-step flag */
EFL_sig(ucontext) &= ~0x100; /* clear single-step flag */
break;
case TRAP_BRKPT: /* Breakpoint exception */
rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */
......@@ -660,7 +644,7 @@ static HANDLER_DEF(trap_handler)
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
/**********************************************************************
......@@ -668,19 +652,19 @@ static HANDLER_DEF(trap_handler)
*
* Handler for SIGFPE.
*/
static HANDLER_DEF(fpe_handler)
static void fpe_handler( int signal, siginfo_t *siginfo, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
rec.ExceptionAddress = (LPVOID)context.Rip;
rec.NumberParameters = 0;
switch (FAULT_CODE)
switch (siginfo->si_code)
{
case FPE_FLTSUB:
rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
......@@ -711,7 +695,7 @@ static HANDLER_DEF(fpe_handler)
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
/**********************************************************************
......@@ -719,7 +703,7 @@ static HANDLER_DEF(fpe_handler)
*
* Handler for SIGINT.
*/
static HANDLER_DEF(int_handler)
static void int_handler( int signal, siginfo_t *siginfo, void *ucontext )
{
if (!dispatch_signal(SIGINT))
{
......@@ -727,7 +711,7 @@ static HANDLER_DEF(int_handler)
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionCode = CONTROL_C_EXIT;
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
......@@ -735,7 +719,7 @@ static HANDLER_DEF(int_handler)
rec.NumberParameters = 0;
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
}
......@@ -745,13 +729,13 @@ static HANDLER_DEF(int_handler)
*
* Handler for SIGABRT.
*/
static HANDLER_DEF(abrt_handler)
static void abrt_handler( int signal, siginfo_t *siginfo, void *ucontext )
{
EXCEPTION_RECORD rec;
CONTEXT context;
NTSTATUS status;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionRecord = NULL;
......@@ -759,7 +743,7 @@ static HANDLER_DEF(abrt_handler)
rec.NumberParameters = 0;
status = raise_exception( &rec, &context, TRUE );
if (status) raise_status( status, &rec );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
......@@ -768,7 +752,7 @@ static HANDLER_DEF(abrt_handler)
*
* Handler for SIGQUIT.
*/
static HANDLER_DEF(quit_handler)
static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext )
{
abort_thread(0);
}
......@@ -779,13 +763,13 @@ static HANDLER_DEF(quit_handler)
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
{
CONTEXT context;
save_context( &context, HANDLER_CONTEXT );
save_context( &context, ucontext );
wait_suspend( &context );
restore_context( &context, HANDLER_CONTEXT );
restore_context( &context, ucontext );
}
......@@ -803,22 +787,6 @@ size_t get_signal_stack_total_size(void)
/***********************************************************************
* set_handler
*
* Set a signal handler
*/
static int set_handler( int sig, void (*func)() )
{
struct sigaction sig_act;
sig_act.sa_sigaction = func;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
return sigaction( sig, &sig_act, NULL );
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
......@@ -847,18 +815,32 @@ void signal_init_thread( TEB *teb )
*/
void signal_init_process(void)
{
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;
if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
struct sigaction sig_act;
sig_act.sa_mask = server_block_set;
sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
sig_act.sa_sigaction = int_handler;
if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = fpe_handler;
if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = abrt_handler;
if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = quit_handler;
if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = usr1_handler;
if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error;
sig_act.sa_sigaction = segv_handler;
if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error;
if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error;
#ifdef SIGBUS
if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error;
if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
#endif
#ifdef SIGTRAP
if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
sig_act.sa_sigaction = trap_handler;
if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
#endif
return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment