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.67 by gbeauche, 2007-12-30T08:45:18Z vs.
Revision 1.68 by gbeauche, 2007-12-30T12:11:17Z

# Line 605 | Line 605 | if (ret != KERN_SUCCESS) { \
605   #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state_t
606   #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE
607   #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE_COUNT
608 < #define SIGSEGV_FAULT_ADDRESS                   exc_state->dar
608 > #define SIGSEGV_FAULT_ADDRESS                   sip->exc_state.dar
609   #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state_t
610   #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE
611   #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE_COUNT
612 < #define SIGSEGV_FAULT_INSTRUCTION               state.srr0
612 > #define SIGSEGV_FAULT_INSTRUCTION               sip->thr_state.srr0
613   #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
614 < #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&state.srr0, (unsigned long *)&state.r0
614 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&sip->thr_state.srr0, (unsigned long *)&sip->thr_state.r0
615   #endif
616   #ifdef __i386__
617 #ifdef i386_SAVED_STATE
618 #define SIGSEGV_THREAD_STATE_TYPE               struct i386_saved_state
619 #define SIGSEGV_THREAD_STATE_FLAVOR             i386_SAVED_STATE
620 #define SIGSEGV_THREAD_STATE_COUNT              i386_SAVED_STATE_COUNT
621 #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state.edi) /* EDI is the first GPR we consider */
622 #else
617   #define SIGSEGV_EXCEPTION_STATE_TYPE    struct i386_exception_state
618   #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
619   #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_COUNT
620 < #define SIGSEGV_FAULT_ADDRESS                   exc_state->faultvaddr
620 > #define SIGSEGV_FAULT_ADDRESS                   sip->exc_state.faultvaddr
621   #define SIGSEGV_THREAD_STATE_TYPE               struct i386_thread_state
622   #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
623   #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
624 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state.eax) /* EAX is the first GPR we consider */
631 < #endif
632 < #define SIGSEGV_FAULT_INSTRUCTION               state.eip
624 > #define SIGSEGV_FAULT_INSTRUCTION               sip->thr_state.eip
625   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
626 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&sip->thr_state.eax) /* EAX is the first GPR we consider */
627   #endif
628   #ifdef __x86_64__
629   #define SIGSEGV_EXCEPTION_STATE_TYPE    struct x86_exception_state64
630   #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
631   #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
632 < #define SIGSEGV_FAULT_ADDRESS                   exc_state->faultvaddr
632 > #define SIGSEGV_FAULT_ADDRESS                   sip->exc_state.faultvaddr
633   #define SIGSEGV_THREAD_STATE_TYPE               struct x86_thread_state64
634   #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
635   #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
636 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state.rax) /* RAX is the first GPR we consider */
644 < #define SIGSEGV_FAULT_INSTRUCTION               state.rip
636 > #define SIGSEGV_FAULT_INSTRUCTION               sip->thr_state.rip
637   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
638 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&sip->thr_state.rax) /* RAX is the first GPR we consider */
639   #endif
640 < #ifdef SIGSEGV_EXCEPTION_STATE_TYPE
641 < #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, SIGSEGV_EXCEPTION_STATE_TYPE *exc_state
649 < #define SIGSEGV_FAULT_HANDLER_ARGS              thread, &exc_state
650 < #else
651 < #define SIGSEGV_FAULT_ADDRESS                   code[1]
640 > #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
641 > #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
642   #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
643   #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
654 #endif
644  
645   // Since there can only be one exception thread running at any time
646   // this is not a problem.
# Line 1635 | Line 1624 | static bool arm_skip_instruction(unsigne
1624  
1625  
1626   // Fallbacks
1627 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
1628 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
1629 + #endif
1630 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
1631 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
1632 + #endif
1633   #ifndef SIGSEGV_FAULT_INSTRUCTION
1634   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
1635   #endif
# Line 1658 | Line 1653 | static bool arm_skip_instruction(unsigne
1653   struct sigsegv_info_t {
1654          sigsegv_address_t addr;
1655          sigsegv_address_t pc;
1656 + #ifdef HAVE_MACH_EXCEPTIONS
1657 +        mach_port_t thread;
1658 +        bool has_exc_state;
1659 +        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
1660 +        mach_msg_type_number_t exc_state_count;
1661 +        bool has_thr_state;
1662 +        SIGSEGV_THREAD_STATE_TYPE thr_state;
1663 +        mach_msg_type_number_t thr_state_count;
1664 + #endif
1665   };
1666  
1667   // Return the address of the invalid memory reference
1668   sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip)
1669   {
1670 + #ifdef HAVE_MACH_EXCEPTIONS
1671 +        static int use_fast_path = -1;
1672 +        if (use_fast_path != 1 && !sip->has_exc_state) {
1673 +                sip->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
1674 +                kern_return_t krc = thread_get_state(sip->thread,
1675 +                                                                                         SIGSEGV_EXCEPTION_STATE_FLAVOR,
1676 +                                                                                         (natural_t *)&sip->exc_state,
1677 +                                                                                         &sip->exc_state_count);
1678 +                MACH_CHECK_ERROR(thread_get_state, krc);
1679 +                sip->has_exc_state = true;
1680 +
1681 +                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1682 +                if (use_fast_path < 0)
1683 +                        use_fast_path = addr == sip->addr;
1684 +                sip->addr = addr;
1685 +        }
1686 + #endif
1687          return sip->addr;
1688   }
1689  
# Line 1670 | Line 1691 | sigsegv_address_t sigsegv_get_fault_addr
1691   // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
1692   sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *sip)
1693   {
1694 + #ifdef HAVE_MACH_EXCEPTIONS
1695 +        if (!sip->has_thr_state) {
1696 +                sip->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
1697 +                kern_return_t krc = thread_get_state(sip->thread,
1698 +                                                                                         SIGSEGV_THREAD_STATE_FLAVOR,
1699 +                                                                                         (natural_t *)&sip->thr_state,
1700 +                                                                                         &sip->thr_state_count);
1701 +                MACH_CHECK_ERROR(thread_get_state, krc);
1702 +                sip->has_thr_state = true;
1703 +
1704 +                sip->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1705 +        }
1706 + #endif
1707          return sip->pc;
1708   }
1709  
# Line 1677 | Line 1711 | sigsegv_address_t sigsegv_get_fault_inst
1711   // It is called from the signal handler or the exception handler.
1712   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
1713   {
1714 +        sigsegv_info_t si;
1715 +        si.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
1716 +        si.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
1717   #ifdef HAVE_MACH_EXCEPTIONS
1718 <        // We must match the initial count when writing back the CPU state registers
1719 <        kern_return_t krc;
1720 <        mach_msg_type_number_t count;
1684 <        SIGSEGV_THREAD_STATE_TYPE state;
1685 <
1686 <        count = SIGSEGV_THREAD_STATE_COUNT;
1687 <        krc = thread_get_state(thread, SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)&state, &count);
1688 <        MACH_CHECK_ERROR (thread_get_state, krc);
1718 >        si.thread = thread;
1719 >        si.has_exc_state = false;
1720 >        si.has_thr_state = false;
1721   #endif
1722 +        sigsegv_info_t * const sip = &si;
1723  
1691        sigsegv_info_t si;
1692        si.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1693        si.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1694        
1724          // Call user's handler and reinstall the global handler, if required
1725 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(&si)) {
1725 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(sip)) {
1726          case SIGSEGV_RETURN_SUCCESS:
1727                  return true;
1728  
# Line 1707 | Line 1736 | static bool handle_badaccess(SIGSEGV_FAU
1736                          // is modified off of the stack, in Mach we
1737                          // need to actually call thread_set_state to
1738                          // have the register values updated.
1739 <                        krc = thread_set_state(thread,
1740 <                                                                   SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)&state,
1741 <                                                                   count);
1742 <                        MACH_CHECK_ERROR (thread_set_state, krc);
1739 >                        kern_return_t krc = thread_set_state(sip->thread,
1740 >                                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
1741 >                                                                                                 (natural_t *)&sip->thr_state,
1742 >                                                                                                 sip->thr_state_count);
1743 >                        MACH_CHECK_ERROR(thread_set_state, krc);
1744   #endif
1745                          return true;
1746                  }
# Line 1719 | Line 1749 | static bool handle_badaccess(SIGSEGV_FAU
1749          case SIGSEGV_RETURN_FAILURE:
1750                  // We can't do anything with the fault_address, dump state?
1751                  if (sigsegv_state_dumper != 0)
1752 <                        sigsegv_state_dumper(&si);
1752 >                        sigsegv_state_dumper(sip);
1753                  break;
1754          }
1755  
# Line 1868 | Line 1898 | catch_exception_raise(mach_port_t except
1898                  switch (code[0]) {
1899                  case KERN_PROTECTION_FAILURE:
1900                  case KERN_INVALID_ADDRESS:
1871                {
1872 #ifdef SIGSEGV_EXCEPTION_STATE_TYPE
1873                        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
1874                        mach_msg_type_number_t exc_state_count;
1875                        exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
1876                        krc = thread_get_state(thread, SIGSEGV_EXCEPTION_STATE_FLAVOR, (natural_t *)&exc_state, &exc_state_count);
1877                        MACH_CHECK_ERROR (thread_get_state, krc);
1878 #endif
1879
1901                          if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
1902                                  return KERN_SUCCESS;
1903                          break;
1904                  }
1884                }
1905          }
1906  
1907          // In Mach we do not need to remove the exception handler.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines