ntdll: Added a stub for RtlUnwindEx on x86_64.
[wine/multimedia.git] / dlls / ntdll / signal_x86_64.c
blobdd8dad9423ab0b4ed9547912dabb0ffc183338e5
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "ntstatus.h"
44 #define WIN32_NO_STATUS
45 #include "windef.h"
46 #include "winternl.h"
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
58 #ifdef linux
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))
91 #endif /* linux */
93 #if defined(__NetBSD__)
94 # include <sys/ucontext.h>
95 # include <sys/types.h>
96 # include <signal.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__ */
132 enum i386_trap_code
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 /***********************************************************************
161 * dispatch_signal
163 static inline int dispatch_signal(unsigned int sig)
165 if (handlers[sig] == NULL) return 0;
166 return handlers[sig](sig);
169 /***********************************************************************
170 * save_context
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);
198 #ifdef DS_sig
199 context->SegDs = DS_sig(sigcontext);
200 #else
201 __asm__("movw %%ds,%0" : "=m" (context->SegDs));
202 #endif
203 #ifdef ES_sig
204 context->SegEs = ES_sig(sigcontext);
205 #else
206 __asm__("movw %%es,%0" : "=m" (context->SegEs));
207 #endif
208 #ifdef SS_sig
209 context->SegSs = SS_sig(sigcontext);
210 #else
211 __asm__("movw %%ss,%0" : "=m" (context->SegSs));
212 #endif
213 context->MxCsr = 0; /* FIXME */
214 if (FPU_sig(sigcontext))
216 context->ContextFlags |= CONTEXT_FLOATING_POINT;
217 context->u.FltSave = *FPU_sig(sigcontext);
222 /***********************************************************************
223 * restore_context
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;
250 #ifdef DS_sig
251 DS_sig(sigcontext) = context->SegDs;
252 #endif
253 #ifdef ES_sig
254 ES_sig(sigcontext) = context->SegEs;
255 #endif
256 #ifdef SS_sig
257 SS_sig(sigcontext) = context->SegSs;
258 #endif
259 if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
263 /***********************************************************************
264 * RtlCaptureContext (NTDLL.@)
266 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
268 *context = *regs;
270 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
273 /***********************************************************************
274 * set_cpu_context
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 /***********************************************************************
286 * copy_context
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)
295 to->Rbp = from->Rbp;
296 to->Rip = from->Rip;
297 to->Rsp = from->Rsp;
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)
305 to->Rax = from->Rax;
306 to->Rcx = from->Rcx;
307 to->Rdx = from->Rdx;
308 to->Rbx = from->Rbx;
309 to->Rsi = from->Rsi;
310 to->Rdi = from->Rdi;
311 to->R8 = from->R8;
312 to->R9 = from->R9;
313 to->R10 = from->R10;
314 to->R11 = from->R11;
315 to->R12 = from->R12;
316 to->R13 = from->R13;
317 to->R14 = from->R14;
318 to->R15 = from->R15;
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)
333 to->Dr0 = from->Dr0;
334 to->Dr1 = from->Dr1;
335 to->Dr2 = from->Dr2;
336 to->Dr3 = from->Dr3;
337 to->Dr6 = from->Dr6;
338 to->Dr7 = from->Dr7;
343 /***********************************************************************
344 * context_to_server
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 /*******************************************************************
498 * raise_exception
500 * Implementation of NtRaiseException.
502 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
504 NTSTATUS status;
506 if (first_chance)
508 DWORD c;
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] );
521 else
522 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
523 rec->ExceptionAddress,
524 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
526 else
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)
545 return status;
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");
557 else
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 /**********************************************************************
567 * segv_handler
569 * Handler for SIGSEGV and related errors.
571 static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
573 EXCEPTION_RECORD rec;
574 CONTEXT context;
575 NTSTATUS status;
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;
589 break;
590 case TRAP_x86_BOUND: /* Bound range exception */
591 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
592 break;
593 case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */
594 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
595 break;
596 case TRAP_x86_STKFLT: /* Stack fault */
597 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
598 break;
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;
604 break;
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] )))
611 goto done;
612 break;
613 case TRAP_x86_ALIGNFLT: /* Alignment check exception */
614 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
615 break;
616 default:
617 ERR( "Got unexpected trap %ld\n", TRAP_sig(ucontext) );
618 /* fall through */
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;
626 break;
629 status = raise_exception( &rec, &context, TRUE );
630 if (status) raise_status( status, &rec );
631 done:
632 restore_context( &context, ucontext );
635 /**********************************************************************
636 * trap_handler
638 * Handler for SIGTRAP.
640 static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
642 EXCEPTION_RECORD rec;
643 CONTEXT context;
644 NTSTATUS status;
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 */
658 break;
659 case TRAP_BRKPT: /* Breakpoint exception */
660 rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */
661 /* fall through */
662 default:
663 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
664 break;
667 status = raise_exception( &rec, &context, TRUE );
668 if (status) raise_status( status, &rec );
669 restore_context( &context, ucontext );
672 /**********************************************************************
673 * fpe_handler
675 * Handler for SIGFPE.
677 static void fpe_handler( int signal, siginfo_t *siginfo, void *ucontext )
679 EXCEPTION_RECORD rec;
680 CONTEXT context;
681 NTSTATUS status;
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)
691 case FPE_FLTSUB:
692 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
693 break;
694 case FPE_INTDIV:
695 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
696 break;
697 case FPE_INTOVF:
698 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
699 break;
700 case FPE_FLTDIV:
701 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
702 break;
703 case FPE_FLTOVF:
704 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
705 break;
706 case FPE_FLTUND:
707 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
708 break;
709 case FPE_FLTRES:
710 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
711 break;
712 case FPE_FLTINV:
713 default:
714 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
715 break;
718 status = raise_exception( &rec, &context, TRUE );
719 if (status) raise_status( status, &rec );
720 restore_context( &context, ucontext );
723 /**********************************************************************
724 * int_handler
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;
733 CONTEXT context;
734 NTSTATUS status;
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 /**********************************************************************
750 * abrt_handler
752 * Handler for SIGABRT.
754 static void abrt_handler( int signal, siginfo_t *siginfo, void *ucontext )
756 EXCEPTION_RECORD rec;
757 CONTEXT context;
758 NTSTATUS status;
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 /**********************************************************************
773 * quit_handler
775 * Handler for SIGQUIT.
777 static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext )
779 abort_thread(0);
783 /**********************************************************************
784 * usr1_handler
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 )
790 CONTEXT context;
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;
818 handlers[sig] = wsh;
819 return 0;
823 /**********************************************************************
824 * signal_init_thread
826 void signal_init_thread( TEB *teb )
828 #ifdef __linux__
829 arch_prctl( ARCH_SET_GS, teb );
830 #else
831 # error Please define setting %gs for your architecture
832 #endif
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;
859 #ifdef SIGBUS
860 if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
861 #endif
863 #ifdef SIGTRAP
864 sig_act.sa_sigaction = trap_handler;
865 if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
866 #endif
867 return;
869 error:
870 perror("sigaction");
871 exit(1);
875 /**********************************************************************
876 * RtlLookupFunctionEntry (NTDLL.@)
878 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
879 UNWIND_HISTORY_TABLE *table )
881 FIXME("stub\n");
882 return NULL;
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 )
894 FIXME("stub\n");
895 return NULL;
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 */
908 if (!rec)
910 record.ExceptionCode = STATUS_UNWIND;
911 record.ExceptionFlags = 0;
912 record.ExceptionRecord = NULL;
913 record.ExceptionAddress = (void *)context->Rip;
914 record.NumberParameters = 0;
915 rec = &record;
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 );
943 return status;
947 /***********************************************************************
948 * RtlRaiseException (NTDLL.@)
950 void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
952 NTSTATUS status;
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__ */