ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.50
Committed: 2004-12-11T13:07:38Z (19 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.49: +8 -5 lines
Log Message:
Check that we can really read at the faulty eip in Windows prior to decoding
the instruction. Also fix the unrecoverable fault dump to really be useful.

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