ntdll: Use the NTAPI definition of EXCEPTION_ACCESS_VIOLATION.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 #define T_UNKNOWN     (-1)  /* Unknown fault (TRAP_sig not defined) */
97 #define T_DIVIDE        0   /* Division by zero exception */
98 #define T_TRCTRAP       1   /* Single-step exception */
99 #define T_NMI           2   /* NMI interrupt */
100 #define T_BPTFLT        3   /* Breakpoint exception */
101 #define T_OFLOW         4   /* Overflow exception */
102 #define T_BOUND         5   /* Bound range exception */
103 #define T_PRIVINFLT     6   /* Invalid opcode exception */
104 #define T_DNA           7   /* Device not available exception */
105 #define T_DOUBLEFLT     8   /* Double fault exception */
106 #define T_FPOPFLT       9   /* Coprocessor segment overrun */
107 #define T_TSSFLT        10  /* Invalid TSS exception */
108 #define T_SEGNPFLT      11  /* Segment not present exception */
109 #define T_STKFLT        12  /* Stack fault */
110 #define T_PROTFLT       13  /* General protection fault */
111 #define T_PAGEFLT       14  /* Page fault */
112 #define T_RESERVED      15  /* Unknown exception */
113 #define T_ARITHTRAP     16  /* Floating point exception */
114 #define T_ALIGNFLT      17  /* Alignment check exception */
115 #define T_MCHK          18  /* Machine check exception */
116 #define T_CACHEFLT      19  /* Cache flush exception */
117
118 typedef int (*wine_signal_handler)(unsigned int sig);
119
120 static wine_signal_handler handlers[256];
121
122 /***********************************************************************
123  *           dispatch_signal
124  */
125 inline static int dispatch_signal(unsigned int sig)
126 {
127     if (handlers[sig] == NULL) return 0;
128     return handlers[sig](sig);
129 }
130
131 /***********************************************************************
132  *           save_context
133  *
134  * Set the register values from a sigcontext.
135  */
136 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
137 {
138     context->Rax    = RAX_sig(sigcontext);
139     context->Rcx    = RCX_sig(sigcontext);
140     context->Rdx    = RDX_sig(sigcontext);
141     context->Rbx    = RBX_sig(sigcontext);
142     context->Rsp    = RSP_sig(sigcontext);
143     context->Rbp    = RBP_sig(sigcontext);
144     context->Rsi    = RSI_sig(sigcontext);
145     context->Rdi    = RDI_sig(sigcontext);
146     context->R8     = R8_sig(sigcontext);
147     context->R9     = R9_sig(sigcontext);
148     context->R10    = R10_sig(sigcontext);
149     context->R11    = R11_sig(sigcontext);
150     context->R12    = R12_sig(sigcontext);
151     context->R13    = R13_sig(sigcontext);
152     context->R14    = R14_sig(sigcontext);
153     context->R15    = R15_sig(sigcontext);
154     context->Rip    = RIP_sig(sigcontext);
155     context->SegCs  = CS_sig(sigcontext);
156     context->SegFs  = FS_sig(sigcontext);
157     context->SegGs  = GS_sig(sigcontext);
158     context->EFlags = EFL_sig(sigcontext);
159     context->SegDs  = 0;  /* FIXME */
160     context->SegEs  = 0;  /* FIXME */
161     context->SegSs  = 0;  /* FIXME */
162     context->MxCsr  = 0;  /* FIXME */
163     if (FPU_sig(sigcontext)) context->u.FltSave = *FPU_sig(sigcontext);
164 }
165
166
167 /***********************************************************************
168  *           restore_context
169  *
170  * Build a sigcontext from the register values.
171  */
172 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
173 {
174     RAX_sig(sigcontext) = context->Rax;
175     RCX_sig(sigcontext) = context->Rcx;
176     RDX_sig(sigcontext) = context->Rdx;
177     RBX_sig(sigcontext) = context->Rbx;
178     RSP_sig(sigcontext) = context->Rsp;
179     RBP_sig(sigcontext) = context->Rbp;
180     RSI_sig(sigcontext) = context->Rsi;
181     RDI_sig(sigcontext) = context->Rdi;
182     R8_sig(sigcontext)  = context->R8;
183     R9_sig(sigcontext)  = context->R9;
184     R10_sig(sigcontext) = context->R10;
185     R11_sig(sigcontext) = context->R11;
186     R12_sig(sigcontext) = context->R12;
187     R13_sig(sigcontext) = context->R13;
188     R14_sig(sigcontext) = context->R14;
189     R15_sig(sigcontext) = context->R15;
190     RIP_sig(sigcontext) = context->Rip;
191     CS_sig(sigcontext)  = context->SegCs;
192     FS_sig(sigcontext)  = context->SegFs;
193     GS_sig(sigcontext)  = context->SegGs;
194     EFL_sig(sigcontext) = context->EFlags;
195     if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
196 }
197
198
199 /***********************************************************************
200  *           set_cpu_context
201  *
202  * Set the new CPU context.
203  */
204 void set_cpu_context( const CONTEXT *context )
205 {
206     FIXME("not implemented\n");
207 }
208
209
210 /**********************************************************************
211  *              segv_handler
212  *
213  * Handler for SIGSEGV and related errors.
214  */
215 static HANDLER_DEF(segv_handler)
216 {
217     EXCEPTION_RECORD rec;
218     CONTEXT context;
219
220     save_context( &context, HANDLER_CONTEXT );
221
222     rec.ExceptionRecord  = NULL;
223     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
224     rec.ExceptionAddress = (LPVOID)context.Rip;
225     rec.NumberParameters = 0;
226
227     switch(TRAP_sig(HANDLER_CONTEXT))
228     {
229     case T_OFLOW:   /* Overflow exception */
230         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
231         break;
232     case T_BOUND:   /* Bound range exception */
233         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
234         break;
235     case T_PRIVINFLT:   /* Invalid opcode exception */
236         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
237         break;
238     case T_STKFLT:  /* Stack fault */
239         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
240         break;
241     case T_SEGNPFLT:  /* Segment not present exception */
242     case T_PROTFLT:   /* General protection fault */
243     case T_UNKNOWN:   /* Unknown fault code */
244         rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
245                                                        : EXCEPTION_PRIV_INSTRUCTION;
246         break;
247     case T_PAGEFLT:  /* Page fault */
248         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
249 #ifdef FAULT_ADDRESS
250         rec.NumberParameters = 2;
251         rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
252         rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
253 #endif
254         break;
255     case T_ALIGNFLT:  /* Alignment check exception */
256         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
257         break;
258     default:
259         ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
260         /* fall through */
261     case T_NMI:       /* NMI interrupt */
262     case T_DNA:       /* Device not available exception */
263     case T_DOUBLEFLT: /* Double fault exception */
264     case T_TSSFLT:    /* Invalid TSS exception */
265     case T_RESERVED:  /* Unknown exception */
266     case T_MCHK:      /* Machine check exception */
267     case T_CACHEFLT:  /* Cache flush exception */
268         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
269         break;
270     }
271
272     __regs_RtlRaiseException( &rec, &context );
273     restore_context( &context, HANDLER_CONTEXT );
274 }
275
276 /**********************************************************************
277  *              trap_handler
278  *
279  * Handler for SIGTRAP.
280  */
281 static HANDLER_DEF(trap_handler)
282 {
283     EXCEPTION_RECORD rec;
284     CONTEXT context;
285
286     save_context( &context, HANDLER_CONTEXT );
287     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
288     rec.ExceptionRecord  = NULL;
289     rec.ExceptionAddress = (LPVOID)context.Rip;
290     rec.NumberParameters = 0;
291
292     switch(FAULT_CODE)
293     {
294     case TRAP_TRACE:  /* Single-step exception */
295         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
296         EFL_sig(HANDLER_CONTEXT) &= ~0x100;  /* clear single-step flag */
297         break;
298     case TRAP_BRKPT:   /* Breakpoint exception */
299         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
300         /* fall through */
301     default:
302         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
303         break;
304     }
305
306     __regs_RtlRaiseException( &rec, &context );
307     restore_context( &context, HANDLER_CONTEXT );
308 }
309
310 /**********************************************************************
311  *              fpe_handler
312  *
313  * Handler for SIGFPE.
314  */
315 static HANDLER_DEF(fpe_handler)
316 {
317     EXCEPTION_RECORD rec;
318     CONTEXT context;
319
320     save_context( &context, HANDLER_CONTEXT );
321     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
322     rec.ExceptionRecord  = NULL;
323     rec.ExceptionAddress = (LPVOID)context.Rip;
324     rec.NumberParameters = 0;
325
326     switch (FAULT_CODE)
327     {
328     case FPE_FLTSUB:
329         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
330         break;
331     case FPE_INTDIV:
332         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
333         break;
334     case FPE_INTOVF:
335         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
336         break;
337     case FPE_FLTDIV:
338         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
339         break;
340     case FPE_FLTOVF:
341         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
342         break;
343     case FPE_FLTUND:
344         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
345         break;
346     case FPE_FLTRES:
347         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
348         break;
349     case FPE_FLTINV:
350     default:
351         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
352         break;
353     }
354
355     __regs_RtlRaiseException( &rec, &context );
356     restore_context( &context, HANDLER_CONTEXT );
357 }
358
359 /**********************************************************************
360  *              int_handler
361  *
362  * Handler for SIGINT.
363  */
364 static HANDLER_DEF(int_handler)
365 {
366     if (!dispatch_signal(SIGINT))
367     {
368         EXCEPTION_RECORD rec;
369         CONTEXT context;
370
371         save_context( &context, HANDLER_CONTEXT );
372         rec.ExceptionCode    = CONTROL_C_EXIT;
373         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
374         rec.ExceptionRecord  = NULL;
375         rec.ExceptionAddress = (LPVOID)context.Rip;
376         rec.NumberParameters = 0;
377         __regs_RtlRaiseException( &rec, &context );
378         restore_context( &context, HANDLER_CONTEXT );
379     }
380 }
381
382
383 /**********************************************************************
384  *              abrt_handler
385  *
386  * Handler for SIGABRT.
387  */
388 static HANDLER_DEF(abrt_handler)
389 {
390     EXCEPTION_RECORD rec;
391     CONTEXT context;
392
393     save_context( &context, HANDLER_CONTEXT );
394     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
395     rec.ExceptionFlags   = EH_NONCONTINUABLE;
396     rec.ExceptionRecord  = NULL;
397     rec.ExceptionAddress = (LPVOID)context.Rip;
398     rec.NumberParameters = 0;
399     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
400     restore_context( &context, HANDLER_CONTEXT );
401 }
402
403
404 /**********************************************************************
405  *              term_handler
406  *
407  * Handler for SIGTERM.
408  */
409 static HANDLER_DEF(term_handler)
410 {
411     server_abort_thread(0);
412 }
413
414
415 /**********************************************************************
416  *              usr1_handler
417  *
418  * Handler for SIGUSR1, used to signal a thread that it got suspended.
419  */
420 static HANDLER_DEF(usr1_handler)
421 {
422     CONTEXT context;
423
424     save_context( &context, HANDLER_CONTEXT );
425     wait_suspend( &context );
426     restore_context( &context, HANDLER_CONTEXT );
427 }
428
429
430 /**********************************************************************
431  *              get_signal_stack_total_size
432  *
433  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
434  * Must be a power of two.
435  */
436 size_t get_signal_stack_total_size(void)
437 {
438     assert( sizeof(TEB) <= 2*getpagesize() );
439     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
440 }
441
442
443 /***********************************************************************
444  *           set_handler
445  *
446  * Set a signal handler
447  */
448 static int set_handler( int sig, void (*func)() )
449 {
450     struct sigaction sig_act;
451
452     sig_act.sa_sigaction = func;
453     sigemptyset( &sig_act.sa_mask );
454     sigaddset( &sig_act.sa_mask, SIGINT );
455     sigaddset( &sig_act.sa_mask, SIGUSR2 );
456
457     sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
458     return sigaction( sig, &sig_act, NULL );
459 }
460
461
462 /***********************************************************************
463  *           __wine_set_signal_handler   (NTDLL.@)
464  */
465 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
466 {
467     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
468     if (handlers[sig] != NULL) return -2;
469     handlers[sig] = wsh;
470     return 0;
471 }
472
473
474 /**********************************************************************
475  *              SIGNAL_Init
476  */
477 BOOL SIGNAL_Init(void)
478 {
479     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
480     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
481     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
482     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
483     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
484     if (set_handler( SIGTERM, (void (*)())term_handler ) == -1) goto error;
485     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
486 #ifdef SIGBUS
487     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
488 #endif
489 #ifdef SIGTRAP
490     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
491 #endif
492     return TRUE;
493
494  error:
495     perror("sigaction");
496     return FALSE;
497 }
498
499
500 /**********************************************************************
501  *              __wine_enter_vm86   (NTDLL.@)
502  */
503 void __wine_enter_vm86( CONTEXT *context )
504 {
505     MESSAGE("vm86 mode not supported on this platform\n");
506 }
507
508 /**********************************************************************
509  *              DbgBreakPoint   (NTDLL.@)
510  */
511 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
512
513 /**********************************************************************
514  *              DbgUserBreakPoint   (NTDLL.@)
515  */
516 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
517
518 #endif  /* __x86_64__ */