ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
Revision: 1.91
Committed: 2010-04-08T03:53:27Z (14 years, 1 month ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.90: +32 -0 lines
Log Message:
[Joel Mauras]
GCC has become too smart - we need to slice the binary created to be sure the
address of the trap is within the test addresses. This is why each trap occurs
between two case labels and a new section of assembly code is set in between.

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