comdlg32: Update the original dialog structure rather than a temporary copy.
[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 "windef.h"
44 #include "winternl.h"
45 #include "wine/library.h"
46 #include "wine/exception.h"
47 #include "ntdll_misc.h"
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(seh);
51
52
53 /***********************************************************************
54  * signal context platform-specific definitions
55  */
56 #ifdef linux
57
58 typedef struct ucontext SIGCONTEXT;
59
60 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
61 # define HANDLER_CONTEXT (__context)
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 #define FAULT_CODE     (__siginfo->si_code)
92 #define FAULT_ADDRESS  (__siginfo->si_addr)
93
94 #endif /* linux */
95
96 enum i386_trap_code
97 {
98     TRAP_x86_UNKNOWN    = -1,  /* Unknown fault (TRAP_sig not defined) */
99     TRAP_x86_DIVIDE     = 0,   /* Division by zero exception */
100     TRAP_x86_TRCTRAP    = 1,   /* Single-step exception */
101     TRAP_x86_NMI        = 2,   /* NMI interrupt */
102     TRAP_x86_BPTFLT     = 3,   /* Breakpoint exception */
103     TRAP_x86_OFLOW      = 4,   /* Overflow exception */
104     TRAP_x86_BOUND      = 5,   /* Bound range exception */
105     TRAP_x86_PRIVINFLT  = 6,   /* Invalid opcode exception */
106     TRAP_x86_DNA        = 7,   /* Device not available exception */
107     TRAP_x86_DOUBLEFLT  = 8,   /* Double fault exception */
108     TRAP_x86_FPOPFLT    = 9,   /* Coprocessor segment overrun */
109     TRAP_x86_TSSFLT     = 10,  /* Invalid TSS exception */
110     TRAP_x86_SEGNPFLT   = 11,  /* Segment not present exception */
111     TRAP_x86_STKFLT     = 12,  /* Stack fault */
112     TRAP_x86_PROTFLT    = 13,  /* General protection fault */
113     TRAP_x86_PAGEFLT    = 14,  /* Page fault */
114     TRAP_x86_ARITHTRAP  = 16,  /* Floating point exception */
115     TRAP_x86_ALIGNFLT   = 17,  /* Alignment check exception */
116     TRAP_x86_MCHK       = 18,  /* Machine check exception */
117     TRAP_x86_CACHEFLT   = 19   /* Cache flush exception */
118 };
119
120 typedef int (*wine_signal_handler)(unsigned int sig);
121
122 static wine_signal_handler handlers[256];
123
124 /***********************************************************************
125  *           dispatch_signal
126  */
127 static inline int dispatch_signal(unsigned int sig)
128 {
129     if (handlers[sig] == NULL) return 0;
130     return handlers[sig](sig);
131 }
132
133 /***********************************************************************
134  *           save_context
135  *
136  * Set the register values from a sigcontext.
137  */
138 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
139 {
140     context->Rax    = RAX_sig(sigcontext);
141     context->Rcx    = RCX_sig(sigcontext);
142     context->Rdx    = RDX_sig(sigcontext);
143     context->Rbx    = RBX_sig(sigcontext);
144     context->Rsp    = RSP_sig(sigcontext);
145     context->Rbp    = RBP_sig(sigcontext);
146     context->Rsi    = RSI_sig(sigcontext);
147     context->Rdi    = RDI_sig(sigcontext);
148     context->R8     = R8_sig(sigcontext);
149     context->R9     = R9_sig(sigcontext);
150     context->R10    = R10_sig(sigcontext);
151     context->R11    = R11_sig(sigcontext);
152     context->R12    = R12_sig(sigcontext);
153     context->R13    = R13_sig(sigcontext);
154     context->R14    = R14_sig(sigcontext);
155     context->R15    = R15_sig(sigcontext);
156     context->Rip    = RIP_sig(sigcontext);
157     context->SegCs  = CS_sig(sigcontext);
158     context->SegFs  = FS_sig(sigcontext);
159     context->SegGs  = GS_sig(sigcontext);
160     context->EFlags = EFL_sig(sigcontext);
161     context->SegDs  = 0;  /* FIXME */
162     context->SegEs  = 0;  /* FIXME */
163     context->SegSs  = 0;  /* FIXME */
164     context->MxCsr  = 0;  /* FIXME */
165     if (FPU_sig(sigcontext)) context->u.FltSave = *FPU_sig(sigcontext);
166 }
167
168
169 /***********************************************************************
170  *           restore_context
171  *
172  * Build a sigcontext from the register values.
173  */
174 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
175 {
176     RAX_sig(sigcontext) = context->Rax;
177     RCX_sig(sigcontext) = context->Rcx;
178     RDX_sig(sigcontext) = context->Rdx;
179     RBX_sig(sigcontext) = context->Rbx;
180     RSP_sig(sigcontext) = context->Rsp;
181     RBP_sig(sigcontext) = context->Rbp;
182     RSI_sig(sigcontext) = context->Rsi;
183     RDI_sig(sigcontext) = context->Rdi;
184     R8_sig(sigcontext)  = context->R8;
185     R9_sig(sigcontext)  = context->R9;
186     R10_sig(sigcontext) = context->R10;
187     R11_sig(sigcontext) = context->R11;
188     R12_sig(sigcontext) = context->R12;
189     R13_sig(sigcontext) = context->R13;
190     R14_sig(sigcontext) = context->R14;
191     R15_sig(sigcontext) = context->R15;
192     RIP_sig(sigcontext) = context->Rip;
193     CS_sig(sigcontext)  = context->SegCs;
194     FS_sig(sigcontext)  = context->SegFs;
195     GS_sig(sigcontext)  = context->SegGs;
196     EFL_sig(sigcontext) = context->EFlags;
197     if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
198 }
199
200
201 /***********************************************************************
202  *              RtlCaptureContext (NTDLL.@)
203  */
204 void WINAPI __regs_RtlCaptureContext( CONTEXT *context, CONTEXT *regs )
205 {
206     *context = *regs;
207 }
208 DEFINE_REGS_ENTRYPOINT( RtlCaptureContext, 1 )
209
210
211 /***********************************************************************
212  *           set_cpu_context
213  *
214  * Set the new CPU context.
215  */
216 void set_cpu_context( const CONTEXT *context )
217 {
218     FIXME("not implemented\n");
219 }
220
221
222 /**********************************************************************
223  *              segv_handler
224  *
225  * Handler for SIGSEGV and related errors.
226  */
227 static HANDLER_DEF(segv_handler)
228 {
229     EXCEPTION_RECORD rec;
230     CONTEXT context;
231
232     save_context( &context, HANDLER_CONTEXT );
233
234     rec.ExceptionRecord  = NULL;
235     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
236     rec.ExceptionAddress = (LPVOID)context.Rip;
237     rec.NumberParameters = 0;
238
239     switch(TRAP_sig(HANDLER_CONTEXT))
240     {
241     case TRAP_x86_OFLOW:   /* Overflow exception */
242         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
243         break;
244     case TRAP_x86_BOUND:   /* Bound range exception */
245         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
246         break;
247     case TRAP_x86_PRIVINFLT:   /* Invalid opcode exception */
248         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
249         break;
250     case TRAP_x86_STKFLT:  /* Stack fault */
251         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
252         break;
253     case TRAP_x86_SEGNPFLT:  /* Segment not present exception */
254     case TRAP_x86_PROTFLT:   /* General protection fault */
255     case TRAP_x86_UNKNOWN:   /* Unknown fault code */
256         rec.ExceptionCode = ERROR_sig(HANDLER_CONTEXT) ? EXCEPTION_ACCESS_VIOLATION
257                                                        : EXCEPTION_PRIV_INSTRUCTION;
258         break;
259     case TRAP_x86_PAGEFLT:  /* Page fault */
260         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
261 #ifdef FAULT_ADDRESS
262         rec.NumberParameters = 2;
263         rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
264         rec.ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS;
265         if (!(rec.ExceptionCode = virtual_handle_fault( FAULT_ADDRESS, rec.ExceptionInformation[0] )))
266             goto done;
267 #endif
268         break;
269     case TRAP_x86_ALIGNFLT:  /* Alignment check exception */
270         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
271         break;
272     default:
273         ERR( "Got unexpected trap %ld\n", TRAP_sig(HANDLER_CONTEXT) );
274         /* fall through */
275     case TRAP_x86_NMI:       /* NMI interrupt */
276     case TRAP_x86_DNA:       /* Device not available exception */
277     case TRAP_x86_DOUBLEFLT: /* Double fault exception */
278     case TRAP_x86_TSSFLT:    /* Invalid TSS exception */
279     case TRAP_x86_MCHK:      /* Machine check exception */
280     case TRAP_x86_CACHEFLT:  /* Cache flush exception */
281         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
282         break;
283     }
284
285     __regs_RtlRaiseException( &rec, &context );
286 done:
287     restore_context( &context, HANDLER_CONTEXT );
288 }
289
290 /**********************************************************************
291  *              trap_handler
292  *
293  * Handler for SIGTRAP.
294  */
295 static HANDLER_DEF(trap_handler)
296 {
297     EXCEPTION_RECORD rec;
298     CONTEXT context;
299
300     save_context( &context, HANDLER_CONTEXT );
301     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
302     rec.ExceptionRecord  = NULL;
303     rec.ExceptionAddress = (LPVOID)context.Rip;
304     rec.NumberParameters = 0;
305
306     switch(FAULT_CODE)
307     {
308     case TRAP_TRACE:  /* Single-step exception */
309         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
310         EFL_sig(HANDLER_CONTEXT) &= ~0x100;  /* clear single-step flag */
311         break;
312     case TRAP_BRKPT:   /* Breakpoint exception */
313         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
314         /* fall through */
315     default:
316         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
317         break;
318     }
319
320     __regs_RtlRaiseException( &rec, &context );
321     restore_context( &context, HANDLER_CONTEXT );
322 }
323
324 /**********************************************************************
325  *              fpe_handler
326  *
327  * Handler for SIGFPE.
328  */
329 static HANDLER_DEF(fpe_handler)
330 {
331     EXCEPTION_RECORD rec;
332     CONTEXT context;
333
334     save_context( &context, HANDLER_CONTEXT );
335     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
336     rec.ExceptionRecord  = NULL;
337     rec.ExceptionAddress = (LPVOID)context.Rip;
338     rec.NumberParameters = 0;
339
340     switch (FAULT_CODE)
341     {
342     case FPE_FLTSUB:
343         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
344         break;
345     case FPE_INTDIV:
346         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
347         break;
348     case FPE_INTOVF:
349         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
350         break;
351     case FPE_FLTDIV:
352         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
353         break;
354     case FPE_FLTOVF:
355         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
356         break;
357     case FPE_FLTUND:
358         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
359         break;
360     case FPE_FLTRES:
361         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
362         break;
363     case FPE_FLTINV:
364     default:
365         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
366         break;
367     }
368
369     __regs_RtlRaiseException( &rec, &context );
370     restore_context( &context, HANDLER_CONTEXT );
371 }
372
373 /**********************************************************************
374  *              int_handler
375  *
376  * Handler for SIGINT.
377  */
378 static HANDLER_DEF(int_handler)
379 {
380     if (!dispatch_signal(SIGINT))
381     {
382         EXCEPTION_RECORD rec;
383         CONTEXT context;
384
385         save_context( &context, HANDLER_CONTEXT );
386         rec.ExceptionCode    = CONTROL_C_EXIT;
387         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
388         rec.ExceptionRecord  = NULL;
389         rec.ExceptionAddress = (LPVOID)context.Rip;
390         rec.NumberParameters = 0;
391         __regs_RtlRaiseException( &rec, &context );
392         restore_context( &context, HANDLER_CONTEXT );
393     }
394 }
395
396
397 /**********************************************************************
398  *              abrt_handler
399  *
400  * Handler for SIGABRT.
401  */
402 static HANDLER_DEF(abrt_handler)
403 {
404     EXCEPTION_RECORD rec;
405     CONTEXT context;
406
407     save_context( &context, HANDLER_CONTEXT );
408     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
409     rec.ExceptionFlags   = EH_NONCONTINUABLE;
410     rec.ExceptionRecord  = NULL;
411     rec.ExceptionAddress = (LPVOID)context.Rip;
412     rec.NumberParameters = 0;
413     __regs_RtlRaiseException( &rec, &context ); /* Should never return.. */
414     restore_context( &context, HANDLER_CONTEXT );
415 }
416
417
418 /**********************************************************************
419  *              quit_handler
420  *
421  * Handler for SIGQUIT.
422  */
423 static HANDLER_DEF(quit_handler)
424 {
425     server_abort_thread(0);
426 }
427
428
429 /**********************************************************************
430  *              usr1_handler
431  *
432  * Handler for SIGUSR1, used to signal a thread that it got suspended.
433  */
434 static HANDLER_DEF(usr1_handler)
435 {
436     CONTEXT context;
437
438     save_context( &context, HANDLER_CONTEXT );
439     wait_suspend( &context );
440     restore_context( &context, HANDLER_CONTEXT );
441 }
442
443
444 /**********************************************************************
445  *              get_signal_stack_total_size
446  *
447  * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
448  * Must be a power of two.
449  */
450 size_t get_signal_stack_total_size(void)
451 {
452     assert( sizeof(TEB) <= 2*getpagesize() );
453     return 2*getpagesize();  /* this is just for the TEB, we don't need a signal stack */
454 }
455
456
457 /***********************************************************************
458  *           set_handler
459  *
460  * Set a signal handler
461  */
462 static int set_handler( int sig, void (*func)() )
463 {
464     struct sigaction sig_act;
465
466     sig_act.sa_sigaction = func;
467     sig_act.sa_mask = server_block_set;
468     sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
469     return sigaction( sig, &sig_act, NULL );
470 }
471
472
473 /***********************************************************************
474  *           __wine_set_signal_handler   (NTDLL.@)
475  */
476 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
477 {
478     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
479     if (handlers[sig] != NULL) return -2;
480     handlers[sig] = wsh;
481     return 0;
482 }
483
484
485 /**********************************************************************
486  *              signal_init_thread
487  */
488 void signal_init_thread(void)
489 {
490 }
491
492 /**********************************************************************
493  *              signal_init_process
494  */
495 void signal_init_process(void)
496 {
497     if (set_handler( SIGINT,  (void (*)())int_handler ) == -1) goto error;
498     if (set_handler( SIGFPE,  (void (*)())fpe_handler ) == -1) goto error;
499     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
500     if (set_handler( SIGILL,  (void (*)())segv_handler ) == -1) goto error;
501     if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
502     if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
503     if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
504 #ifdef SIGBUS
505     if (set_handler( SIGBUS,  (void (*)())segv_handler ) == -1) goto error;
506 #endif
507 #ifdef SIGTRAP
508     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
509 #endif
510     signal_init_thread();
511     return;
512
513  error:
514     perror("sigaction");
515     exit(1);
516 }
517
518
519 /**********************************************************************
520  *              RtlLookupFunctionEntry   (NTDLL.@)
521  */
522 PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG64 pc, ULONG64 *base,
523                                                  UNWIND_HISTORY_TABLE *table )
524 {
525     FIXME("stub\n");
526     return NULL;
527 }
528
529
530 /**********************************************************************
531  *              RtlVirtualUnwind   (NTDLL.@)
532  */
533 PVOID WINAPI RtlVirtualUnwind ( ULONG type, ULONG64 base, ULONG64 pc,
534                                 RUNTIME_FUNCTION *function, CONTEXT *context,
535                                 PVOID *data, ULONG64 *frame,
536                                 KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
537 {
538     FIXME("stub\n");
539     return NULL;
540 }
541
542
543 /**********************************************************************
544  *              __wine_enter_vm86   (NTDLL.@)
545  */
546 void __wine_enter_vm86( CONTEXT *context )
547 {
548     MESSAGE("vm86 mode not supported on this platform\n");
549 }
550
551 /**********************************************************************
552  *              DbgBreakPoint   (NTDLL.@)
553  */
554 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret")
555
556 /**********************************************************************
557  *              DbgUserBreakPoint   (NTDLL.@)
558  */
559 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret")
560
561 #endif  /* __x86_64__ */