2 * PowerPC signal handling routines
4 * Copyright 2002 Marcus Meissner, SuSE Linux AG
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
34 #ifdef HAVE_SYS_PARAM_H
35 # include <sys/param.h>
40 # ifdef HAVE_SYS_SYSCALL_H
41 # include <sys/syscall.h>
45 #ifdef HAVE_SYS_VM86_H
46 # include <sys/vm86.h>
49 #ifdef HAVE_SYS_SIGNAL_H
50 # include <sys/signal.h>
57 #include "wine/library.h"
58 #include "wine/exception.h"
59 #include "selectors.h"
61 #include "ntdll_misc.h"
63 #include "wine/debug.h"
65 WINE_DEFAULT_DEBUG_CHANNEL(seh);
68 /***********************************************************************
69 * signal context platform-specific definitions
73 typedef struct ucontext SIGCONTEXT;
75 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
76 # define HANDLER_CONTEXT (__context)
78 /* All Registers access - only for local access */
79 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
82 /* Gpr Registers access */
83 # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
85 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
86 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
87 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
89 # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
90 # define LR_sig(context) REG_sig(link, context) /* Link register */
91 # define CR_sig(context) REG_sig(ccr, context) /* Condition register */
93 /* Float Registers access */
94 # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
96 # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
98 /* Exception Registers access */
99 # define DAR_sig(context) REG_sig(dar, context)
100 # define DSISR_sig(context) REG_sig(dsisr, context)
101 # define TRAP_sig(context) REG_sig(trap, context)
107 # include <sys/ucontext.h>
109 # include <sys/types.h>
111 typedef siginfo_t siginfo;
113 typedef struct ucontext SIGCONTEXT;
116 # define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context )
117 # define HANDLER_CONTEXT (__context)
119 /* All Registers access - only for local access */
120 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
121 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
122 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
123 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
125 /* Gpr Registers access */
126 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
128 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
129 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
130 # define CTR_sig(context) REG_sig(ctr, context)
132 # define XER_sig(context) REG_sig(xer, context) /* Link register */
133 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
134 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
136 /* Float Registers access */
137 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
139 # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
141 /* Exception Registers access */
142 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
143 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
144 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
146 /* Signal defs : Those are undefined on darwin
163 #endif /* __APPLE__ */
167 typedef int (*wine_signal_handler)(unsigned int sig);
169 static wine_signal_handler handlers[256];
171 extern void WINAPI EXC_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
173 /***********************************************************************
176 inline static int dispatch_signal(unsigned int sig)
178 if (handlers[sig] == NULL) return 0;
179 return handlers[sig](sig);
182 /***********************************************************************
185 * Set the register values from a sigcontext.
187 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
190 #define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
191 /* Save Gpr registers */
192 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
193 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
194 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
198 context->Iar = IAR_sig(sigcontext); /* Program Counter */
199 context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */
200 context->Ctr = CTR_sig(sigcontext);
202 context->Xer = XER_sig(sigcontext);
203 context->Lr = LR_sig(sigcontext);
204 context->Cr = CR_sig(sigcontext);
206 /* Saving Exception regs */
207 context->Dar = DAR_sig(sigcontext);
208 context->Dsisr = DSISR_sig(sigcontext);
209 context->Trap = TRAP_sig(sigcontext);
213 /***********************************************************************
216 * Build a sigcontext from the register values.
218 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
221 #define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
222 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
223 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
224 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
228 IAR_sig(sigcontext) = context->Iar; /* Program Counter */
229 MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */
230 CTR_sig(sigcontext) = context->Ctr;
232 XER_sig(sigcontext) = context->Xer;
233 LR_sig(sigcontext) = context->Lr;
234 CR_sig(sigcontext) = context->Cr;
236 /* Setting Exception regs */
237 DAR_sig(sigcontext) = context->Dar;
238 DSISR_sig(sigcontext) = context->Dsisr;
239 TRAP_sig(sigcontext) = context->Trap;
243 /***********************************************************************
246 * Set the FPU context from a sigcontext.
248 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
250 #define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
251 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
252 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
253 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
256 context->Fpscr = FPSCR_sig(sigcontext);
260 /***********************************************************************
263 * Restore the FPU context to a sigcontext.
265 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
267 #define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
268 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
269 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
270 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
273 FPSCR_sig(sigcontext) = context->Fpscr;
277 /**********************************************************************
280 * Get the FPU exception code from the FPU status.
282 static inline DWORD get_fpu_code( const CONTEXT *context )
284 DWORD status = context->Fpscr;
286 if (status & 0x01) /* IE */
288 if (status & 0x40) /* SF */
289 return EXCEPTION_FLT_STACK_CHECK;
291 return EXCEPTION_FLT_INVALID_OPERATION;
293 if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND; /* DE flag */
294 if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO; /* ZE flag */
295 if (status & 0x08) return EXCEPTION_FLT_OVERFLOW; /* OE flag */
296 if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */
297 if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */
298 return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */
301 /**********************************************************************
304 * Implementation of SIGSEGV handler.
306 static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr )
308 EXCEPTION_RECORD rec;
309 DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
311 rec.ExceptionRecord = NULL;
312 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
313 rec.ExceptionAddress = addr;
314 rec.NumberParameters = 0;
318 switch ( code & 0xffff ) {
321 rec.NumberParameters = 2;
322 rec.ExceptionInformation[0] = 0; /* FIXME ? */
323 rec.ExceptionInformation[1] = (DWORD)addr;
324 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
326 rec.ExceptionCode = page_fault_code;
328 default:FIXME("Unhandled SIGSEGV/%x\n",code);
333 switch ( code & 0xffff ) {
335 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
342 /* FIXME: correct for all cases ? */
343 rec.NumberParameters = 2;
344 rec.ExceptionInformation[0] = 0; /* FIXME ? */
345 rec.ExceptionInformation[1] = (DWORD)addr;
346 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
348 rec.ExceptionCode = page_fault_code;
351 default:FIXME("Unhandled SIGBUS/%x\n",code);
356 switch ( code & 0xffff ) {
357 case ILL_ILLOPC: /* illegal opcode */
359 case ILL_ILLOPN: /* illegal operand */
362 case ILL_ILLADR: /* illegal addressing mode */
365 case ILL_ILLTRP: /* illegal trap */
368 case ILL_COPROC: /* coprocessor error */
370 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
372 case ILL_PRVOPC: /* privileged opcode */
374 case ILL_PRVREG: /* privileged register */
376 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
379 case ILL_BADSTK: /* internal stack error */
380 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
383 default:FIXME("Unhandled SIGILL/%x\n", code);
388 EXC_RtlRaiseException( &rec, context );
391 /**********************************************************************
394 * Implementation of SIGTRAP handler.
396 static void do_trap( CONTEXT *context, int code, void * addr )
398 EXCEPTION_RECORD rec;
400 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
401 rec.ExceptionRecord = NULL;
402 rec.ExceptionAddress = addr;
403 rec.NumberParameters = 0;
405 /* FIXME: check if we might need to modify PC */
406 switch (code & 0xffff) {
409 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
414 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
417 default:FIXME("Unhandled SIGTRAP/%x\n", code);
420 EXC_RtlRaiseException( &rec, context );
423 /**********************************************************************
426 * Implementation of SIGFPE handler.
428 static void do_fpe( CONTEXT *context, int code, void * addr )
430 EXCEPTION_RECORD rec;
432 switch ( code & 0xffff ) {
435 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
440 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
445 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
450 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
455 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
460 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
465 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
472 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
475 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
476 rec.ExceptionRecord = NULL;
477 rec.ExceptionAddress = addr;
478 rec.NumberParameters = 0;
479 EXC_RtlRaiseException( &rec, context );
482 /**********************************************************************
485 * Handler for SIGSEGV and related errors.
487 static HANDLER_DEF(segv_handler)
490 save_context( &context, HANDLER_CONTEXT );
491 do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr );
492 restore_context( &context, HANDLER_CONTEXT );
495 /**********************************************************************
498 * Handler for SIGTRAP.
500 static HANDLER_DEF(trap_handler)
503 save_context( &context, HANDLER_CONTEXT );
504 do_trap( &context, __siginfo->si_code, __siginfo->si_addr );
505 restore_context( &context, HANDLER_CONTEXT );
508 /**********************************************************************
511 * Handler for SIGFPE.
513 static HANDLER_DEF(fpe_handler)
516 save_fpu( &context, HANDLER_CONTEXT );
517 save_context( &context, HANDLER_CONTEXT );
518 do_fpe( &context, __siginfo->si_code, __siginfo->si_addr );
519 restore_context( &context, HANDLER_CONTEXT );
520 restore_fpu( &context, HANDLER_CONTEXT );
523 /**********************************************************************
526 * Handler for SIGINT.
528 static HANDLER_DEF(int_handler)
530 if (!dispatch_signal(SIGINT))
532 EXCEPTION_RECORD rec;
535 save_context( &context, HANDLER_CONTEXT );
536 rec.ExceptionCode = CONTROL_C_EXIT;
537 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
538 rec.ExceptionRecord = NULL;
539 rec.ExceptionAddress = (LPVOID)context.Iar;
540 rec.NumberParameters = 0;
541 EXC_RtlRaiseException( &rec, &context );
542 restore_context( &context, HANDLER_CONTEXT );
547 /**********************************************************************
550 * Handler for SIGABRT.
552 static HANDLER_DEF(abrt_handler)
554 EXCEPTION_RECORD rec;
557 save_context( &context, HANDLER_CONTEXT );
558 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
559 rec.ExceptionFlags = EH_NONCONTINUABLE;
560 rec.ExceptionRecord = NULL;
561 rec.ExceptionAddress = (LPVOID)context.Iar;
562 rec.NumberParameters = 0;
563 EXC_RtlRaiseException( &rec, &context ); /* Should never return.. */
564 restore_context( &context, HANDLER_CONTEXT );
568 /**********************************************************************
571 * Handler for SIGTERM.
573 static HANDLER_DEF(term_handler)
575 SYSDEPS_AbortThread(0);
579 /**********************************************************************
582 * Handler for SIGUSR1, used to signal a thread that it got suspended.
584 static HANDLER_DEF(usr1_handler)
586 LARGE_INTEGER timeout;
588 /* wait with 0 timeout, will only return once the thread is no longer suspended */
589 timeout.QuadPart = 0;
590 NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
594 /***********************************************************************
597 * Set a signal handler
599 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
601 struct sigaction sig_act;
603 sig_act.sa_sigaction = func;
604 sigemptyset( &sig_act.sa_mask );
605 sigaddset( &sig_act.sa_mask, SIGINT );
606 sigaddset( &sig_act.sa_mask, SIGALRM );
608 sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
611 if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
613 return sigaction( sig, &sig_act, NULL );
617 /***********************************************************************
618 * __wine_set_signal_handler (NTDLL.@)
620 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
622 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
623 if (handlers[sig] != NULL) return -2;
629 /**********************************************************************
632 BOOL SIGNAL_Init(void)
634 int have_sigaltstack = 0;
636 #ifdef HAVE_SIGALTSTACK
637 struct sigaltstack ss;
638 if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
640 ss.ss_size = SIGNAL_STACK_SIZE;
642 if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
644 #endif /* HAVE_SIGALTSTACK */
646 if (set_handler( SIGINT, have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
647 if (set_handler( SIGFPE, have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
648 if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
649 if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
650 if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
651 if (set_handler( SIGTERM, have_sigaltstack, (void (*)())term_handler ) == -1) goto error;
652 if (set_handler( SIGUSR1, have_sigaltstack, (void (*)())usr1_handler ) == -1) goto error;
654 if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
657 if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
668 /**********************************************************************
671 * Block the async signals.
673 void SIGNAL_Block(void)
677 sigemptyset( &block_set );
678 sigaddset( &block_set, SIGALRM );
679 sigaddset( &block_set, SIGIO );
680 sigaddset( &block_set, SIGHUP );
681 sigaddset( &block_set, SIGUSR1 );
682 sigaddset( &block_set, SIGUSR2 );
683 sigprocmask( SIG_BLOCK, &block_set, NULL );
687 /***********************************************************************
690 * Unblock signals. Called from EXC_RtlRaiseException.
692 void SIGNAL_Unblock(void)
696 sigfillset( &all_sigs );
697 sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
701 /**********************************************************************
704 * Restore the default handlers.
706 void SIGNAL_Reset(void)
708 signal( SIGINT, SIG_DFL );
709 signal( SIGFPE, SIG_DFL );
710 signal( SIGSEGV, SIG_DFL );
711 signal( SIGILL, SIG_DFL );
712 signal( SIGABRT, SIG_DFL );
713 signal( SIGTERM, SIG_DFL );
715 signal( SIGBUS, SIG_DFL );
718 signal( SIGTRAP, SIG_DFL );
723 /**********************************************************************
724 * __wine_enter_vm86 (NTDLL.@)
726 void __wine_enter_vm86( CONTEXT *context )
728 MESSAGE("vm86 mode not supported on this platform\n");
731 /**********************************************************************
732 * DbgBreakPoint (NTDLL.@)
734 void WINAPI DbgBreakPoint(void)
736 kill(getpid(), SIGTRAP);
739 /**********************************************************************
740 * DbgUserBreakPoint (NTDLL.@)
742 void WINAPI DbgUserBreakPoint(void)
744 kill(getpid(), SIGTRAP);
747 #endif /* __powerpc__ */