ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.46
Committed: 2004-01-22T00:00:55Z (20 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-16, nigel-build-15
Changes since 1.45: +1 -1 lines
Log Message:
cosmetic fixes when printing movsbq operation summary

File Contents

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