1636 |
|
|
1637 |
|
// Fallbacks |
1638 |
|
#ifndef SIGSEGV_FAULT_INSTRUCTION |
1639 |
< |
#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_INVALID_PC |
1639 |
> |
#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_INVALID_ADDRESS |
1640 |
|
#endif |
1641 |
|
#ifndef SIGSEGV_FAULT_HANDLER_ARGLIST_1 |
1642 |
|
#define SIGSEGV_FAULT_HANDLER_ARGLIST_1 SIGSEGV_FAULT_HANDLER_ARGLIST |
1643 |
|
#endif |
1644 |
|
#ifndef SIGSEGV_FAULT_HANDLER_INVOKE |
1645 |
< |
#define SIGSEGV_FAULT_HANDLER_INVOKE(ADDR, IP) sigsegv_fault_handler(ADDR, IP) |
1645 |
> |
#define SIGSEGV_FAULT_HANDLER_INVOKE(P) sigsegv_fault_handler(P) |
1646 |
|
#endif |
1647 |
|
|
1648 |
|
// SIGSEGV recovery supported ? |
1655 |
|
* SIGSEGV global handler |
1656 |
|
*/ |
1657 |
|
|
1658 |
+ |
struct sigsegv_info_t { |
1659 |
+ |
sigsegv_address_t addr; |
1660 |
+ |
sigsegv_address_t pc; |
1661 |
+ |
}; |
1662 |
+ |
|
1663 |
+ |
// Return the address of the invalid memory reference |
1664 |
+ |
sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip) |
1665 |
+ |
{ |
1666 |
+ |
return sip->addr; |
1667 |
+ |
} |
1668 |
+ |
|
1669 |
+ |
// Return the address of the instruction that caused the fault, or |
1670 |
+ |
// SIGSEGV_INVALID_ADDRESS if we could not retrieve this information |
1671 |
+ |
sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *sip) |
1672 |
+ |
{ |
1673 |
+ |
return sip->pc; |
1674 |
+ |
} |
1675 |
+ |
|
1676 |
|
// This function handles the badaccess to memory. |
1677 |
|
// It is called from the signal handler or the exception handler. |
1678 |
|
static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1) |
1688 |
|
MACH_CHECK_ERROR (thread_get_state, krc); |
1689 |
|
#endif |
1690 |
|
|
1691 |
< |
sigsegv_address_t fault_address = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS; |
1692 |
< |
sigsegv_address_t fault_instruction = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION; |
1691 |
> |
sigsegv_info_t si; |
1692 |
> |
si.addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS; |
1693 |
> |
si.pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION; |
1694 |
|
|
1695 |
|
// Call user's handler and reinstall the global handler, if required |
1696 |
< |
switch (SIGSEGV_FAULT_HANDLER_INVOKE(fault_address, fault_instruction)) { |
1696 |
> |
switch (SIGSEGV_FAULT_HANDLER_INVOKE(&si)) { |
1697 |
|
case SIGSEGV_RETURN_SUCCESS: |
1698 |
|
return true; |
1699 |
|
|
1719 |
|
case SIGSEGV_RETURN_FAILURE: |
1720 |
|
// We can't do anything with the fault_address, dump state? |
1721 |
|
if (sigsegv_state_dumper != 0) |
1722 |
< |
sigsegv_state_dumper(fault_address, fault_instruction); |
1722 |
> |
sigsegv_state_dumper(&si); |
1723 |
|
break; |
1724 |
|
} |
1725 |
|
|
2211 |
|
static void *b_region, *e_region; |
2212 |
|
#endif |
2213 |
|
|
2214 |
< |
static sigsegv_return_t sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address) |
2214 |
> |
static sigsegv_return_t sigsegv_test_handler(sigsegv_info_t *sip) |
2215 |
|
{ |
2216 |
+ |
const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip); |
2217 |
+ |
const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip); |
2218 |
|
#if DEBUG |
2219 |
|
printf("sigsegv_test_handler(%p, %p)\n", fault_address, instruction_address); |
2220 |
|
printf("expected fault at %p\n", page + REF_INDEX); |
2228 |
|
#ifdef __GNUC__ |
2229 |
|
// Make sure reported fault instruction address falls into |
2230 |
|
// expected code range |
2231 |
< |
if (instruction_address != SIGSEGV_INVALID_PC |
2231 |
> |
if (instruction_address != SIGSEGV_INVALID_ADDRESS |
2232 |
|
&& ((instruction_address < (sigsegv_address_t)b_region) || |
2233 |
|
(instruction_address >= (sigsegv_address_t)e_region))) |
2234 |
|
exit(11); |
2239 |
|
} |
2240 |
|
|
2241 |
|
#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION |
2242 |
< |
static sigsegv_return_t sigsegv_insn_handler(sigsegv_address_t fault_address, sigsegv_address_t instruction_address) |
2242 |
> |
static sigsegv_return_t sigsegv_insn_handler(sigsegv_info_t *sip) |
2243 |
|
{ |
2244 |
+ |
const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip); |
2245 |
+ |
const sigsegv_address_t instruction_address = sigsegv_get_fault_instruction_address(sip); |
2246 |
|
#if DEBUG |
2247 |
|
printf("sigsegv_insn_handler(%p, %p)\n", fault_address, instruction_address); |
2248 |
|
#endif |
2250 |
|
#ifdef __GNUC__ |
2251 |
|
// Make sure reported fault instruction address falls into |
2252 |
|
// expected code range |
2253 |
< |
if (instruction_address != SIGSEGV_INVALID_PC |
2253 |
> |
if (instruction_address != SIGSEGV_INVALID_ADDRESS |
2254 |
|
&& ((instruction_address < (sigsegv_address_t)b_region) || |
2255 |
|
(instruction_address >= (sigsegv_address_t)e_region))) |
2256 |
|
return SIGSEGV_RETURN_FAILURE; |