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