ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.78
Committed: 2008-01-07T22:44:39Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.77: +11 -2 lines
Log Message:
Make it possible to override the Mach fault recovery scheme through an
environment variable: SIGSEGV_MACH_FAULT. It can be set to "direct" to
assume the fault address comes from code[1] argument, or "slow" to use
the slow path through thread_get_status(EXCEPTION_STATE)->faultvaddr.

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_CONTEXT_REGS ((struct sigcontext *)scp)
311 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
312 #define SIGSEGV_REGISTER_FILE SIGSEGV_CONTEXT_REGS
313 #define SIGSEGV_SKIP_INSTRUCTION ia64_skip_instruction
314 #endif
315 #if (defined(powerpc) || defined(__powerpc__))
316 #include <sys/ucontext.h>
317 #define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.regs)
318 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->nip)
319 #define SIGSEGV_REGISTER_FILE (unsigned long *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned long *)(SIGSEGV_CONTEXT_REGS->gpr)
320 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
321 #endif
322 #if (defined(hppa) || defined(__hppa__))
323 #undef SIGSEGV_FAULT_ADDRESS
324 #define SIGSEGV_FAULT_ADDRESS sip->si_ptr
325 #endif
326 #if (defined(arm) || defined(__arm__))
327 #include <asm/ucontext.h> /* use kernel structure, glibc may not be in sync */
328 #define SIGSEGV_CONTEXT_REGS (((struct ucontext *)scp)->uc_mcontext)
329 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS.arm_pc)
330 #define SIGSEGV_REGISTER_FILE (&SIGSEGV_CONTEXT_REGS.arm_r0)
331 #define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction
332 #endif
333 #if (defined(mips) || defined(__mips__))
334 #include <sys/ucontext.h>
335 #define SIGSEGV_CONTEXT_REGS (((struct ucontext *)scp)->uc_mcontext)
336 #define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS.pc)
337 #define SIGSEGV_REGISTER_FILE &SIGSEGV_CONTEXT_REGS.pc, &SIGSEGV_CONTEXT_REGS.gregs[0]
338 #define SIGSEGV_SKIP_INSTRUCTION mips_skip_instruction
339 #endif
340 #endif
341 #endif
342
343 #if HAVE_SIGCONTEXT_SUBTERFUGE
344 // Linux kernels prior to 2.4 ?
345 #if defined(__linux__)
346 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
347 #if (defined(i386) || defined(__i386__))
348 #include <asm/sigcontext.h>
349 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext scs
350 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp
351 #define SIGSEGV_FAULT_HANDLER_ARGS &scs
352 #define SIGSEGV_FAULT_ADDRESS scp->cr2
353 #define SIGSEGV_FAULT_INSTRUCTION scp->eip
354 #define SIGSEGV_REGISTER_FILE (unsigned long *)scp
355 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
356 #endif
357 #if (defined(sparc) || defined(__sparc__))
358 #include <asm/sigcontext.h>
359 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr
360 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr
361 #define SIGSEGV_FAULT_ADDRESS addr
362 #endif
363 #if (defined(powerpc) || defined(__powerpc__))
364 #include <asm/sigcontext.h>
365 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext *scp
366 #define SIGSEGV_FAULT_HANDLER_ARGS sig, scp
367 #define SIGSEGV_FAULT_ADDRESS scp->regs->dar
368 #define SIGSEGV_FAULT_INSTRUCTION scp->regs->nip
369 #define SIGSEGV_REGISTER_FILE (unsigned long *)&scp->regs->nip, (unsigned long *)(scp->regs->gpr)
370 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
371 #endif
372 #if (defined(alpha) || defined(__alpha__))
373 #include <asm/sigcontext.h>
374 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
375 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
376 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
377 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc
378 #endif
379 #if (defined(arm) || defined(__arm__))
380 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r1, int r2, int r3, struct sigcontext sc
381 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp
382 #define SIGSEGV_FAULT_HANDLER_ARGS &sc
383 #define SIGSEGV_FAULT_ADDRESS scp->fault_address
384 #define SIGSEGV_FAULT_INSTRUCTION scp->arm_pc
385 #define SIGSEGV_REGISTER_FILE &scp->arm_r0
386 #define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction
387 #endif
388 #endif
389
390 // Irix 5 or 6 on MIPS
391 #if (defined(sgi) || defined(__sgi)) && (defined(SYSTYPE_SVR4) || defined(_SYSTYPE_SVR4))
392 #include <ucontext.h>
393 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
394 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
395 #define SIGSEGV_FAULT_ADDRESS (unsigned long)scp->sc_badvaddr
396 #define SIGSEGV_FAULT_INSTRUCTION (unsigned long)scp->sc_pc
397 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
398 #endif
399
400 // HP-UX
401 #if (defined(hpux) || defined(__hpux__))
402 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
403 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
404 #define SIGSEGV_FAULT_ADDRESS scp->sc_sl.sl_ss.ss_narrow.ss_cr21
405 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) FAULT_HANDLER(SIGBUS)
406 #endif
407
408 // OSF/1 on Alpha
409 #if defined(__osf__)
410 #include <ucontext.h>
411 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
412 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
413 #define SIGSEGV_FAULT_ADDRESS scp->sc_traparg_a0
414 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
415 #endif
416
417 // AIX
418 #if defined(_AIX)
419 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
420 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
421 #define SIGSEGV_FAULT_ADDRESS scp->sc_jmpbuf.jmp_context.o_vaddr
422 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
423 #endif
424
425 // NetBSD
426 #if defined(__NetBSD__)
427 #if (defined(m68k) || defined(__m68k__))
428 #include <m68k/frame.h>
429 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
430 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
431 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
432 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
433
434 // Use decoding scheme from BasiliskII/m68k native
435 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
436 {
437 struct sigstate {
438 int ss_flags;
439 struct frame ss_frame;
440 };
441 struct sigstate *state = (struct sigstate *)scp->sc_ap;
442 char *fault_addr;
443 switch (state->ss_frame.f_format) {
444 case 7: /* 68040 access error */
445 /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */
446 fault_addr = state->ss_frame.f_fmt7.f_fa;
447 break;
448 default:
449 fault_addr = (char *)code;
450 break;
451 }
452 return (sigsegv_address_t)fault_addr;
453 }
454 #endif
455 #if (defined(alpha) || defined(__alpha__))
456 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
457 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
458 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
459 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
460 #endif
461 #if (defined(i386) || defined(__i386__))
462 #error "FIXME: need to decode instruction and compute EA"
463 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
464 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
465 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
466 #endif
467 #endif
468 #if defined(__FreeBSD__)
469 #if (defined(i386) || defined(__i386__))
470 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
471 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr
472 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr
473 #define SIGSEGV_FAULT_ADDRESS addr
474 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_eip
475 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&scp->sc_edi)
476 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
477 #endif
478 #if (defined(alpha) || defined(__alpha__))
479 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV)
480 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, char *addr, struct sigcontext *scp
481 #define SIGSEGV_FAULT_HANDLER_ARGS sig, addr, scp
482 #define SIGSEGV_FAULT_ADDRESS addr
483 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc
484 #endif
485 #endif
486
487 // Extract fault address out of a sigcontext
488 #if (defined(alpha) || defined(__alpha__))
489 // From Boehm's GC 6.0alpha8
490 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
491 {
492 unsigned int instruction = *((unsigned int *)(scp->sc_pc));
493 unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f];
494 fault_address += (signed long)(signed short)(instruction & 0xffff);
495 return (sigsegv_address_t)fault_address;
496 }
497 #endif
498
499
500 // MacOS X, not sure which version this works in. Under 10.1
501 // vm_protect does not appear to work from a signal handler. Under
502 // 10.2 signal handlers get siginfo type arguments but the si_addr
503 // field is the address of the faulting instruction and not the
504 // address that caused the SIGBUS. Maybe this works in 10.0? In any
505 // case with Mach exception handlers there is a way to do what this
506 // was meant to do.
507 #ifndef HAVE_MACH_EXCEPTIONS
508 #if defined(__APPLE__) && defined(__MACH__)
509 #if (defined(ppc) || defined(__ppc__))
510 #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
511 #define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp
512 #define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
513 #define SIGSEGV_FAULT_INSTRUCTION scp->sc_ir
514 #define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
515 #define SIGSEGV_REGISTER_FILE (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2]
516 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
517
518 // Use decoding scheme from SheepShaver
519 static sigsegv_address_t get_fault_address(struct sigcontext *scp)
520 {
521 unsigned int nip = (unsigned int) scp->sc_ir;
522 unsigned int * gpr = &((unsigned int *) scp->sc_regs)[2];
523 instruction_t instr;
524
525 powerpc_decode_instruction(&instr, nip, gpr);
526 return (sigsegv_address_t)instr.addr;
527 }
528 #endif
529 #endif
530 #endif
531 #endif
532
533 #if HAVE_WIN32_EXCEPTIONS
534 #define WIN32_LEAN_AND_MEAN /* avoid including junk */
535 #include <windows.h>
536 #include <winerror.h>
537
538 #define SIGSEGV_FAULT_HANDLER_ARGLIST EXCEPTION_POINTERS *ExceptionInfo
539 #define SIGSEGV_FAULT_HANDLER_ARGS ExceptionInfo
540 #define SIGSEGV_FAULT_ADDRESS ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
541 #define SIGSEGV_CONTEXT_REGS ExceptionInfo->ContextRecord
542 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS->Eip
543 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&SIGSEGV_CONTEXT_REGS->Edi)
544 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
545 #endif
546
547 #if HAVE_MACH_EXCEPTIONS
548
549 // This can easily be extended to other Mach systems, but really who
550 // uses HURD (oops GNU/HURD), Darwin/x86, NextStep, Rhapsody, or CMU
551 // Mach 2.5/3.0?
552 #if defined(__APPLE__) && defined(__MACH__)
553
554 #include <sys/types.h>
555 #include <stdlib.h>
556 #include <stdio.h>
557 #include <pthread.h>
558
559 /*
560 * If you are familiar with MIG then you will understand the frustration
561 * that was necessary to get these embedded into C++ code by hand.
562 */
563 extern "C" {
564 #include <mach/mach.h>
565 #include <mach/mach_error.h>
566
567 extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
568 extern kern_return_t catch_exception_raise(mach_port_t, mach_port_t,
569 mach_port_t, exception_type_t, exception_data_t, mach_msg_type_number_t);
570 extern kern_return_t exception_raise(mach_port_t, mach_port_t, mach_port_t,
571 exception_type_t, exception_data_t, mach_msg_type_number_t);
572 extern kern_return_t exception_raise_state(mach_port_t, exception_type_t,
573 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 extern kern_return_t exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
576 exception_type_t, exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
577 thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);
578 }
579
580 // Could make this dynamic by looking for a result of MIG_ARRAY_TOO_LARGE
581 #define HANDLER_COUNT 64
582
583 // structure to tuck away existing exception handlers
584 typedef struct _ExceptionPorts {
585 mach_msg_type_number_t maskCount;
586 exception_mask_t masks[HANDLER_COUNT];
587 exception_handler_t handlers[HANDLER_COUNT];
588 exception_behavior_t behaviors[HANDLER_COUNT];
589 thread_state_flavor_t flavors[HANDLER_COUNT];
590 } ExceptionPorts;
591
592 // exception handler thread
593 static pthread_t exc_thread;
594
595 // place where old exception handler info is stored
596 static ExceptionPorts ports;
597
598 // our exception port
599 static mach_port_t _exceptionPort = MACH_PORT_NULL;
600
601 #define MACH_CHECK_ERROR(name,ret) \
602 if (ret != KERN_SUCCESS) { \
603 mach_error(#name, ret); \
604 exit (1); \
605 }
606
607 #ifdef __ppc__
608 #define SIGSEGV_EXCEPTION_STATE_TYPE ppc_exception_state_t
609 #define SIGSEGV_EXCEPTION_STATE_FLAVOR PPC_EXCEPTION_STATE
610 #define SIGSEGV_EXCEPTION_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
611 #define SIGSEGV_FAULT_ADDRESS SIP->exc_state.dar
612 #define SIGSEGV_THREAD_STATE_TYPE ppc_thread_state_t
613 #define SIGSEGV_THREAD_STATE_FLAVOR PPC_THREAD_STATE
614 #define SIGSEGV_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
615 #define SIGSEGV_FAULT_INSTRUCTION SIP->thr_state.srr0
616 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
617 #define SIGSEGV_REGISTER_FILE (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
618 #endif
619 #ifdef __ppc64__
620 #define SIGSEGV_EXCEPTION_STATE_TYPE ppc_exception_state64_t
621 #define SIGSEGV_EXCEPTION_STATE_FLAVOR PPC_EXCEPTION_STATE64
622 #define SIGSEGV_EXCEPTION_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT
623 #define SIGSEGV_FAULT_ADDRESS SIP->exc_state.dar
624 #define SIGSEGV_THREAD_STATE_TYPE ppc_thread_state64_t
625 #define SIGSEGV_THREAD_STATE_FLAVOR PPC_THREAD_STATE64
626 #define SIGSEGV_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT
627 #define SIGSEGV_FAULT_INSTRUCTION SIP->thr_state.srr0
628 #define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction
629 #define SIGSEGV_REGISTER_FILE (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
630 #endif
631 #ifdef __i386__
632 #define SIGSEGV_EXCEPTION_STATE_TYPE struct i386_exception_state
633 #define SIGSEGV_EXCEPTION_STATE_FLAVOR i386_EXCEPTION_STATE
634 #define SIGSEGV_EXCEPTION_STATE_COUNT i386_EXCEPTION_STATE_COUNT
635 #define SIGSEGV_FAULT_ADDRESS SIP->exc_state.faultvaddr
636 #define SIGSEGV_THREAD_STATE_TYPE struct i386_thread_state
637 #define SIGSEGV_THREAD_STATE_FLAVOR i386_THREAD_STATE
638 #define SIGSEGV_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
639 #define SIGSEGV_FAULT_INSTRUCTION SIP->thr_state.eip
640 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
641 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&SIP->thr_state.eax) /* EAX is the first GPR we consider */
642 #endif
643 #ifdef __x86_64__
644 #define SIGSEGV_EXCEPTION_STATE_TYPE struct x86_exception_state64
645 #define SIGSEGV_EXCEPTION_STATE_FLAVOR x86_EXCEPTION_STATE64
646 #define SIGSEGV_EXCEPTION_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
647 #define SIGSEGV_FAULT_ADDRESS SIP->exc_state.faultvaddr
648 #define SIGSEGV_THREAD_STATE_TYPE struct x86_thread_state64
649 #define SIGSEGV_THREAD_STATE_FLAVOR x86_THREAD_STATE64
650 #define SIGSEGV_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
651 #define SIGSEGV_FAULT_INSTRUCTION SIP->thr_state.rip
652 #define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction
653 #define SIGSEGV_REGISTER_FILE ((unsigned long *)&SIP->thr_state.rax) /* RAX is the first GPR we consider */
654 #endif
655 #define SIGSEGV_FAULT_ADDRESS_FAST code[1]
656 #define SIGSEGV_FAULT_INSTRUCTION_FAST SIGSEGV_INVALID_ADDRESS
657 #define SIGSEGV_FAULT_HANDLER_ARGLIST mach_port_t thread, exception_data_t code
658 #define SIGSEGV_FAULT_HANDLER_ARGS thread, code
659
660 // Since there can only be one exception thread running at any time
661 // this is not a problem.
662 #define MSG_SIZE 512
663 static char msgbuf[MSG_SIZE];
664 static char replybuf[MSG_SIZE];
665
666 /*
667 * This is the entry point for the exception handler thread. The job
668 * of this thread is to wait for exception messages on the exception
669 * port that was setup beforehand and to pass them on to exc_server.
670 * exc_server is a MIG generated function that is a part of Mach.
671 * Its job is to decide what to do with the exception message. In our
672 * case exc_server calls catch_exception_raise on our behalf. After
673 * exc_server returns, it is our responsibility to send the reply.
674 */
675 static void *
676 handleExceptions(void *priv)
677 {
678 mach_msg_header_t *msg, *reply;
679 kern_return_t krc;
680
681 msg = (mach_msg_header_t *)msgbuf;
682 reply = (mach_msg_header_t *)replybuf;
683
684 for (;;) {
685 krc = mach_msg(msg, MACH_RCV_MSG, MSG_SIZE, MSG_SIZE,
686 _exceptionPort, 0, MACH_PORT_NULL);
687 MACH_CHECK_ERROR(mach_msg, krc);
688
689 if (!exc_server(msg, reply)) {
690 fprintf(stderr, "exc_server hated the message\n");
691 exit(1);
692 }
693
694 krc = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
695 msg->msgh_local_port, 0, MACH_PORT_NULL);
696 if (krc != KERN_SUCCESS) {
697 fprintf(stderr, "Error sending message to original reply port, krc = %d, %s",
698 krc, mach_error_string(krc));
699 exit(1);
700 }
701 }
702 }
703 #endif
704 #endif
705
706
707 /*
708 * Instruction skipping
709 */
710
711 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
712 // Decode and skip X86 instruction
713 #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
714 #if defined(__linux__)
715 enum {
716 #if (defined(i386) || defined(__i386__))
717 X86_REG_EIP = 14,
718 X86_REG_EAX = 11,
719 X86_REG_ECX = 10,
720 X86_REG_EDX = 9,
721 X86_REG_EBX = 8,
722 X86_REG_ESP = 7,
723 X86_REG_EBP = 6,
724 X86_REG_ESI = 5,
725 X86_REG_EDI = 4
726 #endif
727 #if defined(__x86_64__)
728 X86_REG_R8 = 0,
729 X86_REG_R9 = 1,
730 X86_REG_R10 = 2,
731 X86_REG_R11 = 3,
732 X86_REG_R12 = 4,
733 X86_REG_R13 = 5,
734 X86_REG_R14 = 6,
735 X86_REG_R15 = 7,
736 X86_REG_EDI = 8,
737 X86_REG_ESI = 9,
738 X86_REG_EBP = 10,
739 X86_REG_EBX = 11,
740 X86_REG_EDX = 12,
741 X86_REG_EAX = 13,
742 X86_REG_ECX = 14,
743 X86_REG_ESP = 15,
744 X86_REG_EIP = 16
745 #endif
746 };
747 #endif
748 #if defined(__NetBSD__)
749 enum {
750 #if (defined(i386) || defined(__i386__))
751 X86_REG_EIP = _REG_EIP,
752 X86_REG_EAX = _REG_EAX,
753 X86_REG_ECX = _REG_ECX,
754 X86_REG_EDX = _REG_EDX,
755 X86_REG_EBX = _REG_EBX,
756 X86_REG_ESP = _REG_ESP,
757 X86_REG_EBP = _REG_EBP,
758 X86_REG_ESI = _REG_ESI,
759 X86_REG_EDI = _REG_EDI
760 #endif
761 };
762 #endif
763 #if defined(__FreeBSD__)
764 enum {
765 #if (defined(i386) || defined(__i386__))
766 X86_REG_EIP = 10,
767 X86_REG_EAX = 7,
768 X86_REG_ECX = 6,
769 X86_REG_EDX = 5,
770 X86_REG_EBX = 4,
771 X86_REG_ESP = 13,
772 X86_REG_EBP = 2,
773 X86_REG_ESI = 1,
774 X86_REG_EDI = 0
775 #endif
776 };
777 #endif
778 #if defined(__OpenBSD__)
779 enum {
780 #if defined(__i386__)
781 // EDI is the first register we consider
782 #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
783 #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
784 X86_REG_EIP = DREG(eip), // 7
785 X86_REG_EAX = DREG(eax), // 6
786 X86_REG_ECX = DREG(ecx), // 5
787 X86_REG_EDX = DREG(edx), // 4
788 X86_REG_EBX = DREG(ebx), // 3
789 X86_REG_ESP = DREG(esp), // 10
790 X86_REG_EBP = DREG(ebp), // 2
791 X86_REG_ESI = DREG(esi), // 1
792 X86_REG_EDI = DREG(edi) // 0
793 #undef DREG
794 #undef OREG
795 #endif
796 };
797 #endif
798 #if defined(__sun__)
799 // Same as for Linux, need to check for x86-64
800 enum {
801 #if defined(__i386__)
802 X86_REG_EIP = EIP,
803 X86_REG_EAX = EAX,
804 X86_REG_ECX = ECX,
805 X86_REG_EDX = EDX,
806 X86_REG_EBX = EBX,
807 X86_REG_ESP = ESP,
808 X86_REG_EBP = EBP,
809 X86_REG_ESI = ESI,
810 X86_REG_EDI = EDI
811 #endif
812 };
813 #endif
814 #if defined(__APPLE__) && defined(__MACH__)
815 enum {
816 #if (defined(i386) || defined(__i386__))
817 #ifdef i386_SAVED_STATE
818 // same as FreeBSD (in Open Darwin 8.0.1)
819 X86_REG_EIP = 10,
820 X86_REG_EAX = 7,
821 X86_REG_ECX = 6,
822 X86_REG_EDX = 5,
823 X86_REG_EBX = 4,
824 X86_REG_ESP = 13,
825 X86_REG_EBP = 2,
826 X86_REG_ESI = 1,
827 X86_REG_EDI = 0
828 #else
829 // new layout (MacOS X 10.4.4 for x86)
830 X86_REG_EIP = 10,
831 X86_REG_EAX = 0,
832 X86_REG_ECX = 2,
833 X86_REG_EDX = 3,
834 X86_REG_EBX = 1,
835 X86_REG_ESP = 7,
836 X86_REG_EBP = 6,
837 X86_REG_ESI = 5,
838 X86_REG_EDI = 4
839 #endif
840 #endif
841 #if defined(__x86_64__)
842 X86_REG_R8 = 8,
843 X86_REG_R9 = 9,
844 X86_REG_R10 = 10,
845 X86_REG_R11 = 11,
846 X86_REG_R12 = 12,
847 X86_REG_R13 = 13,
848 X86_REG_R14 = 14,
849 X86_REG_R15 = 15,
850 X86_REG_EDI = 4,
851 X86_REG_ESI = 5,
852 X86_REG_EBP = 6,
853 X86_REG_EBX = 1,
854 X86_REG_EDX = 3,
855 X86_REG_EAX = 0,
856 X86_REG_ECX = 2,
857 X86_REG_ESP = 7,
858 X86_REG_EIP = 16
859 #endif
860 };
861 #endif
862 #if defined(_WIN32)
863 enum {
864 #if (defined(i386) || defined(__i386__))
865 X86_REG_EIP = 7,
866 X86_REG_EAX = 5,
867 X86_REG_ECX = 4,
868 X86_REG_EDX = 3,
869 X86_REG_EBX = 2,
870 X86_REG_ESP = 10,
871 X86_REG_EBP = 6,
872 X86_REG_ESI = 1,
873 X86_REG_EDI = 0
874 #endif
875 };
876 #endif
877 // FIXME: this is partly redundant with the instruction decoding phase
878 // to discover transfer type and register number
879 static inline int ix86_step_over_modrm(unsigned char * p)
880 {
881 int mod = (p[0] >> 6) & 3;
882 int rm = p[0] & 7;
883 int offset = 0;
884
885 // ModR/M Byte
886 switch (mod) {
887 case 0: // [reg]
888 if (rm == 5) return 4; // disp32
889 break;
890 case 1: // disp8[reg]
891 offset = 1;
892 break;
893 case 2: // disp32[reg]
894 offset = 4;
895 break;
896 case 3: // register
897 return 0;
898 }
899
900 // SIB Byte
901 if (rm == 4) {
902 if (mod == 0 && (p[1] & 7) == 5)
903 offset = 5; // disp32[index]
904 else
905 offset++;
906 }
907
908 return offset;
909 }
910
911 static bool ix86_skip_instruction(unsigned long * regs)
912 {
913 unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
914
915 if (eip == 0)
916 return false;
917 #ifdef _WIN32
918 if (IsBadCodePtr((FARPROC)eip))
919 return false;
920 #endif
921
922 enum instruction_type_t {
923 i_MOV,
924 i_ADD
925 };
926
927 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
928 transfer_size_t transfer_size = SIZE_LONG;
929 instruction_type_t instruction_type = i_MOV;
930
931 int reg = -1;
932 int len = 0;
933
934 #if DEBUG
935 printf("IP: %p [%02x %02x %02x %02x...]\n",
936 eip, eip[0], eip[1], eip[2], eip[3]);
937 #endif
938
939 // Operand size prefix
940 if (*eip == 0x66) {
941 eip++;
942 len++;
943 transfer_size = SIZE_WORD;
944 }
945
946 // REX prefix
947 #if defined(__x86_64__)
948 struct rex_t {
949 unsigned char W;
950 unsigned char R;
951 unsigned char X;
952 unsigned char B;
953 };
954 rex_t rex = { 0, 0, 0, 0 };
955 bool has_rex = false;
956 if ((*eip & 0xf0) == 0x40) {
957 has_rex = true;
958 const unsigned char b = *eip;
959 rex.W = b & (1 << 3);
960 rex.R = b & (1 << 2);
961 rex.X = b & (1 << 1);
962 rex.B = b & (1 << 0);
963 #if DEBUG
964 printf("REX: %c,%c,%c,%c\n",
965 rex.W ? 'W' : '_',
966 rex.R ? 'R' : '_',
967 rex.X ? 'X' : '_',
968 rex.B ? 'B' : '_');
969 #endif
970 eip++;
971 len++;
972 if (rex.W)
973 transfer_size = SIZE_QUAD;
974 }
975 #else
976 const bool has_rex = false;
977 #endif
978
979 // Decode instruction
980 int op_len = 1;
981 int target_size = SIZE_UNKNOWN;
982 switch (eip[0]) {
983 case 0x0f:
984 target_size = transfer_size;
985 switch (eip[1]) {
986 case 0xbe: // MOVSX r32, r/m8
987 case 0xb6: // MOVZX r32, r/m8
988 transfer_size = SIZE_BYTE;
989 goto do_mov_extend;
990 case 0xbf: // MOVSX r32, r/m16
991 case 0xb7: // MOVZX r32, r/m16
992 transfer_size = SIZE_WORD;
993 goto do_mov_extend;
994 do_mov_extend:
995 op_len = 2;
996 goto do_transfer_load;
997 }
998 break;
999 #if defined(__x86_64__)
1000 case 0x63: // MOVSXD r64, r/m32
1001 if (has_rex && rex.W) {
1002 transfer_size = SIZE_LONG;
1003 target_size = SIZE_QUAD;
1004 }
1005 else if (transfer_size != SIZE_WORD) {
1006 transfer_size = SIZE_LONG;
1007 target_size = SIZE_QUAD;
1008 }
1009 goto do_transfer_load;
1010 #endif
1011 case 0x02: // ADD r8, r/m8
1012 transfer_size = SIZE_BYTE;
1013 case 0x03: // ADD r32, r/m32
1014 instruction_type = i_ADD;
1015 goto do_transfer_load;
1016 case 0x8a: // MOV r8, r/m8
1017 transfer_size = SIZE_BYTE;
1018 case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1019 do_transfer_load:
1020 switch (eip[op_len] & 0xc0) {
1021 case 0x80:
1022 reg = (eip[op_len] >> 3) & 7;
1023 transfer_type = SIGSEGV_TRANSFER_LOAD;
1024 break;
1025 case 0x40:
1026 reg = (eip[op_len] >> 3) & 7;
1027 transfer_type = SIGSEGV_TRANSFER_LOAD;
1028 break;
1029 case 0x00:
1030 reg = (eip[op_len] >> 3) & 7;
1031 transfer_type = SIGSEGV_TRANSFER_LOAD;
1032 break;
1033 }
1034 len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1035 break;
1036 case 0x00: // ADD r/m8, r8
1037 transfer_size = SIZE_BYTE;
1038 case 0x01: // ADD r/m32, r32
1039 instruction_type = i_ADD;
1040 goto do_transfer_store;
1041 case 0x88: // MOV r/m8, r8
1042 transfer_size = SIZE_BYTE;
1043 case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1044 do_transfer_store:
1045 switch (eip[op_len] & 0xc0) {
1046 case 0x80:
1047 reg = (eip[op_len] >> 3) & 7;
1048 transfer_type = SIGSEGV_TRANSFER_STORE;
1049 break;
1050 case 0x40:
1051 reg = (eip[op_len] >> 3) & 7;
1052 transfer_type = SIGSEGV_TRANSFER_STORE;
1053 break;
1054 case 0x00:
1055 reg = (eip[op_len] >> 3) & 7;
1056 transfer_type = SIGSEGV_TRANSFER_STORE;
1057 break;
1058 }
1059 len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1060 break;
1061 }
1062 if (target_size == SIZE_UNKNOWN)
1063 target_size = transfer_size;
1064
1065 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1066 // Unknown machine code, let it crash. Then patch the decoder
1067 return false;
1068 }
1069
1070 #if defined(__x86_64__)
1071 if (rex.R)
1072 reg += 8;
1073 #endif
1074
1075 if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1076 static const int x86_reg_map[] = {
1077 X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1078 X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1079 #if defined(__x86_64__)
1080 X86_REG_R8, X86_REG_R9, X86_REG_R10, X86_REG_R11,
1081 X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1082 #endif
1083 };
1084
1085 if (reg < 0 || reg >= (sizeof(x86_reg_map)/sizeof(x86_reg_map[0]) - 1))
1086 return false;
1087
1088 // Set 0 to the relevant register part
1089 // NOTE: this is only valid for MOV alike instructions
1090 int rloc = x86_reg_map[reg];
1091 switch (target_size) {
1092 case SIZE_BYTE:
1093 if (has_rex || reg < 4)
1094 regs[rloc] = (regs[rloc] & ~0x00ffL);
1095 else {
1096 rloc = x86_reg_map[reg - 4];
1097 regs[rloc] = (regs[rloc] & ~0xff00L);
1098 }
1099 break;
1100 case SIZE_WORD:
1101 regs[rloc] = (regs[rloc] & ~0xffffL);
1102 break;
1103 case SIZE_LONG:
1104 case SIZE_QUAD: // zero-extension
1105 regs[rloc] = 0;
1106 break;
1107 }
1108 }
1109
1110 #if DEBUG
1111 printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1112 transfer_size == SIZE_BYTE ? "byte" :
1113 transfer_size == SIZE_WORD ? "word" :
1114 transfer_size == SIZE_LONG ? "long" :
1115 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1116 transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
1117
1118 if (reg != -1) {
1119 static const char * x86_byte_reg_str_map[] = {
1120 "al", "cl", "dl", "bl",
1121 "spl", "bpl", "sil", "dil",
1122 "r8b", "r9b", "r10b", "r11b",
1123 "r12b", "r13b", "r14b", "r15b",
1124 "ah", "ch", "dh", "bh",
1125 };
1126 static const char * x86_word_reg_str_map[] = {
1127 "ax", "cx", "dx", "bx",
1128 "sp", "bp", "si", "di",
1129 "r8w", "r9w", "r10w", "r11w",
1130 "r12w", "r13w", "r14w", "r15w",
1131 };
1132 static const char *x86_long_reg_str_map[] = {
1133 "eax", "ecx", "edx", "ebx",
1134 "esp", "ebp", "esi", "edi",
1135 "r8d", "r9d", "r10d", "r11d",
1136 "r12d", "r13d", "r14d", "r15d",
1137 };
1138 static const char *x86_quad_reg_str_map[] = {
1139 "rax", "rcx", "rdx", "rbx",
1140 "rsp", "rbp", "rsi", "rdi",
1141 "r8", "r9", "r10", "r11",
1142 "r12", "r13", "r14", "r15",
1143 };
1144 const char * reg_str = NULL;
1145 switch (target_size) {
1146 case SIZE_BYTE:
1147 reg_str = x86_byte_reg_str_map[(!has_rex && reg >= 4 ? 12 : 0) + reg];
1148 break;
1149 case SIZE_WORD: reg_str = x86_word_reg_str_map[reg]; break;
1150 case SIZE_LONG: reg_str = x86_long_reg_str_map[reg]; break;
1151 case SIZE_QUAD: reg_str = x86_quad_reg_str_map[reg]; break;
1152 }
1153 if (reg_str)
1154 printf(" %s register %%%s",
1155 transfer_type == SIGSEGV_TRANSFER_LOAD ? "to" : "from",
1156 reg_str);
1157 }
1158 printf(", %d bytes instruction\n", len);
1159 #endif
1160
1161 regs[X86_REG_EIP] += len;
1162 return true;
1163 }
1164 #endif
1165
1166 // Decode and skip IA-64 instruction
1167 #if defined(__ia64__)
1168 #if defined(__linux__)
1169 // We can directly patch the slot number
1170 #define IA64_CAN_PATCH_IP_SLOT 1
1171 // Helper macros to access the machine context
1172 #define IA64_CONTEXT_TYPE struct sigcontext *
1173 #define IA64_CONTEXT scp
1174 #define IA64_GET_IP() (IA64_CONTEXT->sc_ip)
1175 #define IA64_SET_IP(V) (IA64_CONTEXT->sc_ip = (V))
1176 #define IA64_GET_PR(P) ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1177 #define IA64_GET_NAT(I) ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1178 #define IA64_SET_NAT(I,V) (IA64_CONTEXT->sc_nat= (IA64_CONTEXT->sc_nat & ~(1ul << (I))) | (((unsigned long)!!(V)) << (I)))
1179 #define IA64_GET_GR(R) (IA64_CONTEXT->sc_gr[(R)])
1180 #define IA64_SET_GR(R,V) (IA64_CONTEXT->sc_gr[(R)] = (V))
1181 #endif
1182
1183 // Instruction operations
1184 enum {
1185 IA64_INST_UNKNOWN = 0,
1186 IA64_INST_LD1, // ld1 op0=[op1]
1187 IA64_INST_LD1_UPDATE, // ld1 op0=[op1],op2
1188 IA64_INST_LD2, // ld2 op0=[op1]
1189 IA64_INST_LD2_UPDATE, // ld2 op0=[op1],op2
1190 IA64_INST_LD4, // ld4 op0=[op1]
1191 IA64_INST_LD4_UPDATE, // ld4 op0=[op1],op2
1192 IA64_INST_LD8, // ld8 op0=[op1]
1193 IA64_INST_LD8_UPDATE, // ld8 op0=[op1],op2
1194 IA64_INST_ST1, // st1 [op0]=op1
1195 IA64_INST_ST1_UPDATE, // st1 [op0]=op1,op2
1196 IA64_INST_ST2, // st2 [op0]=op1
1197 IA64_INST_ST2_UPDATE, // st2 [op0]=op1,op2
1198 IA64_INST_ST4, // st4 [op0]=op1
1199 IA64_INST_ST4_UPDATE, // st4 [op0]=op1,op2
1200 IA64_INST_ST8, // st8 [op0]=op1
1201 IA64_INST_ST8_UPDATE, // st8 [op0]=op1,op2
1202 IA64_INST_ADD, // add op0=op1,op2,op3
1203 IA64_INST_SUB, // sub op0=op1,op2,op3
1204 IA64_INST_SHLADD, // shladd op0=op1,op3,op2
1205 IA64_INST_AND, // and op0=op1,op2
1206 IA64_INST_ANDCM, // andcm op0=op1,op2
1207 IA64_INST_OR, // or op0=op1,op2
1208 IA64_INST_XOR, // xor op0=op1,op2
1209 IA64_INST_SXT1, // sxt1 op0=op1
1210 IA64_INST_SXT2, // sxt2 op0=op1
1211 IA64_INST_SXT4, // sxt4 op0=op1
1212 IA64_INST_ZXT1, // zxt1 op0=op1
1213 IA64_INST_ZXT2, // zxt2 op0=op1
1214 IA64_INST_ZXT4, // zxt4 op0=op1
1215 IA64_INST_NOP // nop op0
1216 };
1217
1218 const int IA64_N_OPERANDS = 4;
1219
1220 // Decoded operand type
1221 struct ia64_operand_t {
1222 unsigned char commit; // commit result of operation to register file?
1223 unsigned char valid; // XXX: not really used, can be removed (debug)
1224 signed char index; // index of GPR, or -1 if immediate value
1225 unsigned char nat; // NaT state before operation
1226 unsigned long value; // register contents or immediate value
1227 };
1228
1229 // Decoded instruction type
1230 struct ia64_instruction_t {
1231 unsigned char mnemo; // operation to perform
1232 unsigned char pred; // predicate register to check
1233 unsigned char no_memory; // used to emulated main fault instruction
1234 unsigned long inst; // the raw instruction bits (41-bit wide)
1235 ia64_operand_t operands[IA64_N_OPERANDS];
1236 };
1237
1238 // Get immediate sign-bit
1239 static inline int ia64_inst_get_sbit(unsigned long inst)
1240 {
1241 return (inst >> 36) & 1;
1242 }
1243
1244 // Get 8-bit immediate value (A3, A8, I27, M30)
1245 static inline unsigned long ia64_inst_get_imm8(unsigned long inst)
1246 {
1247 unsigned long value = (inst >> 13) & 0x7ful;
1248 if (ia64_inst_get_sbit(inst))
1249 value |= ~0x7ful;
1250 return value;
1251 }
1252
1253 // Get 9-bit immediate value (M3)
1254 static inline unsigned long ia64_inst_get_imm9b(unsigned long inst)
1255 {
1256 unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1257 if (ia64_inst_get_sbit(inst))
1258 value |= ~0xfful;
1259 return value;
1260 }
1261
1262 // Get 9-bit immediate value (M5)
1263 static inline unsigned long ia64_inst_get_imm9a(unsigned long inst)
1264 {
1265 unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1266 if (ia64_inst_get_sbit(inst))
1267 value |= ~0xfful;
1268 return value;
1269 }
1270
1271 // Get 14-bit immediate value (A4)
1272 static inline unsigned long ia64_inst_get_imm14(unsigned long inst)
1273 {
1274 unsigned long value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1275 if (ia64_inst_get_sbit(inst))
1276 value |= ~0x1fful;
1277 return value;
1278 }
1279
1280 // Get 22-bit immediate value (A5)
1281 static inline unsigned long ia64_inst_get_imm22(unsigned long inst)
1282 {
1283 unsigned long value = ((((inst >> 22) & 0x1f) << 16) |
1284 (((inst >> 27) & 0x1ff) << 7) |
1285 (inst & 0x7f));
1286 if (ia64_inst_get_sbit(inst))
1287 value |= ~0x1ffffful;
1288 return value;
1289 }
1290
1291 // Get 21-bit immediate value (I19)
1292 static inline unsigned long ia64_inst_get_imm21(unsigned long inst)
1293 {
1294 return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1295 }
1296
1297 // Get 2-bit count value (A2)
1298 static inline int ia64_inst_get_count2(unsigned long inst)
1299 {
1300 return (inst >> 27) & 0x3;
1301 }
1302
1303 // Get bundle template
1304 static inline unsigned int ia64_get_template(unsigned long raw_ip)
1305 {
1306 unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1307 return ip[0] & 0x1f;
1308 }
1309
1310 // Get specified instruction in bundle
1311 static unsigned long ia64_get_instruction(unsigned long raw_ip, int slot)
1312 {
1313 unsigned long inst;
1314 unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1315 #if DEBUG
1316 printf("Bundle: %016lx%016lx\n", ip[1], ip[0]);
1317 #endif
1318
1319 switch (slot) {
1320 case 0:
1321 inst = (ip[0] >> 5) & 0x1fffffffffful;
1322 break;
1323 case 1:
1324 inst = ((ip[1] & 0x7ffffful) << 18) | ((ip[0] >> 46) & 0x3fffful);
1325 break;
1326 case 2:
1327 inst = (ip[1] >> 23) & 0x1fffffffffful;
1328 break;
1329 case 3:
1330 fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1331 abort();
1332 break;
1333 }
1334
1335 #if DEBUG
1336 printf(" Instruction %d: 0x%016lx\n", slot, inst);
1337 #endif
1338 return inst;
1339 }
1340
1341 // Decode group 0 instructions
1342 static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1343 {
1344 const int r1 = (inst->inst >> 6) & 0x7f;
1345 const int r3 = (inst->inst >> 20) & 0x7f;
1346
1347 const int x3 = (inst->inst >> 33) & 0x07;
1348 const int x6 = (inst->inst >> 27) & 0x3f;
1349 const int x2 = (inst->inst >> 31) & 0x03;
1350 const int x4 = (inst->inst >> 27) & 0x0f;
1351
1352 if (x3 == 0) {
1353 switch (x6) {
1354 case 0x01: // nop.i (I19)
1355 inst->mnemo = IA64_INST_NOP;
1356 inst->operands[0].valid = true;
1357 inst->operands[0].index = -1;
1358 inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1359 return true;
1360 case 0x14: // sxt1 (I29)
1361 case 0x15: // sxt2 (I29)
1362 case 0x16: // sxt4 (I29)
1363 case 0x10: // zxt1 (I29)
1364 case 0x11: // zxt2 (I29)
1365 case 0x12: // zxt4 (I29)
1366 switch (x6) {
1367 case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1368 case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1369 case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1370 case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1371 case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1372 case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1373 default: abort();
1374 }
1375 inst->operands[0].valid = true;
1376 inst->operands[0].index = r1;
1377 inst->operands[1].valid = true;
1378 inst->operands[1].index = r3;
1379 inst->operands[1].value = IA64_GET_GR(r3);
1380 inst->operands[1].nat = IA64_GET_NAT(r3);
1381 return true;
1382 }
1383 }
1384 return false;
1385 }
1386
1387 // Decode group 4 instructions (load/store instructions)
1388 static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1389 {
1390 const int r1 = (inst->inst >> 6) & 0x7f;
1391 const int r2 = (inst->inst >> 13) & 0x7f;
1392 const int r3 = (inst->inst >> 20) & 0x7f;
1393
1394 const int m = (inst->inst >> 36) & 1;
1395 const int x = (inst->inst >> 27) & 1;
1396 const int x6 = (inst->inst >> 30) & 0x3f;
1397
1398 switch (x6) {
1399 case 0x00:
1400 case 0x01:
1401 case 0x02:
1402 case 0x03:
1403 if (x == 0) {
1404 inst->operands[0].valid = true;
1405 inst->operands[0].index = r1;
1406 inst->operands[1].valid = true;
1407 inst->operands[1].index = r3;
1408 inst->operands[1].value = IA64_GET_GR(r3);
1409 inst->operands[1].nat = IA64_GET_NAT(r3);
1410 if (m == 0) {
1411 switch (x6) {
1412 case 0x00: inst->mnemo = IA64_INST_LD1; break;
1413 case 0x01: inst->mnemo = IA64_INST_LD2; break;
1414 case 0x02: inst->mnemo = IA64_INST_LD4; break;
1415 case 0x03: inst->mnemo = IA64_INST_LD8; break;
1416 }
1417 }
1418 else {
1419 inst->operands[2].valid = true;
1420 inst->operands[2].index = r2;
1421 inst->operands[2].value = IA64_GET_GR(r2);
1422 inst->operands[2].nat = IA64_GET_NAT(r2);
1423 switch (x6) {
1424 case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1425 case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1426 case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1427 case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1428 }
1429 }
1430 return true;
1431 }
1432 break;
1433 case 0x30:
1434 case 0x31:
1435 case 0x32:
1436 case 0x33:
1437 if (m == 0 && x == 0) {
1438 inst->operands[0].valid = true;
1439 inst->operands[0].index = r3;
1440 inst->operands[0].value = IA64_GET_GR(r3);
1441 inst->operands[0].nat = IA64_GET_NAT(r3);
1442 inst->operands[1].valid = true;
1443 inst->operands[1].index = r2;
1444 inst->operands[1].value = IA64_GET_GR(r2);
1445 inst->operands[1].nat = IA64_GET_NAT(r2);
1446 switch (x6) {
1447 case 0x30: inst->mnemo = IA64_INST_ST1; break;
1448 case 0x31: inst->mnemo = IA64_INST_ST2; break;
1449 case 0x32: inst->mnemo = IA64_INST_ST4; break;
1450 case 0x33: inst->mnemo = IA64_INST_ST8; break;
1451 }
1452 return true;
1453 }
1454 break;
1455 }
1456 return false;
1457 }
1458
1459 // Decode group 5 instructions (load/store instructions)
1460 static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1461 {
1462 const int r1 = (inst->inst >> 6) & 0x7f;
1463 const int r2 = (inst->inst >> 13) & 0x7f;
1464 const int r3 = (inst->inst >> 20) & 0x7f;
1465
1466 const int x6 = (inst->inst >> 30) & 0x3f;
1467
1468 switch (x6) {
1469 case 0x00:
1470 case 0x01:
1471 case 0x02:
1472 case 0x03:
1473 inst->operands[0].valid = true;
1474 inst->operands[0].index = r1;
1475 inst->operands[1].valid = true;
1476 inst->operands[1].index = r3;
1477 inst->operands[1].value = IA64_GET_GR(r3);
1478 inst->operands[1].nat = IA64_GET_NAT(r3);
1479 inst->operands[2].valid = true;
1480 inst->operands[2].index = -1;
1481 inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1482 inst->operands[2].nat = 0;
1483 switch (x6) {
1484 case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1485 case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1486 case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1487 case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1488 }
1489 return true;
1490 case 0x30:
1491 case 0x31:
1492 case 0x32:
1493 case 0x33:
1494 inst->operands[0].valid = true;
1495 inst->operands[0].index = r3;
1496 inst->operands[0].value = IA64_GET_GR(r3);
1497 inst->operands[0].nat = IA64_GET_NAT(r3);
1498 inst->operands[1].valid = true;
1499 inst->operands[1].index = r2;
1500 inst->operands[1].value = IA64_GET_GR(r2);
1501 inst->operands[1].nat = IA64_GET_NAT(r2);
1502 inst->operands[2].valid = true;
1503 inst->operands[2].index = -1;
1504 inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1505 inst->operands[2].nat = 0;
1506 switch (x6) {
1507 case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1508 case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1509 case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1510 case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1511 }
1512 return true;
1513 }
1514 return false;
1515 }
1516
1517 // Decode group 8 instructions (ALU integer)
1518 static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1519 {
1520 const int r1 = (inst->inst >> 6) & 0x7f;
1521 const int r2 = (inst->inst >> 13) & 0x7f;
1522 const int r3 = (inst->inst >> 20) & 0x7f;
1523
1524 const int x2a = (inst->inst >> 34) & 0x3;
1525 const int x2b = (inst->inst >> 27) & 0x3;
1526 const int x4 = (inst->inst >> 29) & 0xf;
1527 const int ve = (inst->inst >> 33) & 0x1;
1528
1529 // destination register (r1) is always valid in this group
1530 inst->operands[0].valid = true;
1531 inst->operands[0].index = r1;
1532
1533 // source register (r3) is always valid in this group
1534 inst->operands[2].valid = true;
1535 inst->operands[2].index = r3;
1536 inst->operands[2].value = IA64_GET_GR(r3);
1537 inst->operands[2].nat = IA64_GET_NAT(r3);
1538
1539 if (x2a == 0 && ve == 0) {
1540 inst->operands[1].valid = true;
1541 inst->operands[1].index = r2;
1542 inst->operands[1].value = IA64_GET_GR(r2);
1543 inst->operands[1].nat = IA64_GET_NAT(r2);
1544 switch (x4) {
1545 case 0x0: // add (A1)
1546 inst->mnemo = IA64_INST_ADD;
1547 inst->operands[3].valid = true;
1548 inst->operands[3].index = -1;
1549 inst->operands[3].value = x2b == 1;
1550 return true;
1551 case 0x1: // add (A1)
1552 inst->mnemo = IA64_INST_SUB;
1553 inst->operands[3].valid = true;
1554 inst->operands[3].index = -1;
1555 inst->operands[3].value = x2b == 0;
1556 return true;
1557 case 0x4: // shladd (A2)
1558 inst->mnemo = IA64_INST_SHLADD;
1559 inst->operands[3].valid = true;
1560 inst->operands[3].index = -1;
1561 inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1562 return true;
1563 case 0x9:
1564 if (x2b == 1) {
1565 inst->mnemo = IA64_INST_SUB;
1566 inst->operands[1].index = -1;
1567 inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1568 inst->operands[1].nat = 0;
1569 return true;
1570 }
1571 break;
1572 case 0xb:
1573 inst->operands[1].index = -1;
1574 inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1575 inst->operands[1].nat = 0;
1576 // fall-through
1577 case 0x3:
1578 switch (x2b) {
1579 case 0: inst->mnemo = IA64_INST_AND; break;
1580 case 1: inst->mnemo = IA64_INST_ANDCM; break;
1581 case 2: inst->mnemo = IA64_INST_OR; break;
1582 case 3: inst->mnemo = IA64_INST_XOR; break;
1583 }
1584 return true;
1585 }
1586 }
1587 return false;
1588 }
1589
1590 // Decode instruction
1591 static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1592 {
1593 const int major = (inst->inst >> 37) & 0xf;
1594
1595 inst->mnemo = IA64_INST_UNKNOWN;
1596 inst->pred = inst->inst & 0x3f;
1597 memset(&inst->operands[0], 0, sizeof(inst->operands));
1598
1599 switch (major) {
1600 case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1601 case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1602 case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1603 case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1604 }
1605 return false;
1606 }
1607
1608 static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1609 {
1610 // XXX: handle Register NaT Consumption fault?
1611 // XXX: this simple emulator assumes instructions in a bundle
1612 // don't depend on effects of other instructions in the same
1613 // bundle. It probably would be simpler to JIT-generate code to be
1614 // executed natively but probably more costly (inject/extract CPU state)
1615 if (inst->mnemo == IA64_INST_UNKNOWN)
1616 return false;
1617 if (inst->pred && !IA64_GET_PR(inst->pred))
1618 return true;
1619
1620 unsigned char nat, nat2;
1621 unsigned long dst, dst2, src1, src2, src3;
1622
1623 switch (inst->mnemo) {
1624 case IA64_INST_NOP:
1625 break;
1626 case IA64_INST_ADD:
1627 case IA64_INST_SUB:
1628 case IA64_INST_SHLADD:
1629 src3 = inst->operands[3].value;
1630 // fall-through
1631 case IA64_INST_AND:
1632 case IA64_INST_ANDCM:
1633 case IA64_INST_OR:
1634 case IA64_INST_XOR:
1635 src1 = inst->operands[1].value;
1636 src2 = inst->operands[2].value;
1637 switch (inst->mnemo) {
1638 case IA64_INST_ADD: dst = src1 + src2 + src3; break;
1639 case IA64_INST_SUB: dst = src1 - src2 - src3; break;
1640 case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1641 case IA64_INST_AND: dst = src1 & src2; break;
1642 case IA64_INST_ANDCM: dst = src1 &~ src2; break;
1643 case IA64_INST_OR: dst = src1 | src2; break;
1644 case IA64_INST_XOR: dst = src1 ^ src2; break;
1645 }
1646 inst->operands[0].commit = true;
1647 inst->operands[0].value = dst;
1648 inst->operands[0].nat = inst->operands[1].nat | inst->operands[2].nat;
1649 break;
1650 case IA64_INST_SXT1:
1651 case IA64_INST_SXT2:
1652 case IA64_INST_SXT4:
1653 case IA64_INST_ZXT1:
1654 case IA64_INST_ZXT2:
1655 case IA64_INST_ZXT4:
1656 src1 = inst->operands[1].value;
1657 switch (inst->mnemo) {
1658 case IA64_INST_SXT1: dst = (signed long)(signed char)src1; break;
1659 case IA64_INST_SXT2: dst = (signed long)(signed short)src1; break;
1660 case IA64_INST_SXT4: dst = (signed long)(signed int)src1; break;
1661 case IA64_INST_ZXT1: dst = (unsigned char)src1; break;
1662 case IA64_INST_ZXT2: dst = (unsigned short)src1; break;
1663 case IA64_INST_ZXT4: dst = (unsigned int)src1; break;
1664 }
1665 inst->operands[0].commit = true;
1666 inst->operands[0].value = dst;
1667 inst->operands[0].nat = inst->operands[1].nat;
1668 break;
1669 case IA64_INST_LD1_UPDATE:
1670 case IA64_INST_LD2_UPDATE:
1671 case IA64_INST_LD4_UPDATE:
1672 case IA64_INST_LD8_UPDATE:
1673 inst->operands[1].commit = true;
1674 dst2 = inst->operands[1].value + inst->operands[2].value;
1675 nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1676 // fall-through
1677 case IA64_INST_LD1:
1678 case IA64_INST_LD2:
1679 case IA64_INST_LD4:
1680 case IA64_INST_LD8:
1681 src1 = inst->operands[1].value;
1682 if (inst->no_memory)
1683 dst = 0;
1684 else {
1685 switch (inst->mnemo) {
1686 case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((unsigned char *)src1); break;
1687 case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((unsigned short *)src1); break;
1688 case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((unsigned int *)src1); break;
1689 case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((unsigned long *)src1); break;
1690 }
1691 }
1692 inst->operands[0].commit = true;
1693 inst->operands[0].value = dst;
1694 inst->operands[0].nat = 0;
1695 inst->operands[1].value = dst2;
1696 inst->operands[1].nat = nat2;
1697 break;
1698 case IA64_INST_ST1_UPDATE:
1699 case IA64_INST_ST2_UPDATE:
1700 case IA64_INST_ST4_UPDATE:
1701 case IA64_INST_ST8_UPDATE:
1702 inst->operands[0].commit = 0;
1703 dst2 = inst->operands[0].value + inst->operands[2].value;
1704 nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1705 // fall-through
1706 case IA64_INST_ST1:
1707 case IA64_INST_ST2:
1708 case IA64_INST_ST4:
1709 case IA64_INST_ST8:
1710 dst = inst->operands[0].value;
1711 src1 = inst->operands[1].value;
1712 if (!inst->no_memory) {
1713 switch (inst->mnemo) {
1714 case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((unsigned char *)dst) = src1; break;
1715 case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((unsigned short *)dst) = src1; break;
1716 case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((unsigned int *)dst) = src1; break;
1717 case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((unsigned long *)dst) = src1; break;
1718 }
1719 }
1720 inst->operands[0].value = dst2;
1721 inst->operands[0].nat = nat2;
1722 break;
1723 default:
1724 return false;
1725 }
1726
1727 for (int i = 0; i < IA64_N_OPERANDS; i++) {
1728 ia64_operand_t const & op = inst->operands[i];
1729 if (!op.commit)
1730 continue;
1731 if (op.index == -1)
1732 return false; // XXX: internal error
1733 IA64_SET_GR(op.index, op.value);
1734 IA64_SET_NAT(op.index, op.nat);
1735 }
1736 return true;
1737 }
1738
1739 static bool ia64_emulate_instruction(unsigned long raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1740 {
1741 ia64_instruction_t inst;
1742 memset(&inst, 0, sizeof(inst));
1743 inst.inst = raw_inst;
1744 if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1745 return false;
1746 return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1747 }
1748
1749 static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1750 {
1751 unsigned long ip = IA64_GET_IP();
1752 #if DEBUG
1753 printf("IP: 0x%016lx\n", ip);
1754 #if 0
1755 printf(" Template 0x%02x\n", ia64_get_template(ip));
1756 ia64_get_instruction(ip, 0);
1757 ia64_get_instruction(ip, 1);
1758 ia64_get_instruction(ip, 2);
1759 #endif
1760 #endif
1761
1762 // Select which decode switch to use
1763 ia64_instruction_t inst;
1764 inst.inst = ia64_get_instruction(ip, ip & 3);
1765 if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1766 fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1767 return false;
1768 }
1769
1770 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1771 transfer_size_t transfer_size = SIZE_UNKNOWN;
1772
1773 switch (inst.mnemo) {
1774 case IA64_INST_LD1:
1775 case IA64_INST_LD2:
1776 case IA64_INST_LD4:
1777 case IA64_INST_LD8:
1778 case IA64_INST_LD1_UPDATE:
1779 case IA64_INST_LD2_UPDATE:
1780 case IA64_INST_LD4_UPDATE:
1781 case IA64_INST_LD8_UPDATE:
1782 transfer_type = SIGSEGV_TRANSFER_LOAD;
1783 break;
1784 case IA64_INST_ST1:
1785 case IA64_INST_ST2:
1786 case IA64_INST_ST4:
1787 case IA64_INST_ST8:
1788 case IA64_INST_ST1_UPDATE:
1789 case IA64_INST_ST2_UPDATE:
1790 case IA64_INST_ST4_UPDATE:
1791 case IA64_INST_ST8_UPDATE:
1792 transfer_type = SIGSEGV_TRANSFER_STORE;
1793 break;
1794 }
1795
1796 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1797 // Unknown machine code, let it crash. Then patch the decoder
1798 fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1799 return false;
1800 }
1801
1802 switch (inst.mnemo) {
1803 case IA64_INST_LD1:
1804 case IA64_INST_LD1_UPDATE:
1805 case IA64_INST_ST1:
1806 case IA64_INST_ST1_UPDATE:
1807 transfer_size = SIZE_BYTE;
1808 break;
1809 case IA64_INST_LD2:
1810 case IA64_INST_LD2_UPDATE:
1811 case IA64_INST_ST2:
1812 case IA64_INST_ST2_UPDATE:
1813 transfer_size = SIZE_WORD;
1814 break;
1815 case IA64_INST_LD4:
1816 case IA64_INST_LD4_UPDATE:
1817 case IA64_INST_ST4:
1818 case IA64_INST_ST4_UPDATE:
1819 transfer_size = SIZE_LONG;
1820 break;
1821 case IA64_INST_LD8:
1822 case IA64_INST_LD8_UPDATE:
1823 case IA64_INST_ST8:
1824 case IA64_INST_ST8_UPDATE:
1825 transfer_size = SIZE_QUAD;
1826 break;
1827 }
1828
1829 if (transfer_size == SIZE_UNKNOWN) {
1830 // Unknown machine code, let it crash. Then patch the decoder
1831 fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1832 return false;
1833 }
1834
1835 inst.no_memory = true;
1836 if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1837 fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1838 return false;
1839 }
1840
1841 int slot = ip & 3;
1842 bool emulate_next = false;
1843 switch (slot) {
1844 case 0:
1845 switch (ia64_get_template(ip)) {
1846 case 0x2: // MI;I
1847 case 0x3: // MI;I;
1848 emulate_next = true;
1849 slot = 2;
1850 break;
1851 case 0xa: // M;MI
1852 case 0xb: // M;MI;
1853 emulate_next = true;
1854 slot = 1;
1855 break;
1856 }
1857 break;
1858 }
1859 if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
1860 while (slot < 3) {
1861 if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
1862 fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
1863 return false;
1864 }
1865 ++slot;
1866 }
1867 }
1868
1869 #if IA64_CAN_PATCH_IP_SLOT
1870 if ((slot = ip & 3) < 2)
1871 IA64_SET_IP((ip & ~3ul) + (slot + 1));
1872 else
1873 #endif
1874 IA64_SET_IP((ip & ~3ul) + 16);
1875 #if DEBUG
1876 printf("IP: 0x%016lx\n", IA64_GET_IP());
1877 #endif
1878 return true;
1879 }
1880 #endif
1881
1882 // Decode and skip PPC instruction
1883 #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
1884 static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
1885 {
1886 instruction_t instr;
1887 powerpc_decode_instruction(&instr, *nip_p, regs);
1888
1889 if (instr.transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1890 // Unknown machine code, let it crash. Then patch the decoder
1891 return false;
1892 }
1893
1894 #if DEBUG
1895 printf("%08x: %s %s access", *nip_p,
1896 instr.transfer_size == SIZE_BYTE ? "byte" :
1897 instr.transfer_size == SIZE_WORD ? "word" :
1898 instr.transfer_size == SIZE_LONG ? "long" : "quad",
1899 instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
1900
1901 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1902 printf(" r%d (ra = %08x)\n", instr.ra, instr.addr);
1903 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1904 printf(" r%d (rd = 0)\n", instr.rd);
1905 #endif
1906
1907 if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
1908 regs[instr.ra] = instr.addr;
1909 if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD)
1910 regs[instr.rd] = 0;
1911
1912 *nip_p += 4;
1913 return true;
1914 }
1915 #endif
1916
1917 // Decode and skip MIPS instruction
1918 #if (defined(mips) || defined(__mips))
1919 static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
1920 {
1921 unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
1922
1923 if (epc == 0)
1924 return false;
1925
1926 #if DEBUG
1927 printf("IP: %p [%08x]\n", epc, epc[0]);
1928 #endif
1929
1930 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1931 transfer_size_t transfer_size = SIZE_LONG;
1932 int direction = 0;
1933
1934 const unsigned int opcode = epc[0];
1935 switch (opcode >> 26) {
1936 case 32: // Load Byte
1937 case 36: // Load Byte Unsigned
1938 transfer_type = SIGSEGV_TRANSFER_LOAD;
1939 transfer_size = SIZE_BYTE;
1940 break;
1941 case 33: // Load Halfword
1942 case 37: // Load Halfword Unsigned
1943 transfer_type = SIGSEGV_TRANSFER_LOAD;
1944 transfer_size = SIZE_WORD;
1945 break;
1946 case 35: // Load Word
1947 case 39: // Load Word Unsigned
1948 transfer_type = SIGSEGV_TRANSFER_LOAD;
1949 transfer_size = SIZE_LONG;
1950 break;
1951 case 34: // Load Word Left
1952 transfer_type = SIGSEGV_TRANSFER_LOAD;
1953 transfer_size = SIZE_LONG;
1954 direction = -1;
1955 break;
1956 case 38: // Load Word Right
1957 transfer_type = SIGSEGV_TRANSFER_LOAD;
1958 transfer_size = SIZE_LONG;
1959 direction = 1;
1960 break;
1961 case 55: // Load Doubleword
1962 transfer_type = SIGSEGV_TRANSFER_LOAD;
1963 transfer_size = SIZE_QUAD;
1964 break;
1965 case 26: // Load Doubleword Left
1966 transfer_type = SIGSEGV_TRANSFER_LOAD;
1967 transfer_size = SIZE_QUAD;
1968 direction = -1;
1969 break;
1970 case 27: // Load Doubleword Right
1971 transfer_type = SIGSEGV_TRANSFER_LOAD;
1972 transfer_size = SIZE_QUAD;
1973 direction = 1;
1974 break;
1975 case 40: // Store Byte
1976 transfer_type = SIGSEGV_TRANSFER_STORE;
1977 transfer_size = SIZE_BYTE;
1978 break;
1979 case 41: // Store Halfword
1980 transfer_type = SIGSEGV_TRANSFER_STORE;
1981 transfer_size = SIZE_WORD;
1982 break;
1983 case 43: // Store Word
1984 case 42: // Store Word Left
1985 case 46: // Store Word Right
1986 transfer_type = SIGSEGV_TRANSFER_STORE;
1987 transfer_size = SIZE_LONG;
1988 break;
1989 case 63: // Store Doubleword
1990 case 44: // Store Doubleword Left
1991 case 45: // Store Doubleword Right
1992 transfer_type = SIGSEGV_TRANSFER_STORE;
1993 transfer_size = SIZE_QUAD;
1994 break;
1995 /* Misc instructions unlikely to be used within CPU emulators */
1996 case 48: // Load Linked Word
1997 transfer_type = SIGSEGV_TRANSFER_LOAD;
1998 transfer_size = SIZE_LONG;
1999 break;
2000 case 52: // Load Linked Doubleword
2001 transfer_type = SIGSEGV_TRANSFER_LOAD;
2002 transfer_size = SIZE_QUAD;
2003 break;
2004 case 56: // Store Conditional Word
2005 transfer_type = SIGSEGV_TRANSFER_STORE;
2006 transfer_size = SIZE_LONG;
2007 break;
2008 case 60: // Store Conditional Doubleword
2009 transfer_type = SIGSEGV_TRANSFER_STORE;
2010 transfer_size = SIZE_QUAD;
2011 break;
2012 }
2013
2014 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
2015 // Unknown machine code, let it crash. Then patch the decoder
2016 return false;
2017 }
2018
2019 // Zero target register in case of a load operation
2020 const int reg = (opcode >> 16) & 0x1f;
2021 if (transfer_type == SIGSEGV_TRANSFER_LOAD) {
2022 if (direction == 0)
2023 regs[reg] = 0;
2024 else {
2025 // FIXME: untested code
2026 unsigned long ea = regs[(opcode >> 21) & 0x1f];
2027 ea += (signed long)(signed int)(signed short)(opcode & 0xffff);
2028 const int offset = ea & (transfer_size == SIZE_LONG ? 3 : 7);
2029 unsigned long value;
2030 if (direction > 0) {
2031 const unsigned long rmask = ~((1L << ((offset + 1) * 8)) - 1);
2032 value = regs[reg] & rmask;
2033 }
2034 else {
2035 const unsigned long lmask = (1L << (offset * 8)) - 1;
2036 value = regs[reg] & lmask;
2037 }
2038 // restore most significant bits
2039 if (transfer_size == SIZE_LONG)
2040 value = (signed long)(signed int)value;
2041 regs[reg] = value;
2042 }
2043 }
2044
2045 #if DEBUG
2046 #if (defined(_ABIN32) || defined(_ABI64))
2047 static const char * mips_gpr_names[32] = {
2048 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2049 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2050 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2051 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
2052 };
2053 #else
2054 static const char * mips_gpr_names[32] = {
2055 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2056 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
2057 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2058 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
2059 };
2060 #endif
2061 printf("%s %s register %s\n",
2062 transfer_size == SIZE_BYTE ? "byte" :
2063 transfer_size == SIZE_WORD ? "word" :
2064 transfer_size == SIZE_LONG ? "long" :
2065 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2066 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2067 mips_gpr_names[reg]);
2068 #endif
2069
2070 *pc_p += 4;
2071 return true;
2072 }
2073 #endif
2074
2075 // Decode and skip SPARC instruction
2076 #if (defined(sparc) || defined(__sparc__))
2077 enum {
2078 #if (defined(__sun__))
2079 SPARC_REG_G1 = REG_G1,
2080 SPARC_REG_O0 = REG_O0,
2081 SPARC_REG_PC = REG_PC,
2082 SPARC_REG_nPC = REG_nPC
2083 #endif
2084 };
2085 static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
2086 {
2087 unsigned int * pc = (unsigned int *)regs[SPARC_REG_PC];
2088
2089 if (pc == 0)
2090 return false;
2091
2092 #if DEBUG
2093 printf("IP: %p [%08x]\n", pc, pc[0]);
2094 #endif
2095
2096 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
2097 transfer_size_t transfer_size = SIZE_LONG;
2098 bool register_pair = false;
2099
2100 const unsigned int opcode = pc[0];
2101 if ((opcode >> 30) != 3)
2102 return false;
2103 switch ((opcode >> 19) & 0x3f) {
2104 case 9: // Load Signed Byte
2105 case 1: // Load Unsigned Byte
2106 transfer_type = SIGSEGV_TRANSFER_LOAD;
2107 transfer_size = SIZE_BYTE;
2108 break;
2109 case 10:// Load Signed Halfword
2110 case 2: // Load Unsigned Word
2111 transfer_type = SIGSEGV_TRANSFER_LOAD;
2112 transfer_size = SIZE_WORD;
2113 break;
2114 case 8: // Load Word
2115 case 0: // Load Unsigned Word
2116 transfer_type = SIGSEGV_TRANSFER_LOAD;
2117 transfer_size = SIZE_LONG;
2118 break;
2119 case 11:// Load Extended Word
2120 transfer_type = SIGSEGV_TRANSFER_LOAD;
2121 transfer_size = SIZE_QUAD;
2122 break;
2123 case 3: // Load Doubleword
2124 transfer_type = SIGSEGV_TRANSFER_LOAD;
2125 transfer_size = SIZE_LONG;
2126 register_pair = true;
2127 break;
2128 case 5: // Store Byte
2129 transfer_type = SIGSEGV_TRANSFER_STORE;
2130 transfer_size = SIZE_BYTE;
2131 break;
2132 case 6: // Store Halfword
2133 transfer_type = SIGSEGV_TRANSFER_STORE;
2134 transfer_size = SIZE_WORD;
2135 break;
2136 case 4: // Store Word
2137 transfer_type = SIGSEGV_TRANSFER_STORE;
2138 transfer_size = SIZE_LONG;
2139 break;
2140 case 14:// Store Extended Word
2141 transfer_type = SIGSEGV_TRANSFER_STORE;
2142 transfer_size = SIZE_QUAD;
2143 break;
2144 case 7: // Store Doubleword
2145 transfer_type = SIGSEGV_TRANSFER_STORE;
2146 transfer_size = SIZE_LONG;
2147 register_pair = true;
2148 break;
2149 }
2150
2151 if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
2152 // Unknown machine code, let it crash. Then patch the decoder
2153 return false;
2154 }
2155
2156 const int reg = (opcode >> 25) & 0x1f;
2157
2158 #if DEBUG
2159 static const char * reg_names[] = {
2160 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2161 "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2162 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2163 "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2164 };
2165 printf("%s %s register %s\n",
2166 transfer_size == SIZE_BYTE ? "byte" :
2167 transfer_size == SIZE_WORD ? "word" :
2168 transfer_size == SIZE_LONG ? "long" :
2169 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2170 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2171 reg_names[reg]);
2172 #endif
2173
2174 // Zero target register in case of a load operation
2175 if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2176 // FIXME: code to handle local & input registers is not tested
2177 if (reg >= 1 && reg < 8) {
2178 // global registers
2179 regs[reg - 1 + SPARC_REG_G1] = 0;
2180 }
2181 else if (reg >= 8 && reg < 16) {
2182 // output registers
2183 regs[reg - 8 + SPARC_REG_O0] = 0;
2184 }
2185 else if (reg >= 16 && reg < 24) {
2186 // local registers (in register windows)
2187 if (gwins)
2188 gwins->wbuf->rw_local[reg - 16] = 0;
2189 else
2190 rwin->rw_local[reg - 16] = 0;
2191 }
2192 else {
2193 // input registers (in register windows)
2194 if (gwins)
2195 gwins->wbuf->rw_in[reg - 24] = 0;
2196 else
2197 rwin->rw_in[reg - 24] = 0;
2198 }
2199 }
2200
2201 regs[SPARC_REG_PC] += 4;
2202 regs[SPARC_REG_nPC] += 4;
2203 return true;
2204 }
2205 #endif
2206 #endif
2207
2208 // Decode and skip ARM instruction
2209 #if (defined(arm) || defined(__arm__))
2210 enum {
2211 #if (defined(__linux__))
2212 ARM_REG_PC = 15,
2213 ARM_REG_CPSR = 16
2214 #endif
2215 };
2216 static bool arm_skip_instruction(unsigned long * regs)
2217 {
2218 unsigned int * pc = (unsigned int *)regs[ARM_REG_PC];
2219
2220 if (pc == 0)
2221 return false;
2222
2223 #if DEBUG
2224 printf("IP: %p [%08x]\n", pc, pc[0]);
2225 #endif
2226
2227 transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
2228 transfer_size_t transfer_size = SIZE_UNKNOWN;
2229 enum { op_sdt = 1, op_sdth = 2 };
2230 int op = 0;
2231
2232 // Handle load/store instructions only
2233 const unsigned int opcode = pc[0];
2234 switch ((opcode >> 25) & 7) {
2235 case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH)
2236 op = op_sdth;
2237 // Determine transfer size (S/H bits)
2238 switch ((opcode >> 5) & 3) {
2239 case 0: // SWP instruction
2240 break;
2241 case 1: // Unsigned halfwords
2242 case 3: // Signed halfwords
2243 transfer_size = SIZE_WORD;
2244 break;
2245 case 2: // Signed byte
2246 transfer_size = SIZE_BYTE;
2247 break;
2248 }
2249 break;
2250 case 2:
2251 case 3: // Single Data Transfer (LDR, STR)
2252 op = op_sdt;
2253 // Determine transfer size (B bit)
2254 if (((opcode >> 22) & 1) == 1)
2255 transfer_size = SIZE_BYTE;
2256 else
2257 transfer_size = SIZE_LONG;
2258 break;
2259 default:
2260 // FIXME: support load/store mutliple?
2261 return false;
2262 }
2263
2264 // Check for invalid transfer size (SWP instruction?)
2265 if (transfer_size == SIZE_UNKNOWN)
2266 return false;
2267
2268 // Determine transfer type (L bit)
2269 if (((opcode >> 20) & 1) == 1)
2270 transfer_type = SIGSEGV_TRANSFER_LOAD;
2271 else
2272 transfer_type = SIGSEGV_TRANSFER_STORE;
2273
2274 // Compute offset
2275 int offset;
2276 if (((opcode >> 25) & 1) == 0) {
2277 if (op == op_sdt)
2278 offset = opcode & 0xfff;
2279 else if (op == op_sdth) {
2280 int rm = opcode & 0xf;
2281 if (((opcode >> 22) & 1) == 0) {
2282 // register offset
2283 offset = regs[rm];
2284 }
2285 else {
2286 // immediate offset
2287 offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f);
2288 }
2289 }
2290 }
2291 else {
2292 const int rm = opcode & 0xf;
2293 const int sh = (opcode >> 7) & 0x1f;
2294 if (((opcode >> 4) & 1) == 1) {
2295 // we expect only legal load/store instructions
2296 printf("FATAL: invalid shift operand\n");
2297 return false;
2298 }
2299 const unsigned int v = regs[rm];
2300 switch ((opcode >> 5) & 3) {
2301 case 0: // logical shift left
2302 offset = sh ? v << sh : v;
2303 break;
2304 case 1: // logical shift right
2305 offset = sh ? v >> sh : 0;
2306 break;
2307 case 2: // arithmetic shift right
2308 if (sh)
2309 offset = ((signed int)v) >> sh;
2310 else
2311 offset = (v & 0x80000000) ? 0xffffffff : 0;
2312 break;
2313 case 3: // rotate right
2314 if (sh)
2315 offset = (v >> sh) | (v << (32 - sh));
2316 else
2317 offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000);
2318 break;
2319 }
2320 }
2321 if (((opcode >> 23) & 1) == 0)
2322 offset = -offset;
2323
2324 int rd = (opcode >> 12) & 0xf;
2325 int rn = (opcode >> 16) & 0xf;
2326 #if DEBUG
2327 static const char * reg_names[] = {
2328 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2329 "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc"
2330 };
2331 printf("%s %s register %s\n",
2332 transfer_size == SIZE_BYTE ? "byte" :
2333 transfer_size == SIZE_WORD ? "word" :
2334 transfer_size == SIZE_LONG ? "long" : "unknown",
2335 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2336 reg_names[rd]);
2337 #endif
2338
2339 unsigned int base = regs[rn];
2340 if (((opcode >> 24) & 1) == 1)
2341 base += offset;
2342
2343 if (transfer_type == SIGSEGV_TRANSFER_LOAD)
2344 regs[rd] = 0;
2345
2346 if (((opcode >> 24) & 1) == 0) // post-index addressing
2347 regs[rn] += offset;
2348 else if (((opcode >> 21) & 1) == 1) // write-back address into base
2349 regs[rn] = base;
2350
2351 regs[ARM_REG_PC] += 4;
2352 return true;
2353 }
2354 #endif
2355
2356
2357 // Fallbacks
2358 #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2359 #define SIGSEGV_FAULT_ADDRESS_FAST SIGSEGV_FAULT_ADDRESS
2360 #endif
2361 #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2362 #define SIGSEGV_FAULT_INSTRUCTION_FAST SIGSEGV_FAULT_INSTRUCTION
2363 #endif
2364 #ifndef SIGSEGV_FAULT_INSTRUCTION
2365 #define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_INVALID_ADDRESS
2366 #endif
2367 #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2368 #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2369 #endif
2370 #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2371 #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2372 #endif
2373
2374 // SIGSEGV recovery supported ?
2375 #if defined(SIGSEGV_ALL_SIGNALS) && defined(SIGSEGV_FAULT_HANDLER_ARGLIST) && defined(SIGSEGV_FAULT_ADDRESS)
2376 #define HAVE_SIGSEGV_RECOVERY
2377 #endif
2378
2379
2380 /*
2381 * SIGSEGV global handler
2382 */
2383
2384 struct sigsegv_info_t {
2385 sigsegv_address_t addr;
2386 sigsegv_address_t pc;
2387 #ifdef HAVE_MACH_EXCEPTIONS
2388 mach_port_t thread;
2389 bool has_exc_state;
2390 SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2391 mach_msg_type_number_t exc_state_count;
2392 bool has_thr_state;
2393 SIGSEGV_THREAD_STATE_TYPE thr_state;
2394 mach_msg_type_number_t thr_state_count;
2395 #endif
2396 };
2397
2398 #ifdef HAVE_MACH_EXCEPTIONS
2399 static void mach_get_exception_state(sigsegv_info_t *SIP)
2400 {
2401 SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2402 kern_return_t krc = thread_get_state(SIP->thread,
2403 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2404 (natural_t *)&SIP->exc_state,
2405 &SIP->exc_state_count);
2406 MACH_CHECK_ERROR(thread_get_state, krc);
2407 SIP->has_exc_state = true;
2408 }
2409
2410 static void mach_get_thread_state(sigsegv_info_t *SIP)
2411 {
2412 SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2413 kern_return_t krc = thread_get_state(SIP->thread,
2414 SIGSEGV_THREAD_STATE_FLAVOR,
2415 (natural_t *)&SIP->thr_state,
2416 &SIP->thr_state_count);
2417 MACH_CHECK_ERROR(thread_get_state, krc);
2418 SIP->has_thr_state = true;
2419 }
2420
2421 static void mach_set_thread_state(sigsegv_info_t *SIP)
2422 {
2423 kern_return_t krc = thread_set_state(SIP->thread,
2424 SIGSEGV_THREAD_STATE_FLAVOR,
2425 (natural_t *)&SIP->thr_state,
2426 SIP->thr_state_count);
2427 MACH_CHECK_ERROR(thread_set_state, krc);
2428 }
2429 #endif
2430
2431 // Return the address of the invalid memory reference
2432 sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2433 {
2434 #ifdef HAVE_MACH_EXCEPTIONS
2435 static int use_fast_path = -1;
2436 if (use_fast_path != 1 && !SIP->has_exc_state) {
2437 mach_get_exception_state(SIP);
2438
2439 sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2440 if (use_fast_path < 0) {
2441 const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2442 if (machfault) {
2443 if (strcmp(machfault, "fast") == 0)
2444 use_fast_path = 1;
2445 else if (strcmp(machfault, "slow") == 0)
2446 use_fast_path = 0;
2447 }
2448 if (use_fast_path < 0)
2449 use_fast_path = addr == SIP->addr;
2450 }
2451 SIP->addr = addr;
2452 }
2453 #endif
2454 return SIP->addr;
2455 }
2456
2457 // Return the address of the instruction that caused the fault, or
2458 // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2459 sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2460 {
2461 #ifdef HAVE_MACH_EXCEPTIONS
2462 if (!SIP->has_thr_state) {
2463 mach_get_thread_state(SIP);
2464
2465 SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2466 }
2467 #endif
2468 return SIP->pc;
2469 }
2470
2471 // This function handles the badaccess to memory.
2472 // It is called from the signal handler or the exception handler.
2473 static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2474 {
2475 sigsegv_info_t SI;
2476 SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2477 SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2478 #ifdef HAVE_MACH_EXCEPTIONS
2479 SI.thread = thread;
2480 SI.has_exc_state = false;
2481 SI.has_thr_state = false;
2482 #endif
2483 sigsegv_info_t * const SIP = &SI;
2484
2485 // Call user's handler and reinstall the global handler, if required
2486 switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2487 case SIGSEGV_RETURN_SUCCESS:
2488 return true;
2489
2490 #if HAVE_SIGSEGV_SKIP_INSTRUCTION
2491 case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2492 // Call the instruction skipper with the register file
2493 // available
2494 #ifdef HAVE_MACH_EXCEPTIONS
2495 if (!SIP->has_thr_state)
2496 mach_get_thread_state(SIP);
2497 #endif
2498 if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2499 #ifdef HAVE_MACH_EXCEPTIONS
2500 // Unlike UNIX signals where the thread state
2501 // is modified off of the stack, in Mach we
2502 // need to actually call thread_set_state to
2503 // have the register values updated.
2504 mach_set_thread_state(SIP);
2505 #endif
2506 return true;
2507 }
2508 break;
2509 #endif
2510 case SIGSEGV_RETURN_FAILURE:
2511 // We can't do anything with the fault_address, dump state?
2512 if (sigsegv_state_dumper != 0)
2513 sigsegv_state_dumper(SIP);
2514 break;
2515 }
2516
2517 return false;
2518 }
2519
2520
2521 /*
2522 * There are two mechanisms for handling a bad memory access,
2523 * Mach exceptions and UNIX signals. The implementation specific
2524 * code appears below. Its reponsibility is to call handle_badaccess
2525 * which is the routine that handles the fault in an implementation
2526 * agnostic manner. The implementation specific code below is then
2527 * reponsible for checking whether handle_badaccess was able
2528 * to handle the memory access error and perform any implementation
2529 * specific tasks necessary afterwards.
2530 */
2531
2532 #ifdef HAVE_MACH_EXCEPTIONS
2533 /*
2534 * We need to forward all exceptions that we do not handle.
2535 * This is important, there are many exceptions that may be
2536 * handled by other exception handlers. For example debuggers
2537 * use exceptions and the exception hander is in another
2538 * process in such a case. (Timothy J. Wood states in his
2539 * message to the list that he based this code on that from
2540 * gdb for Darwin.)
2541 */
2542 static inline kern_return_t
2543 forward_exception(mach_port_t thread_port,
2544 mach_port_t task_port,
2545 exception_type_t exception_type,
2546 exception_data_t exception_data,
2547 mach_msg_type_number_t data_count,
2548 ExceptionPorts *oldExceptionPorts)
2549 {
2550 kern_return_t kret;
2551 unsigned int portIndex;
2552 mach_port_t port;
2553 exception_behavior_t behavior;
2554 thread_state_flavor_t flavor;
2555 thread_state_data_t thread_state;
2556 mach_msg_type_number_t thread_state_count;
2557
2558 for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
2559 if (oldExceptionPorts->masks[portIndex] & (1 << exception_type)) {
2560 // This handler wants the exception
2561 break;
2562 }
2563 }
2564
2565 if (portIndex >= oldExceptionPorts->maskCount) {
2566 fprintf(stderr, "No handler for exception_type = %d. Not fowarding\n", exception_type);
2567 return KERN_FAILURE;
2568 }
2569
2570 port = oldExceptionPorts->handlers[portIndex];
2571 behavior = oldExceptionPorts->behaviors[portIndex];
2572 flavor = oldExceptionPorts->flavors[portIndex];
2573
2574 if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2575 fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2576 return KERN_FAILURE;
2577 }
2578
2579 /*
2580 fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2581 */
2582
2583 if (behavior != EXCEPTION_DEFAULT) {
2584 thread_state_count = THREAD_STATE_MAX;
2585 kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2586 &thread_state_count);
2587 MACH_CHECK_ERROR (thread_get_state, kret);
2588 }
2589
2590 switch (behavior) {
2591 case EXCEPTION_DEFAULT:
2592 // fprintf(stderr, "forwarding to exception_raise\n");
2593 kret = exception_raise(port, thread_port, task_port, exception_type,
2594 exception_data, data_count);
2595 MACH_CHECK_ERROR (exception_raise, kret);
2596 break;
2597 case EXCEPTION_STATE:
2598 // fprintf(stderr, "forwarding to exception_raise_state\n");
2599 kret = exception_raise_state(port, exception_type, exception_data,
2600 data_count, &flavor,
2601 (natural_t *)&thread_state, thread_state_count,
2602 (natural_t *)&thread_state, &thread_state_count);
2603 MACH_CHECK_ERROR (exception_raise_state, kret);
2604 break;
2605 case EXCEPTION_STATE_IDENTITY:
2606 // fprintf(stderr, "forwarding to exception_raise_state_identity\n");
2607 kret = exception_raise_state_identity(port, thread_port, task_port,
2608 exception_type, exception_data,
2609 data_count, &flavor,
2610 (natural_t *)&thread_state, thread_state_count,
2611 (natural_t *)&thread_state, &thread_state_count);
2612 MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2613 break;
2614 default:
2615 fprintf(stderr, "forward_exception got unknown behavior\n");
2616 kret = KERN_FAILURE;
2617 break;
2618 }
2619
2620 if (behavior != EXCEPTION_DEFAULT) {
2621 kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2622 thread_state_count);
2623 MACH_CHECK_ERROR (thread_set_state, kret);
2624 }
2625
2626 return kret;
2627 }
2628
2629 /*
2630 * This is the code that actually handles the exception.
2631 * It is called by exc_server. For Darwin 5 Apple changed
2632 * this a bit from how this family of functions worked in
2633 * Mach. If you are familiar with that it is a little
2634 * different. The main variation that concerns us here is
2635 * that code is an array of exception specific codes and
2636 * codeCount is a count of the number of codes in the code
2637 * array. In typical Mach all exceptions have a code
2638 * and sub-code. It happens to be the case that for a
2639 * EXC_BAD_ACCESS exception the first entry is the type of
2640 * bad access that occurred and the second entry is the
2641 * faulting address so these entries correspond exactly to
2642 * how the code and sub-code are used on Mach.
2643 *
2644 * This is a MIG interface. No code in Basilisk II should
2645 * call this directley. This has to have external C
2646 * linkage because that is what exc_server expects.
2647 */
2648 kern_return_t
2649 catch_exception_raise(mach_port_t exception_port,
2650 mach_port_t thread,
2651 mach_port_t task,
2652 exception_type_t exception,
2653 exception_data_t code,
2654 mach_msg_type_number_t code_count)
2655 {
2656 kern_return_t krc;
2657
2658 if (exception == EXC_BAD_ACCESS) {
2659 switch (code[0]) {
2660 case KERN_PROTECTION_FAILURE:
2661 case KERN_INVALID_ADDRESS:
2662 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2663 return KERN_SUCCESS;
2664 break;
2665 }
2666 }
2667
2668 // In Mach we do not need to remove the exception handler.
2669 // If we forward the exception, eventually some exception handler
2670 // will take care of this exception.
2671 krc = forward_exception(thread, task, exception, code, code_count, &ports);
2672
2673 return krc;
2674 }
2675 #endif
2676
2677 #ifdef HAVE_SIGSEGV_RECOVERY
2678 // Handle bad memory accesses with signal handler
2679 static void sigsegv_handler(SIGSEGV_FAULT_HANDLER_ARGLIST)
2680 {
2681 // Call handler and reinstall the global handler, if required
2682 if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS)) {
2683 #if (defined(HAVE_SIGACTION) ? defined(SIGACTION_NEED_REINSTALL) : defined(SIGNAL_NEED_REINSTALL))
2684 sigsegv_do_install_handler(sig);
2685 #endif
2686 return;
2687 }
2688
2689 // Failure: reinstall default handler for "safe" crash
2690 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
2691 SIGSEGV_ALL_SIGNALS
2692 #undef FAULT_HANDLER
2693 }
2694 #endif
2695
2696
2697 /*
2698 * SIGSEGV handler initialization
2699 */
2700
2701 #if defined(HAVE_SIGINFO_T)
2702 static bool sigsegv_do_install_handler(int sig)
2703 {
2704 // Setup SIGSEGV handler to process writes to frame buffer
2705 #ifdef HAVE_SIGACTION
2706 struct sigaction sigsegv_sa;
2707 sigemptyset(&sigsegv_sa.sa_mask);
2708 sigsegv_sa.sa_sigaction = sigsegv_handler;
2709 sigsegv_sa.sa_flags = SA_SIGINFO;
2710 return (sigaction(sig, &sigsegv_sa, 0) == 0);
2711 #else
2712 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
2713 #endif
2714 }
2715 #endif
2716
2717 #if defined(HAVE_SIGCONTEXT_SUBTERFUGE)
2718 static bool sigsegv_do_install_handler(int sig)
2719 {
2720 // Setup SIGSEGV handler to process writes to frame buffer
2721 #ifdef HAVE_SIGACTION
2722 struct sigaction sigsegv_sa;
2723 sigemptyset(&sigsegv_sa.sa_mask);
2724 sigsegv_sa.sa_handler = (signal_handler)sigsegv_handler;
2725 sigsegv_sa.sa_flags = 0;
2726 #if !EMULATED_68K && defined(__NetBSD__)
2727 sigaddset(&sigsegv_sa.sa_mask, SIGALRM);
2728 sigsegv_sa.sa_flags |= SA_ONSTACK;
2729 #endif
2730 return (sigaction(sig, &sigsegv_sa, 0) == 0);
2731 #else
2732 return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR);
2733 #endif
2734 }
2735 #endif
2736
2737 #if defined(HAVE_MACH_EXCEPTIONS)
2738 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
2739 {
2740 /*
2741 * Except for the exception port functions, this should be
2742 * pretty much stock Mach. If later you choose to support
2743 * other Mach's besides Darwin, just check for __MACH__
2744 * here and __APPLE__ where the actual differences are.
2745 */
2746 #if defined(__APPLE__) && defined(__MACH__)
2747 if (sigsegv_fault_handler != NULL) {
2748 sigsegv_fault_handler = handler;
2749 return true;
2750 }
2751
2752 kern_return_t krc;
2753
2754 // create the the exception port
2755 krc = mach_port_allocate(mach_task_self(),
2756 MACH_PORT_RIGHT_RECEIVE, &_exceptionPort);
2757 if (krc != KERN_SUCCESS) {
2758 mach_error("mach_port_allocate", krc);
2759 return false;
2760 }
2761
2762 // add a port send right
2763 krc = mach_port_insert_right(mach_task_self(),
2764 _exceptionPort, _exceptionPort,
2765 MACH_MSG_TYPE_MAKE_SEND);
2766 if (krc != KERN_SUCCESS) {
2767 mach_error("mach_port_insert_right", krc);
2768 return false;
2769 }
2770
2771 // get the old exception ports
2772 ports.maskCount = sizeof (ports.masks) / sizeof (ports.masks[0]);
2773 krc = thread_get_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, ports.masks,
2774 &ports.maskCount, ports.handlers, ports.behaviors, ports.flavors);
2775 if (krc != KERN_SUCCESS) {
2776 mach_error("thread_get_exception_ports", krc);
2777 return false;
2778 }
2779
2780 // set the new exception port
2781 //
2782 // We could have used EXCEPTION_STATE_IDENTITY instead of
2783 // EXCEPTION_DEFAULT to get the thread state in the initial
2784 // message, but it turns out that in the common case this is not
2785 // neccessary. If we need it we can later ask for it from the
2786 // suspended thread.
2787 //
2788 // Even with THREAD_STATE_NONE, Darwin provides the program
2789 // counter in the thread state. The comments in the header file
2790 // seem to imply that you can count on the GPR's on an exception
2791 // as well but just to be safe I use MACHINE_THREAD_STATE because
2792 // you have to ask for all of the GPR's anyway just to get the
2793 // program counter. In any case because of update effective
2794 // address from immediate and update address from effective
2795 // addresses of ra and rb modes (as good an name as any for these
2796 // addressing modes) used in PPC instructions, you will need the
2797 // GPR state anyway.
2798 krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2799 EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2800 if (krc != KERN_SUCCESS) {
2801 mach_error("thread_set_exception_ports", krc);
2802 return false;
2803 }
2804
2805 // create the exception handler thread
2806 if (pthread_create(&exc_thread, NULL, &handleExceptions, NULL) != 0) {
2807 (void)fprintf(stderr, "creation of exception thread failed\n");
2808 return false;
2809 }
2810
2811 // do not care about the exception thread any longer, let is run standalone
2812 (void)pthread_detach(exc_thread);
2813
2814 sigsegv_fault_handler = handler;
2815 return true;
2816 #else
2817 return false;
2818 #endif
2819 }
2820 #endif
2821
2822 #ifdef HAVE_WIN32_EXCEPTIONS
2823 static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo)
2824 {
2825 if (sigsegv_fault_handler != NULL
2826 && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
2827 && ExceptionInfo->ExceptionRecord->NumberParameters == 2
2828 && handle_badaccess(ExceptionInfo))
2829 return EXCEPTION_CONTINUE_EXECUTION;
2830
2831 return EXCEPTION_CONTINUE_SEARCH;
2832 }
2833
2834 #if defined __CYGWIN__ && defined __i386__
2835 /* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
2836 installs a global exception handler. We have to dig deep in order to install
2837 our main_exception_filter. */
2838
2839 /* Data structures for the current thread's exception handler chain.
2840 On the x86 Windows uses register fs, offset 0 to point to the current
2841 exception handler; Cygwin mucks with it, so we must do the same... :-/ */
2842
2843 /* Magic taken from winsup/cygwin/include/exceptions.h. */
2844
2845 struct exception_list {
2846 struct exception_list *prev;
2847 int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
2848 };
2849 typedef struct exception_list exception_list;
2850
2851 /* Magic taken from winsup/cygwin/exceptions.cc. */
2852
2853 __asm__ (".equ __except_list,0");
2854
2855 extern exception_list *_except_list __asm__ ("%fs:__except_list");
2856
2857 /* For debugging. _except_list is not otherwise accessible from gdb. */
2858 static exception_list *
2859 debug_get_except_list ()
2860 {
2861 return _except_list;
2862 }
2863
2864 /* Cygwin's original exception handler. */
2865 static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
2866
2867 /* Our exception handler. */
2868 static int
2869 libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
2870 {
2871 EXCEPTION_POINTERS ExceptionInfo;
2872 ExceptionInfo.ExceptionRecord = exception;
2873 ExceptionInfo.ContextRecord = context;
2874 if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
2875 return cygwin_exception_handler (exception, frame, context, dispatch);
2876 else
2877 return 0;
2878 }
2879
2880 static void
2881 do_install_main_exception_filter ()
2882 {
2883 /* We cannot insert any handler into the chain, because such handlers
2884 must lie on the stack (?). Instead, we have to replace(!) Cygwin's
2885 global exception handler. */
2886 cygwin_exception_handler = _except_list->handler;
2887 _except_list->handler = libsigsegv_exception_handler;
2888 }
2889
2890 #else
2891
2892 static void
2893 do_install_main_exception_filter ()
2894 {
2895 SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
2896 }
2897 #endif
2898
2899 static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
2900 {
2901 static bool main_exception_filter_installed = false;
2902 if (!main_exception_filter_installed) {
2903 do_install_main_exception_filter();
2904 main_exception_filter_installed = true;
2905 }
2906 sigsegv_fault_handler = handler;
2907 return true;
2908 }
2909 #endif
2910
2911 bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
2912 {
2913 #if defined(HAVE_SIGSEGV_RECOVERY)
2914 bool success = true;
2915 #define FAULT_HANDLER(sig) success = success && sigsegv_do_install_handler(sig);
2916 SIGSEGV_ALL_SIGNALS
2917 #undef FAULT_HANDLER
2918 if (success)
2919 sigsegv_fault_handler = handler;
2920 return success;
2921 #elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS)
2922 return sigsegv_do_install_handler(handler);
2923 #else
2924 // FAIL: no siginfo_t nor sigcontext subterfuge is available
2925 return false;
2926 #endif
2927 }
2928
2929
2930 /*
2931 * SIGSEGV handler deinitialization
2932 */
2933
2934 void sigsegv_deinstall_handler(void)
2935 {
2936 // We do nothing for Mach exceptions, the thread would need to be
2937 // suspended if not already so, and we might mess with other
2938 // exception handlers that came after we registered ours. There is
2939 // no need to remove the exception handler, in fact this function is
2940 // not called anywhere in Basilisk II.
2941 #ifdef HAVE_SIGSEGV_RECOVERY
2942 sigsegv_fault_handler = 0;
2943 #define FAULT_HANDLER(sig) signal(sig, SIG_DFL);
2944 SIGSEGV_ALL_SIGNALS
2945 #undef FAULT_HANDLER
2946 #endif
2947 #ifdef HAVE_WIN32_EXCEPTIONS
2948 sigsegv_fault_handler = NULL;
2949 #endif
2950 }
2951
2952
2953 /*
2954 * Set callback function when we cannot handle the fault
2955 */
2956
2957 void sigsegv_set_dump_state(sigsegv_state_dumper_t handler)
2958 {
2959 sigsegv_state_dumper = handler;
2960 }
2961
2962
2963 /*
2964 * Test program used for configure/test
2965 */
2966
2967 #ifdef CONFIGURE_TEST_SIGSEGV_RECOVERY
2968 #include <stdio.h>
2969 #include <stdlib.h>
2970 #include <fcntl.h>
2971 #ifdef HAVE_SYS_MMAN_H
2972 #include <sys/mman.h>
2973 #endif
2974 #include "vm_alloc.h"
2975
2976 const int REF_INDEX = 123;
2977 const int REF_VALUE = 45;
2978
2979 static int page_size;
2980 static volatile char * page = 0;
2981 static volatile int handler_called = 0;
2982
2983 /* Barriers */
2984 #ifdef __GNUC__
2985 #define BARRIER() asm volatile ("" : : : "memory")
2986 #else
2987 #define BARRIER() /* nothing */
2988 #endif
2989
2990 #ifdef __GNUC__
2991 // Code range where we expect the fault to come from
2992 static void *b_region, *e_region;
2993 #endif
2994
2995 static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
2996 {
2997 const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
2998 const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
2999 #if DEBUG
3000 printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3001 printf("expected fault at %p\n", page + REF_INDEX);
3002 #ifdef __GNUC__
3003 printf("expected instruction address range: %p-%p\n", b_region, e_region);
3004 #endif
3005 #endif
3006 handler_called++;
3007 if ((fault_address - REF_INDEX) != page)
3008 exit(10);
3009 #ifdef __GNUC__
3010 // Make sure reported fault instruction address falls into
3011 // expected code range
3012 if (instruction_address != SIGSEGV_INVALID_ADDRESS
3013 && ((instruction_address < (sigsegv_address_t)b_region) ||
3014 (instruction_address >= (sigsegv_address_t)e_region)))
3015 exit(11);
3016 #endif
3017 if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3018 exit(12);
3019 return SIGSEGV_RETURN_SUCCESS;
3020 }
3021
3022 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3023 static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3024 {
3025 const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3026 const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3027 #if DEBUG
3028 printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3029 #endif
3030 if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3031 #ifdef __GNUC__
3032 // Make sure reported fault instruction address falls into
3033 // expected code range
3034 if (instruction_address != SIGSEGV_INVALID_ADDRESS
3035 && ((instruction_address < (sigsegv_address_t)b_region) ||
3036 (instruction_address >= (sigsegv_address_t)e_region)))
3037 return SIGSEGV_RETURN_FAILURE;
3038 #endif
3039 return SIGSEGV_RETURN_SKIP_INSTRUCTION;
3040 }
3041
3042 return SIGSEGV_RETURN_FAILURE;
3043 }
3044
3045 // More sophisticated tests for instruction skipper
3046 static bool arch_insn_skipper_tests()
3047 {
3048 #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3049 static const unsigned char code[] = {
3050 0x8a, 0x00, // mov (%eax),%al
3051 0x8a, 0x2c, 0x18, // mov (%eax,%ebx,1),%ch
3052 0x88, 0x20, // mov %ah,(%eax)
3053 0x88, 0x08, // mov %cl,(%eax)
3054 0x66, 0x8b, 0x00, // mov (%eax),%ax
3055 0x66, 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%cx
3056 0x66, 0x89, 0x00, // mov %ax,(%eax)
3057 0x66, 0x89, 0x0c, 0x18, // mov %cx,(%eax,%ebx,1)
3058 0x8b, 0x00, // mov (%eax),%eax
3059 0x8b, 0x0c, 0x18, // mov (%eax,%ebx,1),%ecx
3060 0x89, 0x00, // mov %eax,(%eax)
3061 0x89, 0x0c, 0x18, // mov %ecx,(%eax,%ebx,1)
3062 #if defined(__x86_64__)
3063 0x44, 0x8a, 0x00, // mov (%rax),%r8b
3064 0x44, 0x8a, 0x20, // mov (%rax),%r12b
3065 0x42, 0x8a, 0x3c, 0x10, // mov (%rax,%r10,1),%dil
3066 0x44, 0x88, 0x00, // mov %r8b,(%rax)
3067 0x44, 0x88, 0x20, // mov %r12b,(%rax)
3068 0x42, 0x88, 0x3c, 0x10, // mov %dil,(%rax,%r10,1)
3069 0x66, 0x44, 0x8b, 0x00, // mov (%rax),%r8w
3070 0x66, 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%cx
3071 0x66, 0x44, 0x89, 0x00, // mov %r8w,(%rax)
3072 0x66, 0x42, 0x89, 0x0c, 0x10, // mov %cx,(%rax,%r10,1)
3073 0x44, 0x8b, 0x00, // mov (%rax),%r8d
3074 0x42, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%ecx
3075 0x44, 0x89, 0x00, // mov %r8d,(%rax)
3076 0x42, 0x89, 0x0c, 0x10, // mov %ecx,(%rax,%r10,1)
3077 0x48, 0x8b, 0x08, // mov (%rax),%rcx
3078 0x4c, 0x8b, 0x18, // mov (%rax),%r11
3079 0x4a, 0x8b, 0x0c, 0x10, // mov (%rax,%r10,1),%rcx
3080 0x4e, 0x8b, 0x1c, 0x10, // mov (%rax,%r10,1),%r11
3081 0x48, 0x89, 0x08, // mov %rcx,(%rax)
3082 0x4c, 0x89, 0x18, // mov %r11,(%rax)
3083 0x4a, 0x89, 0x0c, 0x10, // mov %rcx,(%rax,%r10,1)
3084 0x4e, 0x89, 0x1c, 0x10, // mov %r11,(%rax,%r10,1)
3085 0x63, 0x47, 0x04, // movslq 4(%rdi),%eax
3086 0x48, 0x63, 0x47, 0x04, // movslq 4(%rdi),%rax
3087 #endif
3088 0 // end
3089 };
3090 const int N_REGS = 20;
3091 unsigned long regs[N_REGS];
3092 for (int i = 0; i < N_REGS; i++)
3093 regs[i] = i;
3094 const unsigned long start_code = (unsigned long)&code;
3095 regs[X86_REG_EIP] = start_code;
3096 while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3097 && ix86_skip_instruction(regs))
3098 ; /* simply iterate */
3099 return (regs[X86_REG_EIP] - start_code) == (sizeof(code) - 1);
3100 #endif
3101 return true;
3102 }
3103 #endif
3104
3105 int main(void)
3106 {
3107 if (vm_init() < 0)
3108 return 1;
3109
3110 page_size = vm_get_page_size();
3111 if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3112 return 2;
3113
3114 memset((void *)page, 0, page_size);
3115 if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0)
3116 return 3;
3117
3118 if (!sigsegv_install_handler(sigsegv_test_handler))
3119 return 4;
3120
3121 #ifdef __GNUC__
3122 b_region = &&L_b_region1;
3123 e_region = &&L_e_region1;
3124 #endif
3125 /* This is a really awful hack but otherwise gcc is smart enough
3126 * (or bug'ous enough?) to optimize the labels and place them
3127 * e.g. at the "main" entry point, which is wrong.
3128 */
3129 volatile int label_hack = 1;
3130 switch (label_hack) {
3131 case 1:
3132 L_b_region1:
3133 page[REF_INDEX] = REF_VALUE;
3134 if (page[REF_INDEX] != REF_VALUE)
3135 exit(20);
3136 page[REF_INDEX] = REF_VALUE;
3137 BARRIER();
3138 // fall-through
3139 case 2:
3140 L_e_region1:
3141 BARRIER();
3142 break;
3143 }
3144
3145 if (handler_called != 1)
3146 return 5;
3147
3148 #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3149 if (!sigsegv_install_handler(sigsegv_insn_handler))
3150 return 6;
3151
3152 if (vm_protect((char *)page, page_size, VM_PAGE_READ | VM_PAGE_WRITE) < 0)
3153 return 7;
3154
3155 for (int i = 0; i < page_size; i++)
3156 page[i] = (i + 1) % page_size;
3157
3158 if (vm_protect((char *)page, page_size, VM_PAGE_NOACCESS) < 0)
3159 return 8;
3160
3161 #define TEST_SKIP_INSTRUCTION(TYPE) do { \
3162 const unsigned long TAG = 0x12345678 | \
3163 (sizeof(long) == 8 ? 0x9abcdef0UL << 31 : 0); \
3164 TYPE data = *((TYPE *)(page + sizeof(TYPE))); \
3165 volatile unsigned long effect = data + TAG; \
3166 if (effect != TAG) \
3167 return 9; \
3168 } while (0)
3169
3170 #ifdef __GNUC__
3171 b_region = &&L_b_region2;
3172 e_region = &&L_e_region2;
3173 #endif
3174 switch (label_hack) {
3175 case 1:
3176 L_b_region2:
3177 TEST_SKIP_INSTRUCTION(unsigned char);
3178 TEST_SKIP_INSTRUCTION(unsigned short);
3179 TEST_SKIP_INSTRUCTION(unsigned int);
3180 TEST_SKIP_INSTRUCTION(unsigned long);
3181 TEST_SKIP_INSTRUCTION(signed char);
3182 TEST_SKIP_INSTRUCTION(signed short);
3183 TEST_SKIP_INSTRUCTION(signed int);
3184 TEST_SKIP_INSTRUCTION(signed long);
3185 BARRIER();
3186 // fall-through
3187 case 2:
3188 L_e_region2:
3189 BARRIER();
3190 break;
3191 }
3192 if (!arch_insn_skipper_tests())
3193 return 20;
3194 #endif
3195
3196 vm_exit();
3197 return 0;
3198 }
3199 #endif