ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.51
Committed: 2005-01-04T23:38:01Z (19 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.50: +26 -2 lines
Log Message:
Fixes for NetBSD 2.0

File Contents

# Content
1 /*
2 * sigsegv.cpp - SIGSEGV signals support
3 *
4 * Derived from Bruno Haible's work on his SIGSEGV library for clisp
5 * <http://clisp.sourceforge.net/>
6 *
7 * MacOS X support derived from the post by Timothy J. Wood to the
8 * omnigroup macosx-dev list:
9 * Mach Exception Handlers 101 (Was Re: ptrace, gdb)
10 * tjw@omnigroup.com Sun, 4 Jun 2000
11 * www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html
12 *
13 * Basilisk II (C) 1997-2004 Christian Bauer
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <list>
39 #include <stdio.h>
40 #include <signal.h>
41 #include "sigsegv.h"
42
43 #ifndef NO_STD_NAMESPACE
44 using std::list;
45 #endif
46
47 // Return value type of a signal handler (standard type if not defined)
48 #ifndef RETSIGTYPE
49 #define RETSIGTYPE void
50 #endif
51
52 // Type of the system signal handler
53 typedef RETSIGTYPE (*signal_handler)(int);
54
55 // User's SIGSEGV handler
56 static sigsegv_fault_handler_t sigsegv_fault_handler = 0;
57
58 // Function called to dump state if we can't handle the fault
59 static sigsegv_state_dumper_t sigsegv_state_dumper = 0;
60
61 // Actual SIGSEGV handler installer
62 static bool sigsegv_do_install_handler(int sig);
63
64
65 /*
66 * Instruction decoding aids
67 */
68
69 // Transfer size
70 enum transfer_size_t {
71 SIZE_UNKNOWN,
72 SIZE_BYTE,
73 SIZE_WORD, // 2 bytes
74 SIZE_LONG, // 4 bytes
75 SIZE_QUAD, // 8 bytes
76 };
77
78 // Transfer type
79 typedef sigsegv_transfer_type_t transfer_type_t;
80
81 #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
82 // Addressing mode
83 enum addressing_mode_t {
84 MODE_UNKNOWN,
85 MODE_NORM,
86 MODE_U,
87 MODE_X,
88 MODE_UX
89 };
90
91 // Decoded instruction
92 struct instruction_t {
93 transfer_type_t transfer_type;
94 transfer_size_t transfer_size;
95 addressing_mode_t addr_mode;
96 unsigned int addr;
97 char ra, rd;
98 };
99
100 static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned long * gpr)
101 {
102 // Get opcode and divide into fields
103 unsigned int opcode = *((unsigned int *)(unsigned long)nip);
104 unsigned int primop = opcode >> 26;
105 unsigned int exop = (opcode >> 1) & 0x3ff;
106 unsigned int ra = (opcode >> 16) & 0x1f;
107 unsigned int rb = (opcode >> 11) & 0x1f;
108 unsigned int rd = (opcode >> 21) & 0x1f;
109 signed int imm = (signed short)(opcode & 0xffff);
110
111 // Analyze opcode
112 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
113 transfer_size_t transfer_size = SIZE_UNKNOWN;
114 addressing_mode_t addr_mode = MODE_UNKNOWN;
115 switch (primop) {
116 case 31:
117 switch (exop) {
118 case 23: // lwzx
119 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
120 case 55: // lwzux
121 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
122 case 87: // lbzx
123 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
124 case 119: // lbzux
125 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
126 case 151: // stwx
127 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_X; break;
128 case 183: // stwux
129 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break;
130 case 215: // stbx
131 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
132 case 247: // stbux
133 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
134 case 279: // lhzx
135 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
136 case 311: // lhzux
137 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
138 case 343: // lhax
139 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
140 case 375: // lhaux
141 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
142 case 407: // sthx
143 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
144 case 439: // sthux
145 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
146 }
147 break;
148
149 case 32: // lwz
150 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
151 case 33: // lwzu
152 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
153 case 34: // lbz
154 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
155 case 35: // lbzu
156 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
157 case 36: // stw
158 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break;
159 case 37: // stwu
160 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_U; break;
161 case 38: // stb
162 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
163 case 39: // stbu
164 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
165 case 40: // lhz
166 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
167 case 41: // lhzu
168 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
169 case 42: // lha
170 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
171 case 43: // lhau
172 transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
173 case 44: // sth
174 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
175 case 45: // sthu
176 transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
177 case 58: // ld, ldu, lwa
178 transfer_type = SIGSEGV_TRANSFER_LOAD;
179 transfer_size = SIZE_QUAD;
180 addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM;
181 imm &= ~3;
182 break;
183 case 62: // std, stdu, stq
184 transfer_type = SIGSEGV_TRANSFER_STORE;
185 transfer_size = SIZE_QUAD;
186 addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM;
187 imm &= ~3;
188 break;
189 }
190
191 // Calculate effective address
192 unsigned int addr = 0;
193 switch (addr_mode) {
194 case MODE_X:
195 case MODE_UX:
196 if (ra == 0)
197 addr = gpr[rb];
198 else
199 addr = gpr[ra] + gpr[rb];
200 break;
201 case MODE_NORM:
202 case MODE_U:
203 if (ra == 0)
204 addr = (signed int)(signed short)imm;
205 else
206 addr = gpr[ra] + (signed int)(signed short)imm;
207 break;
208 default:
209 break;
210 }
211
212 // Commit decoded instruction
213 instruction->addr = addr;
214 instruction->addr_mode = addr_mode;
215 instruction->transfer_type = transfer_type;
216 instruction->transfer_size = transfer_size;
217 instruction->ra = ra;
218 instruction->rd = rd;
219 }
220 #endif
221
222
223 /*
224 * OS-dependant SIGSEGV signals support section
225 */
226
227 #if HAVE_SIGINFO_T
228 // Generic extended signal handler
229 #if defined(__FreeBSD__)
230 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
231 #else
232 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
233 #endif
234 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *scp
235 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 siginfo_t *sip, void *scp
236 #define SIGSEGV_FAULT_HANDLER_ARGS sip, scp
237 #define SIGSEGV_FAULT_ADDRESS sip->si_addr
238 #if (defined(sgi) || defined(__sgi))
239 #include <ucontext.h>
240 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs)
241 #define SIGSEGV_FAULT_INSTRUCTION (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC]
242 #if (defined(mips) || defined(__mips))
243 #define SIGSEGV_REGISTER_FILE SIGSEGV_CONTEXT_REGS
244 #define SIGSEGV_SKIP_INSTRUCTION mips_skip_instruction
245 #endif
246 #endif
247 #if defined(__sun__)
248 #if (defined(sparc) || defined(__sparc__))
249 #include <sys/stack.h>
250 #include <sys/regset.h>
251 #include <sys/ucontext.h>
252 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs)
253 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[REG_PC]
254 #define SIGSEGV_SPARC_GWINDOWS (((ucontext_t *)scp)->uc_mcontext.gwins)
255 #define SIGSEGV_SPARC_RWINDOW (struct rwindow *)((char *)SIGSEGV_CONTEXT_REGS[REG_SP] + STACK_BIAS)
256 #define SIGSEGV_REGISTER_FILE ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW
257 #define SIGSEGV_SKIP_INSTRUCTION sparc_skip_instruction
258 #endif
259 #endif
260 #if defined(__FreeBSD__)
261 #if (defined(i386) || defined(__i386__))
262 #define SIGSEGV_FAULT_INSTRUCTION (((struct sigcontext *)scp)->sc_eip)
263 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
264 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
265 #endif
266 #endif
267 #if defined(__NetBSD__)
268 #if (defined(i386) || defined(__i386__))
269 #include <sys/ucontext.h>
270 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.__gregs)
271 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[_REG_EIP]
272 #define SIGSEGV_REGISTER_FILE (unsigned long *)SIGSEGV_CONTEXT_REGS
273 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
274 #endif
275 #endif
276 #if defined(__linux__)
277 #if (defined(i386) || defined(__i386__))
278 #include <sys/ucontext.h>
279 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs)
280 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
281 #define SIGSEGV_REGISTER_FILE (unsigned long *)SIGSEGV_CONTEXT_REGS
282 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
283 #endif
284 #if (defined(x86_64) || defined(__x86_64__))
285 #include <sys/ucontext.h>
286 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs)
287 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */
288 #define SIGSEGV_REGISTER_FILE (unsigned long *)SIGSEGV_CONTEXT_REGS
289 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
290 #endif
291 #if (defined(ia64) || defined(__ia64__))
292 #define SIGSEGV_FAULT_INSTRUCTION (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
293 #endif
294 #if (defined(powerpc) || defined(__powerpc__))
295 #include <sys/ucontext.h>
296 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.regs)
297 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->nip)
298 #define SIGSEGV_REGISTER_FILE (unsigned long *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned long *)(SIGSEGV_CONTEXT_REGS->gpr)
299 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
300 #endif
301 #if (defined(hppa) || defined(__hppa__))
302 #undef SIGSEGV_FAULT_ADDRESS
303 #define SIGSEGV_FAULT_ADDRESS sip->si_ptr
304 #endif
305 #if (defined(arm) || defined(__arm__))
306 #include <asm/ucontext.h> /* use kernel structure, glibc may not be in sync */
307 #define SIGSEGV_CONTEXT_REGS (((struct ucontext *)scp)->uc_mcontext)
308 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS.arm_pc)
309 #define SIGSEGV_REGISTER_FILE (&SIGSEGV_CONTEXT_REGS.arm_r0)
310 #define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction
311 #endif
312 #endif
313 #endif
314
315 #if HAVE_SIGCONTEXT_SUBTERFUGE
316 // Linux kernels prior to 2.4 ?
317 #if defined(__linux__)
318 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
319 #if (defined(i386) || defined(__i386__))
320 #include <asm/sigcontext.h>
321 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext scs
322 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp
323 #define SIGSEGV_FAULT_HANDLER_ARGS &scs
324 #define SIGSEGV_FAULT_ADDRESS scp->cr2
325 #define SIGSEGV_FAULT_INSTRUCTION scp->eip
326 #define SIGSEGV_REGISTER_FILE (unsigned long *)scp
327 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
328 #endif
329 #if (defined(sparc) || defined(__sparc__))
330 #include <asm/sigcontext.h>
331 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr
332 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr
333 #define SIGSEGV_FAULT_ADDRESS addr
334 #endif
335 #if (defined(powerpc) || defined(__powerpc__))
336 #include <asm/sigcontext.h>
337 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext *scp
338 #define SIGSEGV_FAULT_HANDLER_ARGS sig, scp
339 #define SIGSEGV_FAULT_ADDRESS scp->regs->dar
340 #define SIGSEGV_FAULT_INSTRUCTION scp->regs->nip
341 #define SIGSEGV_REGISTER_FILE (unsigned long *)&scp->regs->nip, (unsigned long *)(scp->regs->gpr)
342 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
343 #endif
344 #if (defined(alpha) || defined(__alpha__))
345 #include <asm/sigcontext.h>
346 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
347 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
348 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
349 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc
350 #endif
351 #if (defined(arm) || defined(__arm__))
352 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r1, int r2, int r3, struct sigcontext sc
353 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp
354 #define SIGSEGV_FAULT_HANDLER_ARGS &sc
355 #define SIGSEGV_FAULT_ADDRESS scp->fault_address
356 #define SIGSEGV_FAULT_INSTRUCTION scp->arm_pc
357 #define SIGSEGV_REGISTER_FILE &scp->arm_r0
358 #define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction
359 #endif
360 #endif
361
362 // Irix 5 or 6 on MIPS
363 #if (defined(sgi) || defined(__sgi)) && (defined(SYSTYPE_SVR4) || defined(_SYSTYPE_SVR4))
364 #include <ucontext.h>
365 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
366 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
367 #define SIGSEGV_FAULT_ADDRESS (unsigned long)scp->sc_badvaddr
368 #define SIGSEGV_FAULT_INSTRUCTION (unsigned long)scp->sc_pc
369 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
370 #endif
371
372 // HP-UX
373 #if (defined(hpux) || defined(__hpux__))
374 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
375 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
376 #define SIGSEGV_FAULT_ADDRESS scp->sc_sl.sl_ss.ss_narrow.ss_cr21
377 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) FAULT_HANDLER(SIGBUS)
378 #endif
379
380 // OSF/1 on Alpha
381 #if defined(__osf__)
382 #include <ucontext.h>
383 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
384 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
385 #define SIGSEGV_FAULT_ADDRESS scp->sc_traparg_a0
386 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
387 #endif
388
389 // AIX
390 #if defined(_AIX)
391 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
392 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
393 #define SIGSEGV_FAULT_ADDRESS scp->sc_jmpbuf.jmp_context.o_vaddr
394 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
395 #endif
396
397 // NetBSD
398 #if defined(__NetBSD__)
399 #if (defined(m68k) || defined(__m68k__))
400 #include <m68k/frame.h>
401 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
402 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
403 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
404 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
405
406 // Use decoding scheme from BasiliskII/m68k native
407 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
408 {
409 struct sigstate {
410 int ss_flags;
411 struct frame ss_frame;
412 };
413 struct sigstate *state = (struct sigstate *)scp->sc_ap;
414 char *fault_addr;
415 switch (state->ss_frame.f_format) {
416 case 7: /* 68040 access error */
417 /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */
418 fault_addr = state->ss_frame.f_fmt7.f_fa;
419 break;
420 default:
421 fault_addr = (char *)code;
422 break;
423 }
424 return (sigsegv_address_t)fault_addr;
425 }
426 #endif
427 #if (defined(alpha) || defined(__alpha__))
428 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
429 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
430 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
431 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
432 #endif
433 #if (defined(i386) || defined(__i386__))
434 #error "FIXME: need to decode instruction and compute EA"
435 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
436 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
437 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
438 #endif
439 #endif
440 #if defined(__FreeBSD__)
441 #if (defined(i386) || defined(__i386__))
442 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
443 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr
444 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr
445 #define SIGSEGV_FAULT_ADDRESS addr
446 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_eip
447 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&scp->sc_edi)
448 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
449 #endif
450 #if (defined(alpha) || defined(__alpha__))
451 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
452 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, char *addr, struct sigcontext *scp
453 #define SIGSEGV_FAULT_HANDLER_ARGS sig, addr, scp
454 #define SIGSEGV_FAULT_ADDRESS addr
455 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc
456 #endif
457 #endif
458
459 // Extract fault address out of a sigcontext
460 #if (defined(alpha) || defined(__alpha__))
461 // From Boehm's GC 6.0alpha8
462 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
463 {
464 unsigned int instruction = *((unsigned int *)(scp->sc_pc));
465 unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f];
466 fault_address += (signed long)(signed short)(instruction & 0xffff);
467 return (sigsegv_address_t)fault_address;
468 }
469 #endif
470
471
472 // MacOS X, not sure which version this works in. Under 10.1
473 // vm_protect does not appear to work from a signal handler. Under
474 // 10.2 signal handlers get siginfo type arguments but the si_addr
475 // field is the address of the faulting instruction and not the
476 // address that caused the SIGBUS. Maybe this works in 10.0? In any
477 // case with Mach exception handlers there is a way to do what this
478 // was meant to do.
479 #ifndef HAVE_MACH_EXCEPTIONS
480 #if defined(__APPLE__) && defined(__MACH__)
481 #if (defined(ppc) || defined(__ppc__))
482 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
483 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
484 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
485 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_ir
486 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
487 #define SIGSEGV_REGISTER_FILE (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2]
488 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
489
490 // Use decoding scheme from SheepShaver
491 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
492 {
493 unsigned int nip = (unsigned int) scp->sc_ir;
494 unsigned int * gpr = &((unsigned int *) scp->sc_regs)[2];
495 instruction_t instr;
496
497 powerpc_decode_instruction(&instr, nip, gpr);
498 return (sigsegv_address_t)instr.addr;
499 }
500 #endif
501 #endif
502 #endif
503 #endif
504
505 #if HAVE_WIN32_EXCEPTIONS
506 #define WIN32_LEAN_AND_MEAN /* avoid including junk */
507 #include <windows.h>
508 #include <winerror.h>
509
510 #define SIGSEGV_FAULT_HANDLER_ARGLIST EXCEPTION_POINTERS *ExceptionInfo
511 #define SIGSEGV_FAULT_HANDLER_ARGS ExceptionInfo
512 #define SIGSEGV_FAULT_ADDRESS ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
513 #define SIGSEGV_CONTEXT_REGS ExceptionInfo->ContextRecord
514 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS->Eip
515 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&SIGSEGV_CONTEXT_REGS->Edi)
516 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
517 #endif
518
519 #if HAVE_MACH_EXCEPTIONS
520
521 // This can easily be extended to other Mach systems, but really who
522 // uses HURD (oops GNU/HURD), Darwin/x86, NextStep, Rhapsody, or CMU
523 // Mach 2.5/3.0?
524 #if defined(__APPLE__) && defined(__MACH__)
525
526 #include <sys/types.h>
527 #include <stdlib.h>
528 #include <stdio.h>
529 #include <pthread.h>
530
531 /*
532 * If you are familiar with MIG then you will understand the frustration
533 * that was necessary to get these embedded into C++ code by hand.
534 */
535 extern "C" {
536 #include <mach/mach.h>
537 #include <mach/mach_error.h>
538
539 extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
540 extern kern_return_t catch_exception_raise(mach_port_t, mach_port_t,
541 mach_port_t, exception_type_t, exception_data_t, mach_msg_type_number_t);
542 extern kern_return_t exception_raise(mach_port_t, mach_port_t, mach_port_t,
543 exception_type_t, exception_data_t, mach_msg_type_number_t);
544 extern kern_return_t exception_raise_state(mach_port_t, exception_type_t,
545 exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
546 thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);
547 extern kern_return_t exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
548 exception_type_t, exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
549 thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);
550 }
551
552 // Could make this dynamic by looking for a result of MIG_ARRAY_TOO_LARGE
553 #define HANDLER_COUNT 64
554
555 // structure to tuck away existing exception handlers
556 typedef struct _ExceptionPorts {
557 mach_msg_type_number_t maskCount;
558 exception_mask_t masks[HANDLER_COUNT];
559 exception_handler_t handlers[HANDLER_COUNT];
560 exception_behavior_t behaviors[HANDLER_COUNT];
561 thread_state_flavor_t flavors[HANDLER_COUNT];
562 } ExceptionPorts;
563
564 // exception handler thread
565 static pthread_t exc_thread;
566
567 // place where old exception handler info is stored
568 static ExceptionPorts ports;
569
570 // our exception port
571 static mach_port_t _exceptionPort = MACH_PORT_NULL;
572
573 #define MACH_CHECK_ERROR(name,ret) \
574 if (ret != KERN_SUCCESS) { \
575 mach_error(#name, ret); \
576 exit (1); \
577 }
578
579 #define SIGSEGV_FAULT_ADDRESS code[1]
580 #define SIGSEGV_FAULT_INSTRUCTION get_fault_instruction(thread, state)
581 #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP) ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
582 #define SIGSEGV_FAULT_HANDLER_ARGLIST mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
583 #define SIGSEGV_FAULT_HANDLER_ARGS thread, code, &state
584 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
585 #define SIGSEGV_REGISTER_FILE &state->srr0, &state->r0
586
587 // Given a suspended thread, stuff the current instruction and
588 // registers into state.
589 //
590 // It would have been nice to have this be ppc/x86 independant which
591 // could have been done easily with a thread_state_t instead of
592 // ppc_thread_state_t, but because of the way this is called it is
593 // easier to do it this way.
594 #if (defined(ppc) || defined(__ppc__))
595 static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
596 {
597 kern_return_t krc;
598 mach_msg_type_number_t count;
599
600 count = MACHINE_THREAD_STATE_COUNT;
601 krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
602 MACH_CHECK_ERROR (thread_get_state, krc);
603
604 return (sigsegv_address_t)state->srr0;
605 }
606 #endif
607
608 // Since there can only be one exception thread running at any time
609 // this is not a problem.
610 #define MSG_SIZE 512
611 static char msgbuf[MSG_SIZE];
612 static char replybuf[MSG_SIZE];
613
614 /*
615 * This is the entry point for the exception handler thread. The job
616 * of this thread is to wait for exception messages on the exception
617 * port that was setup beforehand and to pass them on to exc_server.
618 * exc_server is a MIG generated function that is a part of Mach.
619 * Its job is to decide what to do with the exception message. In our
620 * case exc_server calls catch_exception_raise on our behalf. After
621 * exc_server returns, it is our responsibility to send the reply.
622 */
623 static void *
624 handleExceptions(void *priv)
625 {
626 mach_msg_header_t *msg, *reply;
627 kern_return_t krc;
628
629 msg = (mach_msg_header_t *)msgbuf;
630 reply = (mach_msg_header_t *)replybuf;
631
632 for (;;) {
633 krc = mach_msg(msg, MACH_RCV_MSG, MSG_SIZE, MSG_SIZE,
634 _exceptionPort, 0, MACH_PORT_NULL);
635 MACH_CHECK_ERROR(mach_msg, krc);
636
637 if (!exc_server(msg, reply)) {
638 fprintf(stderr, "exc_server hated the message\n");
639 exit(1);
640 }
641
642 krc = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
643 msg->msgh_local_port, 0, MACH_PORT_NULL);
644 if (krc != KERN_SUCCESS) {
645 fprintf(stderr, "Error sending message to original reply port, krc = %d, %s",
646 krc, mach_error_string(krc));
647 exit(1);
648 }
649 }
650 }
651 #endif
652 #endif
653
654
655 /*
656 * Instruction skipping
657 */
658
659 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
660 // Decode and skip X86 instruction
661 #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
662 #if defined(__linux__)
663 enum {
664 #if (defined(i386) || defined(__i386__))
665 X86_REG_EIP = 14,
666 X86_REG_EAX = 11,
667 X86_REG_ECX = 10,
668 X86_REG_EDX = 9,
669 X86_REG_EBX = 8,
670 X86_REG_ESP = 7,
671 X86_REG_EBP = 6,
672 X86_REG_ESI = 5,
673 X86_REG_EDI = 4
674 #endif
675 #if defined(__x86_64__)
676 X86_REG_R8 = 0,
677 X86_REG_R9 = 1,
678 X86_REG_R10 = 2,
679 X86_REG_R11 = 3,
680 X86_REG_R12 = 4,
681 X86_REG_R13 = 5,
682 X86_REG_R14 = 6,
683 X86_REG_R15 = 7,
684 X86_REG_EDI = 8,
685 X86_REG_ESI = 9,
686 X86_REG_EBP = 10,
687 X86_REG_EBX = 11,
688 X86_REG_EDX = 12,
689 X86_REG_EAX = 13,
690 X86_REG_ECX = 14,
691 X86_REG_ESP = 15,
692 X86_REG_EIP = 16
693 #endif
694 };
695 #endif
696 #if defined(__NetBSD__)
697 enum {
698 #if (defined(i386) || defined(__i386__))
699 X86_REG_EIP = _REG_EIP,
700 X86_REG_EAX = _REG_EAX,
701 X86_REG_ECX = _REG_ECX,
702 X86_REG_EDX = _REG_EDX,
703 X86_REG_EBX = _REG_EBX,
704 X86_REG_ESP = _REG_ESP,
705 X86_REG_EBP = _REG_EBP,
706 X86_REG_ESI = _REG_ESI,
707 X86_REG_EDI = _REG_EDI
708 #endif
709 };
710 #endif
711 #if defined(__FreeBSD__)
712 enum {
713 #if (defined(i386) || defined(__i386__))
714 X86_REG_EIP = 10,
715 X86_REG_EAX = 7,
716 X86_REG_ECX = 6,
717 X86_REG_EDX = 5,
718 X86_REG_EBX = 4,
719 X86_REG_ESP = 13,
720 X86_REG_EBP = 2,
721 X86_REG_ESI = 1,
722 X86_REG_EDI = 0
723 #endif
724 };
725 #endif
726 #if defined(_WIN32)
727 enum {
728 #if (defined(i386) || defined(__i386__))
729 X86_REG_EIP = 7,
730 X86_REG_EAX = 5,
731 X86_REG_ECX = 4,
732 X86_REG_EDX = 3,
733 X86_REG_EBX = 2,
734 X86_REG_ESP = 10,
735 X86_REG_EBP = 6,
736 X86_REG_ESI = 1,
737 X86_REG_EDI = 0
738 #endif
739 };
740 #endif
741 // FIXME: this is partly redundant with the instruction decoding phase
742 // to discover transfer type and register number
743 static inline int ix86_step_over_modrm(unsigned char * p)
744 {
745 int mod = (p[0] >> 6) & 3;
746 int rm = p[0] & 7;
747 int offset = 0;
748
749 // ModR/M Byte
750 switch (mod) {
751 case 0: // [reg]
752 if (rm == 5) return 4; // disp32
753 break;
754 case 1: // disp8[reg]
755 offset = 1;
756 break;
757 case 2: // disp32[reg]
758 offset = 4;
759 break;
760 case 3: // register
761 return 0;
762 }
763
764 // SIB Byte
765 if (rm == 4) {
766 if (mod == 0 && (p[1] & 7) == 5)
767 offset = 5; // disp32[index]
768 else
769 offset++;
770 }
771
772 return offset;
773 }
774
775 static bool ix86_skip_instruction(unsigned long * regs)
776 {
777 unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
778
779 if (eip == 0)
780 return false;
781 #ifdef _WIN32
782 if (IsBadCodePtr((FARPROC)eip))
783 return false;
784 #endif
785
786 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
787 transfer_size_t transfer_size = SIZE_LONG;
788
789 int reg = -1;
790 int len = 0;
791
792 #if DEBUG
793 printf("IP: %p [%02x %02x %02x %02x...]\n",
794 eip, eip[0], eip[1], eip[2], eip[3]);
795 #endif
796
797 // Operand size prefix
798 if (*eip == 0x66) {
799 eip++;
800 len++;
801 transfer_size = SIZE_WORD;
802 }
803
804 // REX prefix
805 #if defined(__x86_64__)
806 struct rex_t {
807 unsigned char W;
808 unsigned char R;
809 unsigned char X;
810 unsigned char B;
811 };
812 rex_t rex = { 0, 0, 0, 0 };
813 bool has_rex = false;
814 if ((*eip & 0xf0) == 0x40) {
815 has_rex = true;
816 const unsigned char b = *eip;
817 rex.W = b & (1 << 3);
818 rex.R = b & (1 << 2);
819 rex.X = b & (1 << 1);
820 rex.B = b & (1 << 0);
821 #if DEBUG
822 printf("REX: %c,%c,%c,%c\n",
823 rex.W ? 'W' : '_',
824 rex.R ? 'R' : '_',
825 rex.X ? 'X' : '_',
826 rex.B ? 'B' : '_');
827 #endif
828 eip++;
829 len++;
830 if (rex.W)
831 transfer_size = SIZE_QUAD;
832 }
833 #else
834 const bool has_rex = false;
835 #endif
836
837 // Decode instruction
838 int target_size = SIZE_UNKNOWN;
839 switch (eip[0]) {
840 case 0x0f:
841 target_size = transfer_size;
842 switch (eip[1]) {
843 case 0xbe: // MOVSX r32, r/m8
844 case 0xb6: // MOVZX r32, r/m8
845 transfer_size = SIZE_BYTE;
846 goto do_mov_extend;
847 case 0xbf: // MOVSX r32, r/m16
848 case 0xb7: // MOVZX r32, r/m16
849 transfer_size = SIZE_WORD;
850 goto do_mov_extend;
851 do_mov_extend:
852 switch (eip[2] & 0xc0) {
853 case 0x80:
854 reg = (eip[2] >> 3) & 7;
855 transfer_type = SIGSEGV_TRANSFER_LOAD;
856 break;
857 case 0x40:
858 reg = (eip[2] >> 3) & 7;
859 transfer_type = SIGSEGV_TRANSFER_LOAD;
860 break;
861 case 0x00:
862 reg = (eip[2] >> 3) & 7;
863 transfer_type = SIGSEGV_TRANSFER_LOAD;
864 break;
865 }
866 len += 3 + ix86_step_over_modrm(eip + 2);
867 break;
868 }
869 break;
870 case 0x8a: // MOV r8, r/m8
871 transfer_size = SIZE_BYTE;
872 case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
873 switch (eip[1] & 0xc0) {
874 case 0x80:
875 reg = (eip[1] >> 3) & 7;
876 transfer_type = SIGSEGV_TRANSFER_LOAD;
877 break;
878 case 0x40:
879 reg = (eip[1] >> 3) & 7;
880 transfer_type = SIGSEGV_TRANSFER_LOAD;
881 break;
882 case 0x00:
883 reg = (eip[1] >> 3) & 7;
884 transfer_type = SIGSEGV_TRANSFER_LOAD;
885 break;
886 }
887 len += 2 + ix86_step_over_modrm(eip + 1);
888 break;
889 case 0x88: // MOV r/m8, r8
890 transfer_size = SIZE_BYTE;
891 case 0x89: // MOV r/m32, r32 (or 16-bit operation)
892 switch (eip[1] & 0xc0) {
893 case 0x80:
894 reg = (eip[1] >> 3) & 7;
895 transfer_type = SIGSEGV_TRANSFER_STORE;
896 break;
897 case 0x40:
898 reg = (eip[1] >> 3) & 7;
899 transfer_type = SIGSEGV_TRANSFER_STORE;
900 break;
901 case 0x00:
902 reg = (eip[1] >> 3) & 7;
903 transfer_type = SIGSEGV_TRANSFER_STORE;
904 break;
905 }
906 len += 2 + ix86_step_over_modrm(eip + 1);
907 break;
908 }
909 if (target_size == SIZE_UNKNOWN)
910 target_size = transfer_size;
911
912 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
913 // Unknown machine code, let it crash. Then patch the decoder
914 return false;
915 }
916
917 #if defined(__x86_64__)
918 if (rex.R)
919 reg += 8;
920 #endif
921
922 if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
923 static const int x86_reg_map[] = {
924 X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
925 X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
926 #if defined(__x86_64__)
927 X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11,
928 X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
929 #endif
930 };
931
932 if (reg < 0 || reg >= (sizeof(x86_reg_map)/sizeof(x86_reg_map[0]) - 1))
933 return false;
934
935 // Set 0 to the relevant register part
936 // NOTE: this is only valid for MOV alike instructions
937 int rloc = x86_reg_map[reg];
938 switch (target_size) {
939 case SIZE_BYTE:
940 if (has_rex || reg < 4)
941 regs[rloc] = (regs[rloc] & ~0x00ffL);
942 else {
943 rloc = x86_reg_map[reg - 4];
944 regs[rloc] = (regs[rloc] & ~0xff00L);
945 }
946 break;
947 case SIZE_WORD:
948 regs[rloc] = (regs[rloc] & ~0xffffL);
949 break;
950 case SIZE_LONG:
951 case SIZE_QUAD: // zero-extension
952 regs[rloc] = 0;
953 break;
954 }
955 }
956
957 #if DEBUG
958 printf("%08x: %s %s access", regs[X86_REG_EIP],
959 transfer_size == SIZE_BYTE ? "byte" :
960 transfer_size == SIZE_WORD ? "word" :
961 transfer_size == SIZE_LONG ? "long" :
962 transfer_size == SIZE_QUAD ? "quad" : "unknown",
963 transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
964
965 if (reg != -1) {
966 static const char * x86_byte_reg_str_map[] = {
967 "al", "cl", "dl", "bl",
968 "spl", "bpl", "sil", "dil",
969 "r8b", "r9b", "r10b", "r11b",
970 "r12b", "r13b", "r14b", "r15b",
971 "ah", "ch", "dh", "bh",
972 };
973 static const char * x86_word_reg_str_map[] = {
974 "ax", "cx", "dx", "bx",
975 "sp", "bp", "si", "di",
976 "r8w", "r9w", "r10w", "r11w",
977 "r12w", "r13w", "r14w", "r15w",
978 };
979 static const char *x86_long_reg_str_map[] = {
980 "eax", "ecx", "edx", "ebx",
981 "esp", "ebp", "esi", "edi",
982 "r8d", "r9d", "r10d", "r11d",
983 "r12d", "r13d", "r14d", "r15d",
984 };
985 static const char *x86_quad_reg_str_map[] = {
986 "rax", "rcx", "rdx", "rbx",
987 "rsp", "rbp", "rsi", "rdi",
988 "r8", "r9", "r10", "r11",
989 "r12", "r13", "r14", "r15",
990 };
991 const char * reg_str = NULL;
992 switch (target_size) {
993 case SIZE_BYTE:
994 reg_str = x86_byte_reg_str_map[(!has_rex && reg >= 4 ? 12 : 0) + reg];
995 break;
996 case SIZE_WORD: reg_str = x86_word_reg_str_map[reg]; break;
997 case SIZE_LONG: reg_str = x86_long_reg_str_map[reg]; break;
998 case SIZE_QUAD: reg_str = x86_quad_reg_str_map[reg]; break;
999 }
1000 if (reg_str)
1001 printf(" %s register %%%s",
1002 transfer_type == SIGSEGV_TRANSFER_LOAD ? "to" : "from",
1003 reg_str);
1004 }
1005 printf(", %d bytes instruction\n", len);
1006 #endif
1007
1008 regs[X86_REG_EIP] += len;
1009 return true;
1010 }
1011 #endif
1012
1013 // Decode and skip PPC instruction
1014 #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
1015 static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
1016 {
1017 instruction_t instr;
1018 powerpc_decode_instruction(&instr, *nip_p, regs);
1019
1020 if (instr.transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1021 // Unknown machine code, let it crash. Then patch the decoder
1022 return false;
1023 }
1024
1025 #if DEBUG
1026 printf("%08x: %s %s access", *nip_p,
1027 instr.transfer_size == SIZE_BYTE ? "byte" :
1028 instr.transfer_size == SIZE_WORD ? "word" :
1029 instr.transfer_size == SIZE_LONG ? "long" : "quad",
1030 instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
1031
1032 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1033 printf(" r%d (ra = %08x)\n", instr.ra, instr.addr);
1034 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1035 printf(" r%d (rd = 0)\n", instr.rd);
1036 #endif
1037
1038 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1039 regs[instr.ra] = instr.addr;
1040 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1041 regs[instr.rd] = 0;
1042
1043 *nip_p += 4;
1044 return true;
1045 }
1046 #endif
1047
1048 // Decode and skip MIPS instruction
1049 #if (defined(mips) || defined(__mips))
1050 enum {
1051 #if (defined(sgi) || defined(__sgi))
1052 MIPS_REG_EPC = 35,
1053 #endif
1054 };
1055 static bool mips_skip_instruction(greg_t * regs)
1056 {
1057 unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
1058
1059 if (epc == 0)
1060 return false;
1061
1062 #if DEBUG
1063 printf("IP: %p [%08x]\n", epc, epc[0]);
1064 #endif
1065
1066 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1067 transfer_size_t transfer_size = SIZE_LONG;
1068 int direction = 0;
1069
1070 const unsigned int opcode = epc[0];
1071 switch (opcode >> 26) {
1072 case 32: // Load Byte
1073 case 36: // Load Byte Unsigned
1074 transfer_type = SIGSEGV_TRANSFER_LOAD;
1075 transfer_size = SIZE_BYTE;
1076 break;
1077 case 33: // Load Halfword
1078 case 37: // Load Halfword Unsigned
1079 transfer_type = SIGSEGV_TRANSFER_LOAD;
1080 transfer_size = SIZE_WORD;
1081 break;
1082 case 35: // Load Word
1083 case 39: // Load Word Unsigned
1084 transfer_type = SIGSEGV_TRANSFER_LOAD;
1085 transfer_size = SIZE_LONG;
1086 break;
1087 case 34: // Load Word Left
1088 transfer_type = SIGSEGV_TRANSFER_LOAD;
1089 transfer_size = SIZE_LONG;
1090 direction = -1;
1091 break;
1092 case 38: // Load Word Right
1093 transfer_type = SIGSEGV_TRANSFER_LOAD;
1094 transfer_size = SIZE_LONG;
1095 direction = 1;
1096 break;
1097 case 55: // Load Doubleword
1098 transfer_type = SIGSEGV_TRANSFER_LOAD;
1099 transfer_size = SIZE_QUAD;
1100 break;
1101 case 26: // Load Doubleword Left
1102 transfer_type = SIGSEGV_TRANSFER_LOAD;
1103 transfer_size = SIZE_QUAD;
1104 direction = -1;
1105 break;
1106 case 27: // Load Doubleword Right
1107 transfer_type = SIGSEGV_TRANSFER_LOAD;
1108 transfer_size = SIZE_QUAD;
1109 direction = 1;
1110 break;
1111 case 40: // Store Byte
1112 transfer_type = SIGSEGV_TRANSFER_STORE;
1113 transfer_size = SIZE_BYTE;
1114 break;
1115 case 41: // Store Halfword
1116 transfer_type = SIGSEGV_TRANSFER_STORE;
1117 transfer_size = SIZE_WORD;
1118 break;
1119 case 43: // Store Word
1120 case 42: // Store Word Left
1121 case 46: // Store Word Right
1122 transfer_type = SIGSEGV_TRANSFER_STORE;
1123 transfer_size = SIZE_LONG;
1124 break;
1125 case 63: // Store Doubleword
1126 case 44: // Store Doubleword Left
1127 case 45: // Store Doubleword Right
1128 transfer_type = SIGSEGV_TRANSFER_STORE;
1129 transfer_size = SIZE_QUAD;
1130 break;
1131 /* Misc instructions unlikely to be used within CPU emulators */
1132 case 48: // Load Linked Word
1133 transfer_type = SIGSEGV_TRANSFER_LOAD;
1134 transfer_size = SIZE_LONG;
1135 break;
1136 case 52: // Load Linked Doubleword
1137 transfer_type = SIGSEGV_TRANSFER_LOAD;
1138 transfer_size = SIZE_QUAD;
1139 break;
1140 case 56: // Store Conditional Word
1141 transfer_type = SIGSEGV_TRANSFER_STORE;
1142 transfer_size = SIZE_LONG;
1143 break;
1144 case 60: // Store Conditional Doubleword
1145 transfer_type = SIGSEGV_TRANSFER_STORE;
1146 transfer_size = SIZE_QUAD;
1147 break;
1148 }
1149
1150 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1151 // Unknown machine code, let it crash. Then patch the decoder
1152 return false;
1153 }
1154
1155 // Zero target register in case of a load operation
1156 const int reg = (opcode >> 16) & 0x1f;
1157 if (transfer_type == SIGSEGV_TRANSFER_LOAD) {
1158 if (direction == 0)
1159 regs[reg] = 0;
1160 else {
1161 // FIXME: untested code
1162 unsigned long ea = regs[(opcode >> 21) & 0x1f];
1163 ea += (signed long)(signed int)(signed short)(opcode & 0xffff);
1164 const int offset = ea & (transfer_size == SIZE_LONG ? 3 : 7);
1165 unsigned long value;
1166 if (direction > 0) {
1167 const unsigned long rmask = ~((1L << ((offset + 1) * 8)) - 1);
1168 value = regs[reg] & rmask;
1169 }
1170 else {
1171 const unsigned long lmask = (1L << (offset * 8)) - 1;
1172 value = regs[reg] & lmask;
1173 }
1174 // restore most significant bits
1175 if (transfer_size == SIZE_LONG)
1176 value = (signed long)(signed int)value;
1177 regs[reg] = value;
1178 }
1179 }
1180
1181 #if DEBUG
1182 #if (defined(_ABIN32) || defined(_ABI64))
1183 static const char * mips_gpr_names[32] = {
1184 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1185 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1186 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1187 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
1188 };
1189 #else
1190 static const char * mips_gpr_names[32] = {
1191 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1192 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
1193 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1194 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
1195 };
1196 #endif
1197 printf("%s %s register %s\n",
1198 transfer_size == SIZE_BYTE ? "byte" :
1199 transfer_size == SIZE_WORD ? "word" :
1200 transfer_size == SIZE_LONG ? "long" :
1201 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1202 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1203 mips_gpr_names[reg]);
1204 #endif
1205
1206 regs[MIPS_REG_EPC] += 4;
1207 return true;
1208 }
1209 #endif
1210
1211 // Decode and skip SPARC instruction
1212 #if (defined(sparc) || defined(__sparc__))
1213 enum {
1214 #if (defined(__sun__))
1215 SPARC_REG_G1 = REG_G1,
1216 SPARC_REG_O0 = REG_O0,
1217 SPARC_REG_PC = REG_PC,
1218 #endif
1219 };
1220 static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
1221 {
1222 unsigned int * pc = (unsigned int *)regs[SPARC_REG_PC];
1223
1224 if (pc == 0)
1225 return false;
1226
1227 #if DEBUG
1228 printf("IP: %p [%08x]\n", pc, pc[0]);
1229 #endif
1230
1231 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1232 transfer_size_t transfer_size = SIZE_LONG;
1233 bool register_pair = false;
1234
1235 const unsigned int opcode = pc[0];
1236 if ((opcode >> 30) != 3)
1237 return false;
1238 switch ((opcode >> 19) & 0x3f) {
1239 case 9: // Load Signed Byte
1240 case 1: // Load Unsigned Byte
1241 transfer_type = SIGSEGV_TRANSFER_LOAD;
1242 transfer_size = SIZE_BYTE;
1243 break;
1244 case 10:// Load Signed Halfword
1245 case 2: // Load Unsigned Word
1246 transfer_type = SIGSEGV_TRANSFER_LOAD;
1247 transfer_size = SIZE_WORD;
1248 break;
1249 case 8: // Load Word
1250 case 0: // Load Unsigned Word
1251 transfer_type = SIGSEGV_TRANSFER_LOAD;
1252 transfer_size = SIZE_LONG;
1253 break;
1254 case 11:// Load Extended Word
1255 transfer_type = SIGSEGV_TRANSFER_LOAD;
1256 transfer_size = SIZE_QUAD;
1257 break;
1258 case 3: // Load Doubleword
1259 transfer_type = SIGSEGV_TRANSFER_LOAD;
1260 transfer_size = SIZE_LONG;
1261 register_pair = true;
1262 break;
1263 case 5: // Store Byte
1264 transfer_type = SIGSEGV_TRANSFER_STORE;
1265 transfer_size = SIZE_BYTE;
1266 break;
1267 case 6: // Store Halfword
1268 transfer_type = SIGSEGV_TRANSFER_STORE;
1269 transfer_size = SIZE_WORD;
1270 break;
1271 case 4: // Store Word
1272 transfer_type = SIGSEGV_TRANSFER_STORE;
1273 transfer_size = SIZE_LONG;
1274 break;
1275 case 14:// Store Extended Word
1276 transfer_type = SIGSEGV_TRANSFER_STORE;
1277 transfer_size = SIZE_QUAD;
1278 break;
1279 case 7: // Store Doubleword
1280 transfer_type = SIGSEGV_TRANSFER_STORE;
1281 transfer_size = SIZE_WORD;
1282 register_pair = true;
1283 break;
1284 }
1285
1286 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1287 // Unknown machine code, let it crash. Then patch the decoder
1288 return false;
1289 }
1290
1291 // Zero target register in case of a load operation
1292 const int reg = (opcode >> 25) & 0x1f;
1293 if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
1294 // FIXME: code to handle local & input registers is not tested
1295 if (reg >= 1 && reg <= 7) {
1296 // global registers
1297 regs[reg - 1 + SPARC_REG_G1] = 0;
1298 }
1299 else if (reg >= 8 && reg <= 15) {
1300 // output registers
1301 regs[reg - 8 + SPARC_REG_O0] = 0;
1302 }
1303 else if (reg >= 16 && reg <= 23) {
1304 // local registers (in register windows)
1305 if (gwins)
1306 gwins->wbuf->rw_local[reg - 16] = 0;
1307 else
1308 rwin->rw_local[reg - 16] = 0;
1309 }
1310 else {
1311 // input registers (in register windows)
1312 if (gwins)
1313 gwins->wbuf->rw_in[reg - 24] = 0;
1314 else
1315 rwin->rw_in[reg - 24] = 0;
1316 }
1317 }
1318
1319 #if DEBUG
1320 static const char * reg_names[] = {
1321 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1322 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1323 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1324 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1325 };
1326 printf("%s %s register %s\n",
1327 transfer_size == SIZE_BYTE ? "byte" :
1328 transfer_size == SIZE_WORD ? "word" :
1329 transfer_size == SIZE_LONG ? "long" :
1330 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1331 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1332 reg_names[reg]);
1333 #endif
1334
1335 regs[SPARC_REG_PC] += 4;
1336 return true;
1337 }
1338 #endif
1339 #endif
1340
1341 // Decode and skip ARM instruction
1342 #if (defined(arm) || defined(__arm__))
1343 enum {
1344 #if (defined(__linux__))
1345 ARM_REG_PC = 15,
1346 ARM_REG_CPSR = 16
1347 #endif
1348 };
1349 static bool arm_skip_instruction(unsigned long * regs)
1350 {
1351 unsigned int * pc = (unsigned int *)regs[ARM_REG_PC];
1352
1353 if (pc == 0)
1354 return false;
1355
1356 #if DEBUG
1357 printf("IP: %p [%08x]\n", pc, pc[0]);
1358 #endif
1359
1360 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1361 transfer_size_t transfer_size = SIZE_UNKNOWN;
1362 enum { op_sdt = 1, op_sdth = 2 };
1363 int op = 0;
1364
1365 // Handle load/store instructions only
1366 const unsigned int opcode = pc[0];
1367 switch ((opcode >> 25) & 7) {
1368 case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH)
1369 op = op_sdth;
1370 // Determine transfer size (S/H bits)
1371 switch ((opcode >> 5) & 3) {
1372 case 0: // SWP instruction
1373 break;
1374 case 1: // Unsigned halfwords
1375 case 3: // Signed halfwords
1376 transfer_size = SIZE_WORD;
1377 break;
1378 case 2: // Signed byte
1379 transfer_size = SIZE_BYTE;
1380 break;
1381 }
1382 break;
1383 case 2:
1384 case 3: // Single Data Transfer (LDR, STR)
1385 op = op_sdt;
1386 // Determine transfer size (B bit)
1387 if (((opcode >> 22) & 1) == 1)
1388 transfer_size = SIZE_BYTE;
1389 else
1390 transfer_size = SIZE_LONG;
1391 break;
1392 default:
1393 // FIXME: support load/store mutliple?
1394 return false;
1395 }
1396
1397 // Check for invalid transfer size (SWP instruction?)
1398 if (transfer_size == SIZE_UNKNOWN)
1399 return false;
1400
1401 // Determine transfer type (L bit)
1402 if (((opcode >> 20) & 1) == 1)
1403 transfer_type = SIGSEGV_TRANSFER_LOAD;
1404 else
1405 transfer_type = SIGSEGV_TRANSFER_STORE;
1406
1407 // Compute offset
1408 int offset;
1409 if (((opcode >> 25) & 1) == 0) {
1410 if (op == op_sdt)
1411 offset = opcode & 0xfff;
1412 else if (op == op_sdth) {
1413 int rm = opcode & 0xf;
1414 if (((opcode >> 22) & 1) == 0) {
1415 // register offset
1416 offset = regs[rm];
1417 }
1418 else {
1419 // immediate offset
1420 offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f);
1421 }
1422 }
1423 }
1424 else {
1425 const int rm = opcode & 0xf;
1426 const int sh = (opcode >> 7) & 0x1f;
1427 if (((opcode >> 4) & 1) == 1) {
1428 // we expect only legal load/store instructions
1429 printf("FATAL: invalid shift operand\n");
1430 return false;
1431 }
1432 const unsigned int v = regs[rm];
1433 switch ((opcode >> 5) & 3) {
1434 case 0: // logical shift left
1435 offset = sh ? v << sh : v;
1436 break;
1437 case 1: // logical shift right
1438 offset = sh ? v >> sh : 0;
1439 break;
1440 case 2: // arithmetic shift right
1441 if (sh)
1442 offset = ((signed int)v) >> sh;
1443 else
1444 offset = (v & 0x80000000) ? 0xffffffff : 0;
1445 break;
1446 case 3: // rotate right
1447 if (sh)
1448 offset = (v >> sh) | (v << (32 - sh));
1449 else
1450 offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000);
1451 break;
1452 }
1453 }
1454 if (((opcode >> 23) & 1) == 0)
1455 offset = -offset;
1456
1457 int rd = (opcode >> 12) & 0xf;
1458 int rn = (opcode >> 16) & 0xf;
1459 #if DEBUG
1460 static const char * reg_names[] = {
1461 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1462 "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc"
1463 };
1464 printf("%s %s register %s\n",
1465 transfer_size == SIZE_BYTE ? "byte" :
1466 transfer_size == SIZE_WORD ? "word" :
1467 transfer_size == SIZE_LONG ? "long" : "unknown",
1468 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1469 reg_names[rd]);
1470 #endif
1471
1472 unsigned int base = regs[rn];
1473 if (((opcode >> 24) & 1) == 1)
1474 base += offset;
1475
1476 if (transfer_type == SIGSEGV_TRANSFER_LOAD)
1477 regs[rd] = 0;
1478
1479 if (((opcode >> 24) & 1) == 0) // post-index addressing
1480 regs[rn] += offset;
1481 else if (((opcode >> 21) & 1) == 1) // write-back address into base
1482 regs[rn] = base;
1483
1484 regs[ARM_REG_PC] += 4;
1485 return true;
1486 }
1487 #endif
1488
1489
1490 // Fallbacks
1491 #ifndef SIGSEGV_FAULT_INSTRUCTION
1492 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_INVALID_PC
1493 #endif
1494 #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
1495 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
1496 #endif
1497 #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
1498 #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP) sigsegv_fault_handler(ADDR, IP)
1499 #endif
1500
1501 // SIGSEGV recovery supported ?
1502 #if defined(SIGSEGV_ALL_SIGNALS) && defined(SIGSEGV_FAULT_HANDLER_ARGLIST) && defined(SIGSEGV_FAULT_ADDRESS)
1503 #define HAVE_SIGSEGV_RECOVERY
1504 #endif
1505
1506
1507 /*
1508 * SIGSEGV global handler
1509 */
1510
1511 // This function handles the badaccess to memory.
1512 // It is called from the signal handler or the exception handler.
1513 static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
1514 {
1515 sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1516 sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1517
1518 // Call user's handler and reinstall the global handler, if required
1519 switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
1520 case SIGSEGV_RETURN_SUCCESS:
1521 return true;
1522
1523 #if HAVE_SIGSEGV_SKIP_INSTRUCTION
1524 case SIGSEGV_RETURN_SKIP_INSTRUCTION:
1525 // Call the instruction skipper with the register file
1526 // available
1527 if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
1528 #ifdef HAVE_MACH_EXCEPTIONS
1529 // Unlike UNIX signals where the thread state
1530 // is modified off of the stack, in Mach we
1531 // need to actually call thread_set_state to
1532 // have the register values updated.
1533 kern_return_t krc;
1534
1535 krc = thread_set_state(thread,
1536 MACHINE_THREAD_STATE, (thread_state_t)state,
1537 MACHINE_THREAD_STATE_COUNT);
1538 MACH_CHECK_ERROR (thread_get_state, krc);
1539 #endif
1540 return true;
1541 }
1542 break;
1543 #endif
1544 case SIGSEGV_RETURN_FAILURE:
1545 // We can't do anything with the fault_address, dump state?
1546 if (sigsegv_state_dumper != 0)
1547 sigsegv_state_dumper(fault_address, fault_instruction);
1548 break;
1549 }
1550
1551 return false;
1552 }
1553
1554
1555 /*
1556 * There are two mechanisms for handling a bad memory access,
1557 * Mach exceptions and UNIX signals. The implementation specific
1558 * code appears below. Its reponsibility is to call handle_badaccess
1559 * which is the routine that handles the fault in an implementation
1560 * agnostic manner. The implementation specific code below is then
1561 * reponsible for checking whether handle_badaccess was able
1562 * to handle the memory access error and perform any implementation
1563 * specific tasks necessary afterwards.
1564 */
1565
1566 #ifdef HAVE_MACH_EXCEPTIONS
1567 /*
1568 * We need to forward all exceptions that we do not handle.
1569 * This is important, there are many exceptions that may be
1570 * handled by other exception handlers. For example debuggers
1571 * use exceptions and the exception hander is in another
1572 * process in such a case. (Timothy J. Wood states in his
1573 * message to the list that he based this code on that from
1574 * gdb for Darwin.)
1575 */
1576 static inline kern_return_t
1577 forward_exception(mach_port_t thread_port,
1578 mach_port_t task_port,
1579 exception_type_t exception_type,
1580 exception_data_t exception_data,
1581 mach_msg_type_number_t data_count,
1582 ExceptionPorts *oldExceptionPorts)
1583 {
1584 kern_return_t kret;
1585 unsigned int portIndex;
1586 mach_port_t port;
1587 exception_behavior_t behavior;
1588 thread_state_flavor_t flavor;
1589 thread_state_t thread_state;
1590 mach_msg_type_number_t thread_state_count;
1591
1592 for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
1593 if (oldExceptionPorts->masks[portIndex] & (1 << exception_type)) {
1594 // This handler wants the exception
1595 break;
1596 }
1597 }
1598
1599 if (portIndex >= oldExceptionPorts->maskCount) {
1600 fprintf(stderr, "No handler for exception_type = %d. Not fowarding\n", exception_type);
1601 return KERN_FAILURE;
1602 }
1603
1604 port = oldExceptionPorts->handlers[portIndex];
1605 behavior = oldExceptionPorts->behaviors[portIndex];
1606 flavor = oldExceptionPorts->flavors[portIndex];
1607
1608 /*
1609 fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
1610 */
1611
1612 if (behavior != EXCEPTION_DEFAULT) {
1613 thread_state_count = THREAD_STATE_MAX;
1614 kret = thread_get_state (thread_port, flavor, thread_state,
1615 &thread_state_count);
1616 MACH_CHECK_ERROR (thread_get_state, kret);
1617 }
1618
1619 switch (behavior) {
1620 case EXCEPTION_DEFAULT:
1621 // fprintf(stderr, "forwarding to exception_raise\n");
1622 kret = exception_raise(port, thread_port, task_port, exception_type,
1623 exception_data, data_count);
1624 MACH_CHECK_ERROR (exception_raise, kret);
1625 break;
1626 case EXCEPTION_STATE:
1627 // fprintf(stderr, "forwarding to exception_raise_state\n");
1628 kret = exception_raise_state(port, exception_type, exception_data,
1629 data_count, &flavor,
1630 thread_state, thread_state_count,
1631 thread_state, &thread_state_count);
1632 MACH_CHECK_ERROR (exception_raise_state, kret);
1633 break;
1634 case EXCEPTION_STATE_IDENTITY:
1635 // fprintf(stderr, "forwarding to exception_raise_state_identity\n");
1636 kret = exception_raise_state_identity(port, thread_port, task_port,
1637 exception_type, exception_data,
1638 data_count, &flavor,
1639 thread_state, thread_state_count,
1640 thread_state, &thread_state_count);
1641 MACH_CHECK_ERROR (exception_raise_state_identity, kret);
1642 break;
1643 default:
1644 fprintf(stderr, "forward_exception got unknown behavior\n");
1645 break;
1646 }
1647
1648 if (behavior != EXCEPTION_DEFAULT) {
1649 kret = thread_set_state (thread_port, flavor, thread_state,
1650 thread_state_count);
1651 MACH_CHECK_ERROR (thread_set_state, kret);
1652 }
1653
1654 return KERN_SUCCESS;
1655 }
1656
1657 /*
1658 * This is the code that actually handles the exception.
1659 * It is called by exc_server. For Darwin 5 Apple changed
1660 * this a bit from how this family of functions worked in
1661 * Mach. If you are familiar with that it is a little
1662 * different. The main variation that concerns us here is
1663 * that code is an array of exception specific codes and
1664 * codeCount is a count of the number of codes in the code
1665 * array. In typical Mach all exceptions have a code
1666 * and sub-code. It happens to be the case that for a
1667 * EXC_BAD_ACCESS exception the first entry is the type of
1668 * bad access that occurred and the second entry is the
1669 * faulting address so these entries correspond exactly to
1670 * how the code and sub-code are used on Mach.
1671 *
1672 * This is a MIG interface. No code in Basilisk II should
1673 * call this directley. This has to have external C
1674 * linkage because that is what exc_server expects.
1675 */
1676 kern_return_t
1677 catch_exception_raise(mach_port_t exception_port,
1678 mach_port_t thread,
1679 mach_port_t task,
1680 exception_type_t exception,
1681 exception_data_t code,
1682 mach_msg_type_number_t codeCount)
1683 {
1684 ppc_thread_state_t state;
1685 kern_return_t krc;
1686
1687 if ((exception == EXC_BAD_ACCESS) && (codeCount >= 2)) {
1688 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
1689 return KERN_SUCCESS;
1690 }
1691
1692 // In Mach we do not need to remove the exception handler.
1693 // If we forward the exception, eventually some exception handler
1694 // will take care of this exception.
1695 krc = forward_exception(thread, task, exception, code, codeCount, &ports);
1696
1697 return krc;
1698 }
1699 #endif
1700
1701 #ifdef HAVE_SIGSEGV_RECOVERY
1702 // Handle bad memory accesses with signal handler
1703 static void sigsegv_handler(SIGSEGV_FAULT_HANDLER_ARGLIST)
1704 {
1705 // Call handler and reinstall the global handler, if required
1706 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS)) {
1707 #if (defined(HAVE_SIGACTION) ? defined(SIGACTION_NEED_REINSTALL) : defined(SIGNAL_NEED_REINSTALL))
1708 sigsegv_do_install_handler(sig);
1709 #endif
1710 return;
1711 }
1712
1713 // Failure: reinstall default handler for "safe" crash
1714 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
1715 SIGSEGV_ALL_SIGNALS
1716 #undef FAULT_HANDLER
1717 }
1718 #endif
1719
1720
1721 /*
1722 * SIGSEGV handler initialization
1723 */
1724
1725 #if defined(HAVE_SIGINFO_T)
1726 static bool sigsegv_do_install_handler(int sig)
1727 {
1728 // Setup SIGSEGV handler to process writes to frame buffer
1729 #ifdef HAVE_SIGACTION
1730 struct sigaction sigsegv_sa;
1731 sigemptyset(&sigsegv_sa.sa_mask);
1732 sigsegv_sa.sa_sigaction = sigsegv_handler;
1733 sigsegv_sa.sa_flags = SA_SIGINFO;
1734 return (sigaction(sig, &sigsegv_sa, 0) == 0);
1735 #else
1736 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
1737 #endif
1738 }
1739 #endif
1740
1741 #if defined(HAVE_SIGCONTEXT_SUBTERFUGE)
1742 static bool sigsegv_do_install_handler(int sig)
1743 {
1744 // Setup SIGSEGV handler to process writes to frame buffer
1745 #ifdef HAVE_SIGACTION
1746 struct sigaction sigsegv_sa;
1747 sigemptyset(&sigsegv_sa.sa_mask);
1748 sigsegv_sa.sa_handler = (signal_handler)sigsegv_handler;
1749 sigsegv_sa.sa_flags = 0;
1750 #if !EMULATED_68K && defined(__NetBSD__)
1751 sigaddset(&sigsegv_sa.sa_mask, SIGALRM);
1752 sigsegv_sa.sa_flags |= SA_ONSTACK;
1753 #endif
1754 return (sigaction(sig, &sigsegv_sa, 0) == 0);
1755 #else
1756 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
1757 #endif
1758 }
1759 #endif
1760
1761 #if defined(HAVE_MACH_EXCEPTIONS)
1762 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
1763 {
1764 /*
1765 * Except for the exception port functions, this should be
1766 * pretty much stock Mach. If later you choose to support
1767 * other Mach's besides Darwin, just check for __MACH__
1768 * here and __APPLE__ where the actual differences are.
1769 */
1770 #if defined(__APPLE__) && defined(__MACH__)
1771 if (sigsegv_fault_handler != NULL) {
1772 sigsegv_fault_handler = handler;
1773 return true;
1774 }
1775
1776 kern_return_t krc;
1777
1778 // create the the exception port
1779 krc = mach_port_allocate(mach_task_self(),
1780 MACH_PORT_RIGHT_RECEIVE, &_exceptionPort);
1781 if (krc != KERN_SUCCESS) {
1782 mach_error("mach_port_allocate", krc);
1783 return false;
1784 }
1785
1786 // add a port send right
1787 krc = mach_port_insert_right(mach_task_self(),
1788 _exceptionPort, _exceptionPort,
1789 MACH_MSG_TYPE_MAKE_SEND);
1790 if (krc != KERN_SUCCESS) {
1791 mach_error("mach_port_insert_right", krc);
1792 return false;
1793 }
1794
1795 // get the old exception ports
1796 ports.maskCount = sizeof (ports.masks) / sizeof (ports.masks[0]);
1797 krc = thread_get_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, ports.masks,
1798 &ports.maskCount, ports.handlers, ports.behaviors, ports.flavors);
1799 if (krc != KERN_SUCCESS) {
1800 mach_error("thread_get_exception_ports", krc);
1801 return false;
1802 }
1803
1804 // set the new exception port
1805 //
1806 // We could have used EXCEPTION_STATE_IDENTITY instead of
1807 // EXCEPTION_DEFAULT to get the thread state in the initial
1808 // message, but it turns out that in the common case this is not
1809 // neccessary. If we need it we can later ask for it from the
1810 // suspended thread.
1811 //
1812 // Even with THREAD_STATE_NONE, Darwin provides the program
1813 // counter in the thread state. The comments in the header file
1814 // seem to imply that you can count on the GPR's on an exception
1815 // as well but just to be safe I use MACHINE_THREAD_STATE because
1816 // you have to ask for all of the GPR's anyway just to get the
1817 // program counter. In any case because of update effective
1818 // address from immediate and update address from effective
1819 // addresses of ra and rb modes (as good an name as any for these
1820 // addressing modes) used in PPC instructions, you will need the
1821 // GPR state anyway.
1822 krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
1823 EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
1824 if (krc != KERN_SUCCESS) {
1825 mach_error("thread_set_exception_ports", krc);
1826 return false;
1827 }
1828
1829 // create the exception handler thread
1830 if (pthread_create(&exc_thread, NULL, &handleExceptions, NULL) != 0) {
1831 (void)fprintf(stderr, "creation of exception thread failed\n");
1832 return false;
1833 }
1834
1835 // do not care about the exception thread any longer, let is run standalone
1836 (void)pthread_detach(exc_thread);
1837
1838 sigsegv_fault_handler = handler;
1839 return true;
1840 #else
1841 return false;
1842 #endif
1843 }
1844 #endif
1845
1846 #ifdef HAVE_WIN32_EXCEPTIONS
1847 static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo)
1848 {
1849 if (sigsegv_fault_handler != NULL
1850 && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
1851 && ExceptionInfo->ExceptionRecord->NumberParameters == 2
1852 && handle_badaccess(ExceptionInfo))
1853 return EXCEPTION_CONTINUE_EXECUTION;
1854
1855 return EXCEPTION_CONTINUE_SEARCH;
1856 }
1857
1858 #if defined __CYGWIN__ && defined __i386__
1859 /* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
1860 installs a global exception handler. We have to dig deep in order to install
1861 our main_exception_filter. */
1862
1863 /* Data structures for the current thread's exception handler chain.
1864 On the x86 Windows uses register fs, offset 0 to point to the current
1865 exception handler; Cygwin mucks with it, so we must do the same... :-/ */
1866
1867 /* Magic taken from winsup/cygwin/include/exceptions.h. */
1868
1869 struct exception_list {
1870 struct exception_list *prev;
1871 int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
1872 };
1873 typedef struct exception_list exception_list;
1874
1875 /* Magic taken from winsup/cygwin/exceptions.cc. */
1876
1877 __asm__ (".equ __except_list,0");
1878
1879 extern exception_list *_except_list __asm__ ("%fs:__except_list");
1880
1881 /* For debugging. _except_list is not otherwise accessible from gdb. */
1882 static exception_list *
1883 debug_get_except_list ()
1884 {
1885 return _except_list;
1886 }
1887
1888 /* Cygwin's original exception handler. */
1889 static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
1890
1891 /* Our exception handler. */
1892 static int
1893 libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
1894 {
1895 EXCEPTION_POINTERS ExceptionInfo;
1896 ExceptionInfo.ExceptionRecord = exception;
1897 ExceptionInfo.ContextRecord = context;
1898 if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
1899 return cygwin_exception_handler (exception, frame, context, dispatch);
1900 else
1901 return 0;
1902 }
1903
1904 static void
1905 do_install_main_exception_filter ()
1906 {
1907 /* We cannot insert any handler into the chain, because such handlers
1908 must lie on the stack (?). Instead, we have to replace(!) Cygwin's
1909 global exception handler. */
1910 cygwin_exception_handler = _except_list->handler;
1911 _except_list->handler = libsigsegv_exception_handler;
1912 }
1913
1914 #else
1915
1916 static void
1917 do_install_main_exception_filter ()
1918 {
1919 SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
1920 }
1921 #endif
1922
1923 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
1924 {
1925 static bool main_exception_filter_installed = false;
1926 if (!main_exception_filter_installed) {
1927 do_install_main_exception_filter();
1928 main_exception_filter_installed = true;
1929 }
1930 sigsegv_fault_handler = handler;
1931 return true;
1932 }
1933 #endif
1934
1935 bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
1936 {
1937 #if defined(HAVE_SIGSEGV_RECOVERY)
1938 bool success = true;
1939 #define FAULT_HANDLER(sig) success = success && sigsegv_do_install_handler(sig);
1940 SIGSEGV_ALL_SIGNALS
1941 #undef FAULT_HANDLER
1942 if (success)
1943 sigsegv_fault_handler = handler;
1944 return success;
1945 #elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS)
1946 return sigsegv_do_install_handler(handler);
1947 #else
1948 // FAIL: no siginfo_t nor sigcontext subterfuge is available
1949 return false;
1950 #endif
1951 }
1952
1953
1954 /*
1955 * SIGSEGV handler deinitialization
1956 */
1957
1958 void sigsegv_deinstall_handler(void)
1959 {
1960 // We do nothing for Mach exceptions, the thread would need to be
1961 // suspended if not already so, and we might mess with other
1962 // exception handlers that came after we registered ours. There is
1963 // no need to remove the exception handler, in fact this function is
1964 // not called anywhere in Basilisk II.
1965 #ifdef HAVE_SIGSEGV_RECOVERY
1966 sigsegv_fault_handler = 0;
1967 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
1968 SIGSEGV_ALL_SIGNALS
1969 #undef FAULT_HANDLER
1970 #endif
1971 #ifdef HAVE_WIN32_EXCEPTIONS
1972 sigsegv_fault_handler = NULL;
1973 #endif
1974 }
1975
1976
1977 /*
1978 * Set callback function when we cannot handle the fault
1979 */
1980
1981 void sigsegv_set_dump_state(sigsegv_state_dumper_t handler)
1982 {
1983 sigsegv_state_dumper = handler;
1984 }
1985
1986
1987 /*
1988 * Test program used for configure/test
1989 */
1990
1991 #ifdef CONFIGURE_TEST_SIGSEGV_RECOVERY
1992 #include <stdio.h>
1993 #include <stdlib.h>
1994 #include <fcntl.h>
1995 #ifdef HAVE_SYS_MMAN_H
1996 #include <sys/mman.h>
1997 #endif
1998 #include "vm_alloc.h"
1999
2000 const int REF_INDEX = 123;
2001 const int REF_VALUE = 45;
2002
2003 static int page_size;
2004 static volatile char * page = 0;
2005 static volatile int handler_called = 0;
2006
2007 #ifdef __GNUC__
2008 // Code range where we expect the fault to come from
2009 static void *b_region, *e_region;
2010 #endif
2011
2012 static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
2013 {
2014 #if DEBUG
2015 printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
2016 printf("expected fault at %p\n", page + REF_INDEX);
2017 #ifdef __GNUC__
2018 printf("expected instruction address range: %p-%p\n", b_region, e_region);
2019 #endif
2020 #endif
2021 handler_called++;
2022 if ((fault_address - REF_INDEX) != page)
2023 exit(10);
2024 #ifdef __GNUC__
2025 // Make sure reported fault instruction address falls into
2026 // expected code range
2027 if (instruction_address != SIGSEGV_INVALID_PC
2028 && ((instruction_address < (sigsegv_address_t)b_region) ||
2029 (instruction_address >= (sigsegv_address_t)e_region)))
2030 exit(11);
2031 #endif
2032 if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
2033 exit(12);
2034 return SIGSEGV_RETURN_SUCCESS;
2035 }
2036
2037 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
2038 static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
2039 {
2040 #if DEBUG
2041 printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
2042 #endif
2043 if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
2044 #ifdef __GNUC__
2045 // Make sure reported fault instruction address falls into
2046 // expected code range
2047 if (instruction_address != SIGSEGV_INVALID_PC
2048 && ((instruction_address < (sigsegv_address_t)b_region) ||
2049 (instruction_address >= (sigsegv_address_t)e_region)))
2050 return SIGSEGV_RETURN_FAILURE;
2051 #endif
2052 return SIGSEGV_RETURN_SKIP_INSTRUCTION;
2053 }
2054
2055 return SIGSEGV_RETURN_FAILURE;
2056 }
2057
2058 // More sophisticated tests for instruction skipper
2059 static bool arch_insn_skipper_tests()
2060 {
2061 #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
2062 static const unsigned char code[] = {
2063 0x8a, 0x00, // mov (%eax),%al
2064 0x8a, 0x2c, 0x18, // mov (%eax,%ebx,1),%ch
2065 0x88, 0x20, // mov %ah,(%eax)
2066 0x88, 0x08, // mov %cl,(%eax)
2067 0x66, 0x8b, 0x00, // mov (%eax),%ax
2068 0x66, 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%cx
2069 0x66, 0x89, 0x00, // mov %ax,(%eax)
2070 0x66, 0x89, 0x0c, 0x18, // mov %cx,(%eax,%ebx,1)
2071 0x8b, 0x00, // mov (%eax),%eax
2072 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%ecx
2073 0x89, 0x00, // mov %eax,(%eax)
2074 0x89, 0x0c, 0x18, // mov %ecx,(%eax,%ebx,1)
2075 #if defined(__x86_64__)
2076 0x44, 0x8a, 0x00, // mov (%rax),%r8b
2077 0x44, 0x8a, 0x20, // mov (%rax),%r12b
2078 0x42, 0x8a, 0x3c, 0x10, // mov (%rax,%r10,1),%dil
2079 0x44, 0x88, 0x00, // mov %r8b,(%rax)
2080 0x44, 0x88, 0x20, // mov %r12b,(%rax)
2081 0x42, 0x88, 0x3c, 0x10, // mov %dil,(%rax,%r10,1)
2082 0x66, 0x44, 0x8b, 0x00, // mov (%rax),%r8w
2083 0x66, 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%cx
2084 0x66, 0x44, 0x89, 0x00, // mov %r8w,(%rax)
2085 0x66, 0x42, 0x89, 0x0c, 0x10, // mov %cx,(%rax,%r10,1)
2086 0x44, 0x8b, 0x00, // mov (%rax),%r8d
2087 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%ecx
2088 0x44, 0x89, 0x00, // mov %r8d,(%rax)
2089 0x42, 0x89, 0x0c, 0x10, // mov %ecx,(%rax,%r10,1)
2090 0x48, 0x8b, 0x08, // mov (%rax),%rcx
2091 0x4c, 0x8b, 0x18, // mov (%rax),%r11
2092 0x4a, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%rcx
2093 0x4e, 0x8b, 0x1c, 0x10, // mov (%rax,%r10,1),%r11
2094 0x48, 0x89, 0x08, // mov %rcx,(%rax)
2095 0x4c, 0x89, 0x18, // mov %r11,(%rax)
2096 0x4a, 0x89, 0x0c, 0x10, // mov %rcx,(%rax,%r10,1)
2097 0x4e, 0x89, 0x1c, 0x10, // mov %r11,(%rax,%r10,1)
2098 #endif
2099 0 // end
2100 };
2101 const int N_REGS = 20;
2102 unsigned long regs[N_REGS];
2103 for (int i = 0; i < N_REGS; i++)
2104 regs[i] = i;
2105 const unsigned long start_code = (unsigned long)&code;
2106 regs[X86_REG_EIP] = start_code;
2107 while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
2108 && ix86_skip_instruction(regs))
2109 ; /* simply iterate */
2110 return (regs[X86_REG_EIP] - start_code) == (sizeof(code) - 1);
2111 #endif
2112 return true;
2113 }
2114 #endif
2115
2116 int main(void)
2117 {
2118 if (vm_init() < 0)
2119 return 1;
2120
2121 #ifdef _WIN32
2122 page_size = 4096;
2123 #else
2124 page_size = getpagesize();
2125 #endif
2126 if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
2127 return 2;
2128
2129 memset((void *)page, 0, page_size);
2130 if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0)
2131 return 3;
2132
2133 if (!sigsegv_install_handler(sigsegv_test_handler))
2134 return 4;
2135
2136 #ifdef __GNUC__
2137 b_region = &&L_b_region1;
2138 e_region = &&L_e_region1;
2139 #endif
2140 L_b_region1:
2141 page[REF_INDEX] = REF_VALUE;
2142 if (page[REF_INDEX] != REF_VALUE)
2143 exit(20);
2144 page[REF_INDEX] = REF_VALUE;
2145 L_e_region1:
2146
2147 if (handler_called != 1)
2148 return 5;
2149
2150 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
2151 if (!sigsegv_install_handler(sigsegv_insn_handler))
2152 return 6;
2153
2154 if (vm_protect((char *)page, page_size, VM_PAGE_READ | VM_PAGE_WRITE) < 0)
2155 return 7;
2156
2157 for (int i = 0; i < page_size; i++)
2158 page[i] = (i + 1) % page_size;
2159
2160 if (vm_protect((char *)page, page_size, VM_PAGE_NOACCESS) < 0)
2161 return 8;
2162
2163 #define TEST_SKIP_INSTRUCTION(TYPE) do { \
2164 const unsigned long TAG = 0x12345678 | \
2165 (sizeof(long) == 8 ? 0x9abcdef0UL << 31 : 0); \
2166 TYPE data = *((TYPE *)(page + sizeof(TYPE))); \
2167 volatile unsigned long effect = data + TAG; \
2168 if (effect != TAG) \
2169 return 9; \
2170 } while (0)
2171
2172 #ifdef __GNUC__
2173 b_region = &&L_b_region2;
2174 e_region = &&L_e_region2;
2175 #endif
2176 L_b_region2:
2177 TEST_SKIP_INSTRUCTION(unsigned char);
2178 TEST_SKIP_INSTRUCTION(unsigned short);
2179 TEST_SKIP_INSTRUCTION(unsigned int);
2180 TEST_SKIP_INSTRUCTION(unsigned long);
2181 TEST_SKIP_INSTRUCTION(signed char);
2182 TEST_SKIP_INSTRUCTION(signed short);
2183 TEST_SKIP_INSTRUCTION(signed int);
2184 TEST_SKIP_INSTRUCTION(signed long);
2185 L_e_region2:
2186
2187 if (!arch_insn_skipper_tests())
2188 return 20;
2189 #endif
2190
2191 vm_exit();
2192 return 0;
2193 }
2194 #endif