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.49 by gbeauche, 2004-12-02T23:29:52Z vs.
Revision 1.88 by asvitkine, 2009-04-13T19:57:08Z

# Line 10 | Line 10
10   *    tjw@omnigroup.com Sun, 4 Jun 2000
11   *    www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html
12   *
13 < *  Basilisk II (C) 1997-2004 Christian Bauer
13 > *  Basilisk II (C) 1997-2008 Christian Bauer
14   *
15   *  This program is free software; you can redistribute it and/or modify
16   *  it under the terms of the GNU General Public License as published by
# Line 49 | Line 49 | using std::list;
49   #define RETSIGTYPE void
50   #endif
51  
52 + // Size of an unsigned integer large enough to hold all bits of a pointer
53 + // NOTE: this can be different than SIGSEGV_REGISTER_TYPE. In
54 + // particular, on ILP32 systems with a 64-bit kernel (HP-UX/ia64?)
55 + #if defined(HAVE_WIN32_VM) && !defined(__CYGWIN__)
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 226 | Line 241 | static void powerpc_decode_instruction(i
241  
242   #if HAVE_SIGINFO_T
243   // Generic extended signal handler
244 < #if defined(__NetBSD__) || defined(__FreeBSD__)
244 > #if defined(__FreeBSD__)
245   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
246 + #elif defined(__hpux)
247 + #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV) FAULT_HANDLER(SIGBUS)
248   #else
249   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
250   #endif
# Line 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
291 > #if defined(__NetBSD__)
292 > #if (defined(i386) || defined(__i386__))
293 > #include <sys/ucontext.h>
294 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
295 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_EIP]
296 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
297   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
298   #endif
299 + #if (defined(powerpc) || defined(__powerpc__))
300 + #include <sys/ucontext.h>
301 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
302 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_PC]
303 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_PC], (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_R0]
304 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
305 + #endif
306   #endif
307   #if defined(__linux__)
308   #if (defined(i386) || defined(__i386__))
309   #include <sys/ucontext.h>
310   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
311   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
312 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
312 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
313   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
314   #endif
315   #if (defined(x86_64) || defined(__x86_64__))
316   #include <sys/ucontext.h>
317   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
318   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */
319 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
319 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
320   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
321   #endif
322   #if (defined(ia64) || defined(__ia64__))
323 < #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
323 > #define SIGSEGV_CONTEXT_REGS                    ((struct sigcontext *)scp)
324 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
325 > #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
326 > #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
327   #endif
328   #if (defined(powerpc) || defined(__powerpc__))
329   #include <sys/ucontext.h>
# Line 300 | 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 314 | 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 435 | 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 470 | Line 550 | static sigsegv_address_t get_fault_addre
550   #ifndef HAVE_MACH_EXCEPTIONS
551   #if defined(__APPLE__) && defined(__MACH__)
552   #if (defined(ppc) || defined(__ppc__))
553 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct sigcontext *scp
553 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   int sig, int code, struct __darwin_sigcontext *scp
554   #define SIGSEGV_FAULT_HANDLER_ARGS              sig, code, scp
555   #define SIGSEGV_FAULT_ADDRESS                   get_fault_address(scp)
556 < #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_ir
556 > #define SIGSEGV_FAULT_INSTRUCTION               scp->MACH_FIELD_NAME(sc_ir)
557   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
558   #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2]
559   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
# Line 481 | Line 561 | static sigsegv_address_t get_fault_addre
561   // Use decoding scheme from SheepShaver
562   static sigsegv_address_t get_fault_address(struct sigcontext *scp)
563   {
564 <        unsigned int   nip = (unsigned int) scp->sc_ir;
565 <        unsigned int * gpr = &((unsigned int *) scp->sc_regs)[2];
564 >        unsigned int   nip = (unsigned int) scp->MACH_FIELD_NAME(sc_ir);
565 >        unsigned int * gpr = &((unsigned int *) scp->MACH_FIELD_NAME(sc_regs))[2];
566          instruction_t  instr;
567  
568 <        powerpc_decode_instruction(&instr, nip, gpr);
568 >        powerpc_decode_instruction(&instr, nip, (long unsigned int*)gpr);
569          return (sigsegv_address_t)instr.addr;
570   }
571   #endif
# Line 502 | Line 582 | static sigsegv_address_t get_fault_addre
582   #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
583   #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
584   #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
585 + #if defined(_M_IX86)
586   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Eip
587 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIGSEGV_CONTEXT_REGS->Edi)
587 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Edi)
588   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
589   #endif
590 + #if defined(_M_X64)
591 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Rip
592 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax)
593 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
594 + #endif
595 + #if defined(_M_IA64)
596 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->StIIP
597 + #endif
598 + #endif
599  
600   #if HAVE_MACH_EXCEPTIONS
601  
# Line 527 | Line 617 | extern "C" {
617   #include <mach/mach.h>
618   #include <mach/mach_error.h>
619  
620 < extern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);
621 < extern kern_return_t catch_exception_raise(mach_port_t, mach_port_t,
622 <        mach_port_t, exception_type_t, exception_data_t, mach_msg_type_number_t);
623 < extern kern_return_t exception_raise(mach_port_t, mach_port_t, mach_port_t,
624 <        exception_type_t, exception_data_t, mach_msg_type_number_t);
625 < extern kern_return_t exception_raise_state(mach_port_t, exception_type_t,
626 <        exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
620 > #ifndef HAVE_MACH64_VM
621 >
622 > // Undefine this to prevent a preprocessor warning when compiling on a
623 > // 32-bit machine with Mac OS X 10.5.
624 > #undef  MACH_EXCEPTION_CODES
625 >
626 > #define MACH_EXCEPTION_CODES                                    0
627 > #define mach_exception_data_t                                   exception_data_t
628 > #define mach_exception_data_type_t                              exception_data_type_t
629 > #define mach_exc_server                                                 exc_server
630 > #define catch_mach_exception_raise                              catch_exception_raise
631 > #define mach_exception_raise                                    exception_raise
632 > #define mach_exception_raise_state                              exception_raise_state
633 > #define mach_exception_raise_state_identity             exception_raise_state_identity
634 > #endif
635 >
636 > extern boolean_t mach_exc_server(mach_msg_header_t *, mach_msg_header_t *);
637 > extern kern_return_t catch_mach_exception_raise(mach_port_t, mach_port_t,
638 >        mach_port_t, exception_type_t, mach_exception_data_t, mach_msg_type_number_t);
639 > extern kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port,
640 >        exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t code_count,
641 >        int *flavor,
642 >        thread_state_t old_state, mach_msg_type_number_t old_state_count,
643 >        thread_state_t new_state, mach_msg_type_number_t *new_state_count);
644 > extern kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port,
645 >        mach_port_t thread_port, mach_port_t task_port, exception_type_t exception,
646 >        mach_exception_data_t code, mach_msg_type_number_t code_count,
647 >        int *flavor,
648 >        thread_state_t old_state, mach_msg_type_number_t old_state_count,
649 >        thread_state_t new_state, mach_msg_type_number_t *new_state_count);
650 > extern kern_return_t mach_exception_raise(mach_port_t, mach_port_t, mach_port_t,
651 >        exception_type_t, mach_exception_data_t, mach_msg_type_number_t);
652 > extern kern_return_t mach_exception_raise_state(mach_port_t, exception_type_t,
653 >        mach_exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
654          thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);
655 < extern kern_return_t exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
656 <        exception_type_t, exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
655 > extern kern_return_t mach_exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
656 >        exception_type_t, mach_exception_data_t, mach_msg_type_number_t, thread_state_flavor_t *,
657          thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);
658   }
659  
# Line 567 | Line 684 | if (ret != KERN_SUCCESS) { \
684          exit (1); \
685   }
686  
687 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
688 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
572 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
573 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
574 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
575 < #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
576 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
577 <
578 < // Given a suspended thread, stuff the current instruction and
579 < // registers into state.
580 < //
581 < // It would have been nice to have this be ppc/x86 independant which
582 < // could have been done easily with a thread_state_t instead of
583 < // ppc_thread_state_t, but because of the way this is called it is
584 < // easier to do it this way.
585 < #if (defined(ppc) || defined(__ppc__))
586 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
587 < {
588 <        kern_return_t krc;
589 <        mach_msg_type_number_t count;
590 <
591 <        count = MACHINE_THREAD_STATE_COUNT;
592 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
593 <        MACH_CHECK_ERROR (thread_get_state, krc);
594 <
595 <        return (sigsegv_address_t)state->srr0;
596 < }
687 > #ifndef MACH_FIELD_NAME
688 > #define MACH_FIELD_NAME(X) X
689   #endif
690  
691   // Since there can only be one exception thread running at any time
# Line 625 | Line 717 | handleExceptions(void *priv)
717                                  _exceptionPort, 0, MACH_PORT_NULL);
718                  MACH_CHECK_ERROR(mach_msg, krc);
719  
720 <                if (!exc_server(msg, reply)) {
720 >                if (!mach_exc_server(msg, reply)) {
721                          fprintf(stderr, "exc_server hated the message\n");
722                          exit(1);
723                  }
# Line 647 | Line 739 | handleExceptions(void *priv)
739   *  Instruction skipping
740   */
741  
742 + #ifndef SIGSEGV_REGISTER_TYPE
743 + #define SIGSEGV_REGISTER_TYPE sigsegv_uintptr_t
744 + #endif
745 +
746   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
747   // Decode and skip X86 instruction
748 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
748 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
749   #if defined(__linux__)
750   enum {
751   #if (defined(i386) || defined(__i386__))
# Line 684 | Line 780 | enum {
780   #endif
781   };
782   #endif
783 < #if defined(__NetBSD__) || defined(__FreeBSD__)
783 > #if defined(__NetBSD__)
784 > enum {
785 > #if (defined(i386) || defined(__i386__))
786 >        X86_REG_EIP = _REG_EIP,
787 >        X86_REG_EAX = _REG_EAX,
788 >        X86_REG_ECX = _REG_ECX,
789 >        X86_REG_EDX = _REG_EDX,
790 >        X86_REG_EBX = _REG_EBX,
791 >        X86_REG_ESP = _REG_ESP,
792 >        X86_REG_EBP = _REG_EBP,
793 >        X86_REG_ESI = _REG_ESI,
794 >        X86_REG_EDI = _REG_EDI
795 > #endif
796 > };
797 > #endif
798 > #if defined(__FreeBSD__)
799   enum {
800   #if (defined(i386) || defined(__i386__))
801          X86_REG_EIP = 10,
# Line 699 | Line 810 | enum {
810   #endif
811   };
812   #endif
813 < #if defined(_WIN32)
813 > #if defined(__OpenBSD__)
814 > enum {
815 > #if defined(__i386__)
816 >        // EDI is the first register we consider
817 > #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
818 > #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
819 >        X86_REG_EIP = DREG(eip), // 7
820 >        X86_REG_EAX = DREG(eax), // 6
821 >        X86_REG_ECX = DREG(ecx), // 5
822 >        X86_REG_EDX = DREG(edx), // 4
823 >        X86_REG_EBX = DREG(ebx), // 3
824 >        X86_REG_ESP = DREG(esp), // 10
825 >        X86_REG_EBP = DREG(ebp), // 2
826 >        X86_REG_ESI = DREG(esi), // 1
827 >        X86_REG_EDI = DREG(edi)  // 0
828 > #undef DREG
829 > #undef OREG
830 > #endif
831 > };
832 > #endif
833 > #if defined(__sun__)
834 > // Same as for Linux, need to check for x86-64
835 > enum {
836 > #if defined(__i386__)
837 >        X86_REG_EIP = EIP,
838 >        X86_REG_EAX = EAX,
839 >        X86_REG_ECX = ECX,
840 >        X86_REG_EDX = EDX,
841 >        X86_REG_EBX = EBX,
842 >        X86_REG_ESP = ESP,
843 >        X86_REG_EBP = EBP,
844 >        X86_REG_ESI = ESI,
845 >        X86_REG_EDI = EDI
846 > #endif
847 > };
848 > #endif
849 > #if defined(__APPLE__) && defined(__MACH__)
850   enum {
851   #if (defined(i386) || defined(__i386__))
852 + #ifdef i386_SAVED_STATE
853 +        // same as FreeBSD (in Open Darwin 8.0.1)
854 +        X86_REG_EIP = 10,
855 +        X86_REG_EAX = 7,
856 +        X86_REG_ECX = 6,
857 +        X86_REG_EDX = 5,
858 +        X86_REG_EBX = 4,
859 +        X86_REG_ESP = 13,
860 +        X86_REG_EBP = 2,
861 +        X86_REG_ESI = 1,
862 +        X86_REG_EDI = 0
863 + #else
864 +        // new layout (MacOS X 10.4.4 for x86)
865 +        X86_REG_EIP = 10,
866 +        X86_REG_EAX = 0,
867 +        X86_REG_ECX = 2,
868 +        X86_REG_EDX = 3,
869 +        X86_REG_EBX = 1,
870 +        X86_REG_ESP = 7,
871 +        X86_REG_EBP = 6,
872 +        X86_REG_ESI = 5,
873 +        X86_REG_EDI = 4
874 + #endif
875 + #endif
876 + #if defined(__x86_64__)
877 +        X86_REG_R8  = 8,
878 +        X86_REG_R9  = 9,
879 +        X86_REG_R10 = 10,
880 +        X86_REG_R11 = 11,
881 +        X86_REG_R12 = 12,
882 +        X86_REG_R13 = 13,
883 +        X86_REG_R14 = 14,
884 +        X86_REG_R15 = 15,
885 +        X86_REG_EDI = 4,
886 +        X86_REG_ESI = 5,
887 +        X86_REG_EBP = 6,
888 +        X86_REG_EBX = 1,
889 +        X86_REG_EDX = 3,
890 +        X86_REG_EAX = 0,
891 +        X86_REG_ECX = 2,
892 +        X86_REG_ESP = 7,
893 +        X86_REG_EIP = 16
894 + #endif
895 + };
896 + #endif
897 + #if defined(_WIN32)
898 + enum {
899 + #if defined(_M_IX86)
900          X86_REG_EIP = 7,
901          X86_REG_EAX = 5,
902          X86_REG_ECX = 4,
# Line 712 | Line 907 | enum {
907          X86_REG_ESI = 1,
908          X86_REG_EDI = 0
909   #endif
910 + #if defined(_M_X64)
911 +        X86_REG_EAX = 0,
912 +        X86_REG_ECX = 1,
913 +        X86_REG_EDX = 2,
914 +        X86_REG_EBX = 3,
915 +        X86_REG_ESP = 4,
916 +        X86_REG_EBP = 5,
917 +        X86_REG_ESI = 6,
918 +        X86_REG_EDI = 7,
919 +        X86_REG_R8  = 8,
920 +        X86_REG_R9  = 9,
921 +        X86_REG_R10 = 10,
922 +        X86_REG_R11 = 11,
923 +        X86_REG_R12 = 12,
924 +        X86_REG_R13 = 13,
925 +        X86_REG_R14 = 14,
926 +        X86_REG_R15 = 15,
927 +        X86_REG_EIP = 16
928 + #endif
929   };
930   #endif
931   // FIXME: this is partly redundant with the instruction decoding phase
# Line 748 | Line 962 | static inline int ix86_step_over_modrm(u
962          return offset;
963   }
964  
965 < static bool ix86_skip_instruction(unsigned long * regs)
965 > static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs)
966   {
967          unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
968  
969          if (eip == 0)
970                  return false;
971 + #ifdef _WIN32
972 +        if (IsBadCodePtr((FARPROC)eip))
973 +                return false;
974 + #endif
975          
976 +        enum instruction_type_t {
977 +                i_MOV,
978 +                i_ADD
979 +        };
980 +
981          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
982          transfer_size_t transfer_size = SIZE_LONG;
983 +        instruction_type_t instruction_type = i_MOV;
984          
985          int reg = -1;
986          int len = 0;
# Line 774 | Line 998 | static bool ix86_skip_instruction(unsign
998          }
999  
1000          // REX prefix
1001 < #if defined(__x86_64__)
1001 > #if defined(__x86_64__) || defined(_M_X64)
1002          struct rex_t {
1003                  unsigned char W;
1004                  unsigned char R;
# Line 807 | Line 1031 | static bool ix86_skip_instruction(unsign
1031   #endif
1032  
1033          // Decode instruction
1034 +        int op_len = 1;
1035          int target_size = SIZE_UNKNOWN;
1036          switch (eip[0]) {
1037          case 0x0f:
# Line 821 | Line 1046 | static bool ix86_skip_instruction(unsign
1046                          transfer_size = SIZE_WORD;
1047                          goto do_mov_extend;
1048                    do_mov_extend:
1049 <                        switch (eip[2] & 0xc0) {
1050 <                        case 0x80:
1051 <                                reg = (eip[2] >> 3) & 7;
1052 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1053 <                                break;
1054 <                        case 0x40:
1055 <                                reg = (eip[2] >> 3) & 7;
1056 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1057 <                                break;
1058 <                        case 0x00:
1059 <                                reg = (eip[2] >> 3) & 7;
1060 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1061 <                                break;
1062 <                        }
1063 <                        len += 3 + ix86_step_over_modrm(eip + 2);
1064 <                        break;
1065 <            }
1066 <          break;
1049 >                        op_len = 2;
1050 >                        goto do_transfer_load;
1051 >                }
1052 >                break;
1053 > #if defined(__x86_64__) || defined(_M_X64)
1054 >        case 0x63: // MOVSXD r64, r/m32
1055 >                if (has_rex && rex.W) {
1056 >                        transfer_size = SIZE_LONG;
1057 >                        target_size = SIZE_QUAD;
1058 >                }
1059 >                else if (transfer_size != SIZE_WORD) {
1060 >                        transfer_size = SIZE_LONG;
1061 >                        target_size = SIZE_QUAD;
1062 >                }
1063 >                goto do_transfer_load;
1064 > #endif
1065 >        case 0x02: // ADD r8, r/m8
1066 >                transfer_size = SIZE_BYTE;
1067 >        case 0x03: // ADD r32, r/m32
1068 >                instruction_type = i_ADD;
1069 >                goto do_transfer_load;
1070          case 0x8a: // MOV r8, r/m8
1071                  transfer_size = SIZE_BYTE;
1072          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1073 <                switch (eip[1] & 0xc0) {
1073 >          do_transfer_load:
1074 >                switch (eip[op_len] & 0xc0) {
1075                  case 0x80:
1076 <                        reg = (eip[1] >> 3) & 7;
1076 >                        reg = (eip[op_len] >> 3) & 7;
1077                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1078                          break;
1079                  case 0x40:
1080 <                        reg = (eip[1] >> 3) & 7;
1080 >                        reg = (eip[op_len] >> 3) & 7;
1081                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1082                          break;
1083                  case 0x00:
1084 <                        reg = (eip[1] >> 3) & 7;
1084 >                        reg = (eip[op_len] >> 3) & 7;
1085                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1086                          break;
1087                  }
1088 <                len += 2 + ix86_step_over_modrm(eip + 1);
1088 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1089                  break;
1090 +        case 0x00: // ADD r/m8, r8
1091 +                transfer_size = SIZE_BYTE;
1092 +        case 0x01: // ADD r/m32, r32
1093 +                instruction_type = i_ADD;
1094 +                goto do_transfer_store;
1095          case 0x88: // MOV r/m8, r8
1096                  transfer_size = SIZE_BYTE;
1097          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1098 <                switch (eip[1] & 0xc0) {
1098 >          do_transfer_store:
1099 >                switch (eip[op_len] & 0xc0) {
1100                  case 0x80:
1101 <                        reg = (eip[1] >> 3) & 7;
1101 >                        reg = (eip[op_len] >> 3) & 7;
1102                          transfer_type = SIGSEGV_TRANSFER_STORE;
1103                          break;
1104                  case 0x40:
1105 <                        reg = (eip[1] >> 3) & 7;
1105 >                        reg = (eip[op_len] >> 3) & 7;
1106                          transfer_type = SIGSEGV_TRANSFER_STORE;
1107                          break;
1108                  case 0x00:
1109 <                        reg = (eip[1] >> 3) & 7;
1109 >                        reg = (eip[op_len] >> 3) & 7;
1110                          transfer_type = SIGSEGV_TRANSFER_STORE;
1111                          break;
1112                  }
1113 <                len += 2 + ix86_step_over_modrm(eip + 1);
1113 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1114                  break;
1115          }
1116          if (target_size == SIZE_UNKNOWN)
# Line 886 | Line 1121 | static bool ix86_skip_instruction(unsign
1121                  return false;
1122          }
1123  
1124 < #if defined(__x86_64__)
1124 > #if defined(__x86_64__) || defined(_M_X64)
1125          if (rex.R)
1126                  reg += 8;
1127   #endif
1128  
1129 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1129 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1130                  static const int x86_reg_map[] = {
1131                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1132                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1133 < #if defined(__x86_64__)
1133 > #if defined(__x86_64__) || defined(_M_X64)
1134                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1135                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1136   #endif
# Line 927 | Line 1162 | static bool ix86_skip_instruction(unsign
1162          }
1163  
1164   #if DEBUG
1165 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1165 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1166                     transfer_size == SIZE_BYTE ? "byte" :
1167                     transfer_size == SIZE_WORD ? "word" :
1168                     transfer_size == SIZE_LONG ? "long" :
# Line 982 | Line 1217 | static bool ix86_skip_instruction(unsign
1217   }
1218   #endif
1219  
1220 + // Decode and skip IA-64 instruction
1221 + #if defined(__ia64) || defined(__ia64__)
1222 + typedef uint64_t ia64_bundle_t[2];
1223 + #if defined(__linux__)
1224 + // We can directly patch the slot number
1225 + #define IA64_CAN_PATCH_IP_SLOT  1
1226 + // Helper macros to access the machine context
1227 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1228 + #define IA64_CONTEXT                    scp
1229 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1230 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1231 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1232 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1233 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1234 + #define _IA64_SET_GR(R,V)               (IA64_CONTEXT->sc_gr[(R)] = (V))
1235 + #define _IA64_SET_NAT(I,V)              (IA64_CONTEXT->sc_nat = (IA64_CONTEXT->sc_nat & ~(1ull << (I))) | (((uint64_t)!!(V)) << (I)))
1236 + #define IA64_SET_GR(R,V,N)              (_IA64_SET_GR(R,V), _IA64_SET_NAT(R,N))
1237 +
1238 + // Load bundle (in little-endian)
1239 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1240 + {
1241 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1242 +        bundle[0] = ip[0];
1243 +        bundle[1] = ip[1];
1244 + }
1245 + #endif
1246 + #if defined(__hpux) || defined(__hpux__)
1247 + // We can directly patch the slot number
1248 + #define IA64_CAN_PATCH_IP_SLOT  1
1249 + // Helper macros to access the machine context
1250 + #define IA64_CONTEXT_TYPE               ucontext_t *
1251 + #define IA64_CONTEXT                    ucp
1252 + #define IA64_GET_IP()                   ia64_get_ip(IA64_CONTEXT)
1253 + #define IA64_SET_IP(V)                  ia64_set_ip(IA64_CONTEXT, V)
1254 + #define IA64_GET_PR(P)                  ia64_get_pr(IA64_CONTEXT, P)
1255 + #define IA64_GET_NAT(I)                 ia64_get_nat(IA64_CONTEXT, I)
1256 + #define IA64_GET_GR(R)                  ia64_get_gr(IA64_CONTEXT, R)
1257 + #define IA64_SET_GR(R,V,N)              ia64_set_gr(IA64_CONTEXT, R, V, N)
1258 + #define UC_ACCESS(FUNC,ARGS)    do { if (__uc_##FUNC ARGS != 0) abort(); } while (0)
1259 +
1260 + static inline uint64_t ia64_get_ip(IA64_CONTEXT_TYPE IA64_CONTEXT)
1261 +        { uint64_t v; UC_ACCESS(get_ip,(IA64_CONTEXT, &v)); return v; }
1262 + static inline void ia64_set_ip(IA64_CONTEXT_TYPE IA64_CONTEXT, uint64_t v)
1263 +        { UC_ACCESS(set_ip,(IA64_CONTEXT, v)); }
1264 + static inline unsigned int ia64_get_pr(IA64_CONTEXT_TYPE IA64_CONTEXT, int pr)
1265 +        { uint64_t v; UC_ACCESS(get_prs,(IA64_CONTEXT, &v)); return (v >> pr) & 1; }
1266 + static inline unsigned int ia64_get_nat(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1267 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return (nat >> r) & 1; }
1268 + static inline uint64_t ia64_get_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r)
1269 +        { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return v; }
1270 +
1271 + static void ia64_set_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r, uint64_t v, unsigned int nat)
1272 + {
1273 +        if (r == 0)
1274 +                return;
1275 +        if (r > 0 && r < 32)
1276 +                UC_ACCESS(set_grs,(IA64_CONTEXT, r, 1, &v, (!!nat) << r));
1277 +        else {
1278 +                uint64_t bsp, bspstore;
1279 +                UC_ACCESS(get_ar_bsp,(IA64_CONTEXT, &bsp));
1280 +                UC_ACCESS(get_ar_bspstore,(IA64_CONTEXT, &bspstore));
1281 +                abort(); /* XXX: use libunwind, this is not fun... */
1282 +        }
1283 + }
1284 +
1285 + // Byte-swapping
1286 + #if defined(__GNUC__)
1287 + #define BSWAP64(V) ({ uint64_t r; __asm__ __volatile__("mux1 %0=%1,@rev;;" : "=r" (r) : "r" (V)); r; })
1288 + #elif defined (__HP_aCC)
1289 + #define BSWAP64(V) _Asm_mux1(_MBTYPE_REV, V)
1290 + #else
1291 + #error "Define byte-swap instruction"
1292 + #endif
1293 +
1294 + // Load bundle (in little-endian)
1295 + static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip)
1296 + {
1297 +        uint64_t *ip = (uint64_t *)(raw_ip & ~3ull);
1298 +        bundle[0] = BSWAP64(ip[0]);
1299 +        bundle[1] = BSWAP64(ip[1]);
1300 + }
1301 + #endif
1302 +
1303 + // Instruction operations
1304 + enum {
1305 +        IA64_INST_UNKNOWN = 0,
1306 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1307 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1308 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1309 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1310 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1311 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1312 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1313 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1314 +        IA64_INST_ST1,                          // st1 [op0]=op1
1315 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1316 +        IA64_INST_ST2,                          // st2 [op0]=op1
1317 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1318 +        IA64_INST_ST4,                          // st4 [op0]=op1
1319 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1320 +        IA64_INST_ST8,                          // st8 [op0]=op1
1321 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1322 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1323 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1324 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1325 +        IA64_INST_AND,                          // and op0=op1,op2
1326 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1327 +        IA64_INST_OR,                           // or op0=op1,op2
1328 +        IA64_INST_XOR,                          // xor op0=op1,op2
1329 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1330 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1331 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1332 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1333 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1334 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1335 +        IA64_INST_NOP                           // nop op0
1336 + };
1337 +
1338 + const int IA64_N_OPERANDS = 4;
1339 +
1340 + // Decoded operand type
1341 + struct ia64_operand_t {
1342 +        uint8_t commit;                         // commit result of operation to register file?
1343 +        uint8_t valid;                          // XXX: not really used, can be removed (debug)
1344 +        int8_t index;                           // index of GPR, or -1 if immediate value
1345 +        uint8_t nat;                            // NaT state before operation
1346 +        uint64_t value;                         // register contents or immediate value
1347 + };
1348 +
1349 + // Decoded instruction type
1350 + struct ia64_instruction_t {
1351 +        uint8_t mnemo;                          // operation to perform
1352 +        uint8_t pred;                           // predicate register to check
1353 +        uint8_t no_memory;                      // used to emulated main fault instruction
1354 +        uint64_t inst;                          // the raw instruction bits (41-bit wide)
1355 +        ia64_operand_t operands[IA64_N_OPERANDS];
1356 + };
1357 +
1358 + // Get immediate sign-bit
1359 + static inline int ia64_inst_get_sbit(uint64_t inst)
1360 + {
1361 +        return (inst >> 36) & 1;
1362 + }
1363 +
1364 + // Get 8-bit immediate value (A3, A8, I27, M30)
1365 + static inline uint64_t ia64_inst_get_imm8(uint64_t inst)
1366 + {
1367 +        uint64_t value = (inst >> 13) & 0x7full;
1368 +        if (ia64_inst_get_sbit(inst))
1369 +                value |= ~0x7full;
1370 +        return value;
1371 + }
1372 +
1373 + // Get 9-bit immediate value (M3)
1374 + static inline uint64_t ia64_inst_get_imm9b(uint64_t inst)
1375 + {
1376 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1377 +        if (ia64_inst_get_sbit(inst))
1378 +                value |= ~0xffull;
1379 +        return value;
1380 + }
1381 +
1382 + // Get 9-bit immediate value (M5)
1383 + static inline uint64_t ia64_inst_get_imm9a(uint64_t inst)
1384 + {
1385 +        uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1386 +        if (ia64_inst_get_sbit(inst))
1387 +                value |= ~0xffull;
1388 +        return value;
1389 + }
1390 +
1391 + // Get 14-bit immediate value (A4)
1392 + static inline uint64_t ia64_inst_get_imm14(uint64_t inst)
1393 + {
1394 +        uint64_t value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1395 +        if (ia64_inst_get_sbit(inst))
1396 +                value |= ~0x1ffull;
1397 +        return value;
1398 + }
1399 +
1400 + // Get 22-bit immediate value (A5)
1401 + static inline uint64_t ia64_inst_get_imm22(uint64_t inst)
1402 + {
1403 +        uint64_t value = ((((inst >> 22) & 0x1f) << 16) |
1404 +                                          (((inst >> 27) & 0x1ff) << 7) |
1405 +                                          (inst & 0x7f));
1406 +        if (ia64_inst_get_sbit(inst))
1407 +                value |= ~0x1fffffull;
1408 +        return value;
1409 + }
1410 +
1411 + // Get 21-bit immediate value (I19)
1412 + static inline uint64_t ia64_inst_get_imm21(uint64_t inst)
1413 + {
1414 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1415 + }
1416 +
1417 + // Get 2-bit count value (A2)
1418 + static inline int ia64_inst_get_count2(uint64_t inst)
1419 + {
1420 +        return (inst >> 27) & 0x3;
1421 + }
1422 +
1423 + // Get bundle template
1424 + static inline unsigned int ia64_get_template(uint64_t ip)
1425 + {
1426 +        ia64_bundle_t bundle;
1427 +        ia64_load_bundle(bundle, ip);
1428 +        return bundle[0] & 0x1f;
1429 + }
1430 +
1431 + // Get specified instruction in bundle
1432 + static uint64_t ia64_get_instruction(uint64_t ip, int slot)
1433 + {
1434 +        uint64_t inst;
1435 +        ia64_bundle_t bundle;
1436 +        ia64_load_bundle(bundle, ip);
1437 + #if DEBUG
1438 +        printf("Bundle: %016llx%016llx\n", bundle[1], bundle[0]);
1439 + #endif
1440 +
1441 +        switch (slot) {
1442 +        case 0:
1443 +                inst = (bundle[0] >> 5) & 0x1ffffffffffull;
1444 +                break;
1445 +        case 1:
1446 +                inst = ((bundle[1] & 0x7fffffull) << 18) | ((bundle[0] >> 46) & 0x3ffffull);
1447 +                break;
1448 +        case 2:
1449 +                inst = (bundle[1] >> 23) & 0x1ffffffffffull;
1450 +                break;
1451 +        case 3:
1452 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1453 +                abort();
1454 +                break;
1455 +        }
1456 +
1457 + #if DEBUG
1458 +        printf(" Instruction %d: 0x%016llx\n", slot, inst);
1459 + #endif
1460 +        return inst;
1461 + }
1462 +
1463 + // Decode group 0 instructions
1464 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1465 + {
1466 +        const int r1 = (inst->inst >>  6) & 0x7f;
1467 +        const int r3 = (inst->inst >> 20) & 0x7f;
1468 +
1469 +        const int x3 = (inst->inst >> 33) & 0x07;
1470 +        const int x6 = (inst->inst >> 27) & 0x3f;
1471 +        const int x2 = (inst->inst >> 31) & 0x03;
1472 +        const int x4 = (inst->inst >> 27) & 0x0f;
1473 +
1474 +        if (x3 == 0) {
1475 +                switch (x6) {
1476 +                case 0x01:                                              // nop.i (I19)
1477 +                        inst->mnemo = IA64_INST_NOP;
1478 +                        inst->operands[0].valid = true;
1479 +                        inst->operands[0].index = -1;
1480 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1481 +                        return true;
1482 +                case 0x14:                                              // sxt1 (I29)
1483 +                case 0x15:                                              // sxt2 (I29)
1484 +                case 0x16:                                              // sxt4 (I29)
1485 +                case 0x10:                                              // zxt1 (I29)
1486 +                case 0x11:                                              // zxt2 (I29)
1487 +                case 0x12:                                              // zxt4 (I29)
1488 +                        switch (x6) {
1489 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1490 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1491 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1492 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1493 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1494 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1495 +                        default: abort();
1496 +                        }
1497 +                        inst->operands[0].valid = true;
1498 +                        inst->operands[0].index = r1;
1499 +                        inst->operands[1].valid = true;
1500 +                        inst->operands[1].index = r3;
1501 +                        inst->operands[1].value = IA64_GET_GR(r3);
1502 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1503 +                        return true;
1504 +                }
1505 +        }
1506 +        return false;
1507 + }
1508 +
1509 + // Decode group 4 instructions (load/store instructions)
1510 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1511 + {
1512 +        const int r1 = (inst->inst >> 6) & 0x7f;
1513 +        const int r2 = (inst->inst >> 13) & 0x7f;
1514 +        const int r3 = (inst->inst >> 20) & 0x7f;
1515 +
1516 +        const int m  = (inst->inst >> 36) & 1;
1517 +        const int x  = (inst->inst >> 27) & 1;
1518 +        const int x6 = (inst->inst >> 30) & 0x3f;
1519 +
1520 +        switch (x6) {
1521 +        case 0x00:
1522 +        case 0x01:
1523 +        case 0x02:
1524 +        case 0x03:
1525 +                if (x == 0) {
1526 +                        inst->operands[0].valid = true;
1527 +                        inst->operands[0].index = r1;
1528 +                        inst->operands[1].valid = true;
1529 +                        inst->operands[1].index = r3;
1530 +                        inst->operands[1].value = IA64_GET_GR(r3);
1531 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1532 +                        if (m == 0) {
1533 +                                switch (x6) {
1534 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1535 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1536 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1537 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1538 +                                }
1539 +                        }
1540 +                        else {
1541 +                                inst->operands[2].valid = true;
1542 +                                inst->operands[2].index = r2;
1543 +                                inst->operands[2].value = IA64_GET_GR(r2);
1544 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1545 +                                switch (x6) {
1546 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1547 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1548 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1549 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1550 +                                }
1551 +                        }
1552 +                        return true;
1553 +                }
1554 +                break;
1555 +        case 0x30:
1556 +        case 0x31:
1557 +        case 0x32:
1558 +        case 0x33:
1559 +                if (m == 0 && x == 0) {
1560 +                        inst->operands[0].valid = true;
1561 +                        inst->operands[0].index = r3;
1562 +                        inst->operands[0].value = IA64_GET_GR(r3);
1563 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1564 +                        inst->operands[1].valid = true;
1565 +                        inst->operands[1].index = r2;
1566 +                        inst->operands[1].value = IA64_GET_GR(r2);
1567 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1568 +                        switch (x6) {
1569 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1570 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1571 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1572 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1573 +                        }
1574 +                        return true;
1575 +                }
1576 +                break;
1577 +        }
1578 +        return false;
1579 + }
1580 +
1581 + // Decode group 5 instructions (load/store instructions)
1582 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1583 + {
1584 +        const int r1 = (inst->inst >> 6) & 0x7f;
1585 +        const int r2 = (inst->inst >> 13) & 0x7f;
1586 +        const int r3 = (inst->inst >> 20) & 0x7f;
1587 +
1588 +        const int x6 = (inst->inst >> 30) & 0x3f;
1589 +
1590 +        switch (x6) {
1591 +        case 0x00:
1592 +        case 0x01:
1593 +        case 0x02:
1594 +        case 0x03:
1595 +                inst->operands[0].valid = true;
1596 +                inst->operands[0].index = r1;
1597 +                inst->operands[1].valid = true;
1598 +                inst->operands[1].index = r3;
1599 +                inst->operands[1].value = IA64_GET_GR(r3);
1600 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1601 +                inst->operands[2].valid = true;
1602 +                inst->operands[2].index = -1;
1603 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1604 +                inst->operands[2].nat   = 0;
1605 +                switch (x6) {
1606 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1607 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1608 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1609 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1610 +                }
1611 +                return true;
1612 +        case 0x30:
1613 +        case 0x31:
1614 +        case 0x32:
1615 +        case 0x33:
1616 +                inst->operands[0].valid = true;
1617 +                inst->operands[0].index = r3;
1618 +                inst->operands[0].value = IA64_GET_GR(r3);
1619 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1620 +                inst->operands[1].valid = true;
1621 +                inst->operands[1].index = r2;
1622 +                inst->operands[1].value = IA64_GET_GR(r2);
1623 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1624 +                inst->operands[2].valid = true;
1625 +                inst->operands[2].index = -1;
1626 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1627 +                inst->operands[2].nat   = 0;
1628 +                switch (x6) {
1629 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1630 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1631 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1632 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1633 +                }
1634 +                return true;
1635 +        }
1636 +        return false;
1637 + }
1638 +
1639 + // Decode group 8 instructions (ALU integer)
1640 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1641 + {
1642 +        const int r1  = (inst->inst >> 6) & 0x7f;
1643 +        const int r2  = (inst->inst >> 13) & 0x7f;
1644 +        const int r3  = (inst->inst >> 20) & 0x7f;
1645 +
1646 +        const int x2a = (inst->inst >> 34) & 0x3;
1647 +        const int x2b = (inst->inst >> 27) & 0x3;
1648 +        const int x4  = (inst->inst >> 29) & 0xf;
1649 +        const int ve  = (inst->inst >> 33) & 0x1;
1650 +
1651 +        // destination register (r1) is always valid in this group
1652 +        inst->operands[0].valid = true;
1653 +        inst->operands[0].index = r1;
1654 +
1655 +        // source register (r3) is always valid in this group
1656 +        inst->operands[2].valid = true;
1657 +        inst->operands[2].index = r3;
1658 +        inst->operands[2].value = IA64_GET_GR(r3);
1659 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1660 +
1661 +        if (x2a == 0 && ve == 0) {
1662 +                inst->operands[1].valid = true;
1663 +                inst->operands[1].index = r2;
1664 +                inst->operands[1].value = IA64_GET_GR(r2);
1665 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1666 +                switch (x4) {
1667 +                case 0x0:                               // add (A1)
1668 +                        inst->mnemo = IA64_INST_ADD;
1669 +                        inst->operands[3].valid = true;
1670 +                        inst->operands[3].index = -1;
1671 +                        inst->operands[3].value = x2b == 1;
1672 +                        return true;
1673 +                case 0x1:                               // add (A1)
1674 +                        inst->mnemo = IA64_INST_SUB;
1675 +                        inst->operands[3].valid = true;
1676 +                        inst->operands[3].index = -1;
1677 +                        inst->operands[3].value = x2b == 0;
1678 +                        return true;
1679 +                case 0x4:                               // shladd (A2)
1680 +                        inst->mnemo = IA64_INST_SHLADD;
1681 +                        inst->operands[3].valid = true;
1682 +                        inst->operands[3].index = -1;
1683 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1684 +                        return true;
1685 +                case 0x9:
1686 +                        if (x2b == 1) {
1687 +                                inst->mnemo = IA64_INST_SUB;
1688 +                                inst->operands[1].index = -1;
1689 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1690 +                                inst->operands[1].nat   = 0;
1691 +                                return true;
1692 +                        }
1693 +                        break;
1694 +                case 0xb:
1695 +                        inst->operands[1].index = -1;
1696 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1697 +                        inst->operands[1].nat   = 0;
1698 +                        // fall-through
1699 +                case 0x3:
1700 +                        switch (x2b) {
1701 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1702 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1703 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1704 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1705 +                        }
1706 +                        return true;
1707 +                }
1708 +        }
1709 +        return false;
1710 + }
1711 +
1712 + // Decode instruction
1713 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1714 + {
1715 +        const int major = (inst->inst >> 37) & 0xf;
1716 +
1717 +        inst->mnemo = IA64_INST_UNKNOWN;
1718 +        inst->pred  = inst->inst & 0x3f;
1719 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1720 +
1721 +        switch (major) {
1722 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1723 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1724 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1725 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1726 +        }
1727 +        return false;
1728 + }
1729 +
1730 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1731 + {
1732 +        // XXX: handle Register NaT Consumption fault?
1733 +        // XXX: this simple emulator assumes instructions in a bundle
1734 +        // don't depend on effects of other instructions in the same
1735 +        // bundle. It probably would be simpler to JIT-generate code to be
1736 +        // executed natively but probably more costly (inject/extract CPU state)
1737 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1738 +                return false;
1739 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1740 +                return true;
1741 +
1742 +        uint8_t nat, nat2;
1743 +        uint64_t dst, dst2, src1, src2, src3;
1744 +
1745 +        switch (inst->mnemo) {
1746 +        case IA64_INST_NOP:
1747 +                break;
1748 +        case IA64_INST_ADD:
1749 +        case IA64_INST_SUB:
1750 +        case IA64_INST_SHLADD:
1751 +                src3 = inst->operands[3].value;
1752 +                // fall-through
1753 +        case IA64_INST_AND:
1754 +        case IA64_INST_ANDCM:
1755 +        case IA64_INST_OR:
1756 +        case IA64_INST_XOR:
1757 +                src1 = inst->operands[1].value;
1758 +                src2 = inst->operands[2].value;
1759 +                switch (inst->mnemo) {
1760 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1761 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1762 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1763 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1764 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1765 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1766 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1767 +                }
1768 +                inst->operands[0].commit = true;
1769 +                inst->operands[0].value  = dst;
1770 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1771 +                break;
1772 +        case IA64_INST_SXT1:
1773 +        case IA64_INST_SXT2:
1774 +        case IA64_INST_SXT4:
1775 +        case IA64_INST_ZXT1:
1776 +        case IA64_INST_ZXT2:
1777 +        case IA64_INST_ZXT4:
1778 +                src1 = inst->operands[1].value;
1779 +                switch (inst->mnemo) {
1780 +                case IA64_INST_SXT1: dst = (int64_t)(int8_t)src1;               break;
1781 +                case IA64_INST_SXT2: dst = (int64_t)(int16_t)src1;              break;
1782 +                case IA64_INST_SXT4: dst = (int64_t)(int32_t)src1;              break;
1783 +                case IA64_INST_ZXT1: dst = (uint8_t)src1;                               break;
1784 +                case IA64_INST_ZXT2: dst = (uint16_t)src1;                              break;
1785 +                case IA64_INST_ZXT4: dst = (uint32_t)src1;                              break;
1786 +                }
1787 +                inst->operands[0].commit = true;
1788 +                inst->operands[0].value  = dst;
1789 +                inst->operands[0].nat    = inst->operands[1].nat;
1790 +                break;
1791 +        case IA64_INST_LD1_UPDATE:
1792 +        case IA64_INST_LD2_UPDATE:
1793 +        case IA64_INST_LD4_UPDATE:
1794 +        case IA64_INST_LD8_UPDATE:
1795 +                inst->operands[1].commit = true;
1796 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1797 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1798 +                // fall-through
1799 +        case IA64_INST_LD1:
1800 +        case IA64_INST_LD2:
1801 +        case IA64_INST_LD4:
1802 +        case IA64_INST_LD8:
1803 +                src1 = inst->operands[1].value;
1804 +                if (inst->no_memory)
1805 +                        dst = 0;
1806 +                else {
1807 +                        switch (inst->mnemo) {
1808 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((uint8_t *)src1);        break;
1809 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((uint16_t *)src1);       break;
1810 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((uint32_t *)src1);       break;
1811 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((uint64_t *)src1);       break;
1812 +                        }
1813 +                }
1814 +                inst->operands[0].commit = true;
1815 +                inst->operands[0].value  = dst;
1816 +                inst->operands[0].nat    = 0;
1817 +                inst->operands[1].value  = dst2;
1818 +                inst->operands[1].nat    = nat2;
1819 +                break;
1820 +        case IA64_INST_ST1_UPDATE:
1821 +        case IA64_INST_ST2_UPDATE:
1822 +        case IA64_INST_ST4_UPDATE:
1823 +        case IA64_INST_ST8_UPDATE:
1824 +                inst->operands[0].commit = 0;
1825 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1826 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1827 +                // fall-through
1828 +        case IA64_INST_ST1:
1829 +        case IA64_INST_ST2:
1830 +        case IA64_INST_ST4:
1831 +        case IA64_INST_ST8:
1832 +                dst  = inst->operands[0].value;
1833 +                src1 = inst->operands[1].value;
1834 +                if (!inst->no_memory) {
1835 +                        switch (inst->mnemo) {
1836 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((uint8_t *)dst) = src1;        break;
1837 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((uint16_t *)dst) = src1;       break;
1838 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((uint32_t *)dst) = src1;       break;
1839 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((uint64_t *)dst) = src1;       break;
1840 +                        }
1841 +                }
1842 +                inst->operands[0].value  = dst2;
1843 +                inst->operands[0].nat    = nat2;
1844 +                break;
1845 +        default:
1846 +                return false;
1847 +        }
1848 +
1849 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1850 +                ia64_operand_t const & op = inst->operands[i];
1851 +                if (!op.commit)
1852 +                        continue;
1853 +                if (op.index == -1)
1854 +                        return false; // XXX: internal error
1855 +                IA64_SET_GR(op.index, op.value, op.nat);
1856 +        }
1857 +        return true;
1858 + }
1859 +
1860 + static bool ia64_emulate_instruction(uint64_t raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1861 + {
1862 +        ia64_instruction_t inst;
1863 +        memset(&inst, 0, sizeof(inst));
1864 +        inst.inst = raw_inst;
1865 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1866 +                return false;
1867 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1868 + }
1869 +
1870 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1871 + {
1872 +        uint64_t ip = IA64_GET_IP();
1873 + #if DEBUG
1874 +        printf("IP: 0x%016llx\n", ip);
1875 + #if 0
1876 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1877 +        ia64_get_instruction(ip, 0);
1878 +        ia64_get_instruction(ip, 1);
1879 +        ia64_get_instruction(ip, 2);
1880 + #endif
1881 + #endif
1882 +
1883 +        // Select which decode switch to use
1884 +        ia64_instruction_t inst;
1885 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1886 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1887 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1888 +                return false;
1889 +        }
1890 +
1891 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1892 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1893 +
1894 +        switch (inst.mnemo) {
1895 +        case IA64_INST_LD1:
1896 +        case IA64_INST_LD2:
1897 +        case IA64_INST_LD4:
1898 +        case IA64_INST_LD8:
1899 +        case IA64_INST_LD1_UPDATE:
1900 +        case IA64_INST_LD2_UPDATE:
1901 +        case IA64_INST_LD4_UPDATE:
1902 +        case IA64_INST_LD8_UPDATE:
1903 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1904 +                break;
1905 +        case IA64_INST_ST1:
1906 +        case IA64_INST_ST2:
1907 +        case IA64_INST_ST4:
1908 +        case IA64_INST_ST8:
1909 +        case IA64_INST_ST1_UPDATE:
1910 +        case IA64_INST_ST2_UPDATE:
1911 +        case IA64_INST_ST4_UPDATE:
1912 +        case IA64_INST_ST8_UPDATE:
1913 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1914 +                break;
1915 +        }
1916 +
1917 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1918 +                // Unknown machine code, let it crash. Then patch the decoder
1919 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1920 +                return false;
1921 +        }
1922 +
1923 +        switch (inst.mnemo) {
1924 +        case IA64_INST_LD1:
1925 +        case IA64_INST_LD1_UPDATE:
1926 +        case IA64_INST_ST1:
1927 +        case IA64_INST_ST1_UPDATE:
1928 +                transfer_size = SIZE_BYTE;
1929 +                break;
1930 +        case IA64_INST_LD2:
1931 +        case IA64_INST_LD2_UPDATE:
1932 +        case IA64_INST_ST2:
1933 +        case IA64_INST_ST2_UPDATE:
1934 +                transfer_size = SIZE_WORD;
1935 +                break;
1936 +        case IA64_INST_LD4:
1937 +        case IA64_INST_LD4_UPDATE:
1938 +        case IA64_INST_ST4:
1939 +        case IA64_INST_ST4_UPDATE:
1940 +                transfer_size = SIZE_LONG;
1941 +                break;
1942 +        case IA64_INST_LD8:
1943 +        case IA64_INST_LD8_UPDATE:
1944 +        case IA64_INST_ST8:
1945 +        case IA64_INST_ST8_UPDATE:
1946 +                transfer_size = SIZE_QUAD;
1947 +                break;
1948 +        }
1949 +
1950 +        if (transfer_size == SIZE_UNKNOWN) {
1951 +                // Unknown machine code, let it crash. Then patch the decoder
1952 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1953 +                return false;
1954 +        }
1955 +
1956 +        inst.no_memory = true;
1957 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1958 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1959 +                return false;
1960 +        }
1961 +
1962 +        int slot = ip & 3;
1963 +        bool emulate_next = false;
1964 +        switch (slot) {
1965 +        case 0:
1966 +                switch (ia64_get_template(ip)) {
1967 +                case 0x2: // MI;I
1968 +                case 0x3: // MI;I;
1969 +                        emulate_next = true;
1970 +                        slot = 2;
1971 +                        break;
1972 +                case 0xa: // M;MI
1973 +                case 0xb: // M;MI;
1974 +                        emulate_next = true;
1975 +                        slot = 1;
1976 +                        break;
1977 +                }
1978 +                break;
1979 +        }
1980 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
1981 +                while (slot < 3) {
1982 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
1983 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
1984 +                                return false;
1985 +                        }
1986 +                        ++slot;
1987 +                }
1988 +        }
1989 +
1990 + #if IA64_CAN_PATCH_IP_SLOT
1991 +        if ((slot = ip & 3) < 2)
1992 +                IA64_SET_IP((ip & ~3ull) + (slot + 1));
1993 +        else
1994 + #endif
1995 +                IA64_SET_IP((ip & ~3ull) + 16);
1996 + #if DEBUG
1997 +        printf("IP: 0x%016llx\n", IA64_GET_IP());
1998 + #endif
1999 +        return true;
2000 + }
2001 + #endif
2002 +
2003   // Decode and skip PPC instruction
2004 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
2004 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
2005   static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
2006   {
2007          instruction_t instr;
# Line 1019 | Line 2037 | static bool powerpc_skip_instruction(uns
2037  
2038   // Decode and skip MIPS instruction
2039   #if (defined(mips) || defined(__mips))
2040 < enum {
1023 < #if (defined(sgi) || defined(__sgi))
1024 <  MIPS_REG_EPC = 35,
1025 < #endif
1026 < };
1027 < static bool mips_skip_instruction(greg_t * regs)
2040 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
2041   {
2042 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
2042 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
2043  
2044    if (epc == 0)
2045          return false;
# Line 1175 | Line 2188 | static bool mips_skip_instruction(greg_t
2188                   mips_gpr_names[reg]);
2189   #endif
2190  
2191 <  regs[MIPS_REG_EPC] += 4;
2191 >  *pc_p += 4;
2192    return true;
2193   }
2194   #endif
# Line 1187 | Line 2200 | enum {
2200    SPARC_REG_G1 = REG_G1,
2201    SPARC_REG_O0 = REG_O0,
2202    SPARC_REG_PC = REG_PC,
2203 +  SPARC_REG_nPC = REG_nPC
2204   #endif
2205   };
2206   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1250 | Line 2264 | static bool sparc_skip_instruction(unsig
2264          break;
2265    case 7: // Store Doubleword
2266          transfer_type = SIGSEGV_TRANSFER_STORE;
2267 <        transfer_size = SIZE_WORD;
2267 >        transfer_size = SIZE_LONG;
2268          register_pair = true;
2269          break;
2270    }
# Line 1260 | Line 2274 | static bool sparc_skip_instruction(unsig
2274          return false;
2275    }
2276  
1263  // Zero target register in case of a load operation
2277    const int reg = (opcode >> 25) & 0x1f;
2278 +
2279 + #if DEBUG
2280 +  static const char * reg_names[] = {
2281 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2282 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2283 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2284 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2285 +  };
2286 +  printf("%s %s register %s\n",
2287 +                 transfer_size == SIZE_BYTE ? "byte" :
2288 +                 transfer_size == SIZE_WORD ? "word" :
2289 +                 transfer_size == SIZE_LONG ? "long" :
2290 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2291 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2292 +                 reg_names[reg]);
2293 + #endif
2294 +
2295 +  // Zero target register in case of a load operation
2296    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2297          // FIXME: code to handle local & input registers is not tested
2298 <        if (reg >= 1 && reg <= 7) {
2298 >        if (reg >= 1 && reg < 8) {
2299            // global registers
2300            regs[reg - 1 + SPARC_REG_G1] = 0;
2301          }
2302 <        else if (reg >= 8 && reg <= 15) {
2302 >        else if (reg >= 8 && reg < 16) {
2303            // output registers
2304            regs[reg - 8 + SPARC_REG_O0] = 0;
2305          }
2306 <        else if (reg >= 16 && reg <= 23) {
2306 >        else if (reg >= 16 && reg < 24) {
2307            // local registers (in register windows)
2308            if (gwins)
2309                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1288 | Line 2319 | static bool sparc_skip_instruction(unsig
2319          }
2320    }
2321  
1291 #if DEBUG
1292  static const char * reg_names[] = {
1293        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1294        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1295        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1296        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1297  };
1298  printf("%s %s register %s\n",
1299                 transfer_size == SIZE_BYTE ? "byte" :
1300                 transfer_size == SIZE_WORD ? "word" :
1301                 transfer_size == SIZE_LONG ? "long" :
1302                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1303                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1304                 reg_names[reg]);
1305 #endif
1306
2322    regs[SPARC_REG_PC] += 4;
2323 +  regs[SPARC_REG_nPC] += 4;
2324    return true;
2325   }
2326   #endif
# Line 1460 | Line 2476 | static bool arm_skip_instruction(unsigne
2476  
2477  
2478   // Fallbacks
2479 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2480 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2481 + #endif
2482 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2483 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2484 + #endif
2485   #ifndef SIGSEGV_FAULT_INSTRUCTION
2486 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2486 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2487   #endif
2488   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2489   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2490   #endif
2491   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2492 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2492 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2493   #endif
2494  
2495   // SIGSEGV recovery supported ?
# Line 1480 | Line 2502 | static bool arm_skip_instruction(unsigne
2502   *  SIGSEGV global handler
2503   */
2504  
2505 + #ifdef HAVE_MACH_EXCEPTIONS
2506 + static void mach_get_exception_state(sigsegv_info_t *SIP)
2507 + {
2508 +        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2509 +        kern_return_t krc = thread_get_state(SIP->thread,
2510 +                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2511 +                                                                                 (natural_t *)&SIP->exc_state,
2512 +                                                                                 &SIP->exc_state_count);
2513 +        MACH_CHECK_ERROR(thread_get_state, krc);
2514 +        SIP->has_exc_state = true;
2515 + }
2516 +
2517 + static void mach_get_thread_state(sigsegv_info_t *SIP)
2518 + {
2519 +        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2520 +        kern_return_t krc = thread_get_state(SIP->thread,
2521 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2522 +                                                                                 (natural_t *)&SIP->thr_state,
2523 +                                                                                 &SIP->thr_state_count);
2524 +        MACH_CHECK_ERROR(thread_get_state, krc);
2525 +        SIP->has_thr_state = true;
2526 + }
2527 +
2528 + static void mach_set_thread_state(sigsegv_info_t *SIP)
2529 + {
2530 +        kern_return_t krc = thread_set_state(SIP->thread,
2531 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2532 +                                                                                 (natural_t *)&SIP->thr_state,
2533 +                                                                                 SIP->thr_state_count);
2534 +        MACH_CHECK_ERROR(thread_set_state, krc);
2535 + }
2536 + #endif
2537 +
2538 + // Return the address of the invalid memory reference
2539 + sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2540 + {
2541 + #ifdef HAVE_MACH_EXCEPTIONS
2542 + #ifdef EMULATED_PPC
2543 +        static int use_fast_path = -1;
2544 +        if (use_fast_path != 1 && !SIP->has_exc_state) {
2545 +                mach_get_exception_state(SIP);
2546 +
2547 +                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2548 +                if (use_fast_path < 0) {
2549 +                        const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2550 +                        if (machfault) {
2551 +                                if (strcmp(machfault, "fast") == 0)
2552 +                                        use_fast_path = 1;
2553 +                                else if (strcmp(machfault, "slow") == 0)
2554 +                                        use_fast_path = 0;
2555 +                        }
2556 +                        if (use_fast_path < 0)
2557 +                                use_fast_path = addr == SIP->addr;
2558 +                }
2559 +                SIP->addr = addr;
2560 +        }
2561 + #endif
2562 + #endif
2563 +        return SIP->addr;
2564 + }
2565 +
2566 + // Return the address of the instruction that caused the fault, or
2567 + // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2568 + sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2569 + {
2570 + #ifdef HAVE_MACH_EXCEPTIONS
2571 + #ifdef EMULATED_PPC
2572 +        if (!SIP->has_thr_state) {
2573 +                mach_get_thread_state(SIP);
2574 +
2575 +                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2576 +        }
2577 + #endif
2578 + #endif
2579 +        return SIP->pc;
2580 + }
2581 +
2582   // This function handles the badaccess to memory.
2583   // It is called from the signal handler or the exception handler.
2584   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2585   {
2586 <        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2587 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2588 <        
2586 >        sigsegv_info_t SI;
2587 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2588 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2589 > #ifdef HAVE_MACH_EXCEPTIONS
2590 >        SI.thread = thread;
2591 >        SI.has_exc_state = false;
2592 >        SI.has_thr_state = false;
2593 > #endif
2594 >        sigsegv_info_t * const SIP = &SI;
2595 >
2596          // Call user's handler and reinstall the global handler, if required
2597 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2597 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2598          case SIGSEGV_RETURN_SUCCESS:
2599                  return true;
2600  
# Line 1496 | Line 2602 | static bool handle_badaccess(SIGSEGV_FAU
2602          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2603                  // Call the instruction skipper with the register file
2604                  // available
2605 + #ifdef HAVE_MACH_EXCEPTIONS
2606 +                if (!SIP->has_thr_state)
2607 +                        mach_get_thread_state(SIP);
2608 + #endif
2609                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2610   #ifdef HAVE_MACH_EXCEPTIONS
2611                          // Unlike UNIX signals where the thread state
2612                          // is modified off of the stack, in Mach we
2613                          // need to actually call thread_set_state to
2614                          // have the register values updated.
2615 <                        kern_return_t krc;
1506 <
1507 <                        krc = thread_set_state(thread,
1508 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1509 <                                                                   MACHINE_THREAD_STATE_COUNT);
1510 <                        MACH_CHECK_ERROR (thread_get_state, krc);
2615 >                        mach_set_thread_state(SIP);
2616   #endif
2617                          return true;
2618                  }
2619                  break;
2620   #endif
2621          case SIGSEGV_RETURN_FAILURE:
2622 <                return false;
2622 >                // We can't do anything with the fault_address, dump state?
2623 >                if (sigsegv_state_dumper != 0)
2624 >                        sigsegv_state_dumper(SIP);
2625 >                break;
2626          }
1519        
1520        // We can't do anything with the fault_address, dump state?
1521        if (sigsegv_state_dumper != 0)
1522                sigsegv_state_dumper(fault_address, fault_instruction);
2627  
2628          return false;
2629   }
# Line 1550 | Line 2654 | static inline kern_return_t
2654   forward_exception(mach_port_t thread_port,
2655                                    mach_port_t task_port,
2656                                    exception_type_t exception_type,
2657 <                                  exception_data_t exception_data,
2657 >                                  mach_exception_data_t exception_data,
2658                                    mach_msg_type_number_t data_count,
2659                                    ExceptionPorts *oldExceptionPorts)
2660   {
# Line 1559 | Line 2663 | forward_exception(mach_port_t thread_por
2663          mach_port_t port;
2664          exception_behavior_t behavior;
2665          thread_state_flavor_t flavor;
2666 <        thread_state_t thread_state;
2666 >        thread_state_data_t thread_state;
2667          mach_msg_type_number_t thread_state_count;
2668  
2669          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1578 | Line 2682 | forward_exception(mach_port_t thread_por
2682          behavior = oldExceptionPorts->behaviors[portIndex];
2683          flavor = oldExceptionPorts->flavors[portIndex];
2684  
2685 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2686 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2687 +                return KERN_FAILURE;
2688 +        }
2689 +
2690          /*
2691           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2692           */
2693  
2694          if (behavior != EXCEPTION_DEFAULT) {
2695                  thread_state_count = THREAD_STATE_MAX;
2696 <                kret = thread_get_state (thread_port, flavor, thread_state,
2696 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2697                                                                   &thread_state_count);
2698                  MACH_CHECK_ERROR (thread_get_state, kret);
2699          }
# Line 1592 | Line 2701 | forward_exception(mach_port_t thread_por
2701          switch (behavior) {
2702          case EXCEPTION_DEFAULT:
2703            // fprintf(stderr, "forwarding to exception_raise\n");
2704 <          kret = exception_raise(port, thread_port, task_port, exception_type,
2705 <                                                         exception_data, data_count);
2706 <          MACH_CHECK_ERROR (exception_raise, kret);
2704 >          kret = mach_exception_raise(port, thread_port, task_port, exception_type,
2705 >                                                                  exception_data, data_count);
2706 >          MACH_CHECK_ERROR (mach_exception_raise, kret);
2707            break;
2708          case EXCEPTION_STATE:
2709            // fprintf(stderr, "forwarding to exception_raise_state\n");
2710 <          kret = exception_raise_state(port, exception_type, exception_data,
2711 <                                                                   data_count, &flavor,
2712 <                                                                   thread_state, thread_state_count,
2713 <                                                                   thread_state, &thread_state_count);
2714 <          MACH_CHECK_ERROR (exception_raise_state, kret);
2710 >          kret = mach_exception_raise_state(port, exception_type, exception_data,
2711 >                                                                                data_count, &flavor,
2712 >                                                                                (natural_t *)&thread_state, thread_state_count,
2713 >                                                                                (natural_t *)&thread_state, &thread_state_count);
2714 >          MACH_CHECK_ERROR (mach_exception_raise_state, kret);
2715            break;
2716          case EXCEPTION_STATE_IDENTITY:
2717            // fprintf(stderr, "forwarding to exception_raise_state_identity\n");
2718 <          kret = exception_raise_state_identity(port, thread_port, task_port,
2719 <                                                                                        exception_type, exception_data,
2720 <                                                                                        data_count, &flavor,
2721 <                                                                                        thread_state, thread_state_count,
2722 <                                                                                        thread_state, &thread_state_count);
2723 <          MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2718 >          kret = mach_exception_raise_state_identity(port, thread_port, task_port,
2719 >                                                                                                 exception_type, exception_data,
2720 >                                                                                                 data_count, &flavor,
2721 >                                                                                                 (natural_t *)&thread_state, thread_state_count,
2722 >                                                                                                 (natural_t *)&thread_state, &thread_state_count);
2723 >          MACH_CHECK_ERROR (mach_exception_raise_state_identity, kret);
2724            break;
2725          default:
2726            fprintf(stderr, "forward_exception got unknown behavior\n");
2727 +          kret = KERN_FAILURE;
2728            break;
2729          }
2730  
2731          if (behavior != EXCEPTION_DEFAULT) {
2732 <                kret = thread_set_state (thread_port, flavor, thread_state,
2732 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2733                                                                   thread_state_count);
2734                  MACH_CHECK_ERROR (thread_set_state, kret);
2735          }
2736  
2737 <        return KERN_SUCCESS;
2737 >        return kret;
2738   }
2739  
2740   /*
# Line 1647 | Line 2757 | forward_exception(mach_port_t thread_por
2757   * linkage because that is what exc_server expects.
2758   */
2759   kern_return_t
2760 < catch_exception_raise(mach_port_t exception_port,
2761 <                                          mach_port_t thread,
2762 <                                          mach_port_t task,
2763 <                                          exception_type_t exception,
2764 <                                          exception_data_t code,
2765 <                                          mach_msg_type_number_t codeCount)
2760 > catch_mach_exception_raise(mach_port_t exception_port,
2761 >                                                   mach_port_t thread,
2762 >                                                   mach_port_t task,
2763 >                                                   exception_type_t exception,
2764 >                                                   mach_exception_data_t code,
2765 >                                                   mach_msg_type_number_t code_count)
2766   {
1657        ppc_thread_state_t state;
2767          kern_return_t krc;
2768  
2769 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2770 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2771 <                        return KERN_SUCCESS;
2769 >        if (exception == EXC_BAD_ACCESS) {
2770 >                switch (code[0]) {
2771 >                case KERN_PROTECTION_FAILURE:
2772 >                case KERN_INVALID_ADDRESS:
2773 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2774 >                                return KERN_SUCCESS;
2775 >                        break;
2776 >                }
2777          }
2778  
2779          // In Mach we do not need to remove the exception handler.
2780          // If we forward the exception, eventually some exception handler
2781          // will take care of this exception.
2782 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2782 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2783  
2784          return krc;
2785   }
2786 +
2787 + /* XXX: borrowed from launchd and gdb */
2788 + kern_return_t
2789 + catch_mach_exception_raise_state(mach_port_t exception_port,
2790 +                                                                 exception_type_t exception,
2791 +                                                                 mach_exception_data_t code,
2792 +                                                                 mach_msg_type_number_t code_count,
2793 +                                                                 int *flavor,
2794 +                                                                 thread_state_t old_state,
2795 +                                                                 mach_msg_type_number_t old_state_count,
2796 +                                                                 thread_state_t new_state,
2797 +                                                                 mach_msg_type_number_t *new_state_count)
2798 + {
2799 +        memcpy(new_state, old_state, old_state_count * sizeof(old_state[0]));
2800 +        *new_state_count = old_state_count;
2801 +        return KERN_SUCCESS;
2802 + }
2803 +
2804 + /* XXX: borrowed from launchd and gdb */
2805 + kern_return_t
2806 + catch_mach_exception_raise_state_identity(mach_port_t exception_port,
2807 +                                                                                  mach_port_t thread_port,
2808 +                                                                                  mach_port_t task_port,
2809 +                                                                                  exception_type_t exception,
2810 +                                                                                  mach_exception_data_t code,
2811 +                                                                                  mach_msg_type_number_t code_count,
2812 +                                                                                  int *flavor,
2813 +                                                                                  thread_state_t old_state,
2814 +                                                                                  mach_msg_type_number_t old_state_count,
2815 +                                                                                  thread_state_t new_state,
2816 +                                                                                  mach_msg_type_number_t *new_state_count)
2817 + {
2818 +        kern_return_t kret;
2819 +
2820 +        memcpy(new_state, old_state, old_state_count * sizeof(old_state[0]));
2821 +        *new_state_count = old_state_count;
2822 +
2823 +        kret = mach_port_deallocate(mach_task_self(), task_port);
2824 +        MACH_CHECK_ERROR(mach_port_deallocate, kret);
2825 +        kret = mach_port_deallocate(mach_task_self(), thread_port);
2826 +        MACH_CHECK_ERROR(mach_port_deallocate, kret);
2827 +
2828 +        return KERN_SUCCESS;
2829 + }
2830   #endif
2831  
2832   #ifdef HAVE_SIGSEGV_RECOVERY
# Line 1793 | Line 2951 | static bool sigsegv_do_install_handler(s
2951          // addressing modes) used in PPC instructions, you will need the
2952          // GPR state anyway.
2953          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2954 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2954 >                                EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, SIGSEGV_THREAD_STATE_FLAVOR);
2955          if (krc != KERN_SUCCESS) {
2956                  mach_error("thread_set_exception_ports", krc);
2957                  return false;
# Line 1821 | Line 2979 | static LONG WINAPI main_exception_filter
2979   {
2980          if (sigsegv_fault_handler != NULL
2981                  && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
2982 <                && ExceptionInfo->ExceptionRecord->NumberParameters == 2
2982 >                && ExceptionInfo->ExceptionRecord->NumberParameters >= 2
2983                  && handle_badaccess(ExceptionInfo))
2984                  return EXCEPTION_CONTINUE_EXECUTION;
2985  
# Line 1973 | Line 3131 | void sigsegv_set_dump_state(sigsegv_stat
3131   const int REF_INDEX = 123;
3132   const int REF_VALUE = 45;
3133  
3134 < static int page_size;
3134 > static sigsegv_uintptr_t page_size;
3135   static volatile char * page = 0;
3136   static volatile int handler_called = 0;
3137  
3138 + /* Barriers */
3139 + #ifdef __GNUC__
3140 + #define BARRIER() asm volatile ("" : : : "memory")
3141 + #else
3142 + #define BARRIER() /* nothing */
3143 + #endif
3144 +
3145   #ifdef __GNUC__
3146   // Code range where we expect the fault to come from
3147   static void *b_region, *e_region;
3148   #endif
3149  
3150 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3150 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3151   {
3152 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3153 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3154   #if DEBUG
3155          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3156          printf("expected fault at %p\n", page + REF_INDEX);
# Line 1997 | Line 3164 | static sigsegv_return_t sigsegv_test_han
3164   #ifdef __GNUC__
3165          // Make sure reported fault instruction address falls into
3166          // expected code range
3167 <        if (instruction_address != SIGSEGV_INVALID_PC
3167 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3168                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3169                          (instruction_address >= (sigsegv_address_t)e_region)))
3170                  exit(11);
3171   #endif
3172 <        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3172 >        if (vm_protect((char *)((sigsegv_uintptr_t)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3173                  exit(12);
3174          return SIGSEGV_RETURN_SUCCESS;
3175   }
3176  
3177   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3178 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3178 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3179   {
3180 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3181 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3182   #if DEBUG
3183          printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3184   #endif
3185 <        if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3185 >        if (((sigsegv_uintptr_t)fault_address - (sigsegv_uintptr_t)page) < page_size) {
3186   #ifdef __GNUC__
3187                  // Make sure reported fault instruction address falls into
3188                  // expected code range
3189 <                if (instruction_address != SIGSEGV_INVALID_PC
3189 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3190                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3191                                  (instruction_address >= (sigsegv_address_t)e_region)))
3192                          return SIGSEGV_RETURN_FAILURE;
# Line 2031 | Line 3200 | static sigsegv_return_t sigsegv_insn_han
3200   // More sophisticated tests for instruction skipper
3201   static bool arch_insn_skipper_tests()
3202   {
3203 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3203 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
3204          static const unsigned char code[] = {
3205                  0x8a, 0x00,                    // mov    (%eax),%al
3206                  0x8a, 0x2c, 0x18,              // mov    (%eax,%ebx,1),%ch
# Line 2045 | Line 3214 | static bool arch_insn_skipper_tests()
3214                  0x8b, 0x0c, 0x18,              // mov    (%eax,%ebx,1),%ecx
3215                  0x89, 0x00,                    // mov    %eax,(%eax)
3216                  0x89, 0x0c, 0x18,              // mov    %ecx,(%eax,%ebx,1)
3217 < #if defined(__x86_64__)
3217 > #if defined(__x86_64__) || defined(_M_X64)
3218                  0x44, 0x8a, 0x00,              // mov    (%rax),%r8b
3219                  0x44, 0x8a, 0x20,              // mov    (%rax),%r12b
3220                  0x42, 0x8a, 0x3c, 0x10,        // mov    (%rax,%r10,1),%dil
# Line 2068 | Line 3237 | static bool arch_insn_skipper_tests()
3237                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3238                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3239                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3240 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3241 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3242   #endif
3243                  0                              // end
3244          };
3245          const int N_REGS = 20;
3246 <        unsigned long regs[N_REGS];
3246 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3247          for (int i = 0; i < N_REGS; i++)
3248                  regs[i] = i;
3249 <        const unsigned long start_code = (unsigned long)&code;
3249 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3250          regs[X86_REG_EIP] = start_code;
3251          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3252                     && ix86_skip_instruction(regs))
# Line 2091 | Line 3262 | int main(void)
3262          if (vm_init() < 0)
3263                  return 1;
3264  
3265 < #ifdef _WIN32
2095 <        page_size = 4096;
2096 < #else
2097 <        page_size = getpagesize();
2098 < #endif
3265 >        page_size = vm_get_page_size();
3266          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3267                  return 2;
3268          
# Line 2105 | Line 3272 | int main(void)
3272          
3273          if (!sigsegv_install_handler(sigsegv_test_handler))
3274                  return 4;
3275 <        
3275 >
3276   #ifdef __GNUC__
3277          b_region = &&L_b_region1;
3278          e_region = &&L_e_region1;
3279   #endif
3280 < L_b_region1:
3281 <        page[REF_INDEX] = REF_VALUE;
3282 <        if (page[REF_INDEX] != REF_VALUE)
3283 <          exit(20);
3284 <        page[REF_INDEX] = REF_VALUE;
3285 < L_e_region1:
3280 >        /* This is a really awful hack but otherwise gcc is smart enough
3281 >         * (or bug'ous enough?) to optimize the labels and place them
3282 >         * e.g. at the "main" entry point, which is wrong.
3283 >         */
3284 >        volatile int label_hack = 1;
3285 >        switch (label_hack) {
3286 >        case 1:
3287 >        L_b_region1:
3288 >                page[REF_INDEX] = REF_VALUE;
3289 >                if (page[REF_INDEX] != REF_VALUE)
3290 >                        exit(20);
3291 >                page[REF_INDEX] = REF_VALUE;
3292 >                BARRIER();
3293 >                // fall-through
3294 >        case 2:
3295 >        L_e_region1:
3296 >                BARRIER();
3297 >                break;
3298 >        }
3299  
3300          if (handler_called != 1)
3301                  return 5;
# Line 2146 | Line 3326 | int main(void)
3326          b_region = &&L_b_region2;
3327          e_region = &&L_e_region2;
3328   #endif
3329 < L_b_region2:
3330 <        TEST_SKIP_INSTRUCTION(unsigned char);
3331 <        TEST_SKIP_INSTRUCTION(unsigned short);
3332 <        TEST_SKIP_INSTRUCTION(unsigned int);
3333 <        TEST_SKIP_INSTRUCTION(unsigned long);
3334 <        TEST_SKIP_INSTRUCTION(signed char);
3335 <        TEST_SKIP_INSTRUCTION(signed short);
3336 <        TEST_SKIP_INSTRUCTION(signed int);
3337 <        TEST_SKIP_INSTRUCTION(signed long);
3338 < L_e_region2:
3339 <
3329 >        switch (label_hack) {
3330 >        case 1:
3331 >        L_b_region2:
3332 >                TEST_SKIP_INSTRUCTION(unsigned char);
3333 >                TEST_SKIP_INSTRUCTION(unsigned short);
3334 >                TEST_SKIP_INSTRUCTION(unsigned int);
3335 >                TEST_SKIP_INSTRUCTION(unsigned long);
3336 >                TEST_SKIP_INSTRUCTION(signed char);
3337 >                TEST_SKIP_INSTRUCTION(signed short);
3338 >                TEST_SKIP_INSTRUCTION(signed int);
3339 >                TEST_SKIP_INSTRUCTION(signed long);
3340 >                BARRIER();
3341 >                // fall-through
3342 >        case 2:
3343 >        L_e_region2:
3344 >                BARRIER();
3345 >                break;
3346 >        }
3347          if (!arch_insn_skipper_tests())
3348                  return 20;
3349   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines