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
44 #define WIN32_NO_STATUS
47 #include "wine/library.h"
48 #include "wine/exception.h"
49 #include "ntdll_misc.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
55 /***********************************************************************
56 * signal context platform-specific definitions
60 #include <asm/prctl.h>
61 extern int arch_prctl(int func
, void *ptr
);
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))
93 #if defined(__NetBSD__)
94 # include <sys/ucontext.h>
95 # include <sys/types.h>
98 #define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
99 #define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
100 #define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
101 #define RDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDX])
102 #define RSI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RSI])
103 #define RDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDI])
104 #define RBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBP])
105 #define R8_sig(context) ((context)->uc_mcontext.__gregs[_REG_R8])
106 #define R9_sig(context) ((context)->uc_mcontext.__gregs[_REG_R9])
107 #define R10_sig(context) ((context)->uc_mcontext.__gregs[_REG_R10])
108 #define R11_sig(context) ((context)->uc_mcontext.__gregs[_REG_R11])
109 #define R12_sig(context) ((context)->uc_mcontext.__gregs[_REG_R12])
110 #define R13_sig(context) ((context)->uc_mcontext.__gregs[_REG_R13])
111 #define R14_sig(context) ((context)->uc_mcontext.__gregs[_REG_R14])
112 #define R15_sig(context) ((context)->uc_mcontext.__gregs[_REG_R15])
114 #define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
115 #define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
116 #define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
117 #define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
118 #define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
119 #define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
121 #define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_RFL])
123 #define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_RIP]))
124 #define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_URSP]))
126 #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
127 #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
129 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
130 #endif /* __NetBSD__ */
134 TRAP_x86_UNKNOWN
= -1, /* Unknown fault (TRAP_sig not defined) */
135 TRAP_x86_DIVIDE
= 0, /* Division by zero exception */
136 TRAP_x86_TRCTRAP
= 1, /* Single-step exception */
137 TRAP_x86_NMI
= 2, /* NMI interrupt */
138 TRAP_x86_BPTFLT
= 3, /* Breakpoint exception */
139 TRAP_x86_OFLOW
= 4, /* Overflow exception */
140 TRAP_x86_BOUND
= 5, /* Bound range exception */
141 TRAP_x86_PRIVINFLT
= 6, /* Invalid opcode exception */
142 TRAP_x86_DNA
= 7, /* Device not available exception */
143 TRAP_x86_DOUBLEFLT
= 8, /* Double fault exception */
144 TRAP_x86_FPOPFLT
= 9, /* Coprocessor segment overrun */
145 TRAP_x86_TSSFLT
= 10, /* Invalid TSS exception */
146 TRAP_x86_SEGNPFLT
= 11, /* Segment not present exception */
147 TRAP_x86_STKFLT
= 12, /* Stack fault */
148 TRAP_x86_PROTFLT
= 13, /* General protection fault */
149 TRAP_x86_PAGEFLT
= 14, /* Page fault */
150 TRAP_x86_ARITHTRAP
= 16, /* Floating point exception */
151 TRAP_x86_ALIGNFLT
= 17, /* Alignment check exception */
152 TRAP_x86_MCHK
= 18, /* Machine check exception */
153 TRAP_x86_CACHEFLT
= 19 /* Cache flush exception */
156 typedef int (*wine_signal_handler
)(unsigned int sig
);
158 static wine_signal_handler handlers
[256];
160 /***********************************************************************
163 static inline int dispatch_signal(unsigned int sig
)
165 if (handlers
[sig
] == NULL
) return 0;
166 return handlers
[sig
](sig
);
169 /***********************************************************************
172 * Set the register values from a sigcontext.
174 static void save_context( CONTEXT
*context
, const ucontext_t
*sigcontext
)
176 context
->ContextFlags
= CONTEXT_CONTROL
| CONTEXT_INTEGER
| CONTEXT_SEGMENTS
;
177 context
->Rax
= RAX_sig(sigcontext
);
178 context
->Rcx
= RCX_sig(sigcontext
);
179 context
->Rdx
= RDX_sig(sigcontext
);
180 context
->Rbx
= RBX_sig(sigcontext
);
181 context
->Rsp
= RSP_sig(sigcontext
);
182 context
->Rbp
= RBP_sig(sigcontext
);
183 context
->Rsi
= RSI_sig(sigcontext
);
184 context
->Rdi
= RDI_sig(sigcontext
);
185 context
->R8
= R8_sig(sigcontext
);
186 context
->R9
= R9_sig(sigcontext
);
187 context
->R10
= R10_sig(sigcontext
);
188 context
->R11
= R11_sig(sigcontext
);
189 context
->R12
= R12_sig(sigcontext
);
190 context
->R13
= R13_sig(sigcontext
);
191 context
->R14
= R14_sig(sigcontext
);
192 context
->R15
= R15_sig(sigcontext
);
193 context
->Rip
= RIP_sig(sigcontext
);
194 context
->SegCs
= CS_sig(sigcontext
);
195 context
->SegFs
= FS_sig(sigcontext
);
196 context
->SegGs
= GS_sig(sigcontext
);
197 context
->EFlags
= EFL_sig(sigcontext
);
199 context
->SegDs
= DS_sig(sigcontext
);
201 __asm__("movw %%ds,%0" : "=m" (context
->SegDs
));
204 context
->SegEs
= ES_sig(sigcontext
);
206 __asm__("movw %%es,%0" : "=m" (context
->SegEs
));
209 context
->SegSs
= SS_sig(sigcontext
);
211 __asm__("movw %%ss,%0" : "=m" (context
->SegSs
));
213 context
->MxCsr
= 0; /* FIXME */
214 if (FPU_sig(sigcontext
))
216 context
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
217 context
->u
.FltSave
= *FPU_sig(sigcontext
);
222 /***********************************************************************
225 * Build a sigcontext from the register values.
227 static void restore_context( const CONTEXT
*context
, ucontext_t
*sigcontext
)
229 RAX_sig(sigcontext
) = context
->Rax
;
230 RCX_sig(sigcontext
) = context
->Rcx
;
231 RDX_sig(sigcontext
) = context
->Rdx
;
232 RBX_sig(sigcontext
) = context
->Rbx
;
233 RSP_sig(sigcontext
) = context
->Rsp
;
234 RBP_sig(sigcontext
) = context
->Rbp
;
235 RSI_sig(sigcontext
) = context
->Rsi
;
236 RDI_sig(sigcontext
) = context
->Rdi
;
237 R8_sig(sigcontext
) = context
->R8
;
238 R9_sig(sigcontext
) = context
->R9
;
239 R10_sig(sigcontext
) = context
->R10
;
240 R11_sig(sigcontext
) = context
->R11
;
241 R12_sig(sigcontext
) = context
->R12
;
242 R13_sig(sigcontext
) = context
->R13
;
243 R14_sig(sigcontext
) = context
->R14
;
244 R15_sig(sigcontext
) = context
->R15
;
245 RIP_sig(sigcontext
) = context
->Rip
;
246 CS_sig(sigcontext
) = context
->SegCs
;
247 FS_sig(sigcontext
) = context
->SegFs
;
248 GS_sig(sigcontext
) = context
->SegGs
;
249 EFL_sig(sigcontext
) = context
->EFlags
;
251 DS_sig(sigcontext
) = context
->SegDs
;
254 ES_sig(sigcontext
) = context
->SegEs
;
257 SS_sig(sigcontext
) = context
->SegSs
;
259 if (FPU_sig(sigcontext
)) *FPU_sig(sigcontext
) = context
->u
.FltSave
;
263 /***********************************************************************
264 * RtlCaptureContext (NTDLL.@)
266 void WINAPI
__regs_RtlCaptureContext( CONTEXT
*context
, CONTEXT
*regs
)
270 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext
, 1 )
273 /***********************************************************************
276 * Set the new CPU context.
278 void set_cpu_context( const CONTEXT
*context
)
280 extern void CDECL
__wine_restore_regs( const CONTEXT
* ) DECLSPEC_NORETURN
;
281 __wine_restore_regs( context
);
285 /***********************************************************************
288 * Copy a register context according to the flags.
290 void copy_context( CONTEXT
*to
, const CONTEXT
*from
, DWORD flags
)
292 flags
&= ~CONTEXT_AMD64
; /* get rid of CPU id */
293 if (flags
& CONTEXT_CONTROL
)
298 to
->SegCs
= from
->SegCs
;
299 to
->SegSs
= from
->SegSs
;
300 to
->EFlags
= from
->EFlags
;
301 to
->MxCsr
= from
->MxCsr
;
303 if (flags
& CONTEXT_INTEGER
)
320 if (flags
& CONTEXT_SEGMENTS
)
322 to
->SegDs
= from
->SegDs
;
323 to
->SegEs
= from
->SegEs
;
324 to
->SegFs
= from
->SegFs
;
325 to
->SegGs
= from
->SegGs
;
327 if (flags
& CONTEXT_FLOATING_POINT
)
329 to
->u
.FltSave
= from
->u
.FltSave
;
331 if (flags
& CONTEXT_DEBUG_REGISTERS
)
343 /***********************************************************************
346 * Convert a register context to the server format.
348 NTSTATUS
context_to_server( context_t
*to
, const CONTEXT
*from
)
350 DWORD flags
= from
->ContextFlags
& ~CONTEXT_AMD64
; /* get rid of CPU id */
352 memset( to
, 0, sizeof(*to
) );
353 to
->cpu
= CPU_x86_64
;
355 if (flags
& CONTEXT_CONTROL
)
357 to
->flags
|= SERVER_CTX_CONTROL
;
358 to
->ctl
.x86_64_regs
.rbp
= from
->Rbp
;
359 to
->ctl
.x86_64_regs
.rip
= from
->Rip
;
360 to
->ctl
.x86_64_regs
.rsp
= from
->Rsp
;
361 to
->ctl
.x86_64_regs
.cs
= from
->SegCs
;
362 to
->ctl
.x86_64_regs
.ss
= from
->SegSs
;
363 to
->ctl
.x86_64_regs
.flags
= from
->EFlags
;
364 to
->ctl
.x86_64_regs
.mxcsr
= from
->MxCsr
;
366 if (flags
& CONTEXT_INTEGER
)
368 to
->flags
|= SERVER_CTX_INTEGER
;
369 to
->integer
.x86_64_regs
.rax
= from
->Rax
;
370 to
->integer
.x86_64_regs
.rcx
= from
->Rcx
;
371 to
->integer
.x86_64_regs
.rdx
= from
->Rdx
;
372 to
->integer
.x86_64_regs
.rbx
= from
->Rbx
;
373 to
->integer
.x86_64_regs
.rsi
= from
->Rsi
;
374 to
->integer
.x86_64_regs
.rdi
= from
->Rdi
;
375 to
->integer
.x86_64_regs
.r8
= from
->R8
;
376 to
->integer
.x86_64_regs
.r9
= from
->R9
;
377 to
->integer
.x86_64_regs
.r10
= from
->R10
;
378 to
->integer
.x86_64_regs
.r11
= from
->R11
;
379 to
->integer
.x86_64_regs
.r12
= from
->R12
;
380 to
->integer
.x86_64_regs
.r13
= from
->R13
;
381 to
->integer
.x86_64_regs
.r14
= from
->R14
;
382 to
->integer
.x86_64_regs
.r15
= from
->R15
;
384 if (flags
& CONTEXT_SEGMENTS
)
386 to
->flags
|= SERVER_CTX_SEGMENTS
;
387 to
->seg
.x86_64_regs
.ds
= from
->SegDs
;
388 to
->seg
.x86_64_regs
.es
= from
->SegEs
;
389 to
->seg
.x86_64_regs
.fs
= from
->SegFs
;
390 to
->seg
.x86_64_regs
.gs
= from
->SegGs
;
392 if (flags
& CONTEXT_FLOATING_POINT
)
394 to
->flags
|= SERVER_CTX_FLOATING_POINT
;
395 memcpy( to
->fp
.x86_64_regs
.fpregs
, &from
->u
.FltSave
, sizeof(to
->fp
.x86_64_regs
.fpregs
) );
397 if (flags
& CONTEXT_DEBUG_REGISTERS
)
399 to
->flags
|= SERVER_CTX_DEBUG_REGISTERS
;
400 to
->debug
.x86_64_regs
.dr0
= from
->Dr0
;
401 to
->debug
.x86_64_regs
.dr1
= from
->Dr1
;
402 to
->debug
.x86_64_regs
.dr2
= from
->Dr2
;
403 to
->debug
.x86_64_regs
.dr3
= from
->Dr3
;
404 to
->debug
.x86_64_regs
.dr6
= from
->Dr6
;
405 to
->debug
.x86_64_regs
.dr7
= from
->Dr7
;
407 return STATUS_SUCCESS
;
411 /***********************************************************************
412 * context_from_server
414 * Convert a register context from the server format.
416 NTSTATUS
context_from_server( CONTEXT
*to
, const context_t
*from
)
418 if (from
->cpu
!= CPU_x86_64
) return STATUS_INVALID_PARAMETER
;
420 to
->ContextFlags
= CONTEXT_AMD64
;
421 if (from
->flags
& SERVER_CTX_CONTROL
)
423 to
->ContextFlags
|= CONTEXT_CONTROL
;
424 to
->Rbp
= from
->ctl
.x86_64_regs
.rbp
;
425 to
->Rip
= from
->ctl
.x86_64_regs
.rip
;
426 to
->Rsp
= from
->ctl
.x86_64_regs
.rsp
;
427 to
->SegCs
= from
->ctl
.x86_64_regs
.cs
;
428 to
->SegSs
= from
->ctl
.x86_64_regs
.ss
;
429 to
->EFlags
= from
->ctl
.x86_64_regs
.flags
;
430 to
->MxCsr
= from
->ctl
.x86_64_regs
.mxcsr
;
433 if (from
->flags
& SERVER_CTX_INTEGER
)
435 to
->ContextFlags
|= CONTEXT_INTEGER
;
436 to
->Rax
= from
->integer
.x86_64_regs
.rax
;
437 to
->Rcx
= from
->integer
.x86_64_regs
.rcx
;
438 to
->Rdx
= from
->integer
.x86_64_regs
.rdx
;
439 to
->Rbx
= from
->integer
.x86_64_regs
.rbx
;
440 to
->Rsi
= from
->integer
.x86_64_regs
.rsi
;
441 to
->Rdi
= from
->integer
.x86_64_regs
.rdi
;
442 to
->R8
= from
->integer
.x86_64_regs
.r8
;
443 to
->R9
= from
->integer
.x86_64_regs
.r9
;
444 to
->R10
= from
->integer
.x86_64_regs
.r10
;
445 to
->R11
= from
->integer
.x86_64_regs
.r11
;
446 to
->R12
= from
->integer
.x86_64_regs
.r12
;
447 to
->R13
= from
->integer
.x86_64_regs
.r13
;
448 to
->R14
= from
->integer
.x86_64_regs
.r14
;
449 to
->R15
= from
->integer
.x86_64_regs
.r15
;
451 if (from
->flags
& SERVER_CTX_SEGMENTS
)
453 to
->ContextFlags
|= CONTEXT_SEGMENTS
;
454 to
->SegDs
= from
->seg
.x86_64_regs
.ds
;
455 to
->SegEs
= from
->seg
.x86_64_regs
.es
;
456 to
->SegFs
= from
->seg
.x86_64_regs
.fs
;
457 to
->SegGs
= from
->seg
.x86_64_regs
.gs
;
459 if (from
->flags
& SERVER_CTX_FLOATING_POINT
)
461 to
->ContextFlags
|= CONTEXT_FLOATING_POINT
;
462 memcpy( &to
->u
.FltSave
, from
->fp
.x86_64_regs
.fpregs
, sizeof(from
->fp
.x86_64_regs
.fpregs
) );
464 if (from
->flags
& SERVER_CTX_DEBUG_REGISTERS
)
466 to
->ContextFlags
|= CONTEXT_DEBUG_REGISTERS
;
467 to
->Dr0
= from
->debug
.x86_64_regs
.dr0
;
468 to
->Dr1
= from
->debug
.x86_64_regs
.dr1
;
469 to
->Dr2
= from
->debug
.x86_64_regs
.dr2
;
470 to
->Dr3
= from
->debug
.x86_64_regs
.dr3
;
471 to
->Dr6
= from
->debug
.x86_64_regs
.dr6
;
472 to
->Dr7
= from
->debug
.x86_64_regs
.dr7
;
474 return STATUS_SUCCESS
;
478 /**********************************************************************
479 * call_stack_handlers
481 * Call the stack handlers chain.
483 static NTSTATUS
call_stack_handlers( EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
485 EXCEPTION_POINTERS ptrs
;
487 FIXME( "not implemented on x86_64\n" );
489 /* hack: call unhandled exception filter directly */
490 ptrs
.ExceptionRecord
= rec
;
491 ptrs
.ContextRecord
= context
;
492 unhandled_exception_filter( &ptrs
);
493 return STATUS_UNHANDLED_EXCEPTION
;
497 /*******************************************************************
500 * Implementation of NtRaiseException.
502 static NTSTATUS
raise_exception( EXCEPTION_RECORD
*rec
, CONTEXT
*context
, BOOL first_chance
)
510 TRACE( "code=%x flags=%x addr=%p ip=%lx tid=%04x\n",
511 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
,
512 context
->Rip
, GetCurrentThreadId() );
513 for (c
= 0; c
< rec
->NumberParameters
; c
++)
514 TRACE( " info[%d]=%08lx\n", c
, rec
->ExceptionInformation
[c
] );
515 if (rec
->ExceptionCode
== EXCEPTION_WINE_STUB
)
517 if (rec
->ExceptionInformation
[1] >> 16)
518 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
519 rec
->ExceptionAddress
,
520 (char*)rec
->ExceptionInformation
[0], (char*)rec
->ExceptionInformation
[1] );
522 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
523 rec
->ExceptionAddress
,
524 (char*)rec
->ExceptionInformation
[0], rec
->ExceptionInformation
[1] );
528 TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
529 context
->Rax
, context
->Rbx
, context
->Rcx
, context
->Rdx
);
530 TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
531 context
->Rsi
, context
->Rdi
, context
->Rbp
, context
->Rsp
);
532 TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
533 context
->R8
, context
->R9
, context
->R10
, context
->R11
);
534 TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
535 context
->R12
, context
->R13
, context
->R14
, context
->R15
);
537 status
= send_debug_event( rec
, TRUE
, context
);
538 if (status
== DBG_CONTINUE
|| status
== DBG_EXCEPTION_HANDLED
)
539 return STATUS_SUCCESS
;
541 if (call_vectored_handlers( rec
, context
) == EXCEPTION_CONTINUE_EXECUTION
)
542 return STATUS_SUCCESS
;
544 if ((status
= call_stack_handlers( rec
, context
)) != STATUS_UNHANDLED_EXCEPTION
)
548 /* last chance exception */
550 status
= send_debug_event( rec
, FALSE
, context
);
551 if (status
!= DBG_CONTINUE
)
553 if (rec
->ExceptionFlags
& EH_STACK_INVALID
)
554 ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
555 else if (rec
->ExceptionCode
== STATUS_NONCONTINUABLE_EXCEPTION
)
556 ERR("Process attempted to continue execution after noncontinuable exception.\n");
558 ERR("Unhandled exception code %x flags %x addr %p\n",
559 rec
->ExceptionCode
, rec
->ExceptionFlags
, rec
->ExceptionAddress
);
560 NtTerminateProcess( NtCurrentProcess(), rec
->ExceptionCode
);
562 return STATUS_SUCCESS
;
566 /**********************************************************************
569 * Handler for SIGSEGV and related errors.
571 static void segv_handler( int signal
, siginfo_t
*siginfo
, void *sigcontext
)
573 EXCEPTION_RECORD rec
;
576 ucontext_t
*ucontext
= sigcontext
;
578 save_context( &context
, ucontext
);
580 rec
.ExceptionRecord
= NULL
;
581 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
582 rec
.ExceptionAddress
= (LPVOID
)context
.Rip
;
583 rec
.NumberParameters
= 0;
585 switch(TRAP_sig(ucontext
))
587 case TRAP_x86_OFLOW
: /* Overflow exception */
588 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
590 case TRAP_x86_BOUND
: /* Bound range exception */
591 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
593 case TRAP_x86_PRIVINFLT
: /* Invalid opcode exception */
594 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
596 case TRAP_x86_STKFLT
: /* Stack fault */
597 rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
599 case TRAP_x86_SEGNPFLT
: /* Segment not present exception */
600 case TRAP_x86_PROTFLT
: /* General protection fault */
601 case TRAP_x86_UNKNOWN
: /* Unknown fault code */
602 rec
.ExceptionCode
= ERROR_sig(ucontext
) ? EXCEPTION_ACCESS_VIOLATION
603 : EXCEPTION_PRIV_INSTRUCTION
;
605 case TRAP_x86_PAGEFLT
: /* Page fault */
606 rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
607 rec
.NumberParameters
= 2;
608 rec
.ExceptionInformation
[0] = (ERROR_sig(ucontext
) & 2) != 0;
609 rec
.ExceptionInformation
[1] = (ULONG_PTR
)siginfo
->si_addr
;
610 if (!(rec
.ExceptionCode
= virtual_handle_fault( siginfo
->si_addr
, rec
.ExceptionInformation
[0] )))
613 case TRAP_x86_ALIGNFLT
: /* Alignment check exception */
614 rec
.ExceptionCode
= EXCEPTION_DATATYPE_MISALIGNMENT
;
617 ERR( "Got unexpected trap %ld\n", TRAP_sig(ucontext
) );
619 case TRAP_x86_NMI
: /* NMI interrupt */
620 case TRAP_x86_DNA
: /* Device not available exception */
621 case TRAP_x86_DOUBLEFLT
: /* Double fault exception */
622 case TRAP_x86_TSSFLT
: /* Invalid TSS exception */
623 case TRAP_x86_MCHK
: /* Machine check exception */
624 case TRAP_x86_CACHEFLT
: /* Cache flush exception */
625 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
629 status
= raise_exception( &rec
, &context
, TRUE
);
630 if (status
) raise_status( status
, &rec
);
632 restore_context( &context
, ucontext
);
635 /**********************************************************************
638 * Handler for SIGTRAP.
640 static void trap_handler( int signal
, siginfo_t
*siginfo
, void *sigcontext
)
642 EXCEPTION_RECORD rec
;
645 ucontext_t
*ucontext
= sigcontext
;
647 save_context( &context
, ucontext
);
648 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
649 rec
.ExceptionRecord
= NULL
;
650 rec
.ExceptionAddress
= (LPVOID
)context
.Rip
;
651 rec
.NumberParameters
= 0;
653 switch (siginfo
->si_code
)
655 case TRAP_TRACE
: /* Single-step exception */
656 rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
657 EFL_sig(ucontext
) &= ~0x100; /* clear single-step flag */
659 case TRAP_BRKPT
: /* Breakpoint exception */
660 rec
.ExceptionAddress
= (char *)rec
.ExceptionAddress
- 1; /* back up over the int3 instruction */
663 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
667 status
= raise_exception( &rec
, &context
, TRUE
);
668 if (status
) raise_status( status
, &rec
);
669 restore_context( &context
, ucontext
);
672 /**********************************************************************
675 * Handler for SIGFPE.
677 static void fpe_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
679 EXCEPTION_RECORD rec
;
683 save_context( &context
, ucontext
);
684 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
685 rec
.ExceptionRecord
= NULL
;
686 rec
.ExceptionAddress
= (LPVOID
)context
.Rip
;
687 rec
.NumberParameters
= 0;
689 switch (siginfo
->si_code
)
692 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
695 rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
698 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
701 rec
.ExceptionCode
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
704 rec
.ExceptionCode
= EXCEPTION_FLT_OVERFLOW
;
707 rec
.ExceptionCode
= EXCEPTION_FLT_UNDERFLOW
;
710 rec
.ExceptionCode
= EXCEPTION_FLT_INEXACT_RESULT
;
714 rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
718 status
= raise_exception( &rec
, &context
, TRUE
);
719 if (status
) raise_status( status
, &rec
);
720 restore_context( &context
, ucontext
);
723 /**********************************************************************
726 * Handler for SIGINT.
728 static void int_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
730 if (!dispatch_signal(SIGINT
))
732 EXCEPTION_RECORD rec
;
736 save_context( &context
, ucontext
);
737 rec
.ExceptionCode
= CONTROL_C_EXIT
;
738 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
739 rec
.ExceptionRecord
= NULL
;
740 rec
.ExceptionAddress
= (LPVOID
)context
.Rip
;
741 rec
.NumberParameters
= 0;
742 status
= raise_exception( &rec
, &context
, TRUE
);
743 if (status
) raise_status( status
, &rec
);
744 restore_context( &context
, ucontext
);
749 /**********************************************************************
752 * Handler for SIGABRT.
754 static void abrt_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
756 EXCEPTION_RECORD rec
;
760 save_context( &context
, ucontext
);
761 rec
.ExceptionCode
= EXCEPTION_WINE_ASSERTION
;
762 rec
.ExceptionFlags
= EH_NONCONTINUABLE
;
763 rec
.ExceptionRecord
= NULL
;
764 rec
.ExceptionAddress
= (LPVOID
)context
.Rip
;
765 rec
.NumberParameters
= 0;
766 status
= raise_exception( &rec
, &context
, TRUE
);
767 if (status
) raise_status( status
, &rec
);
768 restore_context( &context
, ucontext
);
772 /**********************************************************************
775 * Handler for SIGQUIT.
777 static void quit_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
783 /**********************************************************************
786 * Handler for SIGUSR1, used to signal a thread that it got suspended.
788 static void usr1_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
792 save_context( &context
, ucontext
);
793 wait_suspend( &context
);
794 restore_context( &context
, ucontext
);
798 /**********************************************************************
799 * get_signal_stack_total_size
801 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
802 * Must be a power of two.
804 size_t get_signal_stack_total_size(void)
806 assert( sizeof(TEB
) <= 2*getpagesize() );
807 return 2*getpagesize(); /* this is just for the TEB, we don't need a signal stack */
811 /***********************************************************************
812 * __wine_set_signal_handler (NTDLL.@)
814 int CDECL
__wine_set_signal_handler(unsigned int sig
, wine_signal_handler wsh
)
816 if (sig
> sizeof(handlers
) / sizeof(handlers
[0])) return -1;
817 if (handlers
[sig
] != NULL
) return -2;
823 /**********************************************************************
826 void signal_init_thread( TEB
*teb
)
829 arch_prctl( ARCH_SET_GS
, teb
);
831 # error Please define setting %gs for your architecture
835 /**********************************************************************
836 * signal_init_process
838 void signal_init_process(void)
840 struct sigaction sig_act
;
842 sig_act
.sa_mask
= server_block_set
;
843 sig_act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
845 sig_act
.sa_sigaction
= int_handler
;
846 if (sigaction( SIGINT
, &sig_act
, NULL
) == -1) goto error
;
847 sig_act
.sa_sigaction
= fpe_handler
;
848 if (sigaction( SIGFPE
, &sig_act
, NULL
) == -1) goto error
;
849 sig_act
.sa_sigaction
= abrt_handler
;
850 if (sigaction( SIGABRT
, &sig_act
, NULL
) == -1) goto error
;
851 sig_act
.sa_sigaction
= quit_handler
;
852 if (sigaction( SIGQUIT
, &sig_act
, NULL
) == -1) goto error
;
853 sig_act
.sa_sigaction
= usr1_handler
;
854 if (sigaction( SIGUSR1
, &sig_act
, NULL
) == -1) goto error
;
856 sig_act
.sa_sigaction
= segv_handler
;
857 if (sigaction( SIGSEGV
, &sig_act
, NULL
) == -1) goto error
;
858 if (sigaction( SIGILL
, &sig_act
, NULL
) == -1) goto error
;
860 if (sigaction( SIGBUS
, &sig_act
, NULL
) == -1) goto error
;
864 sig_act
.sa_sigaction
= trap_handler
;
865 if (sigaction( SIGTRAP
, &sig_act
, NULL
) == -1) goto error
;
875 /**********************************************************************
876 * RtlLookupFunctionEntry (NTDLL.@)
878 PRUNTIME_FUNCTION WINAPI
RtlLookupFunctionEntry( ULONG64 pc
, ULONG64
*base
,
879 UNWIND_HISTORY_TABLE
*table
)
886 /**********************************************************************
887 * RtlVirtualUnwind (NTDLL.@)
889 PVOID WINAPI
RtlVirtualUnwind ( ULONG type
, ULONG64 base
, ULONG64 pc
,
890 RUNTIME_FUNCTION
*function
, CONTEXT
*context
,
891 PVOID
*data
, ULONG64
*frame
,
892 KNONVOLATILE_CONTEXT_POINTERS
*ctx_ptr
)
899 /*******************************************************************
900 * RtlUnwindEx (NTDLL.@)
902 void WINAPI
RtlUnwindEx( ULONG64 frame
, ULONG64 target_ip
, EXCEPTION_RECORD
*rec
,
903 ULONG64 retval
, CONTEXT
*context
, UNWIND_HISTORY_TABLE
*table
)
905 EXCEPTION_RECORD record
;
907 /* build an exception record, if we do not have one */
910 record
.ExceptionCode
= STATUS_UNWIND
;
911 record
.ExceptionFlags
= 0;
912 record
.ExceptionRecord
= NULL
;
913 record
.ExceptionAddress
= (void *)context
->Rip
;
914 record
.NumberParameters
= 0;
918 rec
->ExceptionFlags
|= EH_UNWINDING
| (frame
? 0 : EH_EXIT_UNWIND
);
920 FIXME( "code=%x flags=%x not implemented on x86_64\n", rec
->ExceptionCode
, rec
->ExceptionFlags
);
921 NtTerminateProcess( GetCurrentProcess(), 1 );
925 /*******************************************************************
926 * RtlUnwind (NTDLL.@)
928 void WINAPI
__regs_RtlUnwind( ULONG64 frame
, ULONG64 target_ip
, EXCEPTION_RECORD
*rec
,
929 ULONG64 retval
, CONTEXT
*context
)
931 RtlUnwindEx( frame
, target_ip
, rec
, retval
, context
, NULL
);
933 DEFINE_REGS_ENTRYPOINT( RtlUnwind
, 4 )
936 /*******************************************************************
937 * NtRaiseException (NTDLL.@)
939 NTSTATUS WINAPI
NtRaiseException( EXCEPTION_RECORD
*rec
, CONTEXT
*context
, BOOL first_chance
)
941 NTSTATUS status
= raise_exception( rec
, context
, first_chance
);
942 if (status
== STATUS_SUCCESS
) NtSetContextThread( GetCurrentThread(), context
);
947 /***********************************************************************
948 * RtlRaiseException (NTDLL.@)
950 void WINAPI
__regs_RtlRaiseException( EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
954 rec
->ExceptionAddress
= (void *)context
->Rip
;
955 status
= raise_exception( rec
, context
, TRUE
);
956 if (status
!= STATUS_SUCCESS
) raise_status( status
, rec
);
958 DEFINE_REGS_ENTRYPOINT( RtlRaiseException
, 1 )
961 /**********************************************************************
962 * __wine_enter_vm86 (NTDLL.@)
964 void __wine_enter_vm86( CONTEXT
*context
)
966 MESSAGE("vm86 mode not supported on this platform\n");
969 /**********************************************************************
970 * DbgBreakPoint (NTDLL.@)
972 __ASM_GLOBAL_FUNC( DbgBreakPoint
, "int $3; ret")
974 /**********************************************************************
975 * DbgUserBreakPoint (NTDLL.@)
977 __ASM_GLOBAL_FUNC( DbgUserBreakPoint
, "int $3; ret")
979 #endif /* __x86_64__ */