Procházet zdrojové kódy

[MERGE #4514 @Penguinwizzard] Fix ARM cfg registration asserts.

Merge pull request #4514 from Penguinwizzard:arm_cfg_fix
Derek Morris před 8 roky
rodič
revize
66b6ba8de8

+ 5 - 1
lib/Backend/EmitBuffer.cpp

@@ -234,7 +234,11 @@ EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::FreeAllocation(void* a
             {
                 if (!JITManager::GetJITManager()->IsJITServer() || CONFIG_FLAG(OOPCFGRegistration))
                 {
-                    threadContext->SetValidCallTargetForCFG(address, false);
+                    void* callTarget = address;
+#if _M_ARM
+                    callTarget = (void*)((uintptr_t)callTarget | 0x1); // add the thumb bit back, so we CFG-unregister the actual call target
+#endif
+                    threadContext->SetValidCallTargetForCFG(callTarget, false);
                 }
             }
             VerboseHeapTrace(_u("Freeing 0x%p, allocation: 0x%p\n"), address, allocation->allocation->address);

+ 12 - 2
lib/Backend/InterpreterThunkEmitter.cpp

@@ -377,7 +377,12 @@ bool InterpreterThunkEmitter::NewThunkBlock()
     }
 
     // Call to set VALID flag for CFG check
-    ThreadContext::GetContextForCurrentThread()->SetValidCallTargetForCFG(buffer);
+    BYTE* callTarget = buffer;
+#ifdef _M_ARM
+    // We want to allow the actual callable value, so thumb-tag the address
+    callTarget = (BYTE*)((uintptr_t)buffer | 0x1);
+#endif
+    ThreadContext::GetContextForCurrentThread()->SetValidCallTargetForCFG(callTarget);
 
     // Update object state only at the end when everything has succeeded - and no exceptions can be thrown.
     auto block = this->thunkBlocks.PrependNode(allocator, buffer, count);
@@ -419,7 +424,12 @@ bool InterpreterThunkEmitter::NewOOPJITThunkBlock()
 
     if (!CONFIG_FLAG(OOPCFGRegistration))
     {
-        this->scriptContext->GetThreadContext()->SetValidCallTargetForCFG(buffer);
+        BYTE* callTarget = buffer;
+#ifdef _M_ARM
+        // Need to register the thumb-tagged call target for CFG
+        callTarget = (BYTE*)((uintptr_t)callTarget | 0x1);
+#endif
+        this->scriptContext->GetThreadContext()->SetValidCallTargetForCFG(callTarget);
     }
 
     // Update object state only at the end when everything has succeeded - and no exceptions can be thrown.

+ 5 - 1
lib/Backend/JITOutput.cpp

@@ -284,7 +284,11 @@ JITOutput::FinalizeNativeCode()
     m_outputData->thunkAddress = allocation->thunkAddress;
     if (!allocation->thunkAddress && CONFIG_FLAG(OOPCFGRegistration))
     {
-        m_func->GetThreadContextInfo()->SetValidCallTargetForCFG((PVOID)m_outputData->codeAddress);
+        PVOID callTarget = (PVOID)m_outputData->codeAddress;
+#ifdef _M_ARM
+        callTarget = (PVOID)((uintptr_t)callTarget | 0x1);
+#endif
+        m_func->GetThreadContextInfo()->SetValidCallTargetForCFG(callTarget);
     }
 }
 

+ 5 - 1
lib/JITServer/JITServer.cpp

@@ -613,7 +613,11 @@ ServerNewInterpreterThunkBlock(
         // Call to set VALID flag for CFG check
         if (CONFIG_FLAG(OOPCFGRegistration))
         {
-            threadContext->SetValidCallTargetForCFG(runtimeAddress);
+            BYTE* callTarget = runtimeAddress;
+#ifdef _M_ARM
+            callTarget = (BYTE*)((uintptr_t)callTarget | 0x1); // Thumb-tag buffer to get actual callable value
+#endif
+            threadContext->SetValidCallTargetForCFG(callTarget);
         }
 
         thunkOutput->thunkCount = thunkCount;

+ 5 - 0
lib/Runtime/Base/ThreadContextInfo.cpp

@@ -418,7 +418,12 @@ ThreadContextInfo::SetValidCallTargetForCFG(PVOID callTargetAddress, bool isSetV
 #ifdef _CONTROL_FLOW_GUARD
     if (IsCFGEnabled())
     {
+#ifdef _M_ARM
+        AssertMsg(((uintptr_t)callTargetAddress & 0x1) != 0, "on ARM we expect the thumb bit to be set on anything we use as a call target");
+        AssertMsg(IS_16BYTE_ALIGNED((uintptr_t)callTargetAddress & ~0x1), "callTargetAddress is not 16-byte page aligned?");
+#else
         AssertMsg(IS_16BYTE_ALIGNED(callTargetAddress), "callTargetAddress is not 16-byte page aligned?");
+#endif
 
         // If SetProcessValidCallTargets is not allowed by global policy (e.g.
         // OOP JIT is in use in the client), then generate a fast fail

+ 5 - 1
lib/Runtime/Language/AsmJsEncoder.cpp

@@ -221,7 +221,11 @@ namespace Js
                 Js::Throw::OutOfMemory();
             }
 
-            functionBody->GetScriptContext()->GetThreadContext()->SetValidCallTargetForCFG(buffer);
+            BYTE* callTarget = buffer;
+#ifdef _M_ARM
+            callTarget = (BYTE*)((uintptr_t)buffer | 0x1); // We have to add the thumb bit on arm
+#endif
+            functionBody->GetScriptContext()->GetThreadContext()->SetValidCallTargetForCFG(callTarget);
 
             // TODO: improve this once EntryPoint cleanup work is complete!
 #if 0