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