summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shim-simple
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/superpmi/superpmi-shim-simple')
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/.gitmirror1
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt72
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.cpp58
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.h20
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp59
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h24
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp1726
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h24
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.cpp72
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.h108
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.cpp158
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.h150
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp40
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/jithost.h22
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp217
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def5
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h13
17 files changed, 2769 insertions, 0 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/.gitmirror b/src/ToolBox/superpmi/superpmi-shim-simple/.gitmirror
new file mode 100644
index 0000000000..f507630f94
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/.gitmirror
@@ -0,0 +1 @@
+Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt b/src/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt
new file mode 100644
index 0000000000..354e46d097
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt
@@ -0,0 +1,72 @@
+project(superpmi-shim-simple)
+
+remove_definitions(-DUNICODE)
+remove_definitions(-D_UNICODE)
+
+add_definitions(-DFEATURE_NO_HOST)
+add_definitions(-DSELF_NO_HOST)
+
+if(WIN32)
+ #use static crt
+ add_definitions(-MT)
+endif(WIN32)
+
+include_directories(.)
+include_directories(../superpmi-shared)
+
+set(SUPERPMI_SHIM_SIMPLE_SOURCES
+ coreclrcallbacks.cpp
+ jithost.cpp
+ icorjitcompiler.cpp
+ icorjitinfo.cpp
+ ieememorymanager.cpp
+ iexecutionengine.cpp
+ superpmi-shim-simple.cpp
+ ../superpmi-shared/callutils.cpp
+ ../superpmi-shared/compileresult.cpp
+ ../superpmi-shared/errorhandling.cpp
+ ../superpmi-shared/logging.cpp
+ ../superpmi-shared/mclist.cpp
+ ../superpmi-shared/methodcontext.cpp
+ ../superpmi-shared/methodcontextreader.cpp
+ ../superpmi-shared/simpletimer.cpp
+ ../superpmi-shared/spmiutil.cpp
+ ../superpmi-shared/tocfile.cpp
+ ../superpmi-shared/typeutils.cpp
+)
+
+add_precompiled_header(
+ standardpch.h
+ ../superpmi-shared/standardpch.cpp
+ SUPERPMI_SHIM_SIMPLE_SOURCES
+)
+
+if (WIN32)
+ preprocess_def_file(${CMAKE_CURRENT_SOURCE_DIR}/superpmi-shim-simple.def ${CMAKE_CURRENT_BINARY_DIR}/superpmi-shim-simple.def)
+
+ list(APPEND SUPERPMI_SHIM_SIMPLE_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/superpmi-shim-simple.def)
+endif (WIN32)
+
+add_library(superpmi-shim-simple
+ SHARED
+ ${SUPERPMI_SHIM_SIMPLE_SOURCES}
+)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ target_link_libraries(superpmi-shim-simple
+ utilcodestaticnohost
+ mscorrc_debug
+ coreclrpal
+ palrt
+ )
+else()
+ target_link_libraries(superpmi-shim-simple
+ advapi32.lib
+ ${STATIC_MT_CRT_LIB}
+ ${STATIC_MT_CPP_LIB}
+ )
+
+ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/superpmi-shim-simple.pdb DESTINATION PDB)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+install (TARGETS superpmi-shim-simple DESTINATION .)
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.cpp
new file mode 100644
index 0000000000..cf35748672
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "coreclrcallbacks.h"
+#include "iexecutionengine.h"
+
+typedef LPVOID (__stdcall * pfnEEHeapAllocInProcessHeap)(DWORD dwFlags, SIZE_T dwBytes);
+typedef BOOL (__stdcall * pfnEEHeapFreeInProcessHeap)(DWORD dwFlags, LPVOID lpMem);
+
+CoreClrCallbacks *original_CoreClrCallbacks = nullptr;
+pfnEEHeapAllocInProcessHeap original_EEHeapAllocInProcessHeap = nullptr;
+pfnEEHeapFreeInProcessHeap original_EEHeapFreeInProcessHeap = nullptr;
+
+IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+{
+ interceptor_IEE *iee = new interceptor_IEE();
+ iee->original_IEE = original_CoreClrCallbacks->m_pfnIEE();
+ return iee;
+}
+
+/*#pragma warning( suppress :4996 ) //deprecated
+HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength)
+{
+ DebugBreakorAV(131);
+ return 0;
+}
+*/
+
+LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap (DWORD dwFlags, SIZE_T dwBytes)
+{
+ return original_EEHeapAllocInProcessHeap(dwFlags, dwBytes);
+}
+
+BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap (DWORD dwFlags, LPVOID lpMem)
+{
+ return original_EEHeapFreeInProcessHeap(dwFlags, lpMem);
+}
+
+void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName)
+{
+ if(strcmp(functionName, "EEHeapAllocInProcessHeap")==0)
+ {
+ original_EEHeapAllocInProcessHeap =
+ (pfnEEHeapAllocInProcessHeap)original_CoreClrCallbacks->m_pfnGetCLRFunction("EEHeapAllocInProcessHeap");
+ return (void*)EEHeapAllocInProcessHeap;
+ }
+ if(strcmp(functionName, "EEHeapFreeInProcessHeap")==0)
+ {
+ original_EEHeapFreeInProcessHeap =
+ (pfnEEHeapFreeInProcessHeap)original_CoreClrCallbacks->m_pfnGetCLRFunction("EEHeapFreeInProcessHeap");
+ return (void*)EEHeapFreeInProcessHeap;
+ }
+ return original_CoreClrCallbacks->m_pfnGetCLRFunction(functionName);
+}
+
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.h b/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.h
new file mode 100644
index 0000000000..2e3a673f57
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _CoreClrCallbacks
+#define _CoreClrCallbacks
+
+#include "runtimedetails.h"
+
+IExecutionEngine* STDMETHODCALLTYPE IEE_t();
+HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
+LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap (DWORD dwFlags, SIZE_T dwBytes);
+BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap (DWORD dwFlags, LPVOID lpMem);
+void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName);
+
+// Added to allow us to persist a copy of the original callbacks
+extern CoreClrCallbacks *original_CoreClrCallbacks;
+
+#endif \ No newline at end of file
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp
new file mode 100644
index 0000000000..f6fceb2029
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "icorjitcompiler.h"
+#include "icorjitinfo.h"
+
+interceptor_IEEMM *current_IEEMM = nullptr; //we want this to live beyond the scope of a single compileMethodCall
+
+CorJitResult __stdcall interceptor_ICJC::compileMethod (
+ ICorJitInfo *comp, /* IN */
+ struct CORINFO_METHOD_INFO *info, /* IN */
+ unsigned /* code:CorJitFlag */ flags, /* IN */
+ BYTE **nativeEntry, /* OUT */
+ ULONG *nativeSizeOfCode /* OUT */
+ )
+{
+ interceptor_ICJI our_ICorJitInfo;
+ our_ICorJitInfo.original_ICorJitInfo = comp;
+
+ if(current_IEEMM == nullptr)
+ current_IEEMM = new interceptor_IEEMM();
+
+ CorJitResult temp = original_ICorJitCompiler->compileMethod(&our_ICorJitInfo, info, flags, nativeEntry, nativeSizeOfCode);
+
+ return temp;
+}
+
+void interceptor_ICJC::clearCache()
+{
+ original_ICorJitCompiler->clearCache();
+}
+
+BOOL interceptor_ICJC::isCacheCleanupRequired()
+{
+ return original_ICorJitCompiler->isCacheCleanupRequired();
+}
+
+void interceptor_ICJC::ProcessShutdownWork(ICorStaticInfo* info)
+{
+ original_ICorJitCompiler->ProcessShutdownWork(info);
+}
+
+void interceptor_ICJC::getVersionIdentifier(GUID* versionIdentifier /* OUT */)
+{
+ original_ICorJitCompiler->getVersionIdentifier(versionIdentifier);
+}
+
+unsigned interceptor_ICJC::getMaxIntrinsicSIMDVectorLength(DWORD cpuCompileFlags)
+{
+ return original_ICorJitCompiler->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags);
+}
+
+void interceptor_ICJC::setRealJit(ICorJitCompiler* realJitCompiler)
+{
+ original_ICorJitCompiler->setRealJit(realJitCompiler);
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h
new file mode 100644
index 0000000000..a5eda6aa19
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _ICorJitCompiler
+#define _ICorJitCompiler
+
+#include "runtimedetails.h"
+#include "ieememorymanager.h"
+
+class interceptor_ICJC : public ICorJitCompiler
+{
+
+#include "icorjitcompilerimpl.h"
+
+public:
+ // Added to help us track the original icjc and be able to easily indirect to it.
+ ICorJitCompiler *original_ICorJitCompiler;
+};
+
+extern interceptor_IEEMM *current_IEEMM; // we want a pointer to the memory manager to live beyond the scope of a single compileMethodCall (jit32 expects this)
+
+#endif
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
new file mode 100644
index 0000000000..89b19d8754
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
@@ -0,0 +1,1726 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "icorjitinfo.h"
+#include "superpmi-shim-simple.h"
+#include "ieememorymanager.h"
+#include "icorjitcompiler.h"
+#include "spmiutil.h"
+
+//Stuff on ICorStaticInfo
+/**********************************************************************************/
+//
+// ICorMethodInfo
+//
+/**********************************************************************************/
+// return flags (defined above, CORINFO_FLG_PUBLIC ...)
+DWORD interceptor_ICJI::getMethodAttribs (CORINFO_METHOD_HANDLE ftn /* IN */)
+{
+ return original_ICorJitInfo->getMethodAttribs(ftn);
+}
+
+// sets private JIT flags, which can be, retrieved using getAttrib.
+void interceptor_ICJI::setMethodAttribs (CORINFO_METHOD_HANDLE ftn,/* IN */
+ CorInfoMethodRuntimeFlags attribs/* IN */)
+{
+ original_ICorJitInfo->setMethodAttribs(ftn, attribs);
+}
+
+
+// Given a method descriptor ftnHnd, extract signature information into sigInfo
+//
+// 'memberParent' is typically only set when verifying. It should be the
+// result of calling getMemberParent.
+void interceptor_ICJI::getMethodSig (
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_SIG_INFO *sig, /* OUT */
+ CORINFO_CLASS_HANDLE memberParent/* IN */
+ )
+{
+ original_ICorJitInfo->getMethodSig(ftn, sig, memberParent);
+}
+
+
+ /*********************************************************************
+ * Note the following methods can only be used on functions known
+ * to be IL. This includes the method being compiled and any method
+ * that 'getMethodInfo' returns true for
+ *********************************************************************/
+
+ // return information about a method private to the implementation
+ // returns false if method is not IL, or is otherwise unavailable.
+ // This method is used to fetch data needed to inline functions
+ bool interceptor_ICJI::getMethodInfo (
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_METHOD_INFO* info /* OUT */
+ )
+{
+ return original_ICorJitInfo->getMethodInfo(ftn, info);
+}
+
+// Decides if you have any limitations for inlining. If everything's OK, it will return
+// INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
+// function must respect. If caller passes pRestrictions = nullptr, if there are any restrictions
+// INLINE_FAIL will be returned
+//
+// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
+//
+// The inlined method need not be verified
+
+CorInfoInline interceptor_ICJI::canInline (
+ CORINFO_METHOD_HANDLE callerHnd, /* IN */
+ CORINFO_METHOD_HANDLE calleeHnd, /* IN */
+ DWORD* pRestrictions /* OUT */
+ )
+{
+ return original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
+}
+
+// Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all
+// inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the
+// JIT.
+void interceptor_ICJI::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
+ CORINFO_METHOD_HANDLE inlineeHnd,
+ CorInfoInline inlineResult,
+ const char * reason)
+{
+ original_ICorJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
+}
+
+
+// Returns false if the call is across security boundaries thus we cannot tailcall
+//
+// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
+bool interceptor_ICJI::canTailCall (
+ CORINFO_METHOD_HANDLE callerHnd, /* IN */
+ CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */
+ CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */
+ bool fIsTailPrefix /* IN */
+ )
+{
+ return original_ICorJitInfo->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix);
+}
+
+// Reports whether or not a method can be tail called, and why.
+// canTailCall is responsible for reporting all results when it returns
+// false. All other results are reported by the JIT.
+void interceptor_ICJI::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd,
+ CORINFO_METHOD_HANDLE calleeHnd,
+ bool fIsTailPrefix,
+ CorInfoTailCall tailCallResult,
+ const char * reason)
+{
+ original_ICorJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
+}
+
+// get individual exception handler
+void interceptor_ICJI::getEHinfo(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ unsigned EHnumber, /* IN */
+ CORINFO_EH_CLAUSE* clause /* OUT */
+ )
+{
+ original_ICorJitInfo->getEHinfo(ftn, EHnumber, clause);
+}
+
+// return class it belongs to
+CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass (
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ return original_ICorJitInfo->getMethodClass(method);
+}
+
+// return module it belongs to
+CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule (
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ return original_ICorJitInfo->getMethodModule(method);
+}
+
+// This function returns the offset of the specified method in the
+// vtable of it's owning class or interface.
+void interceptor_ICJI::getMethodVTableOffset (
+ CORINFO_METHOD_HANDLE method, /* IN */
+ unsigned* offsetOfIndirection, /* OUT */
+ unsigned* offsetAfterIndirection /* OUT */
+ )
+{
+ original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+}
+
+// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
+// getIntrinsicID() returns the intrinsic ID.
+CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(
+ CORINFO_METHOD_HANDLE method,
+ bool* pMustExpand /* OUT */
+ )
+{
+ return original_ICorJitInfo->getIntrinsicID(method, pMustExpand);
+}
+
+// Is the given module the System.Numerics.Vectors module?
+bool interceptor_ICJI::isInSIMDModule(
+ CORINFO_CLASS_HANDLE classHnd
+ )
+{
+ return original_ICorJitInfo->isInSIMDModule(classHnd);
+}
+
+// return the unmanaged calling convention for a PInvoke
+CorInfoUnmanagedCallConv interceptor_ICJI::getUnmanagedCallConv(
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ return original_ICorJitInfo->getUnmanagedCallConv(method);
+}
+
+// return if any marshaling is required for PInvoke methods. Note that
+// method == 0 => calli. The call site sig is only needed for the varargs or calli case
+BOOL interceptor_ICJI::pInvokeMarshalingRequired(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* callSiteSig
+ )
+{
+ return original_ICorJitInfo->pInvokeMarshalingRequired(method, callSiteSig);
+}
+
+// Check constraints on method type arguments (only).
+// The parent class should be checked separately using satisfiesClassConstraints(parent).
+BOOL interceptor_ICJI::satisfiesMethodConstraints(
+ CORINFO_CLASS_HANDLE parent, // the exact parent of the method
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ return original_ICorJitInfo->satisfiesMethodConstraints(parent, method);
+}
+
+// Given a delegate target class, a target method parent class, a target method,
+// a delegate class, check if the method signature is compatible with the Invoke method of the delegate
+// (under the typical instantiation of any free type variables in the memberref signatures).
+BOOL interceptor_ICJI::isCompatibleDelegate(
+ CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */
+ CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */
+ CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */
+ CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */
+ BOOL *pfIsOpenDelegate /* is the delegate open */
+ )
+{
+ return original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
+}
+
+// Determines whether the delegate creation obeys security transparency rules
+BOOL interceptor_ICJI::isDelegateCreationAllowed (
+ CORINFO_CLASS_HANDLE delegateHnd,
+ CORINFO_METHOD_HANDLE calleeHnd
+ )
+{
+ return original_ICorJitInfo->isDelegateCreationAllowed(delegateHnd, calleeHnd);
+}
+
+
+// Indicates if the method is an instance of the generic
+// method that passes (or has passed) verification
+CorInfoInstantiationVerification interceptor_ICJI::isInstantiationOfVerifiedGeneric (
+ CORINFO_METHOD_HANDLE method /* IN */
+ )
+{
+ return original_ICorJitInfo->isInstantiationOfVerifiedGeneric(method);
+}
+
+// Loads the constraints on a typical method definition, detecting cycles;
+// for use in verification.
+void interceptor_ICJI::initConstraintsForVerification(
+ CORINFO_METHOD_HANDLE method, /* IN */
+ BOOL *pfHasCircularClassConstraints, /* OUT */
+ BOOL *pfHasCircularMethodConstraint /* OUT */
+ )
+{
+ original_ICorJitInfo->initConstraintsForVerification(method, pfHasCircularClassConstraints, pfHasCircularMethodConstraint);
+}
+
+CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipMethodVerification (
+ CORINFO_METHOD_HANDLE ftnHandle
+ )
+{
+ return original_ICorJitInfo->canSkipMethodVerification(ftnHandle);
+}
+
+// load and restore the method
+void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun(
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ original_ICorJitInfo->methodMustBeLoadedBeforeCodeIsRun(method);
+}
+
+CORINFO_METHOD_HANDLE interceptor_ICJI::mapMethodDeclToMethodImpl(
+ CORINFO_METHOD_HANDLE method
+ )
+{
+ return original_ICorJitInfo->mapMethodDeclToMethodImpl(method);
+}
+
+// Returns the global cookie for the /GS unsafe buffer checks
+// The cookie might be a constant value (JIT), or a handle to memory location (Ngen)
+void interceptor_ICJI::getGSCookie(
+ GSCookie * pCookieVal, // OUT
+ GSCookie ** ppCookieVal // OUT
+ )
+{
+ original_ICorJitInfo->getGSCookie(pCookieVal, ppCookieVal);
+}
+
+/**********************************************************************************/
+//
+// ICorModuleInfo
+//
+/**********************************************************************************/
+
+// Resolve metadata token into runtime method handles.
+void interceptor_ICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
+{
+ original_ICorJitInfo->resolveToken(pResolvedToken);
+}
+
+bool interceptor_ICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
+{
+ return original_ICorJitInfo->tryResolveToken(pResolvedToken);
+}
+
+// Signature information about the call sig
+void interceptor_ICJI::findSig (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned sigTOK, /* IN */
+ CORINFO_CONTEXT_HANDLE context, /* IN */
+ CORINFO_SIG_INFO *sig /* OUT */
+ )
+{
+ original_ICorJitInfo->findSig(module, sigTOK, context, sig);
+}
+
+// for Varargs, the signature at the call site may differ from
+// the signature at the definition. Thus we need a way of
+// fetching the call site information
+void interceptor_ICJI::findCallSiteSig (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned methTOK, /* IN */
+ CORINFO_CONTEXT_HANDLE context, /* IN */
+ CORINFO_SIG_INFO *sig /* OUT */
+ )
+{
+ original_ICorJitInfo->findCallSiteSig(module, methTOK, context, sig);
+}
+
+CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle (
+ CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */)
+{
+ return original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken);
+}
+
+// Returns true if the module does not require verification
+//
+// If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the
+// module does not currently require verification in the current AppDomain.
+// This decision could change in the future, and so should not be cached.
+// If it is cached, it should only be used as a hint.
+// This is only used by ngen for calculating certain hints.
+//
+
+// Returns enum whether the module does not require verification
+// Also see ICorMethodInfo::canSkipMethodVerification();
+CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipVerification (
+ CORINFO_MODULE_HANDLE module /* IN */
+ )
+{
+ return original_ICorJitInfo->canSkipVerification(module);
+}
+
+// Checks if the given metadata token is valid
+BOOL interceptor_ICJI::isValidToken (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK /* IN */
+ )
+{
+ return original_ICorJitInfo->isValidToken(module, metaTOK);
+}
+
+// Checks if the given metadata token is valid StringRef
+BOOL interceptor_ICJI::isValidStringRef (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK /* IN */
+ )
+{
+ return original_ICorJitInfo->isValidStringRef(module, metaTOK);
+}
+
+BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(
+ CORINFO_MODULE_HANDLE scope
+ )
+{
+ return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
+}
+
+/**********************************************************************************/
+//
+// ICorClassInfo
+//
+/**********************************************************************************/
+
+// If the value class 'cls' is isomorphic to a primitive type it will
+// return that type, otherwise it will return CORINFO_TYPE_VALUECLASS
+CorInfoType interceptor_ICJI::asCorInfoType (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->asCorInfoType(cls);
+}
+
+// for completeness
+const char* interceptor_ICJI::getClassName (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getClassName(cls);
+}
+
+
+// Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen
+// If fNamespace=TRUE, include the namespace/enclosing classes
+// If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters
+// If fAssembly=TRUE, suffix with a comma and the full assembly qualification
+// return size of representation
+int interceptor_ICJI::appendClassName(
+ __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
+ int* pnBufLen,
+ CORINFO_CLASS_HANDLE cls,
+ BOOL fNamespace,
+ BOOL fFullInst,
+ BOOL fAssembly
+ )
+{
+ return original_ICorJitInfo->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly);
+}
+
+// Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) & CORINFO_FLG_VALUECLASS, except faster.
+BOOL interceptor_ICJI::isValueClass(CORINFO_CLASS_HANDLE cls)
+{
+ return original_ICorJitInfo->isValueClass(cls);
+}
+
+// If this method returns true, JIT will do optimization to inline the check for
+// GetTypeFromHandle(handle) == obj.GetType()
+BOOL interceptor_ICJI::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls)
+{
+ return original_ICorJitInfo->canInlineTypeCheckWithObjectVTable(cls);
+}
+
+// return flags (defined above, CORINFO_FLG_PUBLIC ...)
+DWORD interceptor_ICJI::getClassAttribs (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getClassAttribs(cls);
+}
+
+// Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value
+// of this type must be stack-allocated. This will generally be true only if the struct
+// contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows
+// an optimization: the JIT may assume that return buffer pointers for return types for which this predicate
+// returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return
+// buffers do not require GC write barriers.
+BOOL interceptor_ICJI::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
+{
+ return original_ICorJitInfo->isStructRequiringStackAllocRetBuf(cls);
+}
+
+CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getClassModule(cls);
+}
+
+// Returns the assembly that contains the module "mod".
+CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly (
+ CORINFO_MODULE_HANDLE mod
+ )
+{
+ return original_ICorJitInfo->getModuleAssembly(mod);
+}
+
+// Returns the name of the assembly "assem".
+const char* interceptor_ICJI::getAssemblyName (
+ CORINFO_ASSEMBLY_HANDLE assem
+ )
+{
+ return original_ICorJitInfo->getAssemblyName(assem);
+}
+
+// Allocate and delete process-lifetime objects. Should only be
+// referred to from static fields, lest a leak occur.
+// Note that "LongLifetimeFree" does not execute destructors, if "obj"
+// is an array of a struct type with a destructor.
+void* interceptor_ICJI::LongLifetimeMalloc(size_t sz)
+{
+ return original_ICorJitInfo->LongLifetimeMalloc(sz);
+}
+
+void interceptor_ICJI::LongLifetimeFree(void* obj)
+{
+ original_ICorJitInfo->LongLifetimeFree(obj);
+}
+
+size_t interceptor_ICJI::getClassModuleIdForStatics (
+ CORINFO_CLASS_HANDLE cls,
+ CORINFO_MODULE_HANDLE *pModule,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
+}
+
+// return the number of bytes needed by an instance of the class
+unsigned interceptor_ICJI::getClassSize (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getClassSize(cls);
+}
+
+unsigned interceptor_ICJI::getClassAlignmentRequirement (
+ CORINFO_CLASS_HANDLE cls,
+ BOOL fDoubleAlignHint
+ )
+{
+ return original_ICorJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
+}
+
+// This is only called for Value classes. It returns a boolean array
+// in representing of 'cls' from a GC perspective. The class is
+// assumed to be an array of machine words
+// (of length // getClassSize(cls) / sizeof(void*)),
+// 'gcPtrs' is a poitner to an array of BYTEs of this length.
+// getClassGClayout fills in this array so that gcPtrs[i] is set
+// to one of the CorInfoGCType values which is the GC type of
+// the i-th machine word of an object of type 'cls'
+// returns the number of GC pointers in the array
+unsigned interceptor_ICJI::getClassGClayout (
+ CORINFO_CLASS_HANDLE cls, /* IN */
+ BYTE *gcPtrs /* OUT */
+ )
+{
+ return original_ICorJitInfo->getClassGClayout(cls, gcPtrs);
+}
+
+// returns the number of instance fields in a class
+unsigned interceptor_ICJI::getClassNumInstanceFields (
+ CORINFO_CLASS_HANDLE cls /* IN */
+ )
+{
+ return original_ICorJitInfo->getClassNumInstanceFields(cls);
+}
+
+CORINFO_FIELD_HANDLE interceptor_ICJI::getFieldInClass(
+ CORINFO_CLASS_HANDLE clsHnd,
+ INT num
+ )
+{
+ return original_ICorJitInfo->getFieldInClass(clsHnd, num);
+}
+
+BOOL interceptor_ICJI::checkMethodModifier(
+ CORINFO_METHOD_HANDLE hMethod,
+ LPCSTR modifier,
+ BOOL fOptional
+ )
+{
+ return original_ICorJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
+}
+
+// returns the "NEW" helper optimized for "newCls."
+CorInfoHelpFunc interceptor_ICJI::getNewHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle
+ )
+{
+ return original_ICorJitInfo->getNewHelper(pResolvedToken, callerHandle);
+}
+
+// returns the newArr (1-Dim array) helper optimized for "arrayCls."
+CorInfoHelpFunc interceptor_ICJI::getNewArrHelper(
+ CORINFO_CLASS_HANDLE arrayCls
+ )
+{
+ return original_ICorJitInfo->getNewArrHelper(arrayCls);
+}
+
+// returns the optimized "IsInstanceOf" or "ChkCast" helper
+CorInfoHelpFunc interceptor_ICJI::getCastingHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ bool fThrowing
+ )
+{
+ return original_ICorJitInfo->getCastingHelper(pResolvedToken, fThrowing);
+}
+
+// returns helper to trigger static constructor
+CorInfoHelpFunc interceptor_ICJI::getSharedCCtorHelper(
+ CORINFO_CLASS_HANDLE clsHnd
+ )
+{
+ return original_ICorJitInfo->getSharedCCtorHelper(clsHnd);
+}
+
+CorInfoHelpFunc interceptor_ICJI::getSecurityPrologHelper(
+ CORINFO_METHOD_HANDLE ftn
+ )
+{
+ return original_ICorJitInfo->getSecurityPrologHelper(ftn);
+}
+
+// This is not pretty. Boxing nullable<T> actually returns
+// a boxed<T> not a boxed Nullable<T>. This call allows the verifier
+// to call back to the EE on the 'box' instruction and get the transformed
+// type to use for verification.
+CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeForBox(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getTypeForBox(cls);
+}
+
+// returns the correct box helper for a particular class. Note
+// that if this returns CORINFO_HELP_BOX, the JIT can assume
+// 'standard' boxing (allocate object and copy), and optimize
+CorInfoHelpFunc interceptor_ICJI::getBoxHelper(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getBoxHelper(cls);
+}
+
+// returns the unbox helper. If 'helperCopies' points to a true
+// value it means the JIT is requesting a helper that unboxes the
+// value into a particular location and thus has the signature
+// void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj)
+// Otherwise (it is null or points at a FALSE value) it is requesting
+// a helper that returns a poitner to the unboxed data
+// void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj)
+// The EE has the option of NOT returning the copy style helper
+// (But must be able to always honor the non-copy style helper)
+// The EE set 'helperCopies' on return to indicate what kind of
+// helper has been created.
+
+CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getUnBoxHelper(cls);
+}
+
+bool interceptor_ICJI::getReadyToRunHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_LOOKUP_KIND * pGenericLookupKind,
+ CorInfoHelpFunc id,
+ CORINFO_CONST_LOOKUP * pLookup
+ )
+{
+ return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup);
+}
+
+void interceptor_ICJI::getReadyToRunDelegateCtorHelper(
+ CORINFO_RESOLVED_TOKEN * pTargetMethod,
+ CORINFO_CLASS_HANDLE delegateType,
+ CORINFO_CONST_LOOKUP * pLookup
+ )
+{
+ original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
+}
+
+const char* interceptor_ICJI::getHelperName(
+ CorInfoHelpFunc funcNum
+ )
+{
+ return original_ICorJitInfo->getHelperName(funcNum);
+}
+
+// This function tries to initialize the class (run the class constructor).
+// this function returns whether the JIT must insert helper calls before
+// accessing static field or method.
+//
+// See code:ICorClassInfo#ClassConstruction.
+CorInfoInitClassResult interceptor_ICJI::initClass(
+ CORINFO_FIELD_HANDLE field, // Non-nullptr - inquire about cctor trigger before static field access
+ // nullptr - inquire about cctor trigger in method prolog
+ CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog
+ CORINFO_CONTEXT_HANDLE context, // Exact context of method
+ BOOL speculative // TRUE means don't actually run it
+ )
+{
+ return original_ICorJitInfo->initClass(field, method, context, speculative);
+}
+
+// This used to be called "loadClass". This records the fact
+// that the class must be loaded (including restored if necessary) before we execute the
+// code that we are currently generating. When jitting code
+// the function loads the class immediately. When zapping code
+// the zapper will if necessary use the call to record the fact that we have
+// to do a fixup/restore before running the method currently being generated.
+//
+// This is typically used to ensure value types are loaded before zapped
+// code that manipulates them is executed, so that the GC can access information
+// about those value types.
+void interceptor_ICJI::classMustBeLoadedBeforeCodeIsRun(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ original_ICorJitInfo->classMustBeLoadedBeforeCodeIsRun(cls);
+}
+
+// returns the class handle for the special builtin classes
+CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass (
+ CorInfoClassId classId
+ )
+{
+ return original_ICorJitInfo->getBuiltinClass(classId);
+}
+
+// "System.Int32" ==> CORINFO_TYPE_INT..
+CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getTypeForPrimitiveValueClass(cls);
+}
+
+// TRUE if child is a subtype of parent
+// if parent is an interface, then does child implement / extend parent
+BOOL interceptor_ICJI::canCast(
+ CORINFO_CLASS_HANDLE child, // subtype (extends parent)
+ CORINFO_CLASS_HANDLE parent // base type
+ )
+{
+ return original_ICorJitInfo->canCast(child, parent);
+}
+
+// TRUE if cls1 and cls2 are considered equivalent types.
+BOOL interceptor_ICJI::areTypesEquivalent(
+ CORINFO_CLASS_HANDLE cls1,
+ CORINFO_CLASS_HANDLE cls2
+ )
+{
+ return original_ICorJitInfo->areTypesEquivalent(cls1, cls2);
+}
+
+// returns is the intersection of cls1 and cls2.
+CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses(
+ CORINFO_CLASS_HANDLE cls1,
+ CORINFO_CLASS_HANDLE cls2
+ )
+{
+ return original_ICorJitInfo->mergeClasses(cls1, cls2);
+}
+
+// Given a class handle, returns the Parent type.
+// For COMObjectType, it returns Class Handle of System.Object.
+// Returns 0 if System.Object is passed in.
+CORINFO_CLASS_HANDLE interceptor_ICJI::getParentType (
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getParentType(cls);
+}
+
+// Returns the CorInfoType of the "child type". If the child type is
+// not a primitive type, *clsRet will be set.
+// Given an Array of Type Foo, returns Foo.
+// Given BYREF Foo, returns Foo
+CorInfoType interceptor_ICJI::getChildType (
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_CLASS_HANDLE *clsRet
+ )
+{
+ return original_ICorJitInfo->getChildType(clsHnd, clsRet);
+}
+
+// Check constraints on type arguments of this class and parent classes
+BOOL interceptor_ICJI::satisfiesClassConstraints(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->satisfiesClassConstraints(cls);
+}
+
+// Check if this is a single dimensional array type
+BOOL interceptor_ICJI::isSDArray(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->isSDArray(cls);
+}
+
+// Get the numbmer of dimensions in an array
+unsigned interceptor_ICJI::getArrayRank(
+ CORINFO_CLASS_HANDLE cls
+ )
+{
+ return original_ICorJitInfo->getArrayRank(cls);
+}
+
+// Get static field data for an array
+void * interceptor_ICJI::getArrayInitializationData(
+ CORINFO_FIELD_HANDLE field,
+ DWORD size
+ )
+{
+ return original_ICorJitInfo->getArrayInitializationData(field, size);
+}
+
+// Check Visibility rules.
+CorInfoIsAccessAllowedResult interceptor_ICJI::canAccessClass(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle,
+ CORINFO_HELPER_DESC *pAccessHelper /* If canAccessMethod returns something other
+ than ALLOWED, then this is filled in. */
+ )
+{
+ return original_ICorJitInfo->canAccessClass(pResolvedToken, callerHandle, pAccessHelper);
+}
+
+/**********************************************************************************/
+//
+// ICorFieldInfo
+//
+/**********************************************************************************/
+
+// this function is for debugging only. It returns the field name
+// and if 'moduleName' is non-null, it sets it to something that will
+// says which method (a class name, or a module name)
+const char* interceptor_ICJI::getFieldName (
+ CORINFO_FIELD_HANDLE ftn, /* IN */
+ const char **moduleName /* OUT */
+ )
+{
+ return original_ICorJitInfo->getFieldName(ftn, moduleName);
+}
+
+// return class it belongs to
+CORINFO_CLASS_HANDLE interceptor_ICJI::getFieldClass (
+ CORINFO_FIELD_HANDLE field
+ )
+{
+ return original_ICorJitInfo->getFieldClass(field);
+}
+
+// Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set
+// the field's value class (if 'structType' == 0, then don't bother
+// the structure info).
+//
+// 'memberParent' is typically only set when verifying. It should be the
+// result of calling getMemberParent.
+CorInfoType interceptor_ICJI::getFieldType(
+ CORINFO_FIELD_HANDLE field,
+ CORINFO_CLASS_HANDLE *structType,
+ CORINFO_CLASS_HANDLE memberParent/* IN */
+ )
+{
+ return original_ICorJitInfo->getFieldType(field, structType, memberParent);
+}
+
+// return the data member's instance offset
+unsigned interceptor_ICJI::getFieldOffset(
+ CORINFO_FIELD_HANDLE field
+ )
+{
+ return original_ICorJitInfo->getFieldOffset(field);
+}
+
+// TODO: jit64 should be switched to the same plan as the i386 jits - use
+// getClassGClayout to figure out the need for writebarrier helper, and inline the copying.
+// The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS
+bool interceptor_ICJI::isWriteBarrierHelperRequired(
+ CORINFO_FIELD_HANDLE field)
+{
+ return original_ICorJitInfo->isWriteBarrierHelperRequired(field);
+}
+
+void interceptor_ICJI::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle,
+ CORINFO_ACCESS_FLAGS flags,
+ CORINFO_FIELD_INFO *pResult
+ )
+{
+ original_ICorJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
+}
+
+// Returns true iff "fldHnd" represents a static field.
+bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
+{
+ // this method does exist in some forms of the jit interface... if trip into one we'll know about it
+ DebugBreakorAV(67);
+ return true;
+}
+
+/*********************************************************************************/
+//
+// ICorDebugInfo
+//
+/*********************************************************************************/
+
+// Query the EE to find out where interesting break points
+// in the code are. The native compiler will ensure that these places
+// have a corresponding break point in native code.
+//
+// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will
+// be used only as a hint and the native compiler should not change its
+// code generation.
+void interceptor_ICJI::getBoundaries(
+ CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
+ unsigned int *cILOffsets, // [OUT] size of pILOffsets
+ DWORD **pILOffsets, // [OUT] IL offsets of interest
+ // jit MUST free with freeArray!
+ ICorDebugInfo::BoundaryTypes *implictBoundaries // [OUT] tell jit, all boundries of this type
+ )
+{
+ original_ICorJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
+}
+
+// Report back the mapping from IL to native code,
+// this map should include all boundaries that 'getBoundaries'
+// reported as interesting to the debugger.
+
+// Note that debugger (and profiler) is assuming that all of the
+// offsets form a contiguous block of memory, and that the
+// OffsetMapping is sorted in order of increasing native offset.
+void interceptor_ICJI::setBoundaries(
+ CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
+ ULONG32 cMap, // [IN] size of pMap
+ ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest.
+ // jit allocated with allocateArray, EE frees
+ )
+{
+ original_ICorJitInfo->setBoundaries(ftn, cMap, pMap);
+}
+
+// Query the EE to find out the scope of local varables.
+// normally the JIT would trash variables after last use, but
+// under debugging, the JIT needs to keep them live over their
+// entire scope so that they can be inspected.
+//
+// Note that unless CORJIT_FLG_DEBUG_CODE is specified, this function will
+// be used only as a hint and the native compiler should not change its
+// code generation.
+void interceptor_ICJI::getVars(
+ CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
+ ULONG32 *cVars, // [OUT] size of 'vars'
+ ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest
+ // jit MUST free with freeArray!
+ bool *extendOthers // [OUT] it TRUE, then assume the scope
+ // of unmentioned vars is entire method
+ )
+{
+ original_ICorJitInfo->getVars(ftn, cVars, vars, extendOthers);
+}
+
+// Report back to the EE the location of every variable.
+// note that the JIT might split lifetimes into different
+// locations etc.
+
+void interceptor_ICJI::setVars(
+ CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
+ ULONG32 cVars, // [IN] size of 'vars'
+ ICorDebugInfo::NativeVarInfo *vars // [IN] map telling where local vars are stored at what points
+ // jit allocated with allocateArray, EE frees
+ )
+{
+ original_ICorJitInfo->setVars(ftn, cVars, vars);
+}
+
+/*-------------------------- Misc ---------------------------------------*/
+
+// Used to allocate memory that needs to handed to the EE.
+// For eg, use this to allocated memory for reporting debug info,
+// which will be handed to the EE by setVars() and setBoundaries()
+void * interceptor_ICJI::allocateArray(
+ ULONG cBytes
+ )
+{
+ return original_ICorJitInfo->allocateArray(cBytes);
+}
+
+// JitCompiler will free arrays passed by the EE using this
+// For eg, The EE returns memory in getVars() and getBoundaries()
+// to the JitCompiler, which the JitCompiler should release using
+// freeArray()
+void interceptor_ICJI::freeArray(
+ void *array
+ )
+{
+ original_ICorJitInfo->freeArray(array);
+}
+
+/*********************************************************************************/
+//
+// ICorArgInfo
+//
+/*********************************************************************************/
+
+// advance the pointer to the argument list.
+// a ptr of 0, is special and always means the first argument
+CORINFO_ARG_LIST_HANDLE interceptor_ICJI::getArgNext (
+ CORINFO_ARG_LIST_HANDLE args /* IN */
+ )
+{
+ return original_ICorJitInfo->getArgNext(args);
+}
+
+// Get the type of a particular argument
+// CORINFO_TYPE_UNDEF is returned when there are no more arguments
+// If the type returned is a primitive type (or an enum) *vcTypeRet set to nullptr
+// otherwise it is set to the TypeHandle associted with the type
+// Enumerations will always look their underlying type (probably should fix this)
+// Otherwise vcTypeRet is the type as would be seen by the IL,
+// The return value is the type that is used for calling convention purposes
+// (Thus if the EE wants a value class to be passed like an int, then it will
+// return CORINFO_TYPE_INT
+CorInfoTypeWithMod interceptor_ICJI::getArgType (
+ CORINFO_SIG_INFO* sig, /* IN */
+ CORINFO_ARG_LIST_HANDLE args, /* IN */
+ CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */
+ )
+{
+ return original_ICorJitInfo->getArgType(sig, args, vcTypeRet);
+}
+
+// If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it
+CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass (
+ CORINFO_SIG_INFO* sig, /* IN */
+ CORINFO_ARG_LIST_HANDLE args /* IN */
+ )
+{
+ return original_ICorJitInfo->getArgClass(sig, args);
+}
+
+// Returns type of HFA for valuetype
+CorInfoType interceptor_ICJI::getHFAType (
+ CORINFO_CLASS_HANDLE hClass
+ )
+{
+ return original_ICorJitInfo->getHFAType(hClass);
+}
+
+/*****************************************************************************
+* ICorErrorInfo contains methods to deal with SEH exceptions being thrown
+* from the corinfo interface. These methods may be called when an exception
+* with code EXCEPTION_COMPLUS is caught.
+*****************************************************************************/
+
+// Returns the HRESULT of the current exception
+HRESULT interceptor_ICJI::GetErrorHRESULT(
+ struct _EXCEPTION_POINTERS *pExceptionPointers
+ )
+{
+ return original_ICorJitInfo->GetErrorHRESULT(pExceptionPointers);
+}
+
+// Fetches the message of the current exception
+// Returns the size of the message (including terminating null). This can be
+// greater than bufferLength if the buffer is insufficient.
+ULONG interceptor_ICJI::GetErrorMessage(
+ __inout_ecount(bufferLength) LPWSTR buffer,
+ ULONG bufferLength
+ )
+{
+ return original_ICorJitInfo->GetErrorMessage(buffer, bufferLength);
+}
+
+// returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the
+// exception, abort some work (like the inlining) and continue compilation
+// returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE
+// things like ThreadStoppedException ...
+// returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE
+
+int interceptor_ICJI::FilterException(
+ struct _EXCEPTION_POINTERS *pExceptionPointers
+ )
+{
+ return original_ICorJitInfo->FilterException(pExceptionPointers);
+}
+
+// Cleans up internal EE tracking when an exception is caught.
+void interceptor_ICJI::HandleException(
+ struct _EXCEPTION_POINTERS *pExceptionPointers
+ )
+{
+ original_ICorJitInfo->HandleException(pExceptionPointers);
+}
+
+void interceptor_ICJI::ThrowExceptionForJitResult(
+ HRESULT result)
+{
+ original_ICorJitInfo->ThrowExceptionForJitResult(result);
+}
+
+//Throws an exception defined by the given throw helper.
+void interceptor_ICJI::ThrowExceptionForHelper(
+ const CORINFO_HELPER_DESC * throwHelper)
+{
+ original_ICorJitInfo->ThrowExceptionForHelper(throwHelper);
+}
+
+/*****************************************************************************
+ * ICorStaticInfo contains EE interface methods which return values that are
+ * constant from invocation to invocation. Thus they may be embedded in
+ * persisted information like statically generated code. (This is of course
+ * assuming that all code versions are identical each time.)
+ *****************************************************************************/
+
+// Return details about EE internal data structures
+void interceptor_ICJI::getEEInfo(
+ CORINFO_EE_INFO *pEEInfoOut
+ )
+{
+ original_ICorJitInfo->getEEInfo(pEEInfoOut);
+}
+
+// Returns name of the JIT timer log
+LPCWSTR interceptor_ICJI::getJitTimeLogFilename()
+{
+ return original_ICorJitInfo->getJitTimeLogFilename();
+}
+
+
+ /*********************************************************************************/
+ //
+ // Diagnostic methods
+ //
+ /*********************************************************************************/
+
+// this function is for debugging only. Returns method token.
+// Returns mdMethodDefNil for dynamic methods.
+mdMethodDef interceptor_ICJI::getMethodDefFromMethod(
+ CORINFO_METHOD_HANDLE hMethod
+ )
+{
+ return original_ICorJitInfo->getMethodDefFromMethod(hMethod);
+}
+
+// this function is for debugging only. It returns the method name
+// and if 'moduleName' is non-null, it sets it to something that will
+// says which method (a class name, or a module name)
+const char* interceptor_ICJI::getMethodName (
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char **moduleName /* OUT */
+ )
+{
+ return original_ICorJitInfo->getMethodName(ftn, moduleName);
+}
+
+// this function is for debugging only. It returns a value that
+// is will always be the same for a given method. It is used
+// to implement the 'jitRange' functionality
+unsigned interceptor_ICJI::getMethodHash (
+ CORINFO_METHOD_HANDLE ftn /* IN */
+ )
+{
+ return original_ICorJitInfo->getMethodHash(ftn);
+}
+
+// this function is for debugging only.
+size_t interceptor_ICJI::findNameOfToken (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ mdToken metaTOK, /* IN */
+ __out_ecount (FQNameCapacity) char * szFQName, /* OUT */
+ size_t FQNameCapacity /* IN */
+ )
+{
+ return original_ICorJitInfo->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
+}
+
+bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor(
+ /* IN */ CORINFO_CLASS_HANDLE structHnd,
+ /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr
+ )
+{
+ return original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr);
+}
+
+//Stuff on ICorDynamicInfo
+DWORD interceptor_ICJI::getThreadTLSIndex(
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getThreadTLSIndex(ppIndirection);
+}
+
+const void * interceptor_ICJI::getInlinedCallFrameVptr(
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection);
+}
+
+LONG * interceptor_ICJI::getAddrOfCaptureThreadGlobal(
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getAddrOfCaptureThreadGlobal(ppIndirection);
+}
+
+SIZE_T* interceptor_ICJI::getAddrModuleDomainID(CORINFO_MODULE_HANDLE module)
+{
+ return original_ICorJitInfo->getAddrModuleDomainID(module);
+}
+
+// return the native entry point to an EE helper (see CorInfoHelpFunc)
+void* interceptor_ICJI::getHelperFtn (
+ CorInfoHelpFunc ftnNum,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getHelperFtn(ftnNum, ppIndirection);
+}
+
+// return a callable address of the function (native code). This function
+// may return a different value (depending on whether the method has
+// been JITed or not.
+void interceptor_ICJI::getFunctionEntryPoint(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_CONST_LOOKUP * pResult, /* OUT */
+ CORINFO_ACCESS_FLAGS accessFlags)
+{
+ original_ICorJitInfo->getFunctionEntryPoint(ftn, pResult, accessFlags);
+}
+
+// return a directly callable address. This can be used similarly to the
+// value returned by getFunctionEntryPoint() except that it is
+// guaranteed to be multi callable entrypoint.
+void interceptor_ICJI::getFunctionFixedEntryPoint(
+ CORINFO_METHOD_HANDLE ftn,
+ CORINFO_CONST_LOOKUP * pResult)
+{
+ original_ICorJitInfo->getFunctionFixedEntryPoint(ftn, pResult);
+}
+
+// get the synchronization handle that is passed to monXstatic function
+void* interceptor_ICJI::getMethodSync(
+ CORINFO_METHOD_HANDLE ftn,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getMethodSync(ftn, ppIndirection);
+}
+
+// These entry points must be called if a handle is being embedded in
+// the code to be passed to a JIT helper function. (as opposed to just
+// being passed back into the ICorInfo interface.)
+
+// get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
+// Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
+CorInfoHelpFunc interceptor_ICJI::getLazyStringLiteralHelper(
+ CORINFO_MODULE_HANDLE handle
+ )
+{
+ return original_ICorJitInfo->getLazyStringLiteralHelper(handle);
+}
+
+CORINFO_MODULE_HANDLE interceptor_ICJI::embedModuleHandle(
+ CORINFO_MODULE_HANDLE handle,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->embedModuleHandle(handle, ppIndirection);
+}
+
+CORINFO_CLASS_HANDLE interceptor_ICJI::embedClassHandle(
+ CORINFO_CLASS_HANDLE handle,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->embedClassHandle(handle, ppIndirection);
+}
+
+CORINFO_METHOD_HANDLE interceptor_ICJI::embedMethodHandle(
+ CORINFO_METHOD_HANDLE handle,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->embedMethodHandle(handle, ppIndirection);
+}
+
+CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle(
+ CORINFO_FIELD_HANDLE handle,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->embedFieldHandle(handle, ppIndirection);
+}
+
+// Given a module scope (module), a method handle (context) and
+// a metadata token (metaTOK), fetch the handle
+// (type, field or method) associated with the token.
+// If this is not possible at compile-time (because the current method's
+// code is shared and the token contains generic parameters)
+// then indicate how the handle should be looked up at run-time.
+//
+void interceptor_ICJI::embedGenericHandle(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ BOOL fEmbedParent, // TRUE - embeds parent type handle of the field/method handle
+ CORINFO_GENERICHANDLE_RESULT * pResult)
+{
+ original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult);
+}
+
+// Return information used to locate the exact enclosing type of the current method.
+// Used only to invoke .cctor method from code shared across generic instantiations
+// !needsRuntimeLookup statically known (enclosing type of method itself)
+// needsRuntimeLookup:
+// CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param
+// CORINFO_LOOKUP_CLASSPARAM use vtable hidden param
+// CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param
+CORINFO_LOOKUP_KIND interceptor_ICJI::getLocationOfThisType(
+ CORINFO_METHOD_HANDLE context
+ )
+{
+ return original_ICorJitInfo->getLocationOfThisType(context);
+}
+
+// return the unmanaged target *if method has already been prelinked.*
+void* interceptor_ICJI::getPInvokeUnmanagedTarget(
+ CORINFO_METHOD_HANDLE method,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getPInvokeUnmanagedTarget(method, ppIndirection);
+}
+
+// return address of fixup area for late-bound PInvoke calls.
+void* interceptor_ICJI::getAddressOfPInvokeFixup(
+ CORINFO_METHOD_HANDLE method,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getAddressOfPInvokeFixup(method, ppIndirection);
+}
+
+// return address of fixup area for late-bound PInvoke calls.
+void interceptor_ICJI::getAddressOfPInvokeTarget(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_CONST_LOOKUP *pLookup
+ )
+{
+ original_ICorJitInfo->getAddressOfPInvokeTarget(method, pLookup);
+}
+
+// Generate a cookie based on the signature that would needs to be passed
+// to CORINFO_HELP_PINVOKE_CALLI
+LPVOID interceptor_ICJI::GetCookieForPInvokeCalliSig(
+ CORINFO_SIG_INFO* szMetaSig,
+ void ** ppIndirection
+ )
+{
+ return original_ICorJitInfo->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection);
+}
+
+// returns true if a VM cookie can be generated for it (might be false due to cross-module
+// inlining, in which case the inlining should be aborted)
+bool interceptor_ICJI::canGetCookieForPInvokeCalliSig(
+ CORINFO_SIG_INFO* szMetaSig
+ )
+{
+ return original_ICorJitInfo->canGetCookieForPInvokeCalliSig(szMetaSig);
+}
+
+// Gets a handle that is checked to see if the current method is
+// included in "JustMyCode"
+CORINFO_JUST_MY_CODE_HANDLE interceptor_ICJI::getJustMyCodeHandle(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_JUST_MY_CODE_HANDLE**ppIndirection
+ )
+{
+ return original_ICorJitInfo->getJustMyCodeHandle(method, ppIndirection);
+}
+
+// Gets a method handle that can be used to correlate profiling data.
+// This is the IP of a native method, or the address of the descriptor struct
+// for IL. Always guaranteed to be unique per process, and not to move. */
+void interceptor_ICJI::GetProfilingHandle(
+ BOOL *pbHookFunction,
+ void **pProfilerHandle,
+ BOOL *pbIndirectedHandles
+ )
+{
+ original_ICorJitInfo->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
+}
+
+// Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values.
+void interceptor_ICJI::getCallInfo(
+ // Token info
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+
+ //Generics info
+ CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
+
+ //Security info
+ CORINFO_METHOD_HANDLE callerHandle,
+
+ //Jit info
+ CORINFO_CALLINFO_FLAGS flags,
+
+ //out params
+ CORINFO_CALL_INFO *pResult
+ )
+{
+ original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
+}
+
+BOOL interceptor_ICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
+ CORINFO_CLASS_HANDLE hInstanceType)
+
+{
+ return original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType);
+}
+// Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class
+// except reflection emitted classes and generics)
+BOOL interceptor_ICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
+{
+ return original_ICorJitInfo->isRIDClassDomainID(cls);
+}
+
+// returns the class's domain ID for accessing shared statics
+unsigned interceptor_ICJI::getClassDomainID (
+ CORINFO_CLASS_HANDLE cls,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
+}
+
+
+// return the data's address (for static fields only)
+void* interceptor_ICJI::getFieldAddress(
+ CORINFO_FIELD_HANDLE field,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getFieldAddress(field, ppIndirection);
+}
+
+// registers a vararg sig & returns a VM cookie for it (which can contain other stuff)
+CORINFO_VARARGS_HANDLE interceptor_ICJI::getVarArgsHandle(
+ CORINFO_SIG_INFO *pSig,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getVarArgsHandle(pSig, ppIndirection);
+}
+
+// returns true if a VM cookie can be generated for it (might be false due to cross-module
+// inlining, in which case the inlining should be aborted)
+bool interceptor_ICJI::canGetVarArgsHandle(
+ CORINFO_SIG_INFO *pSig
+ )
+{
+ return original_ICorJitInfo->canGetVarArgsHandle(pSig);
+}
+
+// Allocate a string literal on the heap and return a handle to it
+InfoAccessType interceptor_ICJI::constructStringLiteral(
+ CORINFO_MODULE_HANDLE module,
+ mdToken metaTok,
+ void **ppValue
+ )
+{
+ return original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue);
+}
+
+InfoAccessType interceptor_ICJI::emptyStringLiteral(
+ void **ppValue
+ )
+{
+ return original_ICorJitInfo->emptyStringLiteral(ppValue);
+}
+
+// (static fields only) given that 'field' refers to thread local store,
+// return the ID (TLS index), which is used to find the begining of the
+// TLS data area for the particular DLL 'field' is associated with.
+DWORD interceptor_ICJI::getFieldThreadLocalStoreID (
+ CORINFO_FIELD_HANDLE field,
+ void **ppIndirection
+ )
+{
+ return original_ICorJitInfo->getFieldThreadLocalStoreID(field, ppIndirection);
+}
+
+// Sets another object to intercept calls to "self" and current method being compiled
+void interceptor_ICJI::setOverride(
+ ICorDynamicInfo *pOverride,
+ CORINFO_METHOD_HANDLE currentMethod
+ )
+{
+ original_ICorJitInfo->setOverride(pOverride, currentMethod);
+}
+
+// Adds an active dependency from the context method's module to the given module
+// This is internal callback for the EE. JIT should not call it directly.
+void interceptor_ICJI::addActiveDependency(
+ CORINFO_MODULE_HANDLE moduleFrom,
+ CORINFO_MODULE_HANDLE moduleTo
+ )
+{
+ original_ICorJitInfo->addActiveDependency(moduleFrom, moduleTo);
+}
+
+CORINFO_METHOD_HANDLE interceptor_ICJI::GetDelegateCtor(
+ CORINFO_METHOD_HANDLE methHnd,
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_METHOD_HANDLE targetMethodHnd,
+ DelegateCtorArgs * pCtorData
+ )
+{
+ return original_ICorJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
+}
+
+void interceptor_ICJI::MethodCompileComplete(
+ CORINFO_METHOD_HANDLE methHnd
+ )
+{
+ original_ICorJitInfo->MethodCompileComplete(methHnd);
+}
+
+// return a thunk that will copy the arguments for the given signature.
+void* interceptor_ICJI::getTailCallCopyArgsThunk (
+ CORINFO_SIG_INFO *pSig,
+ CorInfoHelperTailCallSpecialHandling flags
+ )
+{
+ return original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
+}
+
+//Stuff directly on ICorJitInfo
+
+// Returns extended flags for a particular compilation instance.
+DWORD interceptor_ICJI::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
+{
+ return original_ICorJitInfo->getJitFlags(jitFlags, sizeInBytes);
+}
+
+// Runs the given function with the given parameter under an error trap
+// and returns true if the function completes successfully.
+bool interceptor_ICJI::runWithErrorTrap(void (*function)(void*), void *param)
+{
+ return original_ICorJitInfo->runWithErrorTrap(function, param);
+}
+
+// return memory manager that the JIT can use to allocate a regular memory
+IEEMemoryManager* interceptor_ICJI::getMemoryManager()
+{
+ if(current_IEEMM->original_IEEMM == nullptr)
+ current_IEEMM->original_IEEMM = original_ICorJitInfo->getMemoryManager();
+
+ return current_IEEMM;
+}
+
+// get a block of memory for the code, readonly data, and read-write data
+void interceptor_ICJI::allocMem (
+ ULONG hotCodeSize, /* IN */
+ ULONG coldCodeSize, /* IN */
+ ULONG roDataSize, /* IN */
+ ULONG xcptnsCount, /* IN */
+ CorJitAllocMemFlag flag, /* IN */
+ void ** hotCodeBlock, /* OUT */
+ void ** coldCodeBlock, /* OUT */
+ void ** roDataBlock /* OUT */
+ )
+{
+ return original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock);
+}
+
+// Reserve memory for the method/funclet's unwind information.
+// Note that this must be called before allocMem. It should be
+// called once for the main method, once for every funclet, and
+// once for every block of cold code for which allocUnwindInfo
+// will be called.
+//
+// This is necessary because jitted code must allocate all the
+// memory needed for the unwindInfo at the allocMem call.
+// For prejitted code we split up the unwinding information into
+// separate sections .rdata and .pdata.
+//
+void interceptor_ICJI::reserveUnwindInfo (
+ BOOL isFunclet, /* IN */
+ BOOL isColdCode, /* IN */
+ ULONG unwindSize /* IN */
+ )
+{
+ original_ICorJitInfo->reserveUnwindInfo(isFunclet, isColdCode, unwindSize);
+}
+
+// Allocate and initialize the .rdata and .pdata for this method or
+// funclet, and get the block of memory needed for the machine-specific
+// unwind information (the info for crawling the stack frame).
+// Note that allocMem must be called first.
+//
+// Parameters:
+//
+// pHotCode main method code buffer, always filled in
+// pColdCode cold code buffer, only filled in if this is cold code,
+// null otherwise
+// startOffset start of code block, relative to appropriate code buffer
+// (e.g. pColdCode if cold, pHotCode if hot).
+// endOffset end of code block, relative to appropriate code buffer
+// unwindSize size of unwind info pointed to by pUnwindBlock
+// pUnwindBlock pointer to unwind info
+// funcKind type of funclet (main method code, handler, filter)
+//
+void interceptor_ICJI::allocUnwindInfo (
+ BYTE * pHotCode, /* IN */
+ BYTE * pColdCode, /* IN */
+ ULONG startOffset, /* IN */
+ ULONG endOffset, /* IN */
+ ULONG unwindSize, /* IN */
+ BYTE * pUnwindBlock, /* IN */
+ CorJitFuncKind funcKind /* IN */
+ )
+{
+ original_ICorJitInfo->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock, funcKind);
+}
+
+// Get a block of memory needed for the code manager information,
+// (the info for enumerating the GC pointers while crawling the
+// stack frame).
+// Note that allocMem must be called first
+void * interceptor_ICJI::allocGCInfo (
+ size_t size /* IN */
+ )
+{
+ return original_ICorJitInfo->allocGCInfo(size);
+}
+
+// only used on x64
+void interceptor_ICJI::yieldExecution()
+{
+ original_ICorJitInfo->yieldExecution();
+}
+
+// Indicate how many exception handler blocks are to be returned.
+// This is guaranteed to be called before any 'setEHinfo' call.
+// Note that allocMem must be called before this method can be called.
+void interceptor_ICJI::setEHcount (
+ unsigned cEH /* IN */
+ )
+{
+ original_ICorJitInfo->setEHcount(cEH);
+}
+
+// Set the values for one particular exception handler block.
+//
+// Handler regions should be lexically contiguous.
+// This is because FinallyIsUnwinding() uses lexicality to
+// determine if a "finally" clause is executing.
+void interceptor_ICJI::setEHinfo (
+ unsigned EHnumber, /* IN */
+ const CORINFO_EH_CLAUSE *clause /* IN */
+ )
+{
+ original_ICorJitInfo->setEHinfo(EHnumber, clause);
+}
+
+// Level 1 -> fatalError, Level 2 -> Error, Level 3 -> Warning
+// Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ...
+// returns non-zero if the logging succeeded
+BOOL interceptor_ICJI::logMsg(unsigned level, const char* fmt, va_list args)
+{
+ return original_ICorJitInfo->logMsg(level, fmt, args);
+}
+
+// do an assert. will return true if the code should retry (DebugBreak)
+// returns false, if the assert should be igored.
+int interceptor_ICJI::doAssert(const char* szFile, int iLine, const char* szExpr)
+{
+ return original_ICorJitInfo->doAssert(szFile, iLine, szExpr);
+}
+
+void interceptor_ICJI::reportFatalError(CorJitResult result)
+{
+ original_ICorJitInfo->reportFatalError(result);
+}
+
+// allocate a basic block profile buffer where execution counts will be stored
+// for jitted basic blocks.
+HRESULT interceptor_ICJI::allocBBProfileBuffer (
+ ULONG count, // The number of basic blocks that we have
+ ProfileBuffer ** profileBuffer
+ )
+{
+ return original_ICorJitInfo->allocBBProfileBuffer(count, profileBuffer);
+}
+
+// get profile information to be used for optimizing the current method. The format
+// of the buffer is the same as the format the JIT passes to allocBBProfileBuffer.
+HRESULT interceptor_ICJI::getBBProfileData(
+ CORINFO_METHOD_HANDLE ftnHnd,
+ ULONG * count, // The number of basic blocks that we have
+ ProfileBuffer ** profileBuffer,
+ ULONG * numRuns
+ )
+{
+ return original_ICorJitInfo->getBBProfileData(ftnHnd, count, profileBuffer, numRuns);
+}
+
+// Associates a native call site, identified by its offset in the native code stream, with
+// the signature information and method handle the JIT used to lay out the call site. If
+// the call site has no signature information (e.g. a helper call) or has no method handle
+// (e.g. a CALLI P/Invoke), then null should be passed instead.
+void interceptor_ICJI::recordCallSite(
+ ULONG instrOffset, /* IN */
+ CORINFO_SIG_INFO * callSig, /* IN */
+ CORINFO_METHOD_HANDLE methodHandle /* IN */
+ )
+{
+ original_ICorJitInfo->recordCallSite(instrOffset, callSig, methodHandle);
+}
+
+// A relocation is recorded if we are pre-jitting.
+// A jump thunk may be inserted if we are jitting
+void interceptor_ICJI::recordRelocation(
+ void * location, /* IN */
+ void * target, /* IN */
+ WORD fRelocType, /* IN */
+ WORD slotNum, /* IN */
+ INT32 addlDelta /* IN */
+ )
+{
+ original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
+}
+
+WORD interceptor_ICJI::getRelocTypeHint(void * target)
+{
+ return original_ICorJitInfo->getRelocTypeHint(target);
+}
+
+// A callback to identify the range of address known to point to
+// compiler-generated native entry points that call back into
+// MSIL.
+void interceptor_ICJI::getModuleNativeEntryPointRange(
+ void ** pStart, /* OUT */
+ void ** pEnd /* OUT */
+ )
+{
+ original_ICorJitInfo->getModuleNativeEntryPointRange(pStart, pEnd);
+}
+
+// For what machine does the VM expect the JIT to generate code? The VM
+// returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM
+// is cross-compiling (such as the case for crossgen), it will return a
+// different value than if it was compiling for the host architecture.
+//
+DWORD interceptor_ICJI::getExpectedTargetArchitecture()
+{
+ return original_ICorJitInfo->getExpectedTargetArchitecture();
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h
new file mode 100644
index 0000000000..c266f036fb
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _ICorJitInfo
+#define _ICorJitInfo
+
+#include "runtimedetails.h"
+#include "ieememorymanager.h"
+
+class interceptor_ICJI : public ICorJitInfo
+{
+
+#include "icorjitinfoimpl.h"
+
+public:
+
+ //Added to help us track the original icji and be able to easily indirect
+ //to it. And a simple way to keep one memory manager instance per instance.
+ ICorJitInfo *original_ICorJitInfo;
+};
+
+#endif
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.cpp
new file mode 100644
index 0000000000..668b4b7728
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "ieememorymanager.h"
+#include "superpmi-shim-simple.h"
+
+//***************************************************************************
+// IUnknown methods
+//***************************************************************************
+HRESULT STDMETHODCALLTYPE interceptor_IEEMM::QueryInterface(REFIID id, void **pInterface)
+{
+ return original_IEEMM->QueryInterface(id, pInterface);
+}
+ULONG STDMETHODCALLTYPE interceptor_IEEMM::AddRef()
+{
+ return original_IEEMM->AddRef();
+}
+ULONG STDMETHODCALLTYPE interceptor_IEEMM::Release()
+{
+ return original_IEEMM->Release();
+}
+
+//***************************************************************************
+// IEEMemoryManager methods for locking
+//***************************************************************************
+LPVOID STDMETHODCALLTYPE interceptor_IEEMM::ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
+{
+ return original_IEEMM->ClrVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEEMM::ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
+{
+ return original_IEEMM->ClrVirtualFree(lpAddress, dwSize, dwFreeType);
+}
+SIZE_T STDMETHODCALLTYPE interceptor_IEEMM::ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
+{
+ return original_IEEMM->ClrVirtualQuery(lpAddress, lpBuffer, dwLength);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEEMM::ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)
+{
+ return original_IEEMM->ClrVirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect);
+}
+HANDLE STDMETHODCALLTYPE interceptor_IEEMM::ClrGetProcessHeap()
+{
+ return original_IEEMM->ClrGetProcessHeap();
+}
+HANDLE STDMETHODCALLTYPE interceptor_IEEMM::ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
+{
+ return original_IEEMM->ClrHeapCreate(flOptions, dwInitialSize, dwMaximumSize);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEEMM::ClrHeapDestroy(HANDLE hHeap)
+{
+ return original_IEEMM->ClrHeapDestroy(hHeap);
+}
+LPVOID STDMETHODCALLTYPE interceptor_IEEMM::ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
+{
+ return original_IEEMM->ClrHeapAlloc(hHeap, dwFlags, dwBytes);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEEMM::ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
+{
+ return original_IEEMM->ClrHeapFree(hHeap, dwFlags, lpMem);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEEMM::ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
+{
+ return original_IEEMM->ClrHeapValidate(hHeap, dwFlags, lpMem);
+}
+HANDLE STDMETHODCALLTYPE interceptor_IEEMM::ClrGetProcessExecutableHeap()
+{
+ return original_IEEMM->ClrGetProcessExecutableHeap();
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.h b/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.h
new file mode 100644
index 0000000000..411c532b59
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/ieememorymanager.h
@@ -0,0 +1,108 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _IEEMemoryManager
+#define _IEEMemoryManager
+
+#include "runtimedetails.h"
+
+/*
+interface IEEMemoryManager : IUnknown
+{
+ LPVOID ClrVirtualAlloc(
+ [in] LPVOID lpAddress, // region to reserve or commit
+ [in] SIZE_T dwSize, // size of region
+ [in] DWORD flAllocationType, // type of allocation
+ [in] DWORD flProtect // type of access protection
+ )
+
+ BOOL ClrVirtualFree(
+ [in] LPVOID lpAddress, // address of region
+ [in] SIZE_T dwSize, // size of region
+ [in] DWORD dwFreeType // operation type
+ )
+
+ SIZE_T ClrVirtualQuery(
+ [in] const void* lpAddress, // address of region
+ [in] PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer
+ [in] SIZE_T dwLength // size of buffer
+ )
+
+ BOOL ClrVirtualProtect(
+ [in] LPVOID lpAddress, // region of committed pages
+ [in] SIZE_T dwSize, // size of the region
+ [in] DWORD flNewProtect, // desired access protection
+ [in] DWORD* lpflOldProtect // old protection
+ )
+
+ HANDLE ClrGetProcessHeap()
+
+ HANDLE ClrHeapCreate(
+ [in] DWORD flOptions, // heap allocation attributes
+ [in] SIZE_T dwInitialSize, // initial heap size
+ [in] SIZE_T dwMaximumSize // maximum heap size
+ )
+
+ BOOL ClrHeapDestroy(
+ [in] HANDLE hHeap // handle to heap
+ )
+
+ LPVOID ClrHeapAlloc(
+ [in] HANDLE hHeap, // handle to private heap block
+ [in] DWORD dwFlags, // heap allocation control
+ [in] SIZE_T dwBytes // number of bytes to allocate
+ )
+
+ BOOL ClrHeapFree(
+ [in] HANDLE hHeap, // handle to heap
+ [in] DWORD dwFlags, // heap free options
+ [in] LPVOID lpMem // pointer to memory
+ )
+
+ BOOL ClrHeapValidate(
+ [in] HANDLE hHeap, // handle to heap
+ [in] DWORD dwFlags, // heap access options
+ [in] const void* lpMem // optional pointer to memory block
+ )
+
+ HANDLE ClrGetProcessExecutableHeap()
+
+}; // interface IEEMemoryManager
+
+*/
+
+class interceptor_IEEMM : public IEEMemoryManager
+{
+private:
+
+ //***************************************************************************
+ // IUnknown methods
+ //***************************************************************************
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void **pInterface);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //***************************************************************************
+ // IEEMemoryManager methods for locking
+ //***************************************************************************
+ LPVOID STDMETHODCALLTYPE ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
+ BOOL STDMETHODCALLTYPE ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
+ SIZE_T STDMETHODCALLTYPE ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
+ BOOL STDMETHODCALLTYPE ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+ HANDLE STDMETHODCALLTYPE ClrGetProcessHeap();
+ HANDLE STDMETHODCALLTYPE ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);
+ BOOL STDMETHODCALLTYPE ClrHeapDestroy(HANDLE hHeap);
+ LPVOID STDMETHODCALLTYPE ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
+ BOOL STDMETHODCALLTYPE ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
+ BOOL STDMETHODCALLTYPE ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
+ HANDLE STDMETHODCALLTYPE ClrGetProcessExecutableHeap();
+
+public:
+ // Added so we know where to make the real calls to.
+ IEEMemoryManager *original_IEEMM;
+};
+
+#endif
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.cpp
new file mode 100644
index 0000000000..a137266751
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "iexecutionengine.h"
+#include "superpmi-shim-simple.h"
+
+//***************************************************************************
+// IUnknown methods
+//***************************************************************************
+HRESULT STDMETHODCALLTYPE interceptor_IEE::QueryInterface(REFIID id, void **pInterface)
+{
+ return original_IEE->QueryInterface(id, pInterface);
+}
+ULONG STDMETHODCALLTYPE interceptor_IEE::AddRef()
+{
+ return original_IEE->AddRef();
+}
+ULONG STDMETHODCALLTYPE interceptor_IEE::Release()
+{
+ return original_IEE->Release();
+}
+
+//***************************************************************************
+// IExecutionEngine methods for TLS
+//***************************************************************************
+// Associate a callback for cleanup with a TLS slot
+VOID STDMETHODCALLTYPE interceptor_IEE::TLS_AssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback)
+{
+ original_IEE->TLS_AssociateCallback(slot, callback);
+}
+// Get the TLS block for fast Get/Set operations
+LPVOID* STDMETHODCALLTYPE interceptor_IEE::TLS_GetDataBlock()
+{
+ return original_IEE->TLS_GetDataBlock();
+}
+
+// Get the value at a slot
+LPVOID STDMETHODCALLTYPE interceptor_IEE::TLS_GetValue(DWORD slot)
+{
+ return original_IEE->TLS_GetValue(slot);
+}
+
+// Get the value at a slot, return FALSE if TLS info block doesn't exist
+BOOL STDMETHODCALLTYPE interceptor_IEE::TLS_CheckValue(DWORD slot, LPVOID * pValue)
+{
+ return original_IEE->TLS_CheckValue(slot, pValue);
+}
+// Set the value at a slot
+VOID STDMETHODCALLTYPE interceptor_IEE::TLS_SetValue(DWORD slot, LPVOID pData)
+{
+ original_IEE->TLS_SetValue(slot, pData);
+}
+// Free TLS memory block and make callback
+VOID STDMETHODCALLTYPE interceptor_IEE::TLS_ThreadDetaching()
+{
+ original_IEE->TLS_ThreadDetaching();
+}
+
+//***************************************************************************
+// IExecutionEngine methods for locking
+//***************************************************************************
+CRITSEC_COOKIE STDMETHODCALLTYPE interceptor_IEE::CreateLock(LPCSTR szTag, LPCSTR level, CrstFlags flags)
+{
+ return original_IEE->CreateLock(szTag, level, flags);
+}
+void STDMETHODCALLTYPE interceptor_IEE::DestroyLock(CRITSEC_COOKIE lock)
+{
+ original_IEE->DestroyLock(lock);
+}
+void STDMETHODCALLTYPE interceptor_IEE::AcquireLock(CRITSEC_COOKIE lock)
+{
+ original_IEE->AcquireLock(lock);
+}
+void STDMETHODCALLTYPE interceptor_IEE::ReleaseLock(CRITSEC_COOKIE lock)
+{
+ original_IEE->ReleaseLock(lock);
+}
+
+EVENT_COOKIE STDMETHODCALLTYPE interceptor_IEE::CreateAutoEvent(BOOL bInitialState)
+{
+ return original_IEE->CreateAutoEvent(bInitialState);
+}
+EVENT_COOKIE STDMETHODCALLTYPE interceptor_IEE::CreateManualEvent(BOOL bInitialState)
+{
+ return original_IEE->CreateManualEvent(bInitialState);
+}
+void STDMETHODCALLTYPE interceptor_IEE::CloseEvent(EVENT_COOKIE event)
+{
+ original_IEE->CloseEvent(event);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEE::ClrSetEvent(EVENT_COOKIE event)
+{
+ return original_IEE->ClrSetEvent(event);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEE::ClrResetEvent(EVENT_COOKIE event)
+{
+ return original_IEE->ClrResetEvent(event);
+}
+DWORD STDMETHODCALLTYPE interceptor_IEE::WaitForEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable)
+{
+ return original_IEE->WaitForEvent(event, dwMilliseconds, bAlertable);
+}
+DWORD STDMETHODCALLTYPE interceptor_IEE::WaitForSingleObject(HANDLE handle, DWORD dwMilliseconds)
+{
+ return original_IEE->WaitForSingleObject(handle, dwMilliseconds);
+}
+SEMAPHORE_COOKIE STDMETHODCALLTYPE interceptor_IEE::ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax)
+{
+ return original_IEE->ClrCreateSemaphore(dwInitial, dwMax);
+}
+void STDMETHODCALLTYPE interceptor_IEE::ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore)
+{
+ original_IEE->ClrCloseSemaphore(semaphore);
+}
+DWORD STDMETHODCALLTYPE interceptor_IEE::ClrWaitForSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable)
+{
+ return original_IEE->ClrWaitForSemaphore(semaphore, dwMilliseconds, bAlertable);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEE::ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount)
+{
+ return original_IEE->ClrReleaseSemaphore(semaphore, lReleaseCount, lpPreviousCount);
+}
+MUTEX_COOKIE STDMETHODCALLTYPE interceptor_IEE::ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,
+ BOOL bInitialOwner,
+ LPCTSTR lpName)
+{
+ return original_IEE->ClrCreateMutex(lpMutexAttributes, bInitialOwner, lpName);
+}
+void STDMETHODCALLTYPE interceptor_IEE::ClrCloseMutex(MUTEX_COOKIE mutex)
+{
+ original_IEE->ClrCloseMutex(mutex);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEE::ClrReleaseMutex(MUTEX_COOKIE mutex)
+{
+ return original_IEE->ClrReleaseMutex(mutex);
+}
+DWORD STDMETHODCALLTYPE interceptor_IEE::ClrWaitForMutex(MUTEX_COOKIE mutex,
+ DWORD dwMilliseconds,
+ BOOL bAlertable)
+{
+ return original_IEE->ClrWaitForMutex(mutex, dwMilliseconds, bAlertable);
+}
+
+DWORD STDMETHODCALLTYPE interceptor_IEE::ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable)
+{
+ return original_IEE->ClrSleepEx(dwMilliseconds, bAlertable);
+}
+BOOL STDMETHODCALLTYPE interceptor_IEE::ClrAllocationDisallowed()
+{
+ return original_IEE->ClrAllocationDisallowed();
+}
+void STDMETHODCALLTYPE interceptor_IEE::GetLastThrownObjectExceptionFromThread(void **ppvException)
+{
+ original_IEE->GetLastThrownObjectExceptionFromThread(ppvException);
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.h b/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.h
new file mode 100644
index 0000000000..dd3d7ee1fa
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/iexecutionengine.h
@@ -0,0 +1,150 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _IExecutionEngine
+#define _IExecutionEngine
+
+#include "ieememorymanager.h"
+
+/*
+interface IExecutionEngine : IUnknown
+{
+ // Thread Local Storage is based on logical threads. The underlying
+ // implementation could be threads, fibers, or something more exotic.
+ // Slot numbers are predefined. This is not a general extensibility
+ // mechanism.
+
+ // Associate a callback function for releasing TLS on thread/fiber death.
+ // This can be NULL.
+ void TLS_AssociateCallback([in] DWORD slot, [in] PTLS_CALLBACK_FUNCTION callback)
+
+ // May be called once to get the master TLS block slot for fast Get/Set operations
+ DWORD TLS_GetMasterSlotIndex()
+
+ // Get the value at a slot
+ PVOID TLS_GetValue([in] DWORD slot)
+
+ // Get the value at a slot, return FALSE if TLS info block doesn't exist
+ BOOL TLS_CheckValue([in] DWORD slot, [out] PVOID * pValue)
+
+ // Set the value at a slot
+ void TLS_SetValue([in] DWORD slot, [in] PVOID pData)
+
+ // Free TLS memory block and make callback
+ void TLS_ThreadDetaching()
+
+ // Critical Sections are sometimes exposed to the host and therefore need to be
+ // reflected from all CLR DLLs to the EE.
+ //
+ // In addition, we always monitor interactions between the lock & the GC, based
+ // on the GC mode in which the lock is acquired and we restrict what operations
+ // are permitted while holding the lock based on this.
+ //
+ // Finally, we we rank all our locks to prevent deadlock across all the DLLs of
+ // the CLR. This is the level argument to CreateLock.
+ //
+ // All usage of these locks must be exception-safe. To achieve this, we suggest
+ // using Holders (see holder.h & crst.h). In fact, within the EE code cannot
+ // hold locks except by using exception-safe holders.
+
+ CRITSEC_COOKIE CreateLock([in] LPCSTR szTag, [in] LPCSTR level, [in] CrstFlags flags)
+
+ void DestroyLock([in] CRITSEC_COOKIE lock)
+
+ void AcquireLock([in] CRITSEC_COOKIE lock)
+
+ void ReleaseLock([in] CRITSEC_COOKIE lock)
+
+ EVENT_COOKIE CreateAutoEvent([in] BOOL bInitialState)
+ EVENT_COOKIE CreateManualEvent([in] BOOL bInitialState)
+ void CloseEvent([in] EVENT_COOKIE event)
+ BOOL ClrSetEvent([in] EVENT_COOKIE event)
+ BOOL ClrResetEvent([in] EVENT_COOKIE event)
+ DWORD WaitForEvent([in] EVENT_COOKIE event, [in] DWORD dwMilliseconds, [in] BOOL bAlertable)
+ DWORD WaitForSingleObject([in] HANDLE handle, [in] DWORD dwMilliseconds)
+
+ // OS header file defines CreateSemaphore.
+ SEMAPHORE_COOKIE ClrCreateSemaphore([in] DWORD dwInitial, [in] DWORD dwMax)
+ void ClrCloseSemaphore([in] SEMAPHORE_COOKIE semaphore)
+ DWORD ClrWaitForSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] DWORD dwMilliseconds, [in] BOOL bAlertable)
+ BOOL ClrReleaseSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] LONG lReleaseCount, [in] LONG *lpPreviousCount)
+
+ MUTEX_COOKIE ClrCreateMutex([in]LPSECURITY_ATTRIBUTES lpMutexAttributes, [in]BOOL bInitialOwner, [in]LPCTSTR lpName)
+ DWORD ClrWaitForMutex([in] MUTEX_COOKIE mutex, [in] DWORD dwMilliseconds, [in] BOOL bAlertable)
+ BOOL ClrReleaseMutex([in] MUTEX_COOKIE mutex)
+ void ClrCloseMutex([in] MUTEX_COOKIE mutex)
+
+ DWORD ClrSleepEx([in] DWORD dwMilliseconds, [in] BOOL bAlertable)
+
+ BOOL ClrAllocationDisallowed()
+
+ void GetLastThrownObjectExceptionFromThread([out] void **ppvException)
+
+}; // interface IExecutionEngine
+*/
+
+class interceptor_IEE : public IExecutionEngine
+{
+private:
+
+ //***************************************************************************
+ // IUnknown methods
+ //***************************************************************************
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void **pInterface);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ //***************************************************************************
+ // IExecutionEngine methods for TLS
+ //***************************************************************************
+ // Associate a callback for cleanup with a TLS slot
+ VOID STDMETHODCALLTYPE TLS_AssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback);
+ // Get the TLS block for fast Get/Set operations
+ LPVOID* STDMETHODCALLTYPE TLS_GetDataBlock();
+ // Get the value at a slot
+ LPVOID STDMETHODCALLTYPE TLS_GetValue(DWORD slot);
+ // Get the value at a slot, return FALSE if TLS info block doesn't exist
+ BOOL STDMETHODCALLTYPE TLS_CheckValue(DWORD slot, LPVOID * pValue);
+ // Set the value at a slot
+ VOID STDMETHODCALLTYPE TLS_SetValue(DWORD slot, LPVOID pData);
+ // Free TLS memory block and make callback
+ VOID STDMETHODCALLTYPE TLS_ThreadDetaching();
+
+ //***************************************************************************
+ // IExecutionEngine methods for locking
+ //***************************************************************************
+ CRITSEC_COOKIE STDMETHODCALLTYPE CreateLock(LPCSTR szTag, LPCSTR level, CrstFlags flags);
+ void STDMETHODCALLTYPE DestroyLock(CRITSEC_COOKIE lock);
+ void STDMETHODCALLTYPE AcquireLock(CRITSEC_COOKIE lock);
+ void STDMETHODCALLTYPE ReleaseLock(CRITSEC_COOKIE lock);
+ EVENT_COOKIE STDMETHODCALLTYPE CreateAutoEvent(BOOL bInitialState);
+ EVENT_COOKIE STDMETHODCALLTYPE CreateManualEvent(BOOL bInitialState);
+ void STDMETHODCALLTYPE CloseEvent(EVENT_COOKIE event);
+ BOOL STDMETHODCALLTYPE ClrSetEvent(EVENT_COOKIE event);
+ BOOL STDMETHODCALLTYPE ClrResetEvent(EVENT_COOKIE event);
+ DWORD STDMETHODCALLTYPE WaitForEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable);
+ DWORD STDMETHODCALLTYPE WaitForSingleObject(HANDLE handle, DWORD dwMilliseconds);
+ SEMAPHORE_COOKIE STDMETHODCALLTYPE ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax);
+ void STDMETHODCALLTYPE ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore);
+ DWORD STDMETHODCALLTYPE ClrWaitForSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable);
+ BOOL STDMETHODCALLTYPE ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount);
+ MUTEX_COOKIE STDMETHODCALLTYPE ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,
+ BOOL bInitialOwner,
+ LPCTSTR lpName);
+ void STDMETHODCALLTYPE ClrCloseMutex(MUTEX_COOKIE mutex);
+ BOOL STDMETHODCALLTYPE ClrReleaseMutex(MUTEX_COOKIE mutex);
+ DWORD STDMETHODCALLTYPE ClrWaitForMutex(MUTEX_COOKIE mutex,
+ DWORD dwMilliseconds,
+ BOOL bAlertable);
+ DWORD STDMETHODCALLTYPE ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable);
+ BOOL STDMETHODCALLTYPE ClrAllocationDisallowed();
+ void STDMETHODCALLTYPE GetLastThrownObjectExceptionFromThread(void **ppvException);
+
+public:
+ // Added so we know where to make the real calls to.
+ IExecutionEngine *original_IEE;
+};
+
+#endif \ No newline at end of file
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp
new file mode 100644
index 0000000000..01bff37a01
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "standardpch.h"
+#include "runtimedetails.h"
+#include "spmiutil.h"
+#include "jithost.h"
+
+JitHost* g_ourJitHost;
+
+JitHost::JitHost(ICorJitHost* wrappedHost) : wrappedHost(wrappedHost)
+{
+}
+
+void* JitHost::allocateMemory(size_t size, bool usePageAllocator)
+{
+ return wrappedHost->allocateMemory(size, usePageAllocator);
+}
+
+void JitHost::freeMemory(void* block, bool usePageAllocator)
+{
+ return wrappedHost->freeMemory(block, usePageAllocator);
+}
+
+int JitHost::getIntConfigValue(const wchar_t* key, int defaultValue)
+{
+ return wrappedHost->getIntConfigValue(key, defaultValue);
+}
+
+const wchar_t* JitHost::getStringConfigValue(const wchar_t* key)
+{
+ return wrappedHost->getStringConfigValue(key);
+}
+
+void JitHost::freeStringConfigValue(const wchar_t* value)
+{
+ wrappedHost->freeStringConfigValue(value);
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/jithost.h b/src/ToolBox/superpmi/superpmi-shim-simple/jithost.h
new file mode 100644
index 0000000000..7df1c581dc
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/jithost.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _JITHOST
+#define _JITHOST
+
+class JitHost : public ICorJitHost
+{
+public:
+ JitHost(ICorJitHost* wrappedHost);
+
+#include "icorjithostimpl.h"
+
+private:
+ ICorJitHost* wrappedHost;
+};
+
+extern JitHost* g_ourJitHost;
+
+#endif
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp
new file mode 100644
index 0000000000..2381d0fa38
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp
@@ -0,0 +1,217 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//----------------------------------------------------------
+// SuperPMI-Shim.cpp - thin shim for the jit
+//----------------------------------------------------------
+
+#include "standardpch.h"
+#include "superpmi-shim-simple.h"
+#include "runtimedetails.h"
+#include "coreclrcallbacks.h"
+#include "icorjitcompiler.h"
+#include "errorhandling.h"
+#include "logging.h"
+#include "spmiutil.h"
+#include "jithost.h"
+
+HMODULE g_hRealJit = 0; //We leak this currently (could do the proper shutdown in process_detach)
+WCHAR* g_realJitPath = nullptr; //We leak this (could do the proper shutdown in process_detach)
+char* g_logFilePath = nullptr; //We *don't* leak this, hooray!
+WCHAR* g_HomeDirectory = nullptr;
+WCHAR* g_DefaultRealJitPath = nullptr;
+
+void SetDefaultPaths()
+{
+ if (g_HomeDirectory == nullptr)
+ {
+ g_HomeDirectory = GetEnvironmentVariableWithDefaultW(W("HOME"), W("."));
+ }
+
+ if (g_DefaultRealJitPath == nullptr)
+ {
+ size_t len = wcslen(g_HomeDirectory) + 1 + wcslen(DEFAULT_REAL_JIT_NAME_W) + 1;
+ g_DefaultRealJitPath = new WCHAR[len];
+ wcscpy_s(g_DefaultRealJitPath, len, g_HomeDirectory);
+ wcscat_s(g_DefaultRealJitPath, len, DIRECTORY_SEPARATOR_STR_W);
+ wcscat_s(g_DefaultRealJitPath, len, DEFAULT_REAL_JIT_NAME_W);
+ }
+}
+
+void SetLibName()
+{
+ if (g_realJitPath == nullptr)
+ {
+ g_realJitPath = GetEnvironmentVariableWithDefaultW(W("SuperPMIShimPath"), g_DefaultRealJitPath);
+ }
+}
+
+// TODO: this only works for ANSI file paths...
+void SetLogFilePath()
+{
+ if (g_logFilePath == nullptr)
+ {
+ // If the environment variable isn't set, we don't enable file logging
+ g_logFilePath = GetEnvironmentVariableWithDefaultA("SuperPMIShimLogFilePath", nullptr);
+ }
+}
+
+extern "C"
+BOOL
+#ifndef FEATURE_PAL
+APIENTRY
+#endif // !FEATURE_PAL
+DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+#ifdef FEATURE_PAL
+ if (0 != PAL_InitializeDLL())
+ {
+ fprintf(stderr, "Error: Fail to PAL_InitializeDLL\n");
+ exit(1);
+ }
+#endif // FEATURE_PAL
+
+ Logger::Initialize();
+ SetLogFilePath();
+ Logger::OpenLogFile(g_logFilePath);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ Logger::Shutdown();
+
+ delete[] g_logFilePath;
+ g_logFilePath = nullptr;
+
+ break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+// Exported via def file
+extern "C"
+void __stdcall jitStartup(ICorJitHost* host)
+{
+ SetDefaultPaths();
+ SetLibName();
+
+ //Load Library
+ if (g_hRealJit == 0)
+ {
+ g_hRealJit = ::LoadLibraryW(g_realJitPath);
+ if (g_hRealJit == 0)
+ {
+ LogError("getJit() - LoadLibrary failed to load '%ws' (0x%08x)", g_realJitPath, ::GetLastError());
+ return;
+ }
+ }
+
+ // Get the required entrypoint
+ PjitStartup pnjitStartup = (PjitStartup)::GetProcAddress(g_hRealJit, "jitStartup");
+ if (pnjitStartup == nullptr)
+ {
+ // This portion of the interface is not used by the JIT under test.
+ g_ourJitHost = nullptr;
+ return;
+ }
+
+ g_ourJitHost = new JitHost(host);
+ pnjitStartup(g_ourJitHost);
+}
+
+
+//Exported via def file
+extern "C"
+ICorJitCompiler* __stdcall getJit()
+{
+ DWORD dwRetVal = 0;
+ PgetJit pngetJit;
+ interceptor_ICJC *pJitInstance = nullptr;
+ ICorJitCompiler *tICJI = nullptr;
+
+ SetDefaultPaths();
+ SetLibName();
+
+ //Load Library
+ if(g_hRealJit == 0)
+ {
+ g_hRealJit = ::LoadLibraryW(g_realJitPath);
+ if(g_hRealJit == 0)
+ {
+ LogError("getJit() - LoadLibrary failed to load '%ws' (0x%08x)", g_realJitPath, ::GetLastError());
+ return nullptr;
+ }
+ }
+
+ //get the required entrypoints
+ pngetJit = (PgetJit)::GetProcAddress(g_hRealJit, "getJit");
+ if(pngetJit == 0)
+ {
+ LogError("getJit() - GetProcAddress 'getJit' failed (0x%08x)", ::GetLastError());
+ return nullptr;
+ }
+
+ tICJI = pngetJit();
+ if(tICJI == nullptr)
+ {
+ LogError("getJit() - pngetJit gave us null");
+ return nullptr;
+ }
+
+ pJitInstance = new interceptor_ICJC();
+ pJitInstance->original_ICorJitCompiler = tICJI;
+ return pJitInstance;
+}
+
+//Exported via def file
+extern "C"
+void __stdcall sxsJitStartup(CoreClrCallbacks const & original_cccallbacks)
+{
+ PsxsJitStartup pnsxsJitStartup;
+
+ SetDefaultPaths();
+ SetLibName();
+
+ //Load Library
+ if(g_hRealJit == 0)
+ {
+ g_hRealJit = ::LoadLibraryW(g_realJitPath);
+ if(g_hRealJit == 0)
+ {
+ LogError("sxsJitStartup() - LoadLibrary failed to load '%ws' (0x%08x)", g_realJitPath, ::GetLastError());
+ return;
+ }
+ }
+
+ //get entry point
+ pnsxsJitStartup = (PsxsJitStartup)::GetProcAddress(g_hRealJit, "sxsJitStartup");
+ if(pnsxsJitStartup == 0)
+ {
+ LogError("sxsJitStartup() - GetProcAddress 'sxsJitStartup' failed (0x%08x)", ::GetLastError());
+ return;
+ }
+
+ //Setup CoreClrCallbacks and call sxsJitStartup
+ original_CoreClrCallbacks = new CoreClrCallbacks();
+ original_CoreClrCallbacks->m_hmodCoreCLR = original_cccallbacks.m_hmodCoreCLR;
+ original_CoreClrCallbacks->m_pfnIEE = original_cccallbacks.m_pfnIEE;
+ original_CoreClrCallbacks->m_pfnGetCORSystemDirectory = original_cccallbacks.m_pfnGetCORSystemDirectory;
+ original_CoreClrCallbacks->m_pfnGetCLRFunction = original_cccallbacks.m_pfnGetCLRFunction;
+
+ CoreClrCallbacks *temp = new CoreClrCallbacks();
+
+ temp->m_hmodCoreCLR = original_cccallbacks.m_hmodCoreCLR;
+ temp->m_pfnIEE = IEE_t;
+ temp->m_pfnGetCORSystemDirectory = original_cccallbacks.m_pfnGetCORSystemDirectory;
+ temp->m_pfnGetCLRFunction = GetCLRFunction;
+
+ pnsxsJitStartup(*temp);
+}
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def
new file mode 100644
index 0000000000..436434c3de
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def
@@ -0,0 +1,5 @@
+LIBRARY
+EXPORTS
+ getJit
+ jitStartup
+ sxsJitStartup
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h
new file mode 100644
index 0000000000..2068a02775
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h
@@ -0,0 +1,13 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//----------------------------------------------------------
+// SuperPMI-Shim.h - thin shim for the jit
+//----------------------------------------------------------
+#ifndef _SuperPMIShim
+#define _SuperPMIShim
+
+
+#endif