Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit a0b2e33

Browse files
committed
Merge pull request #1720 from janvorli/fix-osx-activation-and-exception-collision
Fix OSX hardware exception and activation collision
2 parents 0633a25 + 278285a commit a0b2e33

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

src/pal/src/exception/machexception.cpp

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,47 +1821,61 @@ PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread)
18211821
if (palError == NO_ERROR)
18221822
{
18231823
mach_port_t thread = pThread->GetMachPortSelf();
1824-
x86_thread_state64_t ThreadState;
1825-
mach_msg_type_number_t count = sizeof(ThreadState)/sizeof(natural_t);
1824+
mach_msg_type_number_t count;
18261825
kern_return_t MachRet;
18271826

1827+
x86_exception_state64_t ExceptionState;
1828+
count = x86_EXCEPTION_STATE64_COUNT;
18281829
MachRet = thread_get_state(thread,
1829-
x86_THREAD_STATE64,
1830-
(thread_state_t)&ThreadState,
1830+
x86_EXCEPTION_STATE64,
1831+
(thread_state_t)&ExceptionState,
18311832
&count);
1832-
_ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_get_state\n");
1833+
_ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_get_state for x86_EXCEPTION_STATE64\n");
18331834

1834-
if ((g_safeActivationCheckFunction != NULL) && g_safeActivationCheckFunction(ThreadState.__rip))
1835+
// Inject the activation only if the thread doesn't have a pending hardware exception
1836+
static const int MaxHardwareExceptionVector = 31;
1837+
if (ExceptionState.__trapno > MaxHardwareExceptionVector)
18351838
{
1836-
// TODO: it would be nice to preserve the red zone in case a jitter would want to use it
1837-
// Do we really care about unwinding through the wrapper?
1838-
size_t* sp = (size_t*)ThreadState.__rsp;
1839-
*(--sp) = ThreadState.__rip;
1840-
*(--sp) = ThreadState.__rbp;
1841-
size_t rbpAddress = (size_t)sp;
1842-
size_t contextAddress = (((size_t)sp) - sizeof(CONTEXT)) & ~15;
1843-
size_t returnAddressAddress = contextAddress - sizeof(size_t);
1844-
*(size_t*)(returnAddressAddress) = ActivationHandlerReturnOffset + (size_t)ActivationHandlerWrapper;
1845-
1846-
// Fill in the context in the helper frame with the full context of the suspended thread.
1847-
// The ActivationHandler will use the context to resume the execution of the thread
1848-
// after the activation function returns.
1849-
CONTEXT *pContext = (CONTEXT *)contextAddress;
1850-
pContext->ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS;
1851-
MachRet = CONTEXT_GetThreadContextFromPort(thread, pContext);
1852-
_ASSERT_MSG(MachRet == KERN_SUCCESS, "CONTEXT_GetThreadContextFromPort\n");
1853-
1854-
// Make the instruction register point to ActivationHandler
1855-
ThreadState.__rip = (size_t)ActivationHandler;
1856-
ThreadState.__rsp = returnAddressAddress;
1857-
ThreadState.__rbp = rbpAddress;
1858-
ThreadState.__rdi = contextAddress;
1859-
1860-
MachRet = thread_set_state(thread,
1839+
x86_thread_state64_t ThreadState;
1840+
count = x86_THREAD_STATE64_COUNT;
1841+
MachRet = thread_get_state(thread,
18611842
x86_THREAD_STATE64,
18621843
(thread_state_t)&ThreadState,
1863-
count);
1864-
_ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_set_state\n");
1844+
&count);
1845+
_ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_get_state for x86_THREAD_STATE64\n");
1846+
1847+
if ((g_safeActivationCheckFunction != NULL) && g_safeActivationCheckFunction(ThreadState.__rip))
1848+
{
1849+
// TODO: it would be nice to preserve the red zone in case a jitter would want to use it
1850+
// Do we really care about unwinding through the wrapper?
1851+
size_t* sp = (size_t*)ThreadState.__rsp;
1852+
*(--sp) = ThreadState.__rip;
1853+
*(--sp) = ThreadState.__rbp;
1854+
size_t rbpAddress = (size_t)sp;
1855+
size_t contextAddress = (((size_t)sp) - sizeof(CONTEXT)) & ~15;
1856+
size_t returnAddressAddress = contextAddress - sizeof(size_t);
1857+
*(size_t*)(returnAddressAddress) = ActivationHandlerReturnOffset + (size_t)ActivationHandlerWrapper;
1858+
1859+
// Fill in the context in the helper frame with the full context of the suspended thread.
1860+
// The ActivationHandler will use the context to resume the execution of the thread
1861+
// after the activation function returns.
1862+
CONTEXT *pContext = (CONTEXT *)contextAddress;
1863+
pContext->ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS;
1864+
MachRet = CONTEXT_GetThreadContextFromPort(thread, pContext);
1865+
_ASSERT_MSG(MachRet == KERN_SUCCESS, "CONTEXT_GetThreadContextFromPort\n");
1866+
1867+
// Make the instruction register point to ActivationHandler
1868+
ThreadState.__rip = (size_t)ActivationHandler;
1869+
ThreadState.__rsp = returnAddressAddress;
1870+
ThreadState.__rbp = rbpAddress;
1871+
ThreadState.__rdi = contextAddress;
1872+
1873+
MachRet = thread_set_state(thread,
1874+
x86_THREAD_STATE64,
1875+
(thread_state_t)&ThreadState,
1876+
count);
1877+
_ASSERT_MSG(MachRet == KERN_SUCCESS, "thread_set_state\n");
1878+
}
18651879
}
18661880

18671881
palError = pCurrentThread->suspensionInfo.InternalResumeThreadFromData(

0 commit comments

Comments
 (0)