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.46 by gbeauche, 2004-01-22T00:00:55Z vs.
Revision 1.79 by gbeauche, 2008-01-12T23:01:40Z

# 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 + #ifdef HAVE_WIN32_VM
56 + // Windows is either ILP32 or LLP64
57 + typedef UINT_PTR sigsegv_uintptr_t;
58 + #else
59 + // Other systems are sane enough to follow ILP32 or LP64 models
60 + typedef unsigned long sigsegv_uintptr_t;
61 + #endif
62 +
63   // Type of the system signal handler
64   typedef RETSIGTYPE (*signal_handler)(int);
65  
# Line 66 | Line 77 | static bool sigsegv_do_install_handler(i
77   *  Instruction decoding aids
78   */
79  
80 + // Transfer type
81 + enum transfer_type_t {
82 +        SIGSEGV_TRANSFER_UNKNOWN        = 0,
83 +        SIGSEGV_TRANSFER_LOAD           = 1,
84 +        SIGSEGV_TRANSFER_STORE          = 2
85 + };
86 +
87   // Transfer size
88   enum transfer_size_t {
89          SIZE_UNKNOWN,
90          SIZE_BYTE,
91          SIZE_WORD, // 2 bytes
92          SIZE_LONG, // 4 bytes
93 <        SIZE_QUAD, // 8 bytes
93 >        SIZE_QUAD  // 8 bytes
94   };
95  
96 < // Transfer type
79 < typedef sigsegv_transfer_type_t transfer_type_t;
80 <
81 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
96 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
97   // Addressing mode
98   enum addressing_mode_t {
99          MODE_UNKNOWN,
# Line 97 | Line 112 | struct instruction_t {
112          char                            ra, rd;
113   };
114  
115 < static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned int * gpr)
115 > static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned long * gpr)
116   {
117          // Get opcode and divide into fields
118 <        unsigned int opcode = *((unsigned int *)nip);
118 >        unsigned int opcode = *((unsigned int *)(unsigned long)nip);
119          unsigned int primop = opcode >> 26;
120          unsigned int exop = (opcode >> 1) & 0x3ff;
121          unsigned int ra = (opcode >> 16) & 0x1f;
# Line 174 | Line 189 | static void powerpc_decode_instruction(i
189                  transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
190          case 45:        // sthu
191                  transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
192 +        case 58:        // ld, ldu, lwa
193 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
194 +                transfer_size = SIZE_QUAD;
195 +                addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM;
196 +                imm &= ~3;
197 +                break;
198 +        case 62:        // std, stdu, stq
199 +                transfer_type = SIGSEGV_TRANSFER_STORE;
200 +                transfer_size = SIZE_QUAD;
201 +                addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM;
202 +                imm &= ~3;
203 +                break;
204          }
205          
206          // Calculate effective address
# Line 214 | 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   #else
247   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
# Line 228 | Line 255 | static void powerpc_decode_instruction(i
255   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
256   #define SIGSEGV_FAULT_INSTRUCTION               (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC]
257   #if (defined(mips) || defined(__mips))
258 < #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
258 > #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS[CTX_EPC], &SIGSEGV_CONTEXT_REGS[CTX_R0]
259   #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
260   #endif
261   #endif
# Line 244 | Line 271 | static void powerpc_decode_instruction(i
271   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW
272   #define SIGSEGV_SKIP_INSTRUCTION                sparc_skip_instruction
273   #endif
274 + #if defined(__i386__)
275 + #include <sys/regset.h>
276 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
277 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[EIP]
278 + #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
279 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
280   #endif
281 < #if defined(__FreeBSD__)
281 > #endif
282 > #if defined(__FreeBSD__) || defined(__OpenBSD__)
283   #if (defined(i386) || defined(__i386__))
284   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
285 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
285 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
286 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
287 > #endif
288 > #endif
289 > #if defined(__NetBSD__)
290 > #if (defined(i386) || defined(__i386__))
291 > #include <sys/ucontext.h>
292 > #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
293 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_EIP]
294 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
295   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
296   #endif
297 + #if (defined(powerpc) || defined(__powerpc__))
298 + #include <sys/ucontext.h>
299 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
300 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_PC]
301 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_PC], (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_R0]
302 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
303 + #endif
304   #endif
305   #if defined(__linux__)
306   #if (defined(i386) || defined(__i386__))
307   #include <sys/ucontext.h>
308   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
309   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */
310 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
310 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
311   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
312   #endif
313   #if (defined(x86_64) || defined(__x86_64__))
314   #include <sys/ucontext.h>
315   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
316   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */
317 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
317 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS
318   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
319   #endif
320   #if (defined(ia64) || defined(__ia64__))
321 < #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
321 > #define SIGSEGV_CONTEXT_REGS                    ((struct sigcontext *)scp)
322 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
323 > #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
324 > #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
325   #endif
326   #if (defined(powerpc) || defined(__powerpc__))
327   #include <sys/ucontext.h>
328   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.regs)
329   #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->nip)
330 < #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned int *)(SIGSEGV_CONTEXT_REGS->gpr)
330 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned long *)(SIGSEGV_CONTEXT_REGS->gpr)
331   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
332   #endif
333   #if (defined(hppa) || defined(__hppa__))
# Line 288 | Line 341 | static void powerpc_decode_instruction(i
341   #define SIGSEGV_REGISTER_FILE                   (&SIGSEGV_CONTEXT_REGS.arm_r0)
342   #define SIGSEGV_SKIP_INSTRUCTION                arm_skip_instruction
343   #endif
344 + #if (defined(mips) || defined(__mips__))
345 + #include <sys/ucontext.h>
346 + #define SIGSEGV_CONTEXT_REGS                    (((struct ucontext *)scp)->uc_mcontext)
347 + #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS.pc)
348 + #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS.pc, &SIGSEGV_CONTEXT_REGS.gregs[0]
349 + #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
350 + #endif
351   #endif
352   #endif
353  
# Line 302 | Line 362 | static void powerpc_decode_instruction(i
362   #define SIGSEGV_FAULT_HANDLER_ARGS              &scs
363   #define SIGSEGV_FAULT_ADDRESS                   scp->cr2
364   #define SIGSEGV_FAULT_INSTRUCTION               scp->eip
365 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)scp
365 > #define SIGSEGV_REGISTER_FILE                   (SIGSEGV_REGISTER_TYPE *)scp
366   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
367   #endif
368   #if (defined(sparc) || defined(__sparc__))
# Line 317 | Line 377 | static void powerpc_decode_instruction(i
377   #define SIGSEGV_FAULT_HANDLER_ARGS              sig, scp
378   #define SIGSEGV_FAULT_ADDRESS                   scp->regs->dar
379   #define SIGSEGV_FAULT_INSTRUCTION               scp->regs->nip
380 < #define SIGSEGV_REGISTER_FILE                   (unsigned int *)&scp->regs->nip, (unsigned int *)(scp->regs->gpr)
380 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&scp->regs->nip, (unsigned long *)(scp->regs->gpr)
381   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
382   #endif
383   #if (defined(alpha) || defined(__alpha__))
# Line 423 | Line 483 | static sigsegv_address_t get_fault_addre
483   #define SIGSEGV_FAULT_HANDLER_ARGS              sig, code, scp, addr
484   #define SIGSEGV_FAULT_ADDRESS                   addr
485   #define SIGSEGV_FAULT_INSTRUCTION               scp->sc_eip
486 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&scp->sc_edi)
486 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&scp->sc_edi)
487   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
488   #endif
489   #if (defined(alpha) || defined(__alpha__))
# Line 481 | Line 541 | static sigsegv_address_t get_fault_addre
541   #endif
542   #endif
543  
544 + #if HAVE_WIN32_EXCEPTIONS
545 + #define WIN32_LEAN_AND_MEAN /* avoid including junk */
546 + #include <windows.h>
547 + #include <winerror.h>
548 +
549 + #if defined(_M_IX86)
550 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
551 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
552 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
553 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
554 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Eip
555 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Edi)
556 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
557 + #endif
558 + #if defined(_M_X64)
559 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   EXCEPTION_POINTERS *ExceptionInfo
560 + #define SIGSEGV_FAULT_HANDLER_ARGS              ExceptionInfo
561 + #define SIGSEGV_FAULT_ADDRESS                   ExceptionInfo->ExceptionRecord->ExceptionInformation[1]
562 + #define SIGSEGV_CONTEXT_REGS                    ExceptionInfo->ContextRecord
563 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS->Rip
564 + #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax)
565 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
566 + #endif
567 + #endif
568 +
569   #if HAVE_MACH_EXCEPTIONS
570  
571   // This can easily be extended to other Mach systems, but really who
# Line 541 | Line 626 | if (ret != KERN_SUCCESS) { \
626          exit (1); \
627   }
628  
629 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
630 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
631 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
632 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
633 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
629 > #ifdef __ppc__
630 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
631 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
632 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
633 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.dar
634 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
635 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
636 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
637 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.srr0
638   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
639 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
640 <
641 < // Given a suspended thread, stuff the current instruction and
642 < // registers into state.
643 < //
644 < // It would have been nice to have this be ppc/x86 independant which
645 < // could have been done easily with a thread_state_t instead of
646 < // ppc_thread_state_t, but because of the way this is called it is
647 < // easier to do it this way.
648 < #if (defined(ppc) || defined(__ppc__))
649 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
650 < {
651 <        kern_return_t krc;
652 <        mach_msg_type_number_t count;
653 <
654 <        count = MACHINE_THREAD_STATE_COUNT;
655 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
656 <        MACH_CHECK_ERROR (thread_get_state, krc);
657 <
658 <        return (sigsegv_address_t)state->srr0;
659 < }
639 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
640 > #endif
641 > #ifdef __ppc64__
642 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
643 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
644 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
645 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.dar
646 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
647 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
648 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
649 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.srr0
650 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
651 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
652 > #endif
653 > #ifdef __i386__
654 > #define SIGSEGV_EXCEPTION_STATE_TYPE    struct i386_exception_state
655 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
656 > #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
657 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.faultvaddr
658 > #define SIGSEGV_THREAD_STATE_TYPE               struct i386_thread_state
659 > #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
660 > #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
661 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.eip
662 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
663 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.eax) /* EAX is the first GPR we consider */
664 > #endif
665 > #ifdef __x86_64__
666 > #define SIGSEGV_EXCEPTION_STATE_TYPE    struct x86_exception_state64
667 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
668 > #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
669 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.faultvaddr
670 > #define SIGSEGV_THREAD_STATE_TYPE               struct x86_thread_state64
671 > #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
672 > #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
673 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.rip
674 > #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
675 > #define SIGSEGV_REGISTER_FILE                   ((SIGSEGV_REGISTER_TYPE *)&SIP->thr_state.rax) /* RAX is the first GPR we consider */
676   #endif
677 + #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
678 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
679 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
680 + #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
681  
682   // Since there can only be one exception thread running at any time
683   // this is not a problem.
# Line 621 | Line 730 | handleExceptions(void *priv)
730   *  Instruction skipping
731   */
732  
733 + #ifndef SIGSEGV_REGISTER_TYPE
734 + #define SIGSEGV_REGISTER_TYPE sigsegv_uintptr_t
735 + #endif
736 +
737   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
738   // Decode and skip X86 instruction
739 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
739 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
740   #if defined(__linux__)
741   enum {
742   #if (defined(i386) || defined(__i386__))
# Line 658 | Line 771 | enum {
771   #endif
772   };
773   #endif
774 < #if defined(__NetBSD__) || defined(__FreeBSD__)
774 > #if defined(__NetBSD__)
775   enum {
776   #if (defined(i386) || defined(__i386__))
777 +        X86_REG_EIP = _REG_EIP,
778 +        X86_REG_EAX = _REG_EAX,
779 +        X86_REG_ECX = _REG_ECX,
780 +        X86_REG_EDX = _REG_EDX,
781 +        X86_REG_EBX = _REG_EBX,
782 +        X86_REG_ESP = _REG_ESP,
783 +        X86_REG_EBP = _REG_EBP,
784 +        X86_REG_ESI = _REG_ESI,
785 +        X86_REG_EDI = _REG_EDI
786 + #endif
787 + };
788 + #endif
789 + #if defined(__FreeBSD__)
790 + enum {
791 + #if (defined(i386) || defined(__i386__))
792 +        X86_REG_EIP = 10,
793 +        X86_REG_EAX = 7,
794 +        X86_REG_ECX = 6,
795 +        X86_REG_EDX = 5,
796 +        X86_REG_EBX = 4,
797 +        X86_REG_ESP = 13,
798 +        X86_REG_EBP = 2,
799 +        X86_REG_ESI = 1,
800 +        X86_REG_EDI = 0
801 + #endif
802 + };
803 + #endif
804 + #if defined(__OpenBSD__)
805 + enum {
806 + #if defined(__i386__)
807 +        // EDI is the first register we consider
808 + #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
809 + #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
810 +        X86_REG_EIP = DREG(eip), // 7
811 +        X86_REG_EAX = DREG(eax), // 6
812 +        X86_REG_ECX = DREG(ecx), // 5
813 +        X86_REG_EDX = DREG(edx), // 4
814 +        X86_REG_EBX = DREG(ebx), // 3
815 +        X86_REG_ESP = DREG(esp), // 10
816 +        X86_REG_EBP = DREG(ebp), // 2
817 +        X86_REG_ESI = DREG(esi), // 1
818 +        X86_REG_EDI = DREG(edi)  // 0
819 + #undef DREG
820 + #undef OREG
821 + #endif
822 + };
823 + #endif
824 + #if defined(__sun__)
825 + // Same as for Linux, need to check for x86-64
826 + enum {
827 + #if defined(__i386__)
828 +        X86_REG_EIP = EIP,
829 +        X86_REG_EAX = EAX,
830 +        X86_REG_ECX = ECX,
831 +        X86_REG_EDX = EDX,
832 +        X86_REG_EBX = EBX,
833 +        X86_REG_ESP = ESP,
834 +        X86_REG_EBP = EBP,
835 +        X86_REG_ESI = ESI,
836 +        X86_REG_EDI = EDI
837 + #endif
838 + };
839 + #endif
840 + #if defined(__APPLE__) && defined(__MACH__)
841 + enum {
842 + #if (defined(i386) || defined(__i386__))
843 + #ifdef i386_SAVED_STATE
844 +        // same as FreeBSD (in Open Darwin 8.0.1)
845          X86_REG_EIP = 10,
846          X86_REG_EAX = 7,
847          X86_REG_ECX = 6,
# Line 670 | Line 851 | enum {
851          X86_REG_EBP = 2,
852          X86_REG_ESI = 1,
853          X86_REG_EDI = 0
854 + #else
855 +        // new layout (MacOS X 10.4.4 for x86)
856 +        X86_REG_EIP = 10,
857 +        X86_REG_EAX = 0,
858 +        X86_REG_ECX = 2,
859 +        X86_REG_EDX = 3,
860 +        X86_REG_EBX = 1,
861 +        X86_REG_ESP = 7,
862 +        X86_REG_EBP = 6,
863 +        X86_REG_ESI = 5,
864 +        X86_REG_EDI = 4
865 + #endif
866 + #endif
867 + #if defined(__x86_64__)
868 +        X86_REG_R8  = 8,
869 +        X86_REG_R9  = 9,
870 +        X86_REG_R10 = 10,
871 +        X86_REG_R11 = 11,
872 +        X86_REG_R12 = 12,
873 +        X86_REG_R13 = 13,
874 +        X86_REG_R14 = 14,
875 +        X86_REG_R15 = 15,
876 +        X86_REG_EDI = 4,
877 +        X86_REG_ESI = 5,
878 +        X86_REG_EBP = 6,
879 +        X86_REG_EBX = 1,
880 +        X86_REG_EDX = 3,
881 +        X86_REG_EAX = 0,
882 +        X86_REG_ECX = 2,
883 +        X86_REG_ESP = 7,
884 +        X86_REG_EIP = 16
885 + #endif
886 + };
887 + #endif
888 + #if defined(_WIN32)
889 + enum {
890 + #if defined(_M_IX86)
891 +        X86_REG_EIP = 7,
892 +        X86_REG_EAX = 5,
893 +        X86_REG_ECX = 4,
894 +        X86_REG_EDX = 3,
895 +        X86_REG_EBX = 2,
896 +        X86_REG_ESP = 10,
897 +        X86_REG_EBP = 6,
898 +        X86_REG_ESI = 1,
899 +        X86_REG_EDI = 0
900 + #endif
901 + #if defined(_M_X64)
902 +        X86_REG_EAX = 0,
903 +        X86_REG_ECX = 1,
904 +        X86_REG_EDX = 2,
905 +        X86_REG_EBX = 3,
906 +        X86_REG_ESP = 4,
907 +        X86_REG_EBP = 5,
908 +        X86_REG_ESI = 6,
909 +        X86_REG_EDI = 7,
910 +        X86_REG_R8  = 8,
911 +        X86_REG_R9  = 9,
912 +        X86_REG_R10 = 10,
913 +        X86_REG_R11 = 11,
914 +        X86_REG_R12 = 12,
915 +        X86_REG_R13 = 13,
916 +        X86_REG_R14 = 14,
917 +        X86_REG_R15 = 15,
918 +        X86_REG_EIP = 16
919   #endif
920   };
921   #endif
# Line 707 | Line 953 | static inline int ix86_step_over_modrm(u
953          return offset;
954   }
955  
956 < static bool ix86_skip_instruction(unsigned long * regs)
956 > static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs)
957   {
958          unsigned char * eip = (unsigned char *)regs[X86_REG_EIP];
959  
960          if (eip == 0)
961                  return false;
962 + #ifdef _WIN32
963 +        if (IsBadCodePtr((FARPROC)eip))
964 +                return false;
965 + #endif
966          
967 +        enum instruction_type_t {
968 +                i_MOV,
969 +                i_ADD
970 +        };
971 +
972          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
973          transfer_size_t transfer_size = SIZE_LONG;
974 +        instruction_type_t instruction_type = i_MOV;
975          
976          int reg = -1;
977          int len = 0;
# Line 733 | Line 989 | static bool ix86_skip_instruction(unsign
989          }
990  
991          // REX prefix
992 < #if defined(__x86_64__)
992 > #if defined(__x86_64__) || defined(_M_X64)
993          struct rex_t {
994                  unsigned char W;
995                  unsigned char R;
# Line 766 | Line 1022 | static bool ix86_skip_instruction(unsign
1022   #endif
1023  
1024          // Decode instruction
1025 +        int op_len = 1;
1026          int target_size = SIZE_UNKNOWN;
1027          switch (eip[0]) {
1028          case 0x0f:
# Line 775 | Line 1032 | static bool ix86_skip_instruction(unsign
1032              case 0xb6: // MOVZX r32, r/m8
1033                          transfer_size = SIZE_BYTE;
1034                          goto do_mov_extend;
1035 +                case 0xbf: // MOVSX r32, r/m16
1036              case 0xb7: // MOVZX r32, r/m16
1037                          transfer_size = SIZE_WORD;
1038                          goto do_mov_extend;
1039                    do_mov_extend:
1040 <                        switch (eip[2] & 0xc0) {
1041 <                        case 0x80:
1042 <                                reg = (eip[2] >> 3) & 7;
1043 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1044 <                                break;
1045 <                        case 0x40:
1046 <                                reg = (eip[2] >> 3) & 7;
1047 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1048 <                                break;
1049 <                        case 0x00:
1050 <                                reg = (eip[2] >> 3) & 7;
1051 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1052 <                                break;
1053 <                        }
1054 <                        len += 3 + ix86_step_over_modrm(eip + 2);
1055 <                        break;
1056 <            }
1057 <          break;
1040 >                        op_len = 2;
1041 >                        goto do_transfer_load;
1042 >                }
1043 >                break;
1044 > #if defined(__x86_64__) || defined(_M_X64)
1045 >        case 0x63: // MOVSXD r64, r/m32
1046 >                if (has_rex && rex.W) {
1047 >                        transfer_size = SIZE_LONG;
1048 >                        target_size = SIZE_QUAD;
1049 >                }
1050 >                else if (transfer_size != SIZE_WORD) {
1051 >                        transfer_size = SIZE_LONG;
1052 >                        target_size = SIZE_QUAD;
1053 >                }
1054 >                goto do_transfer_load;
1055 > #endif
1056 >        case 0x02: // ADD r8, r/m8
1057 >                transfer_size = SIZE_BYTE;
1058 >        case 0x03: // ADD r32, r/m32
1059 >                instruction_type = i_ADD;
1060 >                goto do_transfer_load;
1061          case 0x8a: // MOV r8, r/m8
1062                  transfer_size = SIZE_BYTE;
1063          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1064 <                switch (eip[1] & 0xc0) {
1064 >          do_transfer_load:
1065 >                switch (eip[op_len] & 0xc0) {
1066                  case 0x80:
1067 <                        reg = (eip[1] >> 3) & 7;
1067 >                        reg = (eip[op_len] >> 3) & 7;
1068                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1069                          break;
1070                  case 0x40:
1071 <                        reg = (eip[1] >> 3) & 7;
1071 >                        reg = (eip[op_len] >> 3) & 7;
1072                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1073                          break;
1074                  case 0x00:
1075 <                        reg = (eip[1] >> 3) & 7;
1075 >                        reg = (eip[op_len] >> 3) & 7;
1076                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1077                          break;
1078                  }
1079 <                len += 2 + ix86_step_over_modrm(eip + 1);
1079 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1080                  break;
1081 +        case 0x00: // ADD r/m8, r8
1082 +                transfer_size = SIZE_BYTE;
1083 +        case 0x01: // ADD r/m32, r32
1084 +                instruction_type = i_ADD;
1085 +                goto do_transfer_store;
1086          case 0x88: // MOV r/m8, r8
1087                  transfer_size = SIZE_BYTE;
1088          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1089 <                switch (eip[1] & 0xc0) {
1089 >          do_transfer_store:
1090 >                switch (eip[op_len] & 0xc0) {
1091                  case 0x80:
1092 <                        reg = (eip[1] >> 3) & 7;
1092 >                        reg = (eip[op_len] >> 3) & 7;
1093                          transfer_type = SIGSEGV_TRANSFER_STORE;
1094                          break;
1095                  case 0x40:
1096 <                        reg = (eip[1] >> 3) & 7;
1096 >                        reg = (eip[op_len] >> 3) & 7;
1097                          transfer_type = SIGSEGV_TRANSFER_STORE;
1098                          break;
1099                  case 0x00:
1100 <                        reg = (eip[1] >> 3) & 7;
1100 >                        reg = (eip[op_len] >> 3) & 7;
1101                          transfer_type = SIGSEGV_TRANSFER_STORE;
1102                          break;
1103                  }
1104 <                len += 2 + ix86_step_over_modrm(eip + 1);
1104 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1105                  break;
1106          }
1107          if (target_size == SIZE_UNKNOWN)
# Line 844 | Line 1112 | static bool ix86_skip_instruction(unsign
1112                  return false;
1113          }
1114  
1115 < #if defined(__x86_64__)
1115 > #if defined(__x86_64__) || defined(_M_X64)
1116          if (rex.R)
1117                  reg += 8;
1118   #endif
1119  
1120 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1120 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1121                  static const int x86_reg_map[] = {
1122                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1123                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
1124 < #if defined(__x86_64__)
1124 > #if defined(__x86_64__) || defined(_M_X64)
1125                          X86_REG_R8,  X86_REG_R9,  X86_REG_R10, X86_REG_R11,
1126                          X86_REG_R12, X86_REG_R13, X86_REG_R14, X86_REG_R15,
1127   #endif
# Line 885 | Line 1153 | static bool ix86_skip_instruction(unsign
1153          }
1154  
1155   #if DEBUG
1156 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1156 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1157                     transfer_size == SIZE_BYTE ? "byte" :
1158                     transfer_size == SIZE_WORD ? "word" :
1159                     transfer_size == SIZE_LONG ? "long" :
# Line 940 | Line 1208 | static bool ix86_skip_instruction(unsign
1208   }
1209   #endif
1210  
1211 + // Decode and skip IA-64 instruction
1212 + #if defined(__ia64__)
1213 + #if defined(__linux__)
1214 + // We can directly patch the slot number
1215 + #define IA64_CAN_PATCH_IP_SLOT 1
1216 + // Helper macros to access the machine context
1217 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1218 + #define IA64_CONTEXT                    scp
1219 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1220 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1221 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1222 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1223 + #define IA64_SET_NAT(I,V)               (IA64_CONTEXT->sc_nat= (IA64_CONTEXT->sc_nat & ~(1ul << (I))) | (((unsigned long)!!(V)) << (I)))
1224 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1225 + #define IA64_SET_GR(R,V)                (IA64_CONTEXT->sc_gr[(R)] = (V))
1226 + #endif
1227 +
1228 + // Instruction operations
1229 + enum {
1230 +        IA64_INST_UNKNOWN = 0,
1231 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1232 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1233 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1234 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1235 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1236 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1237 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1238 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1239 +        IA64_INST_ST1,                          // st1 [op0]=op1
1240 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1241 +        IA64_INST_ST2,                          // st2 [op0]=op1
1242 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1243 +        IA64_INST_ST4,                          // st4 [op0]=op1
1244 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1245 +        IA64_INST_ST8,                          // st8 [op0]=op1
1246 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1247 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1248 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1249 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1250 +        IA64_INST_AND,                          // and op0=op1,op2
1251 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1252 +        IA64_INST_OR,                           // or op0=op1,op2
1253 +        IA64_INST_XOR,                          // xor op0=op1,op2
1254 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1255 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1256 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1257 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1258 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1259 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1260 +        IA64_INST_NOP                           // nop op0
1261 + };
1262 +
1263 + const int IA64_N_OPERANDS = 4;
1264 +
1265 + // Decoded operand type
1266 + struct ia64_operand_t {
1267 +        unsigned char commit;           // commit result of operation to register file?
1268 +        unsigned char valid;            // XXX: not really used, can be removed (debug)
1269 +        signed char index;                      // index of GPR, or -1 if immediate value
1270 +        unsigned char nat;                      // NaT state before operation
1271 +        unsigned long value;            // register contents or immediate value
1272 + };
1273 +
1274 + // Decoded instruction type
1275 + struct ia64_instruction_t {
1276 +        unsigned char mnemo;            // operation to perform
1277 +        unsigned char pred;                     // predicate register to check
1278 +        unsigned char no_memory;        // used to emulated main fault instruction
1279 +        unsigned long inst;                     // the raw instruction bits (41-bit wide)
1280 +        ia64_operand_t operands[IA64_N_OPERANDS];
1281 + };
1282 +
1283 + // Get immediate sign-bit
1284 + static inline int ia64_inst_get_sbit(unsigned long inst)
1285 + {
1286 +        return (inst >> 36) & 1;
1287 + }
1288 +
1289 + // Get 8-bit immediate value (A3, A8, I27, M30)
1290 + static inline unsigned long ia64_inst_get_imm8(unsigned long inst)
1291 + {
1292 +        unsigned long value = (inst >> 13) & 0x7ful;
1293 +        if (ia64_inst_get_sbit(inst))
1294 +                value |= ~0x7ful;
1295 +        return value;
1296 + }
1297 +
1298 + // Get 9-bit immediate value (M3)
1299 + static inline unsigned long ia64_inst_get_imm9b(unsigned long inst)
1300 + {
1301 +        unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1302 +        if (ia64_inst_get_sbit(inst))
1303 +                value |= ~0xfful;
1304 +        return value;
1305 + }
1306 +
1307 + // Get 9-bit immediate value (M5)
1308 + static inline unsigned long ia64_inst_get_imm9a(unsigned long inst)
1309 + {
1310 +        unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1311 +        if (ia64_inst_get_sbit(inst))
1312 +                value |= ~0xfful;
1313 +        return value;
1314 + }
1315 +
1316 + // Get 14-bit immediate value (A4)
1317 + static inline unsigned long ia64_inst_get_imm14(unsigned long inst)
1318 + {
1319 +        unsigned long value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1320 +        if (ia64_inst_get_sbit(inst))
1321 +                value |= ~0x1fful;
1322 +        return value;
1323 + }
1324 +
1325 + // Get 22-bit immediate value (A5)
1326 + static inline unsigned long ia64_inst_get_imm22(unsigned long inst)
1327 + {
1328 +        unsigned long value = ((((inst >> 22) & 0x1f) << 16) |
1329 +                                                   (((inst >> 27) & 0x1ff) << 7) |
1330 +                                                   (inst & 0x7f));
1331 +        if (ia64_inst_get_sbit(inst))
1332 +                value |= ~0x1ffffful;
1333 +        return value;
1334 + }
1335 +
1336 + // Get 21-bit immediate value (I19)
1337 + static inline unsigned long ia64_inst_get_imm21(unsigned long inst)
1338 + {
1339 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1340 + }
1341 +
1342 + // Get 2-bit count value (A2)
1343 + static inline int ia64_inst_get_count2(unsigned long inst)
1344 + {
1345 +        return (inst >> 27) & 0x3;
1346 + }
1347 +
1348 + // Get bundle template
1349 + static inline unsigned int ia64_get_template(unsigned long raw_ip)
1350 + {
1351 +        unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1352 +        return ip[0] & 0x1f;
1353 + }
1354 +
1355 + // Get specified instruction in bundle
1356 + static unsigned long ia64_get_instruction(unsigned long raw_ip, int slot)
1357 + {
1358 +        unsigned long inst;
1359 +        unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1360 + #if DEBUG
1361 +        printf("Bundle: %016lx%016lx\n", ip[1], ip[0]);
1362 + #endif
1363 +
1364 +        switch (slot) {
1365 +        case 0:
1366 +                inst = (ip[0] >> 5) & 0x1fffffffffful;
1367 +                break;
1368 +        case 1:
1369 +                inst = ((ip[1] & 0x7ffffful) << 18) | ((ip[0] >> 46) & 0x3fffful);
1370 +                break;
1371 +        case 2:
1372 +                inst = (ip[1] >> 23) & 0x1fffffffffful;
1373 +                break;
1374 +        case 3:
1375 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1376 +                abort();
1377 +                break;
1378 +        }
1379 +
1380 + #if DEBUG
1381 +        printf(" Instruction %d: 0x%016lx\n", slot, inst);
1382 + #endif
1383 +        return inst;
1384 + }
1385 +
1386 + // Decode group 0 instructions
1387 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1388 + {
1389 +        const int r1 = (inst->inst >>  6) & 0x7f;
1390 +        const int r3 = (inst->inst >> 20) & 0x7f;
1391 +
1392 +        const int x3 = (inst->inst >> 33) & 0x07;
1393 +        const int x6 = (inst->inst >> 27) & 0x3f;
1394 +        const int x2 = (inst->inst >> 31) & 0x03;
1395 +        const int x4 = (inst->inst >> 27) & 0x0f;
1396 +
1397 +        if (x3 == 0) {
1398 +                switch (x6) {
1399 +                case 0x01:                                              // nop.i (I19)
1400 +                        inst->mnemo = IA64_INST_NOP;
1401 +                        inst->operands[0].valid = true;
1402 +                        inst->operands[0].index = -1;
1403 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1404 +                        return true;
1405 +                case 0x14:                                              // sxt1 (I29)
1406 +                case 0x15:                                              // sxt2 (I29)
1407 +                case 0x16:                                              // sxt4 (I29)
1408 +                case 0x10:                                              // zxt1 (I29)
1409 +                case 0x11:                                              // zxt2 (I29)
1410 +                case 0x12:                                              // zxt4 (I29)
1411 +                        switch (x6) {
1412 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1413 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1414 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1415 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1416 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1417 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1418 +                        default: abort();
1419 +                        }
1420 +                        inst->operands[0].valid = true;
1421 +                        inst->operands[0].index = r1;
1422 +                        inst->operands[1].valid = true;
1423 +                        inst->operands[1].index = r3;
1424 +                        inst->operands[1].value = IA64_GET_GR(r3);
1425 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1426 +                        return true;
1427 +                }
1428 +        }
1429 +        return false;
1430 + }
1431 +
1432 + // Decode group 4 instructions (load/store instructions)
1433 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1434 + {
1435 +        const int r1 = (inst->inst >> 6) & 0x7f;
1436 +        const int r2 = (inst->inst >> 13) & 0x7f;
1437 +        const int r3 = (inst->inst >> 20) & 0x7f;
1438 +
1439 +        const int m  = (inst->inst >> 36) & 1;
1440 +        const int x  = (inst->inst >> 27) & 1;
1441 +        const int x6 = (inst->inst >> 30) & 0x3f;
1442 +
1443 +        switch (x6) {
1444 +        case 0x00:
1445 +        case 0x01:
1446 +        case 0x02:
1447 +        case 0x03:
1448 +                if (x == 0) {
1449 +                        inst->operands[0].valid = true;
1450 +                        inst->operands[0].index = r1;
1451 +                        inst->operands[1].valid = true;
1452 +                        inst->operands[1].index = r3;
1453 +                        inst->operands[1].value = IA64_GET_GR(r3);
1454 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1455 +                        if (m == 0) {
1456 +                                switch (x6) {
1457 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1458 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1459 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1460 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1461 +                                }
1462 +                        }
1463 +                        else {
1464 +                                inst->operands[2].valid = true;
1465 +                                inst->operands[2].index = r2;
1466 +                                inst->operands[2].value = IA64_GET_GR(r2);
1467 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1468 +                                switch (x6) {
1469 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1470 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1471 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1472 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1473 +                                }
1474 +                        }
1475 +                        return true;
1476 +                }
1477 +                break;
1478 +        case 0x30:
1479 +        case 0x31:
1480 +        case 0x32:
1481 +        case 0x33:
1482 +                if (m == 0 && x == 0) {
1483 +                        inst->operands[0].valid = true;
1484 +                        inst->operands[0].index = r3;
1485 +                        inst->operands[0].value = IA64_GET_GR(r3);
1486 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1487 +                        inst->operands[1].valid = true;
1488 +                        inst->operands[1].index = r2;
1489 +                        inst->operands[1].value = IA64_GET_GR(r2);
1490 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1491 +                        switch (x6) {
1492 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1493 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1494 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1495 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1496 +                        }
1497 +                        return true;
1498 +                }
1499 +                break;
1500 +        }
1501 +        return false;
1502 + }
1503 +
1504 + // Decode group 5 instructions (load/store instructions)
1505 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1506 + {
1507 +        const int r1 = (inst->inst >> 6) & 0x7f;
1508 +        const int r2 = (inst->inst >> 13) & 0x7f;
1509 +        const int r3 = (inst->inst >> 20) & 0x7f;
1510 +
1511 +        const int x6 = (inst->inst >> 30) & 0x3f;
1512 +
1513 +        switch (x6) {
1514 +        case 0x00:
1515 +        case 0x01:
1516 +        case 0x02:
1517 +        case 0x03:
1518 +                inst->operands[0].valid = true;
1519 +                inst->operands[0].index = r1;
1520 +                inst->operands[1].valid = true;
1521 +                inst->operands[1].index = r3;
1522 +                inst->operands[1].value = IA64_GET_GR(r3);
1523 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1524 +                inst->operands[2].valid = true;
1525 +                inst->operands[2].index = -1;
1526 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1527 +                inst->operands[2].nat   = 0;
1528 +                switch (x6) {
1529 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1530 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1531 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1532 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1533 +                }
1534 +                return true;
1535 +        case 0x30:
1536 +        case 0x31:
1537 +        case 0x32:
1538 +        case 0x33:
1539 +                inst->operands[0].valid = true;
1540 +                inst->operands[0].index = r3;
1541 +                inst->operands[0].value = IA64_GET_GR(r3);
1542 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1543 +                inst->operands[1].valid = true;
1544 +                inst->operands[1].index = r2;
1545 +                inst->operands[1].value = IA64_GET_GR(r2);
1546 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1547 +                inst->operands[2].valid = true;
1548 +                inst->operands[2].index = -1;
1549 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1550 +                inst->operands[2].nat   = 0;
1551 +                switch (x6) {
1552 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1553 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1554 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1555 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1556 +                }
1557 +                return true;
1558 +        }
1559 +        return false;
1560 + }
1561 +
1562 + // Decode group 8 instructions (ALU integer)
1563 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1564 + {
1565 +        const int r1  = (inst->inst >> 6) & 0x7f;
1566 +        const int r2  = (inst->inst >> 13) & 0x7f;
1567 +        const int r3  = (inst->inst >> 20) & 0x7f;
1568 +
1569 +        const int x2a = (inst->inst >> 34) & 0x3;
1570 +        const int x2b = (inst->inst >> 27) & 0x3;
1571 +        const int x4  = (inst->inst >> 29) & 0xf;
1572 +        const int ve  = (inst->inst >> 33) & 0x1;
1573 +
1574 +        // destination register (r1) is always valid in this group
1575 +        inst->operands[0].valid = true;
1576 +        inst->operands[0].index = r1;
1577 +
1578 +        // source register (r3) is always valid in this group
1579 +        inst->operands[2].valid = true;
1580 +        inst->operands[2].index = r3;
1581 +        inst->operands[2].value = IA64_GET_GR(r3);
1582 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1583 +
1584 +        if (x2a == 0 && ve == 0) {
1585 +                inst->operands[1].valid = true;
1586 +                inst->operands[1].index = r2;
1587 +                inst->operands[1].value = IA64_GET_GR(r2);
1588 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1589 +                switch (x4) {
1590 +                case 0x0:                               // add (A1)
1591 +                        inst->mnemo = IA64_INST_ADD;
1592 +                        inst->operands[3].valid = true;
1593 +                        inst->operands[3].index = -1;
1594 +                        inst->operands[3].value = x2b == 1;
1595 +                        return true;
1596 +                case 0x1:                               // add (A1)
1597 +                        inst->mnemo = IA64_INST_SUB;
1598 +                        inst->operands[3].valid = true;
1599 +                        inst->operands[3].index = -1;
1600 +                        inst->operands[3].value = x2b == 0;
1601 +                        return true;
1602 +                case 0x4:                               // shladd (A2)
1603 +                        inst->mnemo = IA64_INST_SHLADD;
1604 +                        inst->operands[3].valid = true;
1605 +                        inst->operands[3].index = -1;
1606 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1607 +                        return true;
1608 +                case 0x9:
1609 +                        if (x2b == 1) {
1610 +                                inst->mnemo = IA64_INST_SUB;
1611 +                                inst->operands[1].index = -1;
1612 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1613 +                                inst->operands[1].nat   = 0;
1614 +                                return true;
1615 +                        }
1616 +                        break;
1617 +                case 0xb:
1618 +                        inst->operands[1].index = -1;
1619 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1620 +                        inst->operands[1].nat   = 0;
1621 +                        // fall-through
1622 +                case 0x3:
1623 +                        switch (x2b) {
1624 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1625 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1626 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1627 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1628 +                        }
1629 +                        return true;
1630 +                }
1631 +        }
1632 +        return false;
1633 + }
1634 +
1635 + // Decode instruction
1636 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1637 + {
1638 +        const int major = (inst->inst >> 37) & 0xf;
1639 +
1640 +        inst->mnemo = IA64_INST_UNKNOWN;
1641 +        inst->pred  = inst->inst & 0x3f;
1642 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1643 +
1644 +        switch (major) {
1645 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1646 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1647 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1648 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1649 +        }
1650 +        return false;
1651 + }
1652 +
1653 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1654 + {
1655 +        // XXX: handle Register NaT Consumption fault?
1656 +        // XXX: this simple emulator assumes instructions in a bundle
1657 +        // don't depend on effects of other instructions in the same
1658 +        // bundle. It probably would be simpler to JIT-generate code to be
1659 +        // executed natively but probably more costly (inject/extract CPU state)
1660 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1661 +                return false;
1662 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1663 +                return true;
1664 +
1665 +        unsigned char nat, nat2;
1666 +        unsigned long dst, dst2, src1, src2, src3;
1667 +
1668 +        switch (inst->mnemo) {
1669 +        case IA64_INST_NOP:
1670 +                break;
1671 +        case IA64_INST_ADD:
1672 +        case IA64_INST_SUB:
1673 +        case IA64_INST_SHLADD:
1674 +                src3 = inst->operands[3].value;
1675 +                // fall-through
1676 +        case IA64_INST_AND:
1677 +        case IA64_INST_ANDCM:
1678 +        case IA64_INST_OR:
1679 +        case IA64_INST_XOR:
1680 +                src1 = inst->operands[1].value;
1681 +                src2 = inst->operands[2].value;
1682 +                switch (inst->mnemo) {
1683 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1684 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1685 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1686 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1687 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1688 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1689 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1690 +                }
1691 +                inst->operands[0].commit = true;
1692 +                inst->operands[0].value  = dst;
1693 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1694 +                break;
1695 +        case IA64_INST_SXT1:
1696 +        case IA64_INST_SXT2:
1697 +        case IA64_INST_SXT4:
1698 +        case IA64_INST_ZXT1:
1699 +        case IA64_INST_ZXT2:
1700 +        case IA64_INST_ZXT4:
1701 +                src1 = inst->operands[1].value;
1702 +                switch (inst->mnemo) {
1703 +                case IA64_INST_SXT1: dst = (signed long)(signed char)src1;              break;
1704 +                case IA64_INST_SXT2: dst = (signed long)(signed short)src1;             break;
1705 +                case IA64_INST_SXT4: dst = (signed long)(signed int)src1;               break;
1706 +                case IA64_INST_ZXT1: dst = (unsigned char)src1;                                 break;
1707 +                case IA64_INST_ZXT2: dst = (unsigned short)src1;                                break;
1708 +                case IA64_INST_ZXT4: dst = (unsigned int)src1;                                  break;
1709 +                }
1710 +                inst->operands[0].commit = true;
1711 +                inst->operands[0].value  = dst;
1712 +                inst->operands[0].nat    = inst->operands[1].nat;
1713 +                break;
1714 +        case IA64_INST_LD1_UPDATE:
1715 +        case IA64_INST_LD2_UPDATE:
1716 +        case IA64_INST_LD4_UPDATE:
1717 +        case IA64_INST_LD8_UPDATE:
1718 +                inst->operands[1].commit = true;
1719 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1720 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1721 +                // fall-through
1722 +        case IA64_INST_LD1:
1723 +        case IA64_INST_LD2:
1724 +        case IA64_INST_LD4:
1725 +        case IA64_INST_LD8:
1726 +                src1 = inst->operands[1].value;
1727 +                if (inst->no_memory)
1728 +                        dst = 0;
1729 +                else {
1730 +                        switch (inst->mnemo) {
1731 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((unsigned char *)src1);  break;
1732 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((unsigned short *)src1); break;
1733 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((unsigned int *)src1);   break;
1734 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((unsigned long *)src1);  break;
1735 +                        }
1736 +                }
1737 +                inst->operands[0].commit = true;
1738 +                inst->operands[0].value  = dst;
1739 +                inst->operands[0].nat    = 0;
1740 +                inst->operands[1].value  = dst2;
1741 +                inst->operands[1].nat    = nat2;
1742 +                break;
1743 +        case IA64_INST_ST1_UPDATE:
1744 +        case IA64_INST_ST2_UPDATE:
1745 +        case IA64_INST_ST4_UPDATE:
1746 +        case IA64_INST_ST8_UPDATE:
1747 +                inst->operands[0].commit = 0;
1748 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1749 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1750 +                // fall-through
1751 +        case IA64_INST_ST1:
1752 +        case IA64_INST_ST2:
1753 +        case IA64_INST_ST4:
1754 +        case IA64_INST_ST8:
1755 +                dst  = inst->operands[0].value;
1756 +                src1 = inst->operands[1].value;
1757 +                if (!inst->no_memory) {
1758 +                        switch (inst->mnemo) {
1759 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((unsigned char *)dst) = src1;  break;
1760 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((unsigned short *)dst) = src1; break;
1761 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((unsigned int *)dst) = src1;   break;
1762 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((unsigned long *)dst) = src1;  break;
1763 +                        }
1764 +                }
1765 +                inst->operands[0].value  = dst2;
1766 +                inst->operands[0].nat    = nat2;
1767 +                break;
1768 +        default:
1769 +                return false;
1770 +        }
1771 +
1772 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1773 +                ia64_operand_t const & op = inst->operands[i];
1774 +                if (!op.commit)
1775 +                        continue;
1776 +                if (op.index == -1)
1777 +                        return false; // XXX: internal error
1778 +                IA64_SET_GR(op.index, op.value);
1779 +                IA64_SET_NAT(op.index, op.nat);
1780 +        }
1781 +        return true;
1782 + }
1783 +
1784 + static bool ia64_emulate_instruction(unsigned long raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1785 + {
1786 +        ia64_instruction_t inst;
1787 +        memset(&inst, 0, sizeof(inst));
1788 +        inst.inst = raw_inst;
1789 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1790 +                return false;
1791 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1792 + }
1793 +
1794 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1795 + {
1796 +        unsigned long ip = IA64_GET_IP();
1797 + #if DEBUG
1798 +        printf("IP: 0x%016lx\n", ip);
1799 + #if 0
1800 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1801 +        ia64_get_instruction(ip, 0);
1802 +        ia64_get_instruction(ip, 1);
1803 +        ia64_get_instruction(ip, 2);
1804 + #endif
1805 + #endif
1806 +
1807 +        // Select which decode switch to use
1808 +        ia64_instruction_t inst;
1809 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1810 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1811 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1812 +                return false;
1813 +        }
1814 +
1815 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1816 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1817 +
1818 +        switch (inst.mnemo) {
1819 +        case IA64_INST_LD1:
1820 +        case IA64_INST_LD2:
1821 +        case IA64_INST_LD4:
1822 +        case IA64_INST_LD8:
1823 +        case IA64_INST_LD1_UPDATE:
1824 +        case IA64_INST_LD2_UPDATE:
1825 +        case IA64_INST_LD4_UPDATE:
1826 +        case IA64_INST_LD8_UPDATE:
1827 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1828 +                break;
1829 +        case IA64_INST_ST1:
1830 +        case IA64_INST_ST2:
1831 +        case IA64_INST_ST4:
1832 +        case IA64_INST_ST8:
1833 +        case IA64_INST_ST1_UPDATE:
1834 +        case IA64_INST_ST2_UPDATE:
1835 +        case IA64_INST_ST4_UPDATE:
1836 +        case IA64_INST_ST8_UPDATE:
1837 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1838 +                break;
1839 +        }
1840 +
1841 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1842 +                // Unknown machine code, let it crash. Then patch the decoder
1843 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1844 +                return false;
1845 +        }
1846 +
1847 +        switch (inst.mnemo) {
1848 +        case IA64_INST_LD1:
1849 +        case IA64_INST_LD1_UPDATE:
1850 +        case IA64_INST_ST1:
1851 +        case IA64_INST_ST1_UPDATE:
1852 +                transfer_size = SIZE_BYTE;
1853 +                break;
1854 +        case IA64_INST_LD2:
1855 +        case IA64_INST_LD2_UPDATE:
1856 +        case IA64_INST_ST2:
1857 +        case IA64_INST_ST2_UPDATE:
1858 +                transfer_size = SIZE_WORD;
1859 +                break;
1860 +        case IA64_INST_LD4:
1861 +        case IA64_INST_LD4_UPDATE:
1862 +        case IA64_INST_ST4:
1863 +        case IA64_INST_ST4_UPDATE:
1864 +                transfer_size = SIZE_LONG;
1865 +                break;
1866 +        case IA64_INST_LD8:
1867 +        case IA64_INST_LD8_UPDATE:
1868 +        case IA64_INST_ST8:
1869 +        case IA64_INST_ST8_UPDATE:
1870 +                transfer_size = SIZE_QUAD;
1871 +                break;
1872 +        }
1873 +
1874 +        if (transfer_size == SIZE_UNKNOWN) {
1875 +                // Unknown machine code, let it crash. Then patch the decoder
1876 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1877 +                return false;
1878 +        }
1879 +
1880 +        inst.no_memory = true;
1881 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1882 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1883 +                return false;
1884 +        }
1885 +
1886 +        int slot = ip & 3;
1887 +        bool emulate_next = false;
1888 +        switch (slot) {
1889 +        case 0:
1890 +                switch (ia64_get_template(ip)) {
1891 +                case 0x2: // MI;I
1892 +                case 0x3: // MI;I;
1893 +                        emulate_next = true;
1894 +                        slot = 2;
1895 +                        break;
1896 +                case 0xa: // M;MI
1897 +                case 0xb: // M;MI;
1898 +                        emulate_next = true;
1899 +                        slot = 1;
1900 +                        break;
1901 +                }
1902 +                break;
1903 +        }
1904 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
1905 +                while (slot < 3) {
1906 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
1907 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
1908 +                                return false;
1909 +                        }
1910 +                        ++slot;
1911 +                }
1912 +        }
1913 +
1914 + #if IA64_CAN_PATCH_IP_SLOT
1915 +        if ((slot = ip & 3) < 2)
1916 +                IA64_SET_IP((ip & ~3ul) + (slot + 1));
1917 +        else
1918 + #endif
1919 +                IA64_SET_IP((ip & ~3ul) + 16);
1920 + #if DEBUG
1921 +        printf("IP: 0x%016lx\n", IA64_GET_IP());
1922 + #endif
1923 +        return true;
1924 + }
1925 + #endif
1926 +
1927   // Decode and skip PPC instruction
1928 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
1929 < static bool powerpc_skip_instruction(unsigned int * nip_p, unsigned int * regs)
1928 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
1929 > static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
1930   {
1931          instruction_t instr;
1932          powerpc_decode_instruction(&instr, *nip_p, regs);
# Line 954 | Line 1938 | static bool powerpc_skip_instruction(uns
1938  
1939   #if DEBUG
1940          printf("%08x: %s %s access", *nip_p,
1941 <                   instr.transfer_size == SIZE_BYTE ? "byte" : instr.transfer_size == SIZE_WORD ? "word" : "long",
1941 >                   instr.transfer_size == SIZE_BYTE ? "byte" :
1942 >                   instr.transfer_size == SIZE_WORD ? "word" :
1943 >                   instr.transfer_size == SIZE_LONG ? "long" : "quad",
1944                     instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write");
1945          
1946          if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX)
# Line 975 | Line 1961 | static bool powerpc_skip_instruction(uns
1961  
1962   // Decode and skip MIPS instruction
1963   #if (defined(mips) || defined(__mips))
1964 < enum {
979 < #if (defined(sgi) || defined(__sgi))
980 <  MIPS_REG_EPC = 35,
981 < #endif
982 < };
983 < static bool mips_skip_instruction(greg_t * regs)
1964 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
1965   {
1966 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
1966 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
1967  
1968    if (epc == 0)
1969          return false;
# Line 1131 | Line 2112 | static bool mips_skip_instruction(greg_t
2112                   mips_gpr_names[reg]);
2113   #endif
2114  
2115 <  regs[MIPS_REG_EPC] += 4;
2115 >  *pc_p += 4;
2116    return true;
2117   }
2118   #endif
# Line 1143 | Line 2124 | enum {
2124    SPARC_REG_G1 = REG_G1,
2125    SPARC_REG_O0 = REG_O0,
2126    SPARC_REG_PC = REG_PC,
2127 +  SPARC_REG_nPC = REG_nPC
2128   #endif
2129   };
2130   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1206 | Line 2188 | static bool sparc_skip_instruction(unsig
2188          break;
2189    case 7: // Store Doubleword
2190          transfer_type = SIGSEGV_TRANSFER_STORE;
2191 <        transfer_size = SIZE_WORD;
2191 >        transfer_size = SIZE_LONG;
2192          register_pair = true;
2193          break;
2194    }
# Line 1216 | Line 2198 | static bool sparc_skip_instruction(unsig
2198          return false;
2199    }
2200  
1219  // Zero target register in case of a load operation
2201    const int reg = (opcode >> 25) & 0x1f;
2202 +
2203 + #if DEBUG
2204 +  static const char * reg_names[] = {
2205 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2206 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2207 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2208 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2209 +  };
2210 +  printf("%s %s register %s\n",
2211 +                 transfer_size == SIZE_BYTE ? "byte" :
2212 +                 transfer_size == SIZE_WORD ? "word" :
2213 +                 transfer_size == SIZE_LONG ? "long" :
2214 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2215 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2216 +                 reg_names[reg]);
2217 + #endif
2218 +
2219 +  // Zero target register in case of a load operation
2220    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2221          // FIXME: code to handle local & input registers is not tested
2222 <        if (reg >= 1 && reg <= 7) {
2222 >        if (reg >= 1 && reg < 8) {
2223            // global registers
2224            regs[reg - 1 + SPARC_REG_G1] = 0;
2225          }
2226 <        else if (reg >= 8 && reg <= 15) {
2226 >        else if (reg >= 8 && reg < 16) {
2227            // output registers
2228            regs[reg - 8 + SPARC_REG_O0] = 0;
2229          }
2230 <        else if (reg >= 16 && reg <= 23) {
2230 >        else if (reg >= 16 && reg < 24) {
2231            // local registers (in register windows)
2232            if (gwins)
2233                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1244 | Line 2243 | static bool sparc_skip_instruction(unsig
2243          }
2244    }
2245  
1247 #if DEBUG
1248  static const char * reg_names[] = {
1249        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1250        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1251        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1252        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1253  };
1254  printf("%s %s register %s\n",
1255                 transfer_size == SIZE_BYTE ? "byte" :
1256                 transfer_size == SIZE_WORD ? "word" :
1257                 transfer_size == SIZE_LONG ? "long" :
1258                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1259                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1260                 reg_names[reg]);
1261 #endif
1262
2246    regs[SPARC_REG_PC] += 4;
2247 +  regs[SPARC_REG_nPC] += 4;
2248    return true;
2249   }
2250   #endif
# Line 1416 | Line 2400 | static bool arm_skip_instruction(unsigne
2400  
2401  
2402   // Fallbacks
2403 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2404 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2405 + #endif
2406 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2407 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2408 + #endif
2409   #ifndef SIGSEGV_FAULT_INSTRUCTION
2410 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2410 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2411   #endif
2412   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2413   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2414   #endif
2415   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2416 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2416 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2417   #endif
2418  
2419   // SIGSEGV recovery supported ?
# Line 1436 | Line 2426 | static bool arm_skip_instruction(unsigne
2426   *  SIGSEGV global handler
2427   */
2428  
2429 < #if defined(HAVE_SIGSEGV_RECOVERY) || defined(HAVE_MACH_EXCEPTIONS)
2429 > struct sigsegv_info_t {
2430 >        sigsegv_address_t addr;
2431 >        sigsegv_address_t pc;
2432 > #ifdef HAVE_MACH_EXCEPTIONS
2433 >        mach_port_t thread;
2434 >        bool has_exc_state;
2435 >        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2436 >        mach_msg_type_number_t exc_state_count;
2437 >        bool has_thr_state;
2438 >        SIGSEGV_THREAD_STATE_TYPE thr_state;
2439 >        mach_msg_type_number_t thr_state_count;
2440 > #endif
2441 > };
2442 >
2443 > #ifdef HAVE_MACH_EXCEPTIONS
2444 > static void mach_get_exception_state(sigsegv_info_t *SIP)
2445 > {
2446 >        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2447 >        kern_return_t krc = thread_get_state(SIP->thread,
2448 >                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2449 >                                                                                 (natural_t *)&SIP->exc_state,
2450 >                                                                                 &SIP->exc_state_count);
2451 >        MACH_CHECK_ERROR(thread_get_state, krc);
2452 >        SIP->has_exc_state = true;
2453 > }
2454 >
2455 > static void mach_get_thread_state(sigsegv_info_t *SIP)
2456 > {
2457 >        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2458 >        kern_return_t krc = thread_get_state(SIP->thread,
2459 >                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2460 >                                                                                 (natural_t *)&SIP->thr_state,
2461 >                                                                                 &SIP->thr_state_count);
2462 >        MACH_CHECK_ERROR(thread_get_state, krc);
2463 >        SIP->has_thr_state = true;
2464 > }
2465 >
2466 > static void mach_set_thread_state(sigsegv_info_t *SIP)
2467 > {
2468 >        kern_return_t krc = thread_set_state(SIP->thread,
2469 >                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2470 >                                                                                 (natural_t *)&SIP->thr_state,
2471 >                                                                                 SIP->thr_state_count);
2472 >        MACH_CHECK_ERROR(thread_set_state, krc);
2473 > }
2474 > #endif
2475 >
2476 > // Return the address of the invalid memory reference
2477 > sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2478 > {
2479 > #ifdef HAVE_MACH_EXCEPTIONS
2480 >        static int use_fast_path = -1;
2481 >        if (use_fast_path != 1 && !SIP->has_exc_state) {
2482 >                mach_get_exception_state(SIP);
2483 >
2484 >                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2485 >                if (use_fast_path < 0) {
2486 >                        const char *machfault = getenv("SIGSEGV_MACH_FAULT");
2487 >                        if (machfault) {
2488 >                                if (strcmp(machfault, "fast") == 0)
2489 >                                        use_fast_path = 1;
2490 >                                else if (strcmp(machfault, "slow") == 0)
2491 >                                        use_fast_path = 0;
2492 >                        }
2493 >                        if (use_fast_path < 0)
2494 >                                use_fast_path = addr == SIP->addr;
2495 >                }
2496 >                SIP->addr = addr;
2497 >        }
2498 > #endif
2499 >        return SIP->addr;
2500 > }
2501 >
2502 > // Return the address of the instruction that caused the fault, or
2503 > // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2504 > sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2505 > {
2506 > #ifdef HAVE_MACH_EXCEPTIONS
2507 >        if (!SIP->has_thr_state) {
2508 >                mach_get_thread_state(SIP);
2509 >
2510 >                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2511 >        }
2512 > #endif
2513 >        return SIP->pc;
2514 > }
2515 >
2516   // This function handles the badaccess to memory.
2517   // It is called from the signal handler or the exception handler.
2518   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2519   {
2520 <        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2521 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2522 <        
2520 >        sigsegv_info_t SI;
2521 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2522 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2523 > #ifdef HAVE_MACH_EXCEPTIONS
2524 >        SI.thread = thread;
2525 >        SI.has_exc_state = false;
2526 >        SI.has_thr_state = false;
2527 > #endif
2528 >        sigsegv_info_t * const SIP = &SI;
2529 >
2530          // Call user's handler and reinstall the global handler, if required
2531 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2531 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2532          case SIGSEGV_RETURN_SUCCESS:
2533                  return true;
2534  
# Line 1453 | Line 2536 | static bool handle_badaccess(SIGSEGV_FAU
2536          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2537                  // Call the instruction skipper with the register file
2538                  // available
2539 + #ifdef HAVE_MACH_EXCEPTIONS
2540 +                if (!SIP->has_thr_state)
2541 +                        mach_get_thread_state(SIP);
2542 + #endif
2543                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2544   #ifdef HAVE_MACH_EXCEPTIONS
2545                          // Unlike UNIX signals where the thread state
2546                          // is modified off of the stack, in Mach we
2547                          // need to actually call thread_set_state to
2548                          // have the register values updated.
2549 <                        kern_return_t krc;
1463 <
1464 <                        krc = thread_set_state(thread,
1465 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1466 <                                                                   MACHINE_THREAD_STATE_COUNT);
1467 <                        MACH_CHECK_ERROR (thread_get_state, krc);
2549 >                        mach_set_thread_state(SIP);
2550   #endif
2551                          return true;
2552                  }
2553                  break;
2554   #endif
2555          case SIGSEGV_RETURN_FAILURE:
2556 <                return false;
2556 >                // We can't do anything with the fault_address, dump state?
2557 >                if (sigsegv_state_dumper != 0)
2558 >                        sigsegv_state_dumper(SIP);
2559 >                break;
2560          }
1476        
1477        // We can't do anything with the fault_address, dump state?
1478        if (sigsegv_state_dumper != 0)
1479                sigsegv_state_dumper(fault_address, fault_instruction);
2561  
2562          return false;
2563   }
1483 #endif
2564  
2565  
2566   /*
# Line 1517 | Line 2597 | forward_exception(mach_port_t thread_por
2597          mach_port_t port;
2598          exception_behavior_t behavior;
2599          thread_state_flavor_t flavor;
2600 <        thread_state_t thread_state;
2600 >        thread_state_data_t thread_state;
2601          mach_msg_type_number_t thread_state_count;
2602  
2603          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1536 | Line 2616 | forward_exception(mach_port_t thread_por
2616          behavior = oldExceptionPorts->behaviors[portIndex];
2617          flavor = oldExceptionPorts->flavors[portIndex];
2618  
2619 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2620 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2621 +                return KERN_FAILURE;
2622 +        }
2623 +
2624          /*
2625           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2626           */
2627  
2628          if (behavior != EXCEPTION_DEFAULT) {
2629                  thread_state_count = THREAD_STATE_MAX;
2630 <                kret = thread_get_state (thread_port, flavor, thread_state,
2630 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2631                                                                   &thread_state_count);
2632                  MACH_CHECK_ERROR (thread_get_state, kret);
2633          }
# Line 1558 | Line 2643 | forward_exception(mach_port_t thread_por
2643            // fprintf(stderr, "forwarding to exception_raise_state\n");
2644            kret = exception_raise_state(port, exception_type, exception_data,
2645                                                                     data_count, &flavor,
2646 <                                                                   thread_state, thread_state_count,
2647 <                                                                   thread_state, &thread_state_count);
2646 >                                                                   (natural_t *)&thread_state, thread_state_count,
2647 >                                                                   (natural_t *)&thread_state, &thread_state_count);
2648            MACH_CHECK_ERROR (exception_raise_state, kret);
2649            break;
2650          case EXCEPTION_STATE_IDENTITY:
# Line 1567 | Line 2652 | forward_exception(mach_port_t thread_por
2652            kret = exception_raise_state_identity(port, thread_port, task_port,
2653                                                                                          exception_type, exception_data,
2654                                                                                          data_count, &flavor,
2655 <                                                                                        thread_state, thread_state_count,
2656 <                                                                                        thread_state, &thread_state_count);
2655 >                                                                                        (natural_t *)&thread_state, thread_state_count,
2656 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
2657            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2658            break;
2659          default:
2660            fprintf(stderr, "forward_exception got unknown behavior\n");
2661 +          kret = KERN_FAILURE;
2662            break;
2663          }
2664  
2665          if (behavior != EXCEPTION_DEFAULT) {
2666 <                kret = thread_set_state (thread_port, flavor, thread_state,
2666 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2667                                                                   thread_state_count);
2668                  MACH_CHECK_ERROR (thread_set_state, kret);
2669          }
2670  
2671 <        return KERN_SUCCESS;
2671 >        return kret;
2672   }
2673  
2674   /*
# Line 1610 | Line 2696 | catch_exception_raise(mach_port_t except
2696                                            mach_port_t task,
2697                                            exception_type_t exception,
2698                                            exception_data_t code,
2699 <                                          mach_msg_type_number_t codeCount)
2699 >                                          mach_msg_type_number_t code_count)
2700   {
1615        ppc_thread_state_t state;
2701          kern_return_t krc;
2702  
2703 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2704 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2705 <                        return KERN_SUCCESS;
2703 >        if (exception == EXC_BAD_ACCESS) {
2704 >                switch (code[0]) {
2705 >                case KERN_PROTECTION_FAILURE:
2706 >                case KERN_INVALID_ADDRESS:
2707 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2708 >                                return KERN_SUCCESS;
2709 >                        break;
2710 >                }
2711          }
2712  
2713          // In Mach we do not need to remove the exception handler.
2714          // If we forward the exception, eventually some exception handler
2715          // will take care of this exception.
2716 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2716 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2717  
2718          return krc;
2719   }
# Line 1751 | Line 2841 | static bool sigsegv_do_install_handler(s
2841          // addressing modes) used in PPC instructions, you will need the
2842          // GPR state anyway.
2843          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2844 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2844 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2845          if (krc != KERN_SUCCESS) {
2846                  mach_error("thread_set_exception_ports", krc);
2847                  return false;
# Line 1774 | Line 2864 | static bool sigsegv_do_install_handler(s
2864   }
2865   #endif
2866  
2867 + #ifdef HAVE_WIN32_EXCEPTIONS
2868 + static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo)
2869 + {
2870 +        if (sigsegv_fault_handler != NULL
2871 +                && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
2872 +                && ExceptionInfo->ExceptionRecord->NumberParameters == 2
2873 +                && handle_badaccess(ExceptionInfo))
2874 +                return EXCEPTION_CONTINUE_EXECUTION;
2875 +
2876 +        return EXCEPTION_CONTINUE_SEARCH;
2877 + }
2878 +
2879 + #if defined __CYGWIN__ && defined __i386__
2880 + /* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin
2881 +   installs a global exception handler.  We have to dig deep in order to install
2882 +   our main_exception_filter.  */
2883 +
2884 + /* Data structures for the current thread's exception handler chain.
2885 +   On the x86 Windows uses register fs, offset 0 to point to the current
2886 +   exception handler; Cygwin mucks with it, so we must do the same... :-/ */
2887 +
2888 + /* Magic taken from winsup/cygwin/include/exceptions.h.  */
2889 +
2890 + struct exception_list {
2891 +    struct exception_list *prev;
2892 +    int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
2893 + };
2894 + typedef struct exception_list exception_list;
2895 +
2896 + /* Magic taken from winsup/cygwin/exceptions.cc.  */
2897 +
2898 + __asm__ (".equ __except_list,0");
2899 +
2900 + extern exception_list *_except_list __asm__ ("%fs:__except_list");
2901 +
2902 + /* For debugging.  _except_list is not otherwise accessible from gdb.  */
2903 + static exception_list *
2904 + debug_get_except_list ()
2905 + {
2906 +  return _except_list;
2907 + }
2908 +
2909 + /* Cygwin's original exception handler.  */
2910 + static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
2911 +
2912 + /* Our exception handler.  */
2913 + static int
2914 + libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch)
2915 + {
2916 +  EXCEPTION_POINTERS ExceptionInfo;
2917 +  ExceptionInfo.ExceptionRecord = exception;
2918 +  ExceptionInfo.ContextRecord = context;
2919 +  if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH)
2920 +    return cygwin_exception_handler (exception, frame, context, dispatch);
2921 +  else
2922 +    return 0;
2923 + }
2924 +
2925 + static void
2926 + do_install_main_exception_filter ()
2927 + {
2928 +  /* We cannot insert any handler into the chain, because such handlers
2929 +     must lie on the stack (?).  Instead, we have to replace(!) Cygwin's
2930 +     global exception handler.  */
2931 +  cygwin_exception_handler = _except_list->handler;
2932 +  _except_list->handler = libsigsegv_exception_handler;
2933 + }
2934 +
2935 + #else
2936 +
2937 + static void
2938 + do_install_main_exception_filter ()
2939 + {
2940 +  SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter);
2941 + }
2942 + #endif
2943 +
2944 + static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler)
2945 + {
2946 +        static bool main_exception_filter_installed = false;
2947 +        if (!main_exception_filter_installed) {
2948 +                do_install_main_exception_filter();
2949 +                main_exception_filter_installed = true;
2950 +        }
2951 +        sigsegv_fault_handler = handler;
2952 +        return true;
2953 + }
2954 + #endif
2955 +
2956   bool sigsegv_install_handler(sigsegv_fault_handler_t handler)
2957   {
2958   #if defined(HAVE_SIGSEGV_RECOVERY)
# Line 1784 | Line 2963 | bool sigsegv_install_handler(sigsegv_fau
2963          if (success)
2964              sigsegv_fault_handler = handler;
2965          return success;
2966 < #elif defined(HAVE_MACH_EXCEPTIONS)
2966 > #elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS)
2967          return sigsegv_do_install_handler(handler);
2968   #else
2969          // FAIL: no siginfo_t nor sigcontext subterfuge is available
# Line 1810 | Line 2989 | void sigsegv_deinstall_handler(void)
2989          SIGSEGV_ALL_SIGNALS
2990   #undef FAULT_HANDLER
2991   #endif
2992 + #ifdef HAVE_WIN32_EXCEPTIONS
2993 +        sigsegv_fault_handler = NULL;
2994 + #endif
2995   }
2996  
2997  
# Line 1831 | Line 3013 | void sigsegv_set_dump_state(sigsegv_stat
3013   #include <stdio.h>
3014   #include <stdlib.h>
3015   #include <fcntl.h>
3016 + #ifdef HAVE_SYS_MMAN_H
3017   #include <sys/mman.h>
3018 + #endif
3019   #include "vm_alloc.h"
3020  
3021   const int REF_INDEX = 123;
3022   const int REF_VALUE = 45;
3023  
3024 < static int page_size;
3024 > static sigsegv_uintptr_t page_size;
3025   static volatile char * page = 0;
3026   static volatile int handler_called = 0;
3027  
3028 + /* Barriers */
3029 + #ifdef __GNUC__
3030 + #define BARRIER() asm volatile ("" : : : "memory")
3031 + #else
3032 + #define BARRIER() /* nothing */
3033 + #endif
3034 +
3035   #ifdef __GNUC__
3036   // Code range where we expect the fault to come from
3037   static void *b_region, *e_region;
3038   #endif
3039  
3040 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3040 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
3041   {
3042 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3043 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3044   #if DEBUG
3045          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
3046          printf("expected fault at %p\n", page + REF_INDEX);
# Line 1861 | Line 3054 | static sigsegv_return_t sigsegv_test_han
3054   #ifdef __GNUC__
3055          // Make sure reported fault instruction address falls into
3056          // expected code range
3057 <        if (instruction_address != SIGSEGV_INVALID_PC
3057 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3058                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3059                          (instruction_address >= (sigsegv_address_t)e_region)))
3060                  exit(11);
3061   #endif
3062 <        if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3062 >        if (vm_protect((char *)((sigsegv_uintptr_t)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
3063                  exit(12);
3064          return SIGSEGV_RETURN_SUCCESS;
3065   }
3066  
3067   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3068 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3068 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3069   {
3070 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3071 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3072   #if DEBUG
3073          printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3074   #endif
3075 <        if (((unsigned long)fault_address - (unsigned long)page) < page_size) {
3075 >        if (((sigsegv_uintptr_t)fault_address - (sigsegv_uintptr_t)page) < page_size) {
3076   #ifdef __GNUC__
3077                  // Make sure reported fault instruction address falls into
3078                  // expected code range
3079 <                if (instruction_address != SIGSEGV_INVALID_PC
3079 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3080                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3081                                  (instruction_address >= (sigsegv_address_t)e_region)))
3082                          return SIGSEGV_RETURN_FAILURE;
# Line 1895 | Line 3090 | static sigsegv_return_t sigsegv_insn_han
3090   // More sophisticated tests for instruction skipper
3091   static bool arch_insn_skipper_tests()
3092   {
3093 < #if (defined(i386) || defined(__i386__)) || defined(__x86_64__)
3093 > #if (defined(i386) || defined(__i386__)) || (defined(__x86_64__) || defined(_M_X64))
3094          static const unsigned char code[] = {
3095                  0x8a, 0x00,                    // mov    (%eax),%al
3096                  0x8a, 0x2c, 0x18,              // mov    (%eax,%ebx,1),%ch
# Line 1909 | Line 3104 | static bool arch_insn_skipper_tests()
3104                  0x8b, 0x0c, 0x18,              // mov    (%eax,%ebx,1),%ecx
3105                  0x89, 0x00,                    // mov    %eax,(%eax)
3106                  0x89, 0x0c, 0x18,              // mov    %ecx,(%eax,%ebx,1)
3107 < #if defined(__x86_64__)
3107 > #if defined(__x86_64__) || defined(_M_X64)
3108                  0x44, 0x8a, 0x00,              // mov    (%rax),%r8b
3109                  0x44, 0x8a, 0x20,              // mov    (%rax),%r12b
3110                  0x42, 0x8a, 0x3c, 0x10,        // mov    (%rax,%r10,1),%dil
# Line 1932 | Line 3127 | static bool arch_insn_skipper_tests()
3127                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3128                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3129                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3130 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3131 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3132   #endif
3133                  0                              // end
3134          };
3135          const int N_REGS = 20;
3136 <        unsigned long regs[N_REGS];
3136 >        SIGSEGV_REGISTER_TYPE regs[N_REGS];
3137          for (int i = 0; i < N_REGS; i++)
3138                  regs[i] = i;
3139 <        const unsigned long start_code = (unsigned long)&code;
3139 >        const sigsegv_uintptr_t start_code = (sigsegv_uintptr_t)&code;
3140          regs[X86_REG_EIP] = start_code;
3141          while ((regs[X86_REG_EIP] - start_code) < (sizeof(code) - 1)
3142                     && ix86_skip_instruction(regs))
# Line 1955 | Line 3152 | int main(void)
3152          if (vm_init() < 0)
3153                  return 1;
3154  
3155 <        page_size = getpagesize();
3155 >        page_size = vm_get_page_size();
3156          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3157                  return 2;
3158          
# Line 1965 | Line 3162 | int main(void)
3162          
3163          if (!sigsegv_install_handler(sigsegv_test_handler))
3164                  return 4;
3165 <        
3165 >
3166   #ifdef __GNUC__
3167          b_region = &&L_b_region1;
3168          e_region = &&L_e_region1;
3169   #endif
3170 < L_b_region1:
3171 <        page[REF_INDEX] = REF_VALUE;
3172 <        if (page[REF_INDEX] != REF_VALUE)
3173 <          exit(20);
3174 <        page[REF_INDEX] = REF_VALUE;
3175 < L_e_region1:
3170 >        /* This is a really awful hack but otherwise gcc is smart enough
3171 >         * (or bug'ous enough?) to optimize the labels and place them
3172 >         * e.g. at the "main" entry point, which is wrong.
3173 >         */
3174 >        volatile int label_hack = 1;
3175 >        switch (label_hack) {
3176 >        case 1:
3177 >        L_b_region1:
3178 >                page[REF_INDEX] = REF_VALUE;
3179 >                if (page[REF_INDEX] != REF_VALUE)
3180 >                        exit(20);
3181 >                page[REF_INDEX] = REF_VALUE;
3182 >                BARRIER();
3183 >                // fall-through
3184 >        case 2:
3185 >        L_e_region1:
3186 >                BARRIER();
3187 >                break;
3188 >        }
3189  
3190          if (handler_called != 1)
3191                  return 5;
# Line 2006 | Line 3216 | int main(void)
3216          b_region = &&L_b_region2;
3217          e_region = &&L_e_region2;
3218   #endif
3219 < L_b_region2:
3220 <        TEST_SKIP_INSTRUCTION(unsigned char);
3221 <        TEST_SKIP_INSTRUCTION(unsigned short);
3222 <        TEST_SKIP_INSTRUCTION(unsigned int);
3223 <        TEST_SKIP_INSTRUCTION(unsigned long);
3224 <        TEST_SKIP_INSTRUCTION(signed char);
3225 <        TEST_SKIP_INSTRUCTION(signed short);
3226 <        TEST_SKIP_INSTRUCTION(signed int);
3227 <        TEST_SKIP_INSTRUCTION(signed long);
3228 < L_e_region2:
3229 <
3219 >        switch (label_hack) {
3220 >        case 1:
3221 >        L_b_region2:
3222 >                TEST_SKIP_INSTRUCTION(unsigned char);
3223 >                TEST_SKIP_INSTRUCTION(unsigned short);
3224 >                TEST_SKIP_INSTRUCTION(unsigned int);
3225 >                TEST_SKIP_INSTRUCTION(unsigned long);
3226 >                TEST_SKIP_INSTRUCTION(signed char);
3227 >                TEST_SKIP_INSTRUCTION(signed short);
3228 >                TEST_SKIP_INSTRUCTION(signed int);
3229 >                TEST_SKIP_INSTRUCTION(signed long);
3230 >                BARRIER();
3231 >                // fall-through
3232 >        case 2:
3233 >        L_e_region2:
3234 >                BARRIER();
3235 >                break;
3236 >        }
3237          if (!arch_insn_skipper_tests())
3238                  return 20;
3239   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines