Add support for WM_WINDOWPOSCHANGED to save new origin of window.
[wine] / dlls / ntdll / signal_sparc.c
1 /*
2  * Sparc signal handling routines
3  * 
4  * Copyright 1999 Ulrich Weigand
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #ifdef __sparc__
22
23 #include "config.h"
24
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <sys/ucontext.h>
30
31 #include "ntddk.h"
32 #include "winbase.h"
33 #include "winnt.h"
34
35 #include "wine/exception.h"
36 #include "global.h"
37 #include "stackframe.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(seh);
42
43 static sigset_t all_sigs;
44
45 /*
46  * FIXME:  All this works only on Solaris for now
47  */
48
49 /**********************************************************************
50  *              save_context
51  */
52 static void save_context( CONTEXT *context, ucontext_t *ucontext )
53 {
54     /* Special registers */
55     context->psr = ucontext->uc_mcontext.gregs[REG_PSR];
56     context->pc  = ucontext->uc_mcontext.gregs[REG_PC];
57     context->npc = ucontext->uc_mcontext.gregs[REG_nPC];
58     context->y   = ucontext->uc_mcontext.gregs[REG_Y];
59     context->wim = 0;  /* FIXME */
60     context->tbr = 0;  /* FIXME */
61
62     /* Global registers */
63     context->g0 = 0;  /* always */
64     context->g1 = ucontext->uc_mcontext.gregs[REG_G1];
65     context->g2 = ucontext->uc_mcontext.gregs[REG_G2];
66     context->g3 = ucontext->uc_mcontext.gregs[REG_G3];
67     context->g4 = ucontext->uc_mcontext.gregs[REG_G4];
68     context->g5 = ucontext->uc_mcontext.gregs[REG_G5];
69     context->g6 = ucontext->uc_mcontext.gregs[REG_G6];
70     context->g7 = ucontext->uc_mcontext.gregs[REG_G7];
71
72     /* Current 'out' registers */
73     context->o0 = ucontext->uc_mcontext.gregs[REG_O0];
74     context->o1 = ucontext->uc_mcontext.gregs[REG_O1];
75     context->o2 = ucontext->uc_mcontext.gregs[REG_O2];
76     context->o3 = ucontext->uc_mcontext.gregs[REG_O3];
77     context->o4 = ucontext->uc_mcontext.gregs[REG_O4];
78     context->o5 = ucontext->uc_mcontext.gregs[REG_O5];
79     context->o6 = ucontext->uc_mcontext.gregs[REG_O6];
80     context->o7 = ucontext->uc_mcontext.gregs[REG_O7];
81
82     /* FIXME: what if the current register window isn't saved? */
83     if ( ucontext->uc_mcontext.gwins && ucontext->uc_mcontext.gwins->wbcnt > 0 )
84     {
85         /* Current 'local' registers from first register window */
86         context->l0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[0];
87         context->l1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[1];
88         context->l2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[2];
89         context->l3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[3];
90         context->l4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[4];
91         context->l5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[5];
92         context->l6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[6];
93         context->l7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_local[7];
94
95         /* Current 'in' registers from first register window */
96         context->i0 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[0];
97         context->i1 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[1];
98         context->i2 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[2];
99         context->i3 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[3];
100         context->i4 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[4];
101         context->i5 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[5];
102         context->i6 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[6];
103         context->i7 = ucontext->uc_mcontext.gwins->wbuf[0].rw_in[7];
104     }
105 }
106
107 /**********************************************************************
108  *              restore_context
109  */
110 static void restore_context( CONTEXT *context, ucontext_t *ucontext )
111 {
112    /* FIXME */
113 }
114
115 /**********************************************************************
116  *              save_fpu
117  */
118 static void save_fpu( CONTEXT *context, ucontext_t *ucontext )
119 {
120    /* FIXME */
121 }
122
123 /**********************************************************************
124  *              restore_fpu
125  */
126 static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
127 {
128    /* FIXME */
129 }
130
131
132 /**********************************************************************
133  *              segv_handler
134  *
135  * Handler for SIGSEGV.
136  */
137 static void segv_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
138 {
139     EXCEPTION_RECORD rec;
140     CONTEXT context;
141
142     /* we want the page-fault case to be fast */
143     if ( info->si_code == SEGV_ACCERR )
144         if (VIRTUAL_HandleFault( (LPVOID)info->si_addr )) return;
145
146     save_context( &context, ucontext );
147     rec.ExceptionCode    = EXCEPTION_ACCESS_VIOLATION;
148     rec.ExceptionRecord  = NULL;
149     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
150     rec.ExceptionAddress = (LPVOID)context.pc;
151     rec.NumberParameters = 2;
152     rec.ExceptionInformation[0] = 0;  /* FIXME: read/write access ? */
153     rec.ExceptionInformation[1] = (DWORD)info->si_addr;
154     
155     EXC_RtlRaiseException( &rec, &context );
156     restore_context( &context, ucontext );
157 }
158
159 /**********************************************************************
160  *              bus_handler
161  *
162  * Handler for SIGBUS.
163  */
164 static void bus_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
165 {
166     EXCEPTION_RECORD rec;
167     CONTEXT context;
168
169     save_context( &context, ucontext );
170     rec.ExceptionRecord  = NULL;
171     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
172     rec.ExceptionAddress = (LPVOID)context.pc;
173     rec.NumberParameters = 0;
174
175     if ( info->si_code == BUS_ADRALN )
176         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
177     else
178         rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
179     
180     EXC_RtlRaiseException( &rec, &context );
181     restore_context( &context, ucontext );
182 }
183
184 /**********************************************************************
185  *              ill_handler
186  *
187  * Handler for SIGILL.
188  */
189 static void ill_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
190 {
191     EXCEPTION_RECORD rec;
192     CONTEXT context;
193
194     switch ( info->si_code )
195     {
196     default:
197     case ILL_ILLOPC:
198     case ILL_ILLOPN:
199     case ILL_ILLADR:
200     case ILL_ILLTRP:
201         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
202         break;
203
204     case ILL_PRVOPC:
205     case ILL_PRVREG:
206         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
207         break;
208
209     case ILL_BADSTK:
210         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
211         break;
212     }
213     
214     save_context( &context, ucontext );
215     rec.ExceptionRecord  = NULL;
216     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
217     rec.ExceptionAddress = (LPVOID)context.pc;
218     rec.NumberParameters = 0;
219     EXC_RtlRaiseException( &rec, &context );
220     restore_context( &context, ucontext );
221 }
222
223
224 /**********************************************************************
225  *              trap_handler
226  *
227  * Handler for SIGTRAP.
228  */
229 static void trap_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
230 {
231     EXCEPTION_RECORD rec;
232     CONTEXT context;
233
234     switch ( info->si_code )
235     {
236     case TRAP_TRACE:
237         rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
238         break;
239     case TRAP_BRKPT:
240     default:
241         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
242         break;
243     }
244
245     save_context( &context, ucontext );
246     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
247     rec.ExceptionRecord  = NULL;
248     rec.ExceptionAddress = (LPVOID)context.pc;
249     rec.NumberParameters = 0;
250     EXC_RtlRaiseException( &rec, &context );
251     restore_context( &context, ucontext );
252 }
253
254
255 /**********************************************************************
256  *              fpe_handler
257  *
258  * Handler for SIGFPE.
259  */
260 static void fpe_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
261 {
262     EXCEPTION_RECORD rec;
263     CONTEXT context;
264
265     switch ( info->si_code )
266     {
267     case FPE_FLTSUB:
268         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
269         break;
270     case FPE_INTDIV:
271         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
272         break;
273     case FPE_INTOVF:
274         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
275         break;
276     case FPE_FLTDIV:
277         rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
278         break;
279     case FPE_FLTOVF:
280         rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
281         break;
282     case FPE_FLTUND:
283         rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
284         break;
285     case FPE_FLTRES:
286         rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
287         break;
288     case FPE_FLTINV:
289     default:
290         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
291         break;
292     }
293
294     save_context( &context, ucontext );
295     save_fpu( &context, ucontext );
296     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
297     rec.ExceptionRecord  = NULL;
298     rec.ExceptionAddress = (LPVOID)context.pc;
299     rec.NumberParameters = 0;
300     EXC_RtlRaiseException( &rec, &context );
301     restore_context( &context, ucontext );
302     restore_fpu( &context, ucontext );
303 }
304
305
306 /**********************************************************************
307  *              int_handler
308  *
309  * Handler for SIGINT.
310  */
311 static void int_handler( int signal, siginfo_t *info, ucontext_t *ucontext )
312 {
313     EXCEPTION_RECORD rec;
314     CONTEXT context;
315
316     save_context( &context, ucontext );
317     rec.ExceptionCode    = CONTROL_C_EXIT;
318     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
319     rec.ExceptionRecord  = NULL;
320     rec.ExceptionAddress = (LPVOID)context.pc;
321     rec.NumberParameters = 0;
322     EXC_RtlRaiseException( &rec, &context );
323     restore_context( &context, ucontext );
324 }
325
326
327 /***********************************************************************
328  *           set_handler
329  *
330  * Set a signal handler
331  */
332 static int set_handler( int sig, void (*func)() )
333 {
334     struct sigaction sig_act;
335
336     sig_act.sa_handler = NULL;
337     sig_act.sa_sigaction = func;
338     sigemptyset( &sig_act.sa_mask );
339     sig_act.sa_flags = SA_SIGINFO;
340
341     return sigaction( sig, &sig_act, NULL );
342 }
343
344
345 /***********************************************************************
346  *           SIGNAL_Unblock
347  *
348  * Unblock signals. Called from EXC_RtlRaiseException.
349  */
350 void SIGNAL_Unblock( void )
351 {
352     sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
353 }
354
355
356 /**********************************************************************
357  *              SIGNAL_Init
358  */
359 BOOL SIGNAL_Init(void)
360 {
361     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
362     signal( SIGPIPE, SIG_IGN );
363     /* automatic child reaping to avoid zombies */
364     signal( SIGCHLD, SIG_IGN );
365
366     sigfillset( &all_sigs );
367
368     if (set_handler( SIGINT,  (void (*)())int_handler  ) == -1) goto error;
369     if (set_handler( SIGFPE,  (void (*)())fpe_handler  ) == -1) goto error;
370     if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
371     if (set_handler( SIGILL,  (void (*)())ill_handler  ) == -1) goto error;
372     if (set_handler( SIGBUS,  (void (*)())bus_handler  ) == -1) goto error;
373     if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
374     return TRUE;
375
376  error:
377     perror("sigaction");
378     return FALSE;
379 }
380
381
382 /**********************************************************************
383  *              SIGNAL_Reset
384  */
385 void SIGNAL_Reset(void)
386 {
387     sigset_t block_set;
388
389     /* block the async signals */
390     sigemptyset( &block_set );
391     sigaddset( &block_set, SIGALRM );
392     sigaddset( &block_set, SIGIO );
393     sigaddset( &block_set, SIGHUP );
394     sigaddset( &block_set, SIGUSR2 );
395     sigprocmask( SIG_BLOCK, &block_set, NULL );
396
397     /* restore default handlers */
398     signal( SIGINT, SIG_DFL );
399     signal( SIGFPE, SIG_DFL );
400     signal( SIGSEGV, SIG_DFL );
401     signal( SIGILL, SIG_DFL );
402     signal( SIGBUS, SIG_DFL );
403     signal( SIGTRAP, SIG_DFL );
404 }
405
406
407 /**********************************************************************
408  *              __wine_enter_vm86
409  */
410 void __wine_enter_vm86( CONTEXT *context )
411 {
412     MESSAGE("vm86 mode not supported on this platform\n");
413 }
414
415 /**********************************************************************
416  *              DbgBreakPoint   (NTDLL.@)
417  */
418 void WINAPI DbgBreakPoint(void)
419 {
420     /* FIXME */
421 }
422
423 /**********************************************************************
424  *              DbgUserBreakPoint   (NTDLL.@)
425  */
426 void WINAPI DbgUserBreakPoint(void)
427 {
428     /* FIXME */
429 }
430
431 #endif  /* __sparc__ */