ntdll: Move NtRaiseException and RtlUnwind implementations to the CPU-specific files.
[wine] / dlls / ntdll / signal_x86_64.c
1 /*
2  * x86-64 signal handling routines
3  *
4  * Copyright 1999, 2005 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #ifdef __x86_64__
22
23 #include "config.h"
24 #include "wine/port.h"
25
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
34
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
41
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"
51
52 WINE_DEFAULT_DEBUG_CHANNEL(seh);
53
54
55 /***********************************************************************
56  * signal context platform-specific definitions
57  */
58 #ifdef linux
59
60 #include <asm/prctl.h>
61 extern int arch_prctl(int func, void *ptr);
62
63 typedef struct ucontext SIGCONTEXT;
64
65 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
66 # define HANDLER_CONTEXT (__context)
67
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])
83
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))
87
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])
93
94 #define FPU_sig(context)     ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
95
96 #define FAULT_CODE     (__siginfo->si_code)
97 #define FAULT_ADDRESS  (__siginfo->si_addr)
98
99 #endif /* linux */
100
101 #if defined(__NetBSD__)
102 # include <sys/ucontext.h>
103 # include <sys/types.h>
104 # include <signal.h>
105
106 typedef ucontext_t SIGCONTEXT;
107
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])
123
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])
130
131 #define EFL_sig(context)    ((context)->uc_mcontext.__gregs[_REG_RFL])
132
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]))
135
136 #define TRAP_sig(context)   ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
137 #define ERROR_sig(context)  ((context)->uc_mcontext.__gregs[_REG_ERR])
138
139 #define FAULT_CODE          (__siginfo->si_code)
140 #define FAULT_ADDRESS       (__siginfo->si_addr)
141
142 #define HANDLER_DEF(name) void name( int __signal, siginfo_t *__siginfo, SIGCONTEXT *__context )
143 #define HANDLER_CONTEXT (__context)
144
145 #define FPU_sig(context)   ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
146 #endif /* __NetBSD__ */
147
148 enum i386_trap_code
149 {
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 */
170 };
171
172 typedef int (*wine_signal_handler)(unsigned int sig);
173
174 static wine_signal_handler handlers[256];
175
176 /***********************************************************************
177  *           dispatch_signal
178  */
179 static inline int dispatch_signal(unsigned int sig)
180 {
181     if (handlers[sig] == NULL) return 0;
182     return handlers[sig](sig);
183 }
184
185 /***********************************************************************
186  *           save_context
187  *
188  * Set the register values from a sigcontext.
189  */
190 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
191 {
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))
219     {
220         context->ContextFlags |= CONTEXT_FLOATING_POINT;
221         context->u.FltSave = *FPU_sig(sigcontext);
222     }
223 }
224
225
226 /***********************************************************************
227  *           restore_context
228  *
229  * Build a sigcontext from the register values.
230  */
231 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
232 {
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;
255 }
256
257
258 /***********************************************************************
259  *              RtlCaptureContext (NTDLL.@)
260  */
261 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
262 {
263     *context = *regs;
264 }
265 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
266
267
268 /***********************************************************************
269  *           set_cpu_context
270  *
271  * Set the new CPU context.
272  */
273 void set_cpu_context( const CONTEXT *context )
274 {
275     FIXME("not implemented\n");
276 }
277
278
279 /***********************************************************************
280  *           copy_context
281  *
282  * Copy a register context according to the flags.
283  */
284 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
285 {
286     flags &= ~CONTEXT_AMD64;  /* get rid of CPU id */
287     if (flags & CONTEXT_CONTROL)
288     {
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;
296     }
297     if (flags & CONTEXT_INTEGER)
298     {
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;
313     }
314     if (flags & CONTEXT_SEGMENTS)
315     {
316         to->SegDs = from->SegDs;
317         to->SegEs = from->SegEs;
318         to->SegFs = from->SegFs;
319         to->SegGs = from->SegGs;
320     }
321     if (flags & CONTEXT_FLOATING_POINT)
322     {
323         to->u.FltSave = from->u.FltSave;
324     }
325     if (flags & CONTEXT_DEBUG_REGISTERS)
326     {
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;
333     }
334 }
335
336
337 /***********************************************************************
338  *           context_to_server
339  *
340  * Convert a register context to the server format.
341  */
342 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
343 {
344     DWORD flags = from->ContextFlags & ~CONTEXT_AMD64;  /* get rid of CPU id */
345
346     memset( to, 0, sizeof(*to) );
347     to->cpu = CPU_x86_64;
348
349     if (flags & CONTEXT_CONTROL)
350     {
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;
359     }
360     if (flags & CONTEXT_INTEGER)
361     {
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;
377     }
378     if (flags & CONTEXT_SEGMENTS)
379     {
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;
385     }
386     if (flags & CONTEXT_FLOATING_POINT)
387     {
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) );
390     }
391     if (flags & CONTEXT_DEBUG_REGISTERS)
392     {
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;
400     }
401     return STATUS_SUCCESS;
402 }
403
404
405 /***********************************************************************
406  *           context_from_server
407  *
408  * Convert a register context from the server format.
409  */
410 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
411 {
412     if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER;
413
414     to->ContextFlags = CONTEXT_AMD64;
415     if (from->flags & SERVER_CTX_CONTROL)
416     {
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;
425     }
426
427     if (from->flags & SERVER_CTX_INTEGER)
428     {
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;
444     }
445     if (from->flags & SERVER_CTX_SEGMENTS)
446     {
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;
452     }
453     if (from->flags & SERVER_CTX_FLOATING_POINT)
454     {
455         to->ContextFlags |= CONTEXT_FLOATING_POINT;
456         memcpy( &to->u.FltSave, from->fp.x86_64_regs.fpregs, sizeof(from->fp.x86_64_regs.fpregs) );
457     }
458     if (from->flags & SERVER_CTX_DEBUG_REGISTERS)
459     {
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;
467     }
468     return STATUS_SUCCESS;
469 }
470
471
472 /**********************************************************************
473  *           call_stack_handlers
474  *
475  * Call the stack handlers chain.
476  */
477 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
478 {
479     EXCEPTION_POINTERS ptrs;
480
481     FIXME( "not implemented on x86_64\n" );
482
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;
488 }
489
490
491 /*******************************************************************
492  *              raise_exception
493  *
494  * Implementation of NtRaiseException.
495  */
496 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
497 {
498     NTSTATUS status;
499
500     if (first_chance)
501     {
502         DWORD c;
503
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)
510         {
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] );
519         }
520         else
521         {
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 );
530         }
531         status = send_debug_event( rec, TRUE, context );
532         if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
533             return STATUS_SUCCESS;
534
535         if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
536             return STATUS_SUCCESS;
537
538         if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
539             return status;
540     }
541
542     /* last chance exception */
543
544     status = send_debug_event( rec, FALSE, context );
545     if (status != DBG_CONTINUE)
546     {
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 );
555     }
556     return STATUS_SUCCESS;
557 }
558
559
560 /**********************************************************************
561  *              segv_handler
562  *
563  * Handler for SIGSEGV and related errors.
564  */
565 static HANDLER_DEF(segv_handler)
566 {
567     EXCEPTION_RECORD rec;
568     CONTEXT context;
569     NTSTATUS status;
570
571     save_context( &context, HANDLER_CONTEXT );
572
573     rec.ExceptionRecord  = NULL;
574     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
575     rec.ExceptionAddress = (LPVOID)context.Rip;
576     rec.NumberParameters = 0;
577
578     switch(TRAP_sig(HANDLER_CONTEXT))
579     {
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;
622     }
623
624     status = raise_exception( &rec, &context, TRUE );
625     if (status) raise_status( status, &rec );
626 done:
627     restore_context( &context, HANDLER_CONTEXT );
628 }
629
630 /**********************************************************************
631  *              trap_handler
632  *
633  * Handler for SIGTRAP.
634  */
635 static HANDLER_DEF(trap_handler)
636 {
637     EXCEPTION_RECORD rec;
638     CONTEXT context;
639     NTSTATUS status;
640
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;
646
647     switch(FAULT_CODE)
648     {
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;
659     }
660
661     status = raise_exception( &rec, &context, TRUE );
662     if (status) raise_status( status, &rec );
663     restore_context( &context, HANDLER_CONTEXT );
664 }
665
666 /**********************************************************************
667  *              fpe_handler
668  *
669  * Handler for SIGFPE.
670  */
671 static HANDLER_DEF(fpe_handler)
672 {
673     EXCEPTION_RECORD rec;
674     CONTEXT context;
675     NTSTATUS status;
676
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;
682
683     switch (FAULT_CODE)
684     {
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;
710     }
711
712     status = raise_exception( &rec, &context, TRUE );
713     if (status) raise_status( status, &rec );
714     restore_context( &context, HANDLER_CONTEXT );
715 }
716
717 /**********************************************************************
718  *              int_handler
719  *
720  * Handler for SIGINT.
721  */
722 static HANDLER_DEF(int_handler)
723 {
724     if (!dispatch_signal(SIGINT))
725     {
726         EXCEPTION_RECORD rec;
727         CONTEXT context;
728         NTSTATUS status;
729
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 );
739     }
740 }
741
742
743 /**********************************************************************
744  *              abrt_handler
745  *
746  * Handler for SIGABRT.
747  */
748 static HANDLER_DEF(abrt_handler)
749 {
750     EXCEPTION_RECORD rec;
751     CONTEXT context;
752     NTSTATUS status;
753
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 );
763 }
764
765
766 /**********************************************************************
767  *              quit_handler
768  *
769  * Handler for SIGQUIT.
770  */
771 static HANDLER_DEF(quit_handler)
772 {
773     abort_thread(0);
774 }
775
776
777 /**********************************************************************
778  *              usr1_handler
779  *
780  * Handler for SIGUSR1, used to signal a thread that it got suspended.
781  */
782 static HANDLER_DEF(usr1_handler)
783 {
784     CONTEXT context;
785
786     save_context( &context, HANDLER_CONTEXT );
787     wait_suspend( &context );
788     restore_context( &context, HANDLER_CONTEXT );
789 }
790
791
792 /**********************************************************************
793  *              get_signal_stack_total_size
794  *
795  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
796  * Must be a power of two.
797  */
798 size_t get_signal_stack_total_size(void)
799 {
800     assert( sizeof(TEB) <= 2*getpagesize() );
801     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
802 }
803
804
805 /***********************************************************************
806  *           set_handler
807  *
808  * Set a signal handler
809  */
810 static int set_handler( int sig, void (*func)() )
811 {
812     struct sigaction sig_act;
813
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 );
818 }
819
820
821 /***********************************************************************
822  *           __wine_set_signal_handler   (NTDLL.@)
823  */
824 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
825 {
826     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
827     if (handlers[sig] != NULL) return -2;
828     handlers[sig] = wsh;
829     return 0;
830 }
831
832
833 /**********************************************************************
834  *              signal_init_thread
835  */
836 void signal_init_thread( TEB *teb )
837 {
838 #ifdef __linux__
839     arch_prctl( ARCH_SET_GS, teb );
840 #else
841 # error Please define setting %gs for your architecture
842 #endif
843 }
844
845 /**********************************************************************
846  *              signal_init_process
847  */
848 void signal_init_process(void)
849 {
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;
864
865  error:
866     perror("sigaction");
867     exit(1);
868 }
869
870
871 /**********************************************************************
872  *              RtlLookupFunctionEntry   (NTDLL.@)
873  */
874 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
875                                                  UNWIND_HISTORY_TABLE *table )
876 {
877     FIXME("stub\n");
878     return NULL;
879 }
880
881
882 /**********************************************************************
883  *              RtlVirtualUnwind   (NTDLL.@)
884  */
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 )
889 {
890     FIXME("stub\n");
891     return NULL;
892 }
893
894
895 /*******************************************************************
896  *              RtlUnwind (NTDLL.@)
897  */
898 void WINAPI __regs_RtlUnwind( EXCEPTION_REGISTRATION_RECORD* pEndFrame, PVOID targetIp,
899                               PEXCEPTION_RECORD pRecord, PVOID retval, CONTEXT *context )
900 {
901     EXCEPTION_RECORD record;
902
903     /* build an exception record, if we do not have one */
904     if (!pRecord)
905     {
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;
912     }
913
914     pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND);
915
916     FIXME( "code=%x flags=%x not implemented on x86_64\n",
917            pRecord->ExceptionCode, pRecord->ExceptionFlags );
918     NtTerminateProcess( GetCurrentProcess(), 1 );
919 }
920 DEFINE_REGS_ENTRYPOINT( RtlUnwind, 4 )
921
922
923 /*******************************************************************
924  *              NtRaiseException (NTDLL.@)
925  */
926 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
927 {
928     NTSTATUS status = raise_exception( rec, context, first_chance );
929     if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
930     return status;
931 }
932
933
934 /***********************************************************************
935  *              RtlRaiseException (NTDLL.@)
936  */
937 void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
938 {
939     NTSTATUS status;
940
941     rec->ExceptionAddress = (void *)context->Rip;
942     status = raise_exception( rec, context, TRUE );
943     if (status != STATUS_SUCCESS) raise_status( status, rec );
944 }
945 DEFINE_REGS_ENTRYPOINT( RtlRaiseException, 1 )
946
947
948 /**********************************************************************
949  *              __wine_enter_vm86   (NTDLL.@)
950  */
951 void __wine_enter_vm86( CONTEXT *context )
952 {
953     MESSAGE("vm86 mode not supported on this platform\n");
954 }
955
956 /**********************************************************************
957  *              DbgBreakPoint   (NTDLL.@)
958  */
959 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
960
961 /**********************************************************************
962  *              DbgUserBreakPoint   (NTDLL.@)
963  */
964 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
965
966 #endif  /* __x86_64__ */