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.65 by gbeauche, 2007-06-05T13:15:57Z vs.
Revision 1.83 by gbeauche, 2008-01-20T00:39:51Z

# Line 10 | Line 10
10   *    tjw@omnigroup.com Sun, 4 Jun 2000
11   *    www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html
12   *
13 < *  Basilisk II (C) 1997-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 70 | Line 81 | static bool sigsegv_do_install_handler(i
81   enum transfer_type_t {
82          SIGSEGV_TRANSFER_UNKNOWN        = 0,
83          SIGSEGV_TRANSFER_LOAD           = 1,
84 <        SIGSEGV_TRANSFER_STORE          = 2,
84 >        SIGSEGV_TRANSFER_STORE          = 2
85   };
86  
87   // Transfer size
# Line 79 | Line 90 | enum transfer_size_t {
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 < #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 232 | 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 264 | Line 277 | static void powerpc_decode_instruction(i
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                   (unsigned long *)SIGSEGV_CONTEXT_REGS
280 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
281   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
282   #endif
283   #endif
284   #if defined(__FreeBSD__) || defined(__OpenBSD__)
285   #if (defined(i386) || defined(__i386__))
286   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
287 < #define SIGSEGV_REGISTER_FILE                   ((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 280 | 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__))
# Line 296 | Line 309 | static void powerpc_decode_instruction(i
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 335 | Line 351 | static void powerpc_decode_instruction(i
351   #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
352   #endif
353   #endif
354 + #if (defined(__hpux) || defined(__hpux__))
355 + #if (defined(__hppa) || defined(__hppa__))
356 + #define SIGSEGV_CONTEXT_REGS                    (&((ucontext_t *)scp)->uc_mcontext)
357 + #define SIGSEGV_FAULT_INSTRUCTION_32    (SIGSEGV_CONTEXT_REGS->ss_narrow.ss_pcoq_head & ~3ul)
358 + #define SIGSEGV_FAULT_INSTRUCTION_64    (SIGSEGV_CONTEXT_REGS->ss_wide.ss_64.ss_pcoq_head & ~3ull)
359 + #if defined(__LP64__)
360 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_FAULT_INSTRUCTION_64
361 + #else
362 + #define SIGSEGV_FAULT_INSTRUCTION               ((SIGSEGV_CONTEXT_REGS->ss_flags & SS_WIDEREGS) ? \
363 +                                                                                 (uint32_t)SIGSEGV_FAULT_INSTRUCTION_64 : \
364 +                                                                                 SIGSEGV_FAULT_INSTRUCTION_32)
365 + #endif
366 + #endif
367 + #if (defined(__ia64) || defined(__ia64__))
368 + #include <sys/ucontext.h>
369 + #define SIGSEGV_CONTEXT_REGS                    ((ucontext_t *)scp)
370 + #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(SIGSEGV_CONTEXT_REGS)
371 + #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
372 + #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
373 +
374 + #include <sys/uc_access.h>
375 + static inline sigsegv_address_t get_fault_instruction(const ucontext_t *ucp)
376 + {
377 +  uint64_t ip;
378 +  if (__uc_get_ip(ucp, &ip) != 0)
379 +        return SIGSEGV_INVALID_ADDRESS;
380 +  return (sigsegv_address_t)(ip & ~3ULL);
381 + }
382 + #endif
383 + #endif
384   #endif
385  
386   #if HAVE_SIGCONTEXT_SUBTERFUGE
# Line 348 | 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 469 | 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 532 | Line 578 | static sigsegv_address_t get_fault_addre
578   #include <windows.h>
579   #include <winerror.h>
580  
581 + #if defined(_M_IX86)
582   #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
583   #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
584   #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
585   #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
586   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Eip
587 < #define SIGSEGV_REGISTER_FILE                   ((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_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
592 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
593 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
594 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
595 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Rip
596 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax)
597 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
598 + #endif
599 + #endif
600  
601   #if HAVE_MACH_EXCEPTIONS
602  
# Line 602 | Line 659 | if (ret != KERN_SUCCESS) { \
659   }
660  
661   #ifdef __ppc__
662 + #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE
663 + #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
664 + #endif
665 + #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
666 + #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
667 + #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
668 + #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
669   #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
670   #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
671   #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
672 < #define SIGSEGV_FAULT_INSTRUCTION               state->srr0
672 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
673   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
674 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&state->srr0, (unsigned long *)&state->r0
674 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
675 > #endif
676 > #ifdef __ppc64__
677 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE64
678 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
679 > #endif
680 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
681 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
682 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
683 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
684 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
685 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
686 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
687 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
688 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
689 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
690   #endif
691   #ifdef __i386__
692 < #ifdef i386_SAVED_STATE
693 < #define SIGSEGV_THREAD_STATE_TYPE               struct i386_saved_state
694 < #define SIGSEGV_THREAD_STATE_FLAVOR             i386_SAVED_STATE
695 < #define SIGSEGV_THREAD_STATE_COUNT              i386_SAVED_STATE_COUNT
696 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state->edi) /* EDI is the first GPR we consider */
697 < #else
698 < #define SIGSEGV_THREAD_STATE_TYPE               struct i386_thread_state
692 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE32
693 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
694 > #endif
695 > #define SIGSEGV_EXCEPTION_STATE_TYPE    i386_exception_state_t
696 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
697 > #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
698 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
699 > #define SIGSEGV_THREAD_STATE_TYPE               i386_thread_state_t
700   #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
701   #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
702 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state->eax) /* EAX is the first GPR we consider */
702 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(eip)
703 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
704 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(eax)) /* EAX is the first GPR we consider */
705   #endif
706 < #define SIGSEGV_FAULT_INSTRUCTION               state->eip
706 > #ifdef __x86_64__
707 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE64
708 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
709 > #endif
710 > #define SIGSEGV_EXCEPTION_STATE_TYPE    x86_exception_state64_t
711 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
712 > #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
713 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
714 > #define SIGSEGV_THREAD_STATE_TYPE               x86_thread_state64_t
715 > #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
716 > #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
717 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(rip)
718   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
719 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(rax)) /* RAX is the first GPR we consider */
720 + #endif
721 + #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
722 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
723 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
724 + #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
725 +
726 + #ifndef MACH_FIELD_NAME
727 + #define MACH_FIELD_NAME(X) X
728   #endif
627 #define SIGSEGV_FAULT_ADDRESS                   code[1]
628 #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE || code[0] == KERN_INVALID_ADDRESS) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
629 #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, SIGSEGV_THREAD_STATE_TYPE *state
630 #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
729  
730   // Since there can only be one exception thread running at any time
731   // this is not a problem.
# Line 680 | Line 778 | handleExceptions(void *priv)
778   *  Instruction skipping
779   */
780  
781 + #ifndef SIGSEGV_REGISTER_TYPE
782 + #define SIGSEGV_REGISTER_TYPE sigsegv_uintptr_t
783 + #endif
784 +
785   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
786   // Decode and skip X86 instruction
787 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
787 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
788   #if defined(__linux__)
789   enum {
790   #if (defined(i386) || defined(__i386__))
# Line 785 | Line 887 | enum {
887   #endif
888   #if defined(__APPLE__) && defined(__MACH__)
889   enum {
890 + #if (defined(i386) || defined(__i386__))
891   #ifdef i386_SAVED_STATE
892          // same as FreeBSD (in Open Darwin 8.0.1)
893          X86_REG_EIP = 10,
# Line 801 | Line 904 | enum {
904          X86_REG_EIP = 10,
905          X86_REG_EAX = 0,
906          X86_REG_ECX = 2,
907 <        X86_REG_EDX = 4,
907 >        X86_REG_EDX = 3,
908          X86_REG_EBX = 1,
909          X86_REG_ESP = 7,
910          X86_REG_EBP = 6,
911          X86_REG_ESI = 5,
912          X86_REG_EDI = 4
913   #endif
914 + #endif
915 + #if defined(__x86_64__)
916 +        X86_REG_R8  = 8,
917 +        X86_REG_R9  = 9,
918 +        X86_REG_R10 = 10,
919 +        X86_REG_R11 = 11,
920 +        X86_REG_R12 = 12,
921 +        X86_REG_R13 = 13,
922 +        X86_REG_R14 = 14,
923 +        X86_REG_R15 = 15,
924 +        X86_REG_EDI = 4,
925 +        X86_REG_ESI = 5,
926 +        X86_REG_EBP = 6,
927 +        X86_REG_EBX = 1,
928 +        X86_REG_EDX = 3,
929 +        X86_REG_EAX = 0,
930 +        X86_REG_ECX = 2,
931 +        X86_REG_ESP = 7,
932 +        X86_REG_EIP = 16
933 + #endif
934   };
935   #endif
936   #if defined(_WIN32)
937   enum {
938 < #if (defined(i386) || defined(__i386__))
938 > #if defined(_M_IX86)
939          X86_REG_EIP = 7,
940          X86_REG_EAX = 5,
941          X86_REG_ECX = 4,
# Line 823 | Line 946 | enum {
946          X86_REG_ESI = 1,
947          X86_REG_EDI = 0
948   #endif
949 + #if defined(_M_X64)
950 +        X86_REG_EAX = 0,
951 +        X86_REG_ECX = 1,
952 +        X86_REG_EDX = 2,
953 +        X86_REG_EBX = 3,
954 +        X86_REG_ESP = 4,
955 +        X86_REG_EBP = 5,
956 +        X86_REG_ESI = 6,
957 +        X86_REG_EDI = 7,
958 +        X86_REG_R8  = 8,
959 +        X86_REG_R9  = 9,
960 +        X86_REG_R10 = 10,
961 +        X86_REG_R11 = 11,
962 +        X86_REG_R12 = 12,
963 +        X86_REG_R13 = 13,
964 +        X86_REG_R14 = 14,
965 +        X86_REG_R15 = 15,
966 +        X86_REG_EIP = 16
967 + #endif
968   };
969   #endif
970   // FIXME: this is partly redundant with the instruction decoding phase
# Line 859 | Line 1001 | static inline int ix86_step_over_modrm(u
1001          return offset;
1002   }
1003  
1004 < static bool ix86_skip_instruction(unsigned long * regs)
1004 > static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs)
1005   {
1006          unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
1007  
# Line 895 | Line 1037 | static bool ix86_skip_instruction(unsign
1037          }
1038  
1039          // REX prefix
1040 < #if defined(__x86_64__)
1040 > #if defined(__x86_64__) || defined(_M_X64)
1041          struct rex_t {
1042                  unsigned char W;
1043                  unsigned char R;
# Line 947 | Line 1089 | static bool ix86_skip_instruction(unsign
1089                          goto do_transfer_load;
1090                  }
1091                  break;
1092 < #if defined(__x86_64__)
1092 > #if defined(__x86_64__) || defined(_M_X64)
1093          case 0x63: // MOVSXD r64, r/m32
1094                  if (has_rex && rex.W) {
1095                          transfer_size = SIZE_LONG;
# Line 1018 | Line 1160 | static bool ix86_skip_instruction(unsign
1160                  return false;
1161          }
1162  
1163 < #if defined(__x86_64__)
1163 > #if defined(__x86_64__) || defined(_M_X64)
1164          if (rex.R)
1165                  reg += 8;
1166   #endif
# Line 1027 | Line 1169 | static bool ix86_skip_instruction(unsign
1169                  static const int x86_reg_map[] = {
1170                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1171                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1172 < #if defined(__x86_64__)
1172 > #if defined(__x86_64__) || defined(_M_X64)
1173                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1174                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1175   #endif
# Line 1114 | Line 1256 | static bool ix86_skip_instruction(unsign
1256   }
1257   #endif
1258  
1259 + // Decode and skip IA-64 instruction
1260 + #if defined(__ia64) || defined(__ia64__)
1261 + typedef uint64_t ia64_bundle_t[2];
1262 + #if defined(__linux__)
1263 + // We can directly patch the slot number
1264 + #define IA64_CAN_PATCH_IP_SLOT  1
1265 + // Helper macros to access the machine context
1266 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1267 + #define IA64_CONTEXT                    scp
1268 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1269 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1270 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1271 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1272 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1273 + #define _IA64_SET_GR(R,V)               (IA64_CONTEXT->sc_gr[(R)] = (V))
1274 + #define _IA64_SET_NAT(I,V)              (IA64_CONTEXT->sc_nat = (IA64_CONTEXT->sc_nat & ~(1ull << (I))) | (((uint64_t)!!(V)) << (I)))
1275 + #define IA64_SET_GR(R,V,N)              (_IA64_SET_GR(R,V), _IA64_SET_NAT(R,N))
1276 +
1277 + // Load bundle (in little-endian)
1278 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1279 + {
1280 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1281 +        bundle[0] = ip[0];
1282 +        bundle[1] = ip[1];
1283 + }
1284 + #endif
1285 + #if defined(__hpux) || defined(__hpux__)
1286 + // We can directly patch the slot number
1287 + #define IA64_CAN_PATCH_IP_SLOT  1
1288 + // Helper macros to access the machine context
1289 + #define IA64_CONTEXT_TYPE               ucontext_t *
1290 + #define IA64_CONTEXT                    ucp
1291 + #define IA64_GET_IP()                   ia64_get_ip(IA64_CONTEXT)
1292 + #define IA64_SET_IP(V)                  ia64_set_ip(IA64_CONTEXT, V)
1293 + #define IA64_GET_PR(P)                  ia64_get_pr(IA64_CONTEXT, P)
1294 + #define IA64_GET_NAT(I)                 ia64_get_nat(IA64_CONTEXT, I)
1295 + #define IA64_GET_GR(R)                  ia64_get_gr(IA64_CONTEXT, R)
1296 + #define IA64_SET_GR(R,V,N)              ia64_set_gr(IA64_CONTEXT, R, V, N)
1297 + #define UC_ACCESS(FUNC,ARGS)    do { if (__uc_##FUNC ARGS != 0) abort(); } while (0)
1298 +
1299 + static inline uint64_t ia64_get_ip(IA64_CONTEXT_TYPE IA64_CONTEXT)
1300 +        { uint64_t v; UC_ACCESS(get_ip,(IA64_CONTEXT, &v)); return v; }
1301 + static inline void ia64_set_ip(IA64_CONTEXT_TYPE IA64_CONTEXT, uint64_t v)
1302 +        { UC_ACCESS(set_ip,(IA64_CONTEXT, v)); }
1303 + static inline unsigned int ia64_get_pr(IA64_CONTEXT_TYPE IA64_CONTEXT, int pr)
1304 +        { uint64_t v; UC_ACCESS(get_prs,(IA64_CONTEXT, &v)); return (v >> pr) & 1; }
1305 + static inline unsigned int ia64_get_nat(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1306 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return (nat >> r) & 1; }
1307 + static inline uint64_t ia64_get_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1308 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return v; }
1309 +
1310 + static void ia64_set_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r, uint64_t v, unsigned int nat)
1311 + {
1312 +        if (r == 0)
1313 +                return;
1314 +        if (r > 0 && r < 32)
1315 +                UC_ACCESS(set_grs,(IA64_CONTEXT, r, 1, &v, (!!nat) << r));
1316 +        else {
1317 +                uint64_t bsp, bspstore;
1318 +                UC_ACCESS(get_ar_bsp,(IA64_CONTEXT, &bsp));
1319 +                UC_ACCESS(get_ar_bspstore,(IA64_CONTEXT, &bspstore));
1320 +                abort(); /* XXX: use libunwind, this is not fun... */
1321 +        }
1322 + }
1323 +
1324 + // Byte-swapping
1325 + #if defined(__GNUC__)
1326 + #define BSWAP64(V) ({ uint64_t r; __asm__ __volatile__("mux1 %0=%1,@rev;;" : "=r" (r) : "r" (V)); r; })
1327 + #elif defined (__HP_aCC)
1328 + #define BSWAP64(V) _Asm_mux1(_MBTYPE_REV, V)
1329 + #else
1330 + #error "Define byte-swap instruction"
1331 + #endif
1332 +
1333 + // Load bundle (in little-endian)
1334 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1335 + {
1336 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1337 +        bundle[0] = BSWAP64(ip[0]);
1338 +        bundle[1] = BSWAP64(ip[1]);
1339 + }
1340 + #endif
1341 +
1342 + // Instruction operations
1343 + enum {
1344 +        IA64_INST_UNKNOWN = 0,
1345 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1346 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1347 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1348 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1349 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1350 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1351 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1352 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1353 +        IA64_INST_ST1,                          // st1 [op0]=op1
1354 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1355 +        IA64_INST_ST2,                          // st2 [op0]=op1
1356 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1357 +        IA64_INST_ST4,                          // st4 [op0]=op1
1358 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1359 +        IA64_INST_ST8,                          // st8 [op0]=op1
1360 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1361 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1362 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1363 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1364 +        IA64_INST_AND,                          // and op0=op1,op2
1365 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1366 +        IA64_INST_OR,                           // or op0=op1,op2
1367 +        IA64_INST_XOR,                          // xor op0=op1,op2
1368 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1369 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1370 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1371 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1372 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1373 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1374 +        IA64_INST_NOP                           // nop op0
1375 + };
1376 +
1377 + const int IA64_N_OPERANDS = 4;
1378 +
1379 + // Decoded operand type
1380 + struct ia64_operand_t {
1381 +        uint8_t commit;                         // commit result of operation to register file?
1382 +        uint8_t valid;                          // XXX: not really used, can be removed (debug)
1383 +        int8_t index;                           // index of GPR, or -1 if immediate value
1384 +        uint8_t nat;                            // NaT state before operation
1385 +        uint64_t value;                         // register contents or immediate value
1386 + };
1387 +
1388 + // Decoded instruction type
1389 + struct ia64_instruction_t {
1390 +        uint8_t mnemo;                          // operation to perform
1391 +        uint8_t pred;                           // predicate register to check
1392 +        uint8_t no_memory;                      // used to emulated main fault instruction
1393 +        uint64_t inst;                          // the raw instruction bits (41-bit wide)
1394 +        ia64_operand_t operands[IA64_N_OPERANDS];
1395 + };
1396 +
1397 + // Get immediate sign-bit
1398 + static inline int ia64_inst_get_sbit(uint64_t inst)
1399 + {
1400 +        return (inst >> 36) & 1;
1401 + }
1402 +
1403 + // Get 8-bit immediate value (A3, A8, I27, M30)
1404 + static inline uint64_t ia64_inst_get_imm8(uint64_t inst)
1405 + {
1406 +        uint64_t value = (inst >> 13) & 0x7full;
1407 +        if (ia64_inst_get_sbit(inst))
1408 +                value |= ~0x7full;
1409 +        return value;
1410 + }
1411 +
1412 + // Get 9-bit immediate value (M3)
1413 + static inline uint64_t ia64_inst_get_imm9b(uint64_t inst)
1414 + {
1415 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1416 +        if (ia64_inst_get_sbit(inst))
1417 +                value |= ~0xffull;
1418 +        return value;
1419 + }
1420 +
1421 + // Get 9-bit immediate value (M5)
1422 + static inline uint64_t ia64_inst_get_imm9a(uint64_t inst)
1423 + {
1424 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1425 +        if (ia64_inst_get_sbit(inst))
1426 +                value |= ~0xffull;
1427 +        return value;
1428 + }
1429 +
1430 + // Get 14-bit immediate value (A4)
1431 + static inline uint64_t ia64_inst_get_imm14(uint64_t inst)
1432 + {
1433 +        uint64_t value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1434 +        if (ia64_inst_get_sbit(inst))
1435 +                value |= ~0x1ffull;
1436 +        return value;
1437 + }
1438 +
1439 + // Get 22-bit immediate value (A5)
1440 + static inline uint64_t ia64_inst_get_imm22(uint64_t inst)
1441 + {
1442 +        uint64_t value = ((((inst >> 22) & 0x1f) << 16) |
1443 +                                          (((inst >> 27) & 0x1ff) << 7) |
1444 +                                          (inst & 0x7f));
1445 +        if (ia64_inst_get_sbit(inst))
1446 +                value |= ~0x1fffffull;
1447 +        return value;
1448 + }
1449 +
1450 + // Get 21-bit immediate value (I19)
1451 + static inline uint64_t ia64_inst_get_imm21(uint64_t inst)
1452 + {
1453 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1454 + }
1455 +
1456 + // Get 2-bit count value (A2)
1457 + static inline int ia64_inst_get_count2(uint64_t inst)
1458 + {
1459 +        return (inst >> 27) & 0x3;
1460 + }
1461 +
1462 + // Get bundle template
1463 + static inline unsigned int ia64_get_template(uint64_t ip)
1464 + {
1465 +        ia64_bundle_t bundle;
1466 +        ia64_load_bundle(bundle, ip);
1467 +        return bundle[0] & 0x1f;
1468 + }
1469 +
1470 + // Get specified instruction in bundle
1471 + static uint64_t ia64_get_instruction(uint64_t ip, int slot)
1472 + {
1473 +        uint64_t inst;
1474 +        ia64_bundle_t bundle;
1475 +        ia64_load_bundle(bundle, ip);
1476 + #if DEBUG
1477 +        printf("Bundle: %016llx%016llx\n", bundle[1], bundle[0]);
1478 + #endif
1479 +
1480 +        switch (slot) {
1481 +        case 0:
1482 +                inst = (bundle[0] >> 5) & 0x1ffffffffffull;
1483 +                break;
1484 +        case 1:
1485 +                inst = ((bundle[1] & 0x7fffffull) << 18) | ((bundle[0] >> 46) & 0x3ffffull);
1486 +                break;
1487 +        case 2:
1488 +                inst = (bundle[1] >> 23) & 0x1ffffffffffull;
1489 +                break;
1490 +        case 3:
1491 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1492 +                abort();
1493 +                break;
1494 +        }
1495 +
1496 + #if DEBUG
1497 +        printf(" Instruction %d: 0x%016llx\n", slot, inst);
1498 + #endif
1499 +        return inst;
1500 + }
1501 +
1502 + // Decode group 0 instructions
1503 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1504 + {
1505 +        const int r1 = (inst->inst >>  6) & 0x7f;
1506 +        const int r3 = (inst->inst >> 20) & 0x7f;
1507 +
1508 +        const int x3 = (inst->inst >> 33) & 0x07;
1509 +        const int x6 = (inst->inst >> 27) & 0x3f;
1510 +        const int x2 = (inst->inst >> 31) & 0x03;
1511 +        const int x4 = (inst->inst >> 27) & 0x0f;
1512 +
1513 +        if (x3 == 0) {
1514 +                switch (x6) {
1515 +                case 0x01:                                              // nop.i (I19)
1516 +                        inst->mnemo = IA64_INST_NOP;
1517 +                        inst->operands[0].valid = true;
1518 +                        inst->operands[0].index = -1;
1519 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1520 +                        return true;
1521 +                case 0x14:                                              // sxt1 (I29)
1522 +                case 0x15:                                              // sxt2 (I29)
1523 +                case 0x16:                                              // sxt4 (I29)
1524 +                case 0x10:                                              // zxt1 (I29)
1525 +                case 0x11:                                              // zxt2 (I29)
1526 +                case 0x12:                                              // zxt4 (I29)
1527 +                        switch (x6) {
1528 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1529 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1530 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1531 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1532 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1533 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1534 +                        default: abort();
1535 +                        }
1536 +                        inst->operands[0].valid = true;
1537 +                        inst->operands[0].index = r1;
1538 +                        inst->operands[1].valid = true;
1539 +                        inst->operands[1].index = r3;
1540 +                        inst->operands[1].value = IA64_GET_GR(r3);
1541 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1542 +                        return true;
1543 +                }
1544 +        }
1545 +        return false;
1546 + }
1547 +
1548 + // Decode group 4 instructions (load/store instructions)
1549 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1550 + {
1551 +        const int r1 = (inst->inst >> 6) & 0x7f;
1552 +        const int r2 = (inst->inst >> 13) & 0x7f;
1553 +        const int r3 = (inst->inst >> 20) & 0x7f;
1554 +
1555 +        const int m  = (inst->inst >> 36) & 1;
1556 +        const int x  = (inst->inst >> 27) & 1;
1557 +        const int x6 = (inst->inst >> 30) & 0x3f;
1558 +
1559 +        switch (x6) {
1560 +        case 0x00:
1561 +        case 0x01:
1562 +        case 0x02:
1563 +        case 0x03:
1564 +                if (x == 0) {
1565 +                        inst->operands[0].valid = true;
1566 +                        inst->operands[0].index = r1;
1567 +                        inst->operands[1].valid = true;
1568 +                        inst->operands[1].index = r3;
1569 +                        inst->operands[1].value = IA64_GET_GR(r3);
1570 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1571 +                        if (m == 0) {
1572 +                                switch (x6) {
1573 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1574 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1575 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1576 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1577 +                                }
1578 +                        }
1579 +                        else {
1580 +                                inst->operands[2].valid = true;
1581 +                                inst->operands[2].index = r2;
1582 +                                inst->operands[2].value = IA64_GET_GR(r2);
1583 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1584 +                                switch (x6) {
1585 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1586 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1587 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1588 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1589 +                                }
1590 +                        }
1591 +                        return true;
1592 +                }
1593 +                break;
1594 +        case 0x30:
1595 +        case 0x31:
1596 +        case 0x32:
1597 +        case 0x33:
1598 +                if (m == 0 && x == 0) {
1599 +                        inst->operands[0].valid = true;
1600 +                        inst->operands[0].index = r3;
1601 +                        inst->operands[0].value = IA64_GET_GR(r3);
1602 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1603 +                        inst->operands[1].valid = true;
1604 +                        inst->operands[1].index = r2;
1605 +                        inst->operands[1].value = IA64_GET_GR(r2);
1606 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1607 +                        switch (x6) {
1608 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1609 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1610 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1611 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1612 +                        }
1613 +                        return true;
1614 +                }
1615 +                break;
1616 +        }
1617 +        return false;
1618 + }
1619 +
1620 + // Decode group 5 instructions (load/store instructions)
1621 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1622 + {
1623 +        const int r1 = (inst->inst >> 6) & 0x7f;
1624 +        const int r2 = (inst->inst >> 13) & 0x7f;
1625 +        const int r3 = (inst->inst >> 20) & 0x7f;
1626 +
1627 +        const int x6 = (inst->inst >> 30) & 0x3f;
1628 +
1629 +        switch (x6) {
1630 +        case 0x00:
1631 +        case 0x01:
1632 +        case 0x02:
1633 +        case 0x03:
1634 +                inst->operands[0].valid = true;
1635 +                inst->operands[0].index = r1;
1636 +                inst->operands[1].valid = true;
1637 +                inst->operands[1].index = r3;
1638 +                inst->operands[1].value = IA64_GET_GR(r3);
1639 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1640 +                inst->operands[2].valid = true;
1641 +                inst->operands[2].index = -1;
1642 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1643 +                inst->operands[2].nat   = 0;
1644 +                switch (x6) {
1645 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1646 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1647 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1648 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1649 +                }
1650 +                return true;
1651 +        case 0x30:
1652 +        case 0x31:
1653 +        case 0x32:
1654 +        case 0x33:
1655 +                inst->operands[0].valid = true;
1656 +                inst->operands[0].index = r3;
1657 +                inst->operands[0].value = IA64_GET_GR(r3);
1658 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1659 +                inst->operands[1].valid = true;
1660 +                inst->operands[1].index = r2;
1661 +                inst->operands[1].value = IA64_GET_GR(r2);
1662 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1663 +                inst->operands[2].valid = true;
1664 +                inst->operands[2].index = -1;
1665 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1666 +                inst->operands[2].nat   = 0;
1667 +                switch (x6) {
1668 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1669 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1670 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1671 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1672 +                }
1673 +                return true;
1674 +        }
1675 +        return false;
1676 + }
1677 +
1678 + // Decode group 8 instructions (ALU integer)
1679 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1680 + {
1681 +        const int r1  = (inst->inst >> 6) & 0x7f;
1682 +        const int r2  = (inst->inst >> 13) & 0x7f;
1683 +        const int r3  = (inst->inst >> 20) & 0x7f;
1684 +
1685 +        const int x2a = (inst->inst >> 34) & 0x3;
1686 +        const int x2b = (inst->inst >> 27) & 0x3;
1687 +        const int x4  = (inst->inst >> 29) & 0xf;
1688 +        const int ve  = (inst->inst >> 33) & 0x1;
1689 +
1690 +        // destination register (r1) is always valid in this group
1691 +        inst->operands[0].valid = true;
1692 +        inst->operands[0].index = r1;
1693 +
1694 +        // source register (r3) is always valid in this group
1695 +        inst->operands[2].valid = true;
1696 +        inst->operands[2].index = r3;
1697 +        inst->operands[2].value = IA64_GET_GR(r3);
1698 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1699 +
1700 +        if (x2a == 0 && ve == 0) {
1701 +                inst->operands[1].valid = true;
1702 +                inst->operands[1].index = r2;
1703 +                inst->operands[1].value = IA64_GET_GR(r2);
1704 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1705 +                switch (x4) {
1706 +                case 0x0:                               // add (A1)
1707 +                        inst->mnemo = IA64_INST_ADD;
1708 +                        inst->operands[3].valid = true;
1709 +                        inst->operands[3].index = -1;
1710 +                        inst->operands[3].value = x2b == 1;
1711 +                        return true;
1712 +                case 0x1:                               // add (A1)
1713 +                        inst->mnemo = IA64_INST_SUB;
1714 +                        inst->operands[3].valid = true;
1715 +                        inst->operands[3].index = -1;
1716 +                        inst->operands[3].value = x2b == 0;
1717 +                        return true;
1718 +                case 0x4:                               // shladd (A2)
1719 +                        inst->mnemo = IA64_INST_SHLADD;
1720 +                        inst->operands[3].valid = true;
1721 +                        inst->operands[3].index = -1;
1722 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1723 +                        return true;
1724 +                case 0x9:
1725 +                        if (x2b == 1) {
1726 +                                inst->mnemo = IA64_INST_SUB;
1727 +                                inst->operands[1].index = -1;
1728 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1729 +                                inst->operands[1].nat   = 0;
1730 +                                return true;
1731 +                        }
1732 +                        break;
1733 +                case 0xb:
1734 +                        inst->operands[1].index = -1;
1735 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1736 +                        inst->operands[1].nat   = 0;
1737 +                        // fall-through
1738 +                case 0x3:
1739 +                        switch (x2b) {
1740 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1741 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1742 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1743 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1744 +                        }
1745 +                        return true;
1746 +                }
1747 +        }
1748 +        return false;
1749 + }
1750 +
1751 + // Decode instruction
1752 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1753 + {
1754 +        const int major = (inst->inst >> 37) & 0xf;
1755 +
1756 +        inst->mnemo = IA64_INST_UNKNOWN;
1757 +        inst->pred  = inst->inst & 0x3f;
1758 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1759 +
1760 +        switch (major) {
1761 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1762 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1763 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1764 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1765 +        }
1766 +        return false;
1767 + }
1768 +
1769 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1770 + {
1771 +        // XXX: handle Register NaT Consumption fault?
1772 +        // XXX: this simple emulator assumes instructions in a bundle
1773 +        // don't depend on effects of other instructions in the same
1774 +        // bundle. It probably would be simpler to JIT-generate code to be
1775 +        // executed natively but probably more costly (inject/extract CPU state)
1776 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1777 +                return false;
1778 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1779 +                return true;
1780 +
1781 +        uint8_t nat, nat2;
1782 +        uint64_t dst, dst2, src1, src2, src3;
1783 +
1784 +        switch (inst->mnemo) {
1785 +        case IA64_INST_NOP:
1786 +                break;
1787 +        case IA64_INST_ADD:
1788 +        case IA64_INST_SUB:
1789 +        case IA64_INST_SHLADD:
1790 +                src3 = inst->operands[3].value;
1791 +                // fall-through
1792 +        case IA64_INST_AND:
1793 +        case IA64_INST_ANDCM:
1794 +        case IA64_INST_OR:
1795 +        case IA64_INST_XOR:
1796 +                src1 = inst->operands[1].value;
1797 +                src2 = inst->operands[2].value;
1798 +                switch (inst->mnemo) {
1799 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1800 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1801 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1802 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1803 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1804 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1805 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1806 +                }
1807 +                inst->operands[0].commit = true;
1808 +                inst->operands[0].value  = dst;
1809 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1810 +                break;
1811 +        case IA64_INST_SXT1:
1812 +        case IA64_INST_SXT2:
1813 +        case IA64_INST_SXT4:
1814 +        case IA64_INST_ZXT1:
1815 +        case IA64_INST_ZXT2:
1816 +        case IA64_INST_ZXT4:
1817 +                src1 = inst->operands[1].value;
1818 +                switch (inst->mnemo) {
1819 +                case IA64_INST_SXT1: dst = (int64_t)(int8_t)src1;               break;
1820 +                case IA64_INST_SXT2: dst = (int64_t)(int16_t)src1;              break;
1821 +                case IA64_INST_SXT4: dst = (int64_t)(int32_t)src1;              break;
1822 +                case IA64_INST_ZXT1: dst = (uint8_t)src1;                               break;
1823 +                case IA64_INST_ZXT2: dst = (uint16_t)src1;                              break;
1824 +                case IA64_INST_ZXT4: dst = (uint32_t)src1;                              break;
1825 +                }
1826 +                inst->operands[0].commit = true;
1827 +                inst->operands[0].value  = dst;
1828 +                inst->operands[0].nat    = inst->operands[1].nat;
1829 +                break;
1830 +        case IA64_INST_LD1_UPDATE:
1831 +        case IA64_INST_LD2_UPDATE:
1832 +        case IA64_INST_LD4_UPDATE:
1833 +        case IA64_INST_LD8_UPDATE:
1834 +                inst->operands[1].commit = true;
1835 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1836 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1837 +                // fall-through
1838 +        case IA64_INST_LD1:
1839 +        case IA64_INST_LD2:
1840 +        case IA64_INST_LD4:
1841 +        case IA64_INST_LD8:
1842 +                src1 = inst->operands[1].value;
1843 +                if (inst->no_memory)
1844 +                        dst = 0;
1845 +                else {
1846 +                        switch (inst->mnemo) {
1847 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((uint8_t *)src1);        break;
1848 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((uint16_t *)src1);       break;
1849 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((uint32_t *)src1);       break;
1850 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((uint64_t *)src1);       break;
1851 +                        }
1852 +                }
1853 +                inst->operands[0].commit = true;
1854 +                inst->operands[0].value  = dst;
1855 +                inst->operands[0].nat    = 0;
1856 +                inst->operands[1].value  = dst2;
1857 +                inst->operands[1].nat    = nat2;
1858 +                break;
1859 +        case IA64_INST_ST1_UPDATE:
1860 +        case IA64_INST_ST2_UPDATE:
1861 +        case IA64_INST_ST4_UPDATE:
1862 +        case IA64_INST_ST8_UPDATE:
1863 +                inst->operands[0].commit = 0;
1864 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1865 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1866 +                // fall-through
1867 +        case IA64_INST_ST1:
1868 +        case IA64_INST_ST2:
1869 +        case IA64_INST_ST4:
1870 +        case IA64_INST_ST8:
1871 +                dst  = inst->operands[0].value;
1872 +                src1 = inst->operands[1].value;
1873 +                if (!inst->no_memory) {
1874 +                        switch (inst->mnemo) {
1875 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((uint8_t *)dst) = src1;        break;
1876 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((uint16_t *)dst) = src1;       break;
1877 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((uint32_t *)dst) = src1;       break;
1878 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((uint64_t *)dst) = src1;       break;
1879 +                        }
1880 +                }
1881 +                inst->operands[0].value  = dst2;
1882 +                inst->operands[0].nat    = nat2;
1883 +                break;
1884 +        default:
1885 +                return false;
1886 +        }
1887 +
1888 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1889 +                ia64_operand_t const & op = inst->operands[i];
1890 +                if (!op.commit)
1891 +                        continue;
1892 +                if (op.index == -1)
1893 +                        return false; // XXX: internal error
1894 +                IA64_SET_GR(op.index, op.value, op.nat);
1895 +        }
1896 +        return true;
1897 + }
1898 +
1899 + static bool ia64_emulate_instruction(uint64_t raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1900 + {
1901 +        ia64_instruction_t inst;
1902 +        memset(&inst, 0, sizeof(inst));
1903 +        inst.inst = raw_inst;
1904 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1905 +                return false;
1906 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1907 + }
1908 +
1909 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1910 + {
1911 +        uint64_t ip = IA64_GET_IP();
1912 + #if DEBUG
1913 +        printf("IP: 0x%016llx\n", ip);
1914 + #if 0
1915 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1916 +        ia64_get_instruction(ip, 0);
1917 +        ia64_get_instruction(ip, 1);
1918 +        ia64_get_instruction(ip, 2);
1919 + #endif
1920 + #endif
1921 +
1922 +        // Select which decode switch to use
1923 +        ia64_instruction_t inst;
1924 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1925 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1926 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1927 +                return false;
1928 +        }
1929 +
1930 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1931 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1932 +
1933 +        switch (inst.mnemo) {
1934 +        case IA64_INST_LD1:
1935 +        case IA64_INST_LD2:
1936 +        case IA64_INST_LD4:
1937 +        case IA64_INST_LD8:
1938 +        case IA64_INST_LD1_UPDATE:
1939 +        case IA64_INST_LD2_UPDATE:
1940 +        case IA64_INST_LD4_UPDATE:
1941 +        case IA64_INST_LD8_UPDATE:
1942 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1943 +                break;
1944 +        case IA64_INST_ST1:
1945 +        case IA64_INST_ST2:
1946 +        case IA64_INST_ST4:
1947 +        case IA64_INST_ST8:
1948 +        case IA64_INST_ST1_UPDATE:
1949 +        case IA64_INST_ST2_UPDATE:
1950 +        case IA64_INST_ST4_UPDATE:
1951 +        case IA64_INST_ST8_UPDATE:
1952 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1953 +                break;
1954 +        }
1955 +
1956 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1957 +                // Unknown machine code, let it crash. Then patch the decoder
1958 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1959 +                return false;
1960 +        }
1961 +
1962 +        switch (inst.mnemo) {
1963 +        case IA64_INST_LD1:
1964 +        case IA64_INST_LD1_UPDATE:
1965 +        case IA64_INST_ST1:
1966 +        case IA64_INST_ST1_UPDATE:
1967 +                transfer_size = SIZE_BYTE;
1968 +                break;
1969 +        case IA64_INST_LD2:
1970 +        case IA64_INST_LD2_UPDATE:
1971 +        case IA64_INST_ST2:
1972 +        case IA64_INST_ST2_UPDATE:
1973 +                transfer_size = SIZE_WORD;
1974 +                break;
1975 +        case IA64_INST_LD4:
1976 +        case IA64_INST_LD4_UPDATE:
1977 +        case IA64_INST_ST4:
1978 +        case IA64_INST_ST4_UPDATE:
1979 +                transfer_size = SIZE_LONG;
1980 +                break;
1981 +        case IA64_INST_LD8:
1982 +        case IA64_INST_LD8_UPDATE:
1983 +        case IA64_INST_ST8:
1984 +        case IA64_INST_ST8_UPDATE:
1985 +                transfer_size = SIZE_QUAD;
1986 +                break;
1987 +        }
1988 +
1989 +        if (transfer_size == SIZE_UNKNOWN) {
1990 +                // Unknown machine code, let it crash. Then patch the decoder
1991 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1992 +                return false;
1993 +        }
1994 +
1995 +        inst.no_memory = true;
1996 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1997 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1998 +                return false;
1999 +        }
2000 +
2001 +        int slot = ip & 3;
2002 +        bool emulate_next = false;
2003 +        switch (slot) {
2004 +        case 0:
2005 +                switch (ia64_get_template(ip)) {
2006 +                case 0x2: // MI;I
2007 +                case 0x3: // MI;I;
2008 +                        emulate_next = true;
2009 +                        slot = 2;
2010 +                        break;
2011 +                case 0xa: // M;MI
2012 +                case 0xb: // M;MI;
2013 +                        emulate_next = true;
2014 +                        slot = 1;
2015 +                        break;
2016 +                }
2017 +                break;
2018 +        }
2019 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
2020 +                while (slot < 3) {
2021 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
2022 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
2023 +                                return false;
2024 +                        }
2025 +                        ++slot;
2026 +                }
2027 +        }
2028 +
2029 + #if IA64_CAN_PATCH_IP_SLOT
2030 +        if ((slot = ip & 3) < 2)
2031 +                IA64_SET_IP((ip & ~3ull) + (slot + 1));
2032 +        else
2033 + #endif
2034 +                IA64_SET_IP((ip & ~3ull) + 16);
2035 + #if DEBUG
2036 +        printf("IP: 0x%016llx\n", IA64_GET_IP());
2037 + #endif
2038 +        return true;
2039 + }
2040 + #endif
2041 +
2042   // Decode and skip PPC instruction
2043 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
2043 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
2044   static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
2045   {
2046          instruction_t instr;
# Line 1590 | Line 2515 | static bool arm_skip_instruction(unsigne
2515  
2516  
2517   // Fallbacks
2518 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2519 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2520 + #endif
2521 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2522 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2523 + #endif
2524   #ifndef SIGSEGV_FAULT_INSTRUCTION
2525 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2525 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2526   #endif
2527   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2528   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2529   #endif
2530   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2531 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2531 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2532   #endif
2533  
2534   // SIGSEGV recovery supported ?
# Line 1610 | Line 2541 | static bool arm_skip_instruction(unsigne
2541   *  SIGSEGV global handler
2542   */
2543  
2544 + struct sigsegv_info_t {
2545 +        sigsegv_address_t addr;
2546 +        sigsegv_address_t pc;
2547 + #ifdef HAVE_MACH_EXCEPTIONS
2548 +        mach_port_t thread;
2549 +        bool has_exc_state;
2550 +        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2551 +        mach_msg_type_number_t exc_state_count;
2552 +        bool has_thr_state;
2553 +        SIGSEGV_THREAD_STATE_TYPE thr_state;
2554 +        mach_msg_type_number_t thr_state_count;
2555 + #endif
2556 + };
2557 +
2558 + #ifdef HAVE_MACH_EXCEPTIONS
2559 + static void mach_get_exception_state(sigsegv_info_t *SIP)
2560 + {
2561 +        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2562 +        kern_return_t krc = thread_get_state(SIP->thread,
2563 +                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2564 +                                                                                 (natural_t *)&SIP->exc_state,
2565 +                                                                                 &SIP->exc_state_count);
2566 +        MACH_CHECK_ERROR(thread_get_state, krc);
2567 +        SIP->has_exc_state = true;
2568 + }
2569 +
2570 + static void mach_get_thread_state(sigsegv_info_t *SIP)
2571 + {
2572 +        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2573 +        kern_return_t krc = thread_get_state(SIP->thread,
2574 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2575 +                                                                                 (natural_t *)&SIP->thr_state,
2576 +                                                                                 &SIP->thr_state_count);
2577 +        MACH_CHECK_ERROR(thread_get_state, krc);
2578 +        SIP->has_thr_state = true;
2579 + }
2580 +
2581 + static void mach_set_thread_state(sigsegv_info_t *SIP)
2582 + {
2583 +        kern_return_t krc = thread_set_state(SIP->thread,
2584 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2585 +                                                                                 (natural_t *)&SIP->thr_state,
2586 +                                                                                 SIP->thr_state_count);
2587 +        MACH_CHECK_ERROR(thread_set_state, krc);
2588 + }
2589 + #endif
2590 +
2591 + // Return the address of the invalid memory reference
2592 + sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2593 + {
2594 + #ifdef HAVE_MACH_EXCEPTIONS
2595 +        static int use_fast_path = -1;
2596 +        if (use_fast_path != 1 && !SIP->has_exc_state) {
2597 +                mach_get_exception_state(SIP);
2598 +
2599 +                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2600 +                if (use_fast_path < 0) {
2601 +                        const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2602 +                        if (machfault) {
2603 +                                if (strcmp(machfault, "fast") == 0)
2604 +                                        use_fast_path = 1;
2605 +                                else if (strcmp(machfault, "slow") == 0)
2606 +                                        use_fast_path = 0;
2607 +                        }
2608 +                        if (use_fast_path < 0)
2609 +                                use_fast_path = addr == SIP->addr;
2610 +                }
2611 +                SIP->addr = addr;
2612 +        }
2613 + #endif
2614 +        return SIP->addr;
2615 + }
2616 +
2617 + // Return the address of the instruction that caused the fault, or
2618 + // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2619 + sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2620 + {
2621 + #ifdef HAVE_MACH_EXCEPTIONS
2622 +        if (!SIP->has_thr_state) {
2623 +                mach_get_thread_state(SIP);
2624 +
2625 +                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2626 +        }
2627 + #endif
2628 +        return SIP->pc;
2629 + }
2630 +
2631   // This function handles the badaccess to memory.
2632   // It is called from the signal handler or the exception handler.
2633   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2634   {
2635 +        sigsegv_info_t SI;
2636 +        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2637 +        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2638   #ifdef HAVE_MACH_EXCEPTIONS
2639 <        // We must match the initial count when writing back the CPU state registers
2640 <        kern_return_t krc;
2641 <        mach_msg_type_number_t count;
1621 <
1622 <        count = SIGSEGV_THREAD_STATE_COUNT;
1623 <        krc = thread_get_state(thread, SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)state, &count);
1624 <        MACH_CHECK_ERROR (thread_get_state, krc);
2639 >        SI.thread = thread;
2640 >        SI.has_exc_state = false;
2641 >        SI.has_thr_state = false;
2642   #endif
2643 +        sigsegv_info_t * const SIP = &SI;
2644  
1627        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1628        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1629        
2645          // Call user's handler and reinstall the global handler, if required
2646 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2646 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2647          case SIGSEGV_RETURN_SUCCESS:
2648                  return true;
2649  
# Line 1636 | Line 2651 | static bool handle_badaccess(SIGSEGV_FAU
2651          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2652                  // Call the instruction skipper with the register file
2653                  // available
2654 + #ifdef HAVE_MACH_EXCEPTIONS
2655 +                if (!SIP->has_thr_state)
2656 +                        mach_get_thread_state(SIP);
2657 + #endif
2658                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2659   #ifdef HAVE_MACH_EXCEPTIONS
2660                          // Unlike UNIX signals where the thread state
2661                          // is modified off of the stack, in Mach we
2662                          // need to actually call thread_set_state to
2663                          // have the register values updated.
2664 <                        krc = thread_set_state(thread,
1646 <                                                                   SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)state,
1647 <                                                                   count);
1648 <                        MACH_CHECK_ERROR (thread_set_state, krc);
2664 >                        mach_set_thread_state(SIP);
2665   #endif
2666                          return true;
2667                  }
# Line 1654 | Line 2670 | static bool handle_badaccess(SIGSEGV_FAU
2670          case SIGSEGV_RETURN_FAILURE:
2671                  // We can't do anything with the fault_address, dump state?
2672                  if (sigsegv_state_dumper != 0)
2673 <                        sigsegv_state_dumper(fault_address, fault_instruction);
2673 >                        sigsegv_state_dumper(SIP);
2674                  break;
2675          }
2676  
# Line 1795 | Line 2811 | catch_exception_raise(mach_port_t except
2811                                            mach_port_t task,
2812                                            exception_type_t exception,
2813                                            exception_data_t code,
2814 <                                          mach_msg_type_number_t codeCount)
2814 >                                          mach_msg_type_number_t code_count)
2815   {
1800        SIGSEGV_THREAD_STATE_TYPE state;
2816          kern_return_t krc;
2817  
2818 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2819 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2820 <                        return KERN_SUCCESS;
2818 >        if (exception == EXC_BAD_ACCESS) {
2819 >                switch (code[0]) {
2820 >                case KERN_PROTECTION_FAILURE:
2821 >                case KERN_INVALID_ADDRESS:
2822 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2823 >                                return KERN_SUCCESS;
2824 >                        break;
2825 >                }
2826          }
2827  
2828          // In Mach we do not need to remove the exception handler.
2829          // If we forward the exception, eventually some exception handler
2830          // will take care of this exception.
2831 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2831 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2832  
2833          return krc;
2834   }
# Line 2116 | Line 3136 | void sigsegv_set_dump_state(sigsegv_stat
3136   const int REF_INDEX = 123;
3137   const int REF_VALUE = 45;
3138  
3139 < static int page_size;
3139 > static sigsegv_uintptr_t page_size;
3140   static volatile char * page = 0;
3141   static volatile int handler_called = 0;
3142  
# Line 2132 | Line 3152 | static volatile int handler_called = 0;
3152   static void *b_region, *e_region;
3153   #endif
3154  
3155 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3155 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3156   {
3157 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3158 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3159   #if DEBUG
3160          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3161          printf("expected fault at %p\n", page + REF_INDEX);
# Line 2147 | Line 3169 | static sigsegv_return_t sigsegv_test_han
3169   #ifdef __GNUC__
3170          // Make sure reported fault instruction address falls into
3171          // expected code range
3172 <        if (instruction_address != SIGSEGV_INVALID_PC
3172 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3173                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3174                          (instruction_address >= (sigsegv_address_t)e_region)))
3175                  exit(11);
3176   #endif
3177 <        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3177 >        if (vm_protect((char *)((sigsegv_uintptr_t)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3178                  exit(12);
3179          return SIGSEGV_RETURN_SUCCESS;
3180   }
3181  
3182   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3183 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3183 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3184   {
3185 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3186 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3187   #if DEBUG
3188          printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3189   #endif
3190 <        if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3190 >        if (((sigsegv_uintptr_t)fault_address - (sigsegv_uintptr_t)page) < page_size) {
3191   #ifdef __GNUC__
3192                  // Make sure reported fault instruction address falls into
3193                  // expected code range
3194 <                if (instruction_address != SIGSEGV_INVALID_PC
3194 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3195                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3196                                  (instruction_address >= (sigsegv_address_t)e_region)))
3197                          return SIGSEGV_RETURN_FAILURE;
# Line 2181 | Line 3205 | static sigsegv_return_t sigsegv_insn_han
3205   // More sophisticated tests for instruction skipper
3206   static bool arch_insn_skipper_tests()
3207   {
3208 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3208 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
3209          static const unsigned char code[] = {
3210                  0x8a, 0x00,                    // mov    (%eax),%al
3211                  0x8a, 0x2c, 0x18,              // mov    (%eax,%ebx,1),%ch
# Line 2195 | Line 3219 | static bool arch_insn_skipper_tests()
3219                  0x8b, 0x0c, 0x18,              // mov    (%eax,%ebx,1),%ecx
3220                  0x89, 0x00,                    // mov    %eax,(%eax)
3221                  0x89, 0x0c, 0x18,              // mov    %ecx,(%eax,%ebx,1)
3222 < #if defined(__x86_64__)
3222 > #if defined(__x86_64__) || defined(_M_X64)
3223                  0x44, 0x8a, 0x00,              // mov    (%rax),%r8b
3224                  0x44, 0x8a, 0x20,              // mov    (%rax),%r12b
3225                  0x42, 0x8a, 0x3c, 0x10,        // mov    (%rax,%r10,1),%dil
# Line 2224 | Line 3248 | static bool arch_insn_skipper_tests()
3248                  0                              // end
3249          };
3250          const int N_REGS = 20;
3251 <        unsigned long regs[N_REGS];
3251 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3252          for (int i = 0; i < N_REGS; i++)
3253                  regs[i] = i;
3254 <        const unsigned long start_code = (unsigned long)&code;
3254 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3255          regs[X86_REG_EIP] = start_code;
3256          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3257                     && ix86_skip_instruction(regs))
# Line 2253 | Line 3277 | int main(void)
3277          
3278          if (!sigsegv_install_handler(sigsegv_test_handler))
3279                  return 4;
3280 <        
3280 >
3281   #ifdef __GNUC__
3282          b_region = &&L_b_region1;
3283          e_region = &&L_e_region1;
3284   #endif
3285 < L_b_region1:
3286 <        page[REF_INDEX] = REF_VALUE;
3287 <        if (page[REF_INDEX] != REF_VALUE)
3288 <          exit(20);
3289 <        page[REF_INDEX] = REF_VALUE;
3290 <        BARRIER();
3291 < L_e_region1:
3285 >        /* This is a really awful hack but otherwise gcc is smart enough
3286 >         * (or bug'ous enough?) to optimize the labels and place them
3287 >         * e.g. at the "main" entry point, which is wrong.
3288 >         */
3289 >        volatile int label_hack = 1;
3290 >        switch (label_hack) {
3291 >        case 1:
3292 >        L_b_region1:
3293 >                page[REF_INDEX] = REF_VALUE;
3294 >                if (page[REF_INDEX] != REF_VALUE)
3295 >                        exit(20);
3296 >                page[REF_INDEX] = REF_VALUE;
3297 >                BARRIER();
3298 >                // fall-through
3299 >        case 2:
3300 >        L_e_region1:
3301 >                BARRIER();
3302 >                break;
3303 >        }
3304  
3305          if (handler_called != 1)
3306                  return 5;
# Line 2295 | Line 3331 | int main(void)
3331          b_region = &&L_b_region2;
3332          e_region = &&L_e_region2;
3333   #endif
3334 < L_b_region2:
3335 <        TEST_SKIP_INSTRUCTION(unsigned char);
3336 <        TEST_SKIP_INSTRUCTION(unsigned short);
3337 <        TEST_SKIP_INSTRUCTION(unsigned int);
3338 <        TEST_SKIP_INSTRUCTION(unsigned long);
3339 <        TEST_SKIP_INSTRUCTION(signed char);
3340 <        TEST_SKIP_INSTRUCTION(signed short);
3341 <        TEST_SKIP_INSTRUCTION(signed int);
3342 <        TEST_SKIP_INSTRUCTION(signed long);
3343 <        BARRIER();
3344 < L_e_region2:
3345 <
3334 >        switch (label_hack) {
3335 >        case 1:
3336 >        L_b_region2:
3337 >                TEST_SKIP_INSTRUCTION(unsigned char);
3338 >                TEST_SKIP_INSTRUCTION(unsigned short);
3339 >                TEST_SKIP_INSTRUCTION(unsigned int);
3340 >                TEST_SKIP_INSTRUCTION(unsigned long);
3341 >                TEST_SKIP_INSTRUCTION(signed char);
3342 >                TEST_SKIP_INSTRUCTION(signed short);
3343 >                TEST_SKIP_INSTRUCTION(signed int);
3344 >                TEST_SKIP_INSTRUCTION(signed long);
3345 >                BARRIER();
3346 >                // fall-through
3347 >        case 2:
3348 >        L_e_region2:
3349 >                BARRIER();
3350 >                break;
3351 >        }
3352          if (!arch_insn_skipper_tests())
3353                  return 20;
3354   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines