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 |
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__) || defined(__ppc64__)) |
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 sip->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 sip->thr_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 *)&sip->thr_state.srr0, (unsigned long *)&sip->thr_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 |
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 |
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 |
626 |
> |
#define SIGSEGV_REGISTER_FILE (unsigned long *)&SIP->thr_state.srr0, (unsigned long *)&SIP->thr_state.r0 |
627 |
|
#endif |
628 |
|
#ifdef __i386__ |
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 sip->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_FAULT_INSTRUCTION sip->thr_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 */ |
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 sip->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_FAULT_INSTRUCTION sip->thr_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 */ |
650 |
> |
#define SIGSEGV_REGISTER_FILE ((unsigned long *)&SIP->thr_state.rax) /* RAX is the first GPR we consider */ |
651 |
|
#endif |
652 |
|
#define SIGSEGV_FAULT_ADDRESS_FAST code[1] |
653 |
|
#define SIGSEGV_FAULT_INSTRUCTION_FAST SIGSEGV_INVALID_ADDRESS |
1677 |
|
}; |
1678 |
|
|
1679 |
|
#ifdef HAVE_MACH_EXCEPTIONS |
1680 |
< |
static void mach_get_exception_state(sigsegv_info_t *sip) |
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, |
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); |
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; |
1688 |
> |
SIP->has_exc_state = true; |
1689 |
|
} |
1690 |
|
|
1691 |
< |
static void mach_get_thread_state(sigsegv_info_t *sip) |
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, |
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); |
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; |
1699 |
> |
SIP->has_thr_state = true; |
1700 |
|
} |
1701 |
|
|
1702 |
< |
static void mach_set_thread_state(sigsegv_info_t *sip) |
1702 |
> |
static void mach_set_thread_state(sigsegv_info_t *SIP) |
1703 |
|
{ |
1704 |
< |
kern_return_t krc = thread_set_state(sip->thread, |
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); |
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 |
|
#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); |
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; |
1722 |
> |
use_fast_path = addr == SIP->addr; |
1723 |
> |
SIP->addr = addr; |
1724 |
|
} |
1725 |
|
#endif |
1726 |
< |
return sip->addr; |
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 |
|
#ifdef HAVE_MACH_EXCEPTIONS |
1734 |
< |
if (!sip->has_thr_state) { |
1735 |
< |
mach_get_thread_state(sip); |
1734 |
> |
if (!SIP->has_thr_state) { |
1735 |
> |
mach_get_thread_state(SIP); |
1736 |
|
|
1737 |
< |
sip->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION; |
1737 |
> |
SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION; |
1738 |
|
} |
1739 |
|
#endif |
1740 |
< |
return sip->pc; |
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; |
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 |
< |
si.thread = thread; |
1752 |
< |
si.has_exc_state = false; |
1753 |
< |
si.has_thr_state = false; |
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; |
1755 |
> |
sigsegv_info_t * const SIP = &SI; |
1756 |
|
|
1757 |
|
// Call user's handler and reinstall the global handler, if required |
1758 |
< |
switch (SIGSEGV_FAULT_HANDLER_INVOKE(sip)) { |
1758 |
> |
switch (SIGSEGV_FAULT_HANDLER_INVOKE(SIP)) { |
1759 |
|
case SIGSEGV_RETURN_SUCCESS: |
1760 |
|
return true; |
1761 |
|
|
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); |
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 |
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 |
< |
mach_set_thread_state(sip); |
1776 |
> |
mach_set_thread_state(SIP); |
1777 |
|
#endif |
1778 |
|
return true; |
1779 |
|
} |
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(sip); |
1785 |
> |
sigsegv_state_dumper(SIP); |
1786 |
|
break; |
1787 |
|
} |
1788 |
|
|
2389 |
|
|
2390 |
|
if (!sigsegv_install_handler(sigsegv_test_handler)) |
2391 |
|
return 4; |
2392 |
< |
|
2392 |
> |
|
2393 |
|
#ifdef __GNUC__ |
2394 |
|
b_region = &&L_b_region1; |
2395 |
|
e_region = &&L_e_region1; |
2396 |
|
#endif |
2397 |
< |
L_b_region1: |
2398 |
< |
page[REF_INDEX] = REF_VALUE; |
2399 |
< |
if (page[REF_INDEX] != REF_VALUE) |
2400 |
< |
exit(20); |
2401 |
< |
page[REF_INDEX] = REF_VALUE; |
2402 |
< |
BARRIER(); |
2403 |
< |
L_e_region1: |
2397 |
> |
/* This is a really awful hack but otherwise gcc is smart enough |
2398 |
> |
* (or bug'ous enough?) to optimize the labels and place them |
2399 |
> |
* e.g. at the "main" entry point, which is wrong. |
2400 |
> |
*/ |
2401 |
> |
volatile int label_hack = 1; |
2402 |
> |
switch (label_hack) { |
2403 |
> |
case 1: |
2404 |
> |
L_b_region1: |
2405 |
> |
page[REF_INDEX] = REF_VALUE; |
2406 |
> |
if (page[REF_INDEX] != REF_VALUE) |
2407 |
> |
exit(20); |
2408 |
> |
page[REF_INDEX] = REF_VALUE; |
2409 |
> |
BARRIER(); |
2410 |
> |
// fall-through |
2411 |
> |
case 2: |
2412 |
> |
L_e_region1: |
2413 |
> |
BARRIER(); |
2414 |
> |
break; |
2415 |
> |
} |
2416 |
|
|
2417 |
|
if (handler_called != 1) |
2418 |
|
return 5; |
2443 |
|
b_region = &&L_b_region2; |
2444 |
|
e_region = &&L_e_region2; |
2445 |
|
#endif |
2446 |
< |
L_b_region2: |
2447 |
< |
TEST_SKIP_INSTRUCTION(unsigned char); |
2448 |
< |
TEST_SKIP_INSTRUCTION(unsigned short); |
2449 |
< |
TEST_SKIP_INSTRUCTION(unsigned int); |
2450 |
< |
TEST_SKIP_INSTRUCTION(unsigned long); |
2451 |
< |
TEST_SKIP_INSTRUCTION(signed char); |
2452 |
< |
TEST_SKIP_INSTRUCTION(signed short); |
2453 |
< |
TEST_SKIP_INSTRUCTION(signed int); |
2454 |
< |
TEST_SKIP_INSTRUCTION(signed long); |
2455 |
< |
BARRIER(); |
2456 |
< |
L_e_region2: |
2457 |
< |
|
2446 |
> |
switch (label_hack) { |
2447 |
> |
case 1: |
2448 |
> |
L_b_region2: |
2449 |
> |
TEST_SKIP_INSTRUCTION(unsigned char); |
2450 |
> |
TEST_SKIP_INSTRUCTION(unsigned short); |
2451 |
> |
TEST_SKIP_INSTRUCTION(unsigned int); |
2452 |
> |
TEST_SKIP_INSTRUCTION(unsigned long); |
2453 |
> |
TEST_SKIP_INSTRUCTION(signed char); |
2454 |
> |
TEST_SKIP_INSTRUCTION(signed short); |
2455 |
> |
TEST_SKIP_INSTRUCTION(signed int); |
2456 |
> |
TEST_SKIP_INSTRUCTION(signed long); |
2457 |
> |
BARRIER(); |
2458 |
> |
// fall-through |
2459 |
> |
case 2: |
2460 |
> |
L_e_region2: |
2461 |
> |
BARRIER(); |
2462 |
> |
break; |
2463 |
> |
} |
2464 |
|
if (!arch_insn_skipper_tests()) |
2465 |
|
return 20; |
2466 |
|
#endif |