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"
33 #ifdef HAVE_SYS_PARAM_H
34 # include <sys/param.h>
39 # ifdef HAVE_SYS_SYSCALL_H
40 # include <sys/syscall.h>
44 #ifdef HAVE_SYS_VM86_H
45 # include <sys/vm86.h>
48 #ifdef HAVE_SYS_SIGNAL_H
49 # include <sys/signal.h>
54 #include "wine/library.h"
55 #include "wine/exception.h"
56 #include "selectors.h"
57 #include "stackframe.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(seh);
65 /***********************************************************************
66 * signal context platform-specific definitions
69 # warning Please define registers for your platform linux ppc some are missing
71 typedef struct ucontext SIGCONTEXT;
73 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
74 # define HANDLER_CONTEXT (__context)
76 /* All Registers access - only for local access */
77 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
80 /* Gpr Registers access */
81 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
83 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
84 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
85 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
87 # define XER_sig(context) XER_sig not defined on your platform /* Link register */
88 # define LR_sig(context) LR_sig not defined on your platform /* User's integer exception register */
89 # define CR_sig(context) CR_sig not defined on your platform /* Condition register */
91 /* Float Registers access */
92 # define FLOAT_sig(reg_num, context) FLOAT_sig not defined on your platform /* Float registers */
94 # define FPSCR_sig(reg_num, context) FPSCR_sig not defined on your platform /* Float registers */
96 /* Exception Registers access */
97 # define DAR_sig(context) DAR_sig not defined on your platform
98 # define DSISR_sig(context) DSISR_sig not defined on your platform
99 # define TRAP_sig(context) TRAP_sig not defined on your platform
105 # include <sys/ucontext.h>
107 # include <sys/types.h>
109 typedef siginfo_t siginfo;
111 typedef struct ucontext SIGCONTEXT;
114 # define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context )
115 # define HANDLER_CONTEXT (__context)
117 /* All Registers access - only for local access */
118 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
119 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
120 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
121 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
123 /* Gpr Registers access */
124 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
126 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
127 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
128 # define CTR_sig(context) REG_sig(ctr, context)
130 # define XER_sig(context) REG_sig(xer, context) /* Link register */
131 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
132 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
134 /* Float Registers access */
135 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
137 # define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
139 /* Exception Registers access */
140 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
141 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
142 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
144 /* Signal defs : Those are undefined on darwin
161 #endif /* __darwin__ */
165 typedef int (*wine_signal_handler)(unsigned int sig);
167 static wine_signal_handler handlers[256];
169 extern void WINAPI EXC_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
171 /***********************************************************************
174 inline static int dispatch_signal(unsigned int sig)
176 if (handlers[sig] == NULL) return 0;
177 return handlers[sig](sig);
180 /***********************************************************************
183 * Set the register values from a sigcontext.
185 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
188 #define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
189 /* Save Gpr registers */
190 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
191 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
192 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
196 context->Iar = IAR_sig(sigcontext); /* Program Counter */
197 context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */
198 context->Ctr = CTR_sig(sigcontext);
200 context->Xer = XER_sig(sigcontext);
201 context->Lr = LR_sig(sigcontext);
202 context->Cr = CR_sig(sigcontext);
204 /* Saving Exception regs */
205 context->Dar = DAR_sig(sigcontext);
206 context->Dsisr = DSISR_sig(sigcontext);
207 context->Trap = TRAP_sig(sigcontext);
211 /***********************************************************************
214 * Build a sigcontext from the register values.
216 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
219 #define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
220 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
221 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
222 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
226 IAR_sig(sigcontext) = context->Iar; /* Program Counter */
227 MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */
228 CTR_sig(sigcontext) = context->Ctr;
230 XER_sig(sigcontext) = context->Xer;
231 LR_sig(sigcontext) = context->Lr;
232 CR_sig(sigcontext) = context->Cr;
234 /* Setting Exception regs */
235 DAR_sig(sigcontext) = context->Dar;
236 DSISR_sig(sigcontext) = context->Dsisr;
237 TRAP_sig(sigcontext) = context->Trap;
241 /***********************************************************************
244 * Set the FPU context from a sigcontext.
246 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
248 #define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
249 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
250 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
251 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
254 context->Fpscr = FPSCR_sig(sigcontext);
258 /***********************************************************************
261 * Restore the FPU context to a sigcontext.
263 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
265 #define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
266 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
267 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
268 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
271 FPSCR_sig(sigcontext) = context->Fpscr;
275 /**********************************************************************
278 * Get the FPU exception code from the FPU status.
280 static inline DWORD get_fpu_code( const CONTEXT *context )
282 DWORD status = context->Fpscr;
284 if (status & 0x01) /* IE */
286 if (status & 0x40) /* SF */
287 return EXCEPTION_FLT_STACK_CHECK;
289 return EXCEPTION_FLT_INVALID_OPERATION;
291 if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND; /* DE flag */
292 if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO; /* ZE flag */
293 if (status & 0x08) return EXCEPTION_FLT_OVERFLOW; /* OE flag */
294 if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */
295 if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */
296 return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */
299 /**********************************************************************
302 * Implementation of SIGSEGV handler.
304 static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr )
306 EXCEPTION_RECORD rec;
307 DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
309 rec.ExceptionRecord = NULL;
310 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
311 rec.ExceptionAddress = addr;
312 rec.NumberParameters = 0;
316 switch ( code & 0xffff ) {
319 rec.NumberParameters = 2;
320 rec.ExceptionInformation[0] = 0; /* FIXME ? */
321 rec.ExceptionInformation[1] = (DWORD)addr;
322 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
324 rec.ExceptionCode = page_fault_code;
326 default:FIXME("Unhandled SIGSEGV/%x\n",code);
331 switch ( code & 0xffff ) {
333 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
340 /* FIXME: correct for all cases ? */
341 rec.NumberParameters = 2;
342 rec.ExceptionInformation[0] = 0; /* FIXME ? */
343 rec.ExceptionInformation[1] = (DWORD)addr;
344 if (!(page_fault_code=VIRTUAL_HandleFault(addr)))
346 rec.ExceptionCode = page_fault_code;
349 default:FIXME("Unhandled SIGBUS/%x\n",code);
354 switch ( code & 0xffff ) {
355 case ILL_ILLOPC: /* illegal opcode */
357 case ILL_ILLOPN: /* illegal operand */
360 case ILL_ILLADR: /* illegal addressing mode */
363 case ILL_ILLTRP: /* illegal trap */
366 case ILL_COPROC: /* coprocessor error */
368 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
370 case ILL_PRVOPC: /* privileged opcode */
372 case ILL_PRVREG: /* privileged register */
374 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
377 case ILL_BADSTK: /* internal stack error */
378 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
381 default:FIXME("Unhandled SIGILL/%x\n", code);
386 EXC_RtlRaiseException( &rec, context );
389 /**********************************************************************
392 * Implementation of SIGTRAP handler.
394 static void do_trap( CONTEXT *context, int code, void * addr )
396 EXCEPTION_RECORD rec;
398 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
399 rec.ExceptionRecord = NULL;
400 rec.ExceptionAddress = addr;
401 rec.NumberParameters = 0;
403 /* FIXME: check if we might need to modify PC */
404 switch (code & 0xffff) {
407 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
412 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
415 default:FIXME("Unhandled SIGTRAP/%x\n", code);
418 EXC_RtlRaiseException( &rec, context );
421 /**********************************************************************
424 * Implementation of SIGFPE handler.
426 static void do_fpe( CONTEXT *context, int code, void * addr )
428 EXCEPTION_RECORD rec;
430 switch ( code & 0xffff ) {
433 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
438 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
443 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
448 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
453 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
458 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
463 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
470 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
473 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
474 rec.ExceptionRecord = NULL;
475 rec.ExceptionAddress = addr;
476 rec.NumberParameters = 0;
477 EXC_RtlRaiseException( &rec, context );
480 /**********************************************************************
483 * Handler for SIGSEGV and related errors.
485 static HANDLER_DEF(segv_handler)
488 save_context( &context, HANDLER_CONTEXT );
489 do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr );
490 restore_context( &context, HANDLER_CONTEXT );
493 /**********************************************************************
496 * Handler for SIGTRAP.
498 static HANDLER_DEF(trap_handler)
501 save_context( &context, HANDLER_CONTEXT );
502 do_trap( &context, __siginfo->si_code, __siginfo->si_addr );
503 restore_context( &context, HANDLER_CONTEXT );
506 /**********************************************************************
509 * Handler for SIGFPE.
511 static HANDLER_DEF(fpe_handler)
514 save_fpu( &context, HANDLER_CONTEXT );
515 save_context( &context, HANDLER_CONTEXT );
516 do_fpe( &context, __siginfo->si_code, __siginfo->si_addr );
517 restore_context( &context, HANDLER_CONTEXT );
518 restore_fpu( &context, HANDLER_CONTEXT );
521 /**********************************************************************
524 * Handler for SIGINT.
526 static HANDLER_DEF(int_handler)
528 if (!dispatch_signal(SIGINT))
530 EXCEPTION_RECORD rec;
533 save_context( &context, HANDLER_CONTEXT );
534 rec.ExceptionCode = CONTROL_C_EXIT;
535 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
536 rec.ExceptionRecord = NULL;
537 rec.ExceptionAddress = (LPVOID)context.Iar;
538 rec.NumberParameters = 0;
539 EXC_RtlRaiseException( &rec, &context );
540 restore_context( &context, HANDLER_CONTEXT );
545 /**********************************************************************
548 * Handler for SIGABRT.
550 static HANDLER_DEF(abrt_handler)
552 EXCEPTION_RECORD rec;
555 save_context( &context, HANDLER_CONTEXT );
556 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
557 rec.ExceptionFlags = EH_NONCONTINUABLE;
558 rec.ExceptionRecord = NULL;
559 rec.ExceptionAddress = (LPVOID)context.Iar;
560 rec.NumberParameters = 0;
561 EXC_RtlRaiseException( &rec, &context ); /* Should never return.. */
562 restore_context( &context, HANDLER_CONTEXT );
566 /**********************************************************************
569 * Handler for SIGTERM.
571 static HANDLER_DEF(term_handler)
573 SYSDEPS_AbortThread(0);
577 /**********************************************************************
580 * Handler for SIGUSR1, used to signal a thread that it got suspended.
582 static HANDLER_DEF(usr1_handler)
584 LARGE_INTEGER timeout;
586 /* wait with 0 timeout, will only return once the thread is no longer suspended */
587 timeout.QuadPart = 0;
588 NtWaitForMultipleObjects( 0, NULL, FALSE, FALSE, &timeout );
592 /***********************************************************************
595 * Set a signal handler
597 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
599 struct sigaction sig_act;
601 sig_act.sa_sigaction = func;
602 sigemptyset( &sig_act.sa_mask );
603 sigaddset( &sig_act.sa_mask, SIGINT );
604 sigaddset( &sig_act.sa_mask, SIGALRM );
606 sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
609 if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
611 return sigaction( sig, &sig_act, NULL );
615 /***********************************************************************
616 * __wine_set_signal_handler (NTDLL.@)
618 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
620 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
621 if (handlers[sig] != NULL) return -2;
627 /**********************************************************************
630 BOOL SIGNAL_Init(void)
632 int have_sigaltstack = 0;
634 #ifdef HAVE_SIGALTSTACK
635 struct sigaltstack ss;
636 if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
638 ss.ss_size = SIGNAL_STACK_SIZE;
640 if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
642 #endif /* HAVE_SIGALTSTACK */
644 if (set_handler( SIGINT, have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
645 if (set_handler( SIGFPE, have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
646 if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
647 if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
648 if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
649 if (set_handler( SIGTERM, have_sigaltstack, (void (*)())term_handler ) == -1) goto error;
650 if (set_handler( SIGUSR1, have_sigaltstack, (void (*)())usr1_handler ) == -1) goto error;
652 if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
655 if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
666 /**********************************************************************
669 * Block the async signals.
671 void SIGNAL_Block(void)
675 sigemptyset( &block_set );
676 sigaddset( &block_set, SIGALRM );
677 sigaddset( &block_set, SIGIO );
678 sigaddset( &block_set, SIGHUP );
679 sigaddset( &block_set, SIGUSR1 );
680 sigaddset( &block_set, SIGUSR2 );
681 sigprocmask( SIG_BLOCK, &block_set, NULL );
685 /***********************************************************************
688 * Unblock signals. Called from EXC_RtlRaiseException.
690 void SIGNAL_Unblock(void)
694 sigfillset( &all_sigs );
695 sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
699 /**********************************************************************
702 * Restore the default handlers.
704 void SIGNAL_Reset(void)
706 signal( SIGINT, SIG_DFL );
707 signal( SIGFPE, SIG_DFL );
708 signal( SIGSEGV, SIG_DFL );
709 signal( SIGILL, SIG_DFL );
710 signal( SIGABRT, SIG_DFL );
711 signal( SIGTERM, SIG_DFL );
713 signal( SIGBUS, SIG_DFL );
716 signal( SIGTRAP, SIG_DFL );
721 /**********************************************************************
722 * __wine_enter_vm86 (NTDLL.@)
724 void __wine_enter_vm86( CONTEXT *context )
726 MESSAGE("vm86 mode not supported on this platform\n");
729 /**********************************************************************
730 * DbgBreakPoint (NTDLL.@)
732 void WINAPI DbgBreakPoint(void)
734 kill(getpid(), SIGTRAP);
737 /**********************************************************************
738 * DbgUserBreakPoint (NTDLL.@)
740 void WINAPI DbgUserBreakPoint(void)
742 kill(getpid(), SIGTRAP);
745 #endif /* __powerpc__ */