ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.48
Committed: 2004-11-13T23:44:11Z (20 years ago) by gbeauche
Branch: MAIN
Changes since 1.47: +128 -3 lines
Log Message:
Integrate SIGSEGV recovery from libsigsegv for Windows and Cygwin.
Also implement instruction skipper for Windows/x86.

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