ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.73
Committed: 2008-01-06T16:10:30Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.72: +2 -2 lines
Log Message:
ISO C++ conformance fixes: remove superfluous coma at the end of enum definitions.

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