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