ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.3 by gbeauche, 2001-06-05T12:16:34Z vs.
Revision 1.86 by asvitkine, 2009-02-11T19:23:53Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines