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.53 by gbeauche, 2005-02-20T11:39:12Z vs.
Revision 1.62 by gbeauche, 2006-03-30T22:45:49Z

# Line 256 | Line 256 | static void powerpc_decode_instruction(i
256   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW
257   #define SIGSEGV_SKIP_INSTRUCTION                sparc_skip_instruction
258   #endif
259 + #if defined(__i386__)
260 + #include <sys/regset.h>
261 + #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
262 + #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_CONTEXT_REGS[EIP]
263 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)SIGSEGV_CONTEXT_REGS
264 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
265   #endif
266 < #if defined(__FreeBSD__)
266 > #endif
267 > #if defined(__FreeBSD__) || defined(__OpenBSD__)
268   #if (defined(i386) || defined(__i386__))
269   #define SIGSEGV_FAULT_INSTRUCTION               (((struct sigcontext *)scp)->sc_eip)
270   #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */
# Line 583 | Line 590 | if (ret != KERN_SUCCESS) { \
590          exit (1); \
591   }
592  
593 + #ifdef __ppc__
594 + #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
595 + #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
596 + #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
597 + #define SIGSEGV_FAULT_INSTRUCTION               state->srr0
598 + #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
599 + #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&state->srr0, (unsigned long *)&state->r0
600 + #endif
601 + #ifdef __i386__
602 + #ifdef i386_SAVED_STATE
603 + #define SIGSEGV_THREAD_STATE_TYPE               struct i386_saved_state
604 + #define SIGSEGV_THREAD_STATE_FLAVOR             i386_SAVED_STATE
605 + #define SIGSEGV_THREAD_STATE_COUNT              i386_SAVED_STATE_COUNT
606 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state->edi) /* EDI is the first GPR we consider */
607 + #else
608 + #define SIGSEGV_THREAD_STATE_TYPE               struct i386_thread_state
609 + #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
610 + #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
611 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state->eax) /* EAX is the first GPR we consider */
612 + #endif
613 + #define SIGSEGV_FAULT_INSTRUCTION               state->eip
614 + #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
615 + #endif
616   #define SIGSEGV_FAULT_ADDRESS                   code[1]
587 #define SIGSEGV_FAULT_INSTRUCTION               get_fault_instruction(thread, state)
617   #define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP)  ((code[0] == KERN_PROTECTION_FAILURE) ? sigsegv_fault_handler(ADDR, IP) : SIGSEGV_RETURN_FAILURE)
618 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, ppc_thread_state_t *state
618 > #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code, SIGSEGV_THREAD_STATE_TYPE *state
619   #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code, &state
591 #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
592 #define SIGSEGV_REGISTER_FILE                   &state->srr0, &state->r0
593
594 // Given a suspended thread, stuff the current instruction and
595 // registers into state.
596 //
597 // It would have been nice to have this be ppc/x86 independant which
598 // could have been done easily with a thread_state_t instead of
599 // ppc_thread_state_t, but because of the way this is called it is
600 // easier to do it this way.
601 #if (defined(ppc) || defined(__ppc__))
602 static inline sigsegv_address_t get_fault_instruction(mach_port_t thread, ppc_thread_state_t *state)
603 {
604        kern_return_t krc;
605        mach_msg_type_number_t count;
606
607        count = MACHINE_THREAD_STATE_COUNT;
608        krc = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)state, &count);
609        MACH_CHECK_ERROR (thread_get_state, krc);
610
611        return (sigsegv_address_t)state->srr0;
612 }
613 #endif
620  
621   // Since there can only be one exception thread running at any time
622   // this is not a problem.
# Line 730 | Line 736 | enum {
736   #endif
737   };
738   #endif
739 + #if defined(__OpenBSD__)
740 + enum {
741 + #if defined(__i386__)
742 +        // EDI is the first register we consider
743 + #define OREG(REG) offsetof(struct sigcontext, sc_##REG)
744 + #define DREG(REG) ((OREG(REG) - OREG(edi)) / 4)
745 +        X86_REG_EIP = DREG(eip), // 7
746 +        X86_REG_EAX = DREG(eax), // 6
747 +        X86_REG_ECX = DREG(ecx), // 5
748 +        X86_REG_EDX = DREG(edx), // 4
749 +        X86_REG_EBX = DREG(ebx), // 3
750 +        X86_REG_ESP = DREG(esp), // 10
751 +        X86_REG_EBP = DREG(ebp), // 2
752 +        X86_REG_ESI = DREG(esi), // 1
753 +        X86_REG_EDI = DREG(edi)  // 0
754 + #undef DREG
755 + #undef OREG
756 + #endif
757 + };
758 + #endif
759 + #if defined(__sun__)
760 + // Same as for Linux, need to check for x86-64
761 + enum {
762 + #if defined(__i386__)
763 +        X86_REG_EIP = EIP,
764 +        X86_REG_EAX = EAX,
765 +        X86_REG_ECX = ECX,
766 +        X86_REG_EDX = EDX,
767 +        X86_REG_EBX = EBX,
768 +        X86_REG_ESP = ESP,
769 +        X86_REG_EBP = EBP,
770 +        X86_REG_ESI = ESI,
771 +        X86_REG_EDI = EDI
772 + #endif
773 + };
774 + #endif
775 + #if defined(__APPLE__) && defined(__MACH__)
776 + enum {
777 + #ifdef i386_SAVED_STATE
778 +        // same as FreeBSD (in Open Darwin 8.0.1)
779 +        X86_REG_EIP = 10,
780 +        X86_REG_EAX = 7,
781 +        X86_REG_ECX = 6,
782 +        X86_REG_EDX = 5,
783 +        X86_REG_EBX = 4,
784 +        X86_REG_ESP = 13,
785 +        X86_REG_EBP = 2,
786 +        X86_REG_ESI = 1,
787 +        X86_REG_EDI = 0
788 + #else
789 +        // new layout (MacOS X 10.4.4 for x86)
790 +        X86_REG_EIP = 10,
791 +        X86_REG_EAX = 0,
792 +        X86_REG_ECX = 2,
793 +        X86_REG_EDX = 4,
794 +        X86_REG_EBX = 1,
795 +        X86_REG_ESP = 7,
796 +        X86_REG_EBP = 6,
797 +        X86_REG_ESI = 5,
798 +        X86_REG_EDI = 4
799 + #endif
800 + };
801 + #endif
802   #if defined(_WIN32)
803   enum {
804   #if (defined(i386) || defined(__i386__))
# Line 874 | Line 943 | static bool ix86_skip_instruction(unsign
943                          break;
944              }
945            break;
946 + #if defined(__x86_64__)
947 +        case 0x63: // MOVSXD r64, r/m32
948 +                if (has_rex && rex.W) {
949 +                        transfer_size = SIZE_LONG;
950 +                        target_size = SIZE_QUAD;
951 +                }
952 +                else if (transfer_size != SIZE_WORD) {
953 +                        transfer_size = SIZE_LONG;
954 +                        target_size = SIZE_QUAD;
955 +                }
956 +                switch (eip[1] & 0xc0) {
957 +                case 0x80:
958 +                        reg = (eip[1] >> 3) & 7;
959 +                        transfer_type = SIGSEGV_TRANSFER_LOAD;
960 +                        break;
961 +                case 0x40:
962 +                        reg = (eip[1] >> 3) & 7;
963 +                        transfer_type = SIGSEGV_TRANSFER_LOAD;
964 +                        break;
965 +                case 0x00:
966 +                        reg = (eip[1] >> 3) & 7;
967 +                        transfer_type = SIGSEGV_TRANSFER_LOAD;
968 +                        break;
969 +                }
970 +                len += 2 + ix86_step_over_modrm(eip + 1);
971 +                break;
972 + #endif
973          case 0x8a: // MOV r8, r/m8
974                  transfer_size = SIZE_BYTE;
975          case 0x8b: // MOV r32, r/m32 (or 16-bit operation)
# Line 1222 | Line 1318 | enum {
1318    SPARC_REG_G1 = REG_G1,
1319    SPARC_REG_O0 = REG_O0,
1320    SPARC_REG_PC = REG_PC,
1321 +  SPARC_REG_nPC = REG_nPC
1322   #endif
1323   };
1324   static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin)
# Line 1285 | Line 1382 | static bool sparc_skip_instruction(unsig
1382          break;
1383    case 7: // Store Doubleword
1384          transfer_type = SIGSEGV_TRANSFER_STORE;
1385 <        transfer_size = SIZE_WORD;
1385 >        transfer_size = SIZE_LONG;
1386          register_pair = true;
1387          break;
1388    }
# Line 1295 | Line 1392 | static bool sparc_skip_instruction(unsig
1392          return false;
1393    }
1394  
1298  // Zero target register in case of a load operation
1395    const int reg = (opcode >> 25) & 0x1f;
1396 +
1397 + #if DEBUG
1398 +  static const char * reg_names[] = {
1399 +        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1400 +        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1401 +        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1402 +        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1403 +  };
1404 +  printf("%s %s register %s\n",
1405 +                 transfer_size == SIZE_BYTE ? "byte" :
1406 +                 transfer_size == SIZE_WORD ? "word" :
1407 +                 transfer_size == SIZE_LONG ? "long" :
1408 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1409 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1410 +                 reg_names[reg]);
1411 + #endif
1412 +
1413 +  // Zero target register in case of a load operation
1414    if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) {
1415          // FIXME: code to handle local & input registers is not tested
1416 <        if (reg >= 1 && reg <= 7) {
1416 >        if (reg >= 1 && reg < 8) {
1417            // global registers
1418            regs[reg - 1 + SPARC_REG_G1] = 0;
1419          }
1420 <        else if (reg >= 8 && reg <= 15) {
1420 >        else if (reg >= 8 && reg < 16) {
1421            // output registers
1422            regs[reg - 8 + SPARC_REG_O0] = 0;
1423          }
1424 <        else if (reg >= 16 && reg <= 23) {
1424 >        else if (reg >= 16 && reg < 24) {
1425            // local registers (in register windows)
1426            if (gwins)
1427                  gwins->wbuf->rw_local[reg - 16] = 0;
# Line 1323 | Line 1437 | static bool sparc_skip_instruction(unsig
1437          }
1438    }
1439  
1326 #if DEBUG
1327  static const char * reg_names[] = {
1328        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
1329        "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
1330        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
1331        "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
1332  };
1333  printf("%s %s register %s\n",
1334                 transfer_size == SIZE_BYTE ? "byte" :
1335                 transfer_size == SIZE_WORD ? "word" :
1336                 transfer_size == SIZE_LONG ? "long" :
1337                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1338                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1339                 reg_names[reg]);
1340 #endif
1341
1440    regs[SPARC_REG_PC] += 4;
1441 +  regs[SPARC_REG_nPC] += 4;
1442    return true;
1443   }
1444   #endif
# Line 1519 | Line 1618 | static bool arm_skip_instruction(unsigne
1618   // It is called from the signal handler or the exception handler.
1619   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
1620   {
1621 + #ifdef HAVE_MACH_EXCEPTIONS
1622 +        // We must match the initial count when writing back the CPU state registers
1623 +        kern_return_t krc;
1624 +        mach_msg_type_number_t count;
1625 +
1626 +        count = SIGSEGV_THREAD_STATE_COUNT;
1627 +        krc = thread_get_state(thread, SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)state, &count);
1628 +        MACH_CHECK_ERROR (thread_get_state, krc);
1629 + #endif
1630 +
1631          sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1632          sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1633          
# Line 1537 | Line 1646 | static bool handle_badaccess(SIGSEGV_FAU
1646                          // is modified off of the stack, in Mach we
1647                          // need to actually call thread_set_state to
1648                          // have the register values updated.
1540                        kern_return_t krc;
1541
1649                          krc = thread_set_state(thread,
1650 <                                                                   MACHINE_THREAD_STATE, (thread_state_t)state,
1651 <                                                                   MACHINE_THREAD_STATE_COUNT);
1652 <                        MACH_CHECK_ERROR (thread_get_state, krc);
1650 >                                                                   SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)state,
1651 >                                                                   count);
1652 >                        MACH_CHECK_ERROR (thread_set_state, krc);
1653   #endif
1654                          return true;
1655                  }
# Line 1593 | Line 1700 | forward_exception(mach_port_t thread_por
1700          mach_port_t port;
1701          exception_behavior_t behavior;
1702          thread_state_flavor_t flavor;
1703 <        thread_state_t thread_state;
1703 >        thread_state_data_t thread_state;
1704          mach_msg_type_number_t thread_state_count;
1705  
1706          for (portIndex = 0; portIndex < oldExceptionPorts->maskCount; portIndex++) {
# Line 1618 | Line 1725 | forward_exception(mach_port_t thread_por
1725  
1726          if (behavior != EXCEPTION_DEFAULT) {
1727                  thread_state_count = THREAD_STATE_MAX;
1728 <                kret = thread_get_state (thread_port, flavor, thread_state,
1728 >                kret = thread_get_state (thread_port, flavor, (natural_t *)&thread_state,
1729                                                                   &thread_state_count);
1730                  MACH_CHECK_ERROR (thread_get_state, kret);
1731          }
# Line 1634 | Line 1741 | forward_exception(mach_port_t thread_por
1741            // fprintf(stderr, "forwarding to exception_raise_state\n");
1742            kret = exception_raise_state(port, exception_type, exception_data,
1743                                                                     data_count, &flavor,
1744 <                                                                   thread_state, thread_state_count,
1745 <                                                                   thread_state, &thread_state_count);
1744 >                                                                   (natural_t *)&thread_state, thread_state_count,
1745 >                                                                   (natural_t *)&thread_state, &thread_state_count);
1746            MACH_CHECK_ERROR (exception_raise_state, kret);
1747            break;
1748          case EXCEPTION_STATE_IDENTITY:
# Line 1643 | Line 1750 | forward_exception(mach_port_t thread_por
1750            kret = exception_raise_state_identity(port, thread_port, task_port,
1751                                                                                          exception_type, exception_data,
1752                                                                                          data_count, &flavor,
1753 <                                                                                        thread_state, thread_state_count,
1754 <                                                                                        thread_state, &thread_state_count);
1753 >                                                                                        (natural_t *)&thread_state, thread_state_count,
1754 >                                                                                        (natural_t *)&thread_state, &thread_state_count);
1755            MACH_CHECK_ERROR (exception_raise_state_identity, kret);
1756            break;
1757          default:
# Line 1653 | Line 1760 | forward_exception(mach_port_t thread_por
1760          }
1761  
1762          if (behavior != EXCEPTION_DEFAULT) {
1763 <                kret = thread_set_state (thread_port, flavor, thread_state,
1763 >                kret = thread_set_state (thread_port, flavor, (natural_t *)&thread_state,
1764                                                                   thread_state_count);
1765                  MACH_CHECK_ERROR (thread_set_state, kret);
1766          }
# Line 1688 | Line 1795 | catch_exception_raise(mach_port_t except
1795                                            exception_data_t code,
1796                                            mach_msg_type_number_t codeCount)
1797   {
1798 <        ppc_thread_state_t state;
1798 >        SIGSEGV_THREAD_STATE_TYPE state;
1799          kern_return_t krc;
1800  
1801          if ((exception == EXC_BAD_ACCESS)  && (codeCount >= 2)) {
# Line 1827 | Line 1934 | static bool sigsegv_do_install_handler(s
1934          // addressing modes) used in PPC instructions, you will need the
1935          // GPR state anyway.
1936          krc = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, _exceptionPort,
1937 <                                EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
1937 >                                EXCEPTION_DEFAULT, SIGSEGV_THREAD_STATE_FLAVOR);
1938          if (krc != KERN_SUCCESS) {
1939                  mach_error("thread_set_exception_ports", krc);
1940                  return false;
# Line 2011 | Line 2118 | static int page_size;
2118   static volatile char * page = 0;
2119   static volatile int handler_called = 0;
2120  
2121 + /* Barriers */
2122 + #ifdef __GNUC__
2123 + #define BARRIER() asm volatile ("" : : : "memory")
2124 + #else
2125 + #define BARRIER() /* nothing */
2126 + #endif
2127 +
2128   #ifdef __GNUC__
2129   // Code range where we expect the fault to come from
2130   static void *b_region, *e_region;
# Line 2102 | Line 2216 | static bool arch_insn_skipper_tests()
2216                  0x4c, 0x89, 0x18,              // mov    %r11,(%rax)
2217                  0x4a, 0x89, 0x0c, 0x10,        // mov    %rcx,(%rax,%r10,1)
2218                  0x4e, 0x89, 0x1c, 0x10,        // mov    %r11,(%rax,%r10,1)
2219 +                0x63, 0x47, 0x04,              // movslq 4(%rdi),%eax
2220 +                0x48, 0x63, 0x47, 0x04,        // movslq 4(%rdi),%rax
2221   #endif
2222                  0                              // end
2223          };
# Line 2125 | Line 2241 | int main(void)
2241          if (vm_init() < 0)
2242                  return 1;
2243  
2244 < #ifdef _WIN32
2129 <        page_size = 4096;
2130 < #else
2131 <        page_size = getpagesize();
2132 < #endif
2244 >        page_size = vm_get_page_size();
2245          if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
2246                  return 2;
2247          
# Line 2149 | Line 2261 | int main(void)
2261          if (page[REF_INDEX] != REF_VALUE)
2262            exit(20);
2263          page[REF_INDEX] = REF_VALUE;
2264 +        BARRIER();
2265   L_e_region1:
2266  
2267          if (handler_called != 1)
# Line 2189 | Line 2302 | int main(void)
2302          TEST_SKIP_INSTRUCTION(signed short);
2303          TEST_SKIP_INSTRUCTION(signed int);
2304          TEST_SKIP_INSTRUCTION(signed long);
2305 +        BARRIER();
2306   L_e_region2:
2307  
2308          if (!arch_insn_skipper_tests())

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines