ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.53
Committed: 2005-02-20T11:39:12Z (19 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.52: +7 -0 lines
Log Message:
NetBSD/ppc support

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