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.73 by gbeauche, 2008-01-06T16:10:30Z

# 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-2005 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 70 | Line 70 | static bool sigsegv_do_install_handler(i
70   enum transfer_type_t {
71          SIGSEGV_TRANSFER_UNKNOWN        = 0,
72          SIGSEGV_TRANSFER_LOAD           = 1,
73 <        SIGSEGV_TRANSFER_STORE          = 2,
73 >        SIGSEGV_TRANSFER_STORE          = 2
74   };
75  
76   // Transfer size
# Line 79 | Line 79 | enum transfer_size_t {
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 < #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 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 __ppc64__
617 > #define SIGSEGV_EXCEPTION_STATE_TYPE    ppc_exception_state64_t
618 > #define SIGSEGV_EXCEPTION_STATE_FLAVOR  PPC_EXCEPTION_STATE64
619 > #define SIGSEGV_EXCEPTION_STATE_COUNT   PPC_EXCEPTION_STATE64_COUNT
620 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.dar
621 > #define SIGSEGV_THREAD_STATE_TYPE               ppc_thread_state64_t
622 > #define SIGSEGV_THREAD_STATE_FLAVOR             PPC_THREAD_STATE64
623 > #define SIGSEGV_THREAD_STATE_COUNT              PPC_THREAD_STATE64_COUNT
624 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.srr0
625 > #define SIGSEGV_SKIP_INSTRUCTION                powerpc_skip_instruction
626 > #define SIGSEGV_REGISTER_FILE                   (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0
627   #endif
628   #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
629   #define SIGSEGV_EXCEPTION_STATE_TYPE    struct i386_exception_state
630   #define SIGSEGV_EXCEPTION_STATE_FLAVOR  i386_EXCEPTION_STATE
631   #define SIGSEGV_EXCEPTION_STATE_COUNT   i386_EXCEPTION_STATE_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 i386_thread_state
634   #define SIGSEGV_THREAD_STATE_FLAVOR             i386_THREAD_STATE
635   #define SIGSEGV_THREAD_STATE_COUNT              i386_THREAD_STATE_COUNT
636 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state.eax) /* EAX is the first GPR we consider */
631 < #endif
632 < #define SIGSEGV_FAULT_INSTRUCTION               state.eip
636 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.eip
637   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
638 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIP->thr_state.eax) /* EAX is the first GPR we consider */
639   #endif
640   #ifdef __x86_64__
641   #define SIGSEGV_EXCEPTION_STATE_TYPE    struct x86_exception_state64
642   #define SIGSEGV_EXCEPTION_STATE_FLAVOR  x86_EXCEPTION_STATE64
643   #define SIGSEGV_EXCEPTION_STATE_COUNT   x86_EXCEPTION_STATE64_COUNT
644 < #define SIGSEGV_FAULT_ADDRESS                   exc_state->faultvaddr
644 > #define SIGSEGV_FAULT_ADDRESS                   SIP->exc_state.faultvaddr
645   #define SIGSEGV_THREAD_STATE_TYPE               struct x86_thread_state64
646   #define SIGSEGV_THREAD_STATE_FLAVOR             x86_THREAD_STATE64
647   #define SIGSEGV_THREAD_STATE_COUNT              x86_THREAD_STATE64_COUNT
648 < #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&state.rax) /* RAX is the first GPR we consider */
644 < #define SIGSEGV_FAULT_INSTRUCTION               state.rip
648 > #define SIGSEGV_FAULT_INSTRUCTION               SIP->thr_state.rip
649   #define SIGSEGV_SKIP_INSTRUCTION                ix86_skip_instruction
650 + #define SIGSEGV_REGISTER_FILE                   ((unsigned long *)&SIP->thr_state.rax) /* RAX is the first GPR we consider */
651   #endif
652 < #ifdef SIGSEGV_EXCEPTION_STATE_TYPE
653 < #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]
652 > #define SIGSEGV_FAULT_ADDRESS_FAST              code[1]
653 > #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_INVALID_ADDRESS
654   #define SIGSEGV_FAULT_HANDLER_ARGLIST   mach_port_t thread, exception_data_t code
655   #define SIGSEGV_FAULT_HANDLER_ARGS              thread, code
654 #endif
656  
657   // Since there can only be one exception thread running at any time
658   // this is not a problem.
# Line 1160 | Line 1161 | static bool ix86_skip_instruction(unsign
1161   #endif
1162  
1163   // Decode and skip PPC instruction
1164 < #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__))
1164 > #if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__))
1165   static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs)
1166   {
1167          instruction_t instr;
# Line 1635 | Line 1636 | static bool arm_skip_instruction(unsigne
1636  
1637  
1638   // Fallbacks
1639 + #ifndef SIGSEGV_FAULT_ADDRESS_FAST
1640 + #define SIGSEGV_FAULT_ADDRESS_FAST              SIGSEGV_FAULT_ADDRESS
1641 + #endif
1642 + #ifndef SIGSEGV_FAULT_INSTRUCTION_FAST
1643 + #define SIGSEGV_FAULT_INSTRUCTION_FAST  SIGSEGV_FAULT_INSTRUCTION
1644 + #endif
1645   #ifndef SIGSEGV_FAULT_INSTRUCTION
1646   #define SIGSEGV_FAULT_INSTRUCTION               SIGSEGV_INVALID_ADDRESS
1647   #endif
# Line 1658 | Line 1665 | static bool arm_skip_instruction(unsigne
1665   struct sigsegv_info_t {
1666          sigsegv_address_t addr;
1667          sigsegv_address_t pc;
1668 + #ifdef HAVE_MACH_EXCEPTIONS
1669 +        mach_port_t thread;
1670 +        bool has_exc_state;
1671 +        SIGSEGV_EXCEPTION_STATE_TYPE exc_state;
1672 +        mach_msg_type_number_t exc_state_count;
1673 +        bool has_thr_state;
1674 +        SIGSEGV_THREAD_STATE_TYPE thr_state;
1675 +        mach_msg_type_number_t thr_state_count;
1676 + #endif
1677   };
1678  
1679 + #ifdef HAVE_MACH_EXCEPTIONS
1680 + static void mach_get_exception_state(sigsegv_info_t *SIP)
1681 + {
1682 +        SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
1683 +        kern_return_t krc = thread_get_state(SIP->thread,
1684 +                                                                                 SIGSEGV_EXCEPTION_STATE_FLAVOR,
1685 +                                                                                 (natural_t *)&SIP->exc_state,
1686 +                                                                                 &SIP->exc_state_count);
1687 +        MACH_CHECK_ERROR(thread_get_state, krc);
1688 +        SIP->has_exc_state = true;
1689 + }
1690 +
1691 + static void mach_get_thread_state(sigsegv_info_t *SIP)
1692 + {
1693 +        SIP->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
1694 +        kern_return_t krc = thread_get_state(SIP->thread,
1695 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
1696 +                                                                                 (natural_t *)&SIP->thr_state,
1697 +                                                                                 &SIP->thr_state_count);
1698 +        MACH_CHECK_ERROR(thread_get_state, krc);
1699 +        SIP->has_thr_state = true;
1700 + }
1701 +
1702 + static void mach_set_thread_state(sigsegv_info_t *SIP)
1703 + {
1704 +        kern_return_t krc = thread_set_state(SIP->thread,
1705 +                                                                                 SIGSEGV_THREAD_STATE_FLAVOR,
1706 +                                                                                 (natural_t *)&SIP->thr_state,
1707 +                                                                                 SIP->thr_state_count);
1708 +        MACH_CHECK_ERROR(thread_set_state, krc);
1709 + }
1710 + #endif
1711 +
1712   // Return the address of the invalid memory reference
1713 < sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip)
1713 > sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP)
1714   {
1715 <        return sip->addr;
1715 > #ifdef HAVE_MACH_EXCEPTIONS
1716 >        static int use_fast_path = -1;
1717 >        if (use_fast_path != 1 && !SIP->has_exc_state) {
1718 >                mach_get_exception_state(SIP);
1719 >
1720 >                sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1721 >                if (use_fast_path < 0)
1722 >                        use_fast_path = addr == SIP->addr;
1723 >                SIP->addr = addr;
1724 >        }
1725 > #endif
1726 >        return SIP->addr;
1727   }
1728  
1729   // Return the address of the instruction that caused the fault, or
1730   // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information
1731 < sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *sip)
1731 > sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP)
1732   {
1733 <        return sip->pc;
1733 > #ifdef HAVE_MACH_EXCEPTIONS
1734 >        if (!SIP->has_thr_state) {
1735 >                mach_get_thread_state(SIP);
1736 >
1737 >                SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1738 >        }
1739 > #endif
1740 >        return SIP->pc;
1741   }
1742  
1743   // This function handles the badaccess to memory.
1744   // It is called from the signal handler or the exception handler.
1745   static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
1746   {
1747 +        sigsegv_info_t SI;
1748 +        SI.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS_FAST;
1749 +        SI.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION_FAST;
1750   #ifdef HAVE_MACH_EXCEPTIONS
1751 <        // We must match the initial count when writing back the CPU state registers
1752 <        kern_return_t krc;
1753 <        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);
1751 >        SI.thread = thread;
1752 >        SI.has_exc_state = false;
1753 >        SI.has_thr_state = false;
1754   #endif
1755 +        sigsegv_info_t * const SIP = &SI;
1756  
1691        sigsegv_info_t si;
1692        si.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
1693        si.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
1694        
1757          // Call user's handler and reinstall the global handler, if required
1758 <        switch (SIGSEGV_FAULT_HANDLER_INVOKE(&si)) {
1758 >        switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) {
1759          case SIGSEGV_RETURN_SUCCESS:
1760                  return true;
1761  
# Line 1701 | Line 1763 | static bool handle_badaccess(SIGSEGV_FAU
1763          case SIGSEGV_RETURN_SKIP_INSTRUCTION:
1764                  // Call the instruction skipper with the register file
1765                  // available
1766 + #ifdef HAVE_MACH_EXCEPTIONS
1767 +                if (!SIP->has_thr_state)
1768 +                        mach_get_thread_state(SIP);
1769 + #endif
1770                  if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
1771   #ifdef HAVE_MACH_EXCEPTIONS
1772                          // Unlike UNIX signals where the thread state
1773                          // is modified off of the stack, in Mach we
1774                          // need to actually call thread_set_state to
1775                          // have the register values updated.
1776 <                        krc = thread_set_state(thread,
1711 <                                                                   SIGSEGV_THREAD_STATE_FLAVOR, (thread_state_t)&state,
1712 <                                                                   count);
1713 <                        MACH_CHECK_ERROR (thread_set_state, krc);
1776 >                        mach_set_thread_state(SIP);
1777   #endif
1778                          return true;
1779                  }
# Line 1719 | Line 1782 | static bool handle_badaccess(SIGSEGV_FAU
1782          case SIGSEGV_RETURN_FAILURE:
1783                  // We can't do anything with the fault_address, dump state?
1784                  if (sigsegv_state_dumper != 0)
1785 <                        sigsegv_state_dumper(&si);
1785 >                        sigsegv_state_dumper(SIP);
1786                  break;
1787          }
1788  
# Line 1868 | Line 1931 | catch_exception_raise(mach_port_t except
1931                  switch (code[0]) {
1932                  case KERN_PROTECTION_FAILURE:
1933                  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
1934                          if (handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGS))
1935                                  return KERN_SUCCESS;
1936                          break;
1937                  }
1884                }
1938          }
1939  
1940          // In Mach we do not need to remove the exception handler.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines