1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 09:34:49 +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
// (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;
*count = 0;
return E_FAIL;
}
COR_ILMETHOD_DECODER methodDecoder(m_methodDesc->GetILHeader());
COR_ILMETHOD_DECODER methodDecoder(ilHeader);
mdSignature localSig = methodDecoder.GetLocalVarSigTok() ?
methodDecoder.GetLocalVarSigTok() : mdSignatureNil;
if (localSig == mdSignatureNil)

View file

@ -905,7 +905,7 @@ namespace ETW
BOOL fSendRichDebugInfoEvent,
BOOL fGetCodeIds);
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 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);
@ -938,7 +938,7 @@ namespace ETW
static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc);
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 SendMethodDetailsEvent(MethodDesc *pMethodDesc);
static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set);
@ -952,7 +952,7 @@ namespace ETW
public:
static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {};
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 StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {};
static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {};

View file

@ -12,9 +12,9 @@
#include "switches.h"
#include "stresslog.h"
#include "clrhost.h"
#include "ex.h"
#define DONOT_DEFINE_ETW_CALLBACK
#include "eventtracebase.h"
#include "ex.h"
#if !defined(STRESS_LOG_READONLY)
#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 */
/*************************************************/
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 {
NOTHROW;
@ -3570,7 +3570,7 @@ VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr
CLR_JIT_KEYWORD))
{
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);
}
@ -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*/
/*****************************************************************/
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 {
THROWS;
@ -4566,15 +4571,13 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n
ulMethodToken = (ULONG)0;
}
else
ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();
if(pMethodDesc->IsIL())
{
COR_ILMETHOD_DECODER::DecoderStatus decoderstatus = COR_ILMETHOD_DECODER::FORMAT_ERROR;
COR_ILMETHOD_DECODER ILHeader(pMethodDesc->GetILHeader(), pMethodDesc->GetMDImport(), &decoderstatus);
ulMethodILSize = (ULONG)ILHeader.GetCodeSize();
ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();
}
if (methodDecoder != NULL)
ulMethodILSize = methodDecoder->GetCodeSize();
SString tNamespace, tMethodName, tMethodSignature;
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;
// 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);

View file

@ -1819,7 +1819,7 @@ private:
PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0);
PCODE JitCompileCode(PrepareCodeConfig* pConfig);
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:
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)
{
STANDARD_VM_CONTRACT;
@ -759,11 +806,18 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
}
#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,
TRACE_LEVEL_VERBOSE,
CLR_JIT_KEYWORD))
{
pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode);
pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);
}
else
{
@ -778,12 +832,13 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
// a small stub of native code but no native-IL mapping.
#ifndef FEATURE_INTERPRETER
ETW::MethodLog::MethodJitting(this,
pilHeader,
&namespaceOrClassName,
&methodName,
&methodSignature);
#endif
pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode);
pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);
// Interpretted methods skip this notification
#ifdef FEATURE_INTERPRETER
@ -869,66 +924,11 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
return pCode;
}
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::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pilHeader, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
{
STANDARD_VM_CONTRACT;
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;
PCODE pOtherCode = NULL;

View file

@ -286,7 +286,7 @@ bool AddVersionResilientHashCodeForInstruction(ILInstructionParser *parser, xxHa
hash->Add(varValue);
break;
}
case InlineVar: // 2 byte value which is token change resilient
{
uint16_t varValue;
@ -388,6 +388,12 @@ bool GetVersionResilientILCodeHashCode(MethodDesc *pMD, int* hashCode, unsigned*
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
{
COR_ILMETHOD_DECODER header(pMD->GetILHeader(TRUE), pMD->GetMDImport(), NULL);

View file

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