diff --git a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp index b051ffdb32a299..9b918353c4b60a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp @@ -9,28 +9,33 @@ void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode) { + if (BreakOnException()) + __debugbreak(); + RaiseException(exceptionCode, 0, 0, nullptr); } // Allocating memory here seems moderately dangerous: we'll probably leak like a sieve... -void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode, va_list args, const char* message) +void MSC_ONLY(__declspec(noreturn)) ThrowSpmiException(DWORD exceptionCode, va_list args, const char* message) { + assert(IsSuperPMIException(exceptionCode)); + char* buffer = new char[8192]; - ULONG_PTR* ptr = new ULONG_PTR(); - *ptr = (ULONG_PTR)buffer; _vsnprintf_s(buffer, 8192, 8191, message, args); if (BreakOnException()) __debugbreak(); - RaiseException(exceptionCode, 0, 1, ptr); + ULONG_PTR exArgs[1]; + exArgs[0] = (ULONG_PTR)buffer; + RaiseException(exceptionCode, 0, ArrLen(exArgs), exArgs); } -void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode, const char* msg, ...) +void MSC_ONLY(__declspec(noreturn)) ThrowSpmiException(DWORD exceptionCode, const char* msg, ...) { va_list ap; va_start(ap, msg); - ThrowException(exceptionCode, ap, msg); + ThrowSpmiException(exceptionCode, ap, msg); } SpmiException::SpmiException(FilterSuperPMIExceptionsParam_CaptureException* e) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h index 0d9aca331fb494..978a40c50a68ed 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h @@ -8,6 +8,7 @@ #define _ErrorHandling #include "logging.h" +#include "corexcep.h" // EXCEPTIONCODE_DebugBreakorAV is just the base exception number; calls to DebugBreakorAV() // pass a unique number to add to this. EXCEPTIONCODE_DebugBreakorAV_MAX is the maximum number @@ -20,10 +21,11 @@ #define EXCEPTIONCODE_CALLUTILS 0xe0426000 #define EXCEPTIONCODE_TYPEUTILS 0xe0427000 #define EXCEPTIONCODE_ASSERT 0xe0440000 +#define EXCEPTIONCODE_COMPLUS EXCEPTION_COMPLUS // RaiseException wrappers void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode); -void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode, const char* message, ...); +void MSC_ONLY(__declspec(noreturn)) ThrowSpmiException(DWORD exceptionCode, const char* message, ...); // Assert stuff #define AssertCodeMsg(expr, exCode, msg, ...) \ diff --git a/src/coreclr/tools/superpmi/superpmi-shared/logging.h b/src/coreclr/tools/superpmi/superpmi-shared/logging.h index b8afe63e312c39..957da040885eaf 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/logging.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/logging.h @@ -30,7 +30,7 @@ do \ { \ Logger::LogExceptionMessage(__FUNCTION__, __FILE__, __LINE__, exCode, msg, __VA_ARGS__); \ - ThrowException(exCode, msg, __VA_ARGS__); \ + ThrowSpmiException(exCode, msg, __VA_ARGS__); \ } while (0) // These are specified as flags so subsets of the logging functionality can be enabled/disabled at once diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp index c2b50459b5c43b..426d9ccd6c0f1b 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp @@ -414,7 +414,7 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i pParam->pThis->mc->cr->recAllocMemCapture(); pParam->pThis->mc->cr->recAllocGCInfoCapture(); - pParam->pThis->mc->cr->recMessageLog("Successful Compile"); + pParam->pThis->mc->cr->recMessageLog(jitResult == CORJIT_OK ? "Successful Compile" : "Successful Compile (BADCODE)"); pParam->metrics->NumCodeBytes += NCodeSizeBlock; } @@ -435,6 +435,22 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i e.DeleteMessage(); param.result = RESULT_MISSING; } + else if (e.GetCode() == EXCEPTIONCODE_COMPLUS) + { + // We assume that managed exceptions are never JIT bugs and were + // thrown by the EE during recording. Various EE APIs can throw + // managed exceptions and replay will faithfully rethrow these. The + // JIT itself will sometimes catch them (e.g. during inlining), but + // if they make it out of the JIT then we assume that they are not + // JIT bugs. The typical scenario is something like + // MissingFieldException thrown from resolveToken. + + // Call these methods to capture that no code/GC info was generated. + mc->cr->recAllocMemCapture(); + mc->cr->recAllocGCInfoCapture(); + + mc->cr->recMessageLog("Successful Compile (EE API exception)"); + } else { e.ShowAndDeleteMessage();