winhlp32: Use Win32 APIs instead of strdup().
[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 #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])
78
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))
82
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])
88
89 #define FPU_sig(context)     ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
90
91 #endif /* linux */
92
93 #if defined(__NetBSD__)
94 # include <sys/ucontext.h>
95 # include <sys/types.h>
96 # include <signal.h>
97
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])
113
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])
120
121 #define EFL_sig(context)    ((context)->uc_mcontext.__gregs[_REG_RFL])
122
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]))
125
126 #define TRAP_sig(context)   ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
127 #define ERROR_sig(context)  ((context)->uc_mcontext.__gregs[_REG_ERR])
128
129 #define FPU_sig(context)   ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
130 #endif /* __NetBSD__ */
131
132 enum i386_trap_code
133 {
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 */
154 };
155
156 typedef int (*wine_signal_handler)(unsigned int sig);
157
158 static wine_signal_handler handlers[256];
159
160 /***********************************************************************
161  *           dispatch_signal
162  */
163 static inline int dispatch_signal(unsigned int sig)
164 {
165     if (handlers[sig] == NULL) return 0;
166     return handlers[sig](sig);
167 }
168
169 /***********************************************************************
170  *           save_context
171  *
172  * Set the register values from a sigcontext.
173  */
174 static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
175 {
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))
215     {
216         context->ContextFlags |= CONTEXT_FLOATING_POINT;
217         context->u.FltSave = *FPU_sig(sigcontext);
218     }
219 }
220
221
222 /***********************************************************************
223  *           restore_context
224  *
225  * Build a sigcontext from the register values.
226  */
227 static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
228 {
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;
260 }
261
262
263 /***********************************************************************
264  *              RtlCaptureContext (NTDLL.@)
265  */
266 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
267 {
268     *context = *regs;
269 }
270 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
271
272
273 /***********************************************************************
274  *           set_cpu_context
275  *
276  * Set the new CPU context.
277  */
278 void set_cpu_context( const CONTEXT *context )
279 {
280     extern void CDECL __wine_restore_regs( const CONTEXT * ) DECLSPEC_NORETURN;
281     __wine_restore_regs( context );
282 }
283
284
285 /***********************************************************************
286  *           copy_context
287  *
288  * Copy a register context according to the flags.
289  */
290 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
291 {
292     flags &= ~CONTEXT_AMD64;  /* get rid of CPU id */
293     if (flags & CONTEXT_CONTROL)
294     {
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;
302     }
303     if (flags & CONTEXT_INTEGER)
304     {
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;
319     }
320     if (flags & CONTEXT_SEGMENTS)
321     {
322         to->SegDs = from->SegDs;
323         to->SegEs = from->SegEs;
324         to->SegFs = from->SegFs;
325         to->SegGs = from->SegGs;
326     }
327     if (flags & CONTEXT_FLOATING_POINT)
328     {
329         to->u.FltSave = from->u.FltSave;
330     }
331     if (flags & CONTEXT_DEBUG_REGISTERS)
332     {
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;
339     }
340 }
341
342
343 /***********************************************************************
344  *           context_to_server
345  *
346  * Convert a register context to the server format.
347  */
348 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
349 {
350     DWORD flags = from->ContextFlags & ~CONTEXT_AMD64;  /* get rid of CPU id */
351
352     memset( to, 0, sizeof(*to) );
353     to->cpu = CPU_x86_64;
354
355     if (flags & CONTEXT_CONTROL)
356     {
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;
365     }
366     if (flags & CONTEXT_INTEGER)
367     {
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;
383     }
384     if (flags & CONTEXT_SEGMENTS)
385     {
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;
391     }
392     if (flags & CONTEXT_FLOATING_POINT)
393     {
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) );
396     }
397     if (flags & CONTEXT_DEBUG_REGISTERS)
398     {
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;
406     }
407     return STATUS_SUCCESS;
408 }
409
410
411 /***********************************************************************
412  *           context_from_server
413  *
414  * Convert a register context from the server format.
415  */
416 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
417 {
418     if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER;
419
420     to->ContextFlags = CONTEXT_AMD64;
421     if (from->flags & SERVER_CTX_CONTROL)
422     {
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;
431     }
432
433     if (from->flags & SERVER_CTX_INTEGER)
434     {
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;
450     }
451     if (from->flags & SERVER_CTX_SEGMENTS)
452     {
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;
458     }
459     if (from->flags & SERVER_CTX_FLOATING_POINT)
460     {
461         to->ContextFlags |= CONTEXT_FLOATING_POINT;
462         memcpy( &to->u.FltSave, from->fp.x86_64_regs.fpregs, sizeof(from->fp.x86_64_regs.fpregs) );
463     }
464     if (from->flags & SERVER_CTX_DEBUG_REGISTERS)
465     {
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;
473     }
474     return STATUS_SUCCESS;
475 }
476
477
478 /**********************************************************************
479  *           call_stack_handlers
480  *
481  * Call the stack handlers chain.
482  */
483 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
484 {
485     EXCEPTION_POINTERS ptrs;
486
487     FIXME( "not implemented on x86_64\n" );
488
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;
494 }
495
496
497 /*******************************************************************
498  *              raise_exception
499  *
500  * Implementation of NtRaiseException.
501  */
502 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
503 {
504     NTSTATUS status;
505
506     if (first_chance)
507     {
508         DWORD c;
509
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)
516         {
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] );
525         }
526         else
527         {
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 );
536         }
537         status = send_debug_event( rec, TRUE, context );
538         if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
539             return STATUS_SUCCESS;
540
541         if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
542             return STATUS_SUCCESS;
543
544         if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
545             return status;
546     }
547
548     /* last chance exception */
549
550     status = send_debug_event( rec, FALSE, context );
551     if (status != DBG_CONTINUE)
552     {
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 );
561     }
562     return STATUS_SUCCESS;
563 }
564
565
566 /**********************************************************************
567  *              segv_handler
568  *
569  * Handler for SIGSEGV and related errors.
570  */
571 static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
572 {
573     EXCEPTION_RECORD rec;
574     CONTEXT context;
575     NTSTATUS status;
576     ucontext_t *ucontext = sigcontext;
577
578     save_context( &context, ucontext );
579
580     rec.ExceptionRecord  = NULL;
581     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
582     rec.ExceptionAddress = (LPVOID)context.Rip;
583     rec.NumberParameters = 0;
584
585     switch(TRAP_sig(ucontext))
586     {
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;
627     }
628
629     status = raise_exception( &rec, &context, TRUE );
630     if (status) raise_status( status, &rec );
631 done:
632     restore_context( &context, ucontext );
633 }
634
635 /**********************************************************************
636  *              trap_handler
637  *
638  * Handler for SIGTRAP.
639  */
640 static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
641 {
642     EXCEPTION_RECORD rec;
643     CONTEXT context;
644     NTSTATUS status;
645     ucontext_t *ucontext = sigcontext;
646
647     save_context( &context, ucontext );
648     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
649     rec.ExceptionRecord  = NULL;
650     rec.ExceptionAddress = (LPVOID)context.Rip;
651     rec.NumberParameters = 0;
652
653     switch (siginfo->si_code)
654     {
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;
665     }
666
667     status = raise_exception( &rec, &context, TRUE );
668     if (status) raise_status( status, &rec );
669     restore_context( &context, ucontext );
670 }
671
672 /**********************************************************************
673  *              fpe_handler
674  *
675  * Handler for SIGFPE.
676  */
677 static void fpe_handler( int signal, siginfo_t *siginfo, void *ucontext )
678 {
679     EXCEPTION_RECORD rec;
680     CONTEXT context;
681     NTSTATUS status;
682
683     save_context( &context, ucontext );
684     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
685     rec.ExceptionRecord  = NULL;
686     rec.ExceptionAddress = (LPVOID)context.Rip;
687     rec.NumberParameters = 0;
688
689     switch (siginfo->si_code)
690     {
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;
716     }
717
718     status = raise_exception( &rec, &context, TRUE );
719     if (status) raise_status( status, &rec );
720     restore_context( &context, ucontext );
721 }
722
723 /**********************************************************************
724  *              int_handler
725  *
726  * Handler for SIGINT.
727  */
728 static void int_handler( int signal, siginfo_t *siginfo, void *ucontext )
729 {
730     if (!dispatch_signal(SIGINT))
731     {
732         EXCEPTION_RECORD rec;
733         CONTEXT context;
734         NTSTATUS status;
735
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 );
745     }
746 }
747
748
749 /**********************************************************************
750  *              abrt_handler
751  *
752  * Handler for SIGABRT.
753  */
754 static void abrt_handler( int signal, siginfo_t *siginfo, void *ucontext )
755 {
756     EXCEPTION_RECORD rec;
757     CONTEXT context;
758     NTSTATUS status;
759
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 );
769 }
770
771
772 /**********************************************************************
773  *              quit_handler
774  *
775  * Handler for SIGQUIT.
776  */
777 static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext )
778 {
779     abort_thread(0);
780 }
781
782
783 /**********************************************************************
784  *              usr1_handler
785  *
786  * Handler for SIGUSR1, used to signal a thread that it got suspended.
787  */
788 static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
789 {
790     CONTEXT context;
791
792     save_context( &context, ucontext );
793     wait_suspend( &context );
794     restore_context( &context, ucontext );
795 }
796
797
798 /**********************************************************************
799  *              get_signal_stack_total_size
800  *
801  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
802  * Must be a power of two.
803  */
804 size_t get_signal_stack_total_size(void)
805 {
806     assert( sizeof(TEB) <= 2*getpagesize() );
807     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
808 }
809
810
811 /***********************************************************************
812  *           __wine_set_signal_handler   (NTDLL.@)
813  */
814 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
815 {
816     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
817     if (handlers[sig] != NULL) return -2;
818     handlers[sig] = wsh;
819     return 0;
820 }
821
822
823 /**********************************************************************
824  *              signal_init_thread
825  */
826 void signal_init_thread( TEB *teb )
827 {
828 #ifdef __linux__
829     arch_prctl( ARCH_SET_GS, teb );
830 #else
831 # error Please define setting %gs for your architecture
832 #endif
833 }
834
835 /**********************************************************************
836  *              signal_init_process
837  */
838 void signal_init_process(void)
839 {
840     struct sigaction sig_act;
841
842     sig_act.sa_mask = server_block_set;
843     sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
844
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;
855
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
862
863 #ifdef SIGTRAP
864     sig_act.sa_sigaction = trap_handler;
865     if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
866 #endif
867     return;
868
869  error:
870     perror("sigaction");
871     exit(1);
872 }
873
874
875 /**********************************************************************
876  *              RtlLookupFunctionEntry   (NTDLL.@)
877  */
878 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
879                                                  UNWIND_HISTORY_TABLE *table )
880 {
881     FIXME("stub\n");
882     return NULL;
883 }
884
885
886 /**********************************************************************
887  *              RtlVirtualUnwind   (NTDLL.@)
888  */
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 )
893 {
894     FIXME("stub\n");
895     return NULL;
896 }
897
898
899 /*******************************************************************
900  *              RtlUnwind (NTDLL.@)
901  */
902 void WINAPI __regs_RtlUnwind( EXCEPTION_REGISTRATION_RECORD* pEndFrame, PVOID targetIp,
903                               PEXCEPTION_RECORD pRecord, PVOID retval, CONTEXT *context )
904 {
905     EXCEPTION_RECORD record;
906
907     /* build an exception record, if we do not have one */
908     if (!pRecord)
909     {
910         record.ExceptionCode    = STATUS_UNWIND;
911         record.ExceptionFlags   = 0;
912         record.ExceptionRecord  = NULL;
913         record.ExceptionAddress = (void *)context->Rip;
914         record.NumberParameters = 0;
915         pRecord = &record;
916     }
917
918     pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND);
919
920     FIXME( "code=%x flags=%x not implemented on x86_64\n",
921            pRecord->ExceptionCode, pRecord->ExceptionFlags );
922     NtTerminateProcess( GetCurrentProcess(), 1 );
923 }
924 DEFINE_REGS_ENTRYPOINT( RtlUnwind, 4 )
925
926
927 /*******************************************************************
928  *              NtRaiseException (NTDLL.@)
929  */
930 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
931 {
932     NTSTATUS status = raise_exception( rec, context, first_chance );
933     if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
934     return status;
935 }
936
937
938 /***********************************************************************
939  *              RtlRaiseException (NTDLL.@)
940  */
941 void WINAPI __regs_RtlRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
942 {
943     NTSTATUS status;
944
945     rec->ExceptionAddress = (void *)context->Rip;
946     status = raise_exception( rec, context, TRUE );
947     if (status != STATUS_SUCCESS) raise_status( status, rec );
948 }
949 DEFINE_REGS_ENTRYPOINT( RtlRaiseException, 1 )
950
951
952 /**********************************************************************
953  *              __wine_enter_vm86   (NTDLL.@)
954  */
955 void __wine_enter_vm86( CONTEXT *context )
956 {
957     MESSAGE("vm86 mode not supported on this platform\n");
958 }
959
960 /**********************************************************************
961  *              DbgBreakPoint   (NTDLL.@)
962  */
963 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
964
965 /**********************************************************************
966  *              DbgUserBreakPoint   (NTDLL.@)
967  */
968 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
969
970 #endif  /* __x86_64__ */