1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

Events for IL methods without IL headers (#90826)

* Events for IL methods without IL headers

Dynamically generated methods like UnsafeAccessor
functions are marked as IL, but don't contain an IL
header. The lack of header is an indication the IL must
be generated at runtime.

Co-authored-by: Tlakaelel Axayakatl Ceja <tlakaelel.ceja@microsoft.com>
This commit is contained in:
Aaron Robinson 2023-08-19 08:03:03 -07:00 committed by GitHub
parent 2efa42bc18
commit a429b0ca4f
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 90 additions and 79 deletions

View file

@ -1253,14 +1253,19 @@ ClrDataFrame::GetLocalSig(MetaSig** sig,
{ {
// It turns out we cannot really get rid of this check. Dynamic methods // It turns out we cannot really get rid of this check. Dynamic methods
// (including IL stubs) do not have their local sig's available after JIT time. // (including IL stubs) do not have their local sig's available after JIT time.
if (!m_methodDesc->IsIL()) // IL methods with dynamically generated IL (for example, UnsafeAccessors) may
// not have an IL header.
COR_ILMETHOD* ilHeader = m_methodDesc->IsIL()
? m_methodDesc->GetILHeader()
: NULL;
if (ilHeader == NULL)
{ {
*sig = NULL; *sig = NULL;
*count = 0; *count = 0;
return E_FAIL; return E_FAIL;
} }
COR_ILMETHOD_DECODER methodDecoder(m_methodDesc->GetILHeader()); COR_ILMETHOD_DECODER methodDecoder(ilHeader);
mdSignature localSig = methodDecoder.GetLocalVarSigTok() ? mdSignature localSig = methodDecoder.GetLocalVarSigTok() ?
methodDecoder.GetLocalVarSigTok() : mdSignatureNil; methodDecoder.GetLocalVarSigTok() : mdSignatureNil;
if (localSig == mdSignatureNil) if (localSig == mdSignatureNil)

View file

@ -905,7 +905,7 @@ namespace ETW
BOOL fSendRichDebugInfoEvent, BOOL fSendRichDebugInfoEvent,
BOOL fGetCodeIds); BOOL fGetCodeIds);
static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions);
static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL);
static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId); static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId);
static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId, MethodDescSet* sentMethodDetailsSet); static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId, MethodDescSet* sentMethodDetailsSet);
static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL, MethodDescSet* sentMethodDetailsSet = NULL); static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL, MethodDescSet* sentMethodDetailsSet = NULL);
@ -938,7 +938,7 @@ namespace ETW
static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc); static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc);
static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint); static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint);
static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); static VOID MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig);
static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc); static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc);
static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set); static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set);
@ -952,7 +952,7 @@ namespace ETW
public: public:
static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {}; static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {};
static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {}; static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {};
static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); static VOID MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig);
static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {};
static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {};

View file

@ -12,9 +12,9 @@
#include "switches.h" #include "switches.h"
#include "stresslog.h" #include "stresslog.h"
#include "clrhost.h" #include "clrhost.h"
#include "ex.h"
#define DONOT_DEFINE_ETW_CALLBACK #define DONOT_DEFINE_ETW_CALLBACK
#include "eventtracebase.h" #include "eventtracebase.h"
#include "ex.h"
#if !defined(STRESS_LOG_READONLY) #if !defined(STRESS_LOG_READONLY)
#ifdef HOST_WINDOWS #ifdef HOST_WINDOWS

View file

