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.52 by gbeauche, 2005-01-30T21:42:14Z vs.
Revision 1.82 by gbeauche, 2008-01-19T22:27:29Z

# 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-2005 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 240 | Line 255 | static void powerpc_decode_instruction(i
255   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
256   #define SIGSEGV_FAULT_INSTRUCTION               (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC]
257   #if (defined(mips) || defined(__mips))
258 < #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
258 > #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS[CTX_EPC], &SIGSEGV_CONTEXT_REGS[CTX_R0]
259   #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
260   #endif
261   #endif
# Line 256 | Line 271 | static void powerpc_decode_instruction(i
271   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW
272   #define SIGSEGV_SKIP_INSTRUCTION                sparc_skip_instruction
273   #endif
274 + #if defined(__i386__)
275 + #include <sys/regset.h>
276 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
277 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[EIP]
278 + #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
279 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
280   #endif
281 < #if defined(__FreeBSD__)
281 > #endif
282 > #if defined(__FreeBSD__) || defined(__OpenBSD__)
283   #if (defined(i386) || defined(__i386__))
284   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
285 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
285 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
286   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
287   #endif
288   #endif
# Line 269 | Line 291 | static void powerpc_decode_instruction(i
291   #include <sys/ucontext.h>
292   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
293   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_EIP]
294 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
294 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
295   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
296   #endif
297 + #if (defined(powerpc) || defined(__powerpc__))
298 + #include <sys/ucontext.h>
299 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
300 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_PC]
301 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_PC], (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_R0]
302 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
303 + #endif
304   #endif
305   #if defined(__linux__)
306   #if (defined(i386) || defined(__i386__))
307   #include <sys/ucontext.h>
308   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
309   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
310 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
310 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
311   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
312   #endif
313   #if (defined(x86_64) || defined(__x86_64__))
314   #include <sys/ucontext.h>
315   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
316   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */
317 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
317 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
318   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
319   #endif
320   #if (defined(ia64) || defined(__ia64__))
321 < #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
321 > #define SIGSEGV_CONTEXT_REGS                    ((struct sigcontext *)scp)
322 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
323 > #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
324 > #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
325   #endif
326   #if (defined(powerpc) || defined(__powerpc__))
327   #include <sys/ucontext.h>
# Line 309 | Line 341 | static void powerpc_decode_instruction(i
341   #define SIGSEGV_REGISTER_FILE                   (&SIGSEGV_CONTEXT_REGS.arm_r0)
342   #define SIGSEGV_SKIP_INSTRUCTION                arm_skip_instruction
343   #endif
344 + #if (defined(mips) || defined(__mips__))
345 + #include <sys/ucontext.h>
346 + #define SIGSEGV_CONTEXT_REGS                    (((struct ucontext *)scp)->uc_mcontext)
347 + #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS.pc)
348 + #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS.pc, &SIGSEGV_CONTEXT_REGS.gregs[0]
349 + #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
350 + #endif
351 + #endif
352 + #if (defined(__hpux) || defined(__hpux__))
353 + #if (defined(__ia64) || defined(__ia64__))
354 + #include <sys/ucontext.h>
355 + #define SIGSEGV_CONTEXT_REGS                    ((ucontext_t *)scp)
356 + #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(SIGSEGV_CONTEXT_REGS)
357 + #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
358 + #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
359 +
360 + #include <sys/uc_access.h>
361 + static sigsegv_address_t get_fault_instruction(const ucontext_t *ucp)
362 + {
363 +  uint64_t ip;
364 +  if (__uc_get_ip(ucp, &ip) != 0)
365 +        return SIGSEGV_INVALID_ADDRESS;
366 +  return (sigsegv_address_t)(ip & ~3ULL);
367 + }
368 + #endif
369   #endif
370   #endif
371  
# Line 323 | Line 380 | static void powerpc_decode_instruction(i
380   #define SIGSEGV_FAULT_HANDLER_ARGS              &scs
381   #define SIGSEGV_FAULT_ADDRESS                   scp->cr2
382   #define SIGSEGV_FAULT_INSTRUCTION               scp->eip
383 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)scp
383 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)scp
384   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
385   #endif
386   #if (defined(sparc) || defined(__sparc__))
# Line 444 | Line 501 | static sigsegv_address_t get_fault_addre
501   #define SIGSEGV_FAULT_HANDLER_ARGS              sig, code, scp, addr
502   #define SIGSEGV_FAULT_ADDRESS                   addr
503   #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_eip
504 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&scp->sc_edi)
504 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&scp->sc_edi)
505   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
506   #endif
507   #if (defined(alpha) || defined(__alpha__))
# Line 507 | Line 564 | static sigsegv_address_t get_fault_addre
564   #include <windows.h>
565   #include <winerror.h>
566  
567 + #if defined(_M_IX86)
568   #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
569   #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
570   #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
571   #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
572   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Eip
573 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIGSEGV_CONTEXT_REGS->Edi)
573 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Edi)
574   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
575   #endif
576 + #if defined(_M_X64)
577 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
578 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
579 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
580 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
581 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Rip
582 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax)
583 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
584 + #endif
585 + #endif
586  
587   #if HAVE_MACH_EXCEPTIONS
588  
# Line 576 | Line 644 | if (ret != KERN_SUCCESS) { \
644          exit (1); \
645   }
646  
647 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
648 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
649 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
650 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
651 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
647 > #ifdef __ppc__
648 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE
649 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
650 > #endif
651 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
652 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
653 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
654 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
655 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
656 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
657 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
658 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
659   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
660 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
661 <
662 < // Given a suspended thread, stuff the current instruction and
663 < // registers into state.
664 < //
665 < // It would have been nice to have this be ppc/x86 independant which
666 < // could have been done easily with a thread_state_t instead of
667 < // ppc_thread_state_t, but because of the way this is called it is
668 < // easier to do it this way.
669 < #if (defined(ppc) || defined(__ppc__))
670 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
671 < {
672 <        kern_return_t krc;
673 <        mach_msg_type_number_t count;
674 <
675 <        count = MACHINE_THREAD_STATE_COUNT;
676 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
677 <        MACH_CHECK_ERROR (thread_get_state, krc);
660 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
661 > #endif
662 > #ifdef __ppc64__
663 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE64
664 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
665 > #endif
666 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
667 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
668 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
669 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
670 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
671 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
672 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
673 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
674 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
675 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
676 > #endif
677 > #ifdef __i386__
678 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE32
679 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
680 > #endif
681 > #define SIGSEGV_EXCEPTION_STATE_TYPE    i386_exception_state_t
682 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
683 > #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
684 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
685 > #define SIGSEGV_THREAD_STATE_TYPE               i386_thread_state_t
686 > #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
687 > #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
688 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(eip)
689 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
690 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(eax)) /* EAX is the first GPR we consider */
691 > #endif
692 > #ifdef __x86_64__
693 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE64
694 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
695 > #endif
696 > #define SIGSEGV_EXCEPTION_STATE_TYPE    x86_exception_state64_t
697 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
698 > #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
699 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
700 > #define SIGSEGV_THREAD_STATE_TYPE               x86_thread_state64_t
701 > #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
702 > #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
703 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(rip)
704 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
705 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(rax)) /* RAX is the first GPR we consider */
706 > #endif
707 > #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
708 > #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
709 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
710 > #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
711  
712 <        return (sigsegv_address_t)state->srr0;
713 < }
712 > #ifndef MACH_FIELD_NAME
713 > #define MACH_FIELD_NAME(X) X
714   #endif
715  
716   // Since there can only be one exception thread running at any time
# Line 656 | Line 764 | handleExceptions(void *priv)
764   *  Instruction skipping
765   */
766  
767 + #ifndef SIGSEGV_REGISTER_TYPE
768 + #define SIGSEGV_REGISTER_TYPE sigsegv_uintptr_t
769 + #endif
770 +
771   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
772   // Decode and skip X86 instruction
773 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
773 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
774   #if defined(__linux__)
775   enum {
776   #if (defined(i386) || defined(__i386__))
# Line 723 | Line 835 | enum {
835   #endif
836   };
837   #endif
838 < #if defined(_WIN32)
838 > #if defined(__OpenBSD__)
839 > enum {
840 > #if defined(__i386__)
841 >        // EDI is the first register we consider
842 > #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
843 > #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
844 >        X86_REG_EIP = DREG(eip), // 7
845 >        X86_REG_EAX = DREG(eax), // 6
846 >        X86_REG_ECX = DREG(ecx), // 5
847 >        X86_REG_EDX = DREG(edx), // 4
848 >        X86_REG_EBX = DREG(ebx), // 3
849 >        X86_REG_ESP = DREG(esp), // 10
850 >        X86_REG_EBP = DREG(ebp), // 2
851 >        X86_REG_ESI = DREG(esi), // 1
852 >        X86_REG_EDI = DREG(edi)  // 0
853 > #undef DREG
854 > #undef OREG
855 > #endif
856 > };
857 > #endif
858 > #if defined(__sun__)
859 > // Same as for Linux, need to check for x86-64
860 > enum {
861 > #if defined(__i386__)
862 >        X86_REG_EIP = EIP,
863 >        X86_REG_EAX = EAX,
864 >        X86_REG_ECX = ECX,
865 >        X86_REG_EDX = EDX,
866 >        X86_REG_EBX = EBX,
867 >        X86_REG_ESP = ESP,
868 >        X86_REG_EBP = EBP,
869 >        X86_REG_ESI = ESI,
870 >        X86_REG_EDI = EDI
871 > #endif
872 > };
873 > #endif
874 > #if defined(__APPLE__) && defined(__MACH__)
875   enum {
876   #if (defined(i386) || defined(__i386__))
877 + #ifdef i386_SAVED_STATE
878 +        // same as FreeBSD (in Open Darwin 8.0.1)
879 +        X86_REG_EIP = 10,
880 +        X86_REG_EAX = 7,
881 +        X86_REG_ECX = 6,
882 +        X86_REG_EDX = 5,
883 +        X86_REG_EBX = 4,
884 +        X86_REG_ESP = 13,
885 +        X86_REG_EBP = 2,
886 +        X86_REG_ESI = 1,
887 +        X86_REG_EDI = 0
888 + #else
889 +        // new layout (MacOS X 10.4.4 for x86)
890 +        X86_REG_EIP = 10,
891 +        X86_REG_EAX = 0,
892 +        X86_REG_ECX = 2,
893 +        X86_REG_EDX = 3,
894 +        X86_REG_EBX = 1,
895 +        X86_REG_ESP = 7,
896 +        X86_REG_EBP = 6,
897 +        X86_REG_ESI = 5,
898 +        X86_REG_EDI = 4
899 + #endif
900 + #endif
901 + #if defined(__x86_64__)
902 +        X86_REG_R8  = 8,
903 +        X86_REG_R9  = 9,
904 +        X86_REG_R10 = 10,
905 +        X86_REG_R11 = 11,
906 +        X86_REG_R12 = 12,
907 +        X86_REG_R13 = 13,
908 +        X86_REG_R14 = 14,
909 +        X86_REG_R15 = 15,
910 +        X86_REG_EDI = 4,
911 +        X86_REG_ESI = 5,
912 +        X86_REG_EBP = 6,
913 +        X86_REG_EBX = 1,
914 +        X86_REG_EDX = 3,
915 +        X86_REG_EAX = 0,
916 +        X86_REG_ECX = 2,
917 +        X86_REG_ESP = 7,
918 +        X86_REG_EIP = 16
919 + #endif
920 + };
921 + #endif
922 + #if defined(_WIN32)
923 + enum {
924 + #if defined(_M_IX86)
925          X86_REG_EIP = 7,
926          X86_REG_EAX = 5,
927          X86_REG_ECX = 4,
# Line 736 | Line 932 | enum {
932          X86_REG_ESI = 1,
933          X86_REG_EDI = 0
934   #endif
935 + #if defined(_M_X64)
936 +        X86_REG_EAX = 0,
937 +        X86_REG_ECX = 1,
938 +        X86_REG_EDX = 2,
939 +        X86_REG_EBX = 3,
940 +        X86_REG_ESP = 4,
941 +        X86_REG_EBP = 5,
942 +        X86_REG_ESI = 6,
943 +        X86_REG_EDI = 7,
944 +        X86_REG_R8  = 8,
945 +        X86_REG_R9  = 9,
946 +        X86_REG_R10 = 10,
947 +        X86_REG_R11 = 11,
948 +        X86_REG_R12 = 12,
949 +        X86_REG_R13 = 13,
950 +        X86_REG_R14 = 14,
951 +        X86_REG_R15 = 15,
952 +        X86_REG_EIP = 16
953 + #endif
954   };
955   #endif
956   // FIXME: this is partly redundant with the instruction decoding phase
# Line 772 | Line 987 | static inline int ix86_step_over_modrm(u
987          return offset;
988   }
989  
990 < static bool ix86_skip_instruction(unsigned long * regs)
990 > static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs)
991   {
992          unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
993  
# Line 783 | Line 998 | static bool ix86_skip_instruction(unsign
998                  return false;
999   #endif
1000          
1001 +        enum instruction_type_t {
1002 +                i_MOV,
1003 +                i_ADD
1004 +        };
1005 +
1006          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1007          transfer_size_t transfer_size = SIZE_LONG;
1008 +        instruction_type_t instruction_type = i_MOV;
1009          
1010          int reg = -1;
1011          int len = 0;
# Line 802 | Line 1023 | static bool ix86_skip_instruction(unsign
1023          }
1024  
1025          // REX prefix
1026 < #if defined(__x86_64__)
1026 > #if defined(__x86_64__) || defined(_M_X64)
1027          struct rex_t {
1028                  unsigned char W;
1029                  unsigned char R;
# Line 835 | Line 1056 | static bool ix86_skip_instruction(unsign
1056   #endif
1057  
1058          // Decode instruction
1059 +        int op_len = 1;
1060          int target_size = SIZE_UNKNOWN;
1061          switch (eip[0]) {
1062          case 0x0f:
# Line 849 | Line 1071 | static bool ix86_skip_instruction(unsign
1071                          transfer_size = SIZE_WORD;
1072                          goto do_mov_extend;
1073                    do_mov_extend:
1074 <                        switch (eip[2] & 0xc0) {
1075 <                        case 0x80:
1076 <                                reg = (eip[2] >> 3) & 7;
1077 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1078 <                                break;
1079 <                        case 0x40:
1080 <                                reg = (eip[2] >> 3) & 7;
1081 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1082 <                                break;
1083 <                        case 0x00:
1084 <                                reg = (eip[2] >> 3) & 7;
1085 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1086 <                                break;
1087 <                        }
1088 <                        len += 3 + ix86_step_over_modrm(eip + 2);
1089 <                        break;
1090 <            }
1091 <          break;
1074 >                        op_len = 2;
1075 >                        goto do_transfer_load;
1076 >                }
1077 >                break;
1078 > #if defined(__x86_64__) || defined(_M_X64)
1079 >        case 0x63: // MOVSXD r64, r/m32
1080 >                if (has_rex && rex.W) {
1081 >                        transfer_size = SIZE_LONG;
1082 >                        target_size = SIZE_QUAD;
1083 >                }
1084 >                else if (transfer_size != SIZE_WORD) {
1085 >                        transfer_size = SIZE_LONG;
1086 >                        target_size = SIZE_QUAD;
1087 >                }
1088 >                goto do_transfer_load;
1089 > #endif
1090 >        case 0x02: // ADD r8, r/m8
1091 >                transfer_size = SIZE_BYTE;
1092 >        case 0x03: // ADD r32, r/m32
1093 >                instruction_type = i_ADD;
1094 >                goto do_transfer_load;
1095          case 0x8a: // MOV r8, r/m8
1096                  transfer_size = SIZE_BYTE;
1097          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1098 <                switch (eip[1] & 0xc0) {
1098 >          do_transfer_load:
1099 >                switch (eip[op_len] & 0xc0) {
1100                  case 0x80:
1101 <                        reg = (eip[1] >> 3) & 7;
1101 >                        reg = (eip[op_len] >> 3) & 7;
1102                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1103                          break;
1104                  case 0x40:
1105 <                        reg = (eip[1] >> 3) & 7;
1105 >                        reg = (eip[op_len] >> 3) & 7;
1106                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1107                          break;
1108                  case 0x00:
1109 <                        reg = (eip[1] >> 3) & 7;
1109 >                        reg = (eip[op_len] >> 3) & 7;
1110                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1111                          break;
1112                  }
1113 <                len += 2 + ix86_step_over_modrm(eip + 1);
1113 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1114                  break;
1115 +        case 0x00: // ADD r/m8, r8
1116 +                transfer_size = SIZE_BYTE;
1117 +        case 0x01: // ADD r/m32, r32
1118 +                instruction_type = i_ADD;
1119 +                goto do_transfer_store;
1120          case 0x88: // MOV r/m8, r8
1121                  transfer_size = SIZE_BYTE;
1122          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1123 <                switch (eip[1] & 0xc0) {
1123 >          do_transfer_store:
1124 >                switch (eip[op_len] & 0xc0) {
1125                  case 0x80:
1126 <                        reg = (eip[1] >> 3) & 7;
1126 >                        reg = (eip[op_len] >> 3) & 7;
1127                          transfer_type = SIGSEGV_TRANSFER_STORE;
1128                          break;
1129                  case 0x40:
1130 <                        reg = (eip[1] >> 3) & 7;
1130 >                        reg = (eip[op_len] >> 3) & 7;
1131                          transfer_type = SIGSEGV_TRANSFER_STORE;
1132                          break;
1133                  case 0x00:
1134 <                        reg = (eip[1] >> 3) & 7;
1134 >                        reg = (eip[op_len] >> 3) & 7;
1135                          transfer_type = SIGSEGV_TRANSFER_STORE;
1136                          break;
1137                  }
1138 <                len += 2 + ix86_step_over_modrm(eip + 1);
1138 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1139                  break;
1140          }
1141          if (target_size == SIZE_UNKNOWN)
# Line 914 | Line 1146 | static bool ix86_skip_instruction(unsign
1146                  return false;
1147          }
1148  
1149 < #if defined(__x86_64__)
1149 > #if defined(__x86_64__) || defined(_M_X64)
1150          if (rex.R)
1151                  reg += 8;
1152   #endif
1153  
1154 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1154 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1155                  static const int x86_reg_map[] = {
1156                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1157                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1158 < #if defined(__x86_64__)
1158 > #if defined(__x86_64__) || defined(_M_X64)
1159                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1160                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1161   #endif
# Line 955 | Line 1187 | static bool ix86_skip_instruction(unsign
1187          }
1188  
1189   #if DEBUG
1190 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1190 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1191                     transfer_size == SIZE_BYTE ? "byte" :
1192                     transfer_size == SIZE_WORD ? "word" :
1193                     transfer_size == SIZE_LONG ? "long" :
# Line 1010 | Line 1242 | static bool ix86_skip_instruction(unsign
1242   }
1243   #endif
1244  
1245 + // Decode and skip IA-64 instruction
1246 + #if defined(__ia64) || defined(__ia64__)
1247 + typedef uint64_t ia64_bundle_t[2];
1248 + #if defined(__linux__)
1249 + // We can directly patch the slot number
1250 + #define IA64_CAN_PATCH_IP_SLOT  1
1251 + // Helper macros to access the machine context
1252 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1253 + #define IA64_CONTEXT                    scp
1254 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1255 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1256 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1257 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1258 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1259 + #define _IA64_SET_GR(R,V)               (IA64_CONTEXT->sc_gr[(R)] = (V))
1260 + #define _IA64_SET_NAT(I,V)              (IA64_CONTEXT->sc_nat = (IA64_CONTEXT->sc_nat & ~(1ull << (I))) | (((uint64_t)!!(V)) << (I)))
1261 + #define IA64_SET_GR(R,V,N)              (_IA64_SET_GR(R,V), _IA64_SET_NAT(R,N))
1262 +
1263 + // Load bundle (in little-endian)
1264 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1265 + {
1266 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1267 +        bundle[0] = ip[0];
1268 +        bundle[1] = ip[1];
1269 + }
1270 + #endif
1271 + #if defined(__hpux) || defined(__hpux__)
1272 + // We can directly patch the slot number
1273 + #define IA64_CAN_PATCH_IP_SLOT  1
1274 + // Helper macros to access the machine context
1275 + #define IA64_CONTEXT_TYPE               ucontext_t *
1276 + #define IA64_CONTEXT                    ucp
1277 + #define IA64_GET_IP()                   ia64_get_ip(IA64_CONTEXT)
1278 + #define IA64_SET_IP(V)                  ia64_set_ip(IA64_CONTEXT, V)
1279 + #define IA64_GET_PR(P)                  ia64_get_pr(IA64_CONTEXT, P)
1280 + #define IA64_GET_NAT(I)                 ia64_get_nat(IA64_CONTEXT, I)
1281 + #define IA64_GET_GR(R)                  ia64_get_gr(IA64_CONTEXT, R)
1282 + #define IA64_SET_GR(R,V,N)              ia64_set_gr(IA64_CONTEXT, R, V, N)
1283 + #define UC_ACCESS(FUNC,ARGS)    do { if (__uc_##FUNC ARGS != 0) abort(); } while (0)
1284 +
1285 + static inline uint64_t ia64_get_ip(IA64_CONTEXT_TYPE IA64_CONTEXT)
1286 +        { uint64_t v; UC_ACCESS(get_ip,(IA64_CONTEXT, &v)); return v; }
1287 + static inline void ia64_set_ip(IA64_CONTEXT_TYPE IA64_CONTEXT, uint64_t v)
1288 +        { UC_ACCESS(set_ip,(IA64_CONTEXT, v)); }
1289 + static inline unsigned int ia64_get_pr(IA64_CONTEXT_TYPE IA64_CONTEXT, int pr)
1290 +        { uint64_t v; UC_ACCESS(get_prs,(IA64_CONTEXT, &v)); return (v >> pr) & 1; }
1291 + static inline unsigned int ia64_get_nat(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1292 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return (nat >> r) & 1; }
1293 + static inline uint64_t ia64_get_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1294 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return v; }
1295 +
1296 + static void ia64_set_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r, uint64_t v, unsigned int nat)
1297 + {
1298 +        if (r == 0)
1299 +                return;
1300 +        if (r > 0 && r < 32)
1301 +                UC_ACCESS(set_grs,(IA64_CONTEXT, r, 1, &v, (!!nat) << r));
1302 +        else {
1303 +                uint64_t bsp, bspstore;
1304 +                UC_ACCESS(get_ar_bsp,(IA64_CONTEXT, &bsp));
1305 +                UC_ACCESS(get_ar_bspstore,(IA64_CONTEXT, &bspstore));
1306 +                abort(); /* XXX: use libunwind, this is not fun... */
1307 +        }
1308 + }
1309 +
1310 + // Byte-swapping
1311 + #if defined(__GNUC__)
1312 + #define BSWAP64(V) ({ uint64_t r; __asm__ __volatile__("mux1 %0=%1,@rev;;" : "=r" (r) : "r" (V)); r; })
1313 + #elif defined (__HP_aCC)
1314 + #define BSWAP64(V) _Asm_mux1(_MBTYPE_REV, V)
1315 + #else
1316 + #error "Define byte-swap instruction"
1317 + #endif
1318 +
1319 + // Load bundle (in little-endian)
1320 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1321 + {
1322 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1323 +        bundle[0] = BSWAP64(ip[0]);
1324 +        bundle[1] = BSWAP64(ip[1]);
1325 + }
1326 + #endif
1327 +
1328 + // Instruction operations
1329 + enum {
1330 +        IA64_INST_UNKNOWN = 0,
1331 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1332 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1333 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1334 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1335 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1336 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1337 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1338 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1339 +        IA64_INST_ST1,                          // st1 [op0]=op1
1340 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1341 +        IA64_INST_ST2,                          // st2 [op0]=op1
1342 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1343 +        IA64_INST_ST4,                          // st4 [op0]=op1
1344 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1345 +        IA64_INST_ST8,                          // st8 [op0]=op1
1346 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1347 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1348 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1349 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1350 +        IA64_INST_AND,                          // and op0=op1,op2
1351 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1352 +        IA64_INST_OR,                           // or op0=op1,op2
1353 +        IA64_INST_XOR,                          // xor op0=op1,op2
1354 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1355 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1356 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1357 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1358 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1359 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1360 +        IA64_INST_NOP                           // nop op0
1361 + };
1362 +
1363 + const int IA64_N_OPERANDS = 4;
1364 +
1365 + // Decoded operand type
1366 + struct ia64_operand_t {
1367 +        uint8_t commit;                         // commit result of operation to register file?
1368 +        uint8_t valid;                          // XXX: not really used, can be removed (debug)
1369 +        int8_t index;                           // index of GPR, or -1 if immediate value
1370 +        uint8_t nat;                            // NaT state before operation
1371 +        uint64_t value;                         // register contents or immediate value
1372 + };
1373 +
1374 + // Decoded instruction type
1375 + struct ia64_instruction_t {
1376 +        uint8_t mnemo;                          // operation to perform
1377 +        uint8_t pred;                           // predicate register to check
1378 +        uint8_t no_memory;                      // used to emulated main fault instruction
1379 +        uint64_t inst;                          // the raw instruction bits (41-bit wide)
1380 +        ia64_operand_t operands[IA64_N_OPERANDS];
1381 + };
1382 +
1383 + // Get immediate sign-bit
1384 + static inline int ia64_inst_get_sbit(uint64_t inst)
1385 + {
1386 +        return (inst >> 36) & 1;
1387 + }
1388 +
1389 + // Get 8-bit immediate value (A3, A8, I27, M30)
1390 + static inline uint64_t ia64_inst_get_imm8(uint64_t inst)
1391 + {
1392 +        uint64_t value = (inst >> 13) & 0x7full;
1393 +        if (ia64_inst_get_sbit(inst))
1394 +                value |= ~0x7full;
1395 +        return value;
1396 + }
1397 +
1398 + // Get 9-bit immediate value (M3)
1399 + static inline uint64_t ia64_inst_get_imm9b(uint64_t inst)
1400 + {
1401 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1402 +        if (ia64_inst_get_sbit(inst))
1403 +                value |= ~0xffull;
1404 +        return value;
1405 + }
1406 +
1407 + // Get 9-bit immediate value (M5)
1408 + static inline uint64_t ia64_inst_get_imm9a(uint64_t inst)
1409 + {
1410 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1411 +        if (ia64_inst_get_sbit(inst))
1412 +                value |= ~0xffull;
1413 +        return value;
1414 + }
1415 +
1416 + // Get 14-bit immediate value (A4)
1417 + static inline uint64_t ia64_inst_get_imm14(uint64_t inst)
1418 + {
1419 +        uint64_t value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1420 +        if (ia64_inst_get_sbit(inst))
1421 +                value |= ~0x1ffull;
1422 +        return value;
1423 + }
1424 +
1425 + // Get 22-bit immediate value (A5)
1426 + static inline uint64_t ia64_inst_get_imm22(uint64_t inst)
1427 + {
1428 +        uint64_t value = ((((inst >> 22) & 0x1f) << 16) |
1429 +                                          (((inst >> 27) & 0x1ff) << 7) |
1430 +                                          (inst & 0x7f));
1431 +        if (ia64_inst_get_sbit(inst))
1432 +                value |= ~0x1fffffull;
1433 +        return value;
1434 + }
1435 +
1436 + // Get 21-bit immediate value (I19)
1437 + static inline uint64_t ia64_inst_get_imm21(uint64_t inst)
1438 + {
1439 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1440 + }
1441 +
1442 + // Get 2-bit count value (A2)
1443 + static inline int ia64_inst_get_count2(uint64_t inst)
1444 + {
1445 +        return (inst >> 27) & 0x3;
1446 + }
1447 +
1448 + // Get bundle template
1449 + static inline unsigned int ia64_get_template(uint64_t ip)
1450 + {
1451 +        ia64_bundle_t bundle;
1452 +        ia64_load_bundle(bundle, ip);
1453 +        return bundle[0] & 0x1f;
1454 + }
1455 +
1456 + // Get specified instruction in bundle
1457 + static uint64_t ia64_get_instruction(uint64_t ip, int slot)
1458 + {
1459 +        uint64_t inst;
1460 +        ia64_bundle_t bundle;
1461 +        ia64_load_bundle(bundle, ip);
1462 + #if DEBUG
1463 +        printf("Bundle: %016llx%016llx\n", bundle[1], bundle[0]);
1464 + #endif
1465 +
1466 +        switch (slot) {
1467 +        case 0:
1468 +                inst = (bundle[0] >> 5) & 0x1ffffffffffull;
1469 +                break;
1470 +        case 1:
1471 +                inst = ((bundle[1] & 0x7fffffull) << 18) | ((bundle[0] >> 46) & 0x3ffffull);
1472 +                break;
1473 +        case 2:
1474 +                inst = (bundle[1] >> 23) & 0x1ffffffffffull;
1475 +                break;
1476 +        case 3:
1477 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1478 +                abort();
1479 +                break;
1480 +        }
1481 +
1482 + #if DEBUG
1483 +        printf(" Instruction %d: 0x%016llx\n", slot, inst);
1484 + #endif
1485 +        return inst;
1486 + }
1487 +
1488 + // Decode group 0 instructions
1489 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1490 + {
1491 +        const int r1 = (inst->inst >>  6) & 0x7f;
1492 +        const int r3 = (inst->inst >> 20) & 0x7f;
1493 +
1494 +        const int x3 = (inst->inst >> 33) & 0x07;
1495 +        const int x6 = (inst->inst >> 27) & 0x3f;
1496 +        const int x2 = (inst->inst >> 31) & 0x03;
1497 +        const int x4 = (inst->inst >> 27) & 0x0f;
1498 +
1499 +        if (x3 == 0) {
1500 +                switch (x6) {
1501 +                case 0x01:                                              // nop.i (I19)
1502 +                        inst->mnemo = IA64_INST_NOP;
1503 +                        inst->operands[0].valid = true;
1504 +                        inst->operands[0].index = -1;
1505 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1506 +                        return true;
1507 +                case 0x14:                                              // sxt1 (I29)
1508 +                case 0x15:                                              // sxt2 (I29)
1509 +                case 0x16:                                              // sxt4 (I29)
1510 +                case 0x10:                                              // zxt1 (I29)
1511 +                case 0x11:                                              // zxt2 (I29)
1512 +                case 0x12:                                              // zxt4 (I29)
1513 +                        switch (x6) {
1514 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1515 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1516 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1517 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1518 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1519 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1520 +                        default: abort();
1521 +                        }
1522 +                        inst->operands[0].valid = true;
1523 +                        inst->operands[0].index = r1;
1524 +                        inst->operands[1].valid = true;
1525 +                        inst->operands[1].index = r3;
1526 +                        inst->operands[1].value = IA64_GET_GR(r3);
1527 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1528 +                        return true;
1529 +                }
1530 +        }
1531 +        return false;
1532 + }
1533 +
1534 + // Decode group 4 instructions (load/store instructions)
1535 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1536 + {
1537 +        const int r1 = (inst->inst >> 6) & 0x7f;
1538 +        const int r2 = (inst->inst >> 13) & 0x7f;
1539 +        const int r3 = (inst->inst >> 20) & 0x7f;
1540 +
1541 +        const int m  = (inst->inst >> 36) & 1;
1542 +        const int x  = (inst->inst >> 27) & 1;
1543 +        const int x6 = (inst->inst >> 30) & 0x3f;
1544 +
1545 +        switch (x6) {
1546 +        case 0x00:
1547 +        case 0x01:
1548 +        case 0x02:
1549 +        case 0x03:
1550 +                if (x == 0) {
1551 +                        inst->operands[0].valid = true;
1552 +                        inst->operands[0].index = r1;
1553 +                        inst->operands[1].valid = true;
1554 +                        inst->operands[1].index = r3;
1555 +                        inst->operands[1].value = IA64_GET_GR(r3);
1556 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1557 +                        if (m == 0) {
1558 +                                switch (x6) {
1559 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1560 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1561 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1562 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1563 +                                }
1564 +                        }
1565 +                        else {
1566 +                                inst->operands[2].valid = true;
1567 +                                inst->operands[2].index = r2;
1568 +                                inst->operands[2].value = IA64_GET_GR(r2);
1569 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1570 +                                switch (x6) {
1571 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1572 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1573 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1574 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1575 +                                }
1576 +                        }
1577 +                        return true;
1578 +                }
1579 +                break;
1580 +        case 0x30:
1581 +        case 0x31:
1582 +        case 0x32:
1583 +        case 0x33:
1584 +                if (m == 0 && x == 0) {
1585 +                        inst->operands[0].valid = true;
1586 +                        inst->operands[0].index = r3;
1587 +                        inst->operands[0].value = IA64_GET_GR(r3);
1588 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1589 +                        inst->operands[1].valid = true;
1590 +                        inst->operands[1].index = r2;
1591 +                        inst->operands[1].value = IA64_GET_GR(r2);
1592 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1593 +                        switch (x6) {
1594 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1595 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1596 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1597 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1598 +                        }
1599 +                        return true;
1600 +                }
1601 +                break;
1602 +        }
1603 +        return false;
1604 + }
1605 +
1606 + // Decode group 5 instructions (load/store instructions)
1607 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1608 + {
1609 +        const int r1 = (inst->inst >> 6) & 0x7f;
1610 +        const int r2 = (inst->inst >> 13) & 0x7f;
1611 +        const int r3 = (inst->inst >> 20) & 0x7f;
1612 +
1613 +        const int x6 = (inst->inst >> 30) & 0x3f;
1614 +
1615 +        switch (x6) {
1616 +        case 0x00:
1617 +        case 0x01:
1618 +        case 0x02:
1619 +        case 0x03:
1620 +                inst->operands[0].valid = true;
1621 +                inst->operands[0].index = r1;
1622 +                inst->operands[1].valid = true;
1623 +                inst->operands[1].index = r3;
1624 +                inst->operands[1].value = IA64_GET_GR(r3);
1625 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1626 +                inst->operands[2].valid = true;
1627 +                inst->operands[2].index = -1;
1628 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1629 +                inst->operands[2].nat   = 0;
1630 +                switch (x6) {
1631 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1632 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1633 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1634 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1635 +                }
1636 +                return true;
1637 +        case 0x30:
1638 +        case 0x31:
1639 +        case 0x32:
1640 +        case 0x33:
1641 +                inst->operands[0].valid = true;
1642 +                inst->operands[0].index = r3;
1643 +                inst->operands[0].value = IA64_GET_GR(r3);
1644 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1645 +                inst->operands[1].valid = true;
1646 +                inst->operands[1].index = r2;
1647 +                inst->operands[1].value = IA64_GET_GR(r2);
1648 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1649 +                inst->operands[2].valid = true;
1650 +                inst->operands[2].index = -1;
1651 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1652 +                inst->operands[2].nat   = 0;
1653 +                switch (x6) {
1654 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1655 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1656 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1657 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1658 +                }
1659 +                return true;
1660 +        }
1661 +        return false;
1662 + }
1663 +
1664 + // Decode group 8 instructions (ALU integer)
1665 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1666 + {
1667 +        const int r1  = (inst->inst >> 6) & 0x7f;
1668 +        const int r2  = (inst->inst >> 13) & 0x7f;
1669 +        const int r3  = (inst->inst >> 20) & 0x7f;
1670 +
1671 +        const int x2a = (inst->inst >> 34) & 0x3;
1672 +        const int x2b = (inst->inst >> 27) & 0x3;
1673 +        const int x4  = (inst->inst >> 29) & 0xf;
1674 +        const int ve  = (inst->inst >> 33) & 0x1;
1675 +
1676 +        // destination register (r1) is always valid in this group
1677 +        inst->operands[0].valid = true;
1678 +        inst->operands[0].index = r1;
1679 +
1680 +        // source register (r3) is always valid in this group
1681 +        inst->operands[2].valid = true;
1682 +        inst->operands[2].index = r3;
1683 +        inst->operands[2].value = IA64_GET_GR(r3);
1684 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1685 +
1686 +        if (x2a == 0 && ve == 0) {
1687 +                inst->operands[1].valid = true;
1688 +                inst->operands[1].index = r2;
1689 +                inst->operands[1].value = IA64_GET_GR(r2);
1690 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1691 +                switch (x4) {
1692 +                case 0x0:                               // add (A1)
1693 +                        inst->mnemo = IA64_INST_ADD;
1694 +                        inst->operands[3].valid = true;
1695 +                        inst->operands[3].index = -1;
1696 +                        inst->operands[3].value = x2b == 1;
1697 +                        return true;
1698 +                case 0x1:                               // add (A1)
1699 +                        inst->mnemo = IA64_INST_SUB;
1700 +                        inst->operands[3].valid = true;
1701 +                        inst->operands[3].index = -1;
1702 +                        inst->operands[3].value = x2b == 0;
1703 +                        return true;
1704 +                case 0x4:                               // shladd (A2)
1705 +                        inst->mnemo = IA64_INST_SHLADD;
1706 +                        inst->operands[3].valid = true;
1707 +                        inst->operands[3].index = -1;
1708 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1709 +                        return true;
1710 +                case 0x9:
1711 +                        if (x2b == 1) {
1712 +                                inst->mnemo = IA64_INST_SUB;
1713 +                                inst->operands[1].index = -1;
1714 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1715 +                                inst->operands[1].nat   = 0;
1716 +                                return true;
1717 +                        }
1718 +                        break;
1719 +                case 0xb:
1720 +                        inst->operands[1].index = -1;
1721 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1722 +                        inst->operands[1].nat   = 0;
1723 +                        // fall-through
1724 +                case 0x3:
1725 +                        switch (x2b) {
1726 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1727 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1728 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1729 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1730 +                        }
1731 +                        return true;
1732 +                }
1733 +        }
1734 +        return false;
1735 + }
1736 +
1737 + // Decode instruction
1738 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1739 + {
1740 +        const int major = (inst->inst >> 37) & 0xf;
1741 +
1742 +        inst->mnemo = IA64_INST_UNKNOWN;
1743 +        inst->pred  = inst->inst & 0x3f;
1744 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1745 +
1746 +        switch (major) {
1747 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1748 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1749 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1750 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1751 +        }
1752 +        return false;
1753 + }
1754 +
1755 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1756 + {
1757 +        // XXX: handle Register NaT Consumption fault?
1758 +        // XXX: this simple emulator assumes instructions in a bundle
1759 +        // don't depend on effects of other instructions in the same
1760 +        // bundle. It probably would be simpler to JIT-generate code to be
1761 +        // executed natively but probably more costly (inject/extract CPU state)
1762 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1763 +                return false;
1764 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1765 +                return true;
1766 +
1767 +        uint8_t nat, nat2;
1768 +        uint64_t dst, dst2, src1, src2, src3;
1769 +
1770 +        switch (inst->mnemo) {
1771 +        case IA64_INST_NOP:
1772 +                break;
1773 +        case IA64_INST_ADD:
1774 +        case IA64_INST_SUB:
1775 +        case IA64_INST_SHLADD:
1776 +                src3 = inst->operands[3].value;
1777 +                // fall-through
1778 +        case IA64_INST_AND:
1779 +        case IA64_INST_ANDCM:
1780 +        case IA64_INST_OR:
1781 +        case IA64_INST_XOR:
1782 +                src1 = inst->operands[1].value;
1783 +                src2 = inst->operands[2].value;
1784 +                switch (inst->mnemo) {
1785 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1786 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1787 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1788 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1789 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1790 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1791 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1792 +                }
1793 +                inst->operands[0].commit = true;
1794 +                inst->operands[0].value  = dst;
1795 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1796 +                break;
1797 +        case IA64_INST_SXT1:
1798 +        case IA64_INST_SXT2:
1799 +        case IA64_INST_SXT4:
1800 +        case IA64_INST_ZXT1:
1801 +        case IA64_INST_ZXT2:
1802 +        case IA64_INST_ZXT4:
1803 +                src1 = inst->operands[1].value;
1804 +                switch (inst->mnemo) {
1805 +                case IA64_INST_SXT1: dst = (int64_t)(int8_t)src1;               break;
1806 +                case IA64_INST_SXT2: dst = (int64_t)(int16_t)src1;              break;
1807 +                case IA64_INST_SXT4: dst = (int64_t)(int32_t)src1;              break;
1808 +                case IA64_INST_ZXT1: dst = (uint8_t)src1;                               break;
1809 +                case IA64_INST_ZXT2: dst = (uint16_t)src1;                              break;
1810 +                case IA64_INST_ZXT4: dst = (uint32_t)src1;                              break;
1811 +                }
1812 +                inst->operands[0].commit = true;
1813 +                inst->operands[0].value  = dst;
1814 +                inst->operands[0].nat    = inst->operands[1].nat;
1815 +                break;
1816 +        case IA64_INST_LD1_UPDATE:
1817 +        case IA64_INST_LD2_UPDATE:
1818 +        case IA64_INST_LD4_UPDATE:
1819 +        case IA64_INST_LD8_UPDATE:
1820 +                inst->operands[1].commit = true;
1821 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1822 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1823 +                // fall-through
1824 +        case IA64_INST_LD1:
1825 +        case IA64_INST_LD2:
1826 +        case IA64_INST_LD4:
1827 +        case IA64_INST_LD8:
1828 +                src1 = inst->operands[1].value;
1829 +                if (inst->no_memory)
1830 +                        dst = 0;
1831 +                else {
1832 +                        switch (inst->mnemo) {
1833 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((uint8_t *)src1);        break;
1834 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((uint16_t *)src1);       break;
1835 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((uint32_t *)src1);       break;
1836 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((uint64_t *)src1);       break;
1837 +                        }
1838 +                }
1839 +                inst->operands[0].commit = true;
1840 +                inst->operands[0].value  = dst;
1841 +                inst->operands[0].nat    = 0;
1842 +                inst->operands[1].value  = dst2;
1843 +                inst->operands[1].nat    = nat2;
1844 +                break;
1845 +        case IA64_INST_ST1_UPDATE:
1846 +        case IA64_INST_ST2_UPDATE:
1847 +        case IA64_INST_ST4_UPDATE:
1848 +        case IA64_INST_ST8_UPDATE:
1849 +                inst->operands[0].commit = 0;
1850 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1851 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1852 +                // fall-through
1853 +        case IA64_INST_ST1:
1854 +        case IA64_INST_ST2:
1855 +        case IA64_INST_ST4:
1856 +        case IA64_INST_ST8:
1857 +                dst  = inst->operands[0].value;
1858 +                src1 = inst->operands[1].value;
1859 +                if (!inst->no_memory) {
1860 +                        switch (inst->mnemo) {
1861 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((uint8_t *)dst) = src1;        break;
1862 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((uint16_t *)dst) = src1;       break;
1863 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((uint32_t *)dst) = src1;       break;
1864 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((uint64_t *)dst) = src1;       break;
1865 +                        }
1866 +                }
1867 +                inst->operands[0].value  = dst2;
1868 +                inst->operands[0].nat    = nat2;
1869 +                break;
1870 +        default:
1871 +                return false;
1872 +        }
1873 +
1874 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1875 +                ia64_operand_t const & op = inst->operands[i];
1876 +                if (!op.commit)
1877 +                        continue;
1878 +                if (op.index == -1)
1879 +                        return false; // XXX: internal error
1880 +                IA64_SET_GR(op.index, op.value, op.nat);
1881 +        }
1882 +        return true;
1883 + }
1884 +
1885 + static bool ia64_emulate_instruction(uint64_t raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1886 + {
1887 +        ia64_instruction_t inst;
1888 +        memset(&inst, 0, sizeof(inst));
1889 +        inst.inst = raw_inst;
1890 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1891 +                return false;
1892 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1893 + }
1894 +
1895 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1896 + {
1897 +        uint64_t ip = IA64_GET_IP();
1898 + #if DEBUG
1899 +        printf("IP: 0x%016llx\n", ip);
1900 + #if 0
1901 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1902 +        ia64_get_instruction(ip, 0);
1903 +        ia64_get_instruction(ip, 1);
1904 +        ia64_get_instruction(ip, 2);
1905 + #endif
1906 + #endif
1907 +
1908 +        // Select which decode switch to use
1909 +        ia64_instruction_t inst;
1910 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1911 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1912 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1913 +                return false;
1914 +        }
1915 +
1916 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1917 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1918 +
1919 +        switch (inst.mnemo) {
1920 +        case IA64_INST_LD1:
1921 +        case IA64_INST_LD2:
1922 +        case IA64_INST_LD4:
1923 +        case IA64_INST_LD8:
1924 +        case IA64_INST_LD1_UPDATE:
1925 +        case IA64_INST_LD2_UPDATE:
1926 +        case IA64_INST_LD4_UPDATE:
1927 +        case IA64_INST_LD8_UPDATE:
1928 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1929 +                break;
1930 +        case IA64_INST_ST1:
1931 +        case IA64_INST_ST2:
1932 +        case IA64_INST_ST4:
1933 +        case IA64_INST_ST8:
1934 +        case IA64_INST_ST1_UPDATE:
1935 +        case IA64_INST_ST2_UPDATE:
1936 +        case IA64_INST_ST4_UPDATE:
1937 +        case IA64_INST_ST8_UPDATE:
1938 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1939 +                break;
1940 +        }
1941 +
1942 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1943 +                // Unknown machine code, let it crash. Then patch the decoder
1944 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1945 +                return false;
1946 +        }
1947 +
1948 +        switch (inst.mnemo) {
1949 +        case IA64_INST_LD1:
1950 +        case IA64_INST_LD1_UPDATE:
1951 +        case IA64_INST_ST1:
1952 +        case IA64_INST_ST1_UPDATE:
1953 +                transfer_size = SIZE_BYTE;
1954 +                break;
1955 +        case IA64_INST_LD2:
1956 +        case IA64_INST_LD2_UPDATE:
1957 +        case IA64_INST_ST2:
1958 +        case IA64_INST_ST2_UPDATE:
1959 +                transfer_size = SIZE_WORD;
1960 +                break;
1961 +        case IA64_INST_LD4:
1962 +        case IA64_INST_LD4_UPDATE:
1963 +        case IA64_INST_ST4:
1964 +        case IA64_INST_ST4_UPDATE:
1965 +                transfer_size = SIZE_LONG;
1966 +                break;
1967 +        case IA64_INST_LD8:
1968 +        case IA64_INST_LD8_UPDATE:
1969 +        case IA64_INST_ST8:
1970 +        case IA64_INST_ST8_UPDATE:
1971 +                transfer_size = SIZE_QUAD;
1972 +                break;
1973 +        }
1974 +
1975 +        if (transfer_size == SIZE_UNKNOWN) {
1976 +                // Unknown machine code, let it crash. Then patch the decoder
1977 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1978 +                return false;
1979 +        }
1980 +
1981 +        inst.no_memory = true;
1982 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1983 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1984 +                return false;
1985 +        }
1986 +
1987 +        int slot = ip & 3;
1988 +        bool emulate_next = false;
1989 +        switch (slot) {
1990 +        case 0:
1991 +                switch (ia64_get_template(ip)) {
1992 +                case 0x2: // MI;I
1993 +                case 0x3: // MI;I;
1994 +                        emulate_next = true;
1995 +                        slot = 2;
1996 +                        break;
1997 +                case 0xa: // M;MI
1998 +                case 0xb: // M;MI;
1999 +                        emulate_next = true;
2000 +                        slot = 1;
2001 +                        break;
2002 +                }
2003 +                break;
2004 +        }
2005 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
2006 +                while (slot < 3) {
2007 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
2008 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
2009 +                                return false;
2010 +                        }
2011 +                        ++slot;
2012 +                }
2013 +        }
2014 +
2015 + #if IA64_CAN_PATCH_IP_SLOT
2016 +        if ((slot = ip & 3) < 2)
2017 +                IA64_SET_IP((ip & ~3ull) + (slot + 1));
2018 +        else
2019 + #endif
2020 +                IA64_SET_IP((ip & ~3ull) + 16);
2021 + #if DEBUG
2022 +        printf("IP: 0x%016llx\n", IA64_GET_IP());
2023 + #endif
2024 +        return true;
2025 + }
2026 + #endif
2027 +
2028   // Decode and skip PPC instruction
2029 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
2029 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
2030   static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
2031   {
2032          instruction_t instr;
# Line 1047 | Line 2062 | static bool powerpc_skip_instruction(uns
2062  
2063   // Decode and skip MIPS instruction
2064   #if (defined(mips) || defined(__mips))
2065 < enum {
1051 < #if (defined(sgi) || defined(__sgi))
1052 <  MIPS_REG_EPC = 35,
1053 < #endif
1054 < };
1055 < static bool mips_skip_instruction(greg_t * regs)
2065 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
2066   {
2067 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
2067 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
2068  
2069    if (epc == 0)
2070          return false;
# Line 1203 | Line 2213 | static bool mips_skip_instruction(greg_t
2213                   mips_gpr_names[reg]);
2214   #endif
2215  
2216 <  regs[MIPS_REG_EPC] += 4;
2216 >  *pc_p += 4;
2217    return true;
2218   }
2219   #endif
# Line 1215 | Line 2225 | enum {
2225    SPARC_REG_G1 = REG_G1,
2226    SPARC_REG_O0 = REG_O0,
2227    SPARC_REG_PC = REG_PC,
2228 +  SPARC_REG_nPC = REG_nPC
2229   #endif
2230   };
2231   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1278 | Line 2289 | static bool sparc_skip_instruction(unsig
2289          break;
2290    case 7: // Store Doubleword
2291          transfer_type = SIGSEGV_TRANSFER_STORE;
2292 <        transfer_size = SIZE_WORD;
2292 >        transfer_size = SIZE_LONG;
2293          register_pair = true;
2294          break;
2295    }
# Line 1288 | Line 2299 | static bool sparc_skip_instruction(unsig
2299          return false;
2300    }
2301  
1291  // Zero target register in case of a load operation
2302    const int reg = (opcode >> 25) & 0x1f;
2303 +
2304 + #if DEBUG
2305 +  static const char * reg_names[] = {
2306 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2307 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2308 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2309 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2310 +  };
2311 +  printf("%s %s register %s\n",
2312 +                 transfer_size == SIZE_BYTE ? "byte" :
2313 +                 transfer_size == SIZE_WORD ? "word" :
2314 +                 transfer_size == SIZE_LONG ? "long" :
2315 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2316 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2317 +                 reg_names[reg]);
2318 + #endif
2319 +
2320 +  // Zero target register in case of a load operation
2321    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2322          // FIXME: code to handle local & input registers is not tested
2323 <        if (reg >= 1 && reg <= 7) {
2323 >        if (reg >= 1 && reg < 8) {
2324            // global registers
2325            regs[reg - 1 + SPARC_REG_G1] = 0;
2326          }
2327 <        else if (reg >= 8 && reg <= 15) {
2327 >        else if (reg >= 8 && reg < 16) {
2328            // output registers
2329            regs[reg - 8 + SPARC_REG_O0] = 0;
2330          }
2331 <        else if (reg >= 16 && reg <= 23) {
2331 >        else if (reg >= 16 && reg < 24) {
2332            // local registers (in register windows)
2333            if (gwins)
2334                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1316 | Line 2344 | static bool sparc_skip_instruction(unsig
2344          }
2345    }
2346  
1319 #if DEBUG
1320  static const char * reg_names[] = {
1321        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1322        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1323        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1324        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1325  };
1326  printf("%s %s register %s\n",
1327                 transfer_size == SIZE_BYTE ? "byte" :
1328                 transfer_size == SIZE_WORD ? "word" :
1329                 transfer_size == SIZE_LONG ? "long" :
1330                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1331                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1332                 reg_names[reg]);
1333 #endif
1334
2347    regs[SPARC_REG_PC] += 4;
2348 +  regs[SPARC_REG_nPC] += 4;
2349    return true;
2350   }
2351   #endif
# Line 1488 | Line 2501 | static bool arm_skip_instruction(unsigne
2501  
2502  
2503   // Fallbacks
2504 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2505 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2506 + #endif
2507 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2508 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2509 + #endif
2510   #ifndef SIGSEGV_FAULT_INSTRUCTION
2511 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2511 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2512   #endif
2513   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2514   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2515   #endif
2516   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2517 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2517 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2518   #endif
2519  
2520   // SIGSEGV recovery supported ?
# Line 1508 | Line 2527 | static bool arm_skip_instruction(unsigne
2527   *  SIGSEGV global handler
2528   */
2529  
2530 + struct sigsegv_info_t {
2531 +        sigsegv_address_t addr;
2532 +        sigsegv_address_t pc;
2533 + #ifdef HAVE_MACH_EXCEPTIONS
2534 +        mach_port_t thread;
2535 +        bool has_exc_state;
2536 +        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2537 +        mach_msg_type_number_t exc_state_count;
2538 +        bool has_thr_state;
2539 +        SIGSEGV_THREAD_STATE_TYPE thr_state;
2540 +        mach_msg_type_number_t thr_state_count;
2541 + #endif
2542 + };
2543 +
2544 + #ifdef HAVE_MACH_EXCEPTIONS
2545 + static void mach_get_exception_state(sigsegv_info_t *SIP)
2546 + {
2547 +        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2548 +        kern_return_t krc = thread_get_state(SIP->thread,
2549 +                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2550 +                                                                                 (natural_t *)&SIP->exc_state,
2551 +                                                                                 &SIP->exc_state_count);
2552 +        MACH_CHECK_ERROR(thread_get_state, krc);
2553 +        SIP->has_exc_state = true;
2554 + }
2555 +
2556 + static void mach_get_thread_state(sigsegv_info_t *SIP)
2557 + {
2558 +        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2559 +        kern_return_t krc = thread_get_state(SIP->thread,
2560 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2561 +                                                                                 (natural_t *)&SIP->thr_state,
2562 +                                                                                 &SIP->thr_state_count);
2563 +        MACH_CHECK_ERROR(thread_get_state, krc);
2564 +        SIP->has_thr_state = true;
2565 + }
2566 +
2567 + static void mach_set_thread_state(sigsegv_info_t *SIP)
2568 + {
2569 +        kern_return_t krc = thread_set_state(SIP->thread,
2570 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2571 +                                                                                 (natural_t *)&SIP->thr_state,
2572 +                                                                                 SIP->thr_state_count);
2573 +        MACH_CHECK_ERROR(thread_set_state, krc);
2574 + }
2575 + #endif
2576 +
2577 + // Return the address of the invalid memory reference
2578 + sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2579 + {
2580 + #ifdef HAVE_MACH_EXCEPTIONS
2581 +        static int use_fast_path = -1;
2582 +        if (use_fast_path != 1 && !SIP->has_exc_state) {
2583 +                mach_get_exception_state(SIP);
2584 +
2585 +                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2586 +                if (use_fast_path < 0) {
2587 +                        const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2588 +                        if (machfault) {
2589 +                                if (strcmp(machfault, "fast") == 0)
2590 +                                        use_fast_path = 1;
2591 +                                else if (strcmp(machfault, "slow") == 0)
2592 +                                        use_fast_path = 0;
2593 +                        }
2594 +                        if (use_fast_path < 0)
2595 +                                use_fast_path = addr == SIP->addr;
2596 +                }
2597 +                SIP->addr = addr;
2598 +        }
2599 + #endif
2600 +        return SIP->addr;
2601 + }
2602 +
2603 + // Return the address of the instruction that caused the fault, or
2604 + // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2605 + sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2606 + {
2607 + #ifdef HAVE_MACH_EXCEPTIONS
2608 +        if (!SIP->has_thr_state) {
2609 +                mach_get_thread_state(SIP);
2610 +
2611 +                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2612 +        }
2613 + #endif
2614 +        return SIP->pc;
2615 + }
2616 +
2617   // This function handles the badaccess to memory.
2618   // It is called from the signal handler or the exception handler.
2619   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2620   {
2621 <        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2622 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2623 <        
2621 >        sigsegv_info_t SI;
2622 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2623 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2624 > #ifdef HAVE_MACH_EXCEPTIONS
2625 >        SI.thread = thread;
2626 >        SI.has_exc_state = false;
2627 >        SI.has_thr_state = false;
2628 > #endif
2629 >        sigsegv_info_t * const SIP = &SI;
2630 >
2631          // Call user's handler and reinstall the global handler, if required
2632 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2632 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2633          case SIGSEGV_RETURN_SUCCESS:
2634                  return true;
2635  
# Line 1524 | Line 2637 | static bool handle_badaccess(SIGSEGV_FAU
2637          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2638                  // Call the instruction skipper with the register file
2639                  // available
2640 + #ifdef HAVE_MACH_EXCEPTIONS
2641 +                if (!SIP->has_thr_state)
2642 +                        mach_get_thread_state(SIP);
2643 + #endif
2644                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2645   #ifdef HAVE_MACH_EXCEPTIONS
2646                          // Unlike UNIX signals where the thread state
2647                          // is modified off of the stack, in Mach we
2648                          // need to actually call thread_set_state to
2649                          // have the register values updated.
2650 <                        kern_return_t krc;
1534 <
1535 <                        krc = thread_set_state(thread,
1536 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1537 <                                                                   MACHINE_THREAD_STATE_COUNT);
1538 <                        MACH_CHECK_ERROR (thread_get_state, krc);
2650 >                        mach_set_thread_state(SIP);
2651   #endif
2652                          return true;
2653                  }
# Line 1544 | Line 2656 | static bool handle_badaccess(SIGSEGV_FAU
2656          case SIGSEGV_RETURN_FAILURE:
2657                  // We can't do anything with the fault_address, dump state?
2658                  if (sigsegv_state_dumper != 0)
2659 <                        sigsegv_state_dumper(fault_address, fault_instruction);
2659 >                        sigsegv_state_dumper(SIP);
2660                  break;
2661          }
2662  
# Line 1586 | Line 2698 | forward_exception(mach_port_t thread_por
2698          mach_port_t port;
2699          exception_behavior_t behavior;
2700          thread_state_flavor_t flavor;
2701 <        thread_state_t thread_state;
2701 >        thread_state_data_t thread_state;
2702          mach_msg_type_number_t thread_state_count;
2703  
2704          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1605 | Line 2717 | forward_exception(mach_port_t thread_por
2717          behavior = oldExceptionPorts->behaviors[portIndex];
2718          flavor = oldExceptionPorts->flavors[portIndex];
2719  
2720 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2721 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2722 +                return KERN_FAILURE;
2723 +        }
2724 +
2725          /*
2726           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2727           */
2728  
2729          if (behavior != EXCEPTION_DEFAULT) {
2730                  thread_state_count = THREAD_STATE_MAX;
2731 <                kret = thread_get_state (thread_port, flavor, thread_state,
2731 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2732                                                                   &thread_state_count);
2733                  MACH_CHECK_ERROR (thread_get_state, kret);
2734          }
# Line 1627 | Line 2744 | forward_exception(mach_port_t thread_por
2744            // fprintf(stderr, "forwarding to exception_raise_state\n");
2745            kret = exception_raise_state(port, exception_type, exception_data,
2746                                                                     data_count, &flavor,
2747 <                                                                   thread_state, thread_state_count,
2748 <                                                                   thread_state, &thread_state_count);
2747 >                                                                   (natural_t *)&thread_state, thread_state_count,
2748 >                                                                   (natural_t *)&thread_state, &thread_state_count);
2749            MACH_CHECK_ERROR (exception_raise_state, kret);
2750            break;
2751          case EXCEPTION_STATE_IDENTITY:
# Line 1636 | Line 2753 | forward_exception(mach_port_t thread_por
2753            kret = exception_raise_state_identity(port, thread_port, task_port,
2754                                                                                          exception_type, exception_data,
2755                                                                                          data_count, &flavor,
2756 <                                                                                        thread_state, thread_state_count,
2757 <                                                                                        thread_state, &thread_state_count);
2756 >                                                                                        (natural_t *)&thread_state, thread_state_count,
2757 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
2758            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2759            break;
2760          default:
2761            fprintf(stderr, "forward_exception got unknown behavior\n");
2762 +          kret = KERN_FAILURE;
2763            break;
2764          }
2765  
2766          if (behavior != EXCEPTION_DEFAULT) {
2767 <                kret = thread_set_state (thread_port, flavor, thread_state,
2767 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2768                                                                   thread_state_count);
2769                  MACH_CHECK_ERROR (thread_set_state, kret);
2770          }
2771  
2772 <        return KERN_SUCCESS;
2772 >        return kret;
2773   }
2774  
2775   /*
# Line 1679 | Line 2797 | catch_exception_raise(mach_port_t except
2797                                            mach_port_t task,
2798                                            exception_type_t exception,
2799                                            exception_data_t code,
2800 <                                          mach_msg_type_number_t codeCount)
2800 >                                          mach_msg_type_number_t code_count)
2801   {
1684        ppc_thread_state_t state;
2802          kern_return_t krc;
2803  
2804 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2805 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2806 <                        return KERN_SUCCESS;
2804 >        if (exception == EXC_BAD_ACCESS) {
2805 >                switch (code[0]) {
2806 >                case KERN_PROTECTION_FAILURE:
2807 >                case KERN_INVALID_ADDRESS:
2808 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2809 >                                return KERN_SUCCESS;
2810 >                        break;
2811 >                }
2812          }
2813  
2814          // In Mach we do not need to remove the exception handler.
2815          // If we forward the exception, eventually some exception handler
2816          // will take care of this exception.
2817 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2817 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2818  
2819          return krc;
2820   }
# Line 1820 | Line 2942 | static bool sigsegv_do_install_handler(s
2942          // addressing modes) used in PPC instructions, you will need the
2943          // GPR state anyway.
2944          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2945 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2945 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2946          if (krc != KERN_SUCCESS) {
2947                  mach_error("thread_set_exception_ports", krc);
2948                  return false;
# Line 2000 | Line 3122 | void sigsegv_set_dump_state(sigsegv_stat
3122   const int REF_INDEX = 123;
3123   const int REF_VALUE = 45;
3124  
3125 < static int page_size;
3125 > static sigsegv_uintptr_t page_size;
3126   static volatile char * page = 0;
3127   static volatile int handler_called = 0;
3128  
3129 + /* Barriers */
3130 + #ifdef __GNUC__
3131 + #define BARRIER() asm volatile ("" : : : "memory")
3132 + #else
3133 + #define BARRIER() /* nothing */
3134 + #endif
3135 +
3136   #ifdef __GNUC__
3137   // Code range where we expect the fault to come from
3138   static void *b_region, *e_region;
3139   #endif
3140  
3141 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3141 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3142   {
3143 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3144 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3145   #if DEBUG
3146          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3147          printf("expected fault at %p\n", page + REF_INDEX);
# Line 2024 | Line 3155 | static sigsegv_return_t sigsegv_test_han
3155   #ifdef __GNUC__
3156          // Make sure reported fault instruction address falls into
3157          // expected code range
3158 <        if (instruction_address != SIGSEGV_INVALID_PC
3158 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3159                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3160                          (instruction_address >= (sigsegv_address_t)e_region)))
3161                  exit(11);
3162   #endif
3163 <        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3163 >        if (vm_protect((char *)((sigsegv_uintptr_t)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3164                  exit(12);
3165          return SIGSEGV_RETURN_SUCCESS;
3166   }
3167  
3168   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3169 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3169 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3170   {
3171 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3172 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3173   #if DEBUG
3174          printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3175   #endif
3176 <        if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3176 >        if (((sigsegv_uintptr_t)fault_address - (sigsegv_uintptr_t)page) < page_size) {
3177   #ifdef __GNUC__
3178                  // Make sure reported fault instruction address falls into
3179                  // expected code range
3180 <                if (instruction_address != SIGSEGV_INVALID_PC
3180 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3181                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3182                                  (instruction_address >= (sigsegv_address_t)e_region)))
3183                          return SIGSEGV_RETURN_FAILURE;
# Line 2058 | Line 3191 | static sigsegv_return_t sigsegv_insn_han
3191   // More sophisticated tests for instruction skipper
3192   static bool arch_insn_skipper_tests()
3193   {
3194 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3194 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
3195          static const unsigned char code[] = {
3196                  0x8a, 0x00,                    // mov    (%eax),%al
3197                  0x8a, 0x2c, 0x18,              // mov    (%eax,%ebx,1),%ch
# Line 2072 | Line 3205 | static bool arch_insn_skipper_tests()
3205                  0x8b, 0x0c, 0x18,              // mov    (%eax,%ebx,1),%ecx
3206                  0x89, 0x00,                    // mov    %eax,(%eax)
3207                  0x89, 0x0c, 0x18,              // mov    %ecx,(%eax,%ebx,1)
3208 < #if defined(__x86_64__)
3208 > #if defined(__x86_64__) || defined(_M_X64)
3209                  0x44, 0x8a, 0x00,              // mov    (%rax),%r8b
3210                  0x44, 0x8a, 0x20,              // mov    (%rax),%r12b
3211                  0x42, 0x8a, 0x3c, 0x10,        // mov    (%rax,%r10,1),%dil
# Line 2095 | Line 3228 | static bool arch_insn_skipper_tests()
3228                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3229                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3230                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3231 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3232 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3233   #endif
3234                  0                              // end
3235          };
3236          const int N_REGS = 20;
3237 <        unsigned long regs[N_REGS];
3237 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3238          for (int i = 0; i < N_REGS; i++)
3239                  regs[i] = i;
3240 <        const unsigned long start_code = (unsigned long)&code;
3240 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3241          regs[X86_REG_EIP] = start_code;
3242          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3243                     && ix86_skip_instruction(regs))
# Line 2118 | Line 3253 | int main(void)
3253          if (vm_init() < 0)
3254                  return 1;
3255  
3256 < #ifdef _WIN32
2122 <        page_size = 4096;
2123 < #else
2124 <        page_size = getpagesize();
2125 < #endif
3256 >        page_size = vm_get_page_size();
3257          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3258                  return 2;
3259          
# Line 2132 | Line 3263 | int main(void)
3263          
3264          if (!sigsegv_install_handler(sigsegv_test_handler))
3265                  return 4;
3266 <        
3266 >
3267   #ifdef __GNUC__
3268          b_region = &&L_b_region1;
3269          e_region = &&L_e_region1;
3270   #endif
3271 < L_b_region1:
3272 <        page[REF_INDEX] = REF_VALUE;
3273 <        if (page[REF_INDEX] != REF_VALUE)
3274 <          exit(20);
3275 <        page[REF_INDEX] = REF_VALUE;
3276 < L_e_region1:
3271 >        /* This is a really awful hack but otherwise gcc is smart enough
3272 >         * (or bug'ous enough?) to optimize the labels and place them
3273 >         * e.g. at the "main" entry point, which is wrong.
3274 >         */
3275 >        volatile int label_hack = 1;
3276 >        switch (label_hack) {
3277 >        case 1:
3278 >        L_b_region1:
3279 >                page[REF_INDEX] = REF_VALUE;
3280 >                if (page[REF_INDEX] != REF_VALUE)
3281 >                        exit(20);
3282 >                page[REF_INDEX] = REF_VALUE;
3283 >                BARRIER();
3284 >                // fall-through
3285 >        case 2:
3286 >        L_e_region1:
3287 >                BARRIER();
3288 >                break;
3289 >        }
3290  
3291          if (handler_called != 1)
3292                  return 5;
# Line 2173 | Line 3317 | int main(void)
3317          b_region = &&L_b_region2;
3318          e_region = &&L_e_region2;
3319   #endif
3320 < L_b_region2:
3321 <        TEST_SKIP_INSTRUCTION(unsigned char);
3322 <        TEST_SKIP_INSTRUCTION(unsigned short);
3323 <        TEST_SKIP_INSTRUCTION(unsigned int);
3324 <        TEST_SKIP_INSTRUCTION(unsigned long);
3325 <        TEST_SKIP_INSTRUCTION(signed char);
3326 <        TEST_SKIP_INSTRUCTION(signed short);
3327 <        TEST_SKIP_INSTRUCTION(signed int);
3328 <        TEST_SKIP_INSTRUCTION(signed long);
3329 < L_e_region2:
3330 <
3320 >        switch (label_hack) {
3321 >        case 1:
3322 >        L_b_region2:
3323 >                TEST_SKIP_INSTRUCTION(unsigned char);
3324 >                TEST_SKIP_INSTRUCTION(unsigned short);
3325 >                TEST_SKIP_INSTRUCTION(unsigned int);
3326 >                TEST_SKIP_INSTRUCTION(unsigned long);
3327 >                TEST_SKIP_INSTRUCTION(signed char);
3328 >                TEST_SKIP_INSTRUCTION(signed short);
3329 >                TEST_SKIP_INSTRUCTION(signed int);
3330 >                TEST_SKIP_INSTRUCTION(signed long);
3331 >                BARRIER();
3332 >                // fall-through
3333 >        case 2:
3334 >        L_e_region2:
3335 >                BARRIER();
3336 >                break;
3337 >        }
3338          if (!arch_insn_skipper_tests())
3339                  return 20;
3340   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines