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. |
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 |
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
} |
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 |
|
|
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. |