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