@ -3555,7 +3555,7 @@ VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC
/*************************************************/ /*************************************************/
/* This is called by the runtime when method jitting started */ /* This is called by the runtime when method jitting started */
/*************************************************/ /*************************************************/
VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature)
{ {
CONTRACTL { CONTRACTL {
NOTHROW; NOTHROW;
@ -3570,7 +3570,7 @@ VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr
CLR_JIT_KEYWORD)) CLR_JIT_KEYWORD))
{ {
pMethodDesc->GetMethodInfo(*namespaceOrClassName, *methodName, *methodSignature); pMethodDesc->GetMethodInfo(*namespaceOrClassName, *methodName, *methodSignature);
ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, namespaceOrClassName, methodName, methodSignature); ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, methodDecoder, namespaceOrClassName, methodName, methodSignature);
} }
} EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions);
} }
@ -4528,7 +4528,12 @@ VOID ETW::MethodLog::SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc,
/*****************************************************************/ /*****************************************************************/
/* This routine is used to send an ETW event just before a method starts jitting*/ /* This routine is used to send an ETW event just before a method starts jitting*/
/*****************************************************************/ /*****************************************************************/
VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) VOID ETW::MethodLog::SendMethodJitStartEvent(
MethodDesc *pMethodDesc,
COR_ILMETHOD_DECODER* methodDecoder,
SString *namespaceOrClassName,
SString *methodName,
SString *methodSignature)
{ {
CONTRACTL { CONTRACTL {
THROWS; THROWS;
@ -4566,15 +4571,13 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n
ulMethodToken = (ULONG)0; ulMethodToken = (ULONG)0;
} }
else else
ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();
if(pMethodDesc->IsIL())
{ {
COR_ILMETHOD_DECODER::DecoderStatus decoderstatus = COR_ILMETHOD_DECODER::FORMAT_ERROR; ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();
COR_ILMETHOD_DECODER ILHeader(pMethodDesc->GetILHeader(), pMethodDesc->GetMDImport(), &decoderstatus);
ulMethodILSize = (ULONG)ILHeader.GetCodeSize();
} }
if (methodDecoder != NULL)
ulMethodILSize = methodDecoder->GetCodeSize();
SString tNamespace, tMethodName, tMethodSignature; SString tNamespace, tMethodName, tMethodSignature;
if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty()))
{ {

View file

@ -12327,7 +12327,7 @@ static CorJitResult CompileMethodWithEtwWrapper(EEJitManager *jitMgr,
SString namespaceOrClassName, methodName, methodSignature; SString namespaceOrClassName, methodName, methodSignature;
// Fire an ETW event to mark the beginning of JIT'ing // Fire an ETW event to mark the beginning of JIT'ing
ETW::MethodLog::MethodJitting(reinterpret_cast<MethodDesc*>(info->ftn), &namespaceOrClassName, &methodName, &methodSignature); ETW::MethodLog::MethodJitting(reinterpret_cast<MethodDesc*>(info->ftn), NULL, &namespaceOrClassName, &methodName, &methodSignature);
CorJitResult ret = jitMgr->m_jit->compileMethod(comp, info, flags, nativeEntry, nativeSizeOfCode); CorJitResult ret = jitMgr->m_jit->compileMethod(comp, info, flags, nativeEntry, nativeSizeOfCode);

View file

@ -1819,7 +1819,7 @@ private:
PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0); PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0);
PCODE JitCompileCode(PrepareCodeConfig* pConfig); PCODE JitCompileCode(PrepareCodeConfig* pConfig);
PCODE JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry); PCODE JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry);
PCODE JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEntry* pLockEntry, ULONG* pSizeOfCode); PCODE JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pilHeader, JitListLockEntry* pLockEntry, ULONG* pSizeOfCode);
public: public:
bool TryGenerateUnsafeAccessor(DynamicResolver** resolver, COR_ILMETHOD_DECODER** methodILDecoder); bool TryGenerateUnsafeAccessor(DynamicResolver** resolver, COR_ILMETHOD_DECODER** methodILDecoder);

View file

@ -709,6 +709,53 @@ PCODE MethodDesc::JitCompileCode(PrepareCodeConfig* pConfig)
} }
} }
namespace
{
COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
_ASSERTE(!pMD->IsNoMetadata());
_ASSERTE(pConfig != NULL);
_ASSERTE(pDecoderMemory != NULL);
COR_ILMETHOD_DECODER* pHeader = NULL;
COR_ILMETHOD* ilHeader = pConfig->GetILHeader();
if (ilHeader == NULL)
return NULL;
COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::FORMAT_ERROR;
{
// Decoder ctor can AV on a malformed method header
AVInRuntimeImplOkayHolder AVOkay;
pHeader = new (pDecoderMemory) COR_ILMETHOD_DECODER(ilHeader, pMD->GetMDImport(), &status);
}
if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
return pHeader;
}
COR_ILMETHOD_DECODER* GetAndVerifyILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
if (pMD->IsIL())
{
return GetAndVerifyMetadataILHeader(pMD, pConfig, pIlDecoderMemory);
}
else if (pMD->IsILStub())
{
ILStubResolver* pResolver = pMD->AsDynamicMethodDesc()->GetILStubResolver();
return pResolver->GetILHeader();
}
_ASSERTE(pMD->IsNoMetadata());
return NULL;
}
}
PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry) PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry)
{ {
STANDARD_VM_CONTRACT; STANDARD_VM_CONTRACT;
@ -759,11 +806,18 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
} }
#endif // PROFILING_SUPPORTED #endif // PROFILING_SUPPORTED
// The profiler may have changed the code on the callback. Need to
// pick up the new code.
//
// (don't want this for OSR, need to see how it works)
COR_ILMETHOD_DECODER ilDecoderTemp;
COR_ILMETHOD_DECODER* pilHeader = GetAndVerifyILHeader(this, pConfig, &ilDecoderTemp);
if (!ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context, if (!ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context,
TRACE_LEVEL_VERBOSE, TRACE_LEVEL_VERBOSE,
CLR_JIT_KEYWORD)) CLR_JIT_KEYWORD))
{ {
pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode); pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);
} }
else else
{ {
@ -778,12 +832,13 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
// a small stub of native code but no native-IL mapping. // a small stub of native code but no native-IL mapping.
#ifndef FEATURE_INTERPRETER #ifndef FEATURE_INTERPRETER
ETW::MethodLog::MethodJitting(this, ETW::MethodLog::MethodJitting(this,
pilHeader,
&namespaceOrClassName, &namespaceOrClassName,
&methodName, &methodName,
&methodSignature); &methodSignature);
#endif #endif
pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode); pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);
// Interpretted methods skip this notification // Interpretted methods skip this notification
#ifdef FEATURE_INTERPRETER #ifdef FEATURE_INTERPRETER
@ -869,66 +924,11 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
return pCode; return pCode;
} }
namespace PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pilHeader, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
{
COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
_ASSERTE(!pMD->IsNoMetadata());
_ASSERTE(pConfig != NULL);
_ASSERTE(pDecoderMemory != NULL);
COR_ILMETHOD_DECODER* pHeader = NULL;
COR_ILMETHOD* ilHeader = pConfig->GetILHeader();
if (ilHeader == NULL)
return NULL;
COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::FORMAT_ERROR;
{
// Decoder ctor can AV on a malformed method header
AVInRuntimeImplOkayHolder AVOkay;
pHeader = new (pDecoderMemory) COR_ILMETHOD_DECODER(ilHeader, pMD->GetMDImport(), &status);
}
if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
return pHeader;
}
COR_ILMETHOD_DECODER* GetAndVerifyILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
if (pMD->IsIL())
{
return GetAndVerifyMetadataILHeader(pMD, pConfig, pIlDecoderMemory);
}
else if (pMD->IsILStub())
{
ILStubResolver* pResolver = pMD->AsDynamicMethodDesc()->GetILStubResolver();
return pResolver->GetILHeader();
}
_ASSERTE(pMD->IsNoMetadata());
return NULL;
}
}
PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
{ {
STANDARD_VM_CONTRACT; STANDARD_VM_CONTRACT;
PCODE pCode = NULL; PCODE pCode = NULL;
// The profiler may have changed the code on the callback. Need to
// pick up the new code.
//
// (don't want this for OSR, need to see how it works)
COR_ILMETHOD_DECODER ilDecoderTemp;
COR_ILMETHOD_DECODER* pilHeader = GetAndVerifyILHeader(this, pConfig, &ilDecoderTemp);
CORJIT_FLAGS jitFlags; CORJIT_FLAGS jitFlags;
PCODE pOtherCode = NULL; PCODE pOtherCode = NULL;

View file

@ -286,7 +286,7 @@ bool AddVersionResilientHashCodeForInstruction(ILInstructionParser *parser, xxHa
hash->Add(varValue); hash->Add(varValue);
break; break;
} }
case InlineVar: // 2 byte value which is token change resilient case InlineVar: // 2 byte value which is token change resilient
{ {
uint16_t varValue; uint16_t varValue;
@ -388,6 +388,12 @@ bool GetVersionResilientILCodeHashCode(MethodDesc *pMD, int* hashCode, unsigned*
initLocals = (options & CORINFO_OPT_INIT_LOCALS) == CORINFO_OPT_INIT_LOCALS; initLocals = (options & CORINFO_OPT_INIT_LOCALS) == CORINFO_OPT_INIT_LOCALS;
} }
else if (!pMD->HasILHeader())
{
// Dynamically generated IL methods like UnsafeAccessors may not have
// an IL header.
return false;
}
else else
{ {
COR_ILMETHOD_DECODER header(pMD->GetILHeader(TRUE), pMD->GetMDImport(), NULL); COR_ILMETHOD_DECODER header(pMD->GetILHeader(TRUE), pMD->GetMDImport(), NULL);

View file

@ -63,9 +63,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Loader/binding/tracing/BinderTracingTest.Basic/*"> <ExcludeList Include="$(XunitTestBinBase)/Loader/binding/tracing/BinderTracingTest.Basic/*">
<Issue>https://github.com/dotnet/runtime/issues/57786</Issue> <Issue>https://github.com/dotnet/runtime/issues/57786</Issue>
</ExcludeList> </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/binding/tracing/BinderTracingTest.ResolutionFlow/*">
<Issue>https://github.com/dotnet/runtime/issues/90580</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/MonoAPI/**"> <ExcludeList Include="$(XunitTestBinBase)/Interop/MonoAPI/**">
<Issue>CoreCLR does not implement the mono embedding API</Issue> <Issue>CoreCLR does not implement the mono embedding API</Issue>
</ExcludeList> </ExcludeList>