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
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 #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 /***********************************************************************
125 inline static int dispatch_signal(unsigned int sig
)
127 if (handlers
[sig
] == NULL
) return 0;
128 return handlers
[sig
](sig
);
131 /***********************************************************************
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 /***********************************************************************
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 /**********************************************************************
202 * Handler for SIGSEGV and related errors.
204 static HANDLER_DEF(segv_handler
)
206 EXCEPTION_RECORD rec
;
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
;
221 case T_BOUND
: /* Bound range exception */
222 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
224 case T_PRIVINFLT
: /* Invalid opcode exception */
225 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
227 case T_STKFLT
: /* Stack fault */
228 rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
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
;
236 case T_PAGEFLT
: /* Page fault */
237 rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
239 rec
.NumberParameters
= 2;
240 rec
.ExceptionInformation
[0] = (ERROR_sig(HANDLER_CONTEXT
) & 2) != 0;
241 rec
.ExceptionInformation
[1] = (ULONG_PTR
)FAULT_ADDRESS
;
244 case T_ALIGNFLT
: /* Alignment check exception */
245 rec
.ExceptionCode
= EXCEPTION_DATATYPE_MISALIGNMENT
;
248 ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT
) );
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
;
261 __regs_RtlRaiseException( &rec
, &context
);
262 restore_context( &context
, HANDLER_CONTEXT
);
265 /**********************************************************************
268 * Handler for SIGTRAP.
270 static HANDLER_DEF(trap_handler
)
272 EXCEPTION_RECORD rec
;
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;
283 case TRAP_TRACE
: /* Single-step exception */
284 rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
285 EFL_sig(HANDLER_CONTEXT
) &= ~0x100; /* clear single-step flag */
287 case TRAP_BRKPT
: /* Breakpoint exception */
288 rec
.ExceptionAddress
= (char *)rec
.ExceptionAddress
- 1; /* back up over the int3 instruction */
291 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
295 __regs_RtlRaiseException( &rec
, &context
);
296 restore_context( &context
, HANDLER_CONTEXT
);
299 /**********************************************************************
302 * Handler for SIGFPE.
304 static HANDLER_DEF(fpe_handler
)
306 EXCEPTION_RECORD rec
;
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;
318 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
321 rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
324 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
327 rec
.ExceptionCode
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
330 rec
.ExceptionCode
= EXCEPTION_FLT_OVERFLOW
;
333 rec
.ExceptionCode
= EXCEPTION_FLT_UNDERFLOW
;
336 rec
.ExceptionCode
= EXCEPTION_FLT_INEXACT_RESULT
;
340 rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
344 __regs_RtlRaiseException( &rec
, &context
);
345 restore_context( &context
, HANDLER_CONTEXT
);
348 /**********************************************************************
351 * Handler for SIGINT.
353 static HANDLER_DEF(int_handler
)
355 if (!dispatch_signal(SIGINT
))
357 EXCEPTION_RECORD rec
;
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 /**********************************************************************
375 * Handler for SIGABRT.
377 static HANDLER_DEF(abrt_handler
)
379 EXCEPTION_RECORD rec
;
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 /**********************************************************************
396 * Handler for SIGTERM.
398 static HANDLER_DEF(term_handler
)
400 server_abort_thread(0);
404 /**********************************************************************
407 * Handler for SIGUSR1, used to signal a thread that it got suspended.
409 static HANDLER_DEF(usr1_handler
)
411 LARGE_INTEGER timeout
;
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 );
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 /***********************************************************************
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;
463 /**********************************************************************
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
;
476 if (set_handler( SIGBUS
, (void (*)())segv_handler
) == -1) goto error
;
479 if (set_handler( SIGTRAP
, (void (*)())trap_handler
) == -1) goto error
;
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__ */