Moved standard syslevel APIs declaration to winbase.h.
[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 #ifdef HAVE_SYS_VM86_H
29 # include <sys/vm86.h>
30 #endif
31
32 #include "winnt.h"
33 #include "selectors.h"
34
35 /***********************************************************************
36  * signal context platform-specific definitions
37  */
38
39 #ifdef linux
40 typedef struct
41 {
42     unsigned short sc_gs, __gsh;
43     unsigned short sc_fs, __fsh;
44     unsigned short sc_es, __esh;
45     unsigned short sc_ds, __dsh;
46     unsigned long sc_edi;
47     unsigned long sc_esi;
48     unsigned long sc_ebp;
49     unsigned long sc_esp;
50     unsigned long sc_ebx;
51     unsigned long sc_edx;
52     unsigned long sc_ecx;
53     unsigned long sc_eax;
54     unsigned long sc_trapno;
55     unsigned long sc_err;
56     unsigned long sc_eip;
57     unsigned short sc_cs, __csh;
58     unsigned long sc_eflags;
59     unsigned long esp_at_signal;
60     unsigned short sc_ss, __ssh;
61     unsigned long i387;
62     unsigned long oldmask;
63     unsigned long cr2;
64 } SIGCONTEXT;
65
66 #define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context )
67 #define HANDLER_CONTEXT (&__context)
68
69 /* this is the sigaction structure from the Linux 2.1.20 kernel.  */
70 struct kernel_sigaction
71 {
72     void (*ksa_handler)();
73     unsigned long ksa_mask;
74     unsigned long ksa_flags;
75     void *ksa_restorer;
76 };
77
78 /* Similar to the sigaction function in libc, except it leaves alone the
79    restorer field, which is used to specify the signal stack address */
80 static inline int wine_sigaction( int sig, struct kernel_sigaction *new,
81                                   struct kernel_sigaction *old )
82 {
83     __asm__ __volatile__( "pushl %%ebx\n\t"
84                           "movl %2,%%ebx\n\t"
85                           "int $0x80\n\t"
86                           "popl %%ebx"
87                           : "=a" (sig)
88                           : "0" (SYS_sigaction), "r" (sig), "c" (new), "d" (old) );
89     if (sig>=0) return 0;
90     errno = -sig;
91     return -1;
92 }
93
94 #ifdef HAVE_SIGALTSTACK
95 /* direct syscall for sigaltstack to work around glibc 2.0 brain-damage */
96 static inline int wine_sigaltstack( const struct sigaltstack *new,
97                                     struct sigaltstack *old )
98 {
99     int ret;
100     __asm__ __volatile__( "pushl %%ebx\n\t"
101                           "movl %2,%%ebx\n\t"
102                           "int $0x80\n\t"
103                           "popl %%ebx"
104                           : "=a" (ret)
105                           : "0" (SYS_sigaltstack), "r" (new), "c" (old) );
106     if (ret >= 0) return 0;
107     errno = -ret;
108     return -1;
109 }
110 #endif
111
112 int vm86_enter( struct vm86plus_struct *ptr );
113 void vm86_return();
114 __ASM_GLOBAL_FUNC(vm86_enter,
115                   "pushl %ebp\n\t"
116                   "movl %esp, %ebp\n\t"
117                   "movl $166,%eax\n\t"  /*SYS_vm86*/
118                   "pushl %fs\n\t"
119                   "movl 8(%ebp),%ecx\n\t"
120                   "pushl %ebx\n\t"
121                   "movl $1,%ebx\n\t"    /*VM86_ENTER*/
122                   "pushl %ecx\n\t"      /* put vm86plus_struct ptr somewhere we can find it */
123                   "int $0x80\n"
124                   ".globl " __ASM_NAME("vm86_return") "\n\t"
125                   ".type " __ASM_NAME("vm86_return") ",@function\n"
126                   __ASM_NAME("vm86_return") ":\n\t"
127                   "popl %ecx\n\t"
128                   "popl %ebx\n\t"
129                   "popl %fs\n\t"
130                   "popl %ebp\n\t"
131                   "ret" );
132
133 #endif  /* linux */
134
135 #ifdef BSDI
136
137 #define EAX_sig(context)     ((context)->tf_eax)
138 #define EBX_sig(context)     ((context)->tf_ebx)
139 #define ECX_sig(context)     ((context)->tf_ecx)
140 #define EDX_sig(context)     ((context)->tf_edx)
141 #define ESI_sig(context)     ((context)->tf_esi)
142 #define EDI_sig(context)     ((context)->tf_edi)
143 #define EBP_sig(context)     ((context)->tf_ebp)
144                             
145 #define CS_sig(context)      ((context)->tf_cs)
146 #define DS_sig(context)      ((context)->tf_ds)
147 #define ES_sig(context)      ((context)->tf_es)
148 #define SS_sig(context)      ((context)->tf_ss)
149
150 #include <machine/frame.h>
151 typedef struct trapframe SIGCONTEXT;
152
153 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
154 #define HANDLER_CONTEXT __context
155
156 #define EFL_sig(context)     ((context)->tf_eflags)
157
158 #define EIP_sig(context)     (*((unsigned long*)&(context)->tf_eip))
159 #define ESP_sig(context)     (*((unsigned long*)&(context)->tf_esp))
160
161 #endif /* bsdi */
162
163 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
164
165 typedef struct sigcontext SIGCONTEXT;
166
167 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
168 #define HANDLER_CONTEXT __context
169
170 #endif  /* FreeBSD */
171
172 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
173
174 #ifdef _SCO_DS
175 #include <sys/regset.h>
176 #endif
177 /* Solaris kludge */
178 #undef ERR
179 #include <sys/ucontext.h>
180 #undef ERR
181 typedef struct ucontext SIGCONTEXT;
182
183 #define HANDLER_DEF(name) void name( int __signal, void *__siginfo, SIGCONTEXT *__context )
184 #define HANDLER_CONTEXT __context
185
186 #endif  /* svr4 || SCO_DS */
187
188 #ifdef __EMX__
189
190 typedef struct
191 {
192     unsigned long ContextFlags;
193     FLOATING_SAVE_AREA sc_float;
194     unsigned long sc_gs;
195     unsigned long sc_fs;
196     unsigned long sc_es;
197     unsigned long sc_ds;
198     unsigned long sc_edi;
199     unsigned long sc_esi;
200     unsigned long sc_eax;
201     unsigned long sc_ebx;
202     unsigned long sc_ecx;
203     unsigned long sc_edx;
204     unsigned long sc_ebp;
205     unsigned long sc_eip;
206     unsigned long sc_cs;
207     unsigned long sc_eflags;
208     unsigned long sc_esp;
209     unsigned long sc_ss;
210 } SIGCONTEXT;
211
212 #endif  /* __EMX__ */
213
214
215 #if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMX__)
216
217 #define EAX_sig(context)     ((context)->sc_eax)
218 #define EBX_sig(context)     ((context)->sc_ebx)
219 #define ECX_sig(context)     ((context)->sc_ecx)
220 #define EDX_sig(context)     ((context)->sc_edx)
221 #define ESI_sig(context)     ((context)->sc_esi)
222 #define EDI_sig(context)     ((context)->sc_edi)
223 #define EBP_sig(context)     ((context)->sc_ebp)
224                             
225 #define CS_sig(context)      ((context)->sc_cs)
226 #define DS_sig(context)      ((context)->sc_ds)
227 #define ES_sig(context)      ((context)->sc_es)
228 #define SS_sig(context)      ((context)->sc_ss)
229                             
230 /* FS and GS are now in the sigcontext struct of FreeBSD, but not 
231  * saved by the exception handling. duh.
232  * Actually they are in -current (have been for a while), and that
233  * patch now finally has been MFC'd to -stable too (Nov 15 1999).
234  * If you're running a system from the -stable branch older than that,
235  * like a 3.3-RELEASE, grab the patch from the ports tree:
236  * ftp://ftp.freebsd.org/pub/FreeBSD/FreeBSD-current/ports/emulators/wine/files/patch-3.3-sys-fsgs
237  * (If its not yet there when you look, go here:
238  * http://www.jelal.kn-bremen.de/freebsd/ports/emulators/wine/files/ )
239  */
240 #ifdef __FreeBSD__
241 #define FS_sig(context)      ((context)->sc_fs)
242 #define GS_sig(context)      ((context)->sc_gs)
243 #endif
244
245 #ifdef linux
246 #define FS_sig(context)      ((context)->sc_fs)
247 #define GS_sig(context)      ((context)->sc_gs)
248 #define CR2_sig(context)     ((context)->cr2)
249 #define TRAP_sig(context)    ((context)->sc_trapno)
250 #define ERROR_sig(context)   ((context)->sc_err)
251 #define FPU_sig(context)     ((FLOATING_SAVE_AREA*)((context)->i387))
252 #endif
253
254 #ifndef __FreeBSD__
255 #define EFL_sig(context)     ((context)->sc_eflags)
256 #else                       
257 #define EFL_sig(context)     ((context)->sc_efl)
258 /* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge  */
259 #define CR2_sig(context)     ((context)->sc_err)
260 #define TRAP_sig(context)    ((context)->sc_trapno)
261 #endif                      
262
263 #define EIP_sig(context)     (*((unsigned long*)&(context)->sc_eip))
264 #define ESP_sig(context)     (*((unsigned long*)&(context)->sc_esp))
265
266 #endif  /* linux || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
267
268 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
269
270 #ifdef _SCO_DS
271 #define gregs regs
272 #endif
273
274 #define EAX_sig(context)     ((context)->uc_mcontext.gregs[EAX])
275 #define EBX_sig(context)     ((context)->uc_mcontext.gregs[EBX])
276 #define ECX_sig(context)     ((context)->uc_mcontext.gregs[ECX])
277 #define EDX_sig(context)     ((context)->uc_mcontext.gregs[EDX])
278 #define ESI_sig(context)     ((context)->uc_mcontext.gregs[ESI])
279 #define EDI_sig(context)     ((context)->uc_mcontext.gregs[EDI])
280 #define EBP_sig(context)     ((context)->uc_mcontext.gregs[EBP])
281                             
282 #define CS_sig(context)      ((context)->uc_mcontext.gregs[CS])
283 #define DS_sig(context)      ((context)->uc_mcontext.gregs[DS])
284 #define ES_sig(context)      ((context)->uc_mcontext.gregs[ES])
285 #define SS_sig(context)      ((context)->uc_mcontext.gregs[SS])
286                             
287 #define FS_sig(context)      ((context)->uc_mcontext.gregs[FS])
288 #define GS_sig(context)      ((context)->uc_mcontext.gregs[GS])
289
290 #define EFL_sig(context)     ((context)->uc_mcontext.gregs[EFL])
291                             
292 #define EIP_sig(context)     ((context)->uc_mcontext.gregs[EIP])
293 #ifdef R_ESP
294 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[R_ESP])
295 #else
296 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[ESP])
297 #endif
298 #ifdef TRAPNO
299 #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[TRAPNO])
300 #endif
301
302 #endif  /* svr4 || SCO_DS */
303
304
305 /* exception code definitions (already defined by FreeBSD) */
306 #ifndef __FreeBSD__  /* FIXME: other BSDs? */
307 #define T_DIVIDE        0   /* Division by zero exception */
308 #define T_TRCTRAP       1   /* Single-step exception */
309 #define T_NMI           2   /* NMI interrupt */
310 #define T_BPTFLT        3   /* Breakpoint exception */
311 #define T_OFLOW         4   /* Overflow exception */
312 #define T_BOUND         5   /* Bound range exception */
313 #define T_PRIVINFLT     6   /* Invalid opcode exception */
314 #define T_DNA           7   /* Device not available exception */
315 #define T_DOUBLEFLT     8   /* Double fault exception */
316 #define T_FPOPFLT       9   /* Coprocessor segment overrun */
317 #define T_TSSFLT        10  /* Invalid TSS exception */
318 #define T_SEGNPFLT      11  /* Segment not present exception */
319 #define T_STKFLT        12  /* Stack fault */
320 #define T_PROTFLT       13  /* General protection fault */
321 #define T_PAGEFLT       14  /* Page fault */
322 #define T_RESERVED      15  /* Unknown exception */
323 #define T_ARITHTRAP     16  /* Floating point exception */
324 #define T_ALIGNFLT      17  /* Alignment check exception */
325 #define T_MCHK          18  /* Machine check exception */
326 #define T_CACHEFLT      19  /* Cache flush exception */
327 #endif
328
329 #define T_UNKNOWN     (-1)  /* Unknown fault (TRAP_sig not defined) */
330
331 #include "wine/exception.h"
332 #include "winnt.h"
333 #include "stackframe.h"
334 #include "global.h"
335 #include "miscemu.h"
336 #include "ntddk.h"
337 #include "syslevel.h"
338 #include "debugtools.h"
339
340 DEFAULT_DEBUG_CHANNEL(seh);
341
342
343 /***********************************************************************
344  *           get_trap_code
345  *
346  * Get the trap code for a signal.
347  */
348 static inline int get_trap_code( const SIGCONTEXT *sigcontext )
349 {
350 #ifdef TRAP_sig
351     return TRAP_sig(sigcontext);
352 #else
353     return T_UNKNOWN;  /* unknown trap code */
354 #endif
355 }
356
357 /***********************************************************************
358  *           get_error_code
359  *
360  * Get the error code for a signal.
361  */
362 static inline int get_error_code( const SIGCONTEXT *sigcontext )
363 {
364 #ifdef ERROR_sig
365     return ERROR_sig(sigcontext);
366 #else
367     return 0;
368 #endif
369 }
370
371 /***********************************************************************
372  *           get_cr2_value
373  *
374  * Get the CR2 value for a signal.
375  */
376 static inline void *get_cr2_value( const SIGCONTEXT *sigcontext )
377 {
378 #ifdef CR2_sig
379     return (void *)CR2_sig(sigcontext);
380 #else
381     return NULL;
382 #endif
383 }
384
385 /***********************************************************************
386  *           save_context
387  *
388  * Set the register values from a sigcontext. 
389  */
390 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
391 {
392     WORD fs;
393     /* get %fs at time of the fault */
394 #ifdef FS_sig
395     fs = FS_sig(sigcontext);
396 #else
397     fs = __get_fs();
398 #endif
399     context->SegFs = fs;
400
401     /* now restore a proper %fs for the fault handler */
402     if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)))  /* 16-bit mode */
403     {
404         fs = SYSLEVEL_Win16CurrentTeb;
405     }
406 #ifdef linux
407     else if ((void *)EIP_sig(sigcontext) == vm86_return)  /* vm86 mode */
408     {
409         /* retrieve pointer to vm86plus struct that was stored in vm86_enter */
410         struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)ESP_sig(sigcontext);
411         /* fetch the saved %fs on the stack */
412         fs = *((unsigned int *)ESP_sig(sigcontext) + 2);
413         __set_fs(fs);
414         /* get context from vm86 struct */
415         context->Eax    = vm86->regs.eax;
416         context->Ebx    = vm86->regs.ebx;
417         context->Ecx    = vm86->regs.ecx;
418         context->Edx    = vm86->regs.edx;
419         context->Esi    = vm86->regs.esi;
420         context->Edi    = vm86->regs.edi;
421         context->Esp    = vm86->regs.esp;
422         context->Ebp    = vm86->regs.ebp;
423         context->Eip    = vm86->regs.eip;
424         context->SegCs  = vm86->regs.cs;
425         context->SegDs  = vm86->regs.ds;
426         context->SegEs  = vm86->regs.es;
427         context->SegFs  = vm86->regs.fs;
428         context->SegGs  = vm86->regs.gs;
429         context->SegSs  = vm86->regs.ss;
430         context->EFlags = vm86->regs.eflags;
431         return;
432     }
433 #endif  /* linux */
434
435     __set_fs(fs);
436
437     context->Eax    = EAX_sig(sigcontext);
438     context->Ebx    = EBX_sig(sigcontext);
439     context->Ecx    = ECX_sig(sigcontext);
440     context->Edx    = EDX_sig(sigcontext);
441     context->Esi    = ESI_sig(sigcontext);
442     context->Edi    = EDI_sig(sigcontext);
443     context->Ebp    = EBP_sig(sigcontext);
444     context->EFlags = EFL_sig(sigcontext);
445     context->Eip    = EIP_sig(sigcontext);
446     context->Esp    = ESP_sig(sigcontext);
447     context->SegCs  = LOWORD(CS_sig(sigcontext));
448     context->SegDs  = LOWORD(DS_sig(sigcontext));
449     context->SegEs  = LOWORD(ES_sig(sigcontext));
450     context->SegSs  = LOWORD(SS_sig(sigcontext));
451 #ifdef GS_sig
452     context->SegGs  = LOWORD(GS_sig(sigcontext));
453 #else
454     context->SegGs  = __get_gs();
455 #endif
456 }
457
458
459 /***********************************************************************
460  *           restore_context
461  *
462  * Build a sigcontext from the register values.
463  */
464 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
465 {
466 #ifdef linux
467     /* check if exception occurred in vm86 mode */
468     if ((void *)EIP_sig(sigcontext) == vm86_return &&
469         IS_SELECTOR_SYSTEM(CS_sig(sigcontext)))
470     {
471         /* retrieve pointer to vm86plus struct that was stored in vm86_enter */
472         struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)ESP_sig(sigcontext);
473         vm86->regs.eax    = context->Eax;
474         vm86->regs.ebx    = context->Ebx;
475         vm86->regs.ecx    = context->Ecx;
476         vm86->regs.edx    = context->Edx;
477         vm86->regs.esi    = context->Esi;
478         vm86->regs.edi    = context->Edi;
479         vm86->regs.esp    = context->Esp;
480         vm86->regs.ebp    = context->Ebp;
481         vm86->regs.eip    = context->Eip;
482         vm86->regs.cs     = context->SegCs;
483         vm86->regs.ds     = context->SegDs;
484         vm86->regs.es     = context->SegEs;
485         vm86->regs.fs     = context->SegFs;
486         vm86->regs.gs     = context->SegGs;
487         vm86->regs.ss     = context->SegSs;
488         vm86->regs.eflags = context->EFlags;
489         return;
490     }
491 #endif /* linux */
492
493     EAX_sig(sigcontext) = context->Eax;
494     EBX_sig(sigcontext) = context->Ebx;
495     ECX_sig(sigcontext) = context->Ecx;
496     EDX_sig(sigcontext) = context->Edx;
497     ESI_sig(sigcontext) = context->Esi;
498     EDI_sig(sigcontext) = context->Edi;
499     EBP_sig(sigcontext) = context->Ebp;
500     EFL_sig(sigcontext) = context->EFlags;
501     EIP_sig(sigcontext) = context->Eip;
502     ESP_sig(sigcontext) = context->Esp;
503     CS_sig(sigcontext)  = context->SegCs;
504     DS_sig(sigcontext)  = context->SegDs;
505     ES_sig(sigcontext)  = context->SegEs;
506     SS_sig(sigcontext)  = context->SegSs;
507 #ifdef FS_sig
508     FS_sig(sigcontext)  = context->SegFs;
509 #else
510     __set_fs( context->SegFs );
511 #endif
512 #ifdef GS_sig
513     GS_sig(sigcontext)  = context->SegGs;
514 #else
515     __set_gs( context->SegGs );
516 #endif
517 }
518
519
520 /***********************************************************************
521  *           save_fpu
522  *
523  * Set the FPU context from a sigcontext. 
524  */
525 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
526 {
527 #ifdef FPU_sig
528     if (FPU_sig(sigcontext))
529     {
530         context->FloatSave = *FPU_sig(sigcontext);
531         return;
532     }
533 #endif  /* FPU_sig */
534 #ifdef __GNUC__
535     __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
536 #endif  /* __GNUC__ */
537 }
538
539
540 /***********************************************************************
541  *           restore_fpu
542  *
543  * Restore the FPU context to a sigcontext. 
544  */
545 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
546 {
547     /* reset the current interrupt status */
548     context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80;
549 #ifdef FPU_sig
550     if (FPU_sig(sigcontext))
551     {
552         *FPU_sig(sigcontext) = context->FloatSave;
553         return;
554     }
555 #endif  /* FPU_sig */
556 #ifdef __GNUC__
557     /* avoid nested exceptions */
558     __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) );
559 #endif  /* __GNUC__ */
560 }
561
562
563 /**********************************************************************
564  *              get_fpu_code
565  *
566  * Get the FPU exception code from the FPU status.
567  */
568 static inline DWORD get_fpu_code( const CONTEXT *context )
569 {
570     DWORD status = context->FloatSave.StatusWord;
571
572     if (status & 0x01)  /* IE */
573     {
574         if (status & 0x40)  /* SF */
575             return EXCEPTION_FLT_STACK_CHECK;
576         else
577             return EXCEPTION_FLT_INVALID_OPERATION;
578     }
579     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
580     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
581     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
582     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
583     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
584     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
585 }
586
587
588 /**********************************************************************
589  *              do_segv
590  *
591  * Implementation of SIGSEGV handler.
592  */
593 static void do_segv( CONTEXT *context, int trap_code, void *cr2, int err_code )
594 {
595     EXCEPTION_RECORD rec;
596     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
597
598 #ifdef CR2_sig
599     /* we want the page-fault case to be fast */
600     if (trap_code == T_PAGEFLT)
601         if (!(page_fault_code = VIRTUAL_HandleFault( cr2 ))) return;
602 #endif
603
604     rec.ExceptionRecord  = NULL;
605     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
606     rec.ExceptionAddress = (LPVOID)context->Eip;
607     rec.NumberParameters = 0;
608
609     switch(trap_code)
610     {
611     case T_OFLOW:   /* Overflow exception */
612         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
613         break;
614     case T_BOUND:   /* Bound range exception */
615         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
616         break;
617     case T_PRIVINFLT:   /* Invalid opcode exception */
618         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
619         break;
620     case T_STKFLT:  /* Stack fault */
621         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
622         break;
623     case T_SEGNPFLT:  /* Segment not present exception */
624     case T_PROTFLT:   /* General protection fault */
625     case T_UNKNOWN:   /* Unknown fault code */
626         if (INSTR_EmulateInstruction( context )) return;
627         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
628         break;
629     case T_PAGEFLT:  /* Page fault */
630 #ifdef CR2_sig
631         rec.NumberParameters = 2;
632         rec.ExceptionInformation[0] = (err_code & 2) != 0;
633         rec.ExceptionInformation[1] = (DWORD)cr2;
634 #endif /* CR2_sig */
635         rec.ExceptionCode = page_fault_code;
636         break;
637     case T_ALIGNFLT:  /* Alignment check exception */
638         /* FIXME: pass through exception handler first? */
639         if (context->EFlags & 0x00040000)
640         {
641             /* Disable AC flag, return */
642             context->EFlags &= ~0x00040000;
643             return;
644         }
645         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
646         break;
647     default:
648         ERR( "Got unexpected trap %d\n", trap_code );
649         /* fall through */
650     case T_NMI:       /* NMI interrupt */
651     case T_DNA:       /* Device not available exception */
652     case T_DOUBLEFLT: /* Double fault exception */
653     case T_TSSFLT:    /* Invalid TSS exception */
654     case T_RESERVED:  /* Unknown exception */
655     case T_MCHK:      /* Machine check exception */
656 #ifdef T_CACHEFLT
657     case T_CACHEFLT:  /* Cache flush exception */
658 #endif
659         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
660         break;
661     }
662     EXC_RtlRaiseException( &rec, context );
663 }
664
665
666 /**********************************************************************
667  *              do_trap
668  *
669  * Implementation of SIGTRAP handler.
670  */
671 static void do_trap( CONTEXT *context, int trap_code )
672 {
673     EXCEPTION_RECORD rec;
674
675     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
676     rec.ExceptionRecord  = NULL;
677     rec.ExceptionAddress = (LPVOID)context->Eip;
678     rec.NumberParameters = 0;
679
680     switch(trap_code)
681     {
682     case T_TRCTRAP:  /* Single-step exception */
683         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
684         context->EFlags &= ~0x100;  /* clear single-step flag */
685         break;
686     case T_BPTFLT:   /* Breakpoint exception */
687         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
688         /* fall through */
689     default:
690         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
691         break;
692     }
693     EXC_RtlRaiseException( &rec, context );
694 }
695
696
697 /**********************************************************************
698  *              do_fpe
699  *
700  * Implementation of SIGFPE handler
701  */
702 static void do_fpe( CONTEXT *context, int trap_code )
703 {
704     EXCEPTION_RECORD rec;
705
706     switch(trap_code)
707     {
708     case T_DIVIDE:   /* Division by zero exception */
709         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
710         break;
711     case T_FPOPFLT:   /* Coprocessor segment overrun */
712         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
713         break;
714     case T_ARITHTRAP:  /* Floating point exception */
715     case T_UNKNOWN:    /* Unknown fault code */
716         rec.ExceptionCode = get_fpu_code( context );
717         break;
718     default:
719         ERR( "Got unexpected trap %d\n", trap_code );
720         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
721         break;
722     }
723     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
724     rec.ExceptionRecord  = NULL;
725     rec.ExceptionAddress = (LPVOID)context->Eip;
726     rec.NumberParameters = 0;
727     EXC_RtlRaiseException( &rec, context );
728 }
729
730
731 /**********************************************************************
732  *              segv_handler
733  *
734  * Handler for SIGSEGV and related errors.
735  */
736 static HANDLER_DEF(segv_handler)
737 {
738     CONTEXT context;
739     save_context( &context, HANDLER_CONTEXT );
740     do_segv( &context, get_trap_code(HANDLER_CONTEXT),
741              get_cr2_value(HANDLER_CONTEXT), get_error_code(HANDLER_CONTEXT) );
742     restore_context( &context, HANDLER_CONTEXT );
743 }
744
745
746 /**********************************************************************
747  *              trap_handler
748  *
749  * Handler for SIGTRAP.
750  */
751 static HANDLER_DEF(trap_handler)
752 {
753     CONTEXT context;
754     save_context( &context, HANDLER_CONTEXT );
755     do_trap( &context, get_trap_code(HANDLER_CONTEXT) );
756     restore_context( &context, HANDLER_CONTEXT );
757 }
758
759
760 /**********************************************************************
761  *              fpe_handler
762  *
763  * Handler for SIGFPE.
764  */
765 static HANDLER_DEF(fpe_handler)
766 {
767     CONTEXT context;
768     save_fpu( &context, HANDLER_CONTEXT );
769     save_context( &context, HANDLER_CONTEXT );
770     do_fpe( &context, get_trap_code(HANDLER_CONTEXT) );
771     restore_context( &context, HANDLER_CONTEXT );
772     restore_fpu( &context, HANDLER_CONTEXT );
773 }
774
775
776 /**********************************************************************
777  *              int_handler
778  *
779  * Handler for SIGINT.
780  */
781 static HANDLER_DEF(int_handler)
782 {
783     EXCEPTION_RECORD rec;
784     CONTEXT context;
785
786     save_context( &context, HANDLER_CONTEXT );
787     rec.ExceptionCode    = CONTROL_C_EXIT;
788     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
789     rec.ExceptionRecord  = NULL;
790     rec.ExceptionAddress = (LPVOID)context.Eip;
791     rec.NumberParameters = 0;
792     EXC_RtlRaiseException( &rec, &context );
793     restore_context( &context, HANDLER_CONTEXT );
794 }
795
796
797 /***********************************************************************
798  *           set_handler
799  *
800  * Set a signal handler
801  */
802 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
803 {
804     struct sigaction sig_act;
805
806 #ifdef linux
807     if (!have_sigaltstack && NtCurrentTeb()->signal_stack)
808     {
809         struct kernel_sigaction sig_act;
810         sig_act.ksa_handler = func;
811         sig_act.ksa_flags   = SA_RESTART | SA_NOMASK;
812         sig_act.ksa_mask    = 0;
813         /* point to the top of the stack */
814         sig_act.ksa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE;
815         return wine_sigaction( sig, &sig_act, NULL );
816     }
817 #endif  /* linux */
818     sig_act.sa_handler = func;
819     sigemptyset( &sig_act.sa_mask );
820
821 #ifdef linux
822     sig_act.sa_flags = SA_RESTART | SA_NOMASK;
823 #elif defined (__svr4__) || defined(_SCO_DS)
824     sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
825 #else
826     sig_act.sa_flags = 0;
827 #endif
828
829 #ifdef SA_ONSTACK
830     if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
831 #endif
832     return sigaction( sig, &sig_act, NULL );
833 }
834
835
836 /**********************************************************************
837  *              SIGNAL_Init
838  */
839 BOOL SIGNAL_Init(void)
840 {
841     int have_sigaltstack = 0;
842
843 #ifdef HAVE_SIGALTSTACK
844     struct sigaltstack ss;
845     if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
846     {
847         ss.ss_size  = SIGNAL_STACK_SIZE;
848         ss.ss_flags = 0;
849         if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
850 #ifdef linux
851         /* sigaltstack may fail because the kernel is too old, or
852            because glibc is brain-dead. In the latter case a
853            direct system call should succeed. */
854         else if (!wine_sigaltstack(&ss, NULL)) have_sigaltstack = 1;
855 #endif  /* linux */
856     }
857 #endif  /* HAVE_SIGALTSTACK */
858     
859     /* automatic child reaping to avoid zombies */
860     signal( SIGCHLD, SIG_IGN );
861
862     if (set_handler( SIGINT,  have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
863     if (set_handler( SIGFPE,  have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
864     if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
865     if (set_handler( SIGILL,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
866 #ifdef SIGBUS
867     if (set_handler( SIGBUS,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
868 #endif
869 #ifdef SIGTRAP
870     if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
871 #endif
872     return TRUE;
873
874  error:
875     perror("sigaction");
876     return FALSE;
877 }
878
879
880 #ifdef linux
881 /**********************************************************************
882  *              __wine_enter_vm86
883  *
884  * Enter vm86 mode with the specified register context.
885  */
886 void __wine_enter_vm86( CONTEXT *context )
887 {
888     EXCEPTION_RECORD rec;
889     int res;
890     struct vm86plus_struct vm86;
891
892     memset( &vm86, 0, sizeof(vm86) );
893     for (;;)
894     {
895         vm86.regs.eax    = context->Eax;
896         vm86.regs.ebx    = context->Ebx;
897         vm86.regs.ecx    = context->Ecx;
898         vm86.regs.edx    = context->Edx;
899         vm86.regs.esi    = context->Esi;
900         vm86.regs.edi    = context->Edi;
901         vm86.regs.esp    = context->Esp;
902         vm86.regs.ebp    = context->Ebp;
903         vm86.regs.eip    = context->Eip;
904         vm86.regs.cs     = context->SegCs;
905         vm86.regs.ds     = context->SegDs;
906         vm86.regs.es     = context->SegEs;
907         vm86.regs.fs     = context->SegFs;
908         vm86.regs.gs     = context->SegGs;
909         vm86.regs.ss     = context->SegSs;
910         vm86.regs.eflags = context->EFlags;
911
912         do
913         {
914             res = vm86_enter( &vm86 );
915             if (res < 0)
916             {
917                 errno = -res;
918                 return;
919             }
920         } while (VM86_TYPE(res) == VM86_SIGNAL);
921
922         context->Eax    = vm86.regs.eax;
923         context->Ebx    = vm86.regs.ebx;
924         context->Ecx    = vm86.regs.ecx;
925         context->Edx    = vm86.regs.edx;
926         context->Esi    = vm86.regs.esi;
927         context->Edi    = vm86.regs.edi;
928         context->Esp    = vm86.regs.esp;
929         context->Ebp    = vm86.regs.ebp;
930         context->Eip    = vm86.regs.eip;
931         context->SegCs  = vm86.regs.cs;
932         context->SegDs  = vm86.regs.ds;
933         context->SegEs  = vm86.regs.es;
934         context->SegFs  = vm86.regs.fs;
935         context->SegGs  = vm86.regs.gs;
936         context->SegSs  = vm86.regs.ss;
937         context->EFlags = vm86.regs.eflags;
938
939         switch(VM86_TYPE(res))
940         {
941         case VM86_UNKNOWN: /* unhandled GP fault - IO-instruction or similar */
942             do_segv( context, T_PROTFLT, 0, 0 );
943             continue;
944         case VM86_TRAP: /* return due to DOS-debugger request */
945             do_trap( context, VM86_ARG(res)  );
946             continue;
947         case VM86_INTx: /* int3/int x instruction (ARG = x) */
948             rec.ExceptionCode = EXCEPTION_VM86_INTx;
949             break;
950         case VM86_STI: /* sti/popf/iret instruction enabled virtual interrupts */
951             rec.ExceptionCode = EXCEPTION_VM86_STI;
952             break;
953         case VM86_PICRETURN: /* return due to pending PIC request */
954             rec.ExceptionCode = EXCEPTION_VM86_PICRETURN;
955             break;
956         default:
957             ERR( "unhandled result from vm86 mode %x\n", res );
958             continue;
959         }
960         rec.ExceptionFlags          = EXCEPTION_CONTINUABLE;
961         rec.ExceptionRecord         = NULL;
962         rec.ExceptionAddress        = (LPVOID)context->Eip;
963         rec.NumberParameters        = 1;
964         rec.ExceptionInformation[0] = VM86_ARG(res);
965         EXC_RtlRaiseException( &rec, context );
966     }
967 }
968
969 #else /* linux */
970 void __wine_enter_vm86( CONTEXT *context )
971 {
972     MESSAGE("vm86 mode not supported on this platform\n");
973 }
974 #endif /* linux */
975
976 /**********************************************************************
977  *              DbgBreakPoint   (NTDLL)
978  */
979 void WINAPI DbgBreakPoint(void);
980 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
981
982 /**********************************************************************
983  *              DbgUserBreakPoint   (NTDLL)
984  */
985 void WINAPI DbgUserBreakPoint(void);
986 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
987
988 #endif  /* __i386__ */