Preliminary implementation of signal handling for x86-64.
[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  *              segv_handler
201  *
202  * Handler for SIGSEGV and related errors.
203  */
204 static HANDLER_DEF(segv_handler)
205 {
206     EXCEPTION_RECORD rec;
207     CONTEXT context;
208
209     save_context( &context, HANDLER_CONTEXT );
210
211     rec.ExceptionRecord  = NULL;
212     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
213     rec.ExceptionAddress = (LPVOID)context.Rip;
214     rec.NumberParameters = 0;
215
216     switch(TRAP_sig(HANDLER_CONTEXT))
217     {
218     case T_OFLOW:   /* Overflow exception */
219         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
220         break;
221     case T_BOUND:   /* Bound range exception */
222         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
223         break;
224     case T_PRIVINFLT:   /* Invalid opcode exception */
225         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
226         break;
227     case T_STKFLT:  /* Stack fault */
228         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
229         break;
230     case T_SEGNPFLT:  /* Segment not present exception */
231     case T_PROTFLT:   /* General protection fault */
232     case T_UNKNOWN:   /* Unknown fault code */
233         rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
234                                                        : EXCEPTION_PRIV_INSTRUCTION;
235         break;
236     case T_PAGEFLT:  /* Page fault */
237         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
238 #ifdef FAULT_ADDRESS
239         rec.NumberParameters = 2;
240         rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
241         rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
242 #endif
243         break;
244     case T_ALIGNFLT:  /* Alignment check exception */
245         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
246         break;
247     default:
248         ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
249         /* fall through */
250     case T_NMI:       /* NMI interrupt */
251     case T_DNA:       /* Device not available exception */
252     case T_DOUBLEFLT: /* Double fault exception */
253     case T_TSSFLT:    /* Invalid TSS exception */
254     case T_RESERVED:  /* Unknown exception */
255     case T_MCHK:      /* Machine check exception */
256     case T_CACHEFLT:  /* Cache flush exception */
257         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
258         break;
259     }
260
261     __regs_RtlRaiseException( &rec, &context );
262     restore_context( &context, HANDLER_CONTEXT );
263 }
264
265 /**********************************************************************
266  *              trap_handler
267  *
268  * Handler for SIGTRAP.
269  */
270 static HANDLER_DEF(trap_handler)
271 {
272     EXCEPTION_RECORD rec;
273     CONTEXT context;
274
275     save_context( &context, HANDLER_CONTEXT );
276     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
277     rec.ExceptionRecord  = NULL;
278     rec.ExceptionAddress = (LPVOID)context.Rip;
279     rec.NumberParameters = 0;
280
281     switch(FAULT_CODE)
282     {
283     case TRAP_TRACE:  /* Single-step exception */
284         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
285         EFL_sig(HANDLER_CONTEXT) &= ~0x100;  /* clear single-step flag */
286         break;
287     case TRAP_BRKPT:   /* Breakpoint exception */
288         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
289         /* fall through */
290     default:
291         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
292         break;
293     }
294
295     __regs_RtlRaiseException( &rec, &context );
296     restore_context( &context, HANDLER_CONTEXT );
297 }
298
299 /**********************************************************************
300  *              fpe_handler
301  *
302  * Handler for SIGFPE.
303  */
304 static HANDLER_DEF(fpe_handler)
305 {
306     EXCEPTION_RECORD rec;
307     CONTEXT context;
308
309     save_context( &context, HANDLER_CONTEXT );
310     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
311     rec.ExceptionRecord  = NULL;
312     rec.ExceptionAddress = (LPVOID)context.Rip;
313     rec.NumberParameters = 0;
314
315     switch (FAULT_CODE)
316     {
317     case FPE_FLTSUB:
318         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
319         break;
320     case FPE_INTDIV:
321         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
322         break;
323     case FPE_INTOVF:
324         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
325         break;
326     case FPE_FLTDIV:
327         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
328         break;
329     case FPE_FLTOVF:
330         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
331         break;
332     case FPE_FLTUND:
333         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
334         break;
335     case FPE_FLTRES:
336         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
337         break;
338     case FPE_FLTINV:
339     default:
340         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
341         break;
342     }
343
344     __regs_RtlRaiseException( &rec, &context );
345     restore_context( &context, HANDLER_CONTEXT );
346 }
347
348 /**********************************************************************
349  *              int_handler
350  *
351  * Handler for SIGINT.
352  */
353 static HANDLER_DEF(int_handler)
354 {
355     if (!dispatch_signal(SIGINT))
356     {
357         EXCEPTION_RECORD rec;
358         CONTEXT context;
359
360         save_context( &context, HANDLER_CONTEXT );
361         rec.ExceptionCode    = CONTROL_C_EXIT;
362         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
363         rec.ExceptionRecord  = NULL;
364         rec.ExceptionAddress = (LPVOID)context.Rip;
365         rec.NumberParameters = 0;
366         __regs_RtlRaiseException( &rec, &context );
367         restore_context( &context, HANDLER_CONTEXT );
368     }
369 }
370
371
372 /**********************************************************************
373  *              abrt_handler
374  *
375  * Handler for SIGABRT.
376  */
377 static HANDLER_DEF(abrt_handler)
378 {
379     EXCEPTION_RECORD rec;
380     CONTEXT context;
381
382     save_context( &context, HANDLER_CONTEXT );
383     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
384     rec.ExceptionFlags   = EH_NONCONTINUABLE;
385     rec.ExceptionRecord  = NULL;
386     rec.ExceptionAddress = (LPVOID)context.Rip;
387     rec.NumberParameters = 0;
388     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
389     restore_context( &context, HANDLER_CONTEXT );
390 }
391
392
393 /**********************************************************************
394  *              term_handler
395  *
396  * Handler for SIGTERM.
397  */
398 static HANDLER_DEF(term_handler)
399 {
400     server_abort_thread(0);
401 }
402
403
404 /**********************************************************************
405  *              usr1_handler
406  *
407  * Handler for SIGUSR1, used to signal a thread that it got suspended.
408  */
409 static HANDLER_DEF(usr1_handler)
410 {
411     LARGE_INTEGER timeout;
412
413     /* wait with 0 timeout, will only return once the thread is no longer suspended */
414     timeout.QuadPart = 0;
415     NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout, 0 );
416 }
417
418
419 /**********************************************************************
420  *              get_signal_stack_total_size
421  *
422  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
423  * Must be a power of two.
424  */
425 size_t get_signal_stack_total_size(void)
426 {
427     assert( sizeof(TEB) <= 2*getpagesize() );
428     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
429 }
430
431
432 /***********************************************************************
433  *           set_handler
434  *
435  * Set a signal handler
436  */
437 static int set_handler( int sig, void (*func)() )
438 {
439     struct sigaction sig_act;
440
441     sig_act.sa_sigaction = func;
442     sigemptyset( &sig_act.sa_mask );
443     sigaddset( &sig_act.sa_mask, SIGINT );
444     sigaddset( &sig_act.sa_mask, SIGUSR2 );
445
446     sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
447     return sigaction( sig, &sig_act, NULL );
448 }
449
450
451 /***********************************************************************
452  *           __wine_set_signal_handler   (NTDLL.@)
453  */
454 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
455 {
456     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
457     if (handlers[sig] != NULL) return -2;
458     handlers[sig] = wsh;
459     return 0;
460 }
461
462
463 /**********************************************************************
464  *              SIGNAL_Init
465  */
466 BOOL SIGNAL_Init(void)
467 {
468     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
469     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
470     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
471     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
472     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
473     if (set_handler( SIGTERM, (void (*)())term_handler ) == -1) goto error;
474     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
475 #ifdef SIGBUS
476     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
477 #endif
478 #ifdef SIGTRAP
479     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
480 #endif
481     return TRUE;
482
483  error:
484     perror("sigaction");
485     return FALSE;
486 }
487
488
489 /**********************************************************************
490  *              __wine_enter_vm86   (NTDLL.@)
491  */
492 void __wine_enter_vm86( CONTEXT *context )
493 {
494     MESSAGE("vm86 mode not supported on this platform\n");
495 }
496
497 /**********************************************************************
498  *              DbgBreakPoint   (NTDLL.@)
499  */
500 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
501
502 /**********************************************************************
503  *              DbgUserBreakPoint   (NTDLL.@)
504  */
505 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
506
507 #endif  /* __x86_64__ */