Extended the winmm joystick API calls to support the new Linux
[wine] / dlls / ntdll / signal_i386.c
1 /*
2  * i386 signal handling routines
3  * 
4  * Copyright 1999 Alexandre Julliard
5  */
6
7 #ifdef __i386__
8
9 #include "config.h"
10
11 #include <errno.h>
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15
16 #ifdef HAVE_SYS_PARAM_H
17 # include <sys/param.h>
18 #endif
19 #ifdef HAVE_SYSCALL_H
20 # include <syscall.h>
21 #else
22 # ifdef HAVE_SYS_SYSCALL_H
23 #  include <sys/syscall.h>
24 # endif
25 #endif
26
27 /***********************************************************************
28  * signal context platform-specific definitions
29  */
30
31 #ifdef linux
32 typedef struct
33 {
34     unsigned short sc_gs, __gsh;
35     unsigned short sc_fs, __fsh;
36     unsigned short sc_es, __esh;
37     unsigned short sc_ds, __dsh;
38     unsigned long sc_edi;
39     unsigned long sc_esi;
40     unsigned long sc_ebp;
41     unsigned long sc_esp;
42     unsigned long sc_ebx;
43     unsigned long sc_edx;
44     unsigned long sc_ecx;
45     unsigned long sc_eax;
46     unsigned long sc_trapno;
47     unsigned long sc_err;
48     unsigned long sc_eip;
49     unsigned short sc_cs, __csh;
50     unsigned long sc_eflags;
51     unsigned long esp_at_signal;
52     unsigned short sc_ss, __ssh;
53     unsigned long i387;
54     unsigned long oldmask;
55     unsigned long cr2;
56 } SIGCONTEXT;
57
58 #define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context )
59 #define HANDLER_CONTEXT (&__context)
60
61 /* this is the sigaction structure from the Linux 2.1.20 kernel.  */
62 #undef sa_handler
63 struct kernel_sigaction
64 {
65     void (*sa_handler)();
66     unsigned long sa_mask;
67     unsigned long sa_flags;
68     void *sa_restorer;
69 };
70
71 /* Similar to the sigaction function in libc, except it leaves alone the
72    restorer field, which is used to specify the signal stack address */
73 static inline int wine_sigaction( int sig, struct kernel_sigaction *new,
74                                   struct kernel_sigaction *old )
75 {
76     __asm__ __volatile__( "pushl %%ebx\n\t"
77                           "movl %2,%%ebx\n\t"
78                           "int $0x80\n\t"
79                           "popl %%ebx"
80                           : "=a" (sig)
81                           : "0" (SYS_sigaction), "r" (sig), "c" (new), "d" (old) );
82     if (sig>=0) return 0;
83     errno = -sig;
84     return -1;
85 }
86
87 #endif  /* linux */
88
89 #ifdef BSDI
90
91 #define EAX_sig(context)     ((context)->tf_eax)
92 #define EBX_sig(context)     ((context)->tf_ebx)
93 #define ECX_sig(context)     ((context)->tf_ecx)
94 #define EDX_sig(context)     ((context)->tf_edx)
95 #define ESI_sig(context)     ((context)->tf_esi)
96 #define EDI_sig(context)     ((context)->tf_edi)
97 #define EBP_sig(context)     ((context)->tf_ebp)
98                             
99 #define CS_sig(context)      ((context)->tf_cs)
100 #define DS_sig(context)      ((context)->tf_ds)
101 #define ES_sig(context)      ((context)->tf_es)
102 #define SS_sig(context)      ((context)->tf_ss)
103
104 #include <machine/frame.h>
105 typedef struct trapframe SIGCONTEXT;
106
107 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
108 #define HANDLER_CONTEXT __context
109
110 #define EFL_sig(context)     ((context)->tf_eflags)
111
112 #define EIP_sig(context)     (*((unsigned long*)&(context)->tf_eip))
113 #define ESP_sig(context)     (*((unsigned long*)&(context)->tf_esp))
114
115 #endif /* bsdi */
116
117 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
118
119 typedef struct sigcontext SIGCONTEXT;
120
121 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
122 #define HANDLER_CONTEXT __context
123
124 #endif  /* FreeBSD */
125
126 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
127
128 #ifdef _SCO_DS
129 #include <sys/regset.h>
130 #endif
131 /* Solaris kludge */
132 #undef ERR
133 #include <sys/ucontext.h>
134 #undef ERR
135 typedef struct ucontext SIGCONTEXT;
136
137 #define HANDLER_DEF(name) void name( int __signal, void *__siginfo, SIGCONTEXT *__context )
138 #define HANDLER_CONTEXT __context
139
140 #endif  /* svr4 || SCO_DS */
141
142 #ifdef __EMX__
143
144 typedef struct
145 {
146     unsigned long ContextFlags;
147     FLOATING_SAVE_AREA sc_float;
148     unsigned long sc_gs;
149     unsigned long sc_fs;
150     unsigned long sc_es;
151     unsigned long sc_ds;
152     unsigned long sc_edi;
153     unsigned long sc_esi;
154     unsigned long sc_eax;
155     unsigned long sc_ebx;
156     unsigned long sc_ecx;
157     unsigned long sc_edx;
158     unsigned long sc_ebp;
159     unsigned long sc_eip;
160     unsigned long sc_cs;
161     unsigned long sc_eflags;
162     unsigned long sc_esp;
163     unsigned long sc_ss;
164 } SIGCONTEXT;
165
166 #endif  /* __EMX__ */
167
168
169 #if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMX__)
170
171 #define EAX_sig(context)     ((context)->sc_eax)
172 #define EBX_sig(context)     ((context)->sc_ebx)
173 #define ECX_sig(context)     ((context)->sc_ecx)
174 #define EDX_sig(context)     ((context)->sc_edx)
175 #define ESI_sig(context)     ((context)->sc_esi)
176 #define EDI_sig(context)     ((context)->sc_edi)
177 #define EBP_sig(context)     ((context)->sc_ebp)
178                             
179 #define CS_sig(context)      ((context)->sc_cs)
180 #define DS_sig(context)      ((context)->sc_ds)
181 #define ES_sig(context)      ((context)->sc_es)
182 #define SS_sig(context)      ((context)->sc_ss)
183                             
184 /* FS and GS are now in the sigcontext struct of FreeBSD, but not 
185  * saved by the exception handling. duh.
186  * Actually they are in -current (have been for a while), and that
187  * patch now finally has been MFC'd to -stable too (Nov 15 1999).
188  * If you're running a system from the -stable branch older than that,
189  * like a 3.3-RELEASE, grab the patch from the ports tree:
190  * ftp://ftp.freebsd.org/pub/FreeBSD/FreeBSD-current/ports/emulators/wine/files/patch-3.3-sys-fsgs
191  * (If its not yet there when you look, go here:
192  * http://www.jelal.kn-bremen.de/freebsd/ports/emulators/wine/files/ )
193  */
194 #ifdef __FreeBSD__
195 #define FS_sig(context)      ((context)->sc_fs)
196 #define GS_sig(context)      ((context)->sc_gs)
197 #endif
198
199 #ifdef linux
200 #define FS_sig(context)      ((context)->sc_fs)
201 #define GS_sig(context)      ((context)->sc_gs)
202 #define CR2_sig(context)     ((context)->cr2)
203 #define TRAP_sig(context)    ((context)->sc_trapno)
204 #define ERROR_sig(context)   ((context)->sc_err)
205 #define FPU_sig(context)     ((FLOATING_SAVE_AREA*)((context)->i387))
206 #endif
207
208 #ifndef __FreeBSD__
209 #define EFL_sig(context)     ((context)->sc_eflags)
210 #else                       
211 #define EFL_sig(context)     ((context)->sc_efl)
212 /* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge  */
213 #define CR2_sig(context)     ((context)->sc_err)
214 #define TRAP_sig(context)    ((context)->sc_trapno)
215 #endif                      
216
217 #define EIP_sig(context)     (*((unsigned long*)&(context)->sc_eip))
218 #define ESP_sig(context)     (*((unsigned long*)&(context)->sc_esp))
219
220 #endif  /* linux || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
221
222 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
223
224 #ifdef _SCO_DS
225 #define gregs regs
226 #endif
227
228 #define EAX_sig(context)     ((context)->uc_mcontext.gregs[EAX])
229 #define EBX_sig(context)     ((context)->uc_mcontext.gregs[EBX])
230 #define ECX_sig(context)     ((context)->uc_mcontext.gregs[ECX])
231 #define EDX_sig(context)     ((context)->uc_mcontext.gregs[EDX])
232 #define ESI_sig(context)     ((context)->uc_mcontext.gregs[ESI])
233 #define EDI_sig(context)     ((context)->uc_mcontext.gregs[EDI])
234 #define EBP_sig(context)     ((context)->uc_mcontext.gregs[EBP])
235                             
236 #define CS_sig(context)      ((context)->uc_mcontext.gregs[CS])
237 #define DS_sig(context)      ((context)->uc_mcontext.gregs[DS])
238 #define ES_sig(context)      ((context)->uc_mcontext.gregs[ES])
239 #define SS_sig(context)      ((context)->uc_mcontext.gregs[SS])
240                             
241 #define FS_sig(context)      ((context)->uc_mcontext.gregs[FS])
242 #define GS_sig(context)      ((context)->uc_mcontext.gregs[GS])
243
244 #define EFL_sig(context)     ((context)->uc_mcontext.gregs[EFL])
245                             
246 #define EIP_sig(context)     ((context)->uc_mcontext.gregs[EIP])
247 #ifdef R_ESP
248 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[R_ESP])
249 #else
250 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[ESP])
251 #endif
252 #ifdef TRAPNO
253 #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[TRAPNO])
254 #endif
255
256 #endif  /* svr4 || SCO_DS */
257
258
259 /* exception code definitions (already defined by FreeBSD) */
260 #ifndef __FreeBSD__  /* FIXME: other BSDs? */
261 #define T_DIVIDE        0   /* Division by zero exception */
262 #define T_TRCTRAP       1   /* Single-step exception */
263 #define T_NMI           2   /* NMI interrupt */
264 #define T_BPTFLT        3   /* Breakpoint exception */
265 #define T_OFLOW         4   /* Overflow exception */
266 #define T_BOUND         5   /* Bound range exception */
267 #define T_PRIVINFLT     6   /* Invalid opcode exception */
268 #define T_DNA           7   /* Device not available exception */
269 #define T_DOUBLEFLT     8   /* Double fault exception */
270 #define T_FPOPFLT       9   /* Coprocessor segment overrun */
271 #define T_TSSFLT        10  /* Invalid TSS exception */
272 #define T_SEGNPFLT      11  /* Segment not present exception */
273 #define T_STKFLT        12  /* Stack fault */
274 #define T_PROTFLT       13  /* General protection fault */
275 #define T_PAGEFLT       14  /* Page fault */
276 #define T_RESERVED      15  /* Unknown exception */
277 #define T_ARITHTRAP     16  /* Floating point exception */
278 #define T_ALIGNFLT      17  /* Alignment check exception */
279 #define T_MCHK          18  /* Machine check exception */
280 #define T_CACHEFLT      19  /* Cache flush exception */
281 #endif
282
283 #define T_UNKNOWN     (-1)  /* Unknown fault (TRAP_sig not defined) */
284
285 #include "wine/exception.h"
286 #include "winnt.h"
287 #include "stackframe.h"
288 #include "global.h"
289 #include "miscemu.h"
290 #include "ntddk.h"
291 #include "syslevel.h"
292 #include "debugtools.h"
293
294 DEFAULT_DEBUG_CHANNEL(seh)
295
296
297
298 /***********************************************************************
299  *           handler_init
300  *
301  * Initialization code for a signal handler.
302  * Restores the proper %fs value for the current thread.
303  */
304 static inline void handler_init( CONTEXT *context, const SIGCONTEXT *sigcontext )
305 {
306     WORD fs;
307     /* get %fs at time of the fault */
308 #ifdef FS_sig
309     fs = FS_sig(sigcontext);
310 #else
311     GET_FS(fs);
312 #endif
313     context->SegFs = fs;
314     /* now restore a proper %fs for the fault handler */
315     if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext))) fs = SYSLEVEL_Win16CurrentTeb;
316     if (!fs) fs = SYSLEVEL_EmergencyTeb;
317     SET_FS(fs);
318 }
319
320 /***********************************************************************
321  *           get_trap_code
322  *
323  * Get the trap code for a signal.
324  */
325 static inline int get_trap_code( const SIGCONTEXT *sigcontext )
326 {
327 #ifdef TRAP_sig
328     return TRAP_sig(sigcontext);
329 #else
330     return T_UNKNOWN;  /* unknown trap code */
331 #endif
332 }
333
334 /***********************************************************************
335  *           save_context
336  *
337  * Set the register values from a sigcontext. 
338  */
339 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
340 {
341     context->Eax    = EAX_sig(sigcontext);
342     context->Ebx    = EBX_sig(sigcontext);
343     context->Ecx    = ECX_sig(sigcontext);
344     context->Edx    = EDX_sig(sigcontext);
345     context->Esi    = ESI_sig(sigcontext);
346     context->Edi    = EDI_sig(sigcontext);
347     context->Ebp    = EBP_sig(sigcontext);
348     context->EFlags = EFL_sig(sigcontext);
349     context->Eip    = EIP_sig(sigcontext);
350     context->Esp    = ESP_sig(sigcontext);
351     context->SegCs  = LOWORD(CS_sig(sigcontext));
352     context->SegDs  = LOWORD(DS_sig(sigcontext));
353     context->SegEs  = LOWORD(ES_sig(sigcontext));
354     context->SegSs  = LOWORD(SS_sig(sigcontext));
355     /* %fs already handled in handler_init */
356 #ifdef GS_sig
357     context->SegGs  = LOWORD(GS_sig(sigcontext));
358 #else
359     GET_GS( context->SegGs );
360     context->SegGs &= 0xffff;
361 #endif
362     if (ISV86(context)) V86BASE(context) = (DWORD)DOSMEM_MemoryBase(0);
363 }
364
365
366 /***********************************************************************
367  *           restore_context
368  *
369  * Build a sigcontext from the register values.
370  */
371 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
372 {
373     EAX_sig(sigcontext) = context->Eax;
374     EBX_sig(sigcontext) = context->Ebx;
375     ECX_sig(sigcontext) = context->Ecx;
376     EDX_sig(sigcontext) = context->Edx;
377     ESI_sig(sigcontext) = context->Esi;
378     EDI_sig(sigcontext) = context->Edi;
379     EBP_sig(sigcontext) = context->Ebp;
380     EFL_sig(sigcontext) = context->EFlags;
381     EIP_sig(sigcontext) = context->Eip;
382     ESP_sig(sigcontext) = context->Esp;
383     CS_sig(sigcontext)  = context->SegCs;
384     DS_sig(sigcontext)  = context->SegDs;
385     ES_sig(sigcontext)  = context->SegEs;
386     SS_sig(sigcontext)  = context->SegSs;
387 #ifdef FS_sig
388     FS_sig(sigcontext)  = context->SegFs;
389 #else
390     SET_FS( context->SegFs );
391 #endif
392 #ifdef GS_sig
393     GS_sig(sigcontext)  = context->SegGs;
394 #else
395     SET_GS( context->SegGs );
396 #endif
397 }
398
399
400 /***********************************************************************
401  *           save_fpu
402  *
403  * Set the FPU context from a sigcontext. 
404  */
405 static void inline save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
406 {
407 #ifdef FPU_sig
408     if (FPU_sig(sigcontext))
409     {
410         context->FloatSave = *FPU_sig(sigcontext);
411         return;
412     }
413 #endif  /* FPU_sig */
414 #ifdef __GNUC__
415     __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
416 #endif  /* __GNUC__ */
417 }
418
419
420 /***********************************************************************
421  *           restore_fpu
422  *
423  * Restore the FPU context to a sigcontext. 
424  */
425 static void inline restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
426 {
427 #ifdef FPU_sig
428     if (FPU_sig(sigcontext))
429     {
430         *FPU_sig(sigcontext) = context->FloatSave;
431         return;
432     }
433 #endif  /* FPU_sig */
434 #ifdef __GNUC__
435     /* avoid nested exceptions */
436     context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80;
437     __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) );
438 #endif  /* __GNUC__ */
439 }
440
441
442 /**********************************************************************
443  *              get_fpu_code
444  *
445  * Get the FPU exception code from the FPU status.
446  */
447 static inline DWORD get_fpu_code( const CONTEXT *context )
448 {
449     DWORD status = context->FloatSave.StatusWord;
450
451     if (status & 0x01)  /* IE */
452     {
453         if (status & 0x40)  /* SF */
454             return EXCEPTION_FLT_STACK_CHECK;
455         else
456             return EXCEPTION_FLT_INVALID_OPERATION;
457     }
458     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
459     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
460     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
461     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
462     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
463     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
464 }
465
466
467 /**********************************************************************
468  *              segv_handler
469  *
470  * Handler for SIGSEGV and related errors.
471  */
472 static HANDLER_DEF(segv_handler)
473 {
474     EXCEPTION_RECORD rec;
475     CONTEXT context;
476
477     handler_init( &context, HANDLER_CONTEXT );
478
479 #ifdef CR2_sig
480     /* we want the page-fault case to be fast */
481     if (get_trap_code(HANDLER_CONTEXT) == T_PAGEFLT)
482         if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return;
483 #endif
484
485     save_context( &context, HANDLER_CONTEXT );
486     rec.ExceptionRecord  = NULL;
487     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
488     rec.ExceptionAddress = (LPVOID)context.Eip;
489     rec.NumberParameters = 0;
490
491     switch(get_trap_code(HANDLER_CONTEXT))
492     {
493     case T_OFLOW:   /* Overflow exception */
494         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
495         break;
496     case T_BOUND:   /* Bound range exception */
497         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
498         break;
499     case T_PRIVINFLT:   /* Invalid opcode exception */
500         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
501         break;
502     case T_STKFLT:  /* Stack fault */
503         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
504         break;
505     case T_SEGNPFLT:  /* Segment not present exception */
506     case T_PROTFLT:   /* General protection fault */
507     case T_UNKNOWN:   /* Unknown fault code */
508         if (INSTR_EmulateInstruction( &context )) goto restore;
509         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
510         break;
511     case T_PAGEFLT:  /* Page fault */
512 #ifdef CR2_sig
513         rec.NumberParameters = 2;
514 #ifdef ERROR_sig
515         rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
516 #else
517         rec.ExceptionInformation[0] = 0;
518 #endif /* ERROR_sig */
519         rec.ExceptionInformation[1] = CR2_sig(HANDLER_CONTEXT);
520 #endif /* CR2_sig */
521         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
522         break;
523     case T_ALIGNFLT:  /* Alignment check exception */
524         /* FIXME: pass through exception handler first? */
525         if (context.EFlags & 0x00040000)
526         {
527             /* Disable AC flag, return */
528             context.EFlags &= ~0x00040000;
529             goto restore;
530         }
531         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
532         break;
533     default:
534         ERR( "Got unexpected trap %d\n", get_trap_code(HANDLER_CONTEXT) );
535         /* fall through */
536     case T_NMI:       /* NMI interrupt */
537     case T_DNA:       /* Device not available exception */
538     case T_DOUBLEFLT: /* Double fault exception */
539     case T_TSSFLT:    /* Invalid TSS exception */
540     case T_RESERVED:  /* Unknown exception */
541     case T_MCHK:      /* Machine check exception */
542 #ifdef T_CACHEFLT
543     case T_CACHEFLT:  /* Cache flush exception */
544 #endif
545         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
546         break;
547     }
548
549     EXC_RtlRaiseException( &rec, &context );
550  restore:
551     restore_context( &context, HANDLER_CONTEXT );
552 }
553
554
555 /**********************************************************************
556  *              trap_handler
557  *
558  * Handler for SIGTRAP.
559  */
560 static HANDLER_DEF(trap_handler)
561 {
562     EXCEPTION_RECORD rec;
563     CONTEXT context;
564
565     handler_init( &context, HANDLER_CONTEXT );
566
567     switch(get_trap_code(HANDLER_CONTEXT))
568     {
569     case T_TRCTRAP:  /* Single-step exception */
570         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
571         break;
572     case T_BPTFLT:   /* Breakpoint exception */
573     default:
574         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
575         break;
576     }
577     save_context( &context, HANDLER_CONTEXT );
578     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
579     rec.ExceptionRecord  = NULL;
580     rec.ExceptionAddress = (LPVOID)context.Eip;
581     rec.NumberParameters = 0;
582     EXC_RtlRaiseException( &rec, &context );
583     restore_context( &context, HANDLER_CONTEXT );
584 }
585
586
587 /**********************************************************************
588  *              fpe_handler
589  *
590  * Handler for SIGFPE.
591  */
592 static HANDLER_DEF(fpe_handler)
593 {
594     EXCEPTION_RECORD rec;
595     CONTEXT context;
596
597     handler_init( &context, HANDLER_CONTEXT );
598
599     save_fpu( &context, HANDLER_CONTEXT );
600
601     switch(get_trap_code(HANDLER_CONTEXT))
602     {
603     case T_DIVIDE:   /* Division by zero exception */
604         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
605         break;
606     case T_FPOPFLT:   /* Coprocessor segment overrun */
607         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
608         break;
609     case T_ARITHTRAP:  /* Floating point exception */
610     case T_UNKNOWN:    /* Unknown fault code */
611         rec.ExceptionCode = get_fpu_code( &context );
612         break;
613     default:
614         ERR( "Got unexpected trap %d\n", get_trap_code(HANDLER_CONTEXT) );
615         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
616         break;
617     }
618     save_context( &context, HANDLER_CONTEXT );
619     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
620     rec.ExceptionRecord  = NULL;
621     rec.ExceptionAddress = (LPVOID)context.Eip;
622     rec.NumberParameters = 0;
623     EXC_RtlRaiseException( &rec, &context );
624     restore_context( &context, HANDLER_CONTEXT );
625     restore_fpu( &context, HANDLER_CONTEXT );
626 }
627
628
629 /**********************************************************************
630  *              int_handler
631  *
632  * Handler for SIGINT.
633  */
634 static HANDLER_DEF(int_handler)
635 {
636     EXCEPTION_RECORD rec;
637     CONTEXT context;
638
639     handler_init( &context, HANDLER_CONTEXT );
640     save_context( &context, HANDLER_CONTEXT );
641     rec.ExceptionCode    = CONTROL_C_EXIT;
642     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
643     rec.ExceptionRecord  = NULL;
644     rec.ExceptionAddress = (LPVOID)context.Eip;
645     rec.NumberParameters = 0;
646     EXC_RtlRaiseException( &rec, &context );
647     restore_context( &context, HANDLER_CONTEXT );
648 }
649
650
651 /***********************************************************************
652  *           set_handler
653  *
654  * Set a signal handler
655  */
656 static int set_handler( int sig, void (*func)() )
657 {
658 #ifdef linux
659     struct kernel_sigaction sig_act;
660     sig_act.sa_handler = func;
661     sig_act.sa_flags   = SA_RESTART | SA_NOMASK;
662     sig_act.sa_mask    = 0;
663     /* point to the top of the stack */
664     sig_act.sa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE;
665     return wine_sigaction( sig, &sig_act, NULL );
666 #else  /* linux */
667     struct sigaction sig_act;
668     sig_act.sa_handler = func;
669     sigemptyset( &sig_act.sa_mask );
670
671 # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
672     sig_act.sa_flags = SA_ONSTACK;
673 # elif defined (__svr4__) || defined(_SCO_DS)
674     sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
675 # elif defined(__EMX__)
676     sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
677 # else
678     sig_act.sa_flags = 0;
679 # endif
680     return sigaction( sig, &sig_act, NULL );
681 #endif  /* linux */
682 }
683
684
685 /**********************************************************************
686  *              SIGNAL_Init
687  */
688 BOOL SIGNAL_Init(void)
689 {
690 #ifdef HAVE_WORKING_SIGALTSTACK
691     struct sigaltstack ss;
692     if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
693     {
694         ss.ss_size  = SIGNAL_STACK_SIZE;
695         ss.ss_flags = 0;
696         if (sigaltstack(&ss, NULL) < 0)
697         {
698             perror("sigaltstack");
699             /* fall through on error and try it differently */
700         }
701     }
702 #endif  /* HAVE_SIGALTSTACK */
703     
704     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
705     signal( SIGPIPE, SIG_IGN );
706     /* automatic child reaping to avoid zombies */
707     signal( SIGCHLD, SIG_IGN );
708
709     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
710     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
711     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
712     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
713 #ifdef SIGBUS
714     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
715 #endif
716 #ifdef SIGTRAP
717     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
718 #endif
719     return TRUE;
720
721  error:
722     perror("sigaction");
723     return FALSE;
724 }
725
726 #endif  /* __i386__ */