2 * Sparc signal handling routines
4 * Copyright 1999 Ulrich Weigand
16 #include <sys/ucontext.h>
18 #include "wine/exception.h"
22 #include "stackframe.h"
23 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(seh
)
29 * FIXME: All this works only on Solaris for now
32 /**********************************************************************
35 static void save_context( CONTEXT
*context
, ucontext_t
*ucontext
)
37 /* Special registers */
38 context
->psr
= ucontext
->uc_mcontext
.gregs
[REG_PSR
];
39 context
->pc
= ucontext
->uc_mcontext
.gregs
[REG_PC
];
40 context
->npc
= ucontext
->uc_mcontext
.gregs
[REG_nPC
];
41 context
->y
= ucontext
->uc_mcontext
.gregs
[REG_Y
];
42 context
->wim
= 0; /* FIXME */
43 context
->tbr
= 0; /* FIXME */
45 /* Global registers */
46 context
->g0
= 0; /* always */
47 context
->g1
= ucontext
->uc_mcontext
.gregs
[REG_G1
];
48 context
->g2
= ucontext
->uc_mcontext
.gregs
[REG_G2
];
49 context
->g3
= ucontext
->uc_mcontext
.gregs
[REG_G3
];
50 context
->g4
= ucontext
->uc_mcontext
.gregs
[REG_G4
];
51 context
->g5
= ucontext
->uc_mcontext
.gregs
[REG_G5
];
52 context
->g6
= ucontext
->uc_mcontext
.gregs
[REG_G6
];
53 context
->g7
= ucontext
->uc_mcontext
.gregs
[REG_G7
];
55 /* Current 'out' registers */
56 context
->o0
= ucontext
->uc_mcontext
.gregs
[REG_O0
];
57 context
->o1
= ucontext
->uc_mcontext
.gregs
[REG_O1
];
58 context
->o2
= ucontext
->uc_mcontext
.gregs
[REG_O2
];
59 context
->o3
= ucontext
->uc_mcontext
.gregs
[REG_O3
];
60 context
->o4
= ucontext
->uc_mcontext
.gregs
[REG_O4
];
61 context
->o5
= ucontext
->uc_mcontext
.gregs
[REG_O5
];
62 context
->o6
= ucontext
->uc_mcontext
.gregs
[REG_O6
];
63 context
->o7
= ucontext
->uc_mcontext
.gregs
[REG_O7
];
65 /* FIXME: what if the current register window isn't saved? */
66 if ( ucontext
->uc_mcontext
.gwins
&& ucontext
->uc_mcontext
.gwins
->wbcnt
> 0 )
68 /* Current 'local' registers from first register window */
69 context
->l0
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[0];
70 context
->l1
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[1];
71 context
->l2
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[2];
72 context
->l3
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[3];
73 context
->l4
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[4];
74 context
->l5
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[5];
75 context
->l6
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[6];
76 context
->l7
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_local
[7];
78 /* Current 'in' registers from first register window */
79 context
->i0
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[0];
80 context
->i1
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[1];
81 context
->i2
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[2];
82 context
->i3
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[3];
83 context
->i4
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[4];
84 context
->i5
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[5];
85 context
->i6
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[6];
86 context
->i7
= ucontext
->uc_mcontext
.gwins
->wbuf
[0].rw_in
[7];
90 /**********************************************************************
93 static void restore_context( CONTEXT
*context
, ucontext_t
*ucontext
)
98 /**********************************************************************
101 static void save_fpu( CONTEXT
*context
, ucontext_t
*ucontext
)
106 /**********************************************************************
109 static void restore_fpu( CONTEXT
*context
, ucontext_t
*ucontext
)
115 /**********************************************************************
118 * Handler for SIGSEGV.
120 static void segv_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
122 EXCEPTION_RECORD rec
;
125 /* we want the page-fault case to be fast */
126 if ( info
->si_code
== SEGV_ACCERR
)
127 if (VIRTUAL_HandleFault( (LPVOID
)info
->si_addr
)) return;
129 save_context( &context
, ucontext
);
130 rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
131 rec
.ExceptionRecord
= NULL
;
132 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
133 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
134 rec
.NumberParameters
= 2;
135 rec
.ExceptionInformation
[0] = 0; /* FIXME: read/write access ? */
136 rec
.ExceptionInformation
[1] = (DWORD
)info
->si_addr
;
138 EXC_RtlRaiseException( &rec
, &context
);
139 restore_context( &context
, ucontext
);
142 /**********************************************************************
145 * Handler for SIGBUS.
147 static void bus_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
149 EXCEPTION_RECORD rec
;
152 save_context( &context
, ucontext
);
153 rec
.ExceptionRecord
= NULL
;
154 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
155 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
156 rec
.NumberParameters
= 0;
158 if ( info
->si_code
== BUS_ADRALN
)
159 rec
.ExceptionCode
= EXCEPTION_DATATYPE_MISALIGNMENT
;
161 rec
.ExceptionCode
= EXCEPTION_ACCESS_VIOLATION
;
163 EXC_RtlRaiseException( &rec
, &context
);
164 restore_context( &context
, ucontext
);
167 /**********************************************************************
170 * Handler for SIGILL.
172 static void ill_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
174 EXCEPTION_RECORD rec
;
177 switch ( info
->si_code
)
184 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
189 rec
.ExceptionCode
= EXCEPTION_PRIV_INSTRUCTION
;
193 rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
197 save_context( &context
, ucontext
);
198 rec
.ExceptionRecord
= NULL
;
199 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
200 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
201 rec
.NumberParameters
= 0;
202 EXC_RtlRaiseException( &rec
, &context
);
203 restore_context( &context
, ucontext
);
207 /**********************************************************************
210 * Handler for SIGTRAP.
212 static void trap_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
214 EXCEPTION_RECORD rec
;
217 switch ( info
->si_code
)
220 rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
224 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
228 save_context( &context
, ucontext
);
229 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
230 rec
.ExceptionRecord
= NULL
;
231 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
232 rec
.NumberParameters
= 0;
233 EXC_RtlRaiseException( &rec
, &context
);
234 restore_context( &context
, ucontext
);
238 /**********************************************************************
241 * Handler for SIGFPE.
243 static void fpe_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
245 EXCEPTION_RECORD rec
;
248 switch ( info
->si_code
)
251 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
254 rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
257 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
260 rec
.ExceptionCode
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
263 rec
.ExceptionCode
= EXCEPTION_FLT_OVERFLOW
;
266 rec
.ExceptionCode
= EXCEPTION_FLT_UNDERFLOW
;
269 rec
.ExceptionCode
= EXCEPTION_FLT_INEXACT_RESULT
;
273 rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
277 save_context( &context
, ucontext
);
278 save_fpu( &context
, ucontext
);
279 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
280 rec
.ExceptionRecord
= NULL
;
281 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
282 rec
.NumberParameters
= 0;
283 EXC_RtlRaiseException( &rec
, &context
);
284 restore_context( &context
, ucontext
);
285 restore_fpu( &context
, ucontext
);
289 /**********************************************************************
292 * Handler for SIGINT.
294 static void int_handler( int signal
, siginfo_t
*info
, ucontext_t
*ucontext
)
296 EXCEPTION_RECORD rec
;
299 save_context( &context
, ucontext
);
300 rec
.ExceptionCode
= CONTROL_C_EXIT
;
301 rec
.ExceptionFlags
= EXCEPTION_CONTINUABLE
;
302 rec
.ExceptionRecord
= NULL
;
303 rec
.ExceptionAddress
= (LPVOID
)context
.pc
;
304 rec
.NumberParameters
= 0;
305 EXC_RtlRaiseException( &rec
, &context
);
306 restore_context( &context
, ucontext
);
310 /***********************************************************************
313 * Set a signal handler
315 static int set_handler( int sig
, void (*func
)() )
317 struct sigaction sig_act
;
319 sig_act
.sa_handler
= NULL
;
320 sig_act
.sa_sigaction
= func
;
321 sigemptyset( &sig_act
.sa_mask
);
322 sig_act
.sa_flags
= SA_SIGINFO
;
324 return sigaction( sig
, &sig_act
, NULL
);
328 /**********************************************************************
331 BOOL
SIGNAL_Init(void)
333 /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */
334 signal( SIGPIPE
, SIG_IGN
);
335 /* automatic child reaping to avoid zombies */
336 signal( SIGCHLD
, SIG_IGN
);
338 if (set_handler( SIGINT
, (void (*)())int_handler
) == -1) goto error
;
339 if (set_handler( SIGFPE
, (void (*)())fpe_handler
) == -1) goto error
;
340 if (set_handler( SIGSEGV
, (void (*)())segv_handler
) == -1) goto error
;
341 if (set_handler( SIGILL
, (void (*)())ill_handler
) == -1) goto error
;
342 if (set_handler( SIGBUS
, (void (*)())bus_handler
) == -1) goto error
;
343 if (set_handler( SIGTRAP
, (void (*)())trap_handler
) == -1) goto error
;
351 #endif /* __sparc__ */