wined3d: Extend out anti-spam database a bit.
[wine] / dlls / ntdll / signal_x86_64.c
1 /*
2  * x86-64 signal handling routines
3  *
4  * Copyright 1999, 2005 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 __x86_64__
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <assert.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif
38 #ifdef HAVE_SYS_SIGNAL_H
39 # include <sys/signal.h>
40 #endif
41
42 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winternl.h"
45 #include "wine/library.h"
46 #include "wine/exception.h"
47 #include "ntdll_misc.h"
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(seh);
51
52
53 /***********************************************************************
54  * signal context platform-specific definitions
55  */
56 #ifdef linux
57
58 typedef struct ucontext SIGCONTEXT;
59
60 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
61 # define HANDLER_CONTEXT (__context)
62
63 #define RAX_sig(context)     ((context)->uc_mcontext.gregs[REG_RAX])
64 #define RBX_sig(context)     ((context)->uc_mcontext.gregs[REG_RBX])
65 #define RCX_sig(context)     ((context)->uc_mcontext.gregs[REG_RCX])
66 #define RDX_sig(context)     ((context)->uc_mcontext.gregs[REG_RDX])
67 #define RSI_sig(context)     ((context)->uc_mcontext.gregs[REG_RSI])
68 #define RDI_sig(context)     ((context)->uc_mcontext.gregs[REG_RDI])
69 #define RBP_sig(context)     ((context)->uc_mcontext.gregs[REG_RBP])
70 #define R8_sig(context)      ((context)->uc_mcontext.gregs[REG_R8])
71 #define R9_sig(context)      ((context)->uc_mcontext.gregs[REG_R9])
72 #define R10_sig(context)     ((context)->uc_mcontext.gregs[REG_R10])
73 #define R11_sig(context)     ((context)->uc_mcontext.gregs[REG_R11])
74 #define R12_sig(context)     ((context)->uc_mcontext.gregs[REG_R12])
75 #define R13_sig(context)     ((context)->uc_mcontext.gregs[REG_R13])
76 #define R14_sig(context)     ((context)->uc_mcontext.gregs[REG_R14])
77 #define R15_sig(context)     ((context)->uc_mcontext.gregs[REG_R15])
78
79 #define CS_sig(context)      (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 0))
80 #define GS_sig(context)      (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 1))
81 #define FS_sig(context)      (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 2))
82
83 #define RSP_sig(context)     ((context)->uc_mcontext.gregs[REG_RSP])
84 #define RIP_sig(context)     ((context)->uc_mcontext.gregs[REG_RIP])
85 #define EFL_sig(context)     ((context)->uc_mcontext.gregs[REG_EFL])
86 #define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
87 #define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
88
89 #define FPU_sig(context)     ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
90
91 #define FAULT_CODE     (__siginfo->si_code)
92 #define FAULT_ADDRESS  (__siginfo->si_addr)
93
94 #endif /* linux */
95
96 enum i386_trap_code
97 {
98     TRAP_x86_UNKNOWN    = -1,  /* Unknown fault (TRAP_sig not defined) */
99     TRAP_x86_DIVIDE     = 0,   /* Division by zero exception */
100     TRAP_x86_TRCTRAP    = 1,   /* Single-step exception */
101     TRAP_x86_NMI        = 2,   /* NMI interrupt */
102     TRAP_x86_BPTFLT     = 3,   /* Breakpoint exception */
103     TRAP_x86_OFLOW      = 4,   /* Overflow exception */
104     TRAP_x86_BOUND      = 5,   /* Bound range exception */
105     TRAP_x86_PRIVINFLT  = 6,   /* Invalid opcode exception */
106     TRAP_x86_DNA        = 7,   /* Device not available exception */
107     TRAP_x86_DOUBLEFLT  = 8,   /* Double fault exception */
108     TRAP_x86_FPOPFLT    = 9,   /* Coprocessor segment overrun */
109     TRAP_x86_TSSFLT     = 10,  /* Invalid TSS exception */
110     TRAP_x86_SEGNPFLT   = 11,  /* Segment not present exception */
111     TRAP_x86_STKFLT     = 12,  /* Stack fault */
112     TRAP_x86_PROTFLT    = 13,  /* General protection fault */
113     TRAP_x86_PAGEFLT    = 14,  /* Page fault */
114     TRAP_x86_ARITHTRAP  = 16,  /* Floating point exception */
115     TRAP_x86_ALIGNFLT   = 17,  /* Alignment check exception */
116     TRAP_x86_MCHK       = 18,  /* Machine check exception */
117     TRAP_x86_CACHEFLT   = 19   /* Cache flush exception */
118 };
119
120 typedef int (*wine_signal_handler)(unsigned int sig);
121
122 static wine_signal_handler handlers[256];
123
124 /***********************************************************************
125  *           dispatch_signal
126  */
127 static inline int dispatch_signal(unsigned int sig)
128 {
129     if (handlers[sig] == NULL) return 0;
130     return handlers[sig](sig);
131 }
132
133 /***********************************************************************
134  *           save_context
135  *
136  * Set the register values from a sigcontext.
137  */
138 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
139 {
140     context->Rax    = RAX_sig(sigcontext);
141     context->Rcx    = RCX_sig(sigcontext);
142     context->Rdx    = RDX_sig(sigcontext);
143     context->Rbx    = RBX_sig(sigcontext);
144     context->Rsp    = RSP_sig(sigcontext);
145     context->Rbp    = RBP_sig(sigcontext);
146     context->Rsi    = RSI_sig(sigcontext);
147     context->Rdi    = RDI_sig(sigcontext);
148     context->R8     = R8_sig(sigcontext);
149     context->R9     = R9_sig(sigcontext);
150     context->R10    = R10_sig(sigcontext);
151     context->R11    = R11_sig(sigcontext);
152     context->R12    = R12_sig(sigcontext);
153     context->R13    = R13_sig(sigcontext);
154     context->R14    = R14_sig(sigcontext);
155     context->R15    = R15_sig(sigcontext);
156     context->Rip    = RIP_sig(sigcontext);
157     context->SegCs  = CS_sig(sigcontext);
158     context->SegFs  = FS_sig(sigcontext);
159     context->SegGs  = GS_sig(sigcontext);
160     context->EFlags = EFL_sig(sigcontext);
161     context->SegDs  = 0;  /* FIXME */
162     context->SegEs  = 0;  /* FIXME */
163     context->SegSs  = 0;  /* FIXME */
164     context->MxCsr  = 0;  /* FIXME */
165     if (FPU_sig(sigcontext)) context->u.FltSave = *FPU_sig(sigcontext);
166 }
167
168
169 /***********************************************************************
170  *           restore_context
171  *
172  * Build a sigcontext from the register values.
173  */
174 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
175 {
176     RAX_sig(sigcontext) = context->Rax;
177     RCX_sig(sigcontext) = context->Rcx;
178     RDX_sig(sigcontext) = context->Rdx;
179     RBX_sig(sigcontext) = context->Rbx;
180     RSP_sig(sigcontext) = context->Rsp;
181     RBP_sig(sigcontext) = context->Rbp;
182     RSI_sig(sigcontext) = context->Rsi;
183     RDI_sig(sigcontext) = context->Rdi;
184     R8_sig(sigcontext)  = context->R8;
185     R9_sig(sigcontext)  = context->R9;
186     R10_sig(sigcontext) = context->R10;
187     R11_sig(sigcontext) = context->R11;
188     R12_sig(sigcontext) = context->R12;
189     R13_sig(sigcontext) = context->R13;
190     R14_sig(sigcontext) = context->R14;
191     R15_sig(sigcontext) = context->R15;
192     RIP_sig(sigcontext) = context->Rip;
193     CS_sig(sigcontext)  = context->SegCs;
194     FS_sig(sigcontext)  = context->SegFs;
195     GS_sig(sigcontext)  = context->SegGs;
196     EFL_sig(sigcontext) = context->EFlags;
197     if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
198 }
199
200
201 /***********************************************************************
202  *              get_cpu_context
203  *
204  * Get the context of the current thread.
205  */
206 void get_cpu_context( CONTEXT *context )
207 {
208     FIXME("not implemented\n");
209 }
210
211
212 /***********************************************************************
213  *           set_cpu_context
214  *
215  * Set the new CPU context.
216  */
217 void set_cpu_context( const CONTEXT *context )
218 {
219     FIXME("not implemented\n");
220 }
221
222
223 /**********************************************************************
224  *              segv_handler
225  *
226  * Handler for SIGSEGV and related errors.
227  */
228 static HANDLER_DEF(segv_handler)
229 {
230     EXCEPTION_RECORD rec;
231     CONTEXT context;
232
233     save_context( &context, HANDLER_CONTEXT );
234
235     rec.ExceptionRecord  = NULL;
236     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
237     rec.ExceptionAddress = (LPVOID)context.Rip;
238     rec.NumberParameters = 0;
239
240     switch(TRAP_sig(HANDLER_CONTEXT))
241     {
242     case TRAP_x86_OFLOW:   /* Overflow exception */
243         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
244         break;
245     case TRAP_x86_BOUND:   /* Bound range exception */
246         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
247         break;
248     case TRAP_x86_PRIVINFLT:   /* Invalid opcode exception */
249         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
250         break;
251     case TRAP_x86_STKFLT:  /* Stack fault */
252         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
253         break;
254     case TRAP_x86_SEGNPFLT:  /* Segment not present exception */
255     case TRAP_x86_PROTFLT:   /* General protection fault */
256     case TRAP_x86_UNKNOWN:   /* Unknown fault code */
257         rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
258                                                        : EXCEPTION_PRIV_INSTRUCTION;
259         break;
260     case TRAP_x86_PAGEFLT:  /* Page fault */
261         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
262 #ifdef FAULT_ADDRESS
263         rec.NumberParameters = 2;
264         rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
265         rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
266 #endif
267         break;
268     case TRAP_x86_ALIGNFLT:  /* Alignment check exception */
269         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
270         break;
271     default:
272         ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
273         /* fall through */
274     case TRAP_x86_NMI:       /* NMI interrupt */
275     case TRAP_x86_DNA:       /* Device not available exception */
276     case TRAP_x86_DOUBLEFLT: /* Double fault exception */
277     case TRAP_x86_TSSFLT:    /* Invalid TSS exception */
278     case TRAP_x86_MCHK:      /* Machine check exception */
279     case TRAP_x86_CACHEFLT:  /* Cache flush exception */
280         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
281         break;
282     }
283
284     __regs_RtlRaiseException( &rec, &context );
285     restore_context( &context, HANDLER_CONTEXT );
286 }
287
288 /**********************************************************************
289  *              trap_handler
290  *
291  * Handler for SIGTRAP.
292  */
293 static HANDLER_DEF(trap_handler)
294 {
295     EXCEPTION_RECORD rec;
296     CONTEXT context;
297
298     save_context( &context, HANDLER_CONTEXT );
299     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
300     rec.ExceptionRecord  = NULL;
301     rec.ExceptionAddress = (LPVOID)context.Rip;
302     rec.NumberParameters = 0;
303
304     switch(FAULT_CODE)
305     {
306     case TRAP_TRACE:  /* Single-step exception */
307         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
308         EFL_sig(HANDLER_CONTEXT) &= ~0x100;  /* clear single-step flag */
309         break;
310     case TRAP_BRKPT:   /* Breakpoint exception */
311         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
312         /* fall through */
313     default:
314         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
315         break;
316     }
317
318     __regs_RtlRaiseException( &rec, &context );
319     restore_context( &context, HANDLER_CONTEXT );
320 }
321
322 /**********************************************************************
323  *              fpe_handler
324  *
325  * Handler for SIGFPE.
326  */
327 static HANDLER_DEF(fpe_handler)
328 {
329     EXCEPTION_RECORD rec;
330     CONTEXT context;
331
332     save_context( &context, HANDLER_CONTEXT );
333     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
334     rec.ExceptionRecord  = NULL;
335     rec.ExceptionAddress = (LPVOID)context.Rip;
336     rec.NumberParameters = 0;
337
338     switch (FAULT_CODE)
339     {
340     case FPE_FLTSUB:
341         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
342         break;
343     case FPE_INTDIV:
344         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
345         break;
346     case FPE_INTOVF:
347         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
348         break;
349     case FPE_FLTDIV:
350         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
351         break;
352     case FPE_FLTOVF:
353         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
354         break;
355     case FPE_FLTUND:
356         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
357         break;
358     case FPE_FLTRES:
359         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
360         break;
361     case FPE_FLTINV:
362     default:
363         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
364         break;
365     }
366
367     __regs_RtlRaiseException( &rec, &context );
368     restore_context( &context, HANDLER_CONTEXT );
369 }
370
371 /**********************************************************************
372  *              int_handler
373  *
374  * Handler for SIGINT.
375  */
376 static HANDLER_DEF(int_handler)
377 {
378     if (!dispatch_signal(SIGINT))
379     {
380         EXCEPTION_RECORD rec;
381         CONTEXT context;
382
383         save_context( &context, HANDLER_CONTEXT );
384         rec.ExceptionCode    = CONTROL_C_EXIT;
385         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
386         rec.ExceptionRecord  = NULL;
387         rec.ExceptionAddress = (LPVOID)context.Rip;
388         rec.NumberParameters = 0;
389         __regs_RtlRaiseException( &rec, &context );
390         restore_context( &context, HANDLER_CONTEXT );
391     }
392 }
393
394
395 /**********************************************************************
396  *              abrt_handler
397  *
398  * Handler for SIGABRT.
399  */
400 static HANDLER_DEF(abrt_handler)
401 {
402     EXCEPTION_RECORD rec;
403     CONTEXT context;
404
405     save_context( &context, HANDLER_CONTEXT );
406     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
407     rec.ExceptionFlags   = EH_NONCONTINUABLE;
408     rec.ExceptionRecord  = NULL;
409     rec.ExceptionAddress = (LPVOID)context.Rip;
410     rec.NumberParameters = 0;
411     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
412     restore_context( &context, HANDLER_CONTEXT );
413 }
414
415
416 /**********************************************************************
417  *              quit_handler
418  *
419  * Handler for SIGQUIT.
420  */
421 static HANDLER_DEF(quit_handler)
422 {
423     server_abort_thread(0);
424 }
425
426
427 /**********************************************************************
428  *              usr1_handler
429  *
430  * Handler for SIGUSR1, used to signal a thread that it got suspended.
431  */
432 static HANDLER_DEF(usr1_handler)
433 {
434     CONTEXT context;
435
436     save_context( &context, HANDLER_CONTEXT );
437     wait_suspend( &context );
438     restore_context( &context, HANDLER_CONTEXT );
439 }
440
441
442 /**********************************************************************
443  *              get_signal_stack_total_size
444  *
445  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
446  * Must be a power of two.
447  */
448 size_t get_signal_stack_total_size(void)
449 {
450     assert( sizeof(TEB) <= 2*getpagesize() );
451     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
452 }
453
454
455 /***********************************************************************
456  *           set_handler
457  *
458  * Set a signal handler
459  */
460 static int set_handler( int sig, void (*func)() )
461 {
462     struct sigaction sig_act;
463
464     sig_act.sa_sigaction = func;
465     sig_act.sa_mask = server_block_set;
466     sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
467     return sigaction( sig, &sig_act, NULL );
468 }
469
470
471 /***********************************************************************
472  *           __wine_set_signal_handler   (NTDLL.@)
473  */
474 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
475 {
476     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
477     if (handlers[sig] != NULL) return -2;
478     handlers[sig] = wsh;
479     return 0;
480 }
481
482
483 /**********************************************************************
484  *              SIGNAL_Init
485  */
486 BOOL SIGNAL_Init(void)
487 {
488     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
489     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
490     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
491     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
492     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
493     if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
494     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
495 #ifdef SIGBUS
496     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
497 #endif
498 #ifdef SIGTRAP
499     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
500 #endif
501     return TRUE;
502
503  error:
504     perror("sigaction");
505     return FALSE;
506 }
507
508
509 /**********************************************************************
510  *              __wine_enter_vm86   (NTDLL.@)
511  */
512 void __wine_enter_vm86( CONTEXT *context )
513 {
514     MESSAGE("vm86 mode not supported on this platform\n");
515 }
516
517 /**********************************************************************
518  *              DbgBreakPoint   (NTDLL.@)
519  */
520 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
521
522 /**********************************************************************
523  *              DbgUserBreakPoint   (NTDLL.@)
524  */
525 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
526
527 #endif  /* __x86_64__ */