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