ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.44
Committed: 2004-01-21T23:14:28Z (20 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.43: +160 -0 lines
Log Message:
Summary: possible support of SheepShaver on Zaurus PDAs

Add Linux/ARM instruction skipping, includes support for ARMv4+ halfword
and signed data transfer instructions. Note that load/store multiple are
not handled and someone has to make sure post-incr/write-back logic is
correctly implemented.

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