Keep track of per-column information inside the listview.
[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 "winternl.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 "stackframe.h"
412 #include "global.h"
413 #include "miscemu.h"
414 #include "syslevel.h"
415 #include "wine/debug.h"
416
417 WINE_DEFAULT_DEBUG_CHANNEL(seh);
418
419 typedef int (*wine_signal_handler)(unsigned int sig);
420
421 static wine_signal_handler handlers[256];
422
423 static sigset_t all_sigs;
424
425
426 /***********************************************************************
427  *           dispatch_signal
428  */
429 inline static int dispatch_signal(unsigned int sig)
430 {
431     if (handlers[sig] == NULL) return 0;
432     return handlers[sig](sig);
433 }
434
435
436 /***********************************************************************
437  *           get_trap_code
438  *
439  * Get the trap code for a signal.
440  */
441 static inline int get_trap_code( const SIGCONTEXT *sigcontext )
442 {
443 #ifdef TRAP_sig
444     return TRAP_sig(sigcontext);
445 #else
446     return T_UNKNOWN;  /* unknown trap code */
447 #endif
448 }
449
450 /***********************************************************************
451  *           get_error_code
452  *
453  * Get the error code for a signal.
454  */
455 static inline int get_error_code( const SIGCONTEXT *sigcontext )
456 {
457 #ifdef ERROR_sig
458     return ERROR_sig(sigcontext);
459 #else
460     return 0;
461 #endif
462 }
463
464 /***********************************************************************
465  *           get_cr2_value
466  *
467  * Get the CR2 value for a signal.
468  */
469 static inline void *get_cr2_value( const SIGCONTEXT *sigcontext )
470 {
471 #ifdef CR2_sig
472     return (void *)CR2_sig(sigcontext);
473 #else
474     return NULL;
475 #endif
476 }
477
478
479 #ifdef __HAVE_VM86
480 /***********************************************************************
481  *           save_vm86_context
482  *
483  * Set the register values from a vm86 structure.
484  */
485 static void save_vm86_context( CONTEXT *context, const struct vm86plus_struct *vm86 )
486 {
487     context->Eax    = vm86->regs.eax;
488     context->Ebx    = vm86->regs.ebx;
489     context->Ecx    = vm86->regs.ecx;
490     context->Edx    = vm86->regs.edx;
491     context->Esi    = vm86->regs.esi;
492     context->Edi    = vm86->regs.edi;
493     context->Esp    = vm86->regs.esp;
494     context->Ebp    = vm86->regs.ebp;
495     context->Eip    = vm86->regs.eip;
496     context->SegCs  = vm86->regs.cs;
497     context->SegDs  = vm86->regs.ds;
498     context->SegEs  = vm86->regs.es;
499     context->SegFs  = vm86->regs.fs;
500     context->SegGs  = vm86->regs.gs;
501     context->SegSs  = vm86->regs.ss;
502     context->EFlags = vm86->regs.eflags;
503 }
504
505
506 /***********************************************************************
507  *           restore_vm86_context
508  *
509  * Build a vm86 structure from the register values.
510  */
511 static void restore_vm86_context( const CONTEXT *context, struct vm86plus_struct *vm86 )
512 {
513     vm86->regs.eax    = context->Eax;
514     vm86->regs.ebx    = context->Ebx;
515     vm86->regs.ecx    = context->Ecx;
516     vm86->regs.edx    = context->Edx;
517     vm86->regs.esi    = context->Esi;
518     vm86->regs.edi    = context->Edi;
519     vm86->regs.esp    = context->Esp;
520     vm86->regs.ebp    = context->Ebp;
521     vm86->regs.eip    = context->Eip;
522     vm86->regs.cs     = context->SegCs;
523     vm86->regs.ds     = context->SegDs;
524     vm86->regs.es     = context->SegEs;
525     vm86->regs.fs     = context->SegFs;
526     vm86->regs.gs     = context->SegGs;
527     vm86->regs.ss     = context->SegSs;
528     vm86->regs.eflags = context->EFlags;
529 }
530 #endif /* __HAVE_VM86 */
531
532
533 /***********************************************************************
534  *           save_context
535  *
536  * Set the register values from a sigcontext.
537  */
538 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
539 {
540     WORD fs;
541     /* get %fs at time of the fault */
542 #ifdef FS_sig
543     fs = FS_sig(sigcontext);
544 #else
545     fs = wine_get_fs();
546 #endif
547     context->SegFs = fs;
548
549     /* now restore a proper %fs for the fault handler */
550     if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)))  /* 16-bit mode */
551     {
552         fs = SYSLEVEL_Win16CurrentTeb;
553     }
554 #ifdef __HAVE_VM86
555     else if ((void *)EIP_sig(sigcontext) == vm86_return)  /* vm86 mode */
556     {
557         /* fetch the saved %fs on the stack */
558         fs = *(unsigned int *)ESP_sig(sigcontext);
559         if (EAX_sig(sigcontext) == VM86_EAX) {
560             struct vm86plus_struct *vm86;
561             wine_set_fs(fs);
562             /* retrieve pointer to vm86plus struct that was stored in vm86_enter
563              * (but we could also get if from teb->vm86_ptr) */
564             vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
565             /* get context from vm86 struct */
566             save_vm86_context( context, vm86 );
567             return;
568         }
569     }
570 #endif  /* __HAVE_VM86 */
571
572     wine_set_fs(fs);
573
574     context->Eax    = EAX_sig(sigcontext);
575     context->Ebx    = EBX_sig(sigcontext);
576     context->Ecx    = ECX_sig(sigcontext);
577     context->Edx    = EDX_sig(sigcontext);
578     context->Esi    = ESI_sig(sigcontext);
579     context->Edi    = EDI_sig(sigcontext);
580     context->Ebp    = EBP_sig(sigcontext);
581     context->EFlags = EFL_sig(sigcontext);
582     context->Eip    = EIP_sig(sigcontext);
583     context->Esp    = ESP_sig(sigcontext);
584     context->SegCs  = LOWORD(CS_sig(sigcontext));
585     context->SegDs  = LOWORD(DS_sig(sigcontext));
586     context->SegEs  = LOWORD(ES_sig(sigcontext));
587     context->SegSs  = LOWORD(SS_sig(sigcontext));
588 #ifdef GS_sig
589     context->SegGs  = LOWORD(GS_sig(sigcontext));
590 #else
591     context->SegGs  = wine_get_gs();
592 #endif
593 }
594
595
596 /***********************************************************************
597  *           restore_context
598  *
599  * Build a sigcontext from the register values.
600  */
601 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
602 {
603 #ifdef __HAVE_VM86
604     /* check if exception occurred in vm86 mode */
605     if ((void *)EIP_sig(sigcontext) == vm86_return &&
606         IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
607         EAX_sig(sigcontext) == VM86_EAX)
608     {
609         /* retrieve pointer to vm86plus struct that was stored in vm86_enter
610          * (but we could also get it from teb->vm86_ptr) */
611         struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
612         restore_vm86_context( context, vm86 );
613         return;
614     }
615 #endif /* __HAVE_VM86 */
616
617     EAX_sig(sigcontext) = context->Eax;
618     EBX_sig(sigcontext) = context->Ebx;
619     ECX_sig(sigcontext) = context->Ecx;
620     EDX_sig(sigcontext) = context->Edx;
621     ESI_sig(sigcontext) = context->Esi;
622     EDI_sig(sigcontext) = context->Edi;
623     EBP_sig(sigcontext) = context->Ebp;
624     EFL_sig(sigcontext) = context->EFlags;
625     EIP_sig(sigcontext) = context->Eip;
626     ESP_sig(sigcontext) = context->Esp;
627     CS_sig(sigcontext)  = context->SegCs;
628     DS_sig(sigcontext)  = context->SegDs;
629     ES_sig(sigcontext)  = context->SegEs;
630     SS_sig(sigcontext)  = context->SegSs;
631 #ifdef FS_sig
632     FS_sig(sigcontext)  = context->SegFs;
633 #else
634     wine_set_fs( context->SegFs );
635 #endif
636 #ifdef GS_sig
637     GS_sig(sigcontext)  = context->SegGs;
638 #else
639     wine_set_gs( context->SegGs );
640 #endif
641 }
642
643
644 /***********************************************************************
645  *           save_fpu
646  *
647  * Set the FPU context from a sigcontext.
648  */
649 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
650 {
651 #ifdef FPU_sig
652     if (FPU_sig(sigcontext))
653     {
654         context->FloatSave = *FPU_sig(sigcontext);
655         return;
656     }
657 #endif  /* FPU_sig */
658 #ifdef __GNUC__
659     __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
660 #endif  /* __GNUC__ */
661 }
662
663
664 /***********************************************************************
665  *           restore_fpu
666  *
667  * Restore the FPU context to a sigcontext.
668  */
669 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
670 {
671     /* reset the current interrupt status */
672     context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80;
673 #ifdef FPU_sig
674     if (FPU_sig(sigcontext))
675     {
676         *FPU_sig(sigcontext) = context->FloatSave;
677         return;
678     }
679 #endif  /* FPU_sig */
680 #ifdef __GNUC__
681     /* avoid nested exceptions */
682     __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) );
683 #endif  /* __GNUC__ */
684 }
685
686
687 /**********************************************************************
688  *              get_fpu_code
689  *
690  * Get the FPU exception code from the FPU status.
691  */
692 static inline DWORD get_fpu_code( const CONTEXT *context )
693 {
694     DWORD status = context->FloatSave.StatusWord;
695
696     if (status & 0x01)  /* IE */
697     {
698         if (status & 0x40)  /* SF */
699             return EXCEPTION_FLT_STACK_CHECK;
700         else
701             return EXCEPTION_FLT_INVALID_OPERATION;
702     }
703     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
704     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
705     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
706     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
707     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
708     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
709 }
710
711
712 /***********************************************************************
713  *           SIGNAL_Unblock
714  *
715  * Unblock signals. Called from EXC_RtlRaiseException.
716  */
717 void SIGNAL_Unblock( void )
718 {
719     sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
720 }
721
722
723 /**********************************************************************
724  *              do_segv
725  *
726  * Implementation of SIGSEGV handler.
727  */
728 static void do_segv( CONTEXT *context, int trap_code, void *cr2, int err_code )
729 {
730     EXCEPTION_RECORD rec;
731     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
732
733 #ifdef CR2_sig
734     /* we want the page-fault case to be fast */
735     if (trap_code == T_PAGEFLT)
736         if (!(page_fault_code = VIRTUAL_HandleFault( cr2 ))) return;
737 #endif
738
739     rec.ExceptionRecord  = NULL;
740     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
741     rec.ExceptionAddress = (LPVOID)context->Eip;
742     rec.NumberParameters = 0;
743
744     switch(trap_code)
745     {
746     case T_OFLOW:   /* Overflow exception */
747         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
748         break;
749     case T_BOUND:   /* Bound range exception */
750         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
751         break;
752     case T_PRIVINFLT:   /* Invalid opcode exception */
753         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
754         break;
755     case T_STKFLT:  /* Stack fault */
756         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
757         break;
758     case T_SEGNPFLT:  /* Segment not present exception */
759     case T_PROTFLT:   /* General protection fault */
760     case T_UNKNOWN:   /* Unknown fault code */
761         if (INSTR_EmulateInstruction( context )) return;
762         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
763         break;
764     case T_PAGEFLT:  /* Page fault */
765 #ifdef CR2_sig
766         rec.NumberParameters = 2;
767         rec.ExceptionInformation[0] = (err_code & 2) != 0;
768         rec.ExceptionInformation[1] = (DWORD)cr2;
769 #endif /* CR2_sig */
770         rec.ExceptionCode = page_fault_code;
771         break;
772     case T_ALIGNFLT:  /* Alignment check exception */
773         /* FIXME: pass through exception handler first? */
774         if (context->EFlags & 0x00040000)
775         {
776             /* Disable AC flag, return */
777             context->EFlags &= ~0x00040000;
778             return;
779         }
780         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
781         break;
782     default:
783         ERR( "Got unexpected trap %d\n", trap_code );
784         /* fall through */
785     case T_NMI:       /* NMI interrupt */
786     case T_DNA:       /* Device not available exception */
787     case T_DOUBLEFLT: /* Double fault exception */
788     case T_TSSFLT:    /* Invalid TSS exception */
789     case T_RESERVED:  /* Unknown exception */
790     case T_MCHK:      /* Machine check exception */
791 #ifdef T_CACHEFLT
792     case T_CACHEFLT:  /* Cache flush exception */
793 #endif
794         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
795         break;
796     }
797     EXC_RtlRaiseException( &rec, context );
798 }
799
800
801 /**********************************************************************
802  *              do_trap
803  *
804  * Implementation of SIGTRAP handler.
805  */
806 static void do_trap( CONTEXT *context, int trap_code )
807 {
808     EXCEPTION_RECORD rec;
809
810     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
811     rec.ExceptionRecord  = NULL;
812     rec.ExceptionAddress = (LPVOID)context->Eip;
813     rec.NumberParameters = 0;
814
815     switch(trap_code)
816     {
817     case T_TRCTRAP:  /* Single-step exception */
818         if (context->EFlags & 0x100)
819         {
820             rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
821             context->EFlags &= ~0x100;  /* clear single-step flag */
822         }
823         else
824         {
825             /* likely we get this because of a kill(SIGTRAP) on ourself,
826              * so send a bp exception instead of a single step exception
827              */
828             TRACE("Spurious single step trap => breakpoint simulation\n");
829             rec.ExceptionCode = EXCEPTION_BREAKPOINT;
830         }
831         break;
832     case T_BPTFLT:   /* Breakpoint exception */
833         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
834         /* fall through */
835     default:
836         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
837         break;
838     }
839     EXC_RtlRaiseException( &rec, context );
840 }
841
842
843 /**********************************************************************
844  *              do_fpe
845  *
846  * Implementation of SIGFPE handler
847  */
848 static void do_fpe( CONTEXT *context, int trap_code )
849 {
850     EXCEPTION_RECORD rec;
851
852     switch(trap_code)
853     {
854     case T_DIVIDE:   /* Division by zero exception */
855         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
856         break;
857     case T_FPOPFLT:   /* Coprocessor segment overrun */
858         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
859         break;
860     case T_ARITHTRAP:  /* Floating point exception */
861     case T_UNKNOWN:    /* Unknown fault code */
862         rec.ExceptionCode = get_fpu_code( context );
863         break;
864     default:
865         ERR( "Got unexpected trap %d\n", trap_code );
866         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
867         break;
868     }
869     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
870     rec.ExceptionRecord  = NULL;
871     rec.ExceptionAddress = (LPVOID)context->Eip;
872     rec.NumberParameters = 0;
873     EXC_RtlRaiseException( &rec, context );
874 }
875
876
877 #ifdef __HAVE_VM86
878 /**********************************************************************
879  *              set_vm86_pend
880  *
881  * Handler for SIGUSR2, which we use to set the vm86 pending flag.
882  */
883 static void set_vm86_pend( CONTEXT *context )
884 {
885     EXCEPTION_RECORD rec;
886     TEB *teb = NtCurrentTeb();
887     struct vm86plus_struct *vm86 = (struct vm86plus_struct*)(teb->vm86_ptr);
888
889     rec.ExceptionCode           = EXCEPTION_VM86_STI;
890     rec.ExceptionFlags          = EXCEPTION_CONTINUABLE;
891     rec.ExceptionRecord         = NULL;
892     rec.NumberParameters        = 1;
893     rec.ExceptionInformation[0] = 0;
894
895     /* __wine_enter_vm86() merges the vm86_pending flag in safely */
896     teb->vm86_pending |= VIP_MASK;
897     /* see if we were in VM86 mode */
898     if (context->EFlags & 0x00020000)
899     {
900         /* seems so, also set flag in signal context */
901         if (context->EFlags & VIP_MASK) return;
902         context->EFlags |= VIP_MASK;
903         vm86->regs.eflags |= VIP_MASK; /* no exception recursion */
904         if (context->EFlags & VIF_MASK) {
905             /* VIF is set, throw exception */
906             teb->vm86_pending = 0;
907             teb->vm86_ptr = NULL;
908             rec.ExceptionAddress = (LPVOID)context->Eip;
909             EXC_RtlRaiseException( &rec, context );
910             teb->vm86_ptr = vm86;
911         }
912     }
913     else if (vm86)
914     {
915         /* not in VM86, but possibly setting up for it */
916         if (vm86->regs.eflags & VIP_MASK) return;
917         vm86->regs.eflags |= VIP_MASK;
918         if (((char*)context->Eip >= (char*)vm86_return) &&
919             ((char*)context->Eip <= (char*)vm86_return_end) &&
920             (VM86_TYPE(context->Eax) != VM86_SIGNAL)) {
921             /* exiting from VM86, can't throw */
922             return;
923         }
924         if (vm86->regs.eflags & VIF_MASK) {
925             /* VIF is set, throw exception */
926             CONTEXT vcontext;
927             teb->vm86_pending = 0;
928             teb->vm86_ptr = NULL;
929             save_vm86_context( &vcontext, vm86 );
930             rec.ExceptionAddress = (LPVOID)vcontext.Eip;
931             EXC_RtlRaiseException( &rec, &vcontext );
932             teb->vm86_ptr = vm86;
933             restore_vm86_context( &vcontext, vm86 );
934         }
935     }
936 }
937
938
939 /**********************************************************************
940  *              usr2_handler
941  *
942  * Handler for SIGUSR2.
943  * We use it to signal that the running __wine_enter_vm86() should
944  * immediately set VIP_MASK, causing pending events to be handled
945  * as early as possible.
946  */
947 static HANDLER_DEF(usr2_handler)
948 {
949     CONTEXT context;
950
951     save_context( &context, HANDLER_CONTEXT );
952     set_vm86_pend( &context );
953     restore_context( &context, HANDLER_CONTEXT );
954 }
955
956
957 /**********************************************************************
958  *              alrm_handler
959  *
960  * Handler for SIGALRM.
961  * Increases the alarm counter and sets the vm86 pending flag.
962  */
963 static HANDLER_DEF(alrm_handler)
964 {
965     CONTEXT context;
966
967     save_context( &context, HANDLER_CONTEXT );
968     NtCurrentTeb()->alarms++;
969     set_vm86_pend( &context );
970     restore_context( &context, HANDLER_CONTEXT );
971 }
972 #endif /* __HAVE_VM86 */
973
974
975 /**********************************************************************
976  *              segv_handler
977  *
978  * Handler for SIGSEGV and related errors.
979  */
980 static HANDLER_DEF(segv_handler)
981 {
982     CONTEXT context;
983     save_context( &context, HANDLER_CONTEXT );
984     do_segv( &context, get_trap_code(HANDLER_CONTEXT),
985              get_cr2_value(HANDLER_CONTEXT), get_error_code(HANDLER_CONTEXT) );
986     restore_context( &context, HANDLER_CONTEXT );
987 }
988
989
990 /**********************************************************************
991  *              trap_handler
992  *
993  * Handler for SIGTRAP.
994  */
995 static HANDLER_DEF(trap_handler)
996 {
997     CONTEXT context;
998     save_context( &context, HANDLER_CONTEXT );
999     do_trap( &context, get_trap_code(HANDLER_CONTEXT) );
1000     restore_context( &context, HANDLER_CONTEXT );
1001 }
1002
1003
1004 /**********************************************************************
1005  *              fpe_handler
1006  *
1007  * Handler for SIGFPE.
1008  */
1009 static HANDLER_DEF(fpe_handler)
1010 {
1011     CONTEXT context;
1012     save_fpu( &context, HANDLER_CONTEXT );
1013     save_context( &context, HANDLER_CONTEXT );
1014     do_fpe( &context, get_trap_code(HANDLER_CONTEXT) );
1015     restore_context( &context, HANDLER_CONTEXT );
1016     restore_fpu( &context, HANDLER_CONTEXT );
1017 }
1018
1019
1020 /**********************************************************************
1021  *              int_handler
1022  *
1023  * Handler for SIGINT.
1024  */
1025 static HANDLER_DEF(int_handler)
1026 {
1027     if (!dispatch_signal(SIGINT))
1028     {
1029         EXCEPTION_RECORD rec;
1030         CONTEXT context;
1031
1032         save_context( &context, HANDLER_CONTEXT );
1033         rec.ExceptionCode    = CONTROL_C_EXIT;
1034         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
1035         rec.ExceptionRecord  = NULL;
1036         rec.ExceptionAddress = (LPVOID)context.Eip;
1037         rec.NumberParameters = 0;
1038         EXC_RtlRaiseException( &rec, &context );
1039         restore_context( &context, HANDLER_CONTEXT );
1040     }
1041 }
1042
1043
1044 /***********************************************************************
1045  *           set_handler
1046  *
1047  * Set a signal handler
1048  */
1049 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
1050 {
1051     struct sigaction sig_act;
1052
1053 #ifdef linux
1054     if (!have_sigaltstack && NtCurrentTeb()->signal_stack)
1055     {
1056         struct kernel_sigaction sig_act;
1057         sig_act.ksa_handler = func;
1058         sig_act.ksa_flags   = SA_RESTART;
1059         sig_act.ksa_mask    = (1 << (SIGINT-1)) |
1060                               (1 << (SIGALRM-1));
1061         /* point to the top of the stack */
1062         sig_act.ksa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE;
1063         return wine_sigaction( sig, &sig_act, NULL );
1064     }
1065 #endif  /* linux */
1066     sig_act.sa_handler = func;
1067     sigemptyset( &sig_act.sa_mask );
1068     sigaddset( &sig_act.sa_mask, SIGINT );
1069     sigaddset( &sig_act.sa_mask, SIGALRM );
1070
1071 #ifdef linux
1072     sig_act.sa_flags = SA_RESTART;
1073 #elif defined (__svr4__) || defined(_SCO_DS)
1074     sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
1075 #else
1076     sig_act.sa_flags = 0;
1077 #endif
1078
1079 #ifdef SA_ONSTACK
1080     if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
1081 #endif
1082     return sigaction( sig, &sig_act, NULL );
1083 }
1084
1085
1086 /***********************************************************************
1087  *           __wine_set_signal_handler   (NTDLL.@)
1088  */
1089 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
1090 {
1091     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
1092     if (handlers[sig] != NULL) return -2;
1093     handlers[sig] = wsh;
1094     return 0;
1095 }
1096
1097
1098 /**********************************************************************
1099  *              SIGNAL_Init
1100  */
1101 BOOL SIGNAL_Init(void)
1102 {
1103     int have_sigaltstack = 0;
1104
1105 #ifdef HAVE_SIGALTSTACK
1106     struct sigaltstack ss;
1107     if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
1108     {
1109         ss.ss_size  = SIGNAL_STACK_SIZE;
1110         ss.ss_flags = 0;
1111         if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
1112 #ifdef linux
1113         /* sigaltstack may fail because the kernel is too old, or
1114            because glibc is brain-dead. In the latter case a
1115            direct system call should succeed. */
1116         else if (!wine_sigaltstack(&ss, NULL)) have_sigaltstack = 1;
1117 #endif  /* linux */
1118     }
1119 #endif  /* HAVE_SIGALTSTACK */
1120
1121     sigfillset( &all_sigs );
1122
1123     if (set_handler( SIGINT,  have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
1124     if (set_handler( SIGFPE,  have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
1125     if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1126     if (set_handler( SIGILL,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1127 #ifdef SIGBUS
1128     if (set_handler( SIGBUS,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1129 #endif
1130 #ifdef SIGTRAP
1131     if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
1132 #endif
1133
1134 #ifdef __HAVE_VM86
1135     if (set_handler( SIGALRM, have_sigaltstack, (void (*)())alrm_handler ) == -1) goto error;
1136     if (set_handler( SIGUSR2, have_sigaltstack, (void (*)())usr2_handler ) == -1) goto error;
1137 #endif
1138
1139     return TRUE;
1140
1141  error:
1142     perror("sigaction");
1143     return FALSE;
1144 }
1145
1146
1147 /**********************************************************************
1148  *              SIGNAL_Reset
1149  */
1150 void SIGNAL_Reset(void)
1151 {
1152     sigset_t block_set;
1153
1154     /* block the async signals */
1155     sigemptyset( &block_set );
1156     sigaddset( &block_set, SIGALRM );
1157     sigaddset( &block_set, SIGIO );
1158     sigaddset( &block_set, SIGHUP );
1159     sigaddset( &block_set, SIGUSR2 );
1160     sigprocmask( SIG_BLOCK, &block_set, NULL );
1161
1162     /* restore default handlers */
1163     signal( SIGINT, SIG_DFL );
1164     signal( SIGFPE, SIG_DFL );
1165     signal( SIGSEGV, SIG_DFL );
1166     signal( SIGILL, SIG_DFL );
1167 #ifdef SIGBUS
1168     signal( SIGBUS, SIG_DFL );
1169 #endif
1170 #ifdef SIGTRAP
1171     signal( SIGTRAP, SIG_DFL );
1172 #endif
1173 }
1174
1175
1176 #ifdef __HAVE_VM86
1177 /**********************************************************************
1178  *              __wine_enter_vm86   (NTDLL.@)
1179  *
1180  * Enter vm86 mode with the specified register context.
1181  */
1182 void __wine_enter_vm86( CONTEXT *context )
1183 {
1184     EXCEPTION_RECORD rec;
1185     TEB *teb = NtCurrentTeb();
1186     int res;
1187     struct vm86plus_struct vm86;
1188
1189     memset( &vm86, 0, sizeof(vm86) );
1190     for (;;)
1191     {
1192         restore_vm86_context( context, &vm86 );
1193         /* Linux doesn't preserve pending flag (VIP_MASK) on return,
1194          * so save it on entry, just in case */
1195         teb->vm86_pending |= (context->EFlags & VIP_MASK);
1196         /* Work around race conditions with signal handler
1197          * (avoiding sigprocmask for performance reasons) */
1198         teb->vm86_ptr = &vm86;
1199         vm86.regs.eflags |= teb->vm86_pending;
1200         /* Check for VIF|VIP here, since vm86_enter doesn't */
1201         if ((vm86.regs.eflags & (VIF_MASK|VIP_MASK)) == (VIF_MASK|VIP_MASK)) {
1202             teb->vm86_ptr = NULL;
1203             teb->vm86_pending = 0;
1204             context->EFlags |= VIP_MASK;
1205             rec.ExceptionCode = EXCEPTION_VM86_STI;
1206             rec.ExceptionInformation[0] = 0;
1207             goto cancel_vm86;
1208         }
1209
1210         do
1211         {
1212             res = vm86_enter( &teb->vm86_ptr ); /* uses and clears teb->vm86_ptr */
1213             if (res < 0)
1214             {
1215                 errno = -res;
1216                 return;
1217             }
1218         } while (VM86_TYPE(res) == VM86_SIGNAL);
1219
1220         save_vm86_context( context, &vm86 );
1221         context->EFlags |= teb->vm86_pending;
1222
1223         switch(VM86_TYPE(res))
1224         {
1225         case VM86_UNKNOWN: /* unhandled GP fault - IO-instruction or similar */
1226             do_segv( context, T_PROTFLT, 0, 0 );
1227             continue;
1228         case VM86_TRAP: /* return due to DOS-debugger request */
1229             do_trap( context, VM86_ARG(res) );
1230             continue;
1231         case VM86_INTx: /* int3/int x instruction (ARG = x) */
1232             rec.ExceptionCode = EXCEPTION_VM86_INTx;
1233             break;
1234         case VM86_STI: /* sti/popf/iret instruction enabled virtual interrupts */
1235             teb->vm86_pending = 0;
1236             rec.ExceptionCode = EXCEPTION_VM86_STI;
1237             break;
1238         case VM86_PICRETURN: /* return due to pending PIC request */
1239             rec.ExceptionCode = EXCEPTION_VM86_PICRETURN;
1240             break;
1241         default:
1242             ERR( "unhandled result from vm86 mode %x\n", res );
1243             continue;
1244         }
1245         rec.ExceptionInformation[0] = VM86_ARG(res);
1246 cancel_vm86:
1247         rec.ExceptionFlags          = EXCEPTION_CONTINUABLE;
1248         rec.ExceptionRecord         = NULL;
1249         rec.ExceptionAddress        = (LPVOID)context->Eip;
1250         rec.NumberParameters        = 1;
1251         EXC_RtlRaiseException( &rec, context );
1252     }
1253 }
1254
1255 #else /* __HAVE_VM86 */
1256 /**********************************************************************
1257  *              __wine_enter_vm86   (NTDLL.@)
1258  */
1259 void __wine_enter_vm86( CONTEXT *context )
1260 {
1261     MESSAGE("vm86 mode not supported on this platform\n");
1262 }
1263 #endif /* __HAVE_VM86 */
1264
1265 /**********************************************************************
1266  *              DbgBreakPoint   (NTDLL.@)
1267  */
1268 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
1269
1270 /**********************************************************************
1271  *              DbgUserBreakPoint   (NTDLL.@)
1272  */
1273 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
1274
1275 #endif  /* __i386__ */