ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.42
Committed: 2004-01-19T16:59:13Z (20 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.41: +12 -0 lines
Log Message:
ARM/linux sigsegv handler. Instruction skipper yet to be written for
happy Zaurus owners.

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