}
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)
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
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"
#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
}
#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
{
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)