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