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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
38 #ifdef HAVE_SYS_SIGNAL_H
39 # include <sys/signal.h>
42 #define NONAMELESSUNION
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
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)
96 #if defined(__NetBSD__)
97 # include <sys/ucontext.h>
98 # include <sys/types.h>
101 typedef ucontext_t SIGCONTEXT;
103 #define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
104 #define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
105 #define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
106 #define RDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDX])
107 #define RSI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RSI])
108 #define RDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDI])
109 #define RBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBP])
110 #define R8_sig(context) ((context)->uc_mcontext.__gregs[_REG_R8])
111 #define R9_sig(context) ((context)->uc_mcontext.__gregs[_REG_R9])
112 #define R10_sig(context) ((context)->uc_mcontext.__gregs[_REG_R10])
113 #define R11_sig(context) ((context)->uc_mcontext.__gregs[_REG_R11])
114 #define R12_sig(context) ((context)->uc_mcontext.__gregs[_REG_R12])
115 #define R13_sig(context) ((context)->uc_mcontext.__gregs[_REG_R13])
116 #define R14_sig(context) ((context)->uc_mcontext.__gregs[_REG_R14])
117 #define R15_sig(context) ((context)->uc_mcontext.__gregs[_REG_R15])
119 #define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
120 #define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
121 #define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
122 #define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
123 #define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
124 #define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
126 #define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_RFL])
128 #define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_RIP]))
129 #define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_URSP]))
131 #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
132 #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
134 #define FAULT_CODE (__siginfo->si_code)
135 #define FAULT_ADDRESS (__siginfo->si_addr)
137 #define HANDLER_DEF(name) void name( int __signal, siginfo_t *__siginfo, SIGCONTEXT *__context )
138 #define HANDLER_CONTEXT (__context)
140 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
141 #endif /* __NetBSD__ */
145 TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */
146 TRAP_x86_DIVIDE = 0, /* Division by zero exception */
147 TRAP_x86_TRCTRAP = 1, /* Single-step exception */
148 TRAP_x86_NMI = 2, /* NMI interrupt */
149 TRAP_x86_BPTFLT = 3, /* Breakpoint exception */
150 TRAP_x86_OFLOW = 4, /* Overflow exception */
151 TRAP_x86_BOUND = 5, /* Bound range exception */
152 TRAP_x86_PRIVINFLT = 6, /* Invalid opcode exception */
153 TRAP_x86_DNA = 7, /* Device not available exception */
154 TRAP_x86_DOUBLEFLT = 8, /* Double fault exception */
155 TRAP_x86_FPOPFLT = 9, /* Coprocessor segment overrun */
156 TRAP_x86_TSSFLT = 10, /* Invalid TSS exception */
157 TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */
158 TRAP_x86_STKFLT = 12, /* Stack fault */
159 TRAP_x86_PROTFLT = 13, /* General protection fault */
160 TRAP_x86_PAGEFLT = 14, /* Page fault */
161 TRAP_x86_ARITHTRAP = 16, /* Floating point exception */
162 TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */
163 TRAP_x86_MCHK = 18, /* Machine check exception */
164 TRAP_x86_CACHEFLT = 19 /* Cache flush exception */
167 typedef int (*wine_signal_handler)(unsigned int sig);
169 static wine_signal_handler handlers[256];
171 /***********************************************************************
174 static inline int dispatch_signal(unsigned int sig)
176 if (handlers[sig] == NULL) return 0;
177 return handlers[sig](sig);
180 /***********************************************************************
183 * Set the register values from a sigcontext.
185 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
187 context->Rax = RAX_sig(sigcontext);
188 context->Rcx = RCX_sig(sigcontext);
189 context->Rdx = RDX_sig(sigcontext);
190 context->Rbx = RBX_sig(sigcontext);
191 context->Rsp = RSP_sig(sigcontext);
192 context->Rbp = RBP_sig(sigcontext);
193 context->Rsi = RSI_sig(sigcontext);
194 context->Rdi = RDI_sig(sigcontext);
195 context->R8 = R8_sig(sigcontext);
196 context->R9 = R9_sig(sigcontext);
197 context->R10 = R10_sig(sigcontext);
198 context->R11 = R11_sig(sigcontext);
199 context->R12 = R12_sig(sigcontext);
200 context->R13 = R13_sig(sigcontext);
201 context->R14 = R14_sig(sigcontext);
202 context->R15 = R15_sig(sigcontext);
203 context->Rip = RIP_sig(sigcontext);
204 context->SegCs = CS_sig(sigcontext);
205 context->SegFs = FS_sig(sigcontext);
206 context->SegGs = GS_sig(sigcontext);
207 context->EFlags = EFL_sig(sigcontext);
208 context->SegDs = 0; /* FIXME */
209 context->SegEs = 0; /* FIXME */
210 context->SegSs = 0; /* FIXME */
211 context->MxCsr = 0; /* FIXME */
212 if (FPU_sig(sigcontext)) context->u.FltSave = *FPU_sig(sigcontext);
216 /***********************************************************************
219 * Build a sigcontext from the register values.
221 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
223 RAX_sig(sigcontext) = context->Rax;
224 RCX_sig(sigcontext) = context->Rcx;
225 RDX_sig(sigcontext) = context->Rdx;
226 RBX_sig(sigcontext) = context->Rbx;
227 RSP_sig(sigcontext) = context->Rsp;
228 RBP_sig(sigcontext) = context->Rbp;
229 RSI_sig(sigcontext) = context->Rsi;
230 RDI_sig(sigcontext) = context->Rdi;
231 R8_sig(sigcontext) = context->R8;
232 R9_sig(sigcontext) = context->R9;
233 R10_sig(sigcontext) = context->R10;
234 R11_sig(sigcontext) = context->R11;
235 R12_sig(sigcontext) = context->R12;
236 R13_sig(sigcontext) = context->R13;
237 R14_sig(sigcontext) = context->R14;
238 R15_sig(sigcontext) = context->R15;
239 RIP_sig(sigcontext) = context->Rip;
240 CS_sig(sigcontext) = context->SegCs;
241 FS_sig(sigcontext) = context->SegFs;
242 GS_sig(sigcontext) = context->SegGs;
243 EFL_sig(sigcontext) = context->EFlags;
244 if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
248 /***********************************************************************
249 * RtlCaptureContext (NTDLL.@)
251 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
255 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
258 /***********************************************************************
261 * Set the new CPU context.
263 void set_cpu_context( const CONTEXT *context )
265 FIXME("not implemented\n");
269 /**********************************************************************
272 * Handler for SIGSEGV and related errors.
274 static HANDLER_DEF(segv_handler)
276 EXCEPTION_RECORD rec;
279 save_context( &context, HANDLER_CONTEXT );
281 rec.ExceptionRecord = NULL;
282 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
283 rec.ExceptionAddress = (LPVOID)context.Rip;
284 rec.NumberParameters = 0;
286 switch(TRAP_sig(HANDLER_CONTEXT))
288 case TRAP_x86_OFLOW: /* Overflow exception */
289 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
291 case TRAP_x86_BOUND: /* Bound range exception */
292 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
294 case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */
295 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
297 case TRAP_x86_STKFLT: /* Stack fault */
298 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
300 case TRAP_x86_SEGNPFLT: /* Segment not present exception */
301 case TRAP_x86_PROTFLT: /* General protection fault */
302 case TRAP_x86_UNKNOWN: /* Unknown fault code */
303 rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
304 : EXCEPTION_PRIV_INSTRUCTION;
306 case TRAP_x86_PAGEFLT: /* Page fault */
307 rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
309 rec.NumberParameters = 2;
310 rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
311 rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
312 if (!(rec.ExceptionCode = virtual_handle_fault( FAULT_ADDRESS, rec.ExceptionInformation[0] )))
316 case TRAP_x86_ALIGNFLT: /* Alignment check exception */
317 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
320 ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
322 case TRAP_x86_NMI: /* NMI interrupt */
323 case TRAP_x86_DNA: /* Device not available exception */
324 case TRAP_x86_DOUBLEFLT: /* Double fault exception */
325 case TRAP_x86_TSSFLT: /* Invalid TSS exception */
326 case TRAP_x86_MCHK: /* Machine check exception */
327 case TRAP_x86_CACHEFLT: /* Cache flush exception */
328 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
332 __regs_RtlRaiseException( &rec, &context );
334 restore_context( &context, HANDLER_CONTEXT );
337 /**********************************************************************
340 * Handler for SIGTRAP.
342 static HANDLER_DEF(trap_handler)
344 EXCEPTION_RECORD rec;
347 save_context( &context, HANDLER_CONTEXT );
348 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
349 rec.ExceptionRecord = NULL;
350 rec.ExceptionAddress = (LPVOID)context.Rip;
351 rec.NumberParameters = 0;
355 case TRAP_TRACE: /* Single-step exception */
356 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
357 EFL_sig(HANDLER_CONTEXT) &= ~0x100; /* clear single-step flag */
359 case TRAP_BRKPT: /* Breakpoint exception */
360 rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */
363 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
367 __regs_RtlRaiseException( &rec, &context );
368 restore_context( &context, HANDLER_CONTEXT );
371 /**********************************************************************
374 * Handler for SIGFPE.
376 static HANDLER_DEF(fpe_handler)
378 EXCEPTION_RECORD rec;
381 save_context( &context, HANDLER_CONTEXT );
382 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
383 rec.ExceptionRecord = NULL;
384 rec.ExceptionAddress = (LPVOID)context.Rip;
385 rec.NumberParameters = 0;
390 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
393 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
396 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
399 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
402 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
405 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
408 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
412 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
416 __regs_RtlRaiseException( &rec, &context );
417 restore_context( &context, HANDLER_CONTEXT );
420 /**********************************************************************
423 * Handler for SIGINT.
425 static HANDLER_DEF(int_handler)
427 if (!dispatch_signal(SIGINT))
429 EXCEPTION_RECORD rec;
432 save_context( &context, HANDLER_CONTEXT );
433 rec.ExceptionCode = CONTROL_C_EXIT;
434 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
435 rec.ExceptionRecord = NULL;
436 rec.ExceptionAddress = (LPVOID)context.Rip;
437 rec.NumberParameters = 0;
438 __regs_RtlRaiseException( &rec, &context );
439 restore_context( &context, HANDLER_CONTEXT );
444 /**********************************************************************
447 * Handler for SIGABRT.
449 static HANDLER_DEF(abrt_handler)
451 EXCEPTION_RECORD rec;
454 save_context( &context, HANDLER_CONTEXT );
455 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
456 rec.ExceptionFlags = EH_NONCONTINUABLE;
457 rec.ExceptionRecord = NULL;
458 rec.ExceptionAddress = (LPVOID)context.Rip;
459 rec.NumberParameters = 0;
460 __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
461 restore_context( &context, HANDLER_CONTEXT );
465 /**********************************************************************
468 * Handler for SIGQUIT.
470 static HANDLER_DEF(quit_handler)
472 server_abort_thread(0);
476 /**********************************************************************
479 * Handler for SIGUSR1, used to signal a thread that it got suspended.
481 static HANDLER_DEF(usr1_handler)
485 save_context( &context, HANDLER_CONTEXT );
486 wait_suspend( &context );
487 restore_context( &context, HANDLER_CONTEXT );
491 /**********************************************************************
492 * get_signal_stack_total_size
494 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
495 * Must be a power of two.
497 size_t get_signal_stack_total_size(void)
499 assert( sizeof(TEB) <= 2*getpagesize() );
500 return 2*getpagesize(); /* this is just for the TEB, we don't need a signal stack */
504 /***********************************************************************
507 * Set a signal handler
509 static int set_handler( int sig, void (*func)() )
511 struct sigaction sig_act;
513 sig_act.sa_sigaction = func;
514 sig_act.sa_mask = server_block_set;
515 sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
516 return sigaction( sig, &sig_act, NULL );
520 /***********************************************************************
521 * __wine_set_signal_handler (NTDLL.@)
523 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
525 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
526 if (handlers[sig] != NULL) return -2;
532 /**********************************************************************
535 void signal_init_thread(void)
539 /**********************************************************************
540 * signal_init_process
542 void signal_init_process(void)
544 if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error;
545 if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error;
546 if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
547 if (set_handler( SIGILL, (void (*)())segv_handler ) == -1) goto error;
548 if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
549 if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
550 if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
552 if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error;
555 if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
557 signal_init_thread();
566 /**********************************************************************
567 * RtlLookupFunctionEntry (NTDLL.@)
569 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
570 UNWIND_HISTORY_TABLE *table )
577 /**********************************************************************
578 * RtlVirtualUnwind (NTDLL.@)
580 PVOID WINAPI RtlVirtualUnwind ( ULONG type, ULONG64 base, ULONG64 pc,
581 RUNTIME_FUNCTION *function, CONTEXT *context,
582 PVOID *data, ULONG64 *frame,
583 KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
590 /**********************************************************************
591 * __wine_enter_vm86 (NTDLL.@)
593 void __wine_enter_vm86( CONTEXT *context )
595 MESSAGE("vm86 mode not supported on this platform\n");
598 /**********************************************************************
599 * DbgBreakPoint (NTDLL.@)
601 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
603 /**********************************************************************
604 * DbgUserBreakPoint (NTDLL.@)
606 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
608 #endif /* __x86_64__ */