ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.47
Committed: 2004-02-16T16:02:48Z (20 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.46: +1 -0 lines
Log Message:
Decode MOVSX r32, r/m16 (generated by icc v8.0 on x86)

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