ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.49
Committed: 2004-12-02T23:29:52Z (19 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.48: +20 -6 lines
Log Message:
ppc64 fixes

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
758 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
759 transfer_size_t transfer_size = SIZE_LONG;
760
761 int reg = -1;
762 int len = 0;
763
764 #if DEBUG
765 printf("IP: %p [%02x %02x %02x %02x...]\n",
766 eip, eip[0], eip[1], eip[2], eip[3]);
767 #endif
768
769 // Operand size prefix
770 if (*eip == 0x66) {
771 eip++;
772 len++;
773 transfer_size = SIZE_WORD;
774 }
775
776 // REX prefix
777 #if defined(__x86_64__)
778 struct rex_t {
779 unsigned char W;
780 unsigned char R;
781 unsigned char X;
782 unsigned char B;
783 };
784 rex_t rex = { 0, 0, 0, 0 };
785 bool has_rex = false;
786 if ((*eip & 0xf0) == 0x40) {
787 has_rex = true;
788 const unsigned char b = *eip;
789 rex.W = b & (1 << 3);
790 rex.R = b & (1 << 2);
791 rex.X = b & (1 << 1);
792 rex.B = b & (1 << 0);
793 #if DEBUG
794 printf("REX: %c,%c,%c,%c\n",
795 rex.W ? 'W' : '_',
796 rex.R ? 'R' : '_',
797 rex.X ? 'X' : '_',
798 rex.B ? 'B' : '_');
799 #endif
800 eip++;
801 len++;
802 if (rex.W)
803 transfer_size = SIZE_QUAD;
804 }
805 #else
806 const bool has_rex = false;
807 #endif
808
809 // Decode instruction
810 int target_size = SIZE_UNKNOWN;
811 switch (eip[0]) {
812 case 0x0f:
813 target_size = transfer_size;
814 switch (eip[1]) {
815 case 0xbe: // MOVSX r32, r/m8
816 case 0xb6: // MOVZX r32, r/m8
817 transfer_size = SIZE_BYTE;
818 goto do_mov_extend;
819 case 0xbf: // MOVSX r32, r/m16
820 case 0xb7: // MOVZX r32, r/m16
821 transfer_size = SIZE_WORD;
822 goto do_mov_extend;
823 do_mov_extend:
824 switch (eip[2] & 0xc0) {
825 case 0x80:
826 reg = (eip[2] >> 3) & 7;
827 transfer_type = SIGSEGV_TRANSFER_LOAD;
828 break;
829 case 0x40:
830 reg = (eip[2] >> 3) & 7;
831 transfer_type = SIGSEGV_TRANSFER_LOAD;
832 break;
833 case 0x00:
834 reg = (eip[2] >> 3) & 7;
835 transfer_type = SIGSEGV_TRANSFER_LOAD;
836 break;
837 }
838 len += 3 + ix86_step_over_modrm(eip + 2);
839 break;
840 }
841 break;
842 case 0x8a: // MOV r8, r/m8
843 transfer_size = SIZE_BYTE;
844 case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
845 switch (eip[1] & 0xc0) {
846 case 0x80:
847 reg = (eip[1] >> 3) & 7;
848 transfer_type = SIGSEGV_TRANSFER_LOAD;
849 break;
850 case 0x40:
851 reg = (eip[1] >> 3) & 7;
852 transfer_type = SIGSEGV_TRANSFER_LOAD;
853 break;
854 case 0x00:
855 reg = (eip[1] >> 3) & 7;
856 transfer_type = SIGSEGV_TRANSFER_LOAD;
857 break;
858 }
859 len += 2 + ix86_step_over_modrm(eip + 1);
860 break;
861 case 0x88: // MOV r/m8, r8
862 transfer_size = SIZE_BYTE;
863 case 0x89: // MOV r/m32, r32 (or 16-bit operation)
864 switch (eip[1] & 0xc0) {
865 case 0x80:
866 reg = (eip[1] >> 3) & 7;
867 transfer_type = SIGSEGV_TRANSFER_STORE;
868 break;
869 case 0x40:
870 reg = (eip[1] >> 3) & 7;
871 transfer_type = SIGSEGV_TRANSFER_STORE;
872 break;
873 case 0x00:
874 reg = (eip[1] >> 3) & 7;
875 transfer_type = SIGSEGV_TRANSFER_STORE;
876 break;
877 }
878 len += 2 + ix86_step_over_modrm(eip + 1);
879 break;
880 }
881 if (target_size == SIZE_UNKNOWN)
882 target_size = transfer_size;
883
884 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
885 // Unknown machine code, let it crash. Then patch the decoder
886 return false;
887 }
888
889 #if defined(__x86_64__)
890 if (rex.R)
891 reg += 8;
892 #endif
893
894 if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
895 static const int x86_reg_map[] = {
896 X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
897 X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
898 #if defined(__x86_64__)
899 X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11,
900 X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
901 #endif
902 };
903
904 if (reg < 0 || reg >= (sizeof(x86_reg_map)/sizeof(x86_reg_map[0]) - 1))
905 return false;
906
907 // Set 0 to the relevant register part
908 // NOTE: this is only valid for MOV alike instructions
909 int rloc = x86_reg_map[reg];
910 switch (target_size) {
911 case SIZE_BYTE:
912 if (has_rex || reg < 4)
913 regs[rloc] = (regs[rloc] & ~0x00ffL);
914 else {
915 rloc = x86_reg_map[reg - 4];
916 regs[rloc] = (regs[rloc] & ~0xff00L);
917 }
918 break;
919 case SIZE_WORD:
920 regs[rloc] = (regs[rloc] & ~0xffffL);
921 break;
922 case SIZE_LONG:
923 case SIZE_QUAD: // zero-extension
924 regs[rloc] = 0;
925 break;
926 }
927 }
928
929 #if DEBUG
930 printf("%08x: %s %s access", regs[X86_REG_EIP],
931 transfer_size == SIZE_BYTE ? "byte" :
932 transfer_size == SIZE_WORD ? "word" :
933 transfer_size == SIZE_LONG ? "long" :
934 transfer_size == SIZE_QUAD ? "quad" : "unknown",
935 transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
936
937 if (reg != -1) {
938 static const char * x86_byte_reg_str_map[] = {
939 "al", "cl", "dl", "bl",
940 "spl", "bpl", "sil", "dil",
941 "r8b", "r9b", "r10b", "r11b",
942 "r12b", "r13b", "r14b", "r15b",
943 "ah", "ch", "dh", "bh",
944 };
945 static const char * x86_word_reg_str_map[] = {
946 "ax", "cx", "dx", "bx",
947 "sp", "bp", "si", "di",
948 "r8w", "r9w", "r10w", "r11w",
949 "r12w", "r13w", "r14w", "r15w",
950 };
951 static const char *x86_long_reg_str_map[] = {
952 "eax", "ecx", "edx", "ebx",
953 "esp", "ebp", "esi", "edi",
954 "r8d", "r9d", "r10d", "r11d",
955 "r12d", "r13d", "r14d", "r15d",
956 };
957 static const char *x86_quad_reg_str_map[] = {
958 "rax", "rcx", "rdx", "rbx",
959 "rsp", "rbp", "rsi", "rdi",
960 "r8", "r9", "r10", "r11",
961 "r12", "r13", "r14", "r15",
962 };
963 const char * reg_str = NULL;
964 switch (target_size) {
965 case SIZE_BYTE:
966 reg_str = x86_byte_reg_str_map[(!has_rex && reg >= 4 ? 12 : 0) + reg];
967 break;
968 case SIZE_WORD: reg_str = x86_word_reg_str_map[reg]; break;
969 case SIZE_LONG: reg_str = x86_long_reg_str_map[reg]; break;
970 case SIZE_QUAD: reg_str = x86_quad_reg_str_map[reg]; break;
971 }
972 if (reg_str)
973 printf(" %s register %%%s",
974 transfer_type == SIGSEGV_TRANSFER_LOAD ? "to" : "from",
975 reg_str);
976 }
977 printf(", %d bytes instruction\n", len);
978 #endif
979
980 regs[X86_REG_EIP] += len;
981 return true;
982 }
983 #endif
984
985 // Decode and skip PPC instruction
986 #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
987 static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
988 {
989 instruction_t instr;
990 powerpc_decode_instruction(&instr, *nip_p, regs);
991
992 if (instr.transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
993 // Unknown machine code, let it crash. Then patch the decoder
994 return false;
995 }
996
997 #if DEBUG
998 printf("%08x: %s %s access", *nip_p,
999 instr.transfer_size == SIZE_BYTE ? "byte" :
1000 instr.transfer_size == SIZE_WORD ? "word" :
1001 instr.transfer_size == SIZE_LONG ? "long" : "quad",
1002 instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
1003
1004 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1005 printf(" r%d (ra = %08x)\n", instr.ra, instr.addr);
1006 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1007 printf(" r%d (rd = 0)\n", instr.rd);
1008 #endif
1009
1010 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1011 regs[instr.ra] = instr.addr;
1012 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1013 regs[instr.rd] = 0;
1014
1015 *nip_p += 4;
1016 return true;
1017 }
1018 #endif
1019
1020 // Decode and skip MIPS instruction
1021 #if (defined(mips) || defined(__mips))
1022 enum {
1023 #if (defined(sgi) || defined(__sgi))
1024 MIPS_REG_EPC = 35,
1025 #endif
1026 };
1027 static bool mips_skip_instruction(greg_t * regs)
1028 {
1029 unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
1030
1031 if (epc == 0)
1032 return false;
1033
1034 #if DEBUG
1035 printf("IP: %p [%08x]\n", epc, epc[0]);
1036 #endif
1037
1038 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1039 transfer_size_t transfer_size = SIZE_LONG;
1040 int direction = 0;
1041
1042 const unsigned int opcode = epc[0];
1043 switch (opcode >> 26) {
1044 case 32: // Load Byte
1045 case 36: // Load Byte Unsigned
1046 transfer_type = SIGSEGV_TRANSFER_LOAD;
1047 transfer_size = SIZE_BYTE;
1048 break;
1049 case 33: // Load Halfword
1050 case 37: // Load Halfword Unsigned
1051 transfer_type = SIGSEGV_TRANSFER_LOAD;
1052 transfer_size = SIZE_WORD;
1053 break;
1054 case 35: // Load Word
1055 case 39: // Load Word Unsigned
1056 transfer_type = SIGSEGV_TRANSFER_LOAD;
1057 transfer_size = SIZE_LONG;
1058 break;
1059 case 34: // Load Word Left
1060 transfer_type = SIGSEGV_TRANSFER_LOAD;
1061 transfer_size = SIZE_LONG;
1062 direction = -1;
1063 break;
1064 case 38: // Load Word Right
1065 transfer_type = SIGSEGV_TRANSFER_LOAD;
1066 transfer_size = SIZE_LONG;
1067 direction = 1;
1068 break;
1069 case 55: // Load Doubleword
1070 transfer_type = SIGSEGV_TRANSFER_LOAD;
1071 transfer_size = SIZE_QUAD;
1072 break;
1073 case 26: // Load Doubleword Left
1074 transfer_type = SIGSEGV_TRANSFER_LOAD;
1075 transfer_size = SIZE_QUAD;
1076 direction = -1;
1077 break;
1078 case 27: // Load Doubleword Right
1079 transfer_type = SIGSEGV_TRANSFER_LOAD;
1080 transfer_size = SIZE_QUAD;
1081 direction = 1;
1082 break;
1083 case 40: // Store Byte
1084 transfer_type = SIGSEGV_TRANSFER_STORE;
1085 transfer_size = SIZE_BYTE;
1086 break;
1087 case 41: // Store Halfword
1088 transfer_type = SIGSEGV_TRANSFER_STORE;
1089 transfer_size = SIZE_WORD;
1090 break;
1091 case 43: // Store Word
1092 case 42: // Store Word Left
1093 case 46: // Store Word Right
1094 transfer_type = SIGSEGV_TRANSFER_STORE;
1095 transfer_size = SIZE_LONG;
1096 break;
1097 case 63: // Store Doubleword
1098 case 44: // Store Doubleword Left
1099 case 45: // Store Doubleword Right
1100 transfer_type = SIGSEGV_TRANSFER_STORE;
1101 transfer_size = SIZE_QUAD;
1102 break;
1103 /* Misc instructions unlikely to be used within CPU emulators */
1104 case 48: // Load Linked Word
1105 transfer_type = SIGSEGV_TRANSFER_LOAD;
1106 transfer_size = SIZE_LONG;
1107 break;
1108 case 52: // Load Linked Doubleword
1109 transfer_type = SIGSEGV_TRANSFER_LOAD;
1110 transfer_size = SIZE_QUAD;
1111 break;
1112 case 56: // Store Conditional Word
1113 transfer_type = SIGSEGV_TRANSFER_STORE;
1114 transfer_size = SIZE_LONG;
1115 break;
1116 case 60: // Store Conditional Doubleword
1117 transfer_type = SIGSEGV_TRANSFER_STORE;
1118 transfer_size = SIZE_QUAD;
1119 break;
1120 }
1121
1122 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1123 // Unknown machine code, let it crash. Then patch the decoder
1124 return false;
1125 }
1126
1127 // Zero target register in case of a load operation
1128 const int reg = (opcode >> 16) & 0x1f;
1129 if (transfer_type == SIGSEGV_TRANSFER_LOAD) {
1130 if (direction == 0)
1131 regs[reg] = 0;
1132 else {
1133 // FIXME: untested code
1134 unsigned long ea = regs[(opcode >> 21) & 0x1f];
1135 ea += (signed long)(signed int)(signed short)(opcode & 0xffff);
1136 const int offset = ea & (transfer_size == SIZE_LONG ? 3 : 7);
1137 unsigned long value;
1138 if (direction > 0) {
1139 const unsigned long rmask = ~((1L << ((offset + 1) * 8)) - 1);
1140 value = regs[reg] & rmask;
1141 }
1142 else {
1143 const unsigned long lmask = (1L << (offset * 8)) - 1;
1144 value = regs[reg] & lmask;
1145 }
1146 // restore most significant bits
1147 if (transfer_size == SIZE_LONG)
1148 value = (signed long)(signed int)value;
1149 regs[reg] = value;
1150 }
1151 }
1152
1153 #if DEBUG
1154 #if (defined(_ABIN32) || defined(_ABI64))
1155 static const char * mips_gpr_names[32] = {
1156 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1157 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1158 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1159 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
1160 };
1161 #else
1162 static const char * mips_gpr_names[32] = {
1163 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1164 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
1165 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1166 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
1167 };
1168 #endif
1169 printf("%s %s register %s\n",
1170 transfer_size == SIZE_BYTE ? "byte" :
1171 transfer_size == SIZE_WORD ? "word" :
1172 transfer_size == SIZE_LONG ? "long" :
1173 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1174 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1175 mips_gpr_names[reg]);
1176 #endif
1177
1178 regs[MIPS_REG_EPC] += 4;
1179 return true;
1180 }
1181 #endif
1182
1183 // Decode and skip SPARC instruction
1184 #if (defined(sparc) || defined(__sparc__))
1185 enum {
1186 #if (defined(__sun__))
1187 SPARC_REG_G1 = REG_G1,
1188 SPARC_REG_O0 = REG_O0,
1189 SPARC_REG_PC = REG_PC,
1190 #endif
1191 };
1192 static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
1193 {
1194 unsigned int * pc = (unsigned int *)regs[SPARC_REG_PC];
1195
1196 if (pc == 0)
1197 return false;
1198
1199 #if DEBUG
1200 printf("IP: %p [%08x]\n", pc, pc[0]);
1201 #endif
1202
1203 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1204 transfer_size_t transfer_size = SIZE_LONG;
1205 bool register_pair = false;
1206
1207 const unsigned int opcode = pc[0];
1208 if ((opcode >> 30) != 3)
1209 return false;
1210 switch ((opcode >> 19) & 0x3f) {
1211 case 9: // Load Signed Byte
1212 case 1: // Load Unsigned Byte
1213 transfer_type = SIGSEGV_TRANSFER_LOAD;
1214 transfer_size = SIZE_BYTE;
1215 break;
1216 case 10:// Load Signed Halfword
1217 case 2: // Load Unsigned Word
1218 transfer_type = SIGSEGV_TRANSFER_LOAD;
1219 transfer_size = SIZE_WORD;
1220 break;
1221 case 8: // Load Word
1222 case 0: // Load Unsigned Word
1223 transfer_type = SIGSEGV_TRANSFER_LOAD;
1224 transfer_size = SIZE_LONG;
1225 break;
1226 case 11:// Load Extended Word
1227 transfer_type = SIGSEGV_TRANSFER_LOAD;
1228 transfer_size = SIZE_QUAD;
1229 break;
1230 case 3: // Load Doubleword
1231 transfer_type = SIGSEGV_TRANSFER_LOAD;
1232 transfer_size = SIZE_LONG;
1233 register_pair = true;
1234 break;
1235 case 5: // Store Byte
1236 transfer_type = SIGSEGV_TRANSFER_STORE;
1237 transfer_size = SIZE_BYTE;
1238 break;
1239 case 6: // Store Halfword
1240 transfer_type = SIGSEGV_TRANSFER_STORE;
1241 transfer_size = SIZE_WORD;
1242 break;
1243 case 4: // Store Word
1244 transfer_type = SIGSEGV_TRANSFER_STORE;
1245 transfer_size = SIZE_LONG;
1246 break;
1247 case 14:// Store Extended Word
1248 transfer_type = SIGSEGV_TRANSFER_STORE;
1249 transfer_size = SIZE_QUAD;
1250 break;
1251 case 7: // Store Doubleword
1252 transfer_type = SIGSEGV_TRANSFER_STORE;
1253 transfer_size = SIZE_WORD;
1254 register_pair = true;
1255 break;
1256 }
1257
1258 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1259 // Unknown machine code, let it crash. Then patch the decoder
1260 return false;
1261 }
1262
1263 // Zero target register in case of a load operation
1264 const int reg = (opcode >> 25) & 0x1f;
1265 if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
1266 // FIXME: code to handle local & input registers is not tested
1267 if (reg >= 1 && reg <= 7) {
1268 // global registers
1269 regs[reg - 1 + SPARC_REG_G1] = 0;
1270 }
1271 else if (reg >= 8 && reg <= 15) {
1272 // output registers
1273 regs[reg - 8 + SPARC_REG_O0] = 0;
1274 }
1275 else if (reg >= 16 && reg <= 23) {
1276 // local registers (in register windows)
1277 if (gwins)
1278 gwins->wbuf->rw_local[reg - 16] = 0;
1279 else
1280 rwin->rw_local[reg - 16] = 0;
1281 }
1282 else {
1283 // input registers (in register windows)
1284 if (gwins)
1285 gwins->wbuf->rw_in[reg - 24] = 0;
1286 else
1287 rwin->rw_in[reg - 24] = 0;
1288 }
1289 }
1290
1291 #if DEBUG
1292 static const char * reg_names[] = {
1293 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1294 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1295 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1296 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1297 };
1298 printf("%s %s register %s\n",
1299 transfer_size == SIZE_BYTE ? "byte" :
1300 transfer_size == SIZE_WORD ? "word" :
1301 transfer_size == SIZE_LONG ? "long" :
1302 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1303 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1304 reg_names[reg]);
1305 #endif
1306
1307 regs[SPARC_REG_PC] += 4;
1308 return true;
1309 }
1310 #endif
1311 #endif
1312
1313 // Decode and skip ARM instruction
1314 #if (defined(arm) || defined(__arm__))
1315 enum {
1316 #if (defined(__linux__))
1317 ARM_REG_PC = 15,
1318 ARM_REG_CPSR = 16
1319 #endif
1320 };
1321 static bool arm_skip_instruction(unsigned long * regs)
1322 {
1323 unsigned int * pc = (unsigned int *)regs[ARM_REG_PC];
1324
1325 if (pc == 0)
1326 return false;
1327
1328 #if DEBUG
1329 printf("IP: %p [%08x]\n", pc, pc[0]);
1330 #endif
1331
1332 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1333 transfer_size_t transfer_size = SIZE_UNKNOWN;
1334 enum { op_sdt = 1, op_sdth = 2 };
1335 int op = 0;
1336
1337 // Handle load/store instructions only
1338 const unsigned int opcode = pc[0];
1339 switch ((opcode >> 25) & 7) {
1340 case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH)
1341 op = op_sdth;
1342 // Determine transfer size (S/H bits)
1343 switch ((opcode >> 5) & 3) {
1344 case 0: // SWP instruction
1345 break;
1346 case 1: // Unsigned halfwords
1347 case 3: // Signed halfwords
1348 transfer_size = SIZE_WORD;
1349 break;
1350 case 2: // Signed byte
1351 transfer_size = SIZE_BYTE;
1352 break;
1353 }
1354 break;
1355 case 2:
1356 case 3: // Single Data Transfer (LDR, STR)
1357 op = op_sdt;
1358 // Determine transfer size (B bit)
1359 if (((opcode >> 22) & 1) == 1)
1360 transfer_size = SIZE_BYTE;
1361 else
1362 transfer_size = SIZE_LONG;
1363 break;
1364 default:
1365 // FIXME: support load/store mutliple?
1366 return false;
1367 }
1368
1369 // Check for invalid transfer size (SWP instruction?)
1370 if (transfer_size == SIZE_UNKNOWN)
1371 return false;
1372
1373 // Determine transfer type (L bit)
1374 if (((opcode >> 20) & 1) == 1)
1375 transfer_type = SIGSEGV_TRANSFER_LOAD;
1376 else
1377 transfer_type = SIGSEGV_TRANSFER_STORE;
1378
1379 // Compute offset
1380 int offset;
1381 if (((opcode >> 25) & 1) == 0) {
1382 if (op == op_sdt)
1383 offset = opcode & 0xfff;
1384 else if (op == op_sdth) {
1385 int rm = opcode & 0xf;
1386 if (((opcode >> 22) & 1) == 0) {
1387 // register offset
1388 offset = regs[rm];
1389 }
1390 else {
1391 // immediate offset
1392 offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f);
1393 }
1394 }
1395 }
1396 else {
1397 const int rm = opcode & 0xf;
1398 const int sh = (opcode >> 7) & 0x1f;
1399 if (((opcode >> 4) & 1) == 1) {
1400 // we expect only legal load/store instructions
1401 printf("FATAL: invalid shift operand\n");
1402 return false;
1403 }
1404 const unsigned int v = regs[rm];
1405 switch ((opcode >> 5) & 3) {
1406 case 0: // logical shift left
1407 offset = sh ? v << sh : v;
1408 break;
1409 case 1: // logical shift right
1410 offset = sh ? v >> sh : 0;
1411 break;
1412 case 2: // arithmetic shift right
1413 if (sh)
1414 offset = ((signed int)v) >> sh;
1415 else
1416 offset = (v & 0x80000000) ? 0xffffffff : 0;
1417 break;
1418 case 3: // rotate right
1419 if (sh)
1420 offset = (v >> sh) | (v << (32 - sh));
1421 else
1422 offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000);
1423 break;
1424 }
1425 }
1426 if (((opcode >> 23) & 1) == 0)
1427 offset = -offset;
1428
1429 int rd = (opcode >> 12) & 0xf;
1430 int rn = (opcode >> 16) & 0xf;
1431 #if DEBUG
1432 static const char * reg_names[] = {
1433 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1434 "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc"
1435 };
1436 printf("%s %s register %s\n",
1437 transfer_size == SIZE_BYTE ? "byte" :
1438 transfer_size == SIZE_WORD ? "word" :
1439 transfer_size == SIZE_LONG ? "long" : "unknown",
1440 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1441 reg_names[rd]);
1442 #endif
1443
1444 unsigned int base = regs[rn];
1445 if (((opcode >> 24) & 1) == 1)
1446 base += offset;
1447
1448 if (transfer_type == SIGSEGV_TRANSFER_LOAD)
1449 regs[rd] = 0;
1450
1451 if (((opcode >> 24) & 1) == 0) // post-index addressing
1452 regs[rn] += offset;
1453 else if (((opcode >> 21) & 1) == 1) // write-back address into base
1454 regs[rn] = base;
1455
1456 regs[ARM_REG_PC] += 4;
1457 return true;
1458 }
1459 #endif
1460
1461
1462 // Fallbacks
1463 #ifndef SIGSEGV_FAULT_INSTRUCTION
1464 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_INVALID_PC
1465 #endif
1466 #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
1467 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
1468 #endif
1469 #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
1470 #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP) sigsegv_fault_handler(ADDR, IP)
1471 #endif
1472
1473 // SIGSEGV recovery supported ?
1474 #if defined(SIGSEGV_ALL_SIGNALS) && defined(SIGSEGV_FAULT_HANDLER_ARGLIST) && defined(SIGSEGV_FAULT_ADDRESS)
1475 #define HAVE_SIGSEGV_RECOVERY
1476 #endif
1477
1478
1479 /*
1480 * SIGSEGV global handler
1481 */
1482
1483 // This function handles the badaccess to memory.
1484 // It is called from the signal handler or the exception handler.
1485 static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
1486 {
1487 sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1488 sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1489
1490 // Call user's handler and reinstall the global handler, if required
1491 switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
1492 case SIGSEGV_RETURN_SUCCESS:
1493 return true;
1494
1495 #if HAVE_SIGSEGV_SKIP_INSTRUCTION
1496 case SIGSEGV_RETURN_SKIP_INSTRUCTION:
1497 // Call the instruction skipper with the register file
1498 // available
1499 if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
1500 #ifdef HAVE_MACH_EXCEPTIONS
1501 // Unlike UNIX signals where the thread state
1502 // is modified off of the stack, in Mach we
1503 // need to actually call thread_set_state to
1504 // have the register values updated.
1505 kern_return_t krc;
1506
1507 krc = thread_set_state(thread,
1508 MACHINE_THREAD_STATE, (thread_state_t)state,
1509 MACHINE_THREAD_STATE_COUNT);
1510 MACH_CHECK_ERROR (thread_get_state, krc);
1511 #endif
1512 return true;
1513 }
1514 break;
1515 #endif
1516 case SIGSEGV_RETURN_FAILURE:
1517 return false;
1518 }
1519
1520 // We can't do anything with the fault_address, dump state?
1521 if (sigsegv_state_dumper != 0)
1522 sigsegv_state_dumper(fault_address, fault_instruction);
1523
1524 return false;
1525 }
1526
1527
1528 /*
1529 * There are two mechanisms for handling a bad memory access,
1530 * Mach exceptions and UNIX signals. The implementation specific
1531 * code appears below. Its reponsibility is to call handle_badaccess
1532 * which is the routine that handles the fault in an implementation
1533 * agnostic manner. The implementation specific code below is then
1534 * reponsible for checking whether handle_badaccess was able
1535 * to handle the memory access error and perform any implementation
1536 * specific tasks necessary afterwards.
1537 */
1538
1539 #ifdef HAVE_MACH_EXCEPTIONS
1540 /*
1541 * We need to forward all exceptions that we do not handle.
1542 * This is important, there are many exceptions that may be
1543 * handled by other exception handlers. For example debuggers
1544 * use exceptions and the exception hander is in another
1545 * process in such a case. (Timothy J. Wood states in his
1546 * message to the list that he based this code on that from
1547 * gdb for Darwin.)
1548 */
1549 static inline kern_return_t
1550 forward_exception(mach_port_t thread_port,
1551 mach_port_t task_port,
1552 exception_type_t exception_type,
1553 exception_data_t exception_data,
1554 mach_msg_type_number_t data_count,
1555 ExceptionPorts *oldExceptionPorts)
1556 {
1557 kern_return_t kret;
1558 unsigned int portIndex;
1559 mach_port_t port;
1560 exception_behavior_t behavior;
1561 thread_state_flavor_t flavor;
1562 thread_state_t thread_state;
1563 mach_msg_type_number_t thread_state_count;
1564
1565 for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
1566 if (oldExceptionPorts->masks[portIndex] & (1 << exception_type)) {
1567 // This handler wants the exception
1568 break;
1569 }
1570 }
1571
1572 if (portIndex >= oldExceptionPorts->maskCount) {
1573 fprintf(stderr, "No handler for exception_type = %d. Not fowarding\n", exception_type);
1574 return KERN_FAILURE;
1575 }
1576
1577 port = oldExceptionPorts->handlers[portIndex];
1578 behavior = oldExceptionPorts->behaviors[portIndex];
1579 flavor = oldExceptionPorts->flavors[portIndex];
1580
1581 /*
1582 fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
1583 */
1584
1585 if (behavior != EXCEPTION_DEFAULT) {
1586 thread_state_count = THREAD_STATE_MAX;
1587 kret = thread_get_state (thread_port, flavor, thread_state,
1588 &thread_state_count);
1589 MACH_CHECK_ERROR (thread_get_state, kret);
1590 }
1591
1592 switch (behavior) {
1593 case EXCEPTION_DEFAULT:
1594 // fprintf(stderr, "forwarding to exception_raise\n");
1595 kret = exception_raise(port, thread_port, task_port, exception_type,
1596 exception_data, data_count);
1597 MACH_CHECK_ERROR (exception_raise, kret);
1598 break;
1599 case EXCEPTION_STATE:
1600 // fprintf(stderr, "forwarding to exception_raise_state\n");
1601 kret = exception_raise_state(port, exception_type, exception_data,
1602 data_count, &flavor,
1603 thread_state, thread_state_count,
1604 thread_state, &thread_state_count);
1605 MACH_CHECK_ERROR (exception_raise_state, kret);
1606 break;
1607 case EXCEPTION_STATE_IDENTITY:
1608 // fprintf(stderr, "forwarding to exception_raise_state_identity\n");
1609 kret = exception_raise_state_identity(port, thread_port, task_port,
1610 exception_type, exception_data,
1611 data_count, &flavor,
1612 thread_state, thread_state_count,
1613 thread_state, &thread_state_count);
1614 MACH_CHECK_ERROR (exception_raise_state_identity, kret);
1615 break;
1616 default:
1617 fprintf(stderr, "forward_exception got unknown behavior\n");
1618 break;
1619 }
1620
1621 if (behavior != EXCEPTION_DEFAULT) {
1622 kret = thread_set_state (thread_port, flavor, thread_state,
1623 thread_state_count);
1624 MACH_CHECK_ERROR (thread_set_state, kret);
1625 }
1626
1627 return KERN_SUCCESS;
1628 }
1629
1630 /*
1631 * This is the code that actually handles the exception.
1632 * It is called by exc_server. For Darwin 5 Apple changed
1633 * this a bit from how this family of functions worked in
1634 * Mach. If you are familiar with that it is a little
1635 * different. The main variation that concerns us here is
1636 * that code is an array of exception specific codes and
1637 * codeCount is a count of the number of codes in the code
1638 * array. In typical Mach all exceptions have a code
1639 * and sub-code. It happens to be the case that for a
1640 * EXC_BAD_ACCESS exception the first entry is the type of
1641 * bad access that occurred and the second entry is the
1642 * faulting address so these entries correspond exactly to
1643 * how the code and sub-code are used on Mach.
1644 *
1645 * This is a MIG interface. No code in Basilisk II should
1646 * call this directley. This has to have external C
1647 * linkage because that is what exc_server expects.
1648 */
1649 kern_return_t
1650 catch_exception_raise(mach_port_t exception_port,
1651 mach_port_t thread,
1652 mach_port_t task,
1653 exception_type_t exception,
1654 exception_data_t code,
1655 mach_msg_type_number_t codeCount)
1656 {
1657 ppc_thread_state_t state;
1658 kern_return_t krc;
1659
1660 if ((exception == EXC_BAD_ACCESS) && (codeCount >= 2)) {
1661 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
1662 return KERN_SUCCESS;
1663 }
1664
1665 // In Mach we do not need to remove the exception handler.
1666 // If we forward the exception, eventually some exception handler
1667 // will take care of this exception.
1668 krc = forward_exception(thread, task, exception, code, codeCount, &ports);
1669
1670 return krc;
1671 }
1672 #endif
1673
1674 #ifdef HAVE_SIGSEGV_RECOVERY
1675 // Handle bad memory accesses with signal handler
1676 static void sigsegv_handler(SIGSEGV_FAULT_HANDLER_ARGLIST)
1677 {
1678 // Call handler and reinstall the global handler, if required
1679 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS)) {
1680 #if (defined(HAVE_SIGACTION) ? defined(SIGACTION_NEED_REINSTALL) : defined(SIGNAL_NEED_REINSTALL))
1681 sigsegv_do_install_handler(sig);
1682 #endif
1683 return;
1684 }
1685
1686 // Failure: reinstall default handler for "safe" crash
1687 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
1688 SIGSEGV_ALL_SIGNALS
1689 #undef FAULT_HANDLER
1690 }
1691 #endif
1692
1693
1694 /*
1695 * SIGSEGV handler initialization
1696 */
1697
1698 #if defined(HAVE_SIGINFO_T)
1699 static bool sigsegv_do_install_handler(int sig)
1700 {
1701 // Setup SIGSEGV handler to process writes to frame buffer
1702 #ifdef HAVE_SIGACTION
1703 struct sigaction sigsegv_sa;
1704 sigemptyset(&sigsegv_sa.sa_mask);
1705 sigsegv_sa.sa_sigaction = sigsegv_handler;
1706 sigsegv_sa.sa_flags = SA_SIGINFO;
1707 return (sigaction(sig, &sigsegv_sa, 0) == 0);
1708 #else
1709 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
1710 #endif
1711 }
1712 #endif
1713
1714 #if defined(HAVE_SIGCONTEXT_SUBTERFUGE)
1715 static bool sigsegv_do_install_handler(int sig)
1716 {
1717 // Setup SIGSEGV handler to process writes to frame buffer
1718 #ifdef HAVE_SIGACTION
1719 struct sigaction sigsegv_sa;
1720 sigemptyset(&sigsegv_sa.sa_mask);
1721 sigsegv_sa.sa_handler = (signal_handler)sigsegv_handler;
1722 sigsegv_sa.sa_flags = 0;
1723 #if !EMULATED_68K && defined(__NetBSD__)
1724 sigaddset(&sigsegv_sa.sa_mask, SIGALRM);
1725 sigsegv_sa.sa_flags |= SA_ONSTACK;
1726 #endif
1727 return (sigaction(sig, &sigsegv_sa, 0) == 0);
1728 #else
1729 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
1730 #endif
1731 }
1732 #endif
1733
1734 #if defined(HAVE_MACH_EXCEPTIONS)
1735 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
1736 {
1737 /*
1738 * Except for the exception port functions, this should be
1739 * pretty much stock Mach. If later you choose to support
1740 * other Mach's besides Darwin, just check for __MACH__
1741 * here and __APPLE__ where the actual differences are.
1742 */
1743 #if defined(__APPLE__) && defined(__MACH__)
1744 if (sigsegv_fault_handler != NULL) {
1745 sigsegv_fault_handler = handler;
1746 return true;
1747 }
1748
1749 kern_return_t krc;
1750
1751 // create the the exception port
1752 krc = mach_port_allocate(mach_task_self(),
1753 MACH_PORT_RIGHT_RECEIVE, &_exceptionPort);
1754 if (krc != KERN_SUCCESS) {
1755 mach_error("mach_port_allocate", krc);
1756 return false;
1757 }
1758
1759 // add a port send right
1760 krc = mach_port_insert_right(mach_task_self(),
1761 _exceptionPort, _exceptionPort,
1762 MACH_MSG_TYPE_MAKE_SEND);
1763 if (krc != KERN_SUCCESS) {
1764 mach_error("mach_port_insert_right", krc);
1765 return false;
1766 }
1767
1768 // get the old exception ports
1769 ports.maskCount = sizeof (ports.masks) / sizeof (ports.masks[0]);
1770 krc = thread_get_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, ports.masks,
1771 &ports.maskCount, ports.handlers, ports.behaviors, ports.flavors);
1772 if (krc != KERN_SUCCESS) {
1773 mach_error("thread_get_exception_ports", krc);
1774 return false;
1775 }
1776
1777 // set the new exception port
1778 //
1779 // We could have used EXCEPTION_STATE_IDENTITY instead of
1780 // EXCEPTION_DEFAULT to get the thread state in the initial
1781 // message, but it turns out that in the common case this is not
1782 // neccessary. If we need it we can later ask for it from the
1783 // suspended thread.
1784 //
1785 // Even with THREAD_STATE_NONE, Darwin provides the program
1786 // counter in the thread state. The comments in the header file
1787 // seem to imply that you can count on the GPR's on an exception
1788 // as well but just to be safe I use MACHINE_THREAD_STATE because
1789 // you have to ask for all of the GPR's anyway just to get the
1790 // program counter. In any case because of update effective
1791 // address from immediate and update address from effective
1792 // addresses of ra and rb modes (as good an name as any for these
1793 // addressing modes) used in PPC instructions, you will need the
1794 // GPR state anyway.
1795 krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
1796 EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
1797 if (krc != KERN_SUCCESS) {
1798 mach_error("thread_set_exception_ports", krc);
1799 return false;
1800 }
1801
1802 // create the exception handler thread
1803 if (pthread_create(&exc_thread, NULL, &handleExceptions, NULL) != 0) {
1804 (void)fprintf(stderr, "creation of exception thread failed\n");
1805 return false;
1806 }
1807
1808 // do not care about the exception thread any longer, let is run standalone
1809 (void)pthread_detach(exc_thread);
1810
1811 sigsegv_fault_handler = handler;
1812 return true;
1813 #else
1814 return false;
1815 #endif
1816 }
1817 #endif
1818
1819 #ifdef HAVE_WIN32_EXCEPTIONS
1820 static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo)
1821 {
1822 if (sigsegv_fault_handler != NULL
1823 && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
1824 && ExceptionInfo->ExceptionRecord->NumberParameters == 2
1825 && handle_badaccess(ExceptionInfo))
1826 return EXCEPTION_CONTINUE_EXECUTION;
1827
1828 return EXCEPTION_CONTINUE_SEARCH;
1829 }
1830
1831 #if defined __CYGWIN__ && defined __i386__
1832 /* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
1833 installs a global exception handler. We have to dig deep in order to install
1834 our main_exception_filter. */
1835
1836 /* Data structures for the current thread's exception handler chain.
1837 On the x86 Windows uses register fs, offset 0 to point to the current
1838 exception handler; Cygwin mucks with it, so we must do the same... :-/ */
1839
1840 /* Magic taken from winsup/cygwin/include/exceptions.h. */
1841
1842 struct exception_list {
1843 struct exception_list *prev;
1844 int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
1845 };
1846 typedef struct exception_list exception_list;
1847
1848 /* Magic taken from winsup/cygwin/exceptions.cc. */
1849
1850 __asm__ (".equ __except_list,0");
1851
1852 extern exception_list *_except_list __asm__ ("%fs:__except_list");
1853
1854 /* For debugging. _except_list is not otherwise accessible from gdb. */
1855 static exception_list *
1856 debug_get_except_list ()
1857 {
1858 return _except_list;
1859 }
1860
1861 /* Cygwin's original exception handler. */
1862 static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
1863
1864 /* Our exception handler. */
1865 static int
1866 libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
1867 {
1868 EXCEPTION_POINTERS ExceptionInfo;
1869 ExceptionInfo.ExceptionRecord = exception;
1870 ExceptionInfo.ContextRecord = context;
1871 if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
1872 return cygwin_exception_handler (exception, frame, context, dispatch);
1873 else
1874 return 0;
1875 }
1876
1877 static void
1878 do_install_main_exception_filter ()
1879 {
1880 /* We cannot insert any handler into the chain, because such handlers
1881 must lie on the stack (?). Instead, we have to replace(!) Cygwin's
1882 global exception handler. */
1883 cygwin_exception_handler = _except_list->handler;
1884 _except_list->handler = libsigsegv_exception_handler;
1885 }
1886
1887 #else
1888
1889 static void
1890 do_install_main_exception_filter ()
1891 {
1892 SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
1893 }
1894 #endif
1895
1896 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
1897 {
1898 static bool main_exception_filter_installed = false;
1899 if (!main_exception_filter_installed) {
1900 do_install_main_exception_filter();
1901 main_exception_filter_installed = true;
1902 }
1903 sigsegv_fault_handler = handler;
1904 return true;
1905 }
1906 #endif
1907
1908 bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
1909 {
1910 #if defined(HAVE_SIGSEGV_RECOVERY)
1911 bool success = true;
1912 #define FAULT_HANDLER(sig) success = success && sigsegv_do_install_handler(sig);
1913 SIGSEGV_ALL_SIGNALS
1914 #undef FAULT_HANDLER
1915 if (success)
1916 sigsegv_fault_handler = handler;
1917 return success;
1918 #elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS)
1919 return sigsegv_do_install_handler(handler);
1920 #else
1921 // FAIL: no siginfo_t nor sigcontext subterfuge is available
1922 return false;
1923 #endif
1924 }
1925
1926
1927 /*
1928 * SIGSEGV handler deinitialization
1929 */
1930
1931 void sigsegv_deinstall_handler(void)
1932 {
1933 // We do nothing for Mach exceptions, the thread would need to be
1934 // suspended if not already so, and we might mess with other
1935 // exception handlers that came after we registered ours. There is
1936 // no need to remove the exception handler, in fact this function is
1937 // not called anywhere in Basilisk II.
1938 #ifdef HAVE_SIGSEGV_RECOVERY
1939 sigsegv_fault_handler = 0;
1940 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
1941 SIGSEGV_ALL_SIGNALS
1942 #undef FAULT_HANDLER
1943 #endif
1944 #ifdef HAVE_WIN32_EXCEPTIONS
1945 sigsegv_fault_handler = NULL;
1946 #endif
1947 }
1948
1949
1950 /*
1951 * Set callback function when we cannot handle the fault
1952 */
1953
1954 void sigsegv_set_dump_state(sigsegv_state_dumper_t handler)
1955 {
1956 sigsegv_state_dumper = handler;
1957 }
1958
1959
1960 /*
1961 * Test program used for configure/test
1962 */
1963
1964 #ifdef CONFIGURE_TEST_SIGSEGV_RECOVERY
1965 #include <stdio.h>
1966 #include <stdlib.h>
1967 #include <fcntl.h>
1968 #ifdef HAVE_SYS_MMAN_H
1969 #include <sys/mman.h>
1970 #endif
1971 #include "vm_alloc.h"
1972
1973 const int REF_INDEX = 123;
1974 const int REF_VALUE = 45;
1975
1976 static int page_size;
1977 static volatile char * page = 0;
1978 static volatile int handler_called = 0;
1979
1980 #ifdef __GNUC__
1981 // Code range where we expect the fault to come from
1982 static void *b_region, *e_region;
1983 #endif
1984
1985 static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
1986 {
1987 #if DEBUG
1988 printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
1989 printf("expected fault at %p\n", page + REF_INDEX);
1990 #ifdef __GNUC__
1991 printf("expected instruction address range: %p-%p\n", b_region, e_region);
1992 #endif
1993 #endif
1994 handler_called++;
1995 if ((fault_address - REF_INDEX) != page)
1996 exit(10);
1997 #ifdef __GNUC__
1998 // Make sure reported fault instruction address falls into
1999 // expected code range
2000 if (instruction_address != SIGSEGV_INVALID_PC
2001 && ((instruction_address < (sigsegv_address_t)b_region) ||
2002 (instruction_address >= (sigsegv_address_t)e_region)))
2003 exit(11);
2004 #endif
2005 if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
2006 exit(12);
2007 return SIGSEGV_RETURN_SUCCESS;
2008 }
2009
2010 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
2011 static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
2012 {
2013 #if DEBUG
2014 printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
2015 #endif
2016 if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
2017 #ifdef __GNUC__
2018 // Make sure reported fault instruction address falls into
2019 // expected code range
2020 if (instruction_address != SIGSEGV_INVALID_PC
2021 && ((instruction_address < (sigsegv_address_t)b_region) ||
2022 (instruction_address >= (sigsegv_address_t)e_region)))
2023 return SIGSEGV_RETURN_FAILURE;
2024 #endif
2025 return SIGSEGV_RETURN_SKIP_INSTRUCTION;
2026 }
2027
2028 return SIGSEGV_RETURN_FAILURE;
2029 }
2030
2031 // More sophisticated tests for instruction skipper
2032 static bool arch_insn_skipper_tests()
2033 {
2034 #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
2035 static const unsigned char code[] = {
2036 0x8a, 0x00, // mov (%eax),%al
2037 0x8a, 0x2c, 0x18, // mov (%eax,%ebx,1),%ch
2038 0x88, 0x20, // mov %ah,(%eax)
2039 0x88, 0x08, // mov %cl,(%eax)
2040 0x66, 0x8b, 0x00, // mov (%eax),%ax
2041 0x66, 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%cx
2042 0x66, 0x89, 0x00, // mov %ax,(%eax)
2043 0x66, 0x89, 0x0c, 0x18, // mov %cx,(%eax,%ebx,1)
2044 0x8b, 0x00, // mov (%eax),%eax
2045 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%ecx
2046 0x89, 0x00, // mov %eax,(%eax)
2047 0x89, 0x0c, 0x18, // mov %ecx,(%eax,%ebx,1)
2048 #if defined(__x86_64__)
2049 0x44, 0x8a, 0x00, // mov (%rax),%r8b
2050 0x44, 0x8a, 0x20, // mov (%rax),%r12b
2051 0x42, 0x8a, 0x3c, 0x10, // mov (%rax,%r10,1),%dil
2052 0x44, 0x88, 0x00, // mov %r8b,(%rax)
2053 0x44, 0x88, 0x20, // mov %r12b,(%rax)
2054 0x42, 0x88, 0x3c, 0x10, // mov %dil,(%rax,%r10,1)
2055 0x66, 0x44, 0x8b, 0x00, // mov (%rax),%r8w
2056 0x66, 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%cx
2057 0x66, 0x44, 0x89, 0x00, // mov %r8w,(%rax)
2058 0x66, 0x42, 0x89, 0x0c, 0x10, // mov %cx,(%rax,%r10,1)
2059 0x44, 0x8b, 0x00, // mov (%rax),%r8d
2060 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%ecx
2061 0x44, 0x89, 0x00, // mov %r8d,(%rax)
2062 0x42, 0x89, 0x0c, 0x10, // mov %ecx,(%rax,%r10,1)
2063 0x48, 0x8b, 0x08, // mov (%rax),%rcx
2064 0x4c, 0x8b, 0x18, // mov (%rax),%r11
2065 0x4a, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%rcx
2066 0x4e, 0x8b, 0x1c, 0x10, // mov (%rax,%r10,1),%r11
2067 0x48, 0x89, 0x08, // mov %rcx,(%rax)
2068 0x4c, 0x89, 0x18, // mov %r11,(%rax)
2069 0x4a, 0x89, 0x0c, 0x10, // mov %rcx,(%rax,%r10,1)
2070 0x4e, 0x89, 0x1c, 0x10, // mov %r11,(%rax,%r10,1)
2071 #endif
2072 0 // end
2073 };
2074 const int N_REGS = 20;
2075 unsigned long regs[N_REGS];
2076 for (int i = 0; i < N_REGS; i++)
2077 regs[i] = i;
2078 const unsigned long start_code = (unsigned long)&code;
2079 regs[X86_REG_EIP] = start_code;
2080 while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
2081 && ix86_skip_instruction(regs))
2082 ; /* simply iterate */
2083 return (regs[X86_REG_EIP] - start_code) == (sizeof(code) - 1);
2084 #endif
2085 return true;
2086 }
2087 #endif
2088
2089 int main(void)
2090 {
2091 if (vm_init() < 0)
2092 return 1;
2093
2094 #ifdef _WIN32
2095 page_size = 4096;
2096 #else
2097 page_size = getpagesize();
2098 #endif
2099 if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
2100 return 2;
2101
2102 memset((void *)page, 0, page_size);
2103 if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0)
2104 return 3;
2105
2106 if (!sigsegv_install_handler(sigsegv_test_handler))
2107 return 4;
2108
2109 #ifdef __GNUC__
2110 b_region = &&L_b_region1;
2111 e_region = &&L_e_region1;
2112 #endif
2113 L_b_region1:
2114 page[REF_INDEX] = REF_VALUE;
2115 if (page[REF_INDEX] != REF_VALUE)
2116 exit(20);
2117 page[REF_INDEX] = REF_VALUE;
2118 L_e_region1:
2119
2120 if (handler_called != 1)
2121 return 5;
2122
2123 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
2124 if (!sigsegv_install_handler(sigsegv_insn_handler))
2125 return 6;
2126
2127 if (vm_protect((char *)page, page_size, VM_PAGE_READ | VM_PAGE_WRITE) < 0)
2128 return 7;
2129
2130 for (int i = 0; i < page_size; i++)
2131 page[i] = (i + 1) % page_size;
2132
2133 if (vm_protect((char *)page, page_size, VM_PAGE_NOACCESS) < 0)
2134 return 8;
2135
2136 #define TEST_SKIP_INSTRUCTION(TYPE) do { \
2137 const unsigned long TAG = 0x12345678 | \
2138 (sizeof(long) == 8 ? 0x9abcdef0UL << 31 : 0); \
2139 TYPE data = *((TYPE *)(page + sizeof(TYPE))); \
2140 volatile unsigned long effect = data + TAG; \
2141 if (effect != TAG) \
2142 return 9; \
2143 } while (0)
2144
2145 #ifdef __GNUC__
2146 b_region = &&L_b_region2;
2147 e_region = &&L_e_region2;
2148 #endif
2149 L_b_region2:
2150 TEST_SKIP_INSTRUCTION(unsigned char);
2151 TEST_SKIP_INSTRUCTION(unsigned short);
2152 TEST_SKIP_INSTRUCTION(unsigned int);
2153 TEST_SKIP_INSTRUCTION(unsigned long);
2154 TEST_SKIP_INSTRUCTION(signed char);
2155 TEST_SKIP_INSTRUCTION(signed short);
2156 TEST_SKIP_INSTRUCTION(signed int);
2157 TEST_SKIP_INSTRUCTION(signed long);
2158 L_e_region2:
2159
2160 if (!arch_insn_skipper_tests())
2161 return 20;
2162 #endif
2163
2164 vm_exit();
2165 return 0;
2166 }
2167 #endif