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.42 by gbeauche, 2004-01-19T16:59:13Z vs.
Revision 1.83 by gbeauche, 2008-01-20T00:39:51Z

# Line 10 | Line 10
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-2004 Christian Bauer
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 49 | Line 49 | using std::list;
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  
# Line 66 | Line 77 | static bool sigsegv_do_install_handler(i
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
93 >        SIZE_QUAD  // 8 bytes
94   };
95  
96 < // Transfer type
79 < typedef sigsegv_transfer_type_t transfer_type_t;
80 <
81 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
96 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
97   // Addressing mode
98   enum addressing_mode_t {
99          MODE_UNKNOWN,
# Line 97 | Line 112 | struct instruction_t {
112          char                            ra, rd;
113   };
114  
115 < static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned int * gpr)
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 *)nip);
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;
# Line 174 | Line 189 | static void powerpc_decode_instruction(i
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
# Line 214 | Line 241 | static void powerpc_decode_instruction(i
241  
242   #if HAVE_SIGINFO_T
243   // Generic extended signal handler
244 < #if defined(__NetBSD__) || defined(__FreeBSD__)
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   #endif
# Line 228 | Line 257 | static void powerpc_decode_instruction(i
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
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
# Line 244 | Line 273 | static void powerpc_decode_instruction(i
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 < #if defined(__FreeBSD__)
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                   ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
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                   (unsigned long *)SIGSEGV_CONTEXT_REGS
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                   (unsigned long *)SIGSEGV_CONTEXT_REGS
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_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
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 int *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned int *)(SIGSEGV_CONTEXT_REGS->gpr)
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__))
# Line 285 | Line 340 | static void powerpc_decode_instruction(i
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
# Line 300 | Line 394 | static void powerpc_decode_instruction(i
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                   (unsigned long *)scp
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__))
# Line 315 | Line 409 | static void powerpc_decode_instruction(i
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 int *)&scp->regs->nip, (unsigned int *)(scp->regs->gpr)
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__))
# Line 331 | Line 425 | static void powerpc_decode_instruction(i
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  
# Line 419 | Line 515 | static sigsegv_address_t get_fault_addre
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                   ((unsigned long *)&scp->sc_edi)
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__))
# Line 477 | Line 573 | static sigsegv_address_t get_fault_addre
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 + #if defined(_M_IX86)
582 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
583 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
584 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
585 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
586 + #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_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
592 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
593 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
594 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
595 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Rip
596 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax)
597 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
598 + #endif
599 + #endif
600 +
601   #if HAVE_MACH_EXCEPTIONS
602  
603   // This can easily be extended to other Mach systems, but really who
# Line 537 | Line 658 | if (ret != KERN_SUCCESS) { \
658          exit (1); \
659   }
660  
661 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
662 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
663 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
664 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
665 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
661 > #ifdef __ppc__
662 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE
663 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
664 > #endif
665 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
666 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
667 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
668 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
669 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
670 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
671 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
672 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
673   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
674 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
675 <
676 < // Given a suspended thread, stuff the current instruction and
677 < // registers into state.
678 < //
679 < // It would have been nice to have this be ppc/x86 independant which
680 < // could have been done easily with a thread_state_t instead of
681 < // ppc_thread_state_t, but because of the way this is called it is
682 < // easier to do it this way.
683 < #if (defined(ppc) || defined(__ppc__))
684 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
685 < {
686 <        kern_return_t krc;
687 <        mach_msg_type_number_t count;
688 <
689 <        count = MACHINE_THREAD_STATE_COUNT;
690 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
691 <        MACH_CHECK_ERROR (thread_get_state, krc);
674 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
675 > #endif
676 > #ifdef __ppc64__
677 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE64
678 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
679 > #endif
680 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
681 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
682 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
683 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
684 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
685 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
686 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
687 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
688 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
689 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
690 > #endif
691 > #ifdef __i386__
692 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE32
693 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
694 > #endif
695 > #define SIGSEGV_EXCEPTION_STATE_TYPE    i386_exception_state_t
696 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
697 > #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
698 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
699 > #define SIGSEGV_THREAD_STATE_TYPE               i386_thread_state_t
700 > #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
701 > #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
702 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(eip)
703 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
704 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(eax)) /* EAX is the first GPR we consider */
705 > #endif
706 > #ifdef __x86_64__
707 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE64
708 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
709 > #endif
710 > #define SIGSEGV_EXCEPTION_STATE_TYPE    x86_exception_state64_t
711 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
712 > #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
713 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
714 > #define SIGSEGV_THREAD_STATE_TYPE               x86_thread_state64_t
715 > #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
716 > #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
717 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(rip)
718 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
719 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(rax)) /* RAX is the first GPR we consider */
720 > #endif
721 > #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
722 > #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
723 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
724 > #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
725  
726 <        return (sigsegv_address_t)state->srr0;
727 < }
726 > #ifndef MACH_FIELD_NAME
727 > #define MACH_FIELD_NAME(X) X
728   #endif
729  
730   // Since there can only be one exception thread running at any time
# Line 617 | Line 778 | handleExceptions(void *priv)
778   *  Instruction skipping
779   */
780  
781 + #ifndef SIGSEGV_REGISTER_TYPE
782 + #define SIGSEGV_REGISTER_TYPE sigsegv_uintptr_t
783 + #endif
784 +
785   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
786   // Decode and skip X86 instruction
787 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
787 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
788   #if defined(__linux__)
789   enum {
790   #if (defined(i386) || defined(__i386__))
# Line 654 | Line 819 | enum {
819   #endif
820   };
821   #endif
822 < #if defined(__NetBSD__) || defined(__FreeBSD__)
822 > #if defined(__NetBSD__)
823 > enum {
824 > #if (defined(i386) || defined(__i386__))
825 >        X86_REG_EIP = _REG_EIP,
826 >        X86_REG_EAX = _REG_EAX,
827 >        X86_REG_ECX = _REG_ECX,
828 >        X86_REG_EDX = _REG_EDX,
829 >        X86_REG_EBX = _REG_EBX,
830 >        X86_REG_ESP = _REG_ESP,
831 >        X86_REG_EBP = _REG_EBP,
832 >        X86_REG_ESI = _REG_ESI,
833 >        X86_REG_EDI = _REG_EDI
834 > #endif
835 > };
836 > #endif
837 > #if defined(__FreeBSD__)
838   enum {
839   #if (defined(i386) || defined(__i386__))
840          X86_REG_EIP = 10,
# Line 669 | Line 849 | enum {
849   #endif
850   };
851   #endif
852 + #if defined(__OpenBSD__)
853 + enum {
854 + #if defined(__i386__)
855 +        // EDI is the first register we consider
856 + #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
857 + #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
858 +        X86_REG_EIP = DREG(eip), // 7
859 +        X86_REG_EAX = DREG(eax), // 6
860 +        X86_REG_ECX = DREG(ecx), // 5
861 +        X86_REG_EDX = DREG(edx), // 4
862 +        X86_REG_EBX = DREG(ebx), // 3
863 +        X86_REG_ESP = DREG(esp), // 10
864 +        X86_REG_EBP = DREG(ebp), // 2
865 +        X86_REG_ESI = DREG(esi), // 1
866 +        X86_REG_EDI = DREG(edi)  // 0
867 + #undef DREG
868 + #undef OREG
869 + #endif
870 + };
871 + #endif
872 + #if defined(__sun__)
873 + // Same as for Linux, need to check for x86-64
874 + enum {
875 + #if defined(__i386__)
876 +        X86_REG_EIP = EIP,
877 +        X86_REG_EAX = EAX,
878 +        X86_REG_ECX = ECX,
879 +        X86_REG_EDX = EDX,
880 +        X86_REG_EBX = EBX,
881 +        X86_REG_ESP = ESP,
882 +        X86_REG_EBP = EBP,
883 +        X86_REG_ESI = ESI,
884 +        X86_REG_EDI = EDI
885 + #endif
886 + };
887 + #endif
888 + #if defined(__APPLE__) && defined(__MACH__)
889 + enum {
890 + #if (defined(i386) || defined(__i386__))
891 + #ifdef i386_SAVED_STATE
892 +        // same as FreeBSD (in Open Darwin 8.0.1)
893 +        X86_REG_EIP = 10,
894 +        X86_REG_EAX = 7,
895 +        X86_REG_ECX = 6,
896 +        X86_REG_EDX = 5,
897 +        X86_REG_EBX = 4,
898 +        X86_REG_ESP = 13,
899 +        X86_REG_EBP = 2,
900 +        X86_REG_ESI = 1,
901 +        X86_REG_EDI = 0
902 + #else
903 +        // new layout (MacOS X 10.4.4 for x86)
904 +        X86_REG_EIP = 10,
905 +        X86_REG_EAX = 0,
906 +        X86_REG_ECX = 2,
907 +        X86_REG_EDX = 3,
908 +        X86_REG_EBX = 1,
909 +        X86_REG_ESP = 7,
910 +        X86_REG_EBP = 6,
911 +        X86_REG_ESI = 5,
912 +        X86_REG_EDI = 4
913 + #endif
914 + #endif
915 + #if defined(__x86_64__)
916 +        X86_REG_R8  = 8,
917 +        X86_REG_R9  = 9,
918 +        X86_REG_R10 = 10,
919 +        X86_REG_R11 = 11,
920 +        X86_REG_R12 = 12,
921 +        X86_REG_R13 = 13,
922 +        X86_REG_R14 = 14,
923 +        X86_REG_R15 = 15,
924 +        X86_REG_EDI = 4,
925 +        X86_REG_ESI = 5,
926 +        X86_REG_EBP = 6,
927 +        X86_REG_EBX = 1,
928 +        X86_REG_EDX = 3,
929 +        X86_REG_EAX = 0,
930 +        X86_REG_ECX = 2,
931 +        X86_REG_ESP = 7,
932 +        X86_REG_EIP = 16
933 + #endif
934 + };
935 + #endif
936 + #if defined(_WIN32)
937 + enum {
938 + #if defined(_M_IX86)
939 +        X86_REG_EIP = 7,
940 +        X86_REG_EAX = 5,
941 +        X86_REG_ECX = 4,
942 +        X86_REG_EDX = 3,
943 +        X86_REG_EBX = 2,
944 +        X86_REG_ESP = 10,
945 +        X86_REG_EBP = 6,
946 +        X86_REG_ESI = 1,
947 +        X86_REG_EDI = 0
948 + #endif
949 + #if defined(_M_X64)
950 +        X86_REG_EAX = 0,
951 +        X86_REG_ECX = 1,
952 +        X86_REG_EDX = 2,
953 +        X86_REG_EBX = 3,
954 +        X86_REG_ESP = 4,
955 +        X86_REG_EBP = 5,
956 +        X86_REG_ESI = 6,
957 +        X86_REG_EDI = 7,
958 +        X86_REG_R8  = 8,
959 +        X86_REG_R9  = 9,
960 +        X86_REG_R10 = 10,
961 +        X86_REG_R11 = 11,
962 +        X86_REG_R12 = 12,
963 +        X86_REG_R13 = 13,
964 +        X86_REG_R14 = 14,
965 +        X86_REG_R15 = 15,
966 +        X86_REG_EIP = 16
967 + #endif
968 + };
969 + #endif
970   // FIXME: this is partly redundant with the instruction decoding phase
971   // to discover transfer type and register number
972   static inline int ix86_step_over_modrm(unsigned char * p)
# Line 703 | Line 1001 | static inline int ix86_step_over_modrm(u
1001          return offset;
1002   }
1003  
1004 < static bool ix86_skip_instruction(unsigned long * regs)
1004 > static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs)
1005   {
1006          unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
1007  
1008          if (eip == 0)
1009                  return false;
1010 + #ifdef _WIN32
1011 +        if (IsBadCodePtr((FARPROC)eip))
1012 +                return false;
1013 + #endif
1014          
1015 +        enum instruction_type_t {
1016 +                i_MOV,
1017 +                i_ADD
1018 +        };
1019 +
1020          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1021          transfer_size_t transfer_size = SIZE_LONG;
1022 +        instruction_type_t instruction_type = i_MOV;
1023          
1024          int reg = -1;
1025          int len = 0;
# Line 729 | Line 1037 | static bool ix86_skip_instruction(unsign
1037          }
1038  
1039          // REX prefix
1040 < #if defined(__x86_64__)
1040 > #if defined(__x86_64__) || defined(_M_X64)
1041          struct rex_t {
1042                  unsigned char W;
1043                  unsigned char R;
# Line 762 | Line 1070 | static bool ix86_skip_instruction(unsign
1070   #endif
1071  
1072          // Decode instruction
1073 +        int op_len = 1;
1074 +        int target_size = SIZE_UNKNOWN;
1075          switch (eip[0]) {
1076          case 0x0f:
1077 +                target_size = transfer_size;
1078              switch (eip[1]) {
1079 +                case 0xbe: // MOVSX r32, r/m8
1080              case 0xb6: // MOVZX r32, r/m8
1081 +                        transfer_size = SIZE_BYTE;
1082 +                        goto do_mov_extend;
1083 +                case 0xbf: // MOVSX r32, r/m16
1084              case 0xb7: // MOVZX r32, r/m16
1085 <                switch (eip[2] & 0xc0) {
1086 <                case 0x80:
1087 <                    reg = (eip[2] >> 3) & 7;
1088 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
1089 <                    break;
775 <                case 0x40:
776 <                    reg = (eip[2] >> 3) & 7;
777 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
778 <                    break;
779 <                case 0x00:
780 <                    reg = (eip[2] >> 3) & 7;
781 <                    transfer_type = SIGSEGV_TRANSFER_LOAD;
782 <                    break;
1085 >                        transfer_size = SIZE_WORD;
1086 >                        goto do_mov_extend;
1087 >                  do_mov_extend:
1088 >                        op_len = 2;
1089 >                        goto do_transfer_load;
1090                  }
784                len += 3 + ix86_step_over_modrm(eip + 2);
1091                  break;
1092 <            }
1093 <          break;
1092 > #if defined(__x86_64__) || defined(_M_X64)
1093 >        case 0x63: // MOVSXD r64, r/m32
1094 >                if (has_rex && rex.W) {
1095 >                        transfer_size = SIZE_LONG;
1096 >                        target_size = SIZE_QUAD;
1097 >                }
1098 >                else if (transfer_size != SIZE_WORD) {
1099 >                        transfer_size = SIZE_LONG;
1100 >                        target_size = SIZE_QUAD;
1101 >                }
1102 >                goto do_transfer_load;
1103 > #endif
1104 >        case 0x02: // ADD r8, r/m8
1105 >                transfer_size = SIZE_BYTE;
1106 >        case 0x03: // ADD r32, r/m32
1107 >                instruction_type = i_ADD;
1108 >                goto do_transfer_load;
1109          case 0x8a: // MOV r8, r/m8
1110                  transfer_size = SIZE_BYTE;
1111          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1112 <                switch (eip[1] & 0xc0) {
1112 >          do_transfer_load:
1113 >                switch (eip[op_len] & 0xc0) {
1114                  case 0x80:
1115 <                        reg = (eip[1] >> 3) & 7;
1115 >                        reg = (eip[op_len] >> 3) & 7;
1116                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1117                          break;
1118                  case 0x40:
1119 <                        reg = (eip[1] >> 3) & 7;
1119 >                        reg = (eip[op_len] >> 3) & 7;
1120                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1121                          break;
1122                  case 0x00:
1123 <                        reg = (eip[1] >> 3) & 7;
1123 >                        reg = (eip[op_len] >> 3) & 7;
1124                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1125                          break;
1126                  }
1127 <                len += 2 + ix86_step_over_modrm(eip + 1);
1127 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1128                  break;
1129 +        case 0x00: // ADD r/m8, r8
1130 +                transfer_size = SIZE_BYTE;
1131 +        case 0x01: // ADD r/m32, r32
1132 +                instruction_type = i_ADD;
1133 +                goto do_transfer_store;
1134          case 0x88: // MOV r/m8, r8
1135                  transfer_size = SIZE_BYTE;
1136          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1137 <                switch (eip[1] & 0xc0) {
1137 >          do_transfer_store:
1138 >                switch (eip[op_len] & 0xc0) {
1139                  case 0x80:
1140 <                        reg = (eip[1] >> 3) & 7;
1140 >                        reg = (eip[op_len] >> 3) & 7;
1141                          transfer_type = SIGSEGV_TRANSFER_STORE;
1142                          break;
1143                  case 0x40:
1144 <                        reg = (eip[1] >> 3) & 7;
1144 >                        reg = (eip[op_len] >> 3) & 7;
1145                          transfer_type = SIGSEGV_TRANSFER_STORE;
1146                          break;
1147                  case 0x00:
1148 <                        reg = (eip[1] >> 3) & 7;
1148 >                        reg = (eip[op_len] >> 3) & 7;
1149                          transfer_type = SIGSEGV_TRANSFER_STORE;
1150                          break;
1151                  }
1152 <                len += 2 + ix86_step_over_modrm(eip + 1);
1152 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1153                  break;
1154          }
1155 +        if (target_size == SIZE_UNKNOWN)
1156 +                target_size = transfer_size;
1157  
1158          if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1159                  // Unknown machine code, let it crash. Then patch the decoder
1160                  return false;
1161          }
1162  
1163 < #if defined(__x86_64__)
1163 > #if defined(__x86_64__) || defined(_M_X64)
1164          if (rex.R)
1165                  reg += 8;
1166   #endif
1167  
1168 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1168 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1169                  static const int x86_reg_map[] = {
1170                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1171                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1172 < #if defined(__x86_64__)
1172 > #if defined(__x86_64__) || defined(_M_X64)
1173                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1174                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1175   #endif
# Line 851 | Line 1181 | static bool ix86_skip_instruction(unsign
1181                  // Set 0 to the relevant register part
1182                  // NOTE: this is only valid for MOV alike instructions
1183                  int rloc = x86_reg_map[reg];
1184 <                switch (transfer_size) {
1184 >                switch (target_size) {
1185                  case SIZE_BYTE:
1186                          if (has_rex || reg < 4)
1187                                  regs[rloc] = (regs[rloc] & ~0x00ffL);
# Line 871 | Line 1201 | static bool ix86_skip_instruction(unsign
1201          }
1202  
1203   #if DEBUG
1204 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1204 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1205                     transfer_size == SIZE_BYTE ? "byte" :
1206                     transfer_size == SIZE_WORD ? "word" :
1207                     transfer_size == SIZE_LONG ? "long" :
# Line 905 | Line 1235 | static bool ix86_skip_instruction(unsign
1235                          "r12", "r13", "r14", "r15",
1236                  };
1237                  const char * reg_str = NULL;
1238 <                switch (transfer_size) {
1238 >                switch (target_size) {
1239                  case SIZE_BYTE:
1240                          reg_str = x86_byte_reg_str_map[(!has_rex && reg >= 4 ? 12 : 0) + reg];
1241                          break;
# Line 926 | Line 1256 | static bool ix86_skip_instruction(unsign
1256   }
1257   #endif
1258  
1259 + // Decode and skip IA-64 instruction
1260 + #if defined(__ia64) || defined(__ia64__)
1261 + typedef uint64_t ia64_bundle_t[2];
1262 + #if defined(__linux__)
1263 + // We can directly patch the slot number
1264 + #define IA64_CAN_PATCH_IP_SLOT  1
1265 + // Helper macros to access the machine context
1266 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1267 + #define IA64_CONTEXT                    scp
1268 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1269 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1270 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1271 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1272 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1273 + #define _IA64_SET_GR(R,V)               (IA64_CONTEXT->sc_gr[(R)] = (V))
1274 + #define _IA64_SET_NAT(I,V)              (IA64_CONTEXT->sc_nat = (IA64_CONTEXT->sc_nat & ~(1ull << (I))) | (((uint64_t)!!(V)) << (I)))
1275 + #define IA64_SET_GR(R,V,N)              (_IA64_SET_GR(R,V), _IA64_SET_NAT(R,N))
1276 +
1277 + // Load bundle (in little-endian)
1278 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1279 + {
1280 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1281 +        bundle[0] = ip[0];
1282 +        bundle[1] = ip[1];
1283 + }
1284 + #endif
1285 + #if defined(__hpux) || defined(__hpux__)
1286 + // We can directly patch the slot number
1287 + #define IA64_CAN_PATCH_IP_SLOT  1
1288 + // Helper macros to access the machine context
1289 + #define IA64_CONTEXT_TYPE               ucontext_t *
1290 + #define IA64_CONTEXT                    ucp
1291 + #define IA64_GET_IP()                   ia64_get_ip(IA64_CONTEXT)
1292 + #define IA64_SET_IP(V)                  ia64_set_ip(IA64_CONTEXT, V)
1293 + #define IA64_GET_PR(P)                  ia64_get_pr(IA64_CONTEXT, P)
1294 + #define IA64_GET_NAT(I)                 ia64_get_nat(IA64_CONTEXT, I)
1295 + #define IA64_GET_GR(R)                  ia64_get_gr(IA64_CONTEXT, R)
1296 + #define IA64_SET_GR(R,V,N)              ia64_set_gr(IA64_CONTEXT, R, V, N)
1297 + #define UC_ACCESS(FUNC,ARGS)    do { if (__uc_##FUNC ARGS != 0) abort(); } while (0)
1298 +
1299 + static inline uint64_t ia64_get_ip(IA64_CONTEXT_TYPE IA64_CONTEXT)
1300 +        { uint64_t v; UC_ACCESS(get_ip,(IA64_CONTEXT, &v)); return v; }
1301 + static inline void ia64_set_ip(IA64_CONTEXT_TYPE IA64_CONTEXT, uint64_t v)
1302 +        { UC_ACCESS(set_ip,(IA64_CONTEXT, v)); }
1303 + static inline unsigned int ia64_get_pr(IA64_CONTEXT_TYPE IA64_CONTEXT, int pr)
1304 +        { uint64_t v; UC_ACCESS(get_prs,(IA64_CONTEXT, &v)); return (v >> pr) & 1; }
1305 + static inline unsigned int ia64_get_nat(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1306 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return (nat >> r) & 1; }
1307 + static inline uint64_t ia64_get_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1308 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return v; }
1309 +
1310 + static void ia64_set_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r, uint64_t v, unsigned int nat)
1311 + {
1312 +        if (r == 0)
1313 +                return;
1314 +        if (r > 0 && r < 32)
1315 +                UC_ACCESS(set_grs,(IA64_CONTEXT, r, 1, &v, (!!nat) << r));
1316 +        else {
1317 +                uint64_t bsp, bspstore;
1318 +                UC_ACCESS(get_ar_bsp,(IA64_CONTEXT, &bsp));
1319 +                UC_ACCESS(get_ar_bspstore,(IA64_CONTEXT, &bspstore));
1320 +                abort(); /* XXX: use libunwind, this is not fun... */
1321 +        }
1322 + }
1323 +
1324 + // Byte-swapping
1325 + #if defined(__GNUC__)
1326 + #define BSWAP64(V) ({ uint64_t r; __asm__ __volatile__("mux1 %0=%1,@rev;;" : "=r" (r) : "r" (V)); r; })
1327 + #elif defined (__HP_aCC)
1328 + #define BSWAP64(V) _Asm_mux1(_MBTYPE_REV, V)
1329 + #else
1330 + #error "Define byte-swap instruction"
1331 + #endif
1332 +
1333 + // Load bundle (in little-endian)
1334 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1335 + {
1336 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1337 +        bundle[0] = BSWAP64(ip[0]);
1338 +        bundle[1] = BSWAP64(ip[1]);
1339 + }
1340 + #endif
1341 +
1342 + // Instruction operations
1343 + enum {
1344 +        IA64_INST_UNKNOWN = 0,
1345 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1346 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1347 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1348 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1349 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1350 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1351 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1352 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1353 +        IA64_INST_ST1,                          // st1 [op0]=op1
1354 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1355 +        IA64_INST_ST2,                          // st2 [op0]=op1
1356 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1357 +        IA64_INST_ST4,                          // st4 [op0]=op1
1358 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1359 +        IA64_INST_ST8,                          // st8 [op0]=op1
1360 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1361 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1362 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1363 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1364 +        IA64_INST_AND,                          // and op0=op1,op2
1365 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1366 +        IA64_INST_OR,                           // or op0=op1,op2
1367 +        IA64_INST_XOR,                          // xor op0=op1,op2
1368 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1369 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1370 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1371 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1372 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1373 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1374 +        IA64_INST_NOP                           // nop op0
1375 + };
1376 +
1377 + const int IA64_N_OPERANDS = 4;
1378 +
1379 + // Decoded operand type
1380 + struct ia64_operand_t {
1381 +        uint8_t commit;                         // commit result of operation to register file?
1382 +        uint8_t valid;                          // XXX: not really used, can be removed (debug)
1383 +        int8_t index;                           // index of GPR, or -1 if immediate value
1384 +        uint8_t nat;                            // NaT state before operation
1385 +        uint64_t value;                         // register contents or immediate value
1386 + };
1387 +
1388 + // Decoded instruction type
1389 + struct ia64_instruction_t {
1390 +        uint8_t mnemo;                          // operation to perform
1391 +        uint8_t pred;                           // predicate register to check
1392 +        uint8_t no_memory;                      // used to emulated main fault instruction
1393 +        uint64_t inst;                          // the raw instruction bits (41-bit wide)
1394 +        ia64_operand_t operands[IA64_N_OPERANDS];
1395 + };
1396 +
1397 + // Get immediate sign-bit
1398 + static inline int ia64_inst_get_sbit(uint64_t inst)
1399 + {
1400 +        return (inst >> 36) & 1;
1401 + }
1402 +
1403 + // Get 8-bit immediate value (A3, A8, I27, M30)
1404 + static inline uint64_t ia64_inst_get_imm8(uint64_t inst)
1405 + {
1406 +        uint64_t value = (inst >> 13) & 0x7full;
1407 +        if (ia64_inst_get_sbit(inst))
1408 +                value |= ~0x7full;
1409 +        return value;
1410 + }
1411 +
1412 + // Get 9-bit immediate value (M3)
1413 + static inline uint64_t ia64_inst_get_imm9b(uint64_t inst)
1414 + {
1415 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1416 +        if (ia64_inst_get_sbit(inst))
1417 +                value |= ~0xffull;
1418 +        return value;
1419 + }
1420 +
1421 + // Get 9-bit immediate value (M5)
1422 + static inline uint64_t ia64_inst_get_imm9a(uint64_t inst)
1423 + {
1424 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1425 +        if (ia64_inst_get_sbit(inst))
1426 +                value |= ~0xffull;
1427 +        return value;
1428 + }
1429 +
1430 + // Get 14-bit immediate value (A4)
1431 + static inline uint64_t ia64_inst_get_imm14(uint64_t inst)
1432 + {
1433 +        uint64_t value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1434 +        if (ia64_inst_get_sbit(inst))
1435 +                value |= ~0x1ffull;
1436 +        return value;
1437 + }
1438 +
1439 + // Get 22-bit immediate value (A5)
1440 + static inline uint64_t ia64_inst_get_imm22(uint64_t inst)
1441 + {
1442 +        uint64_t value = ((((inst >> 22) & 0x1f) << 16) |
1443 +                                          (((inst >> 27) & 0x1ff) << 7) |
1444 +                                          (inst & 0x7f));
1445 +        if (ia64_inst_get_sbit(inst))
1446 +                value |= ~0x1fffffull;
1447 +        return value;
1448 + }
1449 +
1450 + // Get 21-bit immediate value (I19)
1451 + static inline uint64_t ia64_inst_get_imm21(uint64_t inst)
1452 + {
1453 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1454 + }
1455 +
1456 + // Get 2-bit count value (A2)
1457 + static inline int ia64_inst_get_count2(uint64_t inst)
1458 + {
1459 +        return (inst >> 27) & 0x3;
1460 + }
1461 +
1462 + // Get bundle template
1463 + static inline unsigned int ia64_get_template(uint64_t ip)
1464 + {
1465 +        ia64_bundle_t bundle;
1466 +        ia64_load_bundle(bundle, ip);
1467 +        return bundle[0] & 0x1f;
1468 + }
1469 +
1470 + // Get specified instruction in bundle
1471 + static uint64_t ia64_get_instruction(uint64_t ip, int slot)
1472 + {
1473 +        uint64_t inst;
1474 +        ia64_bundle_t bundle;
1475 +        ia64_load_bundle(bundle, ip);
1476 + #if DEBUG
1477 +        printf("Bundle: %016llx%016llx\n", bundle[1], bundle[0]);
1478 + #endif
1479 +
1480 +        switch (slot) {
1481 +        case 0:
1482 +                inst = (bundle[0] >> 5) & 0x1ffffffffffull;
1483 +                break;
1484 +        case 1:
1485 +                inst = ((bundle[1] & 0x7fffffull) << 18) | ((bundle[0] >> 46) & 0x3ffffull);
1486 +                break;
1487 +        case 2:
1488 +                inst = (bundle[1] >> 23) & 0x1ffffffffffull;
1489 +                break;
1490 +        case 3:
1491 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1492 +                abort();
1493 +                break;
1494 +        }
1495 +
1496 + #if DEBUG
1497 +        printf(" Instruction %d: 0x%016llx\n", slot, inst);
1498 + #endif
1499 +        return inst;
1500 + }
1501 +
1502 + // Decode group 0 instructions
1503 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1504 + {
1505 +        const int r1 = (inst->inst >>  6) & 0x7f;
1506 +        const int r3 = (inst->inst >> 20) & 0x7f;
1507 +
1508 +        const int x3 = (inst->inst >> 33) & 0x07;
1509 +        const int x6 = (inst->inst >> 27) & 0x3f;
1510 +        const int x2 = (inst->inst >> 31) & 0x03;
1511 +        const int x4 = (inst->inst >> 27) & 0x0f;
1512 +
1513 +        if (x3 == 0) {
1514 +                switch (x6) {
1515 +                case 0x01:                                              // nop.i (I19)
1516 +                        inst->mnemo = IA64_INST_NOP;
1517 +                        inst->operands[0].valid = true;
1518 +                        inst->operands[0].index = -1;
1519 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1520 +                        return true;
1521 +                case 0x14:                                              // sxt1 (I29)
1522 +                case 0x15:                                              // sxt2 (I29)
1523 +                case 0x16:                                              // sxt4 (I29)
1524 +                case 0x10:                                              // zxt1 (I29)
1525 +                case 0x11:                                              // zxt2 (I29)
1526 +                case 0x12:                                              // zxt4 (I29)
1527 +                        switch (x6) {
1528 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1529 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1530 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1531 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1532 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1533 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1534 +                        default: abort();
1535 +                        }
1536 +                        inst->operands[0].valid = true;
1537 +                        inst->operands[0].index = r1;
1538 +                        inst->operands[1].valid = true;
1539 +                        inst->operands[1].index = r3;
1540 +                        inst->operands[1].value = IA64_GET_GR(r3);
1541 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1542 +                        return true;
1543 +                }
1544 +        }
1545 +        return false;
1546 + }
1547 +
1548 + // Decode group 4 instructions (load/store instructions)
1549 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1550 + {
1551 +        const int r1 = (inst->inst >> 6) & 0x7f;
1552 +        const int r2 = (inst->inst >> 13) & 0x7f;
1553 +        const int r3 = (inst->inst >> 20) & 0x7f;
1554 +
1555 +        const int m  = (inst->inst >> 36) & 1;
1556 +        const int x  = (inst->inst >> 27) & 1;
1557 +        const int x6 = (inst->inst >> 30) & 0x3f;
1558 +
1559 +        switch (x6) {
1560 +        case 0x00:
1561 +        case 0x01:
1562 +        case 0x02:
1563 +        case 0x03:
1564 +                if (x == 0) {
1565 +                        inst->operands[0].valid = true;
1566 +                        inst->operands[0].index = r1;
1567 +                        inst->operands[1].valid = true;
1568 +                        inst->operands[1].index = r3;
1569 +                        inst->operands[1].value = IA64_GET_GR(r3);
1570 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1571 +                        if (m == 0) {
1572 +                                switch (x6) {
1573 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1574 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1575 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1576 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1577 +                                }
1578 +                        }
1579 +                        else {
1580 +                                inst->operands[2].valid = true;
1581 +                                inst->operands[2].index = r2;
1582 +                                inst->operands[2].value = IA64_GET_GR(r2);
1583 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1584 +                                switch (x6) {
1585 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1586 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1587 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1588 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1589 +                                }
1590 +                        }
1591 +                        return true;
1592 +                }
1593 +                break;
1594 +        case 0x30:
1595 +        case 0x31:
1596 +        case 0x32:
1597 +        case 0x33:
1598 +                if (m == 0 && x == 0) {
1599 +                        inst->operands[0].valid = true;
1600 +                        inst->operands[0].index = r3;
1601 +                        inst->operands[0].value = IA64_GET_GR(r3);
1602 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1603 +                        inst->operands[1].valid = true;
1604 +                        inst->operands[1].index = r2;
1605 +                        inst->operands[1].value = IA64_GET_GR(r2);
1606 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1607 +                        switch (x6) {
1608 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1609 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1610 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1611 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1612 +                        }
1613 +                        return true;
1614 +                }
1615 +                break;
1616 +        }
1617 +        return false;
1618 + }
1619 +
1620 + // Decode group 5 instructions (load/store instructions)
1621 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1622 + {
1623 +        const int r1 = (inst->inst >> 6) & 0x7f;
1624 +        const int r2 = (inst->inst >> 13) & 0x7f;
1625 +        const int r3 = (inst->inst >> 20) & 0x7f;
1626 +
1627 +        const int x6 = (inst->inst >> 30) & 0x3f;
1628 +
1629 +        switch (x6) {
1630 +        case 0x00:
1631 +        case 0x01:
1632 +        case 0x02:
1633 +        case 0x03:
1634 +                inst->operands[0].valid = true;
1635 +                inst->operands[0].index = r1;
1636 +                inst->operands[1].valid = true;
1637 +                inst->operands[1].index = r3;
1638 +                inst->operands[1].value = IA64_GET_GR(r3);
1639 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1640 +                inst->operands[2].valid = true;
1641 +                inst->operands[2].index = -1;
1642 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1643 +                inst->operands[2].nat   = 0;
1644 +                switch (x6) {
1645 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1646 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1647 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1648 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1649 +                }
1650 +                return true;
1651 +        case 0x30:
1652 +        case 0x31:
1653 +        case 0x32:
1654 +        case 0x33:
1655 +                inst->operands[0].valid = true;
1656 +                inst->operands[0].index = r3;
1657 +                inst->operands[0].value = IA64_GET_GR(r3);
1658 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1659 +                inst->operands[1].valid = true;
1660 +                inst->operands[1].index = r2;
1661 +                inst->operands[1].value = IA64_GET_GR(r2);
1662 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1663 +                inst->operands[2].valid = true;
1664 +                inst->operands[2].index = -1;
1665 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1666 +                inst->operands[2].nat   = 0;
1667 +                switch (x6) {
1668 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1669 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1670 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1671 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1672 +                }
1673 +                return true;
1674 +        }
1675 +        return false;
1676 + }
1677 +
1678 + // Decode group 8 instructions (ALU integer)
1679 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1680 + {
1681 +        const int r1  = (inst->inst >> 6) & 0x7f;
1682 +        const int r2  = (inst->inst >> 13) & 0x7f;
1683 +        const int r3  = (inst->inst >> 20) & 0x7f;
1684 +
1685 +        const int x2a = (inst->inst >> 34) & 0x3;
1686 +        const int x2b = (inst->inst >> 27) & 0x3;
1687 +        const int x4  = (inst->inst >> 29) & 0xf;
1688 +        const int ve  = (inst->inst >> 33) & 0x1;
1689 +
1690 +        // destination register (r1) is always valid in this group
1691 +        inst->operands[0].valid = true;
1692 +        inst->operands[0].index = r1;
1693 +
1694 +        // source register (r3) is always valid in this group
1695 +        inst->operands[2].valid = true;
1696 +        inst->operands[2].index = r3;
1697 +        inst->operands[2].value = IA64_GET_GR(r3);
1698 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1699 +
1700 +        if (x2a == 0 && ve == 0) {
1701 +                inst->operands[1].valid = true;
1702 +                inst->operands[1].index = r2;
1703 +                inst->operands[1].value = IA64_GET_GR(r2);
1704 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1705 +                switch (x4) {
1706 +                case 0x0:                               // add (A1)
1707 +                        inst->mnemo = IA64_INST_ADD;
1708 +                        inst->operands[3].valid = true;
1709 +                        inst->operands[3].index = -1;
1710 +                        inst->operands[3].value = x2b == 1;
1711 +                        return true;
1712 +                case 0x1:                               // add (A1)
1713 +                        inst->mnemo = IA64_INST_SUB;
1714 +                        inst->operands[3].valid = true;
1715 +                        inst->operands[3].index = -1;
1716 +                        inst->operands[3].value = x2b == 0;
1717 +                        return true;
1718 +                case 0x4:                               // shladd (A2)
1719 +                        inst->mnemo = IA64_INST_SHLADD;
1720 +                        inst->operands[3].valid = true;
1721 +                        inst->operands[3].index = -1;
1722 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1723 +                        return true;
1724 +                case 0x9:
1725 +                        if (x2b == 1) {
1726 +                                inst->mnemo = IA64_INST_SUB;
1727 +                                inst->operands[1].index = -1;
1728 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1729 +                                inst->operands[1].nat   = 0;
1730 +                                return true;
1731 +                        }
1732 +                        break;
1733 +                case 0xb:
1734 +                        inst->operands[1].index = -1;
1735 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1736 +                        inst->operands[1].nat   = 0;
1737 +                        // fall-through
1738 +                case 0x3:
1739 +                        switch (x2b) {
1740 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1741 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1742 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1743 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1744 +                        }
1745 +                        return true;
1746 +                }
1747 +        }
1748 +        return false;
1749 + }
1750 +
1751 + // Decode instruction
1752 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1753 + {
1754 +        const int major = (inst->inst >> 37) & 0xf;
1755 +
1756 +        inst->mnemo = IA64_INST_UNKNOWN;
1757 +        inst->pred  = inst->inst & 0x3f;
1758 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1759 +
1760 +        switch (major) {
1761 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1762 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1763 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1764 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1765 +        }
1766 +        return false;
1767 + }
1768 +
1769 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1770 + {
1771 +        // XXX: handle Register NaT Consumption fault?
1772 +        // XXX: this simple emulator assumes instructions in a bundle
1773 +        // don't depend on effects of other instructions in the same
1774 +        // bundle. It probably would be simpler to JIT-generate code to be
1775 +        // executed natively but probably more costly (inject/extract CPU state)
1776 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1777 +                return false;
1778 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1779 +                return true;
1780 +
1781 +        uint8_t nat, nat2;
1782 +        uint64_t dst, dst2, src1, src2, src3;
1783 +
1784 +        switch (inst->mnemo) {
1785 +        case IA64_INST_NOP:
1786 +                break;
1787 +        case IA64_INST_ADD:
1788 +        case IA64_INST_SUB:
1789 +        case IA64_INST_SHLADD:
1790 +                src3 = inst->operands[3].value;
1791 +                // fall-through
1792 +        case IA64_INST_AND:
1793 +        case IA64_INST_ANDCM:
1794 +        case IA64_INST_OR:
1795 +        case IA64_INST_XOR:
1796 +                src1 = inst->operands[1].value;
1797 +                src2 = inst->operands[2].value;
1798 +                switch (inst->mnemo) {
1799 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1800 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1801 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1802 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1803 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1804 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1805 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1806 +                }
1807 +                inst->operands[0].commit = true;
1808 +                inst->operands[0].value  = dst;
1809 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1810 +                break;
1811 +        case IA64_INST_SXT1:
1812 +        case IA64_INST_SXT2:
1813 +        case IA64_INST_SXT4:
1814 +        case IA64_INST_ZXT1:
1815 +        case IA64_INST_ZXT2:
1816 +        case IA64_INST_ZXT4:
1817 +                src1 = inst->operands[1].value;
1818 +                switch (inst->mnemo) {
1819 +                case IA64_INST_SXT1: dst = (int64_t)(int8_t)src1;               break;
1820 +                case IA64_INST_SXT2: dst = (int64_t)(int16_t)src1;              break;
1821 +                case IA64_INST_SXT4: dst = (int64_t)(int32_t)src1;              break;
1822 +                case IA64_INST_ZXT1: dst = (uint8_t)src1;                               break;
1823 +                case IA64_INST_ZXT2: dst = (uint16_t)src1;                              break;
1824 +                case IA64_INST_ZXT4: dst = (uint32_t)src1;                              break;
1825 +                }
1826 +                inst->operands[0].commit = true;
1827 +                inst->operands[0].value  = dst;
1828 +                inst->operands[0].nat    = inst->operands[1].nat;
1829 +                break;
1830 +        case IA64_INST_LD1_UPDATE:
1831 +        case IA64_INST_LD2_UPDATE:
1832 +        case IA64_INST_LD4_UPDATE:
1833 +        case IA64_INST_LD8_UPDATE:
1834 +                inst->operands[1].commit = true;
1835 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1836 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1837 +                // fall-through
1838 +        case IA64_INST_LD1:
1839 +        case IA64_INST_LD2:
1840 +        case IA64_INST_LD4:
1841 +        case IA64_INST_LD8:
1842 +                src1 = inst->operands[1].value;
1843 +                if (inst->no_memory)
1844 +                        dst = 0;
1845 +                else {
1846 +                        switch (inst->mnemo) {
1847 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((uint8_t *)src1);        break;
1848 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((uint16_t *)src1);       break;
1849 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((uint32_t *)src1);       break;
1850 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((uint64_t *)src1);       break;
1851 +                        }
1852 +                }
1853 +                inst->operands[0].commit = true;
1854 +                inst->operands[0].value  = dst;
1855 +                inst->operands[0].nat    = 0;
1856 +                inst->operands[1].value  = dst2;
1857 +                inst->operands[1].nat    = nat2;
1858 +                break;
1859 +        case IA64_INST_ST1_UPDATE:
1860 +        case IA64_INST_ST2_UPDATE:
1861 +        case IA64_INST_ST4_UPDATE:
1862 +        case IA64_INST_ST8_UPDATE:
1863 +                inst->operands[0].commit = 0;
1864 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1865 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1866 +                // fall-through
1867 +        case IA64_INST_ST1:
1868 +        case IA64_INST_ST2:
1869 +        case IA64_INST_ST4:
1870 +        case IA64_INST_ST8:
1871 +                dst  = inst->operands[0].value;
1872 +                src1 = inst->operands[1].value;
1873 +                if (!inst->no_memory) {
1874 +                        switch (inst->mnemo) {
1875 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((uint8_t *)dst) = src1;        break;
1876 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((uint16_t *)dst) = src1;       break;
1877 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((uint32_t *)dst) = src1;       break;
1878 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((uint64_t *)dst) = src1;       break;
1879 +                        }
1880 +                }
1881 +                inst->operands[0].value  = dst2;
1882 +                inst->operands[0].nat    = nat2;
1883 +                break;
1884 +        default:
1885 +                return false;
1886 +        }
1887 +
1888 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1889 +                ia64_operand_t const & op = inst->operands[i];
1890 +                if (!op.commit)
1891 +                        continue;
1892 +                if (op.index == -1)
1893 +                        return false; // XXX: internal error
1894 +                IA64_SET_GR(op.index, op.value, op.nat);
1895 +        }
1896 +        return true;
1897 + }
1898 +
1899 + static bool ia64_emulate_instruction(uint64_t raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1900 + {
1901 +        ia64_instruction_t inst;
1902 +        memset(&inst, 0, sizeof(inst));
1903 +        inst.inst = raw_inst;
1904 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1905 +                return false;
1906 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1907 + }
1908 +
1909 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1910 + {
1911 +        uint64_t ip = IA64_GET_IP();
1912 + #if DEBUG
1913 +        printf("IP: 0x%016llx\n", ip);
1914 + #if 0
1915 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1916 +        ia64_get_instruction(ip, 0);
1917 +        ia64_get_instruction(ip, 1);
1918 +        ia64_get_instruction(ip, 2);
1919 + #endif
1920 + #endif
1921 +
1922 +        // Select which decode switch to use
1923 +        ia64_instruction_t inst;
1924 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1925 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1926 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1927 +                return false;
1928 +        }
1929 +
1930 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1931 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1932 +
1933 +        switch (inst.mnemo) {
1934 +        case IA64_INST_LD1:
1935 +        case IA64_INST_LD2:
1936 +        case IA64_INST_LD4:
1937 +        case IA64_INST_LD8:
1938 +        case IA64_INST_LD1_UPDATE:
1939 +        case IA64_INST_LD2_UPDATE:
1940 +        case IA64_INST_LD4_UPDATE:
1941 +        case IA64_INST_LD8_UPDATE:
1942 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1943 +                break;
1944 +        case IA64_INST_ST1:
1945 +        case IA64_INST_ST2:
1946 +        case IA64_INST_ST4:
1947 +        case IA64_INST_ST8:
1948 +        case IA64_INST_ST1_UPDATE:
1949 +        case IA64_INST_ST2_UPDATE:
1950 +        case IA64_INST_ST4_UPDATE:
1951 +        case IA64_INST_ST8_UPDATE:
1952 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1953 +                break;
1954 +        }
1955 +
1956 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1957 +                // Unknown machine code, let it crash. Then patch the decoder
1958 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1959 +                return false;
1960 +        }
1961 +
1962 +        switch (inst.mnemo) {
1963 +        case IA64_INST_LD1:
1964 +        case IA64_INST_LD1_UPDATE:
1965 +        case IA64_INST_ST1:
1966 +        case IA64_INST_ST1_UPDATE:
1967 +                transfer_size = SIZE_BYTE;
1968 +                break;
1969 +        case IA64_INST_LD2:
1970 +        case IA64_INST_LD2_UPDATE:
1971 +        case IA64_INST_ST2:
1972 +        case IA64_INST_ST2_UPDATE:
1973 +                transfer_size = SIZE_WORD;
1974 +                break;
1975 +        case IA64_INST_LD4:
1976 +        case IA64_INST_LD4_UPDATE:
1977 +        case IA64_INST_ST4:
1978 +        case IA64_INST_ST4_UPDATE:
1979 +                transfer_size = SIZE_LONG;
1980 +                break;
1981 +        case IA64_INST_LD8:
1982 +        case IA64_INST_LD8_UPDATE:
1983 +        case IA64_INST_ST8:
1984 +        case IA64_INST_ST8_UPDATE:
1985 +                transfer_size = SIZE_QUAD;
1986 +                break;
1987 +        }
1988 +
1989 +        if (transfer_size == SIZE_UNKNOWN) {
1990 +                // Unknown machine code, let it crash. Then patch the decoder
1991 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1992 +                return false;
1993 +        }
1994 +
1995 +        inst.no_memory = true;
1996 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1997 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1998 +                return false;
1999 +        }
2000 +
2001 +        int slot = ip & 3;
2002 +        bool emulate_next = false;
2003 +        switch (slot) {
2004 +        case 0:
2005 +                switch (ia64_get_template(ip)) {
2006 +                case 0x2: // MI;I
2007 +                case 0x3: // MI;I;
2008 +                        emulate_next = true;
2009 +                        slot = 2;
2010 +                        break;
2011 +                case 0xa: // M;MI
2012 +                case 0xb: // M;MI;
2013 +                        emulate_next = true;
2014 +                        slot = 1;
2015 +                        break;
2016 +                }
2017 +                break;
2018 +        }
2019 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
2020 +                while (slot < 3) {
2021 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
2022 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
2023 +                                return false;
2024 +                        }
2025 +                        ++slot;
2026 +                }
2027 +        }
2028 +
2029 + #if IA64_CAN_PATCH_IP_SLOT
2030 +        if ((slot = ip & 3) < 2)
2031 +                IA64_SET_IP((ip & ~3ull) + (slot + 1));
2032 +        else
2033 + #endif
2034 +                IA64_SET_IP((ip & ~3ull) + 16);
2035 + #if DEBUG
2036 +        printf("IP: 0x%016llx\n", IA64_GET_IP());
2037 + #endif
2038 +        return true;
2039 + }
2040 + #endif
2041 +
2042   // Decode and skip PPC instruction
2043 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
2044 < static bool powerpc_skip_instruction(unsigned int * nip_p, unsigned int * regs)
2043 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
2044 > static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
2045   {
2046          instruction_t instr;
2047          powerpc_decode_instruction(&instr, *nip_p, regs);
# Line 940 | Line 2053 | static bool powerpc_skip_instruction(uns
2053  
2054   #if DEBUG
2055          printf("%08x: %s %s access", *nip_p,
2056 <                   instr.transfer_size == SIZE_BYTE ? "byte" : instr.transfer_size == SIZE_WORD ? "word" : "long",
2056 >                   instr.transfer_size == SIZE_BYTE ? "byte" :
2057 >                   instr.transfer_size == SIZE_WORD ? "word" :
2058 >                   instr.transfer_size == SIZE_LONG ? "long" : "quad",
2059                     instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
2060          
2061          if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
# Line 961 | Line 2076 | static bool powerpc_skip_instruction(uns
2076  
2077   // Decode and skip MIPS instruction
2078   #if (defined(mips) || defined(__mips))
2079 < enum {
965 < #if (defined(sgi) || defined(__sgi))
966 <  MIPS_REG_EPC = 35,
967 < #endif
968 < };
969 < static bool mips_skip_instruction(greg_t * regs)
2079 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
2080   {
2081 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
2081 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
2082  
2083    if (epc == 0)
2084          return false;
# Line 1117 | Line 2227 | static bool mips_skip_instruction(greg_t
2227                   mips_gpr_names[reg]);
2228   #endif
2229  
2230 <  regs[MIPS_REG_EPC] += 4;
2230 >  *pc_p += 4;
2231    return true;
2232   }
2233   #endif
# Line 1129 | Line 2239 | enum {
2239    SPARC_REG_G1 = REG_G1,
2240    SPARC_REG_O0 = REG_O0,
2241    SPARC_REG_PC = REG_PC,
2242 +  SPARC_REG_nPC = REG_nPC
2243   #endif
2244   };
2245   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1192 | Line 2303 | static bool sparc_skip_instruction(unsig
2303          break;
2304    case 7: // Store Doubleword
2305          transfer_type = SIGSEGV_TRANSFER_STORE;
2306 <        transfer_size = SIZE_WORD;
2306 >        transfer_size = SIZE_LONG;
2307          register_pair = true;
2308          break;
2309    }
# Line 1202 | Line 2313 | static bool sparc_skip_instruction(unsig
2313          return false;
2314    }
2315  
1205  // Zero target register in case of a load operation
2316    const int reg = (opcode >> 25) & 0x1f;
2317 +
2318 + #if DEBUG
2319 +  static const char * reg_names[] = {
2320 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2321 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2322 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2323 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2324 +  };
2325 +  printf("%s %s register %s\n",
2326 +                 transfer_size == SIZE_BYTE ? "byte" :
2327 +                 transfer_size == SIZE_WORD ? "word" :
2328 +                 transfer_size == SIZE_LONG ? "long" :
2329 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2330 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2331 +                 reg_names[reg]);
2332 + #endif
2333 +
2334 +  // Zero target register in case of a load operation
2335    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2336          // FIXME: code to handle local & input registers is not tested
2337 <        if (reg >= 1 && reg <= 7) {
2337 >        if (reg >= 1 && reg < 8) {
2338            // global registers
2339            regs[reg - 1 + SPARC_REG_G1] = 0;
2340          }
2341 <        else if (reg >= 8 && reg <= 15) {
2341 >        else if (reg >= 8 && reg < 16) {
2342            // output registers
2343            regs[reg - 8 + SPARC_REG_O0] = 0;
2344          }
2345 <        else if (reg >= 16 && reg <= 23) {
2345 >        else if (reg >= 16 && reg < 24) {
2346            // local registers (in register windows)
2347            if (gwins)
2348                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1230 | Line 2358 | static bool sparc_skip_instruction(unsig
2358          }
2359    }
2360  
2361 +  regs[SPARC_REG_PC] += 4;
2362 +  regs[SPARC_REG_nPC] += 4;
2363 +  return true;
2364 + }
2365 + #endif
2366 + #endif
2367 +
2368 + // Decode and skip ARM instruction
2369 + #if (defined(arm) || defined(__arm__))
2370 + enum {
2371 + #if (defined(__linux__))
2372 +  ARM_REG_PC = 15,
2373 +  ARM_REG_CPSR = 16
2374 + #endif
2375 + };
2376 + static bool arm_skip_instruction(unsigned long * regs)
2377 + {
2378 +  unsigned int * pc = (unsigned int *)regs[ARM_REG_PC];
2379 +
2380 +  if (pc == 0)
2381 +        return false;
2382 +
2383 + #if DEBUG
2384 +  printf("IP: %p [%08x]\n", pc, pc[0]);
2385 + #endif
2386 +
2387 +  transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
2388 +  transfer_size_t transfer_size = SIZE_UNKNOWN;
2389 +  enum { op_sdt = 1, op_sdth = 2 };
2390 +  int op = 0;
2391 +
2392 +  // Handle load/store instructions only
2393 +  const unsigned int opcode = pc[0];
2394 +  switch ((opcode >> 25) & 7) {
2395 +  case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH)
2396 +        op = op_sdth;
2397 +        // Determine transfer size (S/H bits)
2398 +        switch ((opcode >> 5) & 3) {
2399 +        case 0: // SWP instruction
2400 +          break;
2401 +        case 1: // Unsigned halfwords
2402 +        case 3: // Signed halfwords
2403 +          transfer_size = SIZE_WORD;
2404 +          break;
2405 +        case 2: // Signed byte
2406 +          transfer_size = SIZE_BYTE;
2407 +          break;
2408 +        }
2409 +        break;
2410 +  case 2:
2411 +  case 3: // Single Data Transfer (LDR, STR)
2412 +        op = op_sdt;
2413 +        // Determine transfer size (B bit)
2414 +        if (((opcode >> 22) & 1) == 1)
2415 +          transfer_size = SIZE_BYTE;
2416 +        else
2417 +          transfer_size = SIZE_LONG;
2418 +        break;
2419 +  default:
2420 +        // FIXME: support load/store mutliple?
2421 +        return false;
2422 +  }
2423 +
2424 +  // Check for invalid transfer size (SWP instruction?)
2425 +  if (transfer_size == SIZE_UNKNOWN)
2426 +        return false;
2427 +
2428 +  // Determine transfer type (L bit)
2429 +  if (((opcode >> 20) & 1) == 1)
2430 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
2431 +  else
2432 +        transfer_type = SIGSEGV_TRANSFER_STORE;
2433 +
2434 +  // Compute offset
2435 +  int offset;
2436 +  if (((opcode >> 25) & 1) == 0) {
2437 +        if (op == op_sdt)
2438 +          offset = opcode & 0xfff;
2439 +        else if (op == op_sdth) {
2440 +          int rm = opcode & 0xf;
2441 +          if (((opcode >> 22) & 1) == 0) {
2442 +                // register offset
2443 +                offset = regs[rm];
2444 +          }
2445 +          else {
2446 +                // immediate offset
2447 +                offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f);
2448 +          }
2449 +        }
2450 +  }
2451 +  else {
2452 +        const int rm = opcode & 0xf;
2453 +        const int sh = (opcode >> 7) & 0x1f;
2454 +        if (((opcode >> 4) & 1) == 1) {
2455 +          // we expect only legal load/store instructions
2456 +          printf("FATAL: invalid shift operand\n");
2457 +          return false;
2458 +        }
2459 +        const unsigned int v = regs[rm];
2460 +        switch ((opcode >> 5) & 3) {
2461 +        case 0: // logical shift left
2462 +          offset = sh ? v << sh : v;
2463 +          break;
2464 +        case 1: // logical shift right
2465 +          offset = sh ? v >> sh : 0;
2466 +          break;
2467 +        case 2: // arithmetic shift right
2468 +          if (sh)
2469 +                offset = ((signed int)v) >> sh;
2470 +          else
2471 +                offset = (v & 0x80000000) ? 0xffffffff : 0;
2472 +          break;
2473 +        case 3: // rotate right
2474 +          if (sh)
2475 +                offset = (v >> sh) | (v << (32 - sh));
2476 +          else
2477 +                offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000);
2478 +          break;
2479 +        }
2480 +  }
2481 +  if (((opcode >> 23) & 1) == 0)
2482 +        offset = -offset;
2483 +
2484 +  int rd = (opcode >> 12) & 0xf;
2485 +  int rn = (opcode >> 16) & 0xf;
2486   #if DEBUG
2487    static const char * reg_names[] = {
2488 <        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2489 <        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1237 <        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1238 <        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2488 >        "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2489 >        "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc"
2490    };
2491    printf("%s %s register %s\n",
2492                   transfer_size == SIZE_BYTE ? "byte" :
2493                   transfer_size == SIZE_WORD ? "word" :
2494 <                 transfer_size == SIZE_LONG ? "long" :
1244 <                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2494 >                 transfer_size == SIZE_LONG ? "long" : "unknown",
2495                   transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2496 <                 reg_names[reg]);
2496 >                 reg_names[rd]);
2497   #endif
2498  
2499 <  regs[SPARC_REG_PC] += 4;
2499 >  unsigned int base = regs[rn];
2500 >  if (((opcode >> 24) & 1) == 1)
2501 >        base += offset;
2502 >
2503 >  if (transfer_type == SIGSEGV_TRANSFER_LOAD)
2504 >        regs[rd] = 0;
2505 >
2506 >  if (((opcode >> 24) & 1) == 0)                // post-index addressing
2507 >        regs[rn] += offset;
2508 >  else if (((opcode >> 21) & 1) == 1)   // write-back address into base
2509 >        regs[rn] = base;
2510 >
2511 >  regs[ARM_REG_PC] += 4;
2512    return true;
2513   }
2514   #endif
2515 < #endif
2515 >
2516  
2517   // Fallbacks
2518 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2519 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2520 + #endif
2521 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2522 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2523 + #endif
2524   #ifndef SIGSEGV_FAULT_INSTRUCTION
2525 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2525 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2526   #endif
2527   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2528   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2529   #endif
2530   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2531 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2531 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2532   #endif
2533  
2534   // SIGSEGV recovery supported ?
# Line 1273 | Line 2541 | static bool sparc_skip_instruction(unsig
2541   *  SIGSEGV global handler
2542   */
2543  
2544 < #if defined(HAVE_SIGSEGV_RECOVERY) || defined(HAVE_MACH_EXCEPTIONS)
2544 > struct sigsegv_info_t {
2545 >        sigsegv_address_t addr;
2546 >        sigsegv_address_t pc;
2547 > #ifdef HAVE_MACH_EXCEPTIONS
2548 >        mach_port_t thread;
2549 >        bool has_exc_state;
2550 >        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2551 >        mach_msg_type_number_t exc_state_count;
2552 >        bool has_thr_state;
2553 >        SIGSEGV_THREAD_STATE_TYPE thr_state;
2554 >        mach_msg_type_number_t thr_state_count;
2555 > #endif
2556 > };
2557 >
2558 > #ifdef HAVE_MACH_EXCEPTIONS
2559 > static void mach_get_exception_state(sigsegv_info_t *SIP)
2560 > {
2561 >        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2562 >        kern_return_t krc = thread_get_state(SIP->thread,
2563 >                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2564 >                                                                                 (natural_t *)&SIP->exc_state,
2565 >                                                                                 &SIP->exc_state_count);
2566 >        MACH_CHECK_ERROR(thread_get_state, krc);
2567 >        SIP->has_exc_state = true;
2568 > }
2569 >
2570 > static void mach_get_thread_state(sigsegv_info_t *SIP)
2571 > {
2572 >        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2573 >        kern_return_t krc = thread_get_state(SIP->thread,
2574 >                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2575 >                                                                                 (natural_t *)&SIP->thr_state,
2576 >                                                                                 &SIP->thr_state_count);
2577 >        MACH_CHECK_ERROR(thread_get_state, krc);
2578 >        SIP->has_thr_state = true;
2579 > }
2580 >
2581 > static void mach_set_thread_state(sigsegv_info_t *SIP)
2582 > {
2583 >        kern_return_t krc = thread_set_state(SIP->thread,
2584 >                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2585 >                                                                                 (natural_t *)&SIP->thr_state,
2586 >                                                                                 SIP->thr_state_count);
2587 >        MACH_CHECK_ERROR(thread_set_state, krc);
2588 > }
2589 > #endif
2590 >
2591 > // Return the address of the invalid memory reference
2592 > sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2593 > {
2594 > #ifdef HAVE_MACH_EXCEPTIONS
2595 >        static int use_fast_path = -1;
2596 >        if (use_fast_path != 1 && !SIP->has_exc_state) {
2597 >                mach_get_exception_state(SIP);
2598 >
2599 >                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2600 >                if (use_fast_path < 0) {
2601 >                        const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2602 >                        if (machfault) {
2603 >                                if (strcmp(machfault, "fast") == 0)
2604 >                                        use_fast_path = 1;
2605 >                                else if (strcmp(machfault, "slow") == 0)
2606 >                                        use_fast_path = 0;
2607 >                        }
2608 >                        if (use_fast_path < 0)
2609 >                                use_fast_path = addr == SIP->addr;
2610 >                }
2611 >                SIP->addr = addr;
2612 >        }
2613 > #endif
2614 >        return SIP->addr;
2615 > }
2616 >
2617 > // Return the address of the instruction that caused the fault, or
2618 > // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2619 > sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2620 > {
2621 > #ifdef HAVE_MACH_EXCEPTIONS
2622 >        if (!SIP->has_thr_state) {
2623 >                mach_get_thread_state(SIP);
2624 >
2625 >                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2626 >        }
2627 > #endif
2628 >        return SIP->pc;
2629 > }
2630 >
2631   // This function handles the badaccess to memory.
2632   // It is called from the signal handler or the exception handler.
2633   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2634   {
2635 <        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2636 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2637 <        
2635 >        sigsegv_info_t SI;
2636 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2637 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2638 > #ifdef HAVE_MACH_EXCEPTIONS
2639 >        SI.thread = thread;
2640 >        SI.has_exc_state = false;
2641 >        SI.has_thr_state = false;
2642 > #endif
2643 >        sigsegv_info_t * const SIP = &SI;
2644 >
2645          // Call user's handler and reinstall the global handler, if required
2646 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2646 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2647          case SIGSEGV_RETURN_SUCCESS:
2648                  return true;
2649  
# Line 1290 | Line 2651 | static bool handle_badaccess(SIGSEGV_FAU
2651          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2652                  // Call the instruction skipper with the register file
2653                  // available
2654 + #ifdef HAVE_MACH_EXCEPTIONS
2655 +                if (!SIP->has_thr_state)
2656 +                        mach_get_thread_state(SIP);
2657 + #endif
2658                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2659   #ifdef HAVE_MACH_EXCEPTIONS
2660                          // Unlike UNIX signals where the thread state
2661                          // is modified off of the stack, in Mach we
2662                          // need to actually call thread_set_state to
2663                          // have the register values updated.
2664 <                        kern_return_t krc;
1300 <
1301 <                        krc = thread_set_state(thread,
1302 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1303 <                                                                   MACHINE_THREAD_STATE_COUNT);
1304 <                        MACH_CHECK_ERROR (thread_get_state, krc);
2664 >                        mach_set_thread_state(SIP);
2665   #endif
2666                          return true;
2667                  }
2668                  break;
2669   #endif
2670 +        case SIGSEGV_RETURN_FAILURE:
2671 +                // We can't do anything with the fault_address, dump state?
2672 +                if (sigsegv_state_dumper != 0)
2673 +                        sigsegv_state_dumper(SIP);
2674 +                break;
2675          }
1311        
1312        // We can't do anything with the fault_address, dump state?
1313        if (sigsegv_state_dumper != 0)
1314                sigsegv_state_dumper(fault_address, fault_instruction);
2676  
2677          return false;
2678   }
1318 #endif
2679  
2680  
2681   /*
# Line 1352 | Line 2712 | forward_exception(mach_port_t thread_por
2712          mach_port_t port;
2713          exception_behavior_t behavior;
2714          thread_state_flavor_t flavor;
2715 <        thread_state_t thread_state;
2715 >        thread_state_data_t thread_state;
2716          mach_msg_type_number_t thread_state_count;
2717  
2718          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1371 | Line 2731 | forward_exception(mach_port_t thread_por
2731          behavior = oldExceptionPorts->behaviors[portIndex];
2732          flavor = oldExceptionPorts->flavors[portIndex];
2733  
2734 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2735 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2736 +                return KERN_FAILURE;
2737 +        }
2738 +
2739          /*
2740           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2741           */
2742  
2743          if (behavior != EXCEPTION_DEFAULT) {
2744                  thread_state_count = THREAD_STATE_MAX;
2745 <                kret = thread_get_state (thread_port, flavor, thread_state,
2745 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2746                                                                   &thread_state_count);
2747                  MACH_CHECK_ERROR (thread_get_state, kret);
2748          }
# Line 1393 | Line 2758 | forward_exception(mach_port_t thread_por
2758            // fprintf(stderr, "forwarding to exception_raise_state\n");
2759            kret = exception_raise_state(port, exception_type, exception_data,
2760                                                                     data_count, &flavor,
2761 <                                                                   thread_state, thread_state_count,
2762 <                                                                   thread_state, &thread_state_count);
2761 >                                                                   (natural_t *)&thread_state, thread_state_count,
2762 >                                                                   (natural_t *)&thread_state, &thread_state_count);
2763            MACH_CHECK_ERROR (exception_raise_state, kret);
2764            break;
2765          case EXCEPTION_STATE_IDENTITY:
# Line 1402 | Line 2767 | forward_exception(mach_port_t thread_por
2767            kret = exception_raise_state_identity(port, thread_port, task_port,
2768                                                                                          exception_type, exception_data,
2769                                                                                          data_count, &flavor,
2770 <                                                                                        thread_state, thread_state_count,
2771 <                                                                                        thread_state, &thread_state_count);
2770 >                                                                                        (natural_t *)&thread_state, thread_state_count,
2771 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
2772            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2773            break;
2774          default:
2775            fprintf(stderr, "forward_exception got unknown behavior\n");
2776 +          kret = KERN_FAILURE;
2777            break;
2778          }
2779  
2780          if (behavior != EXCEPTION_DEFAULT) {
2781 <                kret = thread_set_state (thread_port, flavor, thread_state,
2781 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2782                                                                   thread_state_count);
2783                  MACH_CHECK_ERROR (thread_set_state, kret);
2784          }
2785  
2786 <        return KERN_SUCCESS;
2786 >        return kret;
2787   }
2788  
2789   /*
# Line 1445 | Line 2811 | catch_exception_raise(mach_port_t except
2811                                            mach_port_t task,
2812                                            exception_type_t exception,
2813                                            exception_data_t code,
2814 <                                          mach_msg_type_number_t codeCount)
2814 >                                          mach_msg_type_number_t code_count)
2815   {
1450        ppc_thread_state_t state;
2816          kern_return_t krc;
2817  
2818 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2819 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2820 <                        return KERN_SUCCESS;
2818 >        if (exception == EXC_BAD_ACCESS) {
2819 >                switch (code[0]) {
2820 >                case KERN_PROTECTION_FAILURE:
2821 >                case KERN_INVALID_ADDRESS:
2822 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2823 >                                return KERN_SUCCESS;
2824 >                        break;
2825 >                }
2826          }
2827  
2828          // In Mach we do not need to remove the exception handler.
2829          // If we forward the exception, eventually some exception handler
2830          // will take care of this exception.
2831 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2831 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2832  
2833          return krc;
2834   }
# Line 1586 | Line 2956 | static bool sigsegv_do_install_handler(s
2956          // addressing modes) used in PPC instructions, you will need the
2957          // GPR state anyway.
2958          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2959 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2959 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2960          if (krc != KERN_SUCCESS) {
2961                  mach_error("thread_set_exception_ports", krc);
2962                  return false;
# Line 1609 | Line 2979 | static bool sigsegv_do_install_handler(s
2979   }
2980   #endif
2981  
2982 + #ifdef HAVE_WIN32_EXCEPTIONS
2983 + static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo)
2984 + {
2985 +        if (sigsegv_fault_handler != NULL
2986 +                && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
2987 +                && ExceptionInfo->ExceptionRecord->NumberParameters == 2
2988 +                && handle_badaccess(ExceptionInfo))
2989 +                return EXCEPTION_CONTINUE_EXECUTION;
2990 +
2991 +        return EXCEPTION_CONTINUE_SEARCH;
2992 + }
2993 +
2994 + #if defined __CYGWIN__ && defined __i386__
2995 + /* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
2996 +   installs a global exception handler.  We have to dig deep in order to install
2997 +   our main_exception_filter.  */
2998 +
2999 + /* Data structures for the current thread's exception handler chain.
3000 +   On the x86 Windows uses register fs, offset 0 to point to the current
3001 +   exception handler; Cygwin mucks with it, so we must do the same... :-/ */
3002 +
3003 + /* Magic taken from winsup/cygwin/include/exceptions.h.  */
3004 +
3005 + struct exception_list {
3006 +    struct exception_list *prev;
3007 +    int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
3008 + };
3009 + typedef struct exception_list exception_list;
3010 +
3011 + /* Magic taken from winsup/cygwin/exceptions.cc.  */
3012 +
3013 + __asm__ (".equ __except_list,0");
3014 +
3015 + extern exception_list *_except_list __asm__ ("%fs:__except_list");
3016 +
3017 + /* For debugging.  _except_list is not otherwise accessible from gdb.  */
3018 + static exception_list *
3019 + debug_get_except_list ()
3020 + {
3021 +  return _except_list;
3022 + }
3023 +
3024 + /* Cygwin's original exception handler.  */
3025 + static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
3026 +
3027 + /* Our exception handler.  */
3028 + static int
3029 + libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
3030 + {
3031 +  EXCEPTION_POINTERS ExceptionInfo;
3032 +  ExceptionInfo.ExceptionRecord = exception;
3033 +  ExceptionInfo.ContextRecord = context;
3034 +  if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
3035 +    return cygwin_exception_handler (exception, frame, context, dispatch);
3036 +  else
3037 +    return 0;
3038 + }
3039 +
3040 + static void
3041 + do_install_main_exception_filter ()
3042 + {
3043 +  /* We cannot insert any handler into the chain, because such handlers
3044 +     must lie on the stack (?).  Instead, we have to replace(!) Cygwin's
3045 +     global exception handler.  */
3046 +  cygwin_exception_handler = _except_list->handler;
3047 +  _except_list->handler = libsigsegv_exception_handler;
3048 + }
3049 +
3050 + #else
3051 +
3052 + static void
3053 + do_install_main_exception_filter ()
3054 + {
3055 +  SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
3056 + }
3057 + #endif
3058 +
3059 + static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
3060 + {
3061 +        static bool main_exception_filter_installed = false;
3062 +        if (!main_exception_filter_installed) {
3063 +                do_install_main_exception_filter();
3064 +                main_exception_filter_installed = true;
3065 +        }
3066 +        sigsegv_fault_handler = handler;
3067 +        return true;
3068 + }
3069 + #endif
3070 +
3071   bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
3072   {
3073   #if defined(HAVE_SIGSEGV_RECOVERY)
# Line 1619 | Line 3078 | bool sigsegv_install_handler(sigsegv_fau
3078          if (success)
3079              sigsegv_fault_handler = handler;
3080          return success;
3081 < #elif defined(HAVE_MACH_EXCEPTIONS)
3081 > #elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS)
3082          return sigsegv_do_install_handler(handler);
3083   #else
3084          // FAIL: no siginfo_t nor sigcontext subterfuge is available
# Line 1645 | Line 3104 | void sigsegv_deinstall_handler(void)
3104          SIGSEGV_ALL_SIGNALS
3105   #undef FAULT_HANDLER
3106   #endif
3107 + #ifdef HAVE_WIN32_EXCEPTIONS
3108 +        sigsegv_fault_handler = NULL;
3109 + #endif
3110   }
3111  
3112  
# Line 1666 | Line 3128 | void sigsegv_set_dump_state(sigsegv_stat
3128   #include <stdio.h>
3129   #include <stdlib.h>
3130   #include <fcntl.h>
3131 + #ifdef HAVE_SYS_MMAN_H
3132   #include <sys/mman.h>
3133 + #endif
3134   #include "vm_alloc.h"
3135  
3136   const int REF_INDEX = 123;
3137   const int REF_VALUE = 45;
3138  
3139 < static int page_size;
3139 > static sigsegv_uintptr_t page_size;
3140   static volatile char * page = 0;
3141   static volatile int handler_called = 0;
3142  
3143 + /* Barriers */
3144 + #ifdef __GNUC__
3145 + #define BARRIER() asm volatile ("" : : : "memory")
3146 + #else
3147 + #define BARRIER() /* nothing */
3148 + #endif
3149 +
3150   #ifdef __GNUC__
3151   // Code range where we expect the fault to come from
3152   static void *b_region, *e_region;
3153   #endif
3154  
3155 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3155 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3156   {
3157 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3158 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3159   #if DEBUG
3160          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3161          printf("expected fault at %p\n", page + REF_INDEX);
# Line 1696 | Line 3169 | static sigsegv_return_t sigsegv_test_han
3169   #ifdef __GNUC__
3170          // Make sure reported fault instruction address falls into
3171          // expected code range
3172 <        if (instruction_address != SIGSEGV_INVALID_PC
3172 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3173                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3174                          (instruction_address >= (sigsegv_address_t)e_region)))
3175                  exit(11);
3176   #endif
3177 <        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3177 >        if (vm_protect((char *)((sigsegv_uintptr_t)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3178                  exit(12);
3179          return SIGSEGV_RETURN_SUCCESS;
3180   }
3181  
3182   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3183 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3183 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3184   {
3185 <        if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3185 >        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3186 >        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3187 > #if DEBUG
3188 >        printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3189 > #endif
3190 >        if (((sigsegv_uintptr_t)fault_address - (sigsegv_uintptr_t)page) < page_size) {
3191   #ifdef __GNUC__
3192                  // Make sure reported fault instruction address falls into
3193                  // expected code range
3194 <                if (instruction_address != SIGSEGV_INVALID_PC
3194 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3195                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3196                                  (instruction_address >= (sigsegv_address_t)e_region)))
3197                          return SIGSEGV_RETURN_FAILURE;
# Line 1727 | Line 3205 | static sigsegv_return_t sigsegv_insn_han
3205   // More sophisticated tests for instruction skipper
3206   static bool arch_insn_skipper_tests()
3207   {
3208 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3208 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
3209          static const unsigned char code[] = {
3210                  0x8a, 0x00,                    // mov    (%eax),%al
3211                  0x8a, 0x2c, 0x18,              // mov    (%eax,%ebx,1),%ch
# Line 1741 | Line 3219 | static bool arch_insn_skipper_tests()
3219                  0x8b, 0x0c, 0x18,              // mov    (%eax,%ebx,1),%ecx
3220                  0x89, 0x00,                    // mov    %eax,(%eax)
3221                  0x89, 0x0c, 0x18,              // mov    %ecx,(%eax,%ebx,1)
3222 < #if defined(__x86_64__)
3222 > #if defined(__x86_64__) || defined(_M_X64)
3223                  0x44, 0x8a, 0x00,              // mov    (%rax),%r8b
3224                  0x44, 0x8a, 0x20,              // mov    (%rax),%r12b
3225                  0x42, 0x8a, 0x3c, 0x10,        // mov    (%rax,%r10,1),%dil
# Line 1764 | Line 3242 | static bool arch_insn_skipper_tests()
3242                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3243                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3244                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3245 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3246 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3247   #endif
3248                  0                              // end
3249          };
3250          const int N_REGS = 20;
3251 <        unsigned long regs[N_REGS];
3251 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3252          for (int i = 0; i < N_REGS; i++)
3253                  regs[i] = i;
3254 <        const unsigned long start_code = (unsigned long)&code;
3254 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3255          regs[X86_REG_EIP] = start_code;
3256          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3257                     && ix86_skip_instruction(regs))
# Line 1787 | Line 3267 | int main(void)
3267          if (vm_init() < 0)
3268                  return 1;
3269  
3270 <        page_size = getpagesize();
3270 >        page_size = vm_get_page_size();
3271          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3272                  return 2;
3273          
# Line 1797 | Line 3277 | int main(void)
3277          
3278          if (!sigsegv_install_handler(sigsegv_test_handler))
3279                  return 4;
3280 <        
3280 >
3281   #ifdef __GNUC__
3282          b_region = &&L_b_region1;
3283          e_region = &&L_e_region1;
3284   #endif
3285 < L_b_region1:
3286 <        page[REF_INDEX] = REF_VALUE;
3287 <        if (page[REF_INDEX] != REF_VALUE)
3288 <          exit(20);
3289 <        page[REF_INDEX] = REF_VALUE;
3290 < L_e_region1:
3285 >        /* This is a really awful hack but otherwise gcc is smart enough
3286 >         * (or bug'ous enough?) to optimize the labels and place them
3287 >         * e.g. at the "main" entry point, which is wrong.
3288 >         */
3289 >        volatile int label_hack = 1;
3290 >        switch (label_hack) {
3291 >        case 1:
3292 >        L_b_region1:
3293 >                page[REF_INDEX] = REF_VALUE;
3294 >                if (page[REF_INDEX] != REF_VALUE)
3295 >                        exit(20);
3296 >                page[REF_INDEX] = REF_VALUE;
3297 >                BARRIER();
3298 >                // fall-through
3299 >        case 2:
3300 >        L_e_region1:
3301 >                BARRIER();
3302 >                break;
3303 >        }
3304  
3305          if (handler_called != 1)
3306                  return 5;
# Line 1838 | Line 3331 | int main(void)
3331          b_region = &&L_b_region2;
3332          e_region = &&L_e_region2;
3333   #endif
3334 < L_b_region2:
3335 <        TEST_SKIP_INSTRUCTION(unsigned char);
3336 <        TEST_SKIP_INSTRUCTION(unsigned short);
3337 <        TEST_SKIP_INSTRUCTION(unsigned int);
3338 <        TEST_SKIP_INSTRUCTION(unsigned long);
3339 < L_e_region2:
3340 <
3334 >        switch (label_hack) {
3335 >        case 1:
3336 >        L_b_region2:
3337 >                TEST_SKIP_INSTRUCTION(unsigned char);
3338 >                TEST_SKIP_INSTRUCTION(unsigned short);
3339 >                TEST_SKIP_INSTRUCTION(unsigned int);
3340 >                TEST_SKIP_INSTRUCTION(unsigned long);
3341 >                TEST_SKIP_INSTRUCTION(signed char);
3342 >                TEST_SKIP_INSTRUCTION(signed short);
3343 >                TEST_SKIP_INSTRUCTION(signed int);
3344 >                TEST_SKIP_INSTRUCTION(signed long);
3345 >                BARRIER();
3346 >                // fall-through
3347 >        case 2:
3348 >        L_e_region2:
3349 >                BARRIER();
3350 >                break;
3351 >        }
3352          if (!arch_insn_skipper_tests())
3353                  return 20;
3354   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines