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

Commit 28839fc

Browse files
Konstantin Baladurinjkotas
authored andcommitted
Improve UMEntryThunkCode::Poison method.
Improve UMEntryThunkCode::Poison to produce diagnostic message when collected delegate was called.
1 parent f2ef496 commit 28839fc

File tree

6 files changed

+78
-6
lines changed

6 files changed

+78
-6
lines changed

src/vm/amd64/cgenamd64.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,18 @@ void UMEntryThunkCode::Poison()
680680
}
681681
CONTRACTL_END;
682682

683-
m_movR10[0] = X86_INSTR_INT3;
683+
m_execstub = (BYTE *)UMEntryThunk::ReportViolation;
684+
685+
m_movR10[0] = REX_PREFIX_BASE | REX_OPERAND_SIZE_64BIT;
686+
#ifdef _WIN32
687+
// mov rcx, pUMEntryThunk // 48 b9 xx xx xx xx xx xx xx xx
688+
m_movR10[1] = 0xB9;
689+
#else
690+
// mov rdi, pUMEntryThunk // 48 bf xx xx xx xx xx xx xx xx
691+
m_movR10[1] = 0xBF;
692+
#endif
693+
694+
ClrFlushInstructionCache(&m_movR10[0], &m_jmpRAX[3]-&m_movR10[0]);
684695
}
685696

686697
UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback)

src/vm/arm/stubs.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,12 +2483,22 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam)
24832483
FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code));
24842484
}
24852485

2486+
#ifndef DACCESS_COMPILE
2487+
24862488
void UMEntryThunkCode::Poison()
24872489
{
2488-
// Insert 'udf 0xff' at the entry point
2489-
m_code[0] = 0xdeff;
2490+
m_pTargetCode = (TADDR)UMEntryThunk::ReportViolation;
2491+
2492+
// ldr r0, [pc + 8]
2493+
m_code[0] = 0x4802;
2494+
// nop
2495+
m_code[1] = 0xbf00;
2496+
2497+
ClrFlushInstructionCache(&m_code,sizeof(m_code));
24902498
}
24912499

2500+
#endif // DACCESS_COMPILE
2501+
24922502
///////////////////////////// UNIMPLEMENTED //////////////////////////////////
24932503

24942504
#ifndef DACCESS_COMPILE

src/vm/arm64/stubs.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,12 +1268,20 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam)
12681268
FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code));
12691269
}
12701270

1271+
#ifndef DACCESS_COMPILE
1272+
12711273
void UMEntryThunkCode::Poison()
12721274
{
1273-
// Insert 'brk 0xbe' at the entry point
1274-
m_code[0] = 0xd42017c0;
1275+
m_pTargetCode = (TADDR)UMEntryThunk::ReportViolation;
1276+
1277+
// ldp x16, x0, [x12]
1278+
m_code[1] = 0xd42017c0;
1279+
1280+
ClrFlushInstructionCache(&m_code,sizeof(m_code));
12751281
}
12761282

1283+
#endif // DACCESS_COMPILE
1284+
12771285
#ifdef PROFILING_SUPPORTED
12781286
#include "proftoeeinterfaceimpl.h"
12791287

src/vm/dllimportcallback.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,42 @@ VOID UMEntryThunk::FreeUMEntryThunk(UMEntryThunk* p)
11671167

11681168
#endif // CROSSGEN_COMPILE
11691169

1170+
//-------------------------------------------------------------------------
1171+
// This function is used to report error when we call collected delegate.
1172+
// But memory that was allocated for thunk can be reused, due to it this
1173+
// function will not be called in all cases of the collected delegate call,
1174+
// also it may crash while trying to report the problem.
1175+
//-------------------------------------------------------------------------
1176+
VOID __fastcall UMEntryThunk::ReportViolation(UMEntryThunk* pEntryThunk)
1177+
{
1178+
CONTRACTL
1179+
{
1180+
THROWS;
1181+
GC_TRIGGERS;
1182+
MODE_COOPERATIVE;
1183+
PRECONDITION(CheckPointer(pEntryThunk));
1184+
}
1185+
CONTRACTL_END;
1186+
1187+
MethodDesc* pMethodDesc = pEntryThunk->GetMethod();
1188+
1189+
SString namespaceOrClassName;
1190+
SString methodName;
1191+
SString moduleName;
1192+
1193+
pMethodDesc->GetMethodInfoNoSig(namespaceOrClassName, methodName);
1194+
moduleName.SetUTF8(pMethodDesc->GetModule()->GetSimpleName());
1195+
1196+
SString message;
1197+
1198+
message.Printf(W("A callback was made on a garbage collected delegate of type '%s!%s::%s'."),
1199+
moduleName.GetUnicode(),
1200+
namespaceOrClassName.GetUnicode(),
1201+
methodName.GetUnicode());
1202+
1203+
EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode());
1204+
}
1205+
11701206
UMThunkMarshInfo::~UMThunkMarshInfo()
11711207
{
11721208
CONTRACTL

src/vm/dllimportcallback.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ class UMEntryThunk
511511
}
512512
#endif
513513

514+
static VOID __fastcall ReportViolation(UMEntryThunk* p);
515+
514516
private:
515517
// The start of the managed code.
516518
// if m_pObjectHandle is non-NULL, this field is still set to help with diagnostic of call on collected delegate crashes

src/vm/i386/cgenx86.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,12 @@ void UMEntryThunkCode::Poison()
16141614
{
16151615
LIMITED_METHOD_CONTRACT;
16161616

1617-
m_movEAX = X86_INSTR_INT3;
1617+
m_execstub = (BYTE*) ((BYTE*)UMEntryThunk::ReportViolation - (4+((BYTE*)&m_execstub)));
1618+
1619+
// mov ecx, imm32
1620+
m_movEAX = 0xb9;
1621+
1622+
ClrFlushInstructionCache(GetEntryPoint(),sizeof(UMEntryThunkCode));
16181623
}
16191624

16201625
UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback)

0 commit comments

Comments
 (0)