Improve UMEntryThunkCode::Poison method.
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Wed, 10 Jan 2018 15:26:01 +0000 (18:26 +0300)
committerJan Kotas <jkotas@microsoft.com>
Fri, 12 Jan 2018 20:40:37 +0000 (12:40 -0800)
Improve UMEntryThunkCode::Poison to produce diagnostic message
when collected delegate was called.

src/vm/amd64/cgenamd64.cpp
src/vm/arm/stubs.cpp
src/vm/arm64/stubs.cpp
src/vm/dllimportcallback.cpp
src/vm/dllimportcallback.h
src/vm/i386/cgenx86.cpp

index 4e1f38a..6075134 100644 (file)
@@ -680,7 +680,18 @@ void UMEntryThunkCode::Poison()
     }
     CONTRACTL_END;
 
-    m_movR10[0] = X86_INSTR_INT3;
+    m_execstub    = (BYTE *)UMEntryThunk::ReportViolation;
+
+    m_movR10[0]  = REX_PREFIX_BASE | REX_OPERAND_SIZE_64BIT;
+#ifdef _WIN32
+    // mov rcx, pUMEntryThunk // 48 b9 xx xx xx xx xx xx xx xx
+    m_movR10[1]  = 0xB9;
+#else
+    // mov rdi, pUMEntryThunk // 48 bf xx xx xx xx xx xx xx xx
+    m_movR10[1]  = 0xBF;
+#endif
+
+    ClrFlushInstructionCache(&m_movR10[0], &m_jmpRAX[3]-&m_movR10[0]);
 }
 
 UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback)
index f2500c3..7e5b58c 100644 (file)
@@ -2483,12 +2483,22 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam)
     FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code));
 }
 
+#ifndef DACCESS_COMPILE
+
 void UMEntryThunkCode::Poison()
 {
-    // Insert 'udf 0xff' at the entry point
-    m_code[0] = 0xdeff;
+    m_pTargetCode = (TADDR)UMEntryThunk::ReportViolation;
+
+    // ldr r0, [pc + 8]
+    m_code[0] = 0x4802;
+    // nop
+    m_code[1] = 0xbf00;
+
+    ClrFlushInstructionCache(&m_code,sizeof(m_code));
 }
 
+#endif // DACCESS_COMPILE
+
 ///////////////////////////// UNIMPLEMENTED //////////////////////////////////
 
 #ifndef DACCESS_COMPILE
index 3c56c38..3d4213b 100644 (file)
@@ -1268,12 +1268,20 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam)
     FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code));
 }
 
+#ifndef DACCESS_COMPILE
+
 void UMEntryThunkCode::Poison()
 {
-    // Insert 'brk 0xbe' at the entry point
-    m_code[0] = 0xd42017c0;
+    m_pTargetCode = (TADDR)UMEntryThunk::ReportViolation;
+
+    // ldp x16, x0, [x12]
+    m_code[1] = 0xd42017c0;
+
+    ClrFlushInstructionCache(&m_code,sizeof(m_code));
 }
 
+#endif // DACCESS_COMPILE
+
 #ifdef PROFILING_SUPPORTED
 #include "proftoeeinterfaceimpl.h"
 
index 8684c12..c3e6a4e 100644 (file)
@@ -1167,6 +1167,42 @@ VOID UMEntryThunk::FreeUMEntryThunk(UMEntryThunk* p)
 
 #endif // CROSSGEN_COMPILE
 
+//-------------------------------------------------------------------------
+// This function is used to report error when we call collected delegate.
+// But memory that was allocated for thunk can be reused, due to it this
+// function will not be called in all cases of the collected delegate call,
+// also it may crash while trying to report the problem.
+//-------------------------------------------------------------------------
+VOID __fastcall UMEntryThunk::ReportViolation(UMEntryThunk* pEntryThunk)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_COOPERATIVE;
+        PRECONDITION(CheckPointer(pEntryThunk));
+    }
+    CONTRACTL_END;
+
+    MethodDesc* pMethodDesc = pEntryThunk->GetMethod();
+
+    SString namespaceOrClassName;
+    SString methodName;
+    SString moduleName;
+
+    pMethodDesc->GetMethodInfoNoSig(namespaceOrClassName, methodName);
+    moduleName.SetUTF8(pMethodDesc->GetModule()->GetSimpleName());
+
+    SString message;
+
+    message.Printf(W("A callback was made on a garbage collected delegate of type '%s!%s::%s'."),
+        moduleName.GetUnicode(),
+        namespaceOrClassName.GetUnicode(),
+        methodName.GetUnicode());
+
+    EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode());
+}
+
 UMThunkMarshInfo::~UMThunkMarshInfo()
 {
     CONTRACTL
index e79c5f0..5838e49 100644 (file)
@@ -511,6 +511,8 @@ public:
     }
 #endif
 
+    static VOID __fastcall ReportViolation(UMEntryThunk* p);
+
 private:
     // The start of the managed code.
     // if m_pObjectHandle is non-NULL, this field is still set to help with diagnostic of call on collected delegate crashes
index 19d7bbe..7071d27 100644 (file)
@@ -1614,7 +1614,12 @@ void UMEntryThunkCode::Poison()
 {
     LIMITED_METHOD_CONTRACT;
 
-    m_movEAX = X86_INSTR_INT3;
+    m_execstub = (BYTE*) ((BYTE*)UMEntryThunk::ReportViolation - (4+((BYTE*)&m_execstub)));
+
+    // mov ecx, imm32
+    m_movEAX = 0xb9;
+
+    ClrFlushInstructionCache(GetEntryPoint(),sizeof(UMEntryThunkCode));
 }
 
 UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback)