push 22b3e00525a9a3743634eb8f21ffe1bf98bf885e
[wine/hacks.git] / dlls / ntdll / signal_x86_64.c
blobe0b39d5fc39e07554abfdcd62ac277dfda4f5cd1
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 typedef struct ucontext SIGCONTEXT;
65 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
66 # define HANDLER_CONTEXT (__context)
68 #define RAX_sig(context) ((context)->uc_mcontext.gregs[REG_RAX])
69 #define RBX_sig(context) ((context)->uc_mcontext.gregs[REG_RBX])
70 #define RCX_sig(context) ((context)->uc_mcontext.gregs[REG_RCX])
71 #define RDX_sig(context) ((context)->uc_mcontext.gregs[REG_RDX])
72 #define RSI_sig(context) ((context)->uc_mcontext.gregs[REG_RSI])
73 #define RDI_sig(context) ((context)->uc_mcontext.gregs[REG_RDI])
74 #define RBP_sig(context) ((context)->uc_mcontext.gregs[REG_RBP])
75 #define R8_sig(context) ((context)->uc_mcontext.gregs[REG_R8])
76 #define R9_sig(context) ((context)->uc_mcontext.gregs[REG_R9])
77 #define R10_sig(context) ((context)->uc_mcontext.gregs[REG_R10])
78 #define R11_sig(context) ((context)->uc_mcontext.gregs[REG_R11])
79 #define R12_sig(context) ((context)->uc_mcontext.gregs[REG_R12])
80 #define R13_sig(context) ((context)->uc_mcontext.gregs[REG_R13])
81 #define R14_sig(context) ((context)->uc_mcontext.gregs[REG_R14])
82 #define R15_sig(context) ((context)->uc_mcontext.gregs[REG_R15])
84 #define CS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 0))
85 #define GS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 1))
86 #define FS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 2))
88 #define RSP_sig(context) ((context)->uc_mcontext.gregs[REG_RSP])
89 #define RIP_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
90 #define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
91 #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
92 #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
94 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
96 #define FAULT_CODE (__siginfo->si_code)
97 #define FAULT_ADDRESS (__siginfo->si_addr)
99 #endif /* linux */
101 #if defined(__NetBSD__)
102 # include <sys/ucontext.h>
103 # include <sys/types.h>
104 # include <signal.h>
106 typedef ucontext_t SIGCONTEXT;
108 #define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
109 #define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
110 #define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
111 #define RDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDX])
112 #define RSI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RSI])
113 #define RDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDI])
114 #define RBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBP])
115 #define R8_sig(context) ((context)->uc_mcontext.__gregs[_REG_R8])
116 #define R9_sig(context) ((context)->uc_mcontext.__gregs[_REG_R9])
117 #define R10_sig(context) ((context)->uc_mcontext.__gregs[_REG_R10])
118 #define R11_sig(context) ((context)->uc_mcontext.__gregs[_REG_R11])
119 #define R12_sig(context) ((context)->uc_mcontext.__gregs[_REG_R12])
120 #define R13_sig(context) ((context)->uc_mcontext.__gregs[_REG_R13])
121 #define R14_sig(context) ((context)->uc_mcontext.__gregs[_REG_R14])
122 #define R15_sig(context) ((context)->uc_mcontext.__gregs[_REG_R15])
124 #define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
125 #define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
126 #define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
127 #define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
128 #define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
129 #define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
131 #define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_RFL])
133 #define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_RIP]))
134 #define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_URSP]))
136 #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
137 #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
139 #define FAULT_CODE (__siginfo->si_code)
140 #define FAULT_ADDRESS (__siginfo->si_addr)
142 #define HANDLER_DEF(name) void name( int __signal, siginfo_t *__siginfo, SIGCONTEXT *__context )
143 #define HANDLER_CONTEXT (__context)
145 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
146 #endif /* __NetBSD__ */
148 enum i386_trap_code
150 TRAP_x86_UNKNOWN = -1, /* Unknown fault (TRAP_sig not defined) */
151 TRAP_x86_DIVIDE = 0, /* Division by zero exception */
152 TRAP_x86_TRCTRAP = 1, /* Single-step exception */
153 TRAP_x86_NMI = 2, /* NMI interrupt */
154 TRAP_x86_BPTFLT = 3, /* Breakpoint exception */
155 TRAP_x86_OFLOW = 4, /* Overflow exception */
156 TRAP_x86_BOUND = 5, /* Bound range exception */
157 TRAP_x86_PRIVINFLT = 6, /* Invalid opcode exception */
158 TRAP_x86_DNA = 7, /* Device not available exception */
159 TRAP_x86_DOUBLEFLT = 8, /* Double fault exception */
160 TRAP_x86_FPOPFLT = 9, /* Coprocessor segment overrun */
161 TRAP_x86_TSSFLT = 10, /* Invalid TSS exception */
162 TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */
163 TRAP_x86_STKFLT = 12, /* Stack fault */
164 TRAP_x86_PROTFLT = 13, /* General protection fault */
165 TRAP_x86_PAGEFLT = 14, /* Page fault */
166 TRAP_x86_ARITHTRAP = 16, /* Floating point exception */
167 TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */
168 TRAP_x86_MCHK = 18, /* Machine check exception */
169 TRAP_x86_CACHEFLT = 19 /* Cache flush exception */
172 typedef int (*wine_signal_handler)(unsigned int sig);
174 static wine_signal_handler handlers[256];
176 /***********************************************************************
177 * dispatch_signal
179 static inline int dispatch_signal(unsigned int sig)
181 if (handlers[sig] == NULL) return 0;
182 return handlers[sig](sig);
185 /***********************************************************************
186 * save_context
188 * Set the register values from a sigcontext.
190 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
192 context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
193 context->Rax = RAX_sig(sigcontext);
194 context->Rcx = RCX_sig(sigcontext);
195 context->Rdx = RDX_sig(sigcontext);
196 context->Rbx = RBX_sig(sigcontext);
197 context->Rsp = RSP_sig(sigcontext);
198 context->Rbp = RBP_sig(sigcontext);
199 context->Rsi = RSI_sig(sigcontext);
200 context->Rdi = RDI_sig(sigcontext);
201 context->R8 = R8_sig(sigcontext);
202 context->R9 = R9_sig(sigcontext);
203 context->R10 = R10_sig(sigcontext);
204 context->R11 = R11_sig(sigcontext);
205 context->R12 = R12_sig(sigcontext);
206 context->R13 = R13_sig(sigcontext);
207 context->R14 = R14_sig(sigcontext);
208 context->R15 = R15_sig(sigcontext);
209 context->Rip = RIP_sig(sigcontext);
210 context->SegCs = CS_sig(sigcontext);
211 context->SegFs = FS_sig(sigcontext);
212 context->SegGs = GS_sig(sigcontext);
213 context->EFlags = EFL_sig(sigcontext);
214 context->SegDs = 0; /* FIXME */
215 context->SegEs = 0; /* FIXME */
216 context->SegSs = 0; /* FIXME */
217 context->MxCsr = 0; /* FIXME */
218 if (FPU_sig(sigcontext))
220 context->ContextFlags |= CONTEXT_FLOATING_POINT;
221 context->u.FltSave = *FPU_sig(sigcontext);
226 /***********************************************************************
227 * restore_context
229 * Build a sigcontext from the register values.
231 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
233 RAX_sig(sigcontext) = context->Rax;
234 RCX_sig(sigcontext) = context->Rcx;
235 RDX_sig(sigcontext) = context->Rdx;
236 RBX_sig(sigcontext) = context->Rbx;
237 RSP_sig(sigcontext) = context->Rsp;
238 RBP_sig(sigcontext) = context->Rbp;
239 RSI_sig(sigcontext) = context->Rsi;
240 RDI_sig(sigcontext) = context->Rdi;
241 R8_sig(sigcontext) = context->R8;
242 R9_sig(sigcontext) = context->R9;
243 R10_sig(sigcontext) = context->R10;
244 R11_sig(sigcontext) = context->R11;
245 R12_sig(sigcontext) = context->R12;
246 R13_sig(sigcontext) = context->R13;
247 R14_sig(sigcontext) = context->R14;
248 R15_sig(sigcontext) = context->R15;
249 RIP_sig(sigcontext) = context->Rip;
250 CS_sig(sigcontext) = context->SegCs;
251 FS_sig(sigcontext) = context->SegFs;
252 GS_sig(sigcontext) = context->SegGs;
253 EFL_sig(sigcontext) = context->EFlags;
254 if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
258 /***********************************************************************
259 * RtlCaptureContext (NTDLL.@)
261 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
263 *context = *regs;
265 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
268 /***********************************************************************
269 * set_cpu_context
271 * Set the new CPU context.
273 void set_cpu_context( const CONTEXT *context )
275 FIXME("not implemented\n");
279 /***********************************************************************
280 * copy_context
282 * Copy a register context according to the flags.
284 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
286 flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
287 if (flags & CONTEXT_CONTROL)
289 to->Rbp = from->Rbp;
290 to->Rip = from->Rip;
291 to->Rsp = from->Rsp;
292 to->SegCs = from->SegCs;
293 to->SegSs = from->SegSs;
294 to->EFlags = from->EFlags;
295 to->MxCsr = from->MxCsr;
297 if (flags & CONTEXT_INTEGER)
299 to->Rax = from->Rax;
300 to->Rcx = from->Rcx;
301 to->Rdx = from->Rdx;
302 to->Rbx = from->Rbx;
303 to->Rsi = from->Rsi;
304 to->Rdi = from->Rdi;
305 to->R8 = from->R8;
306 to->R9 = from->R9;
307 to->R10 = from->R10;
308 to->R11 = from->R11;
309 to->R12 = from->R12;
310 to->R13 = from->R13;
311 to->R14 = from->R14;
312 to->R15 = from->R15;
314 if (flags & CONTEXT_SEGMENTS)
316 to->SegDs = from->SegDs;
317 to->SegEs = from->SegEs;
318 to->SegFs = from->SegFs;
319 to->SegGs = from->SegGs;
321 if (flags & CONTEXT_FLOATING_POINT)
323 to->u.FltSave = from->u.FltSave;
325 if (flags & CONTEXT_DEBUG_REGISTERS)
327 to->Dr0 = from->Dr0;
328 to->Dr1 = from->Dr1;
329 to->Dr2 = from->Dr2;
330 to->Dr3 = from->Dr3;
331 to->Dr6 = from->Dr6;
332 to->Dr7 = from->Dr7;
337 /***********************************************************************
338 * context_to_server
340 * Convert a register context to the server format.
342 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
344 DWORD flags = from->ContextFlags & ~CONTEXT_AMD64; /* get rid of CPU id */
346 memset( to, 0, sizeof(*to) );
347 to->cpu = CPU_x86_64;
349 if (flags & CONTEXT_CONTROL)
351 to->flags |= SERVER_CTX_CONTROL;
352 to->ctl.x86_64_regs.rbp = from->Rbp;
353 to->ctl.x86_64_regs.rip = from->Rip;
354 to->ctl.x86_64_regs.rsp = from->Rsp;
355 to->ctl.x86_64_regs.cs = from->SegCs;
356 to->ctl.x86_64_regs.ss = from->SegSs;
357 to->ctl.x86_64_regs.flags = from->EFlags;
358 to->ctl.x86_64_regs.mxcsr = from->MxCsr;
360 if (flags & CONTEXT_INTEGER)
362 to->flags |= SERVER_CTX_INTEGER;
363 to->integer.x86_64_regs.rax = from->Rax;
364 to->integer.x86_64_regs.rcx = from->Rcx;
365 to->integer.x86_64_regs.rdx = from->Rdx;
366 to->integer.x86_64_regs.rbx = from->Rbx;
367 to->integer.x86_64_regs.rsi = from->Rsi;
368 to->integer.x86_64_regs.rdi = from->Rdi;
369 to->integer.x86_64_regs.r8 = from->R8;
370 to->integer.x86_64_regs.r9 = from->R9;
371 to->integer.x86_64_regs.r10 = from->R10;
372 to->integer.x86_64_regs.r11 = from->R11;
373 to->integer.x86_64_regs.r12 = from->R12;
374 to->integer.x86_64_regs.r13 = from->R13;
375 to->integer.x86_64_regs.r14 = from->R14;
376 to->integer.x86_64_regs.r15 = from->R15;
378 if (flags & CONTEXT_SEGMENTS)
380 to->flags |= SERVER_CTX_SEGMENTS;
381 to->seg.x86_64_regs.ds = from->SegDs;
382 to->seg.x86_64_regs.es = from->SegEs;
383 to->seg.x86_64_regs.fs = from->SegFs;
384 to->seg.x86_64_regs.gs = from->SegGs;
386 if (flags & CONTEXT_FLOATING_POINT)
388 to->flags |= SERVER_CTX_FLOATING_POINT;
389 memcpy( to->fp.x86_64_regs.fpregs, &from->u.FltSave, sizeof(to->fp.x86_64_regs.fpregs) );
391 if (flags & CONTEXT_DEBUG_REGISTERS)
393 to->flags |= SERVER_CTX_DEBUG_REGISTERS;
394 to->debug.x86_64_regs.dr0 = from->Dr0;
395 to->debug.x86_64_regs.dr1 = from->Dr1;
396 to->debug.x86_64_regs.dr2 = from->Dr2;
397 to->debug.x86_64_regs.dr3 = from->Dr3;
398 to->debug.x86_64_regs.dr6 = from->Dr6;
399 to->debug.x86_64_regs.dr7 = from->Dr7;
401 return STATUS_SUCCESS;
405 /***********************************************************************
406 * context_from_server
408 * Convert a register context from the server format.
410 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
412 if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER;
414 to->ContextFlags = CONTEXT_AMD64;
415 if (from->flags & SERVER_CTX_CONTROL)
417 to->ContextFlags |= CONTEXT_CONTROL;
418 to->Rbp = from->ctl.x86_64_regs.rbp;
419 to->Rip = from->ctl.x86_64_regs.rip;
420 to->Rsp = from->ctl.x86_64_regs.rsp;
421 to->SegCs = from->ctl.x86_64_regs.cs;
422 to->SegSs = from->ctl.x86_64_regs.ss;
423 to->EFlags = from->ctl.x86_64_regs.flags;
424 to->MxCsr = from->ctl.x86_64_regs.mxcsr;
427 if (from->flags & SERVER_CTX_INTEGER)
429 to->ContextFlags |= CONTEXT_INTEGER;
430 to->Rax = from->integer.x86_64_regs.rax;
431 to->Rcx = from->integer.x86_64_regs.rcx;
432 to->Rdx = from->integer.x86_64_regs.rdx;
433 to->Rbx = from->integer.x86_64_regs.rbx;
434 to->Rsi = from->integer.x86_64_regs.rsi;
435 to->Rdi = from->integer.x86_64_regs.rdi;
436 to->R8 = from->integer.x86_64_regs.r8;
437 to->R9 = from->integer.x86_64_regs.r9;
438 to->R10 = from->integer.x86_64_regs.r10;
439 to->R11 = from->integer.x86_64_regs.r11;
440 to->R12 = from->integer.x86_64_regs.r12;
441 to->R13 = from->integer.x86_64_regs.r13;
442 to->R14 = from->integer.x86_64_regs.r14;
443 to->R15 = from->integer.x86_64_regs.r15;
445 if (from->flags & SERVER_CTX_SEGMENTS)
447 to->ContextFlags |= CONTEXT_SEGMENTS;
448 to->SegDs = from->seg.x86_64_regs.ds;
449 to->SegEs = from->seg.x86_64_regs.es;
450 to->SegFs = from->seg.x86_64_regs.fs;
451 to->SegGs = from->seg.x86_64_regs.gs;
453 if (from->flags & SERVER_CTX_FLOATING_POINT)
455 to->ContextFlags |= CONTEXT_FLOATING_POINT;
456 memcpy( &to->u.FltSave, from->fp.x86_64_regs.fpregs, sizeof(from->fp.x86_64_regs.fpregs) );
458 if (from->flags & SERVER_CTX_DEBUG_REGISTERS)
460 to->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
461 to->Dr0 = from->debug.x86_64_regs.dr0;
462 to->Dr1 = from->debug.x86_64_regs.dr1;
463 to->Dr2 = from->debug.x86_64_regs.dr2;
464 to->Dr3 = from->debug.x86_64_regs.dr3;
465 to->Dr6 = from->debug.x86_64_regs.dr6;
466 to->Dr7 = from->debug.x86_64_regs.dr7;
468 return STATUS_SUCCESS;
472 /**********************************************************************
473 * call_stack_handlers
475 * Call the stack handlers chain.
477 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
479 EXCEPTION_POINTERS ptrs;
481 FIXME( "not implemented on x86_64\n" );
483 /* hack: call unhandled exception filter directly */
484 ptrs.ExceptionRecord = rec;
485 ptrs.ContextRecord = context;
486 unhandled_exception_filter( &ptrs );
487 return STATUS_UNHANDLED_EXCEPTION;
491 /*******************************************************************
492 * raise_exception
494 * Implementation of NtRaiseException.
496 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
498 NTSTATUS status;
500 if (first_chance)
502 DWORD c;
504 TRACE( "code=%x flags=%x addr=%p ip=%lx tid=%04x\n",
505 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
506 context->Rip, GetCurrentThreadId() );
507 for (c = 0; c < rec->NumberParameters; c++)
508 TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
509 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
511 if (rec->ExceptionInformation[1] >> 16)
512 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
513 rec->ExceptionAddress,
514 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
515 else
516 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
517 rec->ExceptionAddress,
518 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
520 else
522 TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
523 context->Rax, context->Rbx, context->Rcx, context->Rdx );
524 TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
525 context->Rsi, context->Rdi, context->Rbp, context->Rsp );
526 TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
527 context->R8, context->R9, context->R10, context->R11 );
528 TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
529 context->R12, context->R13, context->R14, context->R15 );
531 status = send_debug_event( rec, TRUE, context );
532 if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
533 return STATUS_SUCCESS;
535 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
536 return STATUS_SUCCESS;
538 if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
539 return status;
542 /* last chance exception */
544 status = send_debug_event( rec, FALSE, context );
545 if (status != DBG_CONTINUE)
547 if (rec->ExceptionFlags & EH_STACK_INVALID)
548 ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
549 else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
550 ERR("Process attempted to continue execution after noncontinuable exception.\n");
551 else
552 ERR("Unhandled exception code %x flags %x addr %p\n",
553 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
554 NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
556 return STATUS_SUCCESS;
560 /**********************************************************************
561 * segv_handler
563 * Handler for SIGSEGV and related errors.
565 static HANDLER_DEF(segv_handler)
567 EXCEPTION_RECORD rec;
568 CONTEXT context;
569 NTSTATUS status;
571 save_context( &context, HANDLER_CONTEXT );
573 rec.ExceptionRecord = NULL;
574 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
575 rec.ExceptionAddress = (LPVOID)context.Rip;
576 rec.NumberParameters = 0;
578 switch(TRAP_sig(HANDLER_CONTEXT))
580 case TRAP_x86_OFLOW: /* Overflow exception */
581 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
582 break;
583 case TRAP_x86_BOUND: /* Bound range exception */
584 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
585 break;
586 case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */
587 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
588 break;
589 case TRAP_x86_STKFLT: /* Stack fault */
590 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
591 break;
592 case TRAP_x86_SEGNPFLT: /* Segment not present exception */
593 case TRAP_x86_PROTFLT: /* General protection fault */
594 case TRAP_x86_UNKNOWN: /* Unknown fault code */
595 rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
596 : EXCEPTION_PRIV_INSTRUCTION;
597 break;
598 case TRAP_x86_PAGEFLT: /* Page fault */
599 rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
600 #ifdef FAULT_ADDRESS
601 rec.NumberParameters = 2;
602 rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
603 rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
604 if (!(rec.ExceptionCode = virtual_handle_fault( FAULT_ADDRESS, rec.ExceptionInformation[0] )))
605 goto done;
606 #endif
607 break;
608 case TRAP_x86_ALIGNFLT: /* Alignment check exception */
609 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
610 break;
611 default:
612 ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
613 /* fall through */
614 case TRAP_x86_NMI: /* NMI interrupt */
615 case TRAP_x86_DNA: /* Device not available exception */
616 case TRAP_x86_DOUBLEFLT: /* Double fault exception */
617 case TRAP_x86_TSSFLT: /* Invalid TSS exception */
618 case TRAP_x86_MCHK: /* Machine check exception */
619 case TRAP_x86_CACHEFLT: /* Cache flush exception */
620 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
621 break;
624 status = raise_exception( &rec, &context, TRUE );
625 if (status) raise_status( status, &rec );
626 done:
627 restore_context( &context, HANDLER_CONTEXT );
630 /**********************************************************************
631 * trap_handler
633 * Handler for SIGTRAP.
635 static HANDLER_DEF(trap_handler)
637 EXCEPTION_RECORD rec;
638 CONTEXT context;
639 NTSTATUS status;
641 save_context( &context, HANDLER_CONTEXT );
642 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
643 rec.ExceptionRecord = NULL;
644 rec.ExceptionAddress = (LPVOID)context.Rip;
645 rec.NumberParameters = 0;
647 switch(FAULT_CODE)
649 case TRAP_TRACE: /* Single-step exception */
650 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
651 EFL_sig(HANDLER_CONTEXT) &= ~0x100; /* clear single-step flag */
652 break;
653 case TRAP_BRKPT: /* Breakpoint exception */
654 rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */
655 /* fall through */
656 default:
657 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
658 break;
661 status = raise_exception( &rec, &context, TRUE );
662 if (status) raise_status( status, &rec );
663 restore_context( &context, HANDLER_CONTEXT );
666 /**********************************************************************
667 * fpe_handler
669 * Handler for SIGFPE.
671 static HANDLER_DEF(fpe_handler)
673 EXCEPTION_RECORD rec;
674 CONTEXT context;
675 NTSTATUS status;
677 save_context( &context, HANDLER_CONTEXT );
678 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
679 rec.ExceptionRecord = NULL;
680 rec.ExceptionAddress = (LPVOID)context.Rip;
681 rec.NumberParameters = 0;
683 switch (FAULT_CODE)
685 case FPE_FLTSUB:
686 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
687 break;
688 case FPE_INTDIV:
689 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
690 break;
691 case FPE_INTOVF:
692 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
693 break;
694 case FPE_FLTDIV:
695 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
696 break;
697 case FPE_FLTOVF:
698 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
699 break;
700 case FPE_FLTUND:
701 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
702 break;
703 case FPE_FLTRES:
704 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
705 break;
706 case FPE_FLTINV:
707 default:
708 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
709 break;
712 status = raise_exception( &rec, &context, TRUE );
713 if (status) raise_status( status, &rec );
714 restore_context( &context, HANDLER_CONTEXT );
717 /**********************************************************************
718 * int_handler
720 * Handler for SIGINT.
722 static HANDLER_DEF(int_handler)
724 if (!dispatch_signal(SIGINT))
726 EXCEPTION_RECORD rec;
727 CONTEXT context;
728 NTSTATUS status;
730 save_context( &context, HANDLER_CONTEXT );
731 rec.ExceptionCode = CONTROL_C_EXIT;
732 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
733 rec.ExceptionRecord = NULL;
734 rec.ExceptionAddress = (LPVOID)context.Rip;
735 rec.NumberParameters = 0;
736 status = raise_exception( &rec, &context, TRUE );
737 if (status) raise_status( status, &rec );
738 restore_context( &context, HANDLER_CONTEXT );
743 /**********************************************************************
744 * abrt_handler
746 * Handler for SIGABRT.
748 static HANDLER_DEF(abrt_handler)
750 EXCEPTION_RECORD rec;
751 CONTEXT context;
752 NTSTATUS status;
754 save_context( &context, HANDLER_CONTEXT );
755 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
756 rec.ExceptionFlags = EH_NONCONTINUABLE;
757 rec.ExceptionRecord = NULL;
758 rec.ExceptionAddress = (LPVOID)context.Rip;
759 rec.NumberParameters = 0;
760 status = raise_exception( &rec, &context, TRUE );
761 if (status) raise_status( status, &rec );
762 restore_context( &context, HANDLER_CONTEXT );
766 /**********************************************************************
767 * quit_handler
769 * Handler for SIGQUIT.
771 static HANDLER_DEF(quit_handler)
773 abort_thread(0);
777 /**********************************************************************
778 * usr1_handler
780 * Handler for SIGUSR1, used to signal a thread that it got suspended.
782 static HANDLER_DEF(usr1_handler)
784 CONTEXT context;
786 save_context( &context, HANDLER_CONTEXT );
787 wait_suspend( &context );
788 restore_context( &context, HANDLER_CONTEXT );
792 /**********************************************************************
793 * get_signal_stack_total_size
795 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
796 * Must be a power of two.
798 size_t get_signal_stack_total_size(void)
800 assert( sizeof(TEB) <= 2*getpagesize() );
801 return 2*getpagesize(); /* this is just for the TEB, we don't need a signal stack */
805 /***********************************************************************
806 * set_handler
808 * Set a signal handler
810 static int set_handler( int sig, void (*func)() )
812 struct sigaction sig_act;
814 sig_act.sa_sigaction = func;
815 sig_act.sa_mask = server_block_set;
816 sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
817 return sigaction( sig, &sig_act, NULL );
821 /***********************************************************************
822 * __wine_set_signal_handler (NTDLL.@)
824 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
826 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
827 if (handlers[sig] != NULL) return -2;
828 handlers[sig] = wsh;
829 return 0;
833 /**********************************************************************
834 * signal_init_thread
836 void signal_init_thread( TEB *teb )
838 #ifdef __linux__
839 arch_prctl( ARCH_SET_GS, teb );
840 #else
841 # error Please define setting %gs for your architecture
842 #endif
845 /**********************************************************************
846 * signal_init_process
848 void signal_init_process(void)
850 if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error;
851 if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error;
852 if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
853 if (set_handler( SIGILL, (void (*)())segv_handler ) == -1) goto error;
854 if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
855 if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
856 if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
857 #ifdef SIGBUS
858 if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error;
859 #endif
860 #ifdef SIGTRAP
861 if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
862 #endif
863 return;
865 error:
866 perror("sigaction");
867 exit(1);
871 /**********************************************************************
872 * RtlLookupFunctionEntry (NTDLL.@)
874 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
875 UNWIND_HISTORY_TABLE *table )
877 FIXME("stub\n");
878 return NULL;
882 /**********************************************************************
883 * RtlVirtualUnwind (NTDLL.@)
885 PVOID WINAPI RtlVirtualUnwind ( ULONG type, ULONG64 base, ULONG64 pc,
886 RUNTIME_FUNCTION *function, CONTEXT *context,
887 PVOID *data, ULONG64 *frame,
888 KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
890 FIXME("stub\n");
891 return NULL;
895 /*******************************************************************
896 * RtlUnwind (NTDLL.@)
898 void WINAPI __regs_RtlUnwind( EXCEPTION_REGISTRATION_RECORD* pEndFrame, PVOID targetIp,
899 PEXCEPTION_RECORD pRecord, PVOID retval, CONTEXT *context )
901 EXCEPTION_RECORD record;
903 /* build an exception record, if we do not have one */
904 if (!pRecord)
906 record.ExceptionCode = STATUS_UNWIND;
907 record.ExceptionFlags = 0;
908 record.ExceptionRecord = NULL;
909 record.ExceptionAddress = (void *)context->Rip;
910 record.NumberParameters = 0;
911 pRecord = &record;
914 pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND);
916 FIXME( "code=%x flags=%x not implemented on x86_64\n",
917 pRecord->ExceptionCode, pRecord->ExceptionFlags );
918 NtTerminateProcess( GetCurrentProcess(), 1 );
920 DEFINE_REGS_ENTRYPOINT( RtlUnwind, 4 )
923 /*******************************************************************
924 * NtRaiseException (NTDLL.@)
926 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
928 NTSTATUS status = raise_exception( rec, context, first_chance );
929 if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
930 return status;
934 /***********************************************************************
935 * RtlRaiseException (NTDLL.@)
937 void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
939 NTSTATUS status;
941 rec->ExceptionAddress = (void *)context->Rip;
942 status = raise_exception( rec, context, TRUE );
943 if (status != STATUS_SUCCESS) raise_status( status, rec );
945 DEFINE_REGS_ENTRYPOINT( RtlRaiseException, 1 )
948 /**********************************************************************
949 * __wine_enter_vm86 (NTDLL.@)
951 void __wine_enter_vm86( CONTEXT *context )
953 MESSAGE("vm86 mode not supported on this platform\n");
956 /**********************************************************************
957 * DbgBreakPoint (NTDLL.@)
959 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
961 /**********************************************************************
962 * DbgUserBreakPoint (NTDLL.@)
964 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
966 #endif /* __x86_64__ */