mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-12 16:30:44 +00:00
Fix instruction skipping on MacOS X in the fast path case.
This commit is contained in:
parent
b5ac365858
commit
26f9b1d38b
@ -1676,12 +1676,9 @@ struct sigsegv_info_t {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the address of the invalid memory reference
|
|
||||||
sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_MACH_EXCEPTIONS
|
#ifdef HAVE_MACH_EXCEPTIONS
|
||||||
static int use_fast_path = -1;
|
static void mach_get_exception_state(sigsegv_info_t *sip)
|
||||||
if (use_fast_path != 1 && !sip->has_exc_state) {
|
{
|
||||||
sip->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
|
sip->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT;
|
||||||
kern_return_t krc = thread_get_state(sip->thread,
|
kern_return_t krc = thread_get_state(sip->thread,
|
||||||
SIGSEGV_EXCEPTION_STATE_FLAVOR,
|
SIGSEGV_EXCEPTION_STATE_FLAVOR,
|
||||||
@ -1689,6 +1686,36 @@ sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip)
|
|||||||
&sip->exc_state_count);
|
&sip->exc_state_count);
|
||||||
MACH_CHECK_ERROR(thread_get_state, krc);
|
MACH_CHECK_ERROR(thread_get_state, krc);
|
||||||
sip->has_exc_state = true;
|
sip->has_exc_state = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mach_get_thread_state(sigsegv_info_t *sip)
|
||||||
|
{
|
||||||
|
sip->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
|
||||||
|
kern_return_t krc = thread_get_state(sip->thread,
|
||||||
|
SIGSEGV_THREAD_STATE_FLAVOR,
|
||||||
|
(natural_t *)&sip->thr_state,
|
||||||
|
&sip->thr_state_count);
|
||||||
|
MACH_CHECK_ERROR(thread_get_state, krc);
|
||||||
|
sip->has_thr_state = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mach_set_thread_state(sigsegv_info_t *sip)
|
||||||
|
{
|
||||||
|
kern_return_t krc = thread_set_state(sip->thread,
|
||||||
|
SIGSEGV_THREAD_STATE_FLAVOR,
|
||||||
|
(natural_t *)&sip->thr_state,
|
||||||
|
sip->thr_state_count);
|
||||||
|
MACH_CHECK_ERROR(thread_set_state, krc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Return the address of the invalid memory reference
|
||||||
|
sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *sip)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MACH_EXCEPTIONS
|
||||||
|
static int use_fast_path = -1;
|
||||||
|
if (use_fast_path != 1 && !sip->has_exc_state) {
|
||||||
|
mach_get_exception_state(sip);
|
||||||
|
|
||||||
sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
|
sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS;
|
||||||
if (use_fast_path < 0)
|
if (use_fast_path < 0)
|
||||||
@ -1705,13 +1732,7 @@ sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *sip)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_MACH_EXCEPTIONS
|
#ifdef HAVE_MACH_EXCEPTIONS
|
||||||
if (!sip->has_thr_state) {
|
if (!sip->has_thr_state) {
|
||||||
sip->thr_state_count = SIGSEGV_THREAD_STATE_COUNT;
|
mach_get_thread_state(sip);
|
||||||
kern_return_t krc = thread_get_state(sip->thread,
|
|
||||||
SIGSEGV_THREAD_STATE_FLAVOR,
|
|
||||||
(natural_t *)&sip->thr_state,
|
|
||||||
&sip->thr_state_count);
|
|
||||||
MACH_CHECK_ERROR(thread_get_state, krc);
|
|
||||||
sip->has_thr_state = true;
|
|
||||||
|
|
||||||
sip->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
|
sip->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION;
|
||||||
}
|
}
|
||||||
@ -1742,17 +1763,17 @@ static bool handle_badaccess(SIGSEGV_FAULT_HANDLER_ARGLIST_1)
|
|||||||
case SIGSEGV_RETURN_SKIP_INSTRUCTION:
|
case SIGSEGV_RETURN_SKIP_INSTRUCTION:
|
||||||
// Call the instruction skipper with the register file
|
// Call the instruction skipper with the register file
|
||||||
// available
|
// available
|
||||||
|
#ifdef HAVE_MACH_EXCEPTIONS
|
||||||
|
if (!sip->has_thr_state)
|
||||||
|
mach_get_thread_state(sip);
|
||||||
|
#endif
|
||||||
if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
|
if (SIGSEGV_SKIP_INSTRUCTION(SIGSEGV_REGISTER_FILE)) {
|
||||||
#ifdef HAVE_MACH_EXCEPTIONS
|
#ifdef HAVE_MACH_EXCEPTIONS
|
||||||
// Unlike UNIX signals where the thread state
|
// Unlike UNIX signals where the thread state
|
||||||
// is modified off of the stack, in Mach we
|
// is modified off of the stack, in Mach we
|
||||||
// need to actually call thread_set_state to
|
// need to actually call thread_set_state to
|
||||||
// have the register values updated.
|
// have the register values updated.
|
||||||
kern_return_t krc = thread_set_state(sip->thread,
|
mach_set_thread_state(sip);
|
||||||
SIGSEGV_THREAD_STATE_FLAVOR,
|
|
||||||
(natural_t *)&sip->thr_state,
|
|
||||||
sip->thr_state_count);
|
|
||||||
MACH_CHECK_ERROR(thread_set_state, krc);
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user