Merged font.h and path.h into gdi.h. Moved x11font.h to
[wine] / dlls / ntdll / signal_powerpc.c
1 /*
2  * PowerPC signal handling routines
3  *
4  * Copyright 2002 Marcus Meissner, SuSE Linux AG
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #ifdef __powerpc__
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #ifdef HAVE_SYS_PARAM_H
35 # include <sys/param.h>
36 #endif
37 #ifdef HAVE_SYSCALL_H
38 # include <syscall.h>
39 #else
40 # ifdef HAVE_SYS_SYSCALL_H
41 #  include <sys/syscall.h>
42 # endif
43 #endif
44
45 #ifdef HAVE_SYS_VM86_H
46 # include <sys/vm86.h>
47 #endif
48
49 #ifdef HAVE_SYS_SIGNAL_H
50 # include <sys/signal.h>
51 #endif
52
53 #include "winternl.h"
54 #include "winnt.h"
55 #include "wine/library.h"
56 #include "wine/exception.h"
57 #include "selectors.h"
58 #include "stackframe.h"
59 #include "global.h"
60 #include "miscemu.h"
61 #include "wine/debug.h"
62
63 WINE_DEFAULT_DEBUG_CHANNEL(seh);
64
65
66 /***********************************************************************
67  * signal context platform-specific definitions
68  */
69
70 typedef struct ucontext SIGCONTEXT;
71
72 #define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
73 #define HANDLER_CONTEXT (__context)
74
75 typedef int (*wine_signal_handler)(unsigned int sig);
76
77 static wine_signal_handler handlers[256];
78
79 static sigset_t all_sigs;
80
81
82 /***********************************************************************
83  *           dispatch_signal
84  */
85 inline static int dispatch_signal(unsigned int sig)
86 {
87     if (handlers[sig] == NULL) return 0;
88     return handlers[sig](sig);
89 }
90
91 /***********************************************************************
92  *           save_context
93  *
94  * Set the register values from a sigcontext.
95  */
96 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
97 {
98 #define CX(x,y) context->x = sigcontext->uc_mcontext.regs->y
99 #define C(x) CX(Gpr##x,gpr[x])
100         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
101         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
102         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
103         C(31);
104
105         CX(Iar,nip);
106         CX(Msr,msr);
107         CX(Ctr,ctr);
108 #undef CX
109         /* FIXME: fp regs? */
110
111         /* FIXME: missing pt_regs ...
112         unsigned long link;
113         unsigned long xer;
114         unsigned long ccr;
115         unsigned long mq;
116
117         unsigned long trap;
118         unsigned long dar;
119         unsigned long dsisr;
120
121         */
122 }
123
124
125 /***********************************************************************
126  *           restore_context
127  *
128  * Build a sigcontext from the register values.
129  */
130 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
131 {
132 #define CX(x,y) sigcontext->uc_mcontext.regs->y = context->x
133         C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
134         C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
135         C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
136         C(31);
137
138         CX(Iar,nip);
139         CX(Msr,msr);
140         CX(Ctr,ctr);
141 #undef CX
142 }
143
144
145 /***********************************************************************
146  *           save_fpu
147  *
148  * Set the FPU context from a sigcontext.
149  */
150 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
151 {
152         /* FIXME? */
153 }
154
155
156 /***********************************************************************
157  *           restore_fpu
158  *
159  * Restore the FPU context to a sigcontext.
160  */
161 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
162 {
163         /* FIXME? */
164 }
165
166
167 /**********************************************************************
168  *              get_fpu_code
169  *
170  * Get the FPU exception code from the FPU status.
171  */
172 static inline DWORD get_fpu_code( const CONTEXT *context )
173 {
174     DWORD status  = 0 /* FIXME */;
175
176     if (status & 0x01)  /* IE */
177     {
178         if (status & 0x40)  /* SF */
179             return EXCEPTION_FLT_STACK_CHECK;
180         else
181             return EXCEPTION_FLT_INVALID_OPERATION;
182     }
183     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
184     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
185     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
186     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
187     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
188     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
189 }
190
191
192 /***********************************************************************
193  *           SIGNAL_Unblock
194  *
195  * Unblock signals. Called from EXC_RtlRaiseException.
196  */
197 void SIGNAL_Unblock( void )
198 {
199     sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
200 }
201
202 /**********************************************************************
203  *              segv_handler
204  *
205  * Handler for SIGSEGV and related errors.
206  */
207 static HANDLER_DEF(segv_handler)
208 {
209     CONTEXT context;
210     EXCEPTION_RECORD rec;
211     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
212
213     save_context( &context, HANDLER_CONTEXT );
214
215     rec.ExceptionRecord  = NULL;
216     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
217     rec.ExceptionAddress = (LPVOID)HANDLER_CONTEXT->uc_mcontext.regs->nip;
218     rec.NumberParameters = 0;
219     switch (__siginfo->si_signo) {
220     case SIGSEGV:
221         switch ( __siginfo->si_code & 0xffff ) {
222         case SEGV_MAPERR:
223         case SEGV_ACCERR:
224                 rec.NumberParameters = 2;
225                 rec.ExceptionInformation[0] = 0; /* FIXME ? */
226                 rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr;
227                 if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr)))
228                         return;
229                 rec.ExceptionCode = page_fault_code;
230                 break;
231         default:FIXME("Unhandled SIGSEGV/%x\n",__siginfo->si_code);
232                 break;
233         }
234         break;
235     case SIGBUS:
236         switch ( __siginfo->si_code & 0xffff ) {
237         case BUS_ADRALN:
238                 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
239                 break;
240         case BUS_ADRERR:
241         case BUS_OBJERR:
242                 /* FIXME: correct for all cases ? */
243                 rec.NumberParameters = 2;
244                 rec.ExceptionInformation[0] = 0; /* FIXME ? */
245                 rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr;
246                 if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr)))
247                         return;
248                 rec.ExceptionCode = page_fault_code;
249                 break;
250         default:FIXME("Unhandled SIGBUS/%x\n",__siginfo->si_code);
251                 break;
252         }
253         break;
254     case SIGILL:
255         switch ( __siginfo->si_code & 0xffff ) {
256         case ILL_ILLOPC: /* illegal opcode */
257         case ILL_ILLOPN: /* illegal operand */
258         case ILL_ILLADR: /* illegal addressing mode */
259         case ILL_ILLTRP: /* illegal trap */
260         case ILL_COPROC: /* coprocessor error */
261                 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
262                 break;
263         case ILL_PRVOPC: /* privileged opcode */
264         case ILL_PRVREG: /* privileged register */
265                 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
266                 break;
267         case ILL_BADSTK: /* internal stack error */
268                 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
269                 break;
270         default:FIXME("Unhandled SIGILL/%x\n",__siginfo->si_code);
271                 break;
272         }
273         break;
274     }
275     EXC_RtlRaiseException( &rec, &context );
276     restore_context( &context, HANDLER_CONTEXT );
277 }
278
279 /**********************************************************************
280  *              trap_handler
281  *
282  * Handler for SIGTRAP.
283  */
284 static HANDLER_DEF(trap_handler)
285 {
286     CONTEXT context;
287     EXCEPTION_RECORD rec;
288
289     save_context( &context, HANDLER_CONTEXT );
290
291     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
292     rec.ExceptionRecord  = NULL;
293     rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip;
294     rec.NumberParameters = 0;
295
296     /* FIXME: check if we might need to modify PC */
297     switch (__siginfo->si_code & 0xffff) {
298     case TRAP_BRKPT:
299         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
300         break;
301     case TRAP_TRACE:
302         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
303         break;
304     }
305     EXC_RtlRaiseException( &rec, &context );
306     restore_context( &context, HANDLER_CONTEXT );
307 }
308
309
310 /**********************************************************************
311  *              fpe_handler
312  *
313  * Handler for SIGFPE.
314  */
315 static HANDLER_DEF(fpe_handler)
316 {
317     CONTEXT context;
318     EXCEPTION_RECORD rec;
319
320     /*save_fpu( &context, HANDLER_CONTEXT );*/
321     save_context( &context, HANDLER_CONTEXT );
322
323     switch ( __siginfo->si_code  & 0xffff ) {
324     case FPE_FLTSUB:
325         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
326         break;
327     case FPE_INTDIV:
328         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
329         break;
330     case FPE_INTOVF:
331         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
332         break;
333     case FPE_FLTDIV:
334         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
335         break;
336     case FPE_FLTOVF:
337         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
338         break;
339     case FPE_FLTUND:
340         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
341         break;
342     case FPE_FLTRES:
343         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
344         break;
345     case FPE_FLTINV:
346     default:
347         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
348         break;
349     }
350     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
351     rec.ExceptionRecord  = NULL;
352     rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip;
353     rec.NumberParameters = 0;
354     EXC_RtlRaiseException( &rec, &context );
355     restore_context( &context, HANDLER_CONTEXT );
356     /*restore_fpu( &context, HANDLER_CONTEXT );*/
357 }
358
359
360 /**********************************************************************
361  *              int_handler
362  *
363  * Handler for SIGINT.
364  */
365 static HANDLER_DEF(int_handler)
366 {
367     if (!dispatch_signal(SIGINT))
368     {
369         EXCEPTION_RECORD rec;
370         CONTEXT context;
371
372         save_context( &context, HANDLER_CONTEXT );
373         rec.ExceptionCode    = CONTROL_C_EXIT;
374         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
375         rec.ExceptionRecord  = NULL;
376         rec.ExceptionAddress = (LPVOID)context.Iar;
377         rec.NumberParameters = 0;
378         EXC_RtlRaiseException( &rec, &context );
379         restore_context( &context, HANDLER_CONTEXT );
380     }
381 }
382
383 /**********************************************************************
384  *              abrt_handler
385  *
386  * Handler for SIGABRT.
387  */
388 static HANDLER_DEF(abrt_handler)
389 {
390     EXCEPTION_RECORD rec;
391     CONTEXT context;
392
393     save_context( &context, HANDLER_CONTEXT );
394     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
395     rec.ExceptionFlags   = EH_NONCONTINUABLE;
396     rec.ExceptionRecord  = NULL;
397     rec.ExceptionAddress = (LPVOID)context.Iar;
398     rec.NumberParameters = 0;
399     EXC_RtlRaiseException( &rec, &context ); /* Should never return.. */
400     restore_context( &context, HANDLER_CONTEXT );
401 }
402
403
404 /***********************************************************************
405  *           set_handler
406  *
407  * Set a signal handler
408  */
409 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
410 {
411     struct sigaction sig_act;
412
413     sig_act.sa_sigaction = func;
414     sigemptyset( &sig_act.sa_mask );
415     sigaddset( &sig_act.sa_mask, SIGINT );
416     sigaddset( &sig_act.sa_mask, SIGALRM );
417
418     sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
419
420 #ifdef SA_ONSTACK
421     if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
422 #endif
423     return sigaction( sig, &sig_act, NULL );
424 }
425
426
427 /***********************************************************************
428  *           __wine_set_signal_handler   (NTDLL.@)
429  */
430 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
431 {
432     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
433     if (handlers[sig] != NULL) return -2;
434     handlers[sig] = wsh;
435     return 0;
436 }
437
438
439 /**********************************************************************
440  *              SIGNAL_Init
441  */
442 BOOL SIGNAL_Init(void)
443 {
444     int have_sigaltstack = 0;
445
446 #ifdef HAVE_SIGALTSTACK
447     struct sigaltstack ss;
448     if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
449     {
450         ss.ss_size  = SIGNAL_STACK_SIZE;
451         ss.ss_flags = 0;
452         if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
453     }
454 #endif  /* HAVE_SIGALTSTACK */
455
456     sigfillset( &all_sigs );
457
458     if (set_handler( SIGINT,  have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
459     if (set_handler( SIGFPE,  have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
460     if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
461     if (set_handler( SIGILL,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
462     if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
463 #ifdef SIGBUS
464     if (set_handler( SIGBUS,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
465 #endif
466 #ifdef SIGTRAP
467     if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
468 #endif
469
470     return TRUE;
471
472  error:
473     perror("sigaction");
474     return FALSE;
475 }
476
477
478 /**********************************************************************
479  *              SIGNAL_Reset
480  */
481 void SIGNAL_Reset(void)
482 {
483     sigset_t block_set;
484
485     /* block the async signals */
486     sigemptyset( &block_set );
487     sigaddset( &block_set, SIGALRM );
488     sigaddset( &block_set, SIGIO );
489     sigaddset( &block_set, SIGHUP );
490     sigaddset( &block_set, SIGUSR2 );
491     sigprocmask( SIG_BLOCK, &block_set, NULL );
492
493     /* restore default handlers */
494     signal( SIGINT, SIG_DFL );
495     signal( SIGFPE, SIG_DFL );
496     signal( SIGSEGV, SIG_DFL );
497     signal( SIGILL, SIG_DFL );
498 #ifdef SIGBUS
499     signal( SIGBUS, SIG_DFL );
500 #endif
501 #ifdef SIGTRAP
502     signal( SIGTRAP, SIG_DFL );
503 #endif
504 }
505
506 /**********************************************************************
507  *              __wine_enter_vm86   (NTDLL.@)
508  */
509 void __wine_enter_vm86( CONTEXT *context )
510 {
511     MESSAGE("vm86 mode not supported on this platform\n");
512 }
513
514 /**********************************************************************
515  *              DbgBreakPoint   (NTDLL.@)
516  */
517 void WINAPI DbgBreakPoint(void)
518 {
519      kill(getpid(), SIGTRAP);
520 }
521
522 /**********************************************************************
523  *              DbgUserBreakPoint   (NTDLL.@)
524  */
525 void WINAPI DbgUserBreakPoint(void)
526 {
527      kill(getpid(), SIGTRAP);
528 }
529
530 #endif  /* __powerpc__ */