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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 <stdarg.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
35
36 #ifdef HAVE_SYS_PARAM_H
37 # include <sys/param.h>
38 #endif
39 #ifdef HAVE_SYSCALL_H
40 # include <syscall.h>
41 #else
42 # ifdef HAVE_SYS_SYSCALL_H
43 # include <sys/syscall.h>
44 # endif
45 #endif
46
47 #ifdef HAVE_SYS_VM86_H
48 # include <sys/vm86.h>
49 #endif
50
51 #ifdef HAVE_SYS_SIGNAL_H
52 # include <sys/signal.h>
53 #endif
54 #ifdef HAVE_SYS_SYSCTL_H
55 # include <sys/sysctl.h>
56 #endif
57
58 #include "windef.h"
59 #include "wine/library.h"
60 #include "ntdll_misc.h"
61 #include "wine/exception.h"
62 #include "wine/debug.h"
63
64 #ifdef HAVE_VALGRIND_MEMCHECK_H
65 #include <valgrind/memcheck.h>
66 #endif
67
68 #undef ERR /* Solaris needs to define this */
69
70 /* not defined for x86, so copy the x86_64 definition */
71 typedef struct DECLSPEC_ALIGN(16) _M128A
72 {
73 ULONGLONG Low;
74 LONGLONG High;
75 } M128A;
76
77 typedef struct
78 {
79 WORD ControlWord;
80 WORD StatusWord;
81 BYTE TagWord;
82 BYTE Reserved1;
83 WORD ErrorOpcode;
84 DWORD ErrorOffset;
85 WORD ErrorSelector;
86 WORD Reserved2;
87 DWORD DataOffset;
88 WORD DataSelector;
89 WORD Reserved3;
90 DWORD MxCsr;
91 DWORD MxCsr_Mask;
92 M128A FloatRegisters[8];
93 M128A XmmRegisters[16];
94 BYTE Reserved4[96];
95 } XMM_SAVE_AREA32;
96
97 /***********************************************************************
98 * signal context platform-specific definitions
99 */
100
101 #ifdef linux
102
103 typedef ucontext_t SIGCONTEXT;
104
105 #define EAX_sig(context) ((context)->uc_mcontext.gregs[REG_EAX])
106 #define EBX_sig(context) ((context)->uc_mcontext.gregs[REG_EBX])
107 #define ECX_sig(context) ((context)->uc_mcontext.gregs[REG_ECX])
108 #define EDX_sig(context) ((context)->uc_mcontext.gregs[REG_EDX])
109 #define ESI_sig(context) ((context)->uc_mcontext.gregs[REG_ESI])
110 #define EDI_sig(context) ((context)->uc_mcontext.gregs[REG_EDI])
111 #define EBP_sig(context) ((context)->uc_mcontext.gregs[REG_EBP])
112 #define ESP_sig(context) ((context)->uc_mcontext.gregs[REG_ESP])
113
114 #define CS_sig(context) ((context)->uc_mcontext.gregs[REG_CS])
115 #define DS_sig(context) ((context)->uc_mcontext.gregs[REG_DS])
116 #define ES_sig(context) ((context)->uc_mcontext.gregs[REG_ES])
117 #define SS_sig(context) ((context)->uc_mcontext.gregs[REG_SS])
118 #define FS_sig(context) ((context)->uc_mcontext.gregs[REG_FS])
119 #define GS_sig(context) ((context)->uc_mcontext.gregs[REG_GS])
120
121 #define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
122 #define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
123 #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
124 #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
125
126 #define FPU_sig(context) ((FLOATING_SAVE_AREA*)((context)->uc_mcontext.fpregs))
127 #define FPUX_sig(context) (FPU_sig(context) && !((context)->uc_mcontext.fpregs->status >> 16) ? (XMM_SAVE_AREA32 *)(FPU_sig(context) + 1) : NULL)
128
129 #define VM86_EAX 0 /* the %eax value while vm86_enter is executing */
130 #define VIF_FLAG 0x00080000
131 #define VIP_FLAG 0x00100000
132
133 int vm86_enter( void **vm86_ptr );
134 void vm86_return(void);
135 void vm86_return_end(void);
136 __ASM_GLOBAL_FUNC(vm86_enter,
137 "pushl %ebp\n\t"
138 "movl %esp, %ebp\n\t"
139 "movl $166,%eax\n\t" /*SYS_vm86*/
140 "movl 8(%ebp),%ecx\n\t" /* vm86_ptr */
141 "movl (%ecx),%ecx\n\t"
142 "pushl %ebx\n\t"
143 "movl $1,%ebx\n\t" /*VM86_ENTER*/
144 "pushl %ecx\n\t" /* put vm86plus_struct ptr somewhere we can find it */
145 "pushl %fs\n\t"
146 "pushl %gs\n\t"
147 "int $0x80\n"
148 ".globl " __ASM_NAME("vm86_return") "\n\t"
149 __ASM_FUNC("vm86_return") "\n"
150 __ASM_NAME("vm86_return") ":\n\t"
151 "popl %gs\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 __ASM_FUNC("vm86_return_end") "\n"
165 __ASM_NAME("vm86_return_end") ":\n\t"
166 "ret" )
167
168 #ifdef HAVE_SYS_VM86_H
169 # define __HAVE_VM86
170 #endif
171
172 #endif /* linux */
173
174 #ifdef BSDI
175
176 #include <machine/frame.h>
177 typedef struct trapframe SIGCONTEXT;
178
179 #define EAX_sig(context) ((context)->tf_eax)
180 #define EBX_sig(context) ((context)->tf_ebx)
181 #define ECX_sig(context) ((context)->tf_ecx)
182 #define EDX_sig(context) ((context)->tf_edx)
183 #define ESI_sig(context) ((context)->tf_esi)
184 #define EDI_sig(context) ((context)->tf_edi)
185 #define EBP_sig(context) ((context)->tf_ebp)
186
187 #define CS_sig(context) ((context)->tf_cs)
188 #define DS_sig(context) ((context)->tf_ds)
189 #define ES_sig(context) ((context)->tf_es)
190 #define SS_sig(context) ((context)->tf_ss)
191
192 #define EFL_sig(context) ((context)->tf_eflags)
193
194 #define EIP_sig(context) (*((unsigned long*)&(context)->tf_eip))
195 #define ESP_sig(context) (*((unsigned long*)&(context)->tf_esp))
196
197 #define FPU_sig(context) NULL /* FIXME */
198 #define FPUX_sig(context) NULL /* FIXME */
199
200 #endif /* bsdi */
201
202 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
203
204 typedef struct sigcontext SIGCONTEXT;
205
206 #define EAX_sig(context) ((context)->sc_eax)
207 #define EBX_sig(context) ((context)->sc_ebx)
208 #define ECX_sig(context) ((context)->sc_ecx)
209 #define EDX_sig(context) ((context)->sc_edx)
210 #define ESI_sig(context) ((context)->sc_esi)
211 #define EDI_sig(context) ((context)->sc_edi)
212 #define EBP_sig(context) ((context)->sc_ebp)
213
214 #define CS_sig(context) ((context)->sc_cs)
215 #define DS_sig(context) ((context)->sc_ds)
216 #define ES_sig(context) ((context)->sc_es)
217 #define FS_sig(context) ((context)->sc_fs)
218 #define GS_sig(context) ((context)->sc_gs)
219 #define SS_sig(context) ((context)->sc_ss)
220
221 #define TRAP_sig(context) ((context)->sc_trapno)
222 #define ERROR_sig(context) ((context)->sc_err)
223 #define EFL_sig(context) ((context)->sc_eflags)
224
225 #define EIP_sig(context) ((context)->sc_eip)
226 #define ESP_sig(context) ((context)->sc_esp)
227
228 #define FPU_sig(context) NULL /* FIXME */
229 #define FPUX_sig(context) NULL /* FIXME */
230
231 #endif /* *BSD */
232
233 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
234
235 #ifdef _SCO_DS
236 #include <sys/regset.h>
237 #endif
238 #include <sys/ucontext.h>
239 typedef struct ucontext SIGCONTEXT;
240
241 #ifdef _SCO_DS
242 #define gregs regs
243 #endif
244
245 #define EAX_sig(context) ((context)->uc_mcontext.gregs[EAX])
246 #define EBX_sig(context) ((context)->uc_mcontext.gregs[EBX])
247 #define ECX_sig(context) ((context)->uc_mcontext.gregs[ECX])
248 #define EDX_sig(context) ((context)->uc_mcontext.gregs[EDX])
249 #define ESI_sig(context) ((context)->uc_mcontext.gregs[ESI])
250 #define EDI_sig(context) ((context)->uc_mcontext.gregs[EDI])
251 #define EBP_sig(context) ((context)->uc_mcontext.gregs[EBP])
252
253 #define CS_sig(context) ((context)->uc_mcontext.gregs[CS])
254 #define DS_sig(context) ((context)->uc_mcontext.gregs[DS])
255 #define ES_sig(context) ((context)->uc_mcontext.gregs[ES])
256 #define SS_sig(context) ((context)->uc_mcontext.gregs[SS])
257
258 #define FS_sig(context) ((context)->uc_mcontext.gregs[FS])
259 #define GS_sig(context) ((context)->uc_mcontext.gregs[GS])
260
261 #define EFL_sig(context) ((context)->uc_mcontext.gregs[EFL])
262
263 #define EIP_sig(context) ((context)->uc_mcontext.gregs[EIP])
264 #ifdef UESP
265 #define ESP_sig(context) ((context)->uc_mcontext.gregs[UESP])
266 #elif defined(R_ESP)
267 #define ESP_sig(context) ((context)->uc_mcontext.gregs[R_ESP])
268 #else
269 #define ESP_sig(context) ((context)->uc_mcontext.gregs[ESP])
270 #endif
271 #ifdef ERR
272 #define ERROR_sig(context) ((context)->uc_mcontext.gregs[ERR])
273 #endif
274 #ifdef TRAPNO
275 #define TRAP_sig(context) ((context)->uc_mcontext.gregs[TRAPNO])
276 #endif
277
278 #define FPU_sig(context) NULL /* FIXME */
279 #define FPUX_sig(context) NULL /* FIXME */
280
281 #endif /* svr4 || SCO_DS */
282
283 #ifdef __APPLE__
284 # include <sys/ucontext.h>
285
286 typedef ucontext_t SIGCONTEXT;
287
288 /* work around silly renaming of struct members in OS X 10.5 */
289 #if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
290 #define EAX_sig(context) ((context)->uc_mcontext->__ss.__eax)
291 #define EBX_sig(context) ((context)->uc_mcontext->__ss.__ebx)
292 #define ECX_sig(context) ((context)->uc_mcontext->__ss.__ecx)
293 #define EDX_sig(context) ((context)->uc_mcontext->__ss.__edx)
294 #define ESI_sig(context) ((context)->uc_mcontext->__ss.__esi)
295 #define EDI_sig(context) ((context)->uc_mcontext->__ss.__edi)
296 #define EBP_sig(context) ((context)->uc_mcontext->__ss.__ebp)
297 #define CS_sig(context) ((context)->uc_mcontext->__ss.__cs)
298 #define DS_sig(context) ((context)->uc_mcontext->__ss.__ds)
299 #define ES_sig(context) ((context)->uc_mcontext->__ss.__es)
300 #define FS_sig(context) ((context)->uc_mcontext->__ss.__fs)
301 #define GS_sig(context) ((context)->uc_mcontext->__ss.__gs)
302 #define SS_sig(context) ((context)->uc_mcontext->__ss.__ss)
303 #define EFL_sig(context) ((context)->uc_mcontext->__ss.__eflags)
304 #define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__eip))
305 #define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__esp))
306 #define TRAP_sig(context) ((context)->uc_mcontext->__es.__trapno)
307 #define ERROR_sig(context) ((context)->uc_mcontext->__es.__err)
308 #define FPU_sig(context) NULL
309 #define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
310 #else
311 #define EAX_sig(context) ((context)->uc_mcontext->ss.eax)
312 #define EBX_sig(context) ((context)->uc_mcontext->ss.ebx)
313 #define ECX_sig(context) ((context)->uc_mcontext->ss.ecx)
314 #define EDX_sig(context) ((context)->uc_mcontext->ss.edx)
315 #define ESI_sig(context) ((context)->uc_mcontext->ss.esi)
316 #define EDI_sig(context) ((context)->uc_mcontext->ss.edi)
317 #define EBP_sig(context) ((context)->uc_mcontext->ss.ebp)
318 #define CS_sig(context) ((context)->uc_mcontext->ss.cs)
319 #define DS_sig(context) ((context)->uc_mcontext->ss.ds)
320 #define ES_sig(context) ((context)->uc_mcontext->ss.es)
321 #define FS_sig(context) ((context)->uc_mcontext->ss.fs)
322 #define GS_sig(context) ((context)->uc_mcontext->ss.gs)
323 #define SS_sig(context) ((context)->uc_mcontext->ss.ss)
324 #define EFL_sig(context) ((context)->uc_mcontext->ss.eflags)
325 #define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
326 #define ESP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.esp))
327 #define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
328 #define ERROR_sig(context) ((context)->uc_mcontext->es.err)
329 #define FPU_sig(context) NULL
330 #define FPUX_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->fs.fpu_fcw)
331 #endif
332
333 #endif /* __APPLE__ */
334
335 WINE_DEFAULT_DEBUG_CHANNEL(seh);
336
337 typedef int (*wine_signal_handler)(unsigned int sig);
338
339 static size_t signal_stack_mask;
340 static size_t signal_stack_size;
341
342 static wine_signal_handler handlers[256];
343
344 static int fpux_support; /* whether the CPU support extended fpu context */
345
346 extern void DECLSPEC_NORETURN __wine_call_from_32_restore_regs( const CONTEXT *context );
347
348 enum i386_trap_code
349 {
350 TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */
351 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
352 TRAP_x86_DIVIDE = T_DIVIDE, /* Division by zero exception */
353 TRAP_x86_TRCTRAP = T_TRCTRAP, /* Single-step exception */
354 TRAP_x86_NMI = T_NMI, /* NMI interrupt */
355 TRAP_x86_BPTFLT = T_BPTFLT, /* Breakpoint exception */
356 TRAP_x86_OFLOW = T_OFLOW, /* Overflow exception */
357 TRAP_x86_BOUND = T_BOUND, /* Bound range exception */
358 TRAP_x86_PRIVINFLT = T_PRIVINFLT, /* Invalid opcode exception */
359 TRAP_x86_DNA = T_DNA, /* Device not available exception */
360 TRAP_x86_DOUBLEFLT = T_DOUBLEFLT, /* Double fault exception */
361 TRAP_x86_FPOPFLT = T_FPOPFLT, /* Coprocessor segment overrun */
362 TRAP_x86_TSSFLT = T_TSSFLT, /* Invalid TSS exception */
363 TRAP_x86_SEGNPFLT = T_SEGNPFLT, /* Segment not present exception */
364 TRAP_x86_STKFLT = T_STKFLT, /* Stack fault */
365 TRAP_x86_PROTFLT = T_PROTFLT, /* General protection fault */
366 TRAP_x86_PAGEFLT = T_PAGEFLT, /* Page fault */
367 TRAP_x86_ARITHTRAP = T_ARITHTRAP, /* Floating point exception */
368 TRAP_x86_ALIGNFLT = T_ALIGNFLT, /* Alignment check exception */
369 TRAP_x86_MCHK = T_MCHK, /* Machine check exception */
370 TRAP_x86_CACHEFLT = T_XMMFLT /* Cache flush exception */
371 #else
372 TRAP_x86_DIVIDE = 0, /* Division by zero exception */
373 TRAP_x86_TRCTRAP = 1, /* Single-step exception */
374 TRAP_x86_NMI = 2, /* NMI interrupt */
375 TRAP_x86_BPTFLT = 3, /* Breakpoint exception */
376 TRAP_x86_OFLOW = 4, /* Overflow exception */
377 TRAP_x86_BOUND = 5, /* Bound range exception */
378 TRAP_x86_PRIVINFLT = 6, /* Invalid opcode exception */
379 TRAP_x86_DNA = 7, /* Device not available exception */
380 TRAP_x86_DOUBLEFLT = 8, /* Double fault exception */
381 TRAP_x86_FPOPFLT = 9, /* Coprocessor segment overrun */
382 TRAP_x86_TSSFLT = 10, /* Invalid TSS exception */
383 TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */
384 TRAP_x86_STKFLT = 12, /* Stack fault */
385 TRAP_x86_PROTFLT = 13, /* General protection fault */
386 TRAP_x86_PAGEFLT = 14, /* Page fault */
387 TRAP_x86_ARITHTRAP = 16, /* Floating point exception */
388 TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */
389 TRAP_x86_MCHK = 18, /* Machine check exception */
390 TRAP_x86_CACHEFLT = 19 /* SIMD exception (via SIGFPE) if CPU is SSE capable
391 otherwise Cache flush exception (via SIGSEV) */
392 #endif
393 };
394
395
396 /***********************************************************************
397 * dispatch_signal
398 */
399 static inline int dispatch_signal(unsigned int sig)
400 {
401 if (handlers[sig] == NULL) return 0;
402 return handlers[sig](sig);
403 }
404
405
406 /***********************************************************************
407 * get_trap_code
408 *
409 * Get the trap code for a signal.
410 */
411 static inline enum i386_trap_code get_trap_code( const SIGCONTEXT *sigcontext )
412 {
413 #ifdef TRAP_sig
414 return TRAP_sig(sigcontext);
415 #else
416 return TRAP_x86_UNKNOWN; /* unknown trap code */
417 #endif
418 }
419
420 /***********************************************************************
421 * get_error_code
422 *
423 * Get the error code for a signal.
424 */
425 static inline WORD get_error_code( const SIGCONTEXT *sigcontext )
426 {
427 #ifdef ERROR_sig
428 return ERROR_sig(sigcontext);
429 #else
430 return 0;
431 #endif
432 }
433
434 /***********************************************************************
435 * get_signal_stack
436 *
437 * Get the base of the signal stack for the current thread.
438 */
439 static inline void *get_signal_stack(void)
440 {
441 return (char *)NtCurrentTeb() + 4096;
442 }
443
444
445 /***********************************************************************
446 * get_current_teb
447 *
448 * Get the current teb based on the stack pointer.
449 */
450 static inline TEB *get_current_teb(void)
451 {
452 unsigned long esp;
453 __asm__("movl %%esp,%0" : "=g" (esp) );
454 return (TEB *)(esp & ~signal_stack_mask);
455 }
456
457
458 #ifdef __HAVE_VM86
459 /***********************************************************************
460 * save_vm86_context
461 *
462 * Set the register values from a vm86 structure.
463 */
464 static void save_vm86_context( CONTEXT *context, const struct vm86plus_struct *vm86 )
465 {
466 context->ContextFlags = CONTEXT_FULL;
467 context->Eax = vm86->regs.eax;
468 context->Ebx = vm86->regs.ebx;
469 context->Ecx = vm86->regs.ecx;
470 context->Edx = vm86->regs.edx;
471 context->Esi = vm86->regs.esi;
472 context->Edi = vm86->regs.edi;
473 context->Esp = vm86->regs.esp;
474 context->Ebp = vm86->regs.ebp;
475 context->Eip = vm86->regs.eip;
476 context->SegCs = vm86->regs.cs;
477 context->SegDs = vm86->regs.ds;
478 context->SegEs = vm86->regs.es;
479 context->SegFs = vm86->regs.fs;
480 context->SegGs = vm86->regs.gs;
481 context->SegSs = vm86->regs.ss;
482 context->EFlags = vm86->regs.eflags;
483 }
484
485
486 /***********************************************************************
487 * restore_vm86_context
488 *
489 * Build a vm86 structure from the register values.
490 */
491 static void restore_vm86_context( const CONTEXT *context, struct vm86plus_struct *vm86 )
492 {
493 vm86->regs.eax = context->Eax;
494 vm86->regs.ebx = context->Ebx;
495 vm86->regs.ecx = context->Ecx;
496 vm86->regs.edx = context->Edx;
497 vm86->regs.esi = context->Esi;
498 vm86->regs.edi = context->Edi;
499 vm86->regs.esp = context->Esp;
500 vm86->regs.ebp = context->Ebp;
501 vm86->regs.eip = context->Eip;
502 vm86->regs.cs = context->SegCs;
503 vm86->regs.ds = context->SegDs;
504 vm86->regs.es = context->SegEs;
505 vm86->regs.fs = context->SegFs;
506 vm86->regs.gs = context->SegGs;
507 vm86->regs.ss = context->SegSs;
508 vm86->regs.eflags = context->EFlags;
509 }
510
511
512 /**********************************************************************
513 * merge_vm86_pending_flags
514 *
515 * Merges TEB.vm86_ptr and TEB.vm86_pending VIP flags and
516 * raises exception if there are pending events and VIF flag
517 * has been turned on.
518 *
519 * Called from __wine_enter_vm86 because vm86_enter
520 * doesn't check for pending events.
521 *
522 * Called from raise_vm86_sti_exception to check for
523 * pending events in a signal safe way.
524 */
525 static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec )
526 {
527 BOOL check_pending = TRUE;
528 struct vm86plus_struct *vm86 =
529 (struct vm86plus_struct*)(ntdll_get_thread_data()->vm86_ptr);
530
531 /*
532 * In order to prevent a race when SIGUSR2 occurs while
533 * we are returning from exception handler, pending events
534 * will be rechecked after each raised exception.
535 */
536 while (check_pending && get_vm86_teb_info()->vm86_pending)
537 {
538 check_pending = FALSE;
539 ntdll_get_thread_data()->vm86_ptr = NULL;
540
541 /*
542 * If VIF is set, throw exception.
543 * Note that SIGUSR2 may turn VIF flag off so
544 * VIF check must occur only when TEB.vm86_ptr is NULL.
545 */
546 if (vm86->regs.eflags & VIF_FLAG)
547 {
548 CONTEXT vcontext;
549 save_vm86_context( &vcontext, vm86 );
550
551 rec->ExceptionCode = EXCEPTION_VM86_STI;
552 rec->ExceptionFlags = EXCEPTION_CONTINUABLE;
553 rec->ExceptionRecord = NULL;
554 rec->NumberParameters = 0;
555 rec->ExceptionAddress = (LPVOID)vcontext.Eip;
556
557 vcontext.EFlags &= ~VIP_FLAG;
558 get_vm86_teb_info()->vm86_pending = 0;
559 __regs_RtlRaiseException( rec, &vcontext );
560
561 restore_vm86_context( &vcontext, vm86 );
562 check_pending = TRUE;
563 }
564
565 ntdll_get_thread_data()->vm86_ptr = vm86;
566 }
567
568 /*
569 * Merge VIP flags in a signal safe way. This requires
570 * that the following operation compiles into atomic
571 * instruction.
572 */
573 vm86->regs.eflags |= get_vm86_teb_info()->vm86_pending;
574 }
575 #endif /* __HAVE_VM86 */
576
577
578 #ifdef __sun
579
580 /* We have to workaround two Solaris breakages:
581 * - Solaris doesn't restore %ds and %es before calling the signal handler so exceptions in 16-bit
582 * code crash badly.
583 * - Solaris inserts a libc trampoline to call our handler, but the trampoline expects that registers
584 * are setup correctly. So we need to insert our own trampoline below the libc trampoline to set %gs.
585 */
586
587 extern int sigaction_syscall( int sig, const struct sigaction *new, struct sigaction *old );
588 __ASM_GLOBAL_FUNC( sigaction_syscall,
589 "movl $0x62,%eax\n\t"
590 "int $0x91\n\t"
591 "ret" )
592
593 /* assume the same libc handler is used for all signals */
594 static void (*libc_sigacthandler)( int signal, siginfo_t *siginfo, void *context );
595
596 static void wine_sigacthandler( int signal, siginfo_t *siginfo, void *sigcontext )
597 {
598 struct ntdll_thread_data *thread_data;
599
600 __asm__ __volatile__("mov %ss,%ax; mov %ax,%ds; mov %ax,%es");
601
602 thread_data = get_current_teb()->SystemReserved2;
603 wine_set_fs( thread_data->fs );
604 wine_set_gs( thread_data->gs );
605
606 libc_sigacthandler( signal, siginfo, sigcontext );
607 }
608
609 static int solaris_sigaction( int sig, const struct sigaction *new, struct sigaction *old )
610 {
611 struct sigaction real_act;
612
613 if (sigaction( sig, new, old ) == -1) return -1;
614
615 /* retrieve the real handler and flags with a direct syscall */
616 sigaction_syscall( sig, NULL, &real_act );
617 libc_sigacthandler = real_act.sa_sigaction;
618 real_act.sa_sigaction = wine_sigacthandler;
619 sigaction_syscall( sig, &real_act, NULL );
620 return 0;
621 }
622 #define sigaction(sig,new,old) solaris_sigaction(sig,new,old)
623
624 #endif
625
626 typedef void (WINAPI *raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
627
628
629 /***********************************************************************
630 * init_handler
631 *
632 * Handler initialization when the full context is not needed.
633 * Return the stack pointer to use for pushing the exception data.
634 */
635 static inline void *init_handler( const SIGCONTEXT *sigcontext, WORD *fs, WORD *gs )
636 {
637 TEB *teb = get_current_teb();
638 struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
639
640 /* get %fs and %gs at time of the fault */
641 #ifdef FS_sig
642 *fs = LOWORD(FS_sig(sigcontext));
643 #else
644 *fs = wine_get_fs();
645 #endif
646 #ifdef GS_sig
647 *gs = LOWORD(GS_sig(sigcontext));
648 #else
649 *gs = wine_get_gs();
650 #endif
651
652 #ifndef __sun /* see above for Solaris handling */
653 wine_set_fs( thread_data->fs );
654 wine_set_gs( thread_data->gs );
655 #endif
656
657 if (!wine_ldt_is_system(CS_sig(sigcontext)) ||
658 !wine_ldt_is_system(SS_sig(sigcontext))) /* 16-bit mode */
659 {
660 /*
661 * Win16 or DOS protected mode. Note that during switch
662 * from 16-bit mode to linear mode, CS may be set to system
663 * segment before FS is restored. Fortunately, in this case
664 * SS is still non-system segment. This is why both CS and SS
665 * are checked.
666 */
667 return teb->WOW32Reserved;
668 }
669 return (void *)(ESP_sig(sigcontext) & ~3);
670 }
671
672
673 /***********************************************************************
674 * save_fpu
675 *
676 * Save the thread FPU context.
677 */
678 static inline void save_fpu( CONTEXT *context )
679 {
680 #ifdef __GNUC__
681 context->ContextFlags |= CONTEXT_FLOATING_POINT;
682 __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
683 #endif
684 }
685
686
687 /***********************************************************************
688 * save_fpux
689 *
690 * Save the thread FPU extended context.
691 */
692 static inline void save_fpux( CONTEXT *context )
693 {
694 #ifdef __GNUC__
695 /* we have to enforce alignment by hand */
696 char buffer[sizeof(XMM_SAVE_AREA32) + 16];
697 XMM_SAVE_AREA32 *state = (XMM_SAVE_AREA32 *)(((ULONG_PTR)buffer + 15) & ~15);
698
699 __asm__ __volatile__( "fxsave %0" : "=m" (*state) );
700 context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
701 memcpy( context->ExtendedRegisters, state, sizeof(*state) );
702 #endif
703 }
704
705
706 /***********************************************************************
707 * restore_fpu
708 *
709 * Restore the FPU context to a sigcontext.
710 */
711 static inline void restore_fpu( const CONTEXT *context )
712 {
713 FLOATING_SAVE_AREA float_status = context->FloatSave;
714 /* reset the current interrupt status */
715 float_status.StatusWord &= float_status.ControlWord | 0xffffff80;
716 #ifdef __GNUC__
717 __asm__ __volatile__( "frstor %0; fwait" : : "m" (float_status) );
718 #endif /* __GNUC__ */
719 }
720
721
722 /***********************************************************************
723 * restore_fpux
724 *
725 * Restore the FPU extended context to a sigcontext.
726 */
727 static inline void restore_fpux( const CONTEXT *context )
728 {
729 #ifdef __GNUC__
730 /* we have to enforce alignment by hand */
731 char buffer[sizeof(XMM_SAVE_AREA32) + 16];
732 XMM_SAVE_AREA32 *state = (XMM_SAVE_AREA32 *)(((ULONG_PTR)buffer + 15) & ~15);
733
734 memcpy( state, context->ExtendedRegisters, sizeof(*state) );
735 /* reset the current interrupt status */
736 state->StatusWord &= state->ControlWord | 0xff80;
737 __asm__ __volatile__( "fxrstor %0" : : "m" (*state) );
738 #endif
739 }
740
741
742 /***********************************************************************
743 * fpux_to_fpu
744 *
745 * Build a standard FPU context from an extended one.
746 */
747 static void fpux_to_fpu( FLOATING_SAVE_AREA *fpu, const XMM_SAVE_AREA32 *fpux )
748 {
749 unsigned int i, tag, stack_top;
750
751 fpu->ControlWord = fpux->ControlWord | 0xffff0000;
752 fpu->StatusWord = fpux->StatusWord | 0xffff0000;
753 fpu->ErrorOffset = fpux->ErrorOffset;
754 fpu->ErrorSelector = fpux->ErrorSelector | (fpux->ErrorOpcode << 16);
755 fpu->DataOffset = fpux->DataOffset;
756 fpu->DataSelector = fpux->DataSelector;
757 fpu->Cr0NpxState = fpux->StatusWord | 0xffff0000;
758
759 stack_top = (fpux->StatusWord >> 11) & 7;
760 fpu->TagWord = 0xffff0000;
761 for (i = 0; i < 8; i++)
762 {
763 memcpy( &fpu->RegisterArea[10 * i], &fpux->FloatRegisters[i], 10 );
764 if (!(fpux->TagWord & (1 << i))) tag = 3; /* empty */
765 else
766 {
767 const M128A *reg = &fpux->FloatRegisters[(i - stack_top) & 7];
768 if ((reg->High & 0x7fff) == 0x7fff) /* exponent all ones */
769 {
770 tag = 2; /* special */
771 }
772 else if (!(reg->High & 0x7fff)) /* exponent all zeroes */
773 {
774 if (reg->Low) tag = 2; /* special */
775 else tag = 1; /* zero */
776 }
777 else
778 {
779 if (reg->Low >> 63) tag = 0; /* valid */
780 else tag = 2; /* special */
781 }
782 }
783 fpu->TagWord |= tag << (2 * i);
784 }
785 }
786
787
788 /***********************************************************************
789 * save_context
790 *
791 * Build a context structure from the signal info.
792 */
793 static inline void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext, WORD fs, WORD gs )
794 {
795 struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
796 FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext);
797 XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext);
798
799 memset(context, 0, sizeof(*context));
800 context->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
801 context->Eax = EAX_sig(sigcontext);
802 context->Ebx = EBX_sig(sigcontext);
803 context->Ecx = ECX_sig(sigcontext);
804 context->Edx = EDX_sig(sigcontext);
805 context->Esi = ESI_sig(sigcontext);
806 context->Edi = EDI_sig(sigcontext);
807 context->Ebp = EBP_sig(sigcontext);
808 context->EFlags = EFL_sig(sigcontext);
809 context->Eip = EIP_sig(sigcontext);
810 context->Esp = ESP_sig(sigcontext);
811 context->SegCs = LOWORD(CS_sig(sigcontext));
812 context->SegDs = LOWORD(DS_sig(sigcontext));
813 context->SegEs = LOWORD(ES_sig(sigcontext));
814 context->SegFs = fs;
815 context->SegGs = gs;
816 context->SegSs = LOWORD(SS_sig(sigcontext));
817 context->Dr0 = regs->dr0;
818 context->Dr1 = regs->dr1;
819 context->Dr2 = regs->dr2;
820 context->Dr3 = regs->dr3;
821 context->Dr6 = regs->dr6;
822 context->Dr7 = regs->dr7;
823
824 if (fpu)
825 {
826 context->ContextFlags |= CONTEXT_FLOATING_POINT;
827 context->FloatSave = *fpu;
828 }
829 if (fpux)
830 {
831 context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
832 memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) );
833 fpux_support = 1;
834 if (!fpu) fpux_to_fpu( &context->FloatSave, fpux );
835 }
836 if (!fpu && !fpux) save_fpu( context );
837 }
838
839
840 /***********************************************************************
841 * restore_context
842 *
843 * Restore the signal info from the context.
844 */
845 static inline void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
846 {
847 struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
848 FLOATING_SAVE_AREA *fpu = FPU_sig(sigcontext);
849 XMM_SAVE_AREA32 *fpux = FPUX_sig(sigcontext);
850
851 regs->dr0 = context->Dr0;
852 regs->dr1 = context->Dr1;
853 regs->dr2 = context->Dr2;
854 regs->dr3 = context->Dr3;
855 regs->dr6 = context->Dr6;
856 regs->dr7 = context->Dr7;
857 EAX_sig(sigcontext) = context->Eax;
858 EBX_sig(sigcontext) = context->Ebx;
859 ECX_sig(sigcontext) = context->Ecx;
860 EDX_sig(sigcontext) = context->Edx;
861 ESI_sig(sigcontext) = context->Esi;
862 EDI_sig(sigcontext) = context->Edi;
863 EBP_sig(sigcontext) = context->Ebp;
864 EFL_sig(sigcontext) = context->EFlags;
865 EIP_sig(sigcontext) = context->Eip;
866 ESP_sig(sigcontext) = context->Esp;
867 CS_sig(sigcontext) = context->SegCs;