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.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 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 507 | 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 576 | Line 658 | if (ret != KERN_SUCCESS) { \
658          exit (1); \
659   }
660  
661 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
662 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
663 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
664 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
665 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
661 > #ifdef __ppc__
662 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE
663 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
664 > #endif
665 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
666 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
667 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
668 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
669 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
670 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
671 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
672 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
673   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
674 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
675 <
676 < // Given a suspended thread, stuff the current instruction and
677 < // registers into state.
678 < //
679 < // It would have been nice to have this be ppc/x86 independant which
680 < // could have been done easily with a thread_state_t instead of
681 < // ppc_thread_state_t, but because of the way this is called it is
682 < // easier to do it this way.
683 < #if (defined(ppc) || defined(__ppc__))
684 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
685 < {
686 <        kern_return_t krc;
687 <        mach_msg_type_number_t count;
688 <
689 <        count = MACHINE_THREAD_STATE_COUNT;
690 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
691 <        MACH_CHECK_ERROR (thread_get_state, krc);
674 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
675 > #endif
676 > #ifdef __ppc64__
677 > #if __DARWIN_UNIX03 && defined _STRUCT_PPC_THREAD_STATE64
678 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
679 > #endif
680 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
681 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
682 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
683 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(dar)
684 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
685 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
686 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
687 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(srr0)
688 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
689 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(srr0), (unsigned long *)&SIP->thr_state.MACH_FIELD_NAME(r0)
690 > #endif
691 > #ifdef __i386__
692 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE32
693 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
694 > #endif
695 > #define SIGSEGV_EXCEPTION_STATE_TYPE    i386_exception_state_t
696 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
697 > #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
698 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
699 > #define SIGSEGV_THREAD_STATE_TYPE               i386_thread_state_t
700 > #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
701 > #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
702 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(eip)
703 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
704 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(eax)) /* EAX is the first GPR we consider */
705 > #endif
706 > #ifdef __x86_64__
707 > #if __DARWIN_UNIX03 && defined _STRUCT_X86_THREAD_STATE64
708 > #define MACH_FIELD_NAME(X)                              __CONCAT(__,X)
709 > #endif
710 > #define SIGSEGV_EXCEPTION_STATE_TYPE    x86_exception_state64_t
711 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
712 > #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
713 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.MACH_FIELD_NAME(faultvaddr)
714 > #define SIGSEGV_THREAD_STATE_TYPE               x86_thread_state64_t
715 > #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
716 > #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
717 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.MACH_FIELD_NAME(rip)
718 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
719 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.MACH_FIELD_NAME(rax)) /* RAX is the first GPR we consider */
720 > #endif
721 > #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
722 > #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
723 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
724 > #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
725  
726 <        return (sigsegv_address_t)state->srr0;
727 < }
726 > #ifndef MACH_FIELD_NAME
727 > #define MACH_FIELD_NAME(X) X
728   #endif
729  
730   // Since there can only be one exception thread running at any time
# Line 656 | 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 723 | Line 849 | enum {
849   #endif
850   };
851   #endif
852 < #if defined(_WIN32)
852 > #if defined(__OpenBSD__)
853 > enum {
854 > #if defined(__i386__)
855 >        // EDI is the first register we consider
856 > #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
857 > #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
858 >        X86_REG_EIP = DREG(eip), // 7
859 >        X86_REG_EAX = DREG(eax), // 6
860 >        X86_REG_ECX = DREG(ecx), // 5
861 >        X86_REG_EDX = DREG(edx), // 4
862 >        X86_REG_EBX = DREG(ebx), // 3
863 >        X86_REG_ESP = DREG(esp), // 10
864 >        X86_REG_EBP = DREG(ebp), // 2
865 >        X86_REG_ESI = DREG(esi), // 1
866 >        X86_REG_EDI = DREG(edi)  // 0
867 > #undef DREG
868 > #undef OREG
869 > #endif
870 > };
871 > #endif
872 > #if defined(__sun__)
873 > // Same as for Linux, need to check for x86-64
874 > enum {
875 > #if defined(__i386__)
876 >        X86_REG_EIP = EIP,
877 >        X86_REG_EAX = EAX,
878 >        X86_REG_ECX = ECX,
879 >        X86_REG_EDX = EDX,
880 >        X86_REG_EBX = EBX,
881 >        X86_REG_ESP = ESP,
882 >        X86_REG_EBP = EBP,
883 >        X86_REG_ESI = ESI,
884 >        X86_REG_EDI = EDI
885 > #endif
886 > };
887 > #endif
888 > #if defined(__APPLE__) && defined(__MACH__)
889   enum {
890   #if (defined(i386) || defined(__i386__))
891 + #ifdef i386_SAVED_STATE
892 +        // same as FreeBSD (in Open Darwin 8.0.1)
893 +        X86_REG_EIP = 10,
894 +        X86_REG_EAX = 7,
895 +        X86_REG_ECX = 6,
896 +        X86_REG_EDX = 5,
897 +        X86_REG_EBX = 4,
898 +        X86_REG_ESP = 13,
899 +        X86_REG_EBP = 2,
900 +        X86_REG_ESI = 1,
901 +        X86_REG_EDI = 0
902 + #else
903 +        // new layout (MacOS X 10.4.4 for x86)
904 +        X86_REG_EIP = 10,
905 +        X86_REG_EAX = 0,
906 +        X86_REG_ECX = 2,
907 +        X86_REG_EDX = 3,
908 +        X86_REG_EBX = 1,
909 +        X86_REG_ESP = 7,
910 +        X86_REG_EBP = 6,
911 +        X86_REG_ESI = 5,
912 +        X86_REG_EDI = 4
913 + #endif
914 + #endif
915 + #if defined(__x86_64__)
916 +        X86_REG_R8  = 8,
917 +        X86_REG_R9  = 9,
918 +        X86_REG_R10 = 10,
919 +        X86_REG_R11 = 11,
920 +        X86_REG_R12 = 12,
921 +        X86_REG_R13 = 13,
922 +        X86_REG_R14 = 14,
923 +        X86_REG_R15 = 15,
924 +        X86_REG_EDI = 4,
925 +        X86_REG_ESI = 5,
926 +        X86_REG_EBP = 6,
927 +        X86_REG_EBX = 1,
928 +        X86_REG_EDX = 3,
929 +        X86_REG_EAX = 0,
930 +        X86_REG_ECX = 2,
931 +        X86_REG_ESP = 7,
932 +        X86_REG_EIP = 16
933 + #endif
934 + };
935 + #endif
936 + #if defined(_WIN32)
937 + enum {
938 + #if defined(_M_IX86)
939          X86_REG_EIP = 7,
940          X86_REG_EAX = 5,
941          X86_REG_ECX = 4,
# Line 736 | 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 772 | 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 783 | Line 1012 | static bool ix86_skip_instruction(unsign
1012                  return false;
1013   #endif
1014          
1015 +        enum instruction_type_t {
1016 +                i_MOV,
1017 +                i_ADD
1018 +        };
1019 +
1020          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1021          transfer_size_t transfer_size = SIZE_LONG;
1022 +        instruction_type_t instruction_type = i_MOV;
1023          
1024          int reg = -1;
1025          int len = 0;
# Line 802 | 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 835 | Line 1070 | static bool ix86_skip_instruction(unsign
1070   #endif
1071  
1072          // Decode instruction
1073 +        int op_len = 1;
1074          int target_size = SIZE_UNKNOWN;
1075          switch (eip[0]) {
1076          case 0x0f:
# Line 849 | Line 1085 | static bool ix86_skip_instruction(unsign
1085                          transfer_size = SIZE_WORD;
1086                          goto do_mov_extend;
1087                    do_mov_extend:
1088 <                        switch (eip[2] & 0xc0) {
1089 <                        case 0x80:
1090 <                                reg = (eip[2] >> 3) & 7;
1091 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1092 <                                break;
1093 <                        case 0x40:
1094 <                                reg = (eip[2] >> 3) & 7;
1095 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1096 <                                break;
1097 <                        case 0x00:
1098 <                                reg = (eip[2] >> 3) & 7;
1099 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1100 <                                break;
1101 <                        }
1102 <                        len += 3 + ix86_step_over_modrm(eip + 2);
1103 <                        break;
1104 <            }
1105 <          break;
1088 >                        op_len = 2;
1089 >                        goto do_transfer_load;
1090 >                }
1091 >                break;
1092 > #if defined(__x86_64__) || defined(_M_X64)
1093 >        case 0x63: // MOVSXD r64, r/m32
1094 >                if (has_rex && rex.W) {
1095 >                        transfer_size = SIZE_LONG;
1096 >                        target_size = SIZE_QUAD;
1097 >                }
1098 >                else if (transfer_size != SIZE_WORD) {
1099 >                        transfer_size = SIZE_LONG;
1100 >                        target_size = SIZE_QUAD;
1101 >                }
1102 >                goto do_transfer_load;
1103 > #endif
1104 >        case 0x02: // ADD r8, r/m8
1105 >                transfer_size = SIZE_BYTE;
1106 >        case 0x03: // ADD r32, r/m32
1107 >                instruction_type = i_ADD;
1108 >                goto do_transfer_load;
1109          case 0x8a: // MOV r8, r/m8
1110                  transfer_size = SIZE_BYTE;
1111          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1112 <                switch (eip[1] & 0xc0) {
1112 >          do_transfer_load:
1113 >                switch (eip[op_len] & 0xc0) {
1114                  case 0x80:
1115 <                        reg = (eip[1] >> 3) & 7;
1115 >                        reg = (eip[op_len] >> 3) & 7;
1116                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1117                          break;
1118                  case 0x40:
1119 <                        reg = (eip[1] >> 3) & 7;
1119 >                        reg = (eip[op_len] >> 3) & 7;
1120                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1121                          break;
1122                  case 0x00:
1123 <                        reg = (eip[1] >> 3) & 7;
1123 >                        reg = (eip[op_len] >> 3) & 7;
1124                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1125                          break;
1126                  }
1127 <                len += 2 + ix86_step_over_modrm(eip + 1);
1127 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1128                  break;
1129 +        case 0x00: // ADD r/m8, r8
1130 +                transfer_size = SIZE_BYTE;
1131 +        case 0x01: // ADD r/m32, r32
1132 +                instruction_type = i_ADD;
1133 +                goto do_transfer_store;
1134          case 0x88: // MOV r/m8, r8
1135                  transfer_size = SIZE_BYTE;
1136          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1137 <                switch (eip[1] & 0xc0) {
1137 >          do_transfer_store:
1138 >                switch (eip[op_len] & 0xc0) {
1139                  case 0x80:
1140 <                        reg = (eip[1] >> 3) & 7;
1140 >                        reg = (eip[op_len] >> 3) & 7;
1141                          transfer_type = SIGSEGV_TRANSFER_STORE;
1142                          break;
1143                  case 0x40:
1144 <                        reg = (eip[1] >> 3) & 7;
1144 >                        reg = (eip[op_len] >> 3) & 7;
1145                          transfer_type = SIGSEGV_TRANSFER_STORE;
1146                          break;
1147                  case 0x00:
1148 <                        reg = (eip[1] >> 3) & 7;
1148 >                        reg = (eip[op_len] >> 3) & 7;
1149                          transfer_type = SIGSEGV_TRANSFER_STORE;
1150                          break;
1151                  }
1152 <                len += 2 + ix86_step_over_modrm(eip + 1);
1152 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1153                  break;
1154          }
1155          if (target_size == SIZE_UNKNOWN)
# Line 914 | 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
1167  
1168 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1168 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1169                  static const int x86_reg_map[] = {
1170                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1171                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1172 < #if defined(__x86_64__)
1172 > #if defined(__x86_64__) || defined(_M_X64)
1173                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1174                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1175   #endif
# Line 955 | Line 1201 | static bool ix86_skip_instruction(unsign
1201          }
1202  
1203   #if DEBUG
1204 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1204 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1205                     transfer_size == SIZE_BYTE ? "byte" :
1206                     transfer_size == SIZE_WORD ? "word" :
1207                     transfer_size == SIZE_LONG ? "long" :
# Line 1010 | 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 1047 | Line 2076 | static bool powerpc_skip_instruction(uns
2076  
2077   // Decode and skip MIPS instruction
2078   #if (defined(mips) || defined(__mips))
2079 < enum {
1051 < #if (defined(sgi) || defined(__sgi))
1052 <  MIPS_REG_EPC = 35,
1053 < #endif
1054 < };
1055 < static bool mips_skip_instruction(greg_t * regs)
2079 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
2080   {
2081 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
2081 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
2082  
2083    if (epc == 0)
2084          return false;
# Line 1203 | Line 2227 | static bool mips_skip_instruction(greg_t
2227                   mips_gpr_names[reg]);
2228   #endif
2229  
2230 <  regs[MIPS_REG_EPC] += 4;
2230 >  *pc_p += 4;
2231    return true;
2232   }
2233   #endif
# Line 1215 | Line 2239 | enum {
2239    SPARC_REG_G1 = REG_G1,
2240    SPARC_REG_O0 = REG_O0,
2241    SPARC_REG_PC = REG_PC,
2242 +  SPARC_REG_nPC = REG_nPC
2243   #endif
2244   };
2245   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1278 | Line 2303 | static bool sparc_skip_instruction(unsig
2303          break;
2304    case 7: // Store Doubleword
2305          transfer_type = SIGSEGV_TRANSFER_STORE;
2306 <        transfer_size = SIZE_WORD;
2306 >        transfer_size = SIZE_LONG;
2307          register_pair = true;
2308          break;
2309    }
# Line 1288 | Line 2313 | static bool sparc_skip_instruction(unsig
2313          return false;
2314    }
2315  
1291  // Zero target register in case of a load operation
2316    const int reg = (opcode >> 25) & 0x1f;
2317 +
2318 + #if DEBUG
2319 +  static const char * reg_names[] = {
2320 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2321 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2322 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2323 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2324 +  };
2325 +  printf("%s %s register %s\n",
2326 +                 transfer_size == SIZE_BYTE ? "byte" :
2327 +                 transfer_size == SIZE_WORD ? "word" :
2328 +                 transfer_size == SIZE_LONG ? "long" :
2329 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2330 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2331 +                 reg_names[reg]);
2332 + #endif
2333 +
2334 +  // Zero target register in case of a load operation
2335    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2336          // FIXME: code to handle local & input registers is not tested
2337 <        if (reg >= 1 && reg <= 7) {
2337 >        if (reg >= 1 && reg < 8) {
2338            // global registers
2339            regs[reg - 1 + SPARC_REG_G1] = 0;
2340          }
2341 <        else if (reg >= 8 && reg <= 15) {
2341 >        else if (reg >= 8 && reg < 16) {
2342            // output registers
2343            regs[reg - 8 + SPARC_REG_O0] = 0;
2344          }
2345 <        else if (reg >= 16 && reg <= 23) {
2345 >        else if (reg >= 16 && reg < 24) {
2346            // local registers (in register windows)
2347            if (gwins)
2348                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1316 | Line 2358 | static bool sparc_skip_instruction(unsig
2358          }
2359    }
2360  
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
2361    regs[SPARC_REG_PC] += 4;
2362 +  regs[SPARC_REG_nPC] += 4;
2363    return true;
2364   }
2365   #endif
# Line 1488 | 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 1508 | 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_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2636 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2637 <        
2635 >        sigsegv_info_t SI;
2636 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2637 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2638 > #ifdef HAVE_MACH_EXCEPTIONS
2639 >        SI.thread = thread;
2640 >        SI.has_exc_state = false;
2641 >        SI.has_thr_state = false;
2642 > #endif
2643 >        sigsegv_info_t * const SIP = &SI;
2644 >
2645          // Call user's handler and reinstall the global handler, if required
2646 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2646 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2647          case SIGSEGV_RETURN_SUCCESS:
2648                  return true;
2649  
# Line 1524 | Line 2651 | static bool handle_badaccess(SIGSEGV_FAU
2651          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2652                  // Call the instruction skipper with the register file
2653                  // available
2654 + #ifdef HAVE_MACH_EXCEPTIONS
2655 +                if (!SIP->has_thr_state)
2656 +                        mach_get_thread_state(SIP);
2657 + #endif
2658                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2659   #ifdef HAVE_MACH_EXCEPTIONS
2660                          // Unlike UNIX signals where the thread state
2661                          // is modified off of the stack, in Mach we
2662                          // need to actually call thread_set_state to
2663                          // have the register values updated.
2664 <                        kern_return_t krc;
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);
2664 >                        mach_set_thread_state(SIP);
2665   #endif
2666                          return true;
2667                  }
# Line 1544 | 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 1586 | Line 2712 | forward_exception(mach_port_t thread_por
2712          mach_port_t port;
2713          exception_behavior_t behavior;
2714          thread_state_flavor_t flavor;
2715 <        thread_state_t thread_state;
2715 >        thread_state_data_t thread_state;
2716          mach_msg_type_number_t thread_state_count;
2717  
2718          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1605 | Line 2731 | forward_exception(mach_port_t thread_por
2731          behavior = oldExceptionPorts->behaviors[portIndex];
2732          flavor = oldExceptionPorts->flavors[portIndex];
2733  
2734 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2735 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2736 +                return KERN_FAILURE;
2737 +        }
2738 +
2739          /*
2740           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2741           */
2742  
2743          if (behavior != EXCEPTION_DEFAULT) {
2744                  thread_state_count = THREAD_STATE_MAX;
2745 <                kret = thread_get_state (thread_port, flavor, thread_state,
2745 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2746                                                                   &thread_state_count);
2747                  MACH_CHECK_ERROR (thread_get_state, kret);
2748          }
# Line 1627 | Line 2758 | forward_exception(mach_port_t thread_por
2758            // fprintf(stderr, "forwarding to exception_raise_state\n");
2759            kret = exception_raise_state(port, exception_type, exception_data,
2760                                                                     data_count, &flavor,
2761 <                                                                   thread_state, thread_state_count,
2762 <                                                                   thread_state, &thread_state_count);
2761 >                                                                   (natural_t *)&thread_state, thread_state_count,
2762 >                                                                   (natural_t *)&thread_state, &thread_state_count);
2763            MACH_CHECK_ERROR (exception_raise_state, kret);
2764            break;
2765          case EXCEPTION_STATE_IDENTITY:
# Line 1636 | Line 2767 | forward_exception(mach_port_t thread_por
2767            kret = exception_raise_state_identity(port, thread_port, task_port,
2768                                                                                          exception_type, exception_data,
2769                                                                                          data_count, &flavor,
2770 <                                                                                        thread_state, thread_state_count,
2771 <                                                                                        thread_state, &thread_state_count);
2770 >                                                                                        (natural_t *)&thread_state, thread_state_count,
2771 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
2772            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2773            break;
2774          default:
2775            fprintf(stderr, "forward_exception got unknown behavior\n");
2776 +          kret = KERN_FAILURE;
2777            break;
2778          }
2779  
2780          if (behavior != EXCEPTION_DEFAULT) {
2781 <                kret = thread_set_state (thread_port, flavor, thread_state,
2781 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2782                                                                   thread_state_count);
2783                  MACH_CHECK_ERROR (thread_set_state, kret);
2784          }
2785  
2786 <        return KERN_SUCCESS;
2786 >        return kret;
2787   }
2788  
2789   /*
# Line 1679 | 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   {
1684        ppc_thread_state_t state;
2816          kern_return_t krc;
2817  
2818 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2819 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2820 <                        return KERN_SUCCESS;
2818 >        if (exception == EXC_BAD_ACCESS) {
2819 >                switch (code[0]) {
2820 >                case KERN_PROTECTION_FAILURE:
2821 >                case KERN_INVALID_ADDRESS:
2822 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2823 >                                return KERN_SUCCESS;
2824 >                        break;
2825 >                }
2826          }
2827  
2828          // In Mach we do not need to remove the exception handler.
2829          // If we forward the exception, eventually some exception handler
2830          // will take care of this exception.
2831 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2831 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2832  
2833          return krc;
2834   }
# Line 1820 | Line 2956 | static bool sigsegv_do_install_handler(s
2956          // addressing modes) used in PPC instructions, you will need the
2957          // GPR state anyway.
2958          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2959 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2959 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2960          if (krc != KERN_SUCCESS) {
2961                  mach_error("thread_set_exception_ports", krc);
2962                  return false;
# Line 2000 | 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  
3143 + /* Barriers */
3144 + #ifdef __GNUC__
3145 + #define BARRIER() asm volatile ("" : : : "memory")
3146 + #else
3147 + #define BARRIER() /* nothing */
3148 + #endif
3149 +
3150   #ifdef __GNUC__
3151   // Code range where we expect the fault to come from
3152   static void *b_region, *e_region;
3153   #endif
3154  
3155 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3155 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3156   {
3157 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3158 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3159   #if DEBUG
3160          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3161          printf("expected fault at %p\n", page + REF_INDEX);
# Line 2024 | 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 2058 | 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 2072 | 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 2095 | Line 3242 | static bool arch_insn_skipper_tests()
3242                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3243                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3244                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3245 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3246 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3247   #endif
3248                  0                              // end
3249          };
3250          const int N_REGS = 20;
3251 <        unsigned long regs[N_REGS];
3251 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3252          for (int i = 0; i < N_REGS; i++)
3253                  regs[i] = i;
3254 <        const unsigned long start_code = (unsigned long)&code;
3254 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3255          regs[X86_REG_EIP] = start_code;
3256          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3257                     && ix86_skip_instruction(regs))
# Line 2118 | Line 3267 | int main(void)
3267          if (vm_init() < 0)
3268                  return 1;
3269  
3270 < #ifdef _WIN32
2122 <        page_size = 4096;
2123 < #else
2124 <        page_size = getpagesize();
2125 < #endif
3270 >        page_size = vm_get_page_size();
3271          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3272                  return 2;
3273          
# Line 2132 | Line 3277 | int main(void)
3277          
3278          if (!sigsegv_install_handler(sigsegv_test_handler))
3279                  return 4;
3280 <        
3280 >
3281   #ifdef __GNUC__
3282          b_region = &&L_b_region1;
3283          e_region = &&L_e_region1;
3284   #endif
3285 < L_b_region1:
3286 <        page[REF_INDEX] = REF_VALUE;
3287 <        if (page[REF_INDEX] != REF_VALUE)
3288 <          exit(20);
3289 <        page[REF_INDEX] = REF_VALUE;
3290 < L_e_region1:
3285 >        /* This is a really awful hack but otherwise gcc is smart enough
3286 >         * (or bug'ous enough?) to optimize the labels and place them
3287 >         * e.g. at the "main" entry point, which is wrong.
3288 >         */
3289 >        volatile int label_hack = 1;
3290 >        switch (label_hack) {
3291 >        case 1:
3292 >        L_b_region1:
3293 >                page[REF_INDEX] = REF_VALUE;
3294 >                if (page[REF_INDEX] != REF_VALUE)
3295 >                        exit(20);
3296 >                page[REF_INDEX] = REF_VALUE;
3297 >                BARRIER();
3298 >                // fall-through
3299 >        case 2:
3300 >        L_e_region1:
3301 >                BARRIER();
3302 >                break;
3303 >        }
3304  
3305          if (handler_called != 1)
3306                  return 5;
# Line 2173 | 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 < L_e_region2:
3344 <
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