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