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>
55 #include "wine/library.h"
56 #include "wine/exception.h"
57 #include "selectors.h"
58 #include "stackframe.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
66 /***********************************************************************
67 * signal context platform-specific definitions
70 typedef struct ucontext SIGCONTEXT
;
72 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
73 #define HANDLER_CONTEXT (__context)
75 typedef int (*wine_signal_handler
)(unsigned int sig
);
77 static wine_signal_handler handlers
[256];
79 extern void WINAPI
EXC_RtlRaiseException( PEXCEPTION_RECORD
, PCONTEXT
);
81 /***********************************************************************
84 inline static int dispatch_signal(unsigned int sig
)
86 if (handlers
[sig
] == NULL
) return 0;
87 return handlers
[sig
](sig
);
90 /***********************************************************************
93 * Set the register values from a sigcontext.
95 static void save_context( CONTEXT
*context
, const SIGCONTEXT
*sigcontext
)
97 #define CX(x,y) context->x = sigcontext->uc_mcontext.regs->y
98 #define C(x) CX(Gpr##x,gpr[x])
99 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
100 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
101 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
108 /* FIXME: fp regs? */
110 /* FIXME: missing pt_regs ...
124 /***********************************************************************
127 * Build a sigcontext from the register values.
129 static void restore_context( const CONTEXT
*context
, SIGCONTEXT
*sigcontext
)
131 #define CX(x,y) sigcontext->uc_mcontext.regs->y = context->x
132 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
133 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
134 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
144 /***********************************************************************
147 * Set the FPU context from a sigcontext.
149 inline static void save_fpu( CONTEXT
*context
, const SIGCONTEXT
*sigcontext
)
155 /***********************************************************************
158 * Restore the FPU context to a sigcontext.
160 inline static void restore_fpu( CONTEXT
*context
, const SIGCONTEXT
*sigcontext
)
166 /**********************************************************************
169 * Get the FPU exception code from the FPU status.
171 static inline DWORD
get_fpu_code( const CONTEXT
*context
)
173 DWORD status
= 0 /* FIXME */;
175 if (status
& 0x01) /* IE */
177 if (status
& 0x40) /* SF */
178 return EXCEPTION_FLT_STACK_CHECK
;
180 return EXCEPTION_FLT_INVALID_OPERATION
;
182 if (status
& 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND
; /* DE flag */
183 if (status
& 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO
; /* ZE flag */
184 if (status
& 0x08) return EXCEPTION_FLT_OVERFLOW
; /* OE flag */
185 if (status
& 0x10) return EXCEPTION_FLT_UNDERFLOW
; /* UE flag */
186 if (status
& 0x20) return EXCEPTION_FLT_INEXACT_RESULT
; /* PE flag */
187 return EXCEPTION_FLT_INVALID_OPERATION
; /* generic error */
191 /**********************************************************************
194 * Handler for SIGSEGV and related errors.
196 static HANDLER_DEF(segv_handler
)
199 EXCEPTION_RECORD rec
;
200 DWORD page_fault_code
= EXCEPTION_ACCESS_VIOLATION
;
202 save_context( &context
, HANDLER_CONTEXT
);
204 rec
.ExceptionRecord
= NULL
;
205 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
206 rec
.ExceptionAddress
= (LPVOID
)HANDLER_CONTEXT
->uc_mcontext
.regs
->nip
;
207 rec
.NumberParameters
= 0;
208 switch (__siginfo
->si_signo
) {
210 switch ( __siginfo
->si_code
& 0xffff ) {
213 rec
.NumberParameters
= 2;
214 rec
.ExceptionInformation
[0] = 0; /* FIXME ? */
215 rec
.ExceptionInformation
[1] = (DWORD
)__siginfo
->si_addr
;
216 if (!(page_fault_code
=VIRTUAL_HandleFault(__siginfo
->si_addr
)))
218 rec
.ExceptionCode
= page_fault_code
;
220 default:FIXME("Unhandled SIGSEGV/%x\n",__siginfo
->si_code
);
225 switch ( __siginfo
->si_code
& 0xffff ) {
227 rec
.ExceptionCode
= EXCEPTION_DATATYPE_MISALIGNMENT
;
231 /* FIXME: correct for all cases ? */
232 rec
.NumberParameters
= 2;
233 rec
.ExceptionInformation
[0] = 0; /* FIXME ? */
234 rec
.ExceptionInformation
[1] = (DWORD
)__siginfo
->si_addr
;
235 if (!(page_fault_code
=VIRTUAL_HandleFault(__siginfo
->si_addr
)))
237 rec
.ExceptionCode
= page_fault_code
;
239 default:FIXME("Unhandled SIGBUS/%x\n",__siginfo
->si_code
);
244 switch ( __siginfo
->si_code
& 0xffff ) {
245 case ILL_ILLOPC
: /* illegal opcode */
246 case ILL_ILLOPN
: /* illegal operand */
247 case ILL_ILLADR
: /* illegal addressing mode */
248 case ILL_ILLTRP
: /* illegal trap */
249 case ILL_COPROC
: /* coprocessor error */
250 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
252 case ILL_PRVOPC
: /* privileged opcode */
253 case ILL_PRVREG
: /* privileged register */
254 rec
.ExceptionCode
= EXCEPTION_PRIV_INSTRUCTION
;
256 case ILL_BADSTK
: /* internal stack error */
257 rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
259 default:FIXME("Unhandled SIGILL/%x\n",__siginfo
->si_code
);
264 EXC_RtlRaiseException( &rec
, &context
);
265 restore_context( &context
, HANDLER_CONTEXT
);
268 /**********************************************************************
271 * Handler for SIGTRAP.
273 static HANDLER_DEF(trap_handler
)
276 EXCEPTION_RECORD rec
;
278 save_context( &context
, HANDLER_CONTEXT
);
280 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
281 rec
.ExceptionRecord
= NULL
;
282 rec
.ExceptionAddress
= (LPVOID
)__context
->uc_mcontext
.regs
->nip
;
283 rec
.NumberParameters
= 0;
285 /* FIXME: check if we might need to modify PC */
286 switch (__siginfo
->si_code
& 0xffff) {
288 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
291 rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
294 EXC_RtlRaiseException( &rec
, &context
);
295 restore_context( &context
, HANDLER_CONTEXT
);
299 /**********************************************************************
302 * Handler for SIGFPE.
304 static HANDLER_DEF(fpe_handler
)
307 EXCEPTION_RECORD rec
;
309 /*save_fpu( &context, HANDLER_CONTEXT );*/
310 save_context( &context
, HANDLER_CONTEXT
);
312 switch ( __siginfo
->si_code
& 0xffff ) {
314 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
317 rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
320 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
323 rec
.ExceptionCode
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
326 rec
.ExceptionCode
= EXCEPTION_FLT_OVERFLOW
;
329 rec
.ExceptionCode
= EXCEPTION_FLT_UNDERFLOW
;
332 rec
.ExceptionCode
= EXCEPTION_FLT_INEXACT_RESULT
;
336 rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
339 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
340 rec
.ExceptionRecord
= NULL
;
341 rec
.ExceptionAddress
= (LPVOID
)__context
->uc_mcontext
.regs
->nip
;
342 rec
.NumberParameters
= 0;
343 EXC_RtlRaiseException( &rec
, &context
);
344 restore_context( &context
, HANDLER_CONTEXT
);
345 /*restore_fpu( &context, HANDLER_CONTEXT );*/
349 /**********************************************************************
352 * Handler for SIGINT.
354 static HANDLER_DEF(int_handler
)
356 if (!dispatch_signal(SIGINT
))
358 EXCEPTION_RECORD rec
;
361 save_context( &context
, HANDLER_CONTEXT
);
362 rec
.ExceptionCode
= CONTROL_C_EXIT
;
363 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
364 rec
.ExceptionRecord
= NULL
;
365 rec
.ExceptionAddress
= (LPVOID
)context
.Iar
;
366 rec
.NumberParameters
= 0;
367 EXC_RtlRaiseException( &rec
, &context
);
368 restore_context( &context
, HANDLER_CONTEXT
);
373 /**********************************************************************
376 * Handler for SIGABRT.
378 static HANDLER_DEF(abrt_handler
)
380 EXCEPTION_RECORD rec
;
383 save_context( &context
, HANDLER_CONTEXT
);
384 rec
.ExceptionCode
= EXCEPTION_WINE_ASSERTION
;
385 rec
.ExceptionFlags
= EH_NONCONTINUABLE
;
386 rec
.ExceptionRecord
= NULL
;
387 rec
.ExceptionAddress
= (LPVOID
)context
.Iar
;
388 rec
.NumberParameters
= 0;
389 EXC_RtlRaiseException( &rec
, &context
); /* Should never return.. */
390 restore_context( &context
, HANDLER_CONTEXT
);
394 /**********************************************************************
397 * Handler for SIGTERM.
399 static HANDLER_DEF(term_handler
)
401 SYSDEPS_AbortThread(0);
405 /**********************************************************************
408 * Handler for SIGUSR1, used to signal a thread that it got suspended.
410 static HANDLER_DEF(usr1_handler
)
412 LARGE_INTEGER timeout
;
414 /* wait with 0 timeout, will only return once the thread is no longer suspended */
415 timeout
.QuadPart
= 0;
416 NtWaitForMultipleObjects( 0, NULL
, FALSE
, FALSE
, &timeout
);
420 /***********************************************************************
423 * Set a signal handler
425 static int set_handler( int sig
, int have_sigaltstack
, void (*func
)() )
427 struct sigaction sig_act
;
429 sig_act
.sa_sigaction
= func
;
430 sigemptyset( &sig_act
.sa_mask
);
431 sigaddset( &sig_act
.sa_mask
, SIGINT
);
432 sigaddset( &sig_act
.sa_mask
, SIGALRM
);
434 sig_act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
437 if (have_sigaltstack
) sig_act
.sa_flags
|= SA_ONSTACK
;
439 return sigaction( sig
, &sig_act
, NULL
);
443 /***********************************************************************
444 * __wine_set_signal_handler (NTDLL.@)
446 int __wine_set_signal_handler(unsigned int sig
, wine_signal_handler wsh
)
448 if (sig
> sizeof(handlers
) / sizeof(handlers
[0])) return -1;
449 if (handlers
[sig
] != NULL
) return -2;
455 /**********************************************************************
458 BOOL
SIGNAL_Init(void)
460 int have_sigaltstack
= 0;
462 #ifdef HAVE_SIGALTSTACK
463 struct sigaltstack ss
;
464 if ((ss
.ss_sp
= NtCurrentTeb()->signal_stack
))
466 ss
.ss_size
= SIGNAL_STACK_SIZE
;
468 if (!sigaltstack(&ss
, NULL
)) have_sigaltstack
= 1;
470 #endif /* HAVE_SIGALTSTACK */
472 sigfillset( &all_sigs
);
474 if (set_handler( SIGINT
, have_sigaltstack
, (void (*)())int_handler
) == -1) goto error
;
475 if (set_handler( SIGFPE
, have_sigaltstack
, (void (*)())fpe_handler
) == -1) goto error
;
476 if (set_handler( SIGSEGV
, have_sigaltstack
, (void (*)())segv_handler
) == -1) goto error
;
477 if (set_handler( SIGILL
, have_sigaltstack
, (void (*)())segv_handler
) == -1) goto error
;
478 if (set_handler( SIGABRT
, have_sigaltstack
, (void (*)())abrt_handler
) == -1) goto error
;
479 if (set_handler( SIGTERM
, have_sigaltstack
, (void (*)())term_handler
) == -1) goto error
;
480 if (set_handler( SIGUSR1
, have_sigaltstack
, (void (*)())usr1_handler
) == -1) goto error
;
482 if (set_handler( SIGBUS
, have_sigaltstack
, (void (*)())segv_handler
) == -1) goto error
;
485 if (set_handler( SIGTRAP
, have_sigaltstack
, (void (*)())trap_handler
) == -1) goto error
;
496 /**********************************************************************
499 * Block the async signals.
501 void SIGNAL_Block(void)
505 sigemptyset( &block_set
);
506 sigaddset( &block_set
, SIGALRM
);
507 sigaddset( &block_set
, SIGIO
);
508 sigaddset( &block_set
, SIGHUP
);
509 sigaddset( &block_set
, SIGUSR1
);
510 sigaddset( &block_set
, SIGUSR2
);
511 sigprocmask( SIG_BLOCK
, &block_set
, NULL
);
515 /***********************************************************************
518 * Unblock signals. Called from EXC_RtlRaiseException.
520 void SIGNAL_Unblock(void)
524 sigfillset( &all_sigs
);
525 sigprocmask( SIG_UNBLOCK
, &all_sigs
, NULL
);
529 /**********************************************************************
532 * Restore the default handlers.
534 void SIGNAL_Reset(void)
536 signal( SIGINT
, SIG_DFL
);
537 signal( SIGFPE
, SIG_DFL
);
538 signal( SIGSEGV
, SIG_DFL
);
539 signal( SIGILL
, SIG_DFL
);
540 signal( SIGABRT
, SIG_DFL
);
541 signal( SIGTERM
, SIG_DFL
);
543 signal( SIGBUS
, SIG_DFL
);
546 signal( SIGTRAP
, SIG_DFL
);
551 /**********************************************************************
552 * __wine_enter_vm86 (NTDLL.@)
554 void __wine_enter_vm86( CONTEXT
*context
)
556 MESSAGE("vm86 mode not supported on this platform\n");
559 /**********************************************************************
560 * DbgBreakPoint (NTDLL.@)
562 void WINAPI
DbgBreakPoint(void)
564 kill(getpid(), SIGTRAP
);
567 /**********************************************************************
568 * DbgUserBreakPoint (NTDLL.@)
570 void WINAPI
DbgUserBreakPoint(void)
572 kill(getpid(), SIGTRAP
);
575 #endif /* __powerpc__ */