summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inc/corinfo.h22
-rw-r--r--src/jit/compiler.h10
-rw-r--r--src/jit/ee_il_dll.cpp109
-rw-r--r--src/jit/importer.cpp96
-rw-r--r--src/vm/jitinterface.cpp118
-rw-r--r--src/vm/jitinterface.h4
-rw-r--r--src/zap/zapinfo.cpp6
-rw-r--r--src/zap/zapinfo.h1
8 files changed, 273 insertions, 93 deletions
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index fb839996c0..8978b951a5 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -231,11 +231,11 @@ TODO: Talk about initializing strutures before use
#if COR_JIT_EE_VERSION > 460
// Update this one
-SELECTANY const GUID JITEEVersionIdentifier = { /* 27626524-7315-4ed0-b74e-a0e4579883bb */
- 0x27626524,
- 0x7315,
- 0x4ed0,
- { 0xb7, 0x4e, 0xa0, 0xe4, 0x57, 0x98, 0x83, 0xbb }
+SELECTANY const GUID JITEEVersionIdentifier = { /* 8c8e61ca-2b88-4bc5-b03f-d390acdc7fc3 */
+ 0x8c8e61ca,
+ 0x2b88,
+ 0x4bc5,
+ { 0xb0, 0x3f, 0xd3, 0x90, 0xac, 0xdc, 0x7f, 0xc3 }
};
#else
@@ -2153,9 +2153,19 @@ public:
//
/**********************************************************************************/
- // Resolve metadata token into runtime method handles.
+ // Resolve metadata token into runtime method handles. This function may not
+ // return normally (e.g. it may throw) if it encounters invalid metadata or other
+ // failures during token resolution.
virtual void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0;
+#if COR_JIT_EE_VERSION > 460
+ // Attempt to resolve a metadata token into a runtime method handle. Returns true
+ // if resolution succeeded and false otherwise (e.g. if it encounters invalid metadata
+ // during token reoslution). This method should be used instead of `resolveToken` in
+ // situations that need to be resilient to invalid metadata.
+ virtual bool tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0;
+#endif
+
// Signature information about the call sig
virtual void findSig (
CORINFO_MODULE_HANDLE module, /* IN */
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 2c094a33c8..4b6ee0ee27 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -59,6 +59,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include "simd.h"
+// This is only used locally in the JIT to indicate that
+// a verification block should be inserted
+#define SEH_VERIFICATION_EXCEPTION 0xe0564552 // VER
+
/*****************************************************************************
* Forward declarations
*/
@@ -6450,6 +6454,8 @@ public :
/*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr);
#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
+ bool eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken);
+
// Utility functions
#if defined(DEBUG)
@@ -8373,10 +8379,6 @@ public:
// be used to call a member function.
BOOL verTrackObjCtorInitState;
- // Argument of ICorJitInfo::resolveToken. It is used to determine the handling
- // of ICorJitInfo::resolveToken failure during verification.
- CORINFO_RESOLVED_TOKEN * verResolveTokenInProgress;
-
void verInitBBEntryState(BasicBlock* block,
EntryState* currentState);
diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp
index d28335cde6..8193b1573b 100644
--- a/src/jit/ee_il_dll.cpp
+++ b/src/jit/ee_il_dll.cpp
@@ -18,6 +18,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#pragma hdrstop
#endif
#include "emit.h"
+#include "corexcep.h"
/*****************************************************************************/
@@ -1127,6 +1128,114 @@ void Compiler::eeGetSystemVAmd64PassStructInRegisterDescriptor(/*IN*/ CORINFO_C
#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
+#if COR_JIT_EE_VERSION <= 460
+
+// Validate the token to determine whether to turn the bad image format exception into
+// verification failure (for backward compatibility)
+static bool isValidTokenForTryResolveToken(ICorJitInfo* corInfo, CORINFO_RESOLVED_TOKEN* resolvedToken)
+{
+ if (!corInfo->isValidToken(resolvedToken->tokenScope, resolvedToken->token))
+ return false;
+
+ CorInfoTokenKind tokenType = resolvedToken->tokenType;
+ switch (TypeFromToken(resolvedToken->token))
+ {
+ case mdtModuleRef:
+ case mdtTypeDef:
+ case mdtTypeRef:
+ case mdtTypeSpec:
+ if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
+ return false;
+ break;
+
+ case mdtMethodDef:
+ case mdtMethodSpec:
+ if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
+ return false;
+ break;
+
+ case mdtFieldDef:
+ if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
+ return false;
+ break;
+
+ case mdtMemberRef:
+ if ((tokenType & (CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field)) == 0)
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+// This type encapsulates the information necessary for `TryResolveTokenFilter` and
+// `eeTryResolveToken` below.
+struct TryResolveTokenFilterParam
+{
+ ICorJitInfo* m_corInfo;
+ CORINFO_RESOLVED_TOKEN* m_resolvedToken;
+ EXCEPTION_POINTERS m_exceptionPointers;
+ bool m_success;
+};
+
+LONG TryResolveTokenFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam)
+{
+ assert(exceptionPointers->ExceptionRecord->ExceptionCode != SEH_VERIFICATION_EXCEPTION);
+
+ // Backward compatibility: Convert bad image format exceptions thrown by the EE while resolving token to verification exceptions
+ // if we are verifying. Verification exceptions will cause the JIT of the basic block to fail, but the JITing of the whole method
+ // is still going to succeed. This is done for backward compatibility only. Ideally, we would always treat bad tokens in the IL
+ // stream as fatal errors.
+ if (exceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
+ {
+ auto* param = reinterpret_cast<TryResolveTokenFilterParam*>(theParam);
+ if (!isValidTokenForTryResolveToken(param->m_corInfo, param->m_resolvedToken))
+ {
+ param->m_exceptionPointers = *exceptionPointers;
+ return param->m_corInfo->FilterException(exceptionPointers);
+ }
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
+{
+ TryResolveTokenFilterParam param;
+ param.m_corInfo = info.compCompHnd;
+ param.m_resolvedToken = resolvedToken;
+ param.m_success = true;
+
+ PAL_TRY(TryResolveTokenFilterParam*, pParam, &param)
+ {
+ pParam->m_corInfo->resolveToken(pParam->m_resolvedToken);
+ }
+ PAL_EXCEPT_FILTER(TryResolveTokenFilter)
+ {
+ if (param.m_exceptionPointers.ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
+ {
+ param.m_corInfo->HandleException(&param.m_exceptionPointers);
+ }
+
+ param.m_success = false;
+ }
+ PAL_ENDTRY
+
+ return param.m_success;
+}
+
+#else // CORJIT_EE_VER <= 460
+
+bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
+{
+ return info.compCompHnd->tryResolveToken(resolvedToken);
+}
+
+#endif // CORJIT_EE_VER > 460
+
/*****************************************************************************
*
* Utility functions
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index dea7a6ced3..03957eec0c 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -20,10 +20,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include "corexcep.h"
-// This is only used locally in the JIT to indicate that
-// a verification block should be inserted
-#define SEH_VERIFICATION_EXCEPTION 0xe0564552 // VER
-
#define Verify(cond, msg) \
do { \
if (!(cond)) { \
@@ -267,9 +263,14 @@ void Compiler::impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN * pResol
pResolvedToken->token = getU4LittleEndian(addr);
pResolvedToken->tokenType = kind;
- verResolveTokenInProgress = pResolvedToken;
- info.compCompHnd->resolveToken(pResolvedToken);
- verResolveTokenInProgress = NULL;
+ if (!tiVerificationNeeded)
+ {
+ info.compCompHnd->resolveToken(pResolvedToken);
+ }
+ else
+ {
+ Verify(eeTryResolveToken(pResolvedToken), "Token resolution failed");
+ }
}
/*****************************************************************************
@@ -14005,80 +14006,11 @@ void Compiler::impReimportMarkSuccessors(BasicBlock * block)
* from it).
*/
-struct FilterVerificationExceptionsParam
-{
- Compiler *pThis;
- BasicBlock *block;
- EXCEPTION_POINTERS exceptionPointers;
-};
-
-//
-// Validate the token to determine whether to turn the bad image format exception into
-// verification failure (for backward compatibility)
-//
-static bool verIsValidToken(COMP_HANDLE compCompHnd, CORINFO_RESOLVED_TOKEN * pResolvedToken)
-{
- if (!compCompHnd->isValidToken(pResolvedToken->tokenScope, pResolvedToken->token))
- return FALSE;
-
- CorInfoTokenKind tokenType = pResolvedToken->tokenType;
-
- switch (TypeFromToken(pResolvedToken->token))
- {
- case mdtModuleRef:
- case mdtTypeDef:
- case mdtTypeRef:
- case mdtTypeSpec:
- if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
- return FALSE;
- break;
-
- case mdtMethodDef:
- case mdtMethodSpec:
- if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
- return FALSE;
- break;
-
- case mdtFieldDef:
- if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
- return FALSE;
- break;
-
- case mdtMemberRef:
- if ((tokenType & (CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field)) == 0)
- return FALSE;
- break;
-
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
LONG FilterVerificationExceptions(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam)
{
- FilterVerificationExceptionsParam *pFVEParam =
- (FilterVerificationExceptionsParam *)lpvParam;
- pFVEParam->exceptionPointers = *pExceptionPointers;
-
if (pExceptionPointers->ExceptionRecord->ExceptionCode == SEH_VERIFICATION_EXCEPTION)
- return EXCEPTION_EXECUTE_HANDLER;
-
- // Backward compability: Convert bad image format exceptions thrown by the EE while resolving token to verification exceptions
- // if we are verifying. Verification exceptions will cause the JIT of the basic block to fail, but the JITing of the whole method
- // is still going to succeed. This is done for backward compatibility only. Ideally, we would always treat bad tokens in the IL
- // stream as fatal errors.
- if (pExceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
{
- Compiler * pThis = pFVEParam->pThis;
- if (pThis->tiVerificationNeeded && pThis->verResolveTokenInProgress)
- {
- if (!verIsValidToken(pThis->info.compCompHnd, pThis->verResolveTokenInProgress))
- {
- return pThis->info.compCompHnd->FilterException(pExceptionPointers);
- }
- }
+ return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
@@ -14262,13 +14194,16 @@ void Compiler::impImportBlock(BasicBlock *block)
/* Now walk the code and import the IL into GenTrees */
+ struct FilterVerificationExceptionsParam
+ {
+ Compiler *pThis;
+ BasicBlock *block;
+ };
FilterVerificationExceptionsParam param;
param.pThis = this;
param.block = block;
- verResolveTokenInProgress = NULL;
-
PAL_TRY(FilterVerificationExceptionsParam *, pParam, &param)
{
/* @VERIFICATION : For now, the only state propagation from try
@@ -14314,9 +14249,6 @@ void Compiler::impImportBlock(BasicBlock *block)
}
PAL_EXCEPT_FILTER(FilterVerificationExceptions)
{
- if (param.exceptionPointers.ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
- param.pThis->info.compCompHnd->HandleException(&param.exceptionPointers);
-
verHandleVerificationFailure(block DEBUGARG(false));
}
PAL_ENDTRY
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index cf0e456140..e29d6aa671 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -1292,6 +1292,116 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken
}
/*********************************************************************/
+struct TryResolveTokenFilterParam
+{
+ CEEInfo* m_this;
+ CORINFO_RESOLVED_TOKEN* m_resolvedToken;
+ EXCEPTION_POINTERS m_exceptionPointers;
+ bool m_success;
+};
+
+bool isValidTokenForTryResolveToken(CEEInfo* info, CORINFO_RESOLVED_TOKEN* resolvedToken)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ if (!info->isValidToken(resolvedToken->tokenScope, resolvedToken->token))
+ {
+ return false;
+ }
+
+ CorInfoTokenKind tokenType = resolvedToken->tokenType;
+ switch (TypeFromToken(resolvedToken->token))
+ {
+ case mdtModuleRef:
+ case mdtTypeDef:
+ case mdtTypeRef:
+ case mdtTypeSpec:
+ if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
+ return false;
+ break;
+
+ case mdtMethodDef:
+ case mdtMethodSpec:
+ if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
+ return false;
+ break;
+
+ case mdtFieldDef:
+ if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
+ return false;
+ break;
+
+ case mdtMemberRef:
+ if ((tokenType & (CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field)) == 0)
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+LONG EEFilterException(struct _EXCEPTION_POINTERS* exceptionPointers, void* unused);
+
+LONG TryResolveTokenFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ // Backward compatibility: Convert bad image format exceptions thrown while resolving tokens
+ // to simple true/false successes. This is done for backward compatibility only. Ideally,
+ // we would always treat bad tokens in the IL stream as fatal errors.
+ if (exceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
+ {
+ auto* param = reinterpret_cast<TryResolveTokenFilterParam*>(theParam);
+ if (!isValidTokenForTryResolveToken(param->m_this, param->m_resolvedToken))
+ {
+ param->m_exceptionPointers = *exceptionPointers;
+ return EEFilterException(exceptionPointers, nullptr);
+ }
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+bool CEEInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
+{
+ // No dynamic contract here because SEH is used
+ STATIC_CONTRACT_SO_TOLERANT;
+ STATIC_CONTRACT_THROWS;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_MODE_PREEMPTIVE;
+
+ TryResolveTokenFilterParam param;
+ param.m_this = this;
+ param.m_resolvedToken = resolvedToken;
+ param.m_success = true;
+
+ PAL_TRY(TryResolveTokenFilterParam*, pParam, &param)
+ {
+ pParam->m_this->resolveToken(pParam->m_resolvedToken);
+ }
+ PAL_EXCEPT_FILTER(TryResolveTokenFilter)
+ {
+ if (param.m_exceptionPointers.ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
+ {
+ HandleException(&param.m_exceptionPointers);
+ }
+
+ param.m_success = false;
+ }
+ PAL_ENDTRY
+
+ return param.m_success;
+}
+
+/*********************************************************************/
// We have a few frequently used constants in mscorlib that are defined as
// readonly static fields for historic reasons. Check for them here and
// allow them to be treated as actual constants by the JIT.
@@ -9655,7 +9765,7 @@ ULONG CEEInfo::GetErrorMessage(__inout_ecount(bufferLength) LPWSTR buffer, ULONG
// It is fatal to throw an exception while running a SEH filter clause
// so our contract is NOTHROW, NOTRIGGER.
//
-int CEEInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
+LONG EEFilterException(struct _EXCEPTION_POINTERS *pExceptionPointers, void *unused)
{
CONTRACTL {
SO_TOLERANT;
@@ -9743,6 +9853,12 @@ int CEEInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
return result;
}
+int CEEInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
+{
+ WRAPPER_NO_CONTRACT;
+ return EEFilterException(pExceptionPointers, nullptr);
+}
+
// This code is called if FilterException chose to handle the exception.
void CEEInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
{
diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h
index 6780fe0911..e31a07d17b 100644
--- a/src/vm/jitinterface.h
+++ b/src/vm/jitinterface.h
@@ -642,6 +642,10 @@ public:
// Resolve metadata token into runtime method handles.
void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken);
+ // Attempt to resolve a metadata token into a runtime method handle. Returns true
+ // if resolution succeeded and false otherwise.
+ bool tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken);
+
void getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
CORINFO_METHOD_HANDLE callerHandle,
CORINFO_ACCESS_FLAGS flags,
diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp
index 345a920902..4d2d7f8636 100644
--- a/src/zap/zapinfo.cpp
+++ b/src/zap/zapinfo.cpp
@@ -3455,6 +3455,12 @@ void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
}
//-----------------------------------------------------------------------------
+bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
+{
+ return m_pEEJitInfo->tryResolveToken(pResolvedToken);
+}
+
+//-----------------------------------------------------------------------------
void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope,
unsigned sigTOK,
CORINFO_CONTEXT_HANDLE tokenContext,
diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h
index 5fe3dcb76e..7fc93820d2 100644
--- a/src/zap/zapinfo.h
+++ b/src/zap/zapinfo.h
@@ -587,6 +587,7 @@ public:
// ICorModuleInfo
void resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken);
+ bool tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken);
void findSig(CORINFO_MODULE_HANDLE module, unsigned sigTOK,
CORINFO_CONTEXT_HANDLE context,