Dbghelp describes the types of function arguments with a specific
[wine/wine64.git] / dlls / ntdll / signal_x86_64.c
blob271e0a981ddf67b5d9c14b84156d97a58c9c99ce
1 /*
2 * x86-64 signal handling routines
4 * Copyright 1999, 2005 Alexandre Julliard
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.
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.
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
21 #ifdef __x86_64__
23 #include "config.h"
24 #include "wine/port.h"
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
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
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"
50 WINE_DEFAULT_DEBUG_CHANNEL(seh);
53 /***********************************************************************
54 * signal context platform-specific definitions
56 #ifdef linux
58 typedef struct ucontext SIGCONTEXT;
60 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
61 # define HANDLER_CONTEXT (__context)
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])
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))
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])
89 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
91 #define FAULT_CODE (__siginfo->si_code)
92 #define FAULT_ADDRESS (__siginfo->si_addr)
94 #endif /* linux */
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 */
118 typedef int (*wine_signal_handler)(unsigned int sig);
120 static wine_signal_handler handlers[256];
122 /***********************************************************************
123 * dispatch_signal
125 inline static int dispatch_signal(unsigned int sig)
127 if (handlers[sig] == NULL) return 0;
128 return handlers[sig](sig);
131 /***********************************************************************
132 * save_context
134 * Set the register values from a sigcontext.
136 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
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);
167 /***********************************************************************
168 * restore_context
170 * Build a sigcontext from the register values.
172 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
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;
199 /**********************************************************************
200 * segv_handler
202 * Handler for SIGSEGV and related errors.
204 static HANDLER_DEF(segv_handler)
206 EXCEPTION_RECORD rec;
207 CONTEXT context;
209 save_context( &context, HANDLER_CONTEXT );
211 rec.ExceptionRecord = NULL;
212 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
213 rec.ExceptionAddress = (LPVOID)context.Rip;
214 rec.NumberParameters = 0;
216 switch(TRAP_sig(HANDLER_CONTEXT))
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;
261 __regs_RtlRaiseException( &rec, &context );
262 restore_context( &context, HANDLER_CONTEXT );
265 /**********************************************************************
266 * trap_handler
268 * Handler for SIGTRAP.
270 static HANDLER_DEF(trap_handler)
272 EXCEPTION_RECORD rec;
273 CONTEXT context;
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;
281 switch(FAULT_CODE)
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;
295 __regs_RtlRaiseException( &rec, &context );
296 restore_context( &context, HANDLER_CONTEXT );
299 /**********************************************************************
300 * fpe_handler
302 * Handler for SIGFPE.
304 static HANDLER_DEF(fpe_handler)
306 EXCEPTION_RECORD rec;
307 CONTEXT context;
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;
315 switch (FAULT_CODE)
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;
344 __regs_RtlRaiseException( &rec, &context );
345 restore_context( &context, HANDLER_CONTEXT );
348 /**********************************************************************
349 * int_handler
351 * Handler for SIGINT.
353 static HANDLER_DEF(int_handler)
355 if (!dispatch_signal(SIGINT))
357 EXCEPTION_RECORD rec;
358 CONTEXT context;
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 );
372 /**********************************************************************
373 * abrt_handler
375 * Handler for SIGABRT.
377 static HANDLER_DEF(abrt_handler)
379 EXCEPTION_RECORD rec;
380 CONTEXT context;
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 );
393 /**********************************************************************
394 * term_handler
396 * Handler for SIGTERM.
398 static HANDLER_DEF(term_handler)
400 server_abort_thread(0);
404 /**********************************************************************
405 * usr1_handler
407 * Handler for SIGUSR1, used to signal a thread that it got suspended.
409 static HANDLER_DEF(usr1_handler)
411 CONTEXT context;
413 save_context( &context, HANDLER_CONTEXT );
414 wait_suspend( &context );
415 restore_context( &context, HANDLER_CONTEXT );
419 /**********************************************************************
420 * get_signal_stack_total_size
422 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
423 * Must be a power of two.
425 size_t get_signal_stack_total_size(void)
427 assert( sizeof(TEB) <= 2*getpagesize() );
428 return 2*getpagesize(); /* this is just for the TEB, we don't need a signal stack */
432 /***********************************************************************
433 * set_handler
435 * Set a signal handler
437 static int set_handler( int sig, void (*func)() )
439 struct sigaction sig_act;
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 );
446 sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
447 return sigaction( sig, &sig_act, NULL );
451 /***********************************************************************
452 * __wine_set_signal_handler (NTDLL.@)
454 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
456 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
457 if (handlers[sig] != NULL) return -2;
458 handlers[sig] = wsh;
459 return 0;
463 /**********************************************************************
464 * SIGNAL_Init
466 BOOL SIGNAL_Init(void)
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;
483 error:
484 perror("sigaction");
485 return FALSE;
489 /**********************************************************************
490 * __wine_enter_vm86 (NTDLL.@)
492 void __wine_enter_vm86( CONTEXT *context )
494 MESSAGE("vm86 mode not supported on this platform\n");
497 /**********************************************************************
498 * DbgBreakPoint (NTDLL.@)
500 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
502 /**********************************************************************
503 * DbgUserBreakPoint (NTDLL.@)
505 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
507 #endif /* __x86_64__ */