ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.57
Committed: 2006-01-22T00:05:05Z (18 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.56: +23 -3 lines
Log Message:
Adapt for MacOS X for Intel, also fix thread_state type in forward_exception()

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