ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.49 by gbeauche, 2004-12-02T23:29:52Z vs.
Revision 1.77 by gbeauche, 2008-01-06T17:22:19Z

# 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 66 | Line 66 | static bool sigsegv_do_install_handler(i
66   *  Instruction decoding aids
67   */
68  
69 + // Transfer type
70 + enum transfer_type_t {
71 +        SIGSEGV_TRANSFER_UNKNOWN        = 0,
72 +        SIGSEGV_TRANSFER_LOAD           = 1,
73 +        SIGSEGV_TRANSFER_STORE          = 2
74 + };
75 +
76   // Transfer size
77   enum transfer_size_t {
78          SIZE_UNKNOWN,
79          SIZE_BYTE,
80          SIZE_WORD, // 2 bytes
81          SIZE_LONG, // 4 bytes
82 <        SIZE_QUAD, // 8 bytes
82 >        SIZE_QUAD  // 8 bytes
83   };
84  
85 < // Transfer type
79 < typedef sigsegv_transfer_type_t transfer_type_t;
80 <
81 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
85 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
86   // Addressing mode
87   enum addressing_mode_t {
88          MODE_UNKNOWN,
# Line 226 | Line 230 | static void powerpc_decode_instruction(i
230  
231   #if HAVE_SIGINFO_T
232   // Generic extended signal handler
233 < #if defined(__NetBSD__) || defined(__FreeBSD__)
233 > #if defined(__FreeBSD__)
234   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGBUS)
235   #else
236   #define SIGSEGV_ALL_SIGNALS                             FAULT_HANDLER(SIGSEGV)
# Line 240 | Line 244 | static void powerpc_decode_instruction(i
244   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
245   #define SIGSEGV_FAULT_INSTRUCTION               (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC]
246   #if (defined(mips) || defined(__mips))
247 < #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
247 > #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS[CTX_EPC], &SIGSEGV_CONTEXT_REGS[CTX_R0]
248   #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
249   #endif
250   #endif
# Line 256 | Line 260 | static void powerpc_decode_instruction(i
260   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW
261   #define SIGSEGV_SKIP_INSTRUCTION                sparc_skip_instruction
262   #endif
263 + #if defined(__i386__)
264 + #include <sys/regset.h>
265 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
266 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[EIP]
267 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
268 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
269   #endif
270 < #if defined(__FreeBSD__)
270 > #endif
271 > #if defined(__FreeBSD__) || defined(__OpenBSD__)
272   #if (defined(i386) || defined(__i386__))
273   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
274   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
275   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
276   #endif
277   #endif
278 + #if defined(__NetBSD__)
279 + #if (defined(i386) || defined(__i386__))
280 + #include <sys/ucontext.h>
281 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
282 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_EIP]
283 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
284 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
285 + #endif
286 + #if (defined(powerpc) || defined(__powerpc__))
287 + #include <sys/ucontext.h>
288 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.__gregs)
289 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[_REG_PC]
290 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_PC], (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_R0]
291 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
292 + #endif
293 + #endif
294   #if defined(__linux__)
295   #if (defined(i386) || defined(__i386__))
296   #include <sys/ucontext.h>
# Line 280 | Line 307 | static void powerpc_decode_instruction(i
307   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
308   #endif
309   #if (defined(ia64) || defined(__ia64__))
310 < #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
310 > #define SIGSEGV_CONTEXT_REGS                    ((struct sigcontext *)scp)
311 > #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
312 > #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
313 > #define SIGSEGV_SKIP_INSTRUCTION                ia64_skip_instruction
314   #endif
315   #if (defined(powerpc) || defined(__powerpc__))
316   #include <sys/ucontext.h>
# Line 300 | Line 330 | static void powerpc_decode_instruction(i
330   #define SIGSEGV_REGISTER_FILE                   (&SIGSEGV_CONTEXT_REGS.arm_r0)
331   #define SIGSEGV_SKIP_INSTRUCTION                arm_skip_instruction
332   #endif
333 + #if (defined(mips) || defined(__mips__))
334 + #include <sys/ucontext.h>
335 + #define SIGSEGV_CONTEXT_REGS                    (((struct ucontext *)scp)->uc_mcontext)
336 + #define SIGSEGV_FAULT_INSTRUCTION               (SIGSEGV_CONTEXT_REGS.pc)
337 + #define SIGSEGV_REGISTER_FILE                   &SIGSEGV_CONTEXT_REGS.pc, &SIGSEGV_CONTEXT_REGS.gregs[0]
338 + #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
339 + #endif
340   #endif
341   #endif
342  
# Line 567 | Line 604 | if (ret != KERN_SUCCESS) { \
604          exit (1); \
605   }
606  
607 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
608 < #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
609 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
610 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
611 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
607 > #ifdef __ppc__
608 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
609 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
610 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
611 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.dar
612 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
613 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
614 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
615 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.srr0
616   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
617 < #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
618 <
619 < // Given a suspended thread, stuff the current instruction and
620 < // registers into state.
621 < //
622 < // It would have been nice to have this be ppc/x86 independant which
623 < // could have been done easily with a thread_state_t instead of
624 < // ppc_thread_state_t, but because of the way this is called it is
625 < // easier to do it this way.
626 < #if (defined(ppc) || defined(__ppc__))
627 < static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
628 < {
629 <        kern_return_t krc;
589 <        mach_msg_type_number_t count;
590 <
591 <        count = MACHINE_THREAD_STATE_COUNT;
592 <        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
593 <        MACH_CHECK_ERROR (thread_get_state, krc);
594 <
595 <        return (sigsegv_address_t)state->srr0;
596 < }
617 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
618 > #endif
619 > #ifdef __ppc64__
620 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
621 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
622 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
623 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.dar
624 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
625 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
626 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
627 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.srr0
628 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
629 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
630   #endif
631 + #ifdef __i386__
632 + #define SIGSEGV_EXCEPTION_STATE_TYPE    struct i386_exception_state
633 + #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
634 + #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
635 + #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.faultvaddr
636 + #define SIGSEGV_THREAD_STATE_TYPE               struct i386_thread_state
637 + #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
638 + #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
639 + #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.eip
640 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
641 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIP->thr_state.eax) /* EAX is the first GPR we consider */
642 + #endif
643 + #ifdef __x86_64__
644 + #define SIGSEGV_EXCEPTION_STATE_TYPE    struct x86_exception_state64
645 + #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
646 + #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
647 + #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.faultvaddr
648 + #define SIGSEGV_THREAD_STATE_TYPE               struct x86_thread_state64
649 + #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
650 + #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
651 + #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.rip
652 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
653 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIP->thr_state.rax) /* RAX is the first GPR we consider */
654 + #endif
655 + #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
656 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
657 + #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
658 + #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
659  
660   // Since there can only be one exception thread running at any time
661   // this is not a problem.
# Line 684 | Line 745 | enum {
745   #endif
746   };
747   #endif
748 < #if defined(__NetBSD__) || defined(__FreeBSD__)
748 > #if defined(__NetBSD__)
749 > enum {
750 > #if (defined(i386) || defined(__i386__))
751 >        X86_REG_EIP = _REG_EIP,
752 >        X86_REG_EAX = _REG_EAX,
753 >        X86_REG_ECX = _REG_ECX,
754 >        X86_REG_EDX = _REG_EDX,
755 >        X86_REG_EBX = _REG_EBX,
756 >        X86_REG_ESP = _REG_ESP,
757 >        X86_REG_EBP = _REG_EBP,
758 >        X86_REG_ESI = _REG_ESI,
759 >        X86_REG_EDI = _REG_EDI
760 > #endif
761 > };
762 > #endif
763 > #if defined(__FreeBSD__)
764   enum {
765   #if (defined(i386) || defined(__i386__))
766          X86_REG_EIP = 10,
# Line 699 | Line 775 | enum {
775   #endif
776   };
777   #endif
778 + #if defined(__OpenBSD__)
779 + enum {
780 + #if defined(__i386__)
781 +        // EDI is the first register we consider
782 + #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
783 + #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
784 +        X86_REG_EIP = DREG(eip), // 7
785 +        X86_REG_EAX = DREG(eax), // 6
786 +        X86_REG_ECX = DREG(ecx), // 5
787 +        X86_REG_EDX = DREG(edx), // 4
788 +        X86_REG_EBX = DREG(ebx), // 3
789 +        X86_REG_ESP = DREG(esp), // 10
790 +        X86_REG_EBP = DREG(ebp), // 2
791 +        X86_REG_ESI = DREG(esi), // 1
792 +        X86_REG_EDI = DREG(edi)  // 0
793 + #undef DREG
794 + #undef OREG
795 + #endif
796 + };
797 + #endif
798 + #if defined(__sun__)
799 + // Same as for Linux, need to check for x86-64
800 + enum {
801 + #if defined(__i386__)
802 +        X86_REG_EIP = EIP,
803 +        X86_REG_EAX = EAX,
804 +        X86_REG_ECX = ECX,
805 +        X86_REG_EDX = EDX,
806 +        X86_REG_EBX = EBX,
807 +        X86_REG_ESP = ESP,
808 +        X86_REG_EBP = EBP,
809 +        X86_REG_ESI = ESI,
810 +        X86_REG_EDI = EDI
811 + #endif
812 + };
813 + #endif
814 + #if defined(__APPLE__) && defined(__MACH__)
815 + enum {
816 + #if (defined(i386) || defined(__i386__))
817 + #ifdef i386_SAVED_STATE
818 +        // same as FreeBSD (in Open Darwin 8.0.1)
819 +        X86_REG_EIP = 10,
820 +        X86_REG_EAX = 7,
821 +        X86_REG_ECX = 6,
822 +        X86_REG_EDX = 5,
823 +        X86_REG_EBX = 4,
824 +        X86_REG_ESP = 13,
825 +        X86_REG_EBP = 2,
826 +        X86_REG_ESI = 1,
827 +        X86_REG_EDI = 0
828 + #else
829 +        // new layout (MacOS X 10.4.4 for x86)
830 +        X86_REG_EIP = 10,
831 +        X86_REG_EAX = 0,
832 +        X86_REG_ECX = 2,
833 +        X86_REG_EDX = 3,
834 +        X86_REG_EBX = 1,
835 +        X86_REG_ESP = 7,
836 +        X86_REG_EBP = 6,
837 +        X86_REG_ESI = 5,
838 +        X86_REG_EDI = 4
839 + #endif
840 + #endif
841 + #if defined(__x86_64__)
842 +        X86_REG_R8  = 8,
843 +        X86_REG_R9  = 9,
844 +        X86_REG_R10 = 10,
845 +        X86_REG_R11 = 11,
846 +        X86_REG_R12 = 12,
847 +        X86_REG_R13 = 13,
848 +        X86_REG_R14 = 14,
849 +        X86_REG_R15 = 15,
850 +        X86_REG_EDI = 4,
851 +        X86_REG_ESI = 5,
852 +        X86_REG_EBP = 6,
853 +        X86_REG_EBX = 1,
854 +        X86_REG_EDX = 3,
855 +        X86_REG_EAX = 0,
856 +        X86_REG_ECX = 2,
857 +        X86_REG_ESP = 7,
858 +        X86_REG_EIP = 16
859 + #endif
860 + };
861 + #endif
862   #if defined(_WIN32)
863   enum {
864   #if (defined(i386) || defined(__i386__))
# Line 754 | Line 914 | static bool ix86_skip_instruction(unsign
914  
915          if (eip == 0)
916                  return false;
917 + #ifdef _WIN32
918 +        if (IsBadCodePtr((FARPROC)eip))
919 +                return false;
920 + #endif
921          
922 +        enum instruction_type_t {
923 +                i_MOV,
924 +                i_ADD
925 +        };
926 +
927          transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
928          transfer_size_t transfer_size = SIZE_LONG;
929 +        instruction_type_t instruction_type = i_MOV;
930          
931          int reg = -1;
932          int len = 0;
# Line 807 | Line 977 | static bool ix86_skip_instruction(unsign
977   #endif
978  
979          // Decode instruction
980 +        int op_len = 1;
981          int target_size = SIZE_UNKNOWN;
982          switch (eip[0]) {
983          case 0x0f:
# Line 821 | Line 992 | static bool ix86_skip_instruction(unsign
992                          transfer_size = SIZE_WORD;
993                          goto do_mov_extend;
994                    do_mov_extend:
995 <                        switch (eip[2] & 0xc0) {
996 <                        case 0x80:
997 <                                reg = (eip[2] >> 3) & 7;
998 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
999 <                                break;
1000 <                        case 0x40:
1001 <                                reg = (eip[2] >> 3) & 7;
1002 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1003 <                                break;
1004 <                        case 0x00:
1005 <                                reg = (eip[2] >> 3) & 7;
1006 <                                transfer_type = SIGSEGV_TRANSFER_LOAD;
1007 <                                break;
1008 <                        }
1009 <                        len += 3 + ix86_step_over_modrm(eip + 2);
1010 <                        break;
1011 <            }
1012 <          break;
995 >                        op_len = 2;
996 >                        goto do_transfer_load;
997 >                }
998 >                break;
999 > #if defined(__x86_64__)
1000 >        case 0x63: // MOVSXD r64, r/m32
1001 >                if (has_rex && rex.W) {
1002 >                        transfer_size = SIZE_LONG;
1003 >                        target_size = SIZE_QUAD;
1004 >                }
1005 >                else if (transfer_size != SIZE_WORD) {
1006 >                        transfer_size = SIZE_LONG;
1007 >                        target_size = SIZE_QUAD;
1008 >                }
1009 >                goto do_transfer_load;
1010 > #endif
1011 >        case 0x02: // ADD r8, r/m8
1012 >                transfer_size = SIZE_BYTE;
1013 >        case 0x03: // ADD r32, r/m32
1014 >                instruction_type = i_ADD;
1015 >                goto do_transfer_load;
1016          case 0x8a: // MOV r8, r/m8
1017                  transfer_size = SIZE_BYTE;
1018          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
1019 <                switch (eip[1] & 0xc0) {
1019 >          do_transfer_load:
1020 >                switch (eip[op_len] & 0xc0) {
1021                  case 0x80:
1022 <                        reg = (eip[1] >> 3) & 7;
1022 >                        reg = (eip[op_len] >> 3) & 7;
1023                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1024                          break;
1025                  case 0x40:
1026 <                        reg = (eip[1] >> 3) & 7;
1026 >                        reg = (eip[op_len] >> 3) & 7;
1027                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1028                          break;
1029                  case 0x00:
1030 <                        reg = (eip[1] >> 3) & 7;
1030 >                        reg = (eip[op_len] >> 3) & 7;
1031                          transfer_type = SIGSEGV_TRANSFER_LOAD;
1032                          break;
1033                  }
1034 <                len += 2 + ix86_step_over_modrm(eip + 1);
1034 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1035                  break;
1036 +        case 0x00: // ADD r/m8, r8
1037 +                transfer_size = SIZE_BYTE;
1038 +        case 0x01: // ADD r/m32, r32
1039 +                instruction_type = i_ADD;
1040 +                goto do_transfer_store;
1041          case 0x88: // MOV r/m8, r8
1042                  transfer_size = SIZE_BYTE;
1043          case 0x89: // MOV r/m32, r32 (or 16-bit operation)
1044 <                switch (eip[1] & 0xc0) {
1044 >          do_transfer_store:
1045 >                switch (eip[op_len] & 0xc0) {
1046                  case 0x80:
1047 <                        reg = (eip[1] >> 3) & 7;
1047 >                        reg = (eip[op_len] >> 3) & 7;
1048                          transfer_type = SIGSEGV_TRANSFER_STORE;
1049                          break;
1050                  case 0x40:
1051 <                        reg = (eip[1] >> 3) & 7;
1051 >                        reg = (eip[op_len] >> 3) & 7;
1052                          transfer_type = SIGSEGV_TRANSFER_STORE;
1053                          break;
1054                  case 0x00:
1055 <                        reg = (eip[1] >> 3) & 7;
1055 >                        reg = (eip[op_len] >> 3) & 7;
1056                          transfer_type = SIGSEGV_TRANSFER_STORE;
1057                          break;
1058                  }
1059 <                len += 2 + ix86_step_over_modrm(eip + 1);
1059 >                len += 1 + op_len + ix86_step_over_modrm(eip + op_len);
1060                  break;
1061          }
1062          if (target_size == SIZE_UNKNOWN)
# Line 891 | Line 1072 | static bool ix86_skip_instruction(unsign
1072                  reg += 8;
1073   #endif
1074  
1075 <        if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1075 >        if (instruction_type == i_MOV && transfer_type == SIGSEGV_TRANSFER_LOAD && reg != -1) {
1076                  static const int x86_reg_map[] = {
1077                          X86_REG_EAX, X86_REG_ECX, X86_REG_EDX, X86_REG_EBX,
1078                          X86_REG_ESP, X86_REG_EBP, X86_REG_ESI, X86_REG_EDI,
# Line 927 | Line 1108 | static bool ix86_skip_instruction(unsign
1108          }
1109  
1110   #if DEBUG
1111 <        printf("%08x: %s %s access", regs[X86_REG_EIP],
1111 >        printf("%p: %s %s access", (void *)regs[X86_REG_EIP],
1112                     transfer_size == SIZE_BYTE ? "byte" :
1113                     transfer_size == SIZE_WORD ? "word" :
1114                     transfer_size == SIZE_LONG ? "long" :
# Line 982 | Line 1163 | static bool ix86_skip_instruction(unsign
1163   }
1164   #endif
1165  
1166 + // Decode and skip IA-64 instruction
1167 + #if defined(__ia64__)
1168 + #if defined(__linux__)
1169 + // We can directly patch the slot number
1170 + #define IA64_CAN_PATCH_IP_SLOT 1
1171 + // Helper macros to access the machine context
1172 + #define IA64_CONTEXT_TYPE               struct sigcontext *
1173 + #define IA64_CONTEXT                    scp
1174 + #define IA64_GET_IP()                   (IA64_CONTEXT->sc_ip)
1175 + #define IA64_SET_IP(V)                  (IA64_CONTEXT->sc_ip = (V))
1176 + #define IA64_GET_PR(P)                  ((IA64_CONTEXT->sc_pr >> (P)) & 1)
1177 + #define IA64_GET_NAT(I)                 ((IA64_CONTEXT->sc_nat >> (I)) & 1)
1178 + #define IA64_SET_NAT(I,V)               (IA64_CONTEXT->sc_nat= (IA64_CONTEXT->sc_nat & ~(1ul << (I))) | (((unsigned long)!!(V)) << (I)))
1179 + #define IA64_GET_GR(R)                  (IA64_CONTEXT->sc_gr[(R)])
1180 + #define IA64_SET_GR(R,V)                (IA64_CONTEXT->sc_gr[(R)] = (V))
1181 + #endif
1182 +
1183 + // Instruction operations
1184 + enum {
1185 +        IA64_INST_UNKNOWN = 0,
1186 +        IA64_INST_LD1,                          // ld1 op0=[op1]
1187 +        IA64_INST_LD1_UPDATE,           // ld1 op0=[op1],op2
1188 +        IA64_INST_LD2,                          // ld2 op0=[op1]
1189 +        IA64_INST_LD2_UPDATE,           // ld2 op0=[op1],op2
1190 +        IA64_INST_LD4,                          // ld4 op0=[op1]
1191 +        IA64_INST_LD4_UPDATE,           // ld4 op0=[op1],op2
1192 +        IA64_INST_LD8,                          // ld8 op0=[op1]
1193 +        IA64_INST_LD8_UPDATE,           // ld8 op0=[op1],op2
1194 +        IA64_INST_ST1,                          // st1 [op0]=op1
1195 +        IA64_INST_ST1_UPDATE,           // st1 [op0]=op1,op2
1196 +        IA64_INST_ST2,                          // st2 [op0]=op1
1197 +        IA64_INST_ST2_UPDATE,           // st2 [op0]=op1,op2
1198 +        IA64_INST_ST4,                          // st4 [op0]=op1
1199 +        IA64_INST_ST4_UPDATE,           // st4 [op0]=op1,op2
1200 +        IA64_INST_ST8,                          // st8 [op0]=op1
1201 +        IA64_INST_ST8_UPDATE,           // st8 [op0]=op1,op2
1202 +        IA64_INST_ADD,                          // add op0=op1,op2,op3
1203 +        IA64_INST_SUB,                          // sub op0=op1,op2,op3
1204 +        IA64_INST_SHLADD,                       // shladd op0=op1,op3,op2
1205 +        IA64_INST_AND,                          // and op0=op1,op2
1206 +        IA64_INST_ANDCM,                        // andcm op0=op1,op2
1207 +        IA64_INST_OR,                           // or op0=op1,op2
1208 +        IA64_INST_XOR,                          // xor op0=op1,op2
1209 +        IA64_INST_SXT1,                         // sxt1 op0=op1
1210 +        IA64_INST_SXT2,                         // sxt2 op0=op1
1211 +        IA64_INST_SXT4,                         // sxt4 op0=op1
1212 +        IA64_INST_ZXT1,                         // zxt1 op0=op1
1213 +        IA64_INST_ZXT2,                         // zxt2 op0=op1
1214 +        IA64_INST_ZXT4,                         // zxt4 op0=op1
1215 +        IA64_INST_NOP                           // nop op0
1216 + };
1217 +
1218 + const int IA64_N_OPERANDS = 4;
1219 +
1220 + // Decoded operand type
1221 + struct ia64_operand_t {
1222 +        unsigned char commit;           // commit result of operation to register file?
1223 +        unsigned char valid;            // XXX: not really used, can be removed (debug)
1224 +        signed char index;                      // index of GPR, or -1 if immediate value
1225 +        unsigned char nat;                      // NaT state before operation
1226 +        unsigned long value;            // register contents or immediate value
1227 + };
1228 +
1229 + // Decoded instruction type
1230 + struct ia64_instruction_t {
1231 +        unsigned char mnemo;            // operation to perform
1232 +        unsigned char pred;                     // predicate register to check
1233 +        unsigned char no_memory;        // used to emulated main fault instruction
1234 +        unsigned long inst;                     // the raw instruction bits (41-bit wide)
1235 +        ia64_operand_t operands[IA64_N_OPERANDS];
1236 + };
1237 +
1238 + // Get immediate sign-bit
1239 + static inline int ia64_inst_get_sbit(unsigned long inst)
1240 + {
1241 +        return (inst >> 36) & 1;
1242 + }
1243 +
1244 + // Get 8-bit immediate value (A3, A8, I27, M30)
1245 + static inline unsigned long ia64_inst_get_imm8(unsigned long inst)
1246 + {
1247 +        unsigned long value = (inst >> 13) & 0x7ful;
1248 +        if (ia64_inst_get_sbit(inst))
1249 +                value |= ~0x7ful;
1250 +        return value;
1251 + }
1252 +
1253 + // Get 9-bit immediate value (M3)
1254 + static inline unsigned long ia64_inst_get_imm9b(unsigned long inst)
1255 + {
1256 +        unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f);
1257 +        if (ia64_inst_get_sbit(inst))
1258 +                value |= ~0xfful;
1259 +        return value;
1260 + }
1261 +
1262 + // Get 9-bit immediate value (M5)
1263 + static inline unsigned long ia64_inst_get_imm9a(unsigned long inst)
1264 + {
1265 +        unsigned long value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f);
1266 +        if (ia64_inst_get_sbit(inst))
1267 +                value |= ~0xfful;
1268 +        return value;
1269 + }
1270 +
1271 + // Get 14-bit immediate value (A4)
1272 + static inline unsigned long ia64_inst_get_imm14(unsigned long inst)
1273 + {
1274 +        unsigned long value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f);
1275 +        if (ia64_inst_get_sbit(inst))
1276 +                value |= ~0x1fful;
1277 +        return value;
1278 + }
1279 +
1280 + // Get 22-bit immediate value (A5)
1281 + static inline unsigned long ia64_inst_get_imm22(unsigned long inst)
1282 + {
1283 +        unsigned long value = ((((inst >> 22) & 0x1f) << 16) |
1284 +                                                   (((inst >> 27) & 0x1ff) << 7) |
1285 +                                                   (inst & 0x7f));
1286 +        if (ia64_inst_get_sbit(inst))
1287 +                value |= ~0x1ffffful;
1288 +        return value;
1289 + }
1290 +
1291 + // Get 21-bit immediate value (I19)
1292 + static inline unsigned long ia64_inst_get_imm21(unsigned long inst)
1293 + {
1294 +        return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff);
1295 + }
1296 +
1297 + // Get 2-bit count value (A2)
1298 + static inline int ia64_inst_get_count2(unsigned long inst)
1299 + {
1300 +        return (inst >> 27) & 0x3;
1301 + }
1302 +
1303 + // Get bundle template
1304 + static inline unsigned int ia64_get_template(unsigned long raw_ip)
1305 + {
1306 +        unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1307 +        return ip[0] & 0x1f;
1308 + }
1309 +
1310 + // Get specified instruction in bundle
1311 + static unsigned long ia64_get_instruction(unsigned long raw_ip, int slot)
1312 + {
1313 +        unsigned long inst;
1314 +        unsigned long *ip = (unsigned long *)(raw_ip & ~3ul);
1315 + #if DEBUG
1316 +        printf("Bundle: %016lx%016lx\n", ip[1], ip[0]);
1317 + #endif
1318 +
1319 +        switch (slot) {
1320 +        case 0:
1321 +                inst = (ip[0] >> 5) & 0x1fffffffffful;
1322 +                break;
1323 +        case 1:
1324 +                inst = ((ip[1] & 0x7ffffful) << 18) | ((ip[0] >> 46) & 0x3fffful);
1325 +                break;
1326 +        case 2:
1327 +                inst = (ip[1] >> 23) & 0x1fffffffffful;
1328 +                break;
1329 +        case 3:
1330 +                fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot);
1331 +                abort();
1332 +                break;
1333 +        }
1334 +
1335 + #if DEBUG
1336 +        printf(" Instruction %d: 0x%016lx\n", slot, inst);
1337 + #endif
1338 +        return inst;
1339 + }
1340 +
1341 + // Decode group 0 instructions
1342 + static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1343 + {
1344 +        const int r1 = (inst->inst >>  6) & 0x7f;
1345 +        const int r3 = (inst->inst >> 20) & 0x7f;
1346 +
1347 +        const int x3 = (inst->inst >> 33) & 0x07;
1348 +        const int x6 = (inst->inst >> 27) & 0x3f;
1349 +        const int x2 = (inst->inst >> 31) & 0x03;
1350 +        const int x4 = (inst->inst >> 27) & 0x0f;
1351 +
1352 +        if (x3 == 0) {
1353 +                switch (x6) {
1354 +                case 0x01:                                              // nop.i (I19)
1355 +                        inst->mnemo = IA64_INST_NOP;
1356 +                        inst->operands[0].valid = true;
1357 +                        inst->operands[0].index = -1;
1358 +                        inst->operands[0].value = ia64_inst_get_imm21(inst->inst);
1359 +                        return true;
1360 +                case 0x14:                                              // sxt1 (I29)
1361 +                case 0x15:                                              // sxt2 (I29)
1362 +                case 0x16:                                              // sxt4 (I29)
1363 +                case 0x10:                                              // zxt1 (I29)
1364 +                case 0x11:                                              // zxt2 (I29)
1365 +                case 0x12:                                              // zxt4 (I29)
1366 +                        switch (x6) {
1367 +                        case 0x14: inst->mnemo = IA64_INST_SXT1; break;
1368 +                        case 0x15: inst->mnemo = IA64_INST_SXT2; break;
1369 +                        case 0x16: inst->mnemo = IA64_INST_SXT4; break;
1370 +                        case 0x10: inst->mnemo = IA64_INST_ZXT1; break;
1371 +                        case 0x11: inst->mnemo = IA64_INST_ZXT2; break;
1372 +                        case 0x12: inst->mnemo = IA64_INST_ZXT4; break;
1373 +                        default: abort();
1374 +                        }
1375 +                        inst->operands[0].valid = true;
1376 +                        inst->operands[0].index = r1;
1377 +                        inst->operands[1].valid = true;
1378 +                        inst->operands[1].index = r3;
1379 +                        inst->operands[1].value = IA64_GET_GR(r3);
1380 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1381 +                        return true;
1382 +                }
1383 +        }
1384 +        return false;
1385 + }
1386 +
1387 + // Decode group 4 instructions (load/store instructions)
1388 + static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1389 + {
1390 +        const int r1 = (inst->inst >> 6) & 0x7f;
1391 +        const int r2 = (inst->inst >> 13) & 0x7f;
1392 +        const int r3 = (inst->inst >> 20) & 0x7f;
1393 +
1394 +        const int m  = (inst->inst >> 36) & 1;
1395 +        const int x  = (inst->inst >> 27) & 1;
1396 +        const int x6 = (inst->inst >> 30) & 0x3f;
1397 +
1398 +        switch (x6) {
1399 +        case 0x00:
1400 +        case 0x01:
1401 +        case 0x02:
1402 +        case 0x03:
1403 +                if (x == 0) {
1404 +                        inst->operands[0].valid = true;
1405 +                        inst->operands[0].index = r1;
1406 +                        inst->operands[1].valid = true;
1407 +                        inst->operands[1].index = r3;
1408 +                        inst->operands[1].value = IA64_GET_GR(r3);
1409 +                        inst->operands[1].nat   = IA64_GET_NAT(r3);
1410 +                        if (m == 0) {
1411 +                                switch (x6) {
1412 +                                case 0x00: inst->mnemo = IA64_INST_LD1; break;
1413 +                                case 0x01: inst->mnemo = IA64_INST_LD2; break;
1414 +                                case 0x02: inst->mnemo = IA64_INST_LD4; break;
1415 +                                case 0x03: inst->mnemo = IA64_INST_LD8; break;
1416 +                                }
1417 +                        }
1418 +                        else {
1419 +                                inst->operands[2].valid = true;
1420 +                                inst->operands[2].index = r2;
1421 +                                inst->operands[2].value = IA64_GET_GR(r2);
1422 +                                inst->operands[2].nat   = IA64_GET_NAT(r2);
1423 +                                switch (x6) {
1424 +                                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1425 +                                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1426 +                                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1427 +                                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1428 +                                }
1429 +                        }
1430 +                        return true;
1431 +                }
1432 +                break;
1433 +        case 0x30:
1434 +        case 0x31:
1435 +        case 0x32:
1436 +        case 0x33:
1437 +                if (m == 0 && x == 0) {
1438 +                        inst->operands[0].valid = true;
1439 +                        inst->operands[0].index = r3;
1440 +                        inst->operands[0].value = IA64_GET_GR(r3);
1441 +                        inst->operands[0].nat   = IA64_GET_NAT(r3);
1442 +                        inst->operands[1].valid = true;
1443 +                        inst->operands[1].index = r2;
1444 +                        inst->operands[1].value = IA64_GET_GR(r2);
1445 +                        inst->operands[1].nat   = IA64_GET_NAT(r2);
1446 +                        switch (x6) {
1447 +                        case 0x30: inst->mnemo = IA64_INST_ST1; break;
1448 +                        case 0x31: inst->mnemo = IA64_INST_ST2; break;
1449 +                        case 0x32: inst->mnemo = IA64_INST_ST4; break;
1450 +                        case 0x33: inst->mnemo = IA64_INST_ST8; break;
1451 +                        }
1452 +                        return true;
1453 +                }
1454 +                break;
1455 +        }
1456 +        return false;
1457 + }
1458 +
1459 + // Decode group 5 instructions (load/store instructions)
1460 + static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1461 + {
1462 +        const int r1 = (inst->inst >> 6) & 0x7f;
1463 +        const int r2 = (inst->inst >> 13) & 0x7f;
1464 +        const int r3 = (inst->inst >> 20) & 0x7f;
1465 +
1466 +        const int x6 = (inst->inst >> 30) & 0x3f;
1467 +
1468 +        switch (x6) {
1469 +        case 0x00:
1470 +        case 0x01:
1471 +        case 0x02:
1472 +        case 0x03:
1473 +                inst->operands[0].valid = true;
1474 +                inst->operands[0].index = r1;
1475 +                inst->operands[1].valid = true;
1476 +                inst->operands[1].index = r3;
1477 +                inst->operands[1].value = IA64_GET_GR(r3);
1478 +                inst->operands[1].nat   = IA64_GET_NAT(r3);
1479 +                inst->operands[2].valid = true;
1480 +                inst->operands[2].index = -1;
1481 +                inst->operands[2].value = ia64_inst_get_imm9b(inst->inst);
1482 +                inst->operands[2].nat   = 0;
1483 +                switch (x6) {
1484 +                case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break;
1485 +                case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break;
1486 +                case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break;
1487 +                case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break;
1488 +                }
1489 +                return true;
1490 +        case 0x30:
1491 +        case 0x31:
1492 +        case 0x32:
1493 +        case 0x33:
1494 +                inst->operands[0].valid = true;
1495 +                inst->operands[0].index = r3;
1496 +                inst->operands[0].value = IA64_GET_GR(r3);
1497 +                inst->operands[0].nat   = IA64_GET_NAT(r3);
1498 +                inst->operands[1].valid = true;
1499 +                inst->operands[1].index = r2;
1500 +                inst->operands[1].value = IA64_GET_GR(r2);
1501 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1502 +                inst->operands[2].valid = true;
1503 +                inst->operands[2].index = -1;
1504 +                inst->operands[2].value = ia64_inst_get_imm9a(inst->inst);
1505 +                inst->operands[2].nat   = 0;
1506 +                switch (x6) {
1507 +                case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break;
1508 +                case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break;
1509 +                case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break;
1510 +                case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break;
1511 +                }
1512 +                return true;
1513 +        }
1514 +        return false;
1515 + }
1516 +
1517 + // Decode group 8 instructions (ALU integer)
1518 + static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1519 + {
1520 +        const int r1  = (inst->inst >> 6) & 0x7f;
1521 +        const int r2  = (inst->inst >> 13) & 0x7f;
1522 +        const int r3  = (inst->inst >> 20) & 0x7f;
1523 +
1524 +        const int x2a = (inst->inst >> 34) & 0x3;
1525 +        const int x2b = (inst->inst >> 27) & 0x3;
1526 +        const int x4  = (inst->inst >> 29) & 0xf;
1527 +        const int ve  = (inst->inst >> 33) & 0x1;
1528 +
1529 +        // destination register (r1) is always valid in this group
1530 +        inst->operands[0].valid = true;
1531 +        inst->operands[0].index = r1;
1532 +
1533 +        // source register (r3) is always valid in this group
1534 +        inst->operands[2].valid = true;
1535 +        inst->operands[2].index = r3;
1536 +        inst->operands[2].value = IA64_GET_GR(r3);
1537 +        inst->operands[2].nat   = IA64_GET_NAT(r3);
1538 +
1539 +        if (x2a == 0 && ve == 0) {
1540 +                inst->operands[1].valid = true;
1541 +                inst->operands[1].index = r2;
1542 +                inst->operands[1].value = IA64_GET_GR(r2);
1543 +                inst->operands[1].nat   = IA64_GET_NAT(r2);
1544 +                switch (x4) {
1545 +                case 0x0:                               // add (A1)
1546 +                        inst->mnemo = IA64_INST_ADD;
1547 +                        inst->operands[3].valid = true;
1548 +                        inst->operands[3].index = -1;
1549 +                        inst->operands[3].value = x2b == 1;
1550 +                        return true;
1551 +                case 0x1:                               // add (A1)
1552 +                        inst->mnemo = IA64_INST_SUB;
1553 +                        inst->operands[3].valid = true;
1554 +                        inst->operands[3].index = -1;
1555 +                        inst->operands[3].value = x2b == 0;
1556 +                        return true;
1557 +                case 0x4:                               // shladd (A2)
1558 +                        inst->mnemo = IA64_INST_SHLADD;
1559 +                        inst->operands[3].valid = true;
1560 +                        inst->operands[3].index = -1;
1561 +                        inst->operands[3].value = ia64_inst_get_count2(inst->inst);
1562 +                        return true;
1563 +                case 0x9:
1564 +                        if (x2b == 1) {
1565 +                                inst->mnemo = IA64_INST_SUB;
1566 +                                inst->operands[1].index = -1;
1567 +                                inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1568 +                                inst->operands[1].nat   = 0;
1569 +                                return true;
1570 +                        }
1571 +                        break;
1572 +                case 0xb:
1573 +                        inst->operands[1].index = -1;
1574 +                        inst->operands[1].value = ia64_inst_get_imm8(inst->inst);
1575 +                        inst->operands[1].nat   = 0;
1576 +                        // fall-through
1577 +                case 0x3:
1578 +                        switch (x2b) {
1579 +                        case 0: inst->mnemo = IA64_INST_AND;   break;
1580 +                        case 1: inst->mnemo = IA64_INST_ANDCM; break;
1581 +                        case 2: inst->mnemo = IA64_INST_OR;    break;
1582 +                        case 3: inst->mnemo = IA64_INST_XOR;   break;
1583 +                        }
1584 +                        return true;
1585 +                }
1586 +        }
1587 +        return false;
1588 + }
1589 +
1590 + // Decode instruction
1591 + static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1592 + {
1593 +        const int major = (inst->inst >> 37) & 0xf;
1594 +
1595 +        inst->mnemo = IA64_INST_UNKNOWN;
1596 +        inst->pred  = inst->inst & 0x3f;
1597 +        memset(&inst->operands[0], 0, sizeof(inst->operands));
1598 +
1599 +        switch (major) {
1600 +        case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
1601 +        case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
1602 +        case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
1603 +        case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
1604 +        }
1605 +        return false;
1606 + }
1607 +
1608 + static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1609 + {
1610 +        // XXX: handle Register NaT Consumption fault?
1611 +        // XXX: this simple emulator assumes instructions in a bundle
1612 +        // don't depend on effects of other instructions in the same
1613 +        // bundle. It probably would be simpler to JIT-generate code to be
1614 +        // executed natively but probably more costly (inject/extract CPU state)
1615 +        if (inst->mnemo == IA64_INST_UNKNOWN)
1616 +                return false;
1617 +        if (inst->pred && !IA64_GET_PR(inst->pred))
1618 +                return true;
1619 +
1620 +        unsigned char nat, nat2;
1621 +        unsigned long dst, dst2, src1, src2, src3;
1622 +
1623 +        switch (inst->mnemo) {
1624 +        case IA64_INST_NOP:
1625 +                break;
1626 +        case IA64_INST_ADD:
1627 +        case IA64_INST_SUB:
1628 +        case IA64_INST_SHLADD:
1629 +                src3 = inst->operands[3].value;
1630 +                // fall-through
1631 +        case IA64_INST_AND:
1632 +        case IA64_INST_ANDCM:
1633 +        case IA64_INST_OR:
1634 +        case IA64_INST_XOR:
1635 +                src1 = inst->operands[1].value;
1636 +                src2 = inst->operands[2].value;
1637 +                switch (inst->mnemo) {
1638 +                case IA64_INST_ADD:   dst = src1 + src2 + src3; break;
1639 +                case IA64_INST_SUB:   dst = src1 - src2 - src3; break;
1640 +                case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break;
1641 +                case IA64_INST_AND:   dst = src1 & src2;                break;
1642 +                case IA64_INST_ANDCM: dst = src1 &~ src2;               break;
1643 +                case IA64_INST_OR:    dst = src1 | src2;                break;
1644 +                case IA64_INST_XOR:   dst = src1 ^ src2;                break;
1645 +                }
1646 +                inst->operands[0].commit = true;
1647 +                inst->operands[0].value  = dst;
1648 +                inst->operands[0].nat    = inst->operands[1].nat | inst->operands[2].nat;
1649 +                break;
1650 +        case IA64_INST_SXT1:
1651 +        case IA64_INST_SXT2:
1652 +        case IA64_INST_SXT4:
1653 +        case IA64_INST_ZXT1:
1654 +        case IA64_INST_ZXT2:
1655 +        case IA64_INST_ZXT4:
1656 +                src1 = inst->operands[1].value;
1657 +                switch (inst->mnemo) {
1658 +                case IA64_INST_SXT1: dst = (signed long)(signed char)src1;              break;
1659 +                case IA64_INST_SXT2: dst = (signed long)(signed short)src1;             break;
1660 +                case IA64_INST_SXT4: dst = (signed long)(signed int)src1;               break;
1661 +                case IA64_INST_ZXT1: dst = (unsigned char)src1;                                 break;
1662 +                case IA64_INST_ZXT2: dst = (unsigned short)src1;                                break;
1663 +                case IA64_INST_ZXT4: dst = (unsigned int)src1;                                  break;
1664 +                }
1665 +                inst->operands[0].commit = true;
1666 +                inst->operands[0].value  = dst;
1667 +                inst->operands[0].nat    = inst->operands[1].nat;
1668 +                break;
1669 +        case IA64_INST_LD1_UPDATE:
1670 +        case IA64_INST_LD2_UPDATE:
1671 +        case IA64_INST_LD4_UPDATE:
1672 +        case IA64_INST_LD8_UPDATE:
1673 +                inst->operands[1].commit = true;
1674 +                dst2 = inst->operands[1].value + inst->operands[2].value;
1675 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1676 +                // fall-through
1677 +        case IA64_INST_LD1:
1678 +        case IA64_INST_LD2:
1679 +        case IA64_INST_LD4:
1680 +        case IA64_INST_LD8:
1681 +                src1 = inst->operands[1].value;
1682 +                if (inst->no_memory)
1683 +                        dst = 0;
1684 +                else {
1685 +                        switch (inst->mnemo) {
1686 +                        case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((unsigned char *)src1);  break;
1687 +                        case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((unsigned short *)src1); break;
1688 +                        case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((unsigned int *)src1);   break;
1689 +                        case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((unsigned long *)src1);  break;
1690 +                        }
1691 +                }
1692 +                inst->operands[0].commit = true;
1693 +                inst->operands[0].value  = dst;
1694 +                inst->operands[0].nat    = 0;
1695 +                inst->operands[1].value  = dst2;
1696 +                inst->operands[1].nat    = nat2;
1697 +                break;
1698 +        case IA64_INST_ST1_UPDATE:
1699 +        case IA64_INST_ST2_UPDATE:
1700 +        case IA64_INST_ST4_UPDATE:
1701 +        case IA64_INST_ST8_UPDATE:
1702 +                inst->operands[0].commit = 0;
1703 +                dst2 = inst->operands[0].value + inst->operands[2].value;
1704 +                nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0;
1705 +                // fall-through
1706 +        case IA64_INST_ST1:
1707 +        case IA64_INST_ST2:
1708 +        case IA64_INST_ST4:
1709 +        case IA64_INST_ST8:
1710 +                dst  = inst->operands[0].value;
1711 +                src1 = inst->operands[1].value;
1712 +                if (!inst->no_memory) {
1713 +                        switch (inst->mnemo) {
1714 +                        case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((unsigned char *)dst) = src1;  break;
1715 +                        case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((unsigned short *)dst) = src1; break;
1716 +                        case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((unsigned int *)dst) = src1;   break;
1717 +                        case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((unsigned long *)dst) = src1;  break;
1718 +                        }
1719 +                }
1720 +                inst->operands[0].value  = dst2;
1721 +                inst->operands[0].nat    = nat2;
1722 +                break;
1723 +        default:
1724 +                return false;
1725 +        }
1726 +
1727 +        for (int i = 0; i < IA64_N_OPERANDS; i++) {
1728 +                ia64_operand_t const & op = inst->operands[i];
1729 +                if (!op.commit)
1730 +                        continue;
1731 +                if (op.index == -1)
1732 +                        return false; // XXX: internal error
1733 +                IA64_SET_GR(op.index, op.value);
1734 +                IA64_SET_NAT(op.index, op.nat);
1735 +        }
1736 +        return true;
1737 + }
1738 +
1739 + static bool ia64_emulate_instruction(unsigned long raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
1740 + {
1741 +        ia64_instruction_t inst;
1742 +        memset(&inst, 0, sizeof(inst));
1743 +        inst.inst = raw_inst;
1744 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
1745 +                return false;
1746 +        return ia64_emulate_instruction(&inst, IA64_CONTEXT);
1747 + }
1748 +
1749 + static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
1750 + {
1751 +        unsigned long ip = IA64_GET_IP();
1752 + #if DEBUG
1753 +        printf("IP: 0x%016lx\n", ip);
1754 + #if 0
1755 +        printf(" Template 0x%02x\n", ia64_get_template(ip));
1756 +        ia64_get_instruction(ip, 0);
1757 +        ia64_get_instruction(ip, 1);
1758 +        ia64_get_instruction(ip, 2);
1759 + #endif
1760 + #endif
1761 +
1762 +        // Select which decode switch to use
1763 +        ia64_instruction_t inst;
1764 +        inst.inst = ia64_get_instruction(ip, ip & 3);
1765 +        if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
1766 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
1767 +                return false;
1768 +        }
1769 +
1770 +        transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
1771 +        transfer_size_t transfer_size = SIZE_UNKNOWN;
1772 +
1773 +        switch (inst.mnemo) {
1774 +        case IA64_INST_LD1:
1775 +        case IA64_INST_LD2:
1776 +        case IA64_INST_LD4:
1777 +        case IA64_INST_LD8:
1778 +        case IA64_INST_LD1_UPDATE:
1779 +        case IA64_INST_LD2_UPDATE:
1780 +        case IA64_INST_LD4_UPDATE:
1781 +        case IA64_INST_LD8_UPDATE:
1782 +                transfer_type = SIGSEGV_TRANSFER_LOAD;
1783 +                break;
1784 +        case IA64_INST_ST1:
1785 +        case IA64_INST_ST2:
1786 +        case IA64_INST_ST4:
1787 +        case IA64_INST_ST8:
1788 +        case IA64_INST_ST1_UPDATE:
1789 +        case IA64_INST_ST2_UPDATE:
1790 +        case IA64_INST_ST4_UPDATE:
1791 +        case IA64_INST_ST8_UPDATE:
1792 +                transfer_type = SIGSEGV_TRANSFER_STORE;
1793 +                break;
1794 +        }
1795 +
1796 +        if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1797 +                // Unknown machine code, let it crash. Then patch the decoder
1798 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n");
1799 +                return false;
1800 +        }
1801 +
1802 +        switch (inst.mnemo) {
1803 +        case IA64_INST_LD1:
1804 +        case IA64_INST_LD1_UPDATE:
1805 +        case IA64_INST_ST1:
1806 +        case IA64_INST_ST1_UPDATE:
1807 +                transfer_size = SIZE_BYTE;
1808 +                break;
1809 +        case IA64_INST_LD2:
1810 +        case IA64_INST_LD2_UPDATE:
1811 +        case IA64_INST_ST2:
1812 +        case IA64_INST_ST2_UPDATE:
1813 +                transfer_size = SIZE_WORD;
1814 +                break;
1815 +        case IA64_INST_LD4:
1816 +        case IA64_INST_LD4_UPDATE:
1817 +        case IA64_INST_ST4:
1818 +        case IA64_INST_ST4_UPDATE:
1819 +                transfer_size = SIZE_LONG;
1820 +                break;
1821 +        case IA64_INST_LD8:
1822 +        case IA64_INST_LD8_UPDATE:
1823 +        case IA64_INST_ST8:
1824 +        case IA64_INST_ST8_UPDATE:
1825 +                transfer_size = SIZE_QUAD;
1826 +                break;
1827 +        }
1828 +
1829 +        if (transfer_size == SIZE_UNKNOWN) {
1830 +                // Unknown machine code, let it crash. Then patch the decoder
1831 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n");
1832 +                return false;
1833 +        }
1834 +
1835 +        inst.no_memory = true;
1836 +        if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
1837 +                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
1838 +                return false;
1839 +        }
1840 +
1841 +        int slot = ip & 3;
1842 +        bool emulate_next = false;
1843 +        switch (slot) {
1844 +        case 0:
1845 +                switch (ia64_get_template(ip)) {
1846 +                case 0x2: // MI;I
1847 +                case 0x3: // MI;I;
1848 +                        emulate_next = true;
1849 +                        slot = 2;
1850 +                        break;
1851 +                case 0xa: // M;MI
1852 +                case 0xb: // M;MI;
1853 +                        emulate_next = true;
1854 +                        slot = 1;
1855 +                        break;
1856 +                }
1857 +                break;
1858 +        }
1859 +        if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
1860 +                while (slot < 3) {
1861 +                        if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
1862 +                                fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
1863 +                                return false;
1864 +                        }
1865 +                        ++slot;
1866 +                }
1867 +        }
1868 +
1869 + #if IA64_CAN_PATCH_IP_SLOT
1870 +        if ((slot = ip & 3) < 2)
1871 +                IA64_SET_IP((ip & ~3ul) + (slot + 1));
1872 +        else
1873 + #endif
1874 +                IA64_SET_IP((ip & ~3ul) + 16);
1875 + #if DEBUG
1876 +        printf("IP: 0x%016lx\n", IA64_GET_IP());
1877 + #endif
1878 +        return true;
1879 + }
1880 + #endif
1881 +
1882   // Decode and skip PPC instruction
1883 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
1883 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
1884   static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
1885   {
1886          instruction_t instr;
# Line 1019 | Line 1916 | static bool powerpc_skip_instruction(uns
1916  
1917   // Decode and skip MIPS instruction
1918   #if (defined(mips) || defined(__mips))
1919 < enum {
1023 < #if (defined(sgi) || defined(__sgi))
1024 <  MIPS_REG_EPC = 35,
1025 < #endif
1026 < };
1027 < static bool mips_skip_instruction(greg_t * regs)
1919 > static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs)
1920   {
1921 <  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
1921 >  unsigned int * epc = (unsigned int *)(unsigned long)*pc_p;
1922  
1923    if (epc == 0)
1924          return false;
# Line 1175 | Line 2067 | static bool mips_skip_instruction(greg_t
2067                   mips_gpr_names[reg]);
2068   #endif
2069  
2070 <  regs[MIPS_REG_EPC] += 4;
2070 >  *pc_p += 4;
2071    return true;
2072   }
2073   #endif
# Line 1187 | Line 2079 | enum {
2079    SPARC_REG_G1 = REG_G1,
2080    SPARC_REG_O0 = REG_O0,
2081    SPARC_REG_PC = REG_PC,
2082 +  SPARC_REG_nPC = REG_nPC
2083   #endif
2084   };
2085   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1250 | Line 2143 | static bool sparc_skip_instruction(unsig
2143          break;
2144    case 7: // Store Doubleword
2145          transfer_type = SIGSEGV_TRANSFER_STORE;
2146 <        transfer_size = SIZE_WORD;
2146 >        transfer_size = SIZE_LONG;
2147          register_pair = true;
2148          break;
2149    }
# Line 1260 | Line 2153 | static bool sparc_skip_instruction(unsig
2153          return false;
2154    }
2155  
1263  // Zero target register in case of a load operation
2156    const int reg = (opcode >> 25) & 0x1f;
2157 +
2158 + #if DEBUG
2159 +  static const char * reg_names[] = {
2160 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
2161 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
2162 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
2163 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
2164 +  };
2165 +  printf("%s %s register %s\n",
2166 +                 transfer_size == SIZE_BYTE ? "byte" :
2167 +                 transfer_size == SIZE_WORD ? "word" :
2168 +                 transfer_size == SIZE_LONG ? "long" :
2169 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
2170 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
2171 +                 reg_names[reg]);
2172 + #endif
2173 +
2174 +  // Zero target register in case of a load operation
2175    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
2176          // FIXME: code to handle local & input registers is not tested
2177 <        if (reg >= 1 && reg <= 7) {
2177 >        if (reg >= 1 && reg < 8) {
2178            // global registers
2179            regs[reg - 1 + SPARC_REG_G1] = 0;
2180          }
2181 <        else if (reg >= 8 && reg <= 15) {
2181 >        else if (reg >= 8 && reg < 16) {
2182            // output registers
2183            regs[reg - 8 + SPARC_REG_O0] = 0;
2184          }
2185 <        else if (reg >= 16 && reg <= 23) {
2185 >        else if (reg >= 16 && reg < 24) {
2186            // local registers (in register windows)
2187            if (gwins)
2188                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1288 | Line 2198 | static bool sparc_skip_instruction(unsig
2198          }
2199    }
2200  
1291 #if DEBUG
1292  static const char * reg_names[] = {
1293        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1294        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1295        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1296        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1297  };
1298  printf("%s %s register %s\n",
1299                 transfer_size == SIZE_BYTE ? "byte" :
1300                 transfer_size == SIZE_WORD ? "word" :
1301                 transfer_size == SIZE_LONG ? "long" :
1302                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1303                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1304                 reg_names[reg]);
1305 #endif
1306
2201    regs[SPARC_REG_PC] += 4;
2202 +  regs[SPARC_REG_nPC] += 4;
2203    return true;
2204   }
2205   #endif
# Line 1460 | Line 2355 | static bool arm_skip_instruction(unsigne
2355  
2356  
2357   // Fallbacks
2358 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
2359 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
2360 + #endif
2361 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
2362 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
2363 + #endif
2364   #ifndef SIGSEGV_FAULT_INSTRUCTION
2365 < #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_PC
2365 > #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
2366   #endif
2367   #ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1
2368   #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST
2369   #endif
2370   #ifndef SIGSEGV_FAULT_HANDLER_INVOKE
2371 < #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  sigsegv_fault_handler(ADDR, IP)
2371 > #define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P)
2372   #endif
2373  
2374   // SIGSEGV recovery supported ?
# Line 1480 | Line 2381 | static bool arm_skip_instruction(unsigne
2381   *  SIGSEGV global handler
2382   */
2383  
2384 + struct sigsegv_info_t {
2385 +        sigsegv_address_t addr;
2386 +        sigsegv_address_t pc;
2387 + #ifdef HAVE_MACH_EXCEPTIONS
2388 +        mach_port_t thread;
2389 +        bool has_exc_state;
2390 +        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
2391 +        mach_msg_type_number_t exc_state_count;
2392 +        bool has_thr_state;
2393 +        SIGSEGV_THREAD_STATE_TYPE thr_state;
2394 +        mach_msg_type_number_t thr_state_count;
2395 + #endif
2396 + };
2397 +
2398 + #ifdef HAVE_MACH_EXCEPTIONS
2399 + static void mach_get_exception_state(sigsegv_info_t *SIP)
2400 + {
2401 +        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
2402 +        kern_return_t krc = thread_get_state(SIP->thread,
2403 +                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
2404 +                                                                                 (natural_t *)&SIP->exc_state,
2405 +                                                                                 &SIP->exc_state_count);
2406 +        MACH_CHECK_ERROR(thread_get_state, krc);
2407 +        SIP->has_exc_state = true;
2408 + }
2409 +
2410 + static void mach_get_thread_state(sigsegv_info_t *SIP)
2411 + {
2412 +        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
2413 +        kern_return_t krc = thread_get_state(SIP->thread,
2414 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2415 +                                                                                 (natural_t *)&SIP->thr_state,
2416 +                                                                                 &SIP->thr_state_count);
2417 +        MACH_CHECK_ERROR(thread_get_state, krc);
2418 +        SIP->has_thr_state = true;
2419 + }
2420 +
2421 + static void mach_set_thread_state(sigsegv_info_t *SIP)
2422 + {
2423 +        kern_return_t krc = thread_set_state(SIP->thread,
2424 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
2425 +                                                                                 (natural_t *)&SIP->thr_state,
2426 +                                                                                 SIP->thr_state_count);
2427 +        MACH_CHECK_ERROR(thread_set_state, krc);
2428 + }
2429 + #endif
2430 +
2431 + // Return the address of the invalid memory reference
2432 + sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
2433 + {
2434 + #ifdef HAVE_MACH_EXCEPTIONS
2435 +        static int use_fast_path = -1;
2436 +        if (use_fast_path != 1 && !SIP->has_exc_state) {
2437 +                mach_get_exception_state(SIP);
2438 +
2439 +                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2440 +                if (use_fast_path < 0)
2441 +                        use_fast_path = addr == SIP->addr;
2442 +                SIP->addr = addr;
2443 +        }
2444 + #endif
2445 +        return SIP->addr;
2446 + }
2447 +
2448 + // Return the address of the instruction that caused the fault, or
2449 + // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
2450 + sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
2451 + {
2452 + #ifdef HAVE_MACH_EXCEPTIONS
2453 +        if (!SIP->has_thr_state) {
2454 +                mach_get_thread_state(SIP);
2455 +
2456 +                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2457 +        }
2458 + #endif
2459 +        return SIP->pc;
2460 + }
2461 +
2462   // This function handles the badaccess to memory.
2463   // It is called from the signal handler or the exception handler.
2464   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
2465   {
2466 <        sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
2467 <        sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
2468 <        
2466 >        sigsegv_info_t SI;
2467 >        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
2468 >        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
2469 > #ifdef HAVE_MACH_EXCEPTIONS
2470 >        SI.thread = thread;
2471 >        SI.has_exc_state = false;
2472 >        SI.has_thr_state = false;
2473 > #endif
2474 >        sigsegv_info_t * const SIP = &SI;
2475 >
2476          // Call user's handler and reinstall the global handler, if required
2477 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) {
2477 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
2478          case SIGSEGV_RETURN_SUCCESS:
2479                  return true;
2480  
# Line 1496 | Line 2482 | static bool handle_badaccess(SIGSEGV_FAU
2482          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
2483                  // Call the instruction skipper with the register file
2484                  // available
2485 + #ifdef HAVE_MACH_EXCEPTIONS
2486 +                if (!SIP->has_thr_state)
2487 +                        mach_get_thread_state(SIP);
2488 + #endif
2489                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
2490   #ifdef HAVE_MACH_EXCEPTIONS
2491                          // Unlike UNIX signals where the thread state
2492                          // is modified off of the stack, in Mach we
2493                          // need to actually call thread_set_state to
2494                          // have the register values updated.
2495 <                        kern_return_t krc;
1506 <
1507 <                        krc = thread_set_state(thread,
1508 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1509 <                                                                   MACHINE_THREAD_STATE_COUNT);
1510 <                        MACH_CHECK_ERROR (thread_get_state, krc);
2495 >                        mach_set_thread_state(SIP);
2496   #endif
2497                          return true;
2498                  }
2499                  break;
2500   #endif
2501          case SIGSEGV_RETURN_FAILURE:
2502 <                return false;
2502 >                // We can't do anything with the fault_address, dump state?
2503 >                if (sigsegv_state_dumper != 0)
2504 >                        sigsegv_state_dumper(SIP);
2505 >                break;
2506          }
1519        
1520        // We can't do anything with the fault_address, dump state?
1521        if (sigsegv_state_dumper != 0)
1522                sigsegv_state_dumper(fault_address, fault_instruction);
2507  
2508          return false;
2509   }
# Line 1559 | Line 2543 | forward_exception(mach_port_t thread_por
2543          mach_port_t port;
2544          exception_behavior_t behavior;
2545          thread_state_flavor_t flavor;
2546 <        thread_state_t thread_state;
2546 >        thread_state_data_t thread_state;
2547          mach_msg_type_number_t thread_state_count;
2548  
2549          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1578 | Line 2562 | forward_exception(mach_port_t thread_por
2562          behavior = oldExceptionPorts->behaviors[portIndex];
2563          flavor = oldExceptionPorts->flavors[portIndex];
2564  
2565 +        if (!VALID_THREAD_STATE_FLAVOR(flavor)) {
2566 +                fprintf(stderr, "Invalid thread_state flavor = %d. Not forwarding\n", flavor);
2567 +                return KERN_FAILURE;
2568 +        }
2569 +
2570          /*
2571           fprintf(stderr, "forwarding exception, port = 0x%x, behaviour = %d, flavor = %d\n", port, behavior, flavor);
2572           */
2573  
2574          if (behavior != EXCEPTION_DEFAULT) {
2575                  thread_state_count = THREAD_STATE_MAX;
2576 <                kret = thread_get_state (thread_port, flavor, thread_state,
2576 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
2577                                                                   &thread_state_count);
2578                  MACH_CHECK_ERROR (thread_get_state, kret);
2579          }
# Line 1600 | Line 2589 | forward_exception(mach_port_t thread_por
2589            // fprintf(stderr, "forwarding to exception_raise_state\n");
2590            kret = exception_raise_state(port, exception_type, exception_data,
2591                                                                     data_count, &flavor,
2592 <                                                                   thread_state, thread_state_count,
2593 <                                                                   thread_state, &thread_state_count);
2592 >                                                                   (natural_t *)&thread_state, thread_state_count,
2593 >                                                                   (natural_t *)&thread_state, &thread_state_count);
2594            MACH_CHECK_ERROR (exception_raise_state, kret);
2595            break;
2596          case EXCEPTION_STATE_IDENTITY:
# Line 1609 | Line 2598 | forward_exception(mach_port_t thread_por
2598            kret = exception_raise_state_identity(port, thread_port, task_port,
2599                                                                                          exception_type, exception_data,
2600                                                                                          data_count, &flavor,
2601 <                                                                                        thread_state, thread_state_count,
2602 <                                                                                        thread_state, &thread_state_count);
2601 >                                                                                        (natural_t *)&thread_state, thread_state_count,
2602 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
2603            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
2604            break;
2605          default:
2606            fprintf(stderr, "forward_exception got unknown behavior\n");
2607 +          kret = KERN_FAILURE;
2608            break;
2609          }
2610  
2611          if (behavior != EXCEPTION_DEFAULT) {
2612 <                kret = thread_set_state (thread_port, flavor, thread_state,
2612 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
2613                                                                   thread_state_count);
2614                  MACH_CHECK_ERROR (thread_set_state, kret);
2615          }
2616  
2617 <        return KERN_SUCCESS;
2617 >        return kret;
2618   }
2619  
2620   /*
# Line 1652 | Line 2642 | catch_exception_raise(mach_port_t except
2642                                            mach_port_t task,
2643                                            exception_type_t exception,
2644                                            exception_data_t code,
2645 <                                          mach_msg_type_number_t codeCount)
2645 >                                          mach_msg_type_number_t code_count)
2646   {
1657        ppc_thread_state_t state;
2647          kern_return_t krc;
2648  
2649 <        if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
2650 <                if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2651 <                        return KERN_SUCCESS;
2649 >        if (exception == EXC_BAD_ACCESS) {
2650 >                switch (code[0]) {
2651 >                case KERN_PROTECTION_FAILURE:
2652 >                case KERN_INVALID_ADDRESS:
2653 >                        if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
2654 >                                return KERN_SUCCESS;
2655 >                        break;
2656 >                }
2657          }
2658  
2659          // In Mach we do not need to remove the exception handler.
2660          // If we forward the exception, eventually some exception handler
2661          // will take care of this exception.
2662 <        krc = forward_exception(thread, task, exception, code, codeCount, &ports);
2662 >        krc = forward_exception(thread, task, exception, code, code_count, &ports);
2663  
2664          return krc;
2665   }
# Line 1793 | Line 2787 | static bool sigsegv_do_install_handler(s
2787          // addressing modes) used in PPC instructions, you will need the
2788          // GPR state anyway.
2789          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
2790 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
2790 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
2791          if (krc != KERN_SUCCESS) {
2792                  mach_error("thread_set_exception_ports", krc);
2793                  return false;
# Line 1977 | Line 2971 | static int page_size;
2971   static volatile char * page = 0;
2972   static volatile int handler_called = 0;
2973  
2974 + /* Barriers */
2975 + #ifdef __GNUC__
2976 + #define BARRIER() asm volatile ("" : : : "memory")
2977 + #else
2978 + #define BARRIER() /* nothing */
2979 + #endif
2980 +
2981   #ifdef __GNUC__
2982   // Code range where we expect the fault to come from
2983   static void *b_region, *e_region;
2984   #endif
2985  
2986 < static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
2986 > static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip)
2987   {
2988 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
2989 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
2990   #if DEBUG
2991          printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address);
2992          printf("expected fault at %p\n", page + REF_INDEX);
# Line 1997 | Line 3000 | static sigsegv_return_t sigsegv_test_han
3000   #ifdef __GNUC__
3001          // Make sure reported fault instruction address falls into
3002          // expected code range
3003 <        if (instruction_address != SIGSEGV_INVALID_PC
3003 >        if (instruction_address != SIGSEGV_INVALID_ADDRESS
3004                  && ((instruction_address <  (sigsegv_address_t)b_region) ||
3005                          (instruction_address >= (sigsegv_address_t)e_region)))
3006                  exit(11);
# Line 2008 | Line 3011 | static sigsegv_return_t sigsegv_test_han
3011   }
3012  
3013   #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
3014 < static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address)
3014 > static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip)
3015   {
3016 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
3017 +        const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip);
3018   #if DEBUG
3019          printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address);
3020   #endif
# Line 2017 | Line 3022 | static sigsegv_return_t sigsegv_insn_han
3022   #ifdef __GNUC__
3023                  // Make sure reported fault instruction address falls into
3024                  // expected code range
3025 <                if (instruction_address != SIGSEGV_INVALID_PC
3025 >                if (instruction_address != SIGSEGV_INVALID_ADDRESS
3026                          && ((instruction_address <  (sigsegv_address_t)b_region) ||
3027                                  (instruction_address >= (sigsegv_address_t)e_region)))
3028                          return SIGSEGV_RETURN_FAILURE;
# Line 2068 | Line 3073 | static bool arch_insn_skipper_tests()
3073                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
3074                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
3075                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
3076 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
3077 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
3078   #endif
3079                  0                              // end
3080          };
# Line 2091 | Line 3098 | int main(void)
3098          if (vm_init() < 0)
3099                  return 1;
3100  
3101 < #ifdef _WIN32
2095 <        page_size = 4096;
2096 < #else
2097 <        page_size = getpagesize();
2098 < #endif
3101 >        page_size = vm_get_page_size();
3102          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
3103                  return 2;
3104          
# Line 2105 | Line 3108 | int main(void)
3108          
3109          if (!sigsegv_install_handler(sigsegv_test_handler))
3110                  return 4;
3111 <        
3111 >
3112   #ifdef __GNUC__
3113          b_region = &&L_b_region1;
3114          e_region = &&L_e_region1;
3115   #endif
3116 < L_b_region1:
3117 <        page[REF_INDEX] = REF_VALUE;
3118 <        if (page[REF_INDEX] != REF_VALUE)
3119 <          exit(20);
3120 <        page[REF_INDEX] = REF_VALUE;
3121 < L_e_region1:
3116 >        /* This is a really awful hack but otherwise gcc is smart enough
3117 >         * (or bug'ous enough?) to optimize the labels and place them
3118 >         * e.g. at the "main" entry point, which is wrong.
3119 >         */
3120 >        volatile int label_hack = 1;
3121 >        switch (label_hack) {
3122 >        case 1:
3123 >        L_b_region1:
3124 >                page[REF_INDEX] = REF_VALUE;
3125 >                if (page[REF_INDEX] != REF_VALUE)
3126 >                        exit(20);
3127 >                page[REF_INDEX] = REF_VALUE;
3128 >                BARRIER();
3129 >                // fall-through
3130 >        case 2:
3131 >        L_e_region1:
3132 >                BARRIER();
3133 >                break;
3134 >        }
3135  
3136          if (handler_called != 1)
3137                  return 5;
# Line 2146 | Line 3162 | int main(void)
3162          b_region = &&L_b_region2;
3163          e_region = &&L_e_region2;
3164   #endif
3165 < L_b_region2:
3166 <        TEST_SKIP_INSTRUCTION(unsigned char);
3167 <        TEST_SKIP_INSTRUCTION(unsigned short);
3168 <        TEST_SKIP_INSTRUCTION(unsigned int);
3169 <        TEST_SKIP_INSTRUCTION(unsigned long);
3170 <        TEST_SKIP_INSTRUCTION(signed char);
3171 <        TEST_SKIP_INSTRUCTION(signed short);
3172 <        TEST_SKIP_INSTRUCTION(signed int);
3173 <        TEST_SKIP_INSTRUCTION(signed long);
3174 < L_e_region2:
3175 <
3165 >        switch (label_hack) {
3166 >        case 1:
3167 >        L_b_region2:
3168 >                TEST_SKIP_INSTRUCTION(unsigned char);
3169 >                TEST_SKIP_INSTRUCTION(unsigned short);
3170 >                TEST_SKIP_INSTRUCTION(unsigned int);
3171 >                TEST_SKIP_INSTRUCTION(unsigned long);
3172 >                TEST_SKIP_INSTRUCTION(signed char);
3173 >                TEST_SKIP_INSTRUCTION(signed short);
3174 >                TEST_SKIP_INSTRUCTION(signed int);
3175 >                TEST_SKIP_INSTRUCTION(signed long);
3176 >                BARRIER();
3177 >                // fall-through
3178 >        case 2:
3179 >        L_e_region2:
3180 >                BARRIER();
3181 >                break;
3182 >        }
3183          if (!arch_insn_skipper_tests())
3184                  return 20;
3185   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines