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.84 by gbeauche, 2008-01-20T17:09:34Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines