// ----------------------------------------------------------------------------------------------
// Copyright (c) Mattias H�gstr�m.
// ----------------------------------------------------------------------------------------------
// This source code is subject to terms and conditions of the Microsoft Public License. A
// copy of the license can be found in the License.html file at the root of this distribution.
// If you cannot locate the Microsoft Public License, please send an email to
// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
// by the terms of the Microsoft Public License.
// ----------------------------------------------------------------------------------------------
// You must not remove this notice, or any other, from this software.
// ----------------------------------------------------------------------------------------------
#include "stdafx.h"
#include <string>
#include "ILRewriteProfilerImpl.h"
#include "StringHelper.h"
#include "ProfilerLoggers.h"
#include "ILRewriter.h"
#include "FunctionInfo.h"
#include "OpCodeParser.h"
#include "MetadataHelper.h"
#include "InterceptAPI.h"
//#include "ILRewriteConsoleLogger.h"
//#include "ILRewriteDebugLogger.h"
#include <wchar.h>
#include <corhlpr.h>
#include <memory>
#pragma comment(lib, "CorGuids.lib")
CRITICAL_SECTION g_cs_ilRewite;
void ILRewriteProfilerImpl::Check(HRESULT hr)
{
if (hr != S_OK)
throw "HRESULT is != S_OK";
}
HRESULT ILRewriteProfilerImpl::SetEventMask()
{
//COR_PRF_MONITOR_NONE = 0,
//COR_PRF_MONITOR_FUNCTION_UNLOADS = 0x1,
//COR_PRF_MONITOR_CLASS_LOADS = 0x2,
//COR_PRF_MONITOR_MODULE_LOADS = 0x4,
//COR_PRF_MONITOR_ASSEMBLY_LOADS = 0x8,
//COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x10,
//COR_PRF_MONITOR_JIT_COMPILATION = 0x20,
//COR_PRF_MONITOR_EXCEPTIONS = 0x40,
//COR_PRF_MONITOR_GC = 0x80,
//COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x100,
//COR_PRF_MONITOR_THREADS = 0x200,
//COR_PRF_MONITOR_REMOTING = 0x400,
//COR_PRF_MONITOR_CODE_TRANSITIONS = 0x800,
//COR_PRF_MONITOR_ENTERLEAVE = 0x1000,
//COR_PRF_MONITOR_CCW = 0x2000,
//COR_PRF_MONITOR_REMOTING_COOKIE = 0x4000 | COR_PRF_MONITOR_REMOTING,
//COR_PRF_MONITOR_REMOTING_ASYNC = 0x8000 | COR_PRF_MONITOR_REMOTING,
//COR_PRF_MONITOR_SUSPENDS = 0x10000,
//COR_PRF_MONITOR_CACHE_SEARCHES = 0x20000,
//COR_PRF_MONITOR_CLR_EXCEPTIONS = 0x1000000,
//COR_PRF_MONITOR_ALL = 0x107ffff,
//COR_PRF_ENABLE_REJIT = 0x40000,
//COR_PRF_ENABLE_INPROC_DEBUGGING = 0x80000,
//COR_PRF_ENABLE_JIT_MAPS = 0x100000,
//COR_PRF_DISABLE_INLINING = 0x200000,
//COR_PRF_DISABLE_OPTIMIZATIONS = 0x400000,
//COR_PRF_ENABLE_OBJECT_ALLOCATED = 0x800000,
// New in VS2005
//COR_PRF_ENABLE_FUNCTION_ARGS = 0x2000000,
//COR_PRF_ENABLE_FUNCTION_RETVAL = 0x4000000,
//COR_PRF_ENABLE_FRAME_INFO = 0x8000000,
//COR_PRF_ENABLE_STACK_SNAPSHOT = 0x10000000,
//COR_PRF_USE_PROFILE_IMAGES = 0x20000000,
// End New in VS2005
//COR_PRF_ALL = 0x3fffffff,
//COR_PRF_MONITOR_IMMUTABLE = COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_REMOTING | COR_PRF_MONITOR_REMOTING_COOKIE | COR_PRF_MONITOR_REMOTING_ASYNC | COR_PRF_MONITOR_GC | COR_PRF_ENABLE_REJIT | COR_PRF_ENABLE_INPROC_DEBUGGING | COR_PRF_ENABLE_JIT_MAPS | COR_PRF_DISABLE_OPTIMIZATIONS | COR_PRF_DISABLE_INLINING | COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO | COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_USE_PROFILE_IMAGES
// set the event mask
//DWORD eventMask = (DWORD)(COR_PRF_MONITOR_ENTERLEAVE);
DWORD eventMask = COR_PRF_MONITOR_NONE;
//eventMask |= COR_PRF_MONITOR_THREADS; // create / delete thread
eventMask |= COR_PRF_MONITOR_JIT_COMPILATION;
//eventMask |= COR_PRF_MONITOR_MODULE_LOADS;
//
//eventMask |= COR_PRF_MONITOR_CODE_TRANSITIONS;
//eventMask |= COR_PRF_MONITOR_SUSPENDS;
// eventMask |= COR_PRF_ENABLE_STACK_SNAPSHOT;
// eventMask |= COR_PRF_MONITOR_SUSPENDS;
eventMask |= COR_PRF_DISABLE_INLINING;
eventMask |= COR_PRF_DISABLE_OPTIMIZATIONS;
// eventMask | = COR_PRF_MONITOR_IMMUTABLE;
return m_corProfilerInfo->SetEventMask(eventMask);
}
STDMETHODIMP ILRewriteProfilerImpl::QueryInterface(
REFIID riid ,
void **ppObj)
{
LPOLESTR clsid = nullptr;
HRESULT hr = StringFromCLSID(riid, &clsid);
if (SUCCEEDED(hr))
{
std::wstring clsidString(clsid);
g_debugLogger << "ILRewriteProfilerImpl::QueryInterface(" << ConvertStlString(clsidString).c_str() << ")" << std::endl;
::CoTaskMemFree(clsid);
}
if (riid == IID_IUnknown)
{
*ppObj = this;
AddRef() ;
g_debugLogger.WriteLine("QueryInterface -> IUnknown");
return S_OK;
}
if (riid == IID_ILRewriteProfiler)
{
*ppObj = static_cast<ILRewriteProfiler*>(this) ;
AddRef() ;
g_debugLogger.WriteLine("QueryInterface -> IDiagProfiler");
return S_OK;
}
if (riid == IID_ICorProfilerCallback)
{
*ppObj = static_cast<ICorProfilerCallback*>(this) ;
AddRef() ;
g_debugLogger.WriteLine("QueryInterface -> ICorProfilerCallback");
return S_OK;
}
if (riid == IID_ICorProfilerCallback2)
{
*ppObj = static_cast<ICorProfilerCallback2*>(this) ;
AddRef();
g_debugLogger.WriteLine("QueryInterface -> ICorProfilerCallback2");
return S_OK;
}
if (riid == IID_ICorProfilerCallback3)
{
*ppObj = dynamic_cast<ICorProfilerCallback3*>(this) ;
AddRef();
g_debugLogger.WriteLine("QueryInterface -> ICorProfilerCallback");
return S_OK;
}
if (riid == IID_ICorProfilerInfo)
{
g_debugLogger.WriteLine("QueryInterface -> ICorProfilerInfo");
*ppObj = m_corProfilerInfo;
return S_OK;
}
if (riid == IID_ICorProfilerInfo2)
{
g_debugLogger.WriteLine("QueryInterface -> ICorProfilerInfo2");
*ppObj = m_corProfilerInfo2;
return S_OK;
}
*ppObj = NULL ;
g_debugLogger.WriteLine("QueryInterface -> E_NOINTERFACE");
return E_NOINTERFACE ;
}
ULONG STDMETHODCALLTYPE ILRewriteProfilerImpl::AddRef()
{
return InterlockedIncrement(&m_nRefCount) ;
}
ULONG STDMETHODCALLTYPE ILRewriteProfilerImpl::Release()
{
long nRefCount=0;
nRefCount=InterlockedDecrement(&m_nRefCount) ;
if (nRefCount == 0)
{
g_debugLogger.Close();
}
return nRefCount;
}
STDMETHODIMP ILRewriteProfilerImpl::ProfilerAttachComplete(void)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ProfilerDetachSucceeded(void)
{
return S_OK;
};
STDMETHODIMP ILRewriteProfilerImpl::InitializeForAttach(
/* [in] */ IUnknown *pCorProfilerInfoUnk,
/* [in] */ void *pvClientData,
/* [in] */ UINT cbClientData)
{
return S_OK;
}
//
// Called when a profiler is attached using environment variables
//
STDMETHODIMP ILRewriteProfilerImpl::Initialize(IUnknown *pICorProfilerInfoUnk)
{
g_debugLogger.WriteLine("ILRewriteProfilerImpl::Initialize()");
// get the ICorProfilerInfo interface
HRESULT hr = pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo, (LPVOID*)&m_corProfilerInfo);
if (FAILED(hr))
{
g_debugLogger.WriteLine("Error: Failed to get ICorProfilerInfo");
return E_FAIL;
}
else
{
g_debugLogger.WriteLine("Got ICorProfilerInfo");
}
hr = pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo2, (LPVOID*)&m_corProfilerInfo2);
if (FAILED(hr))
{
m_corProfilerInfo2 = nullptr;
g_debugLogger.WriteLine("Error: Failed to get ICorProfiler2");
}
else
{
g_debugLogger.WriteLine("Got ICorProfilerInfo2");
}
// Tell the profiler API which events we want to listen to
// Some events fail when we attach afterwards
hr = SetEventMask();
if (FAILED(hr))
{
g_debugLogger.WriteLine("Error: Failed to set event mask");
}
else
{
g_debugLogger.WriteLine("SetEventMask()");
}
g_debugLogger.WriteLine("Successfully initialized profiling");
//g_debugLogger.WriteLine("Deactivating echo to OutputDebug");
// We do not need echo to OutputDebugString
//g_profilerData.m_debugLogger.Echo2OutputDebug(false);
m_rewritehelper.SetCorProfilerInfo(m_corProfilerInfo);
InitializeCriticalSection(&g_cs_ilRewite);
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ThreadAssignedToOSThread(ThreadID managedThreadID, DWORD osThreadID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::Shutdown()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AppDomainCreationStarted(AppDomainID appDomainID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AppDomainCreationFinished(AppDomainID appDomainID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AppDomainShutdownStarted(AppDomainID appDomainID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AppDomainShutdownFinished(AppDomainID appDomainID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AssemblyLoadStarted(AssemblyID assemblyID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AssemblyLoadFinished(AssemblyID assemblyID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AssemblyUnloadStarted(AssemblyID assemblyID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::AssemblyUnloadFinished(AssemblyID assemblyID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ModuleLoadStarted(ModuleID moduleID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ModuleLoadFinished(ModuleID moduleID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ModuleUnloadStarted(ModuleID moduleID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ModuleUnloadFinished(ModuleID moduleID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ModuleAttachedToAssembly(ModuleID moduleID, AssemblyID assemblyID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ClassLoadStarted(ClassID classID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ClassLoadFinished(ClassID classID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ClassUnloadStarted(ClassID classID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ClassUnloadFinished(ClassID classID, HRESULT hrStatus)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::FunctionUnloadStarted(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITCompilationStarted(FunctionID functionID, BOOL fIsSafeToBlock)
{
EnterCriticalSection(&g_cs_ilRewite);
std::ostringstream o;
o << "ILRewriteProfilerImpl::JITCompilationStarted(";
o << functionID;
o << ")" << std::endl;
std::string msg = o.str();
g_debugLogger << msg.c_str();
FunctionInfo* functionInfo = m_rewritehelper.CreateFunctionInfo(functionID);
if (!functionInfo->IsValid())
return S_OK;
//ILRewriteDebugLogger ilDebugLogger = ILRewriteDebugLogger(m_corProfilerInfo, functionInfo);
std::auto_ptr<ILRewriter> rewriter(m_rewritehelper.CreateILRewriter(nullptr /*&ilDebugLogger*/, functionInfo));
if (rewriter->CanRewrite())
{
// Add Prelude
// g_debugLogger code writes to OutputDebug
// Use DebugView.exe to see the logs
ULONG oldSize = rewriter->GetOldMethodSize();
LPCBYTE oldBytes = rewriter->GetOldMethodBytes();
std::string hexStringOldBytes = PrintHex(oldBytes, oldSize);
g_debugLogger << "Old ILBytes " << hexStringOldBytes << std::endl;
g_debugLogger << "CanRewrite == True" << std::endl;
LPBYTE newBytes = (LPBYTE) rewriter->GetNewILBytes();
ULONG newSize = rewriter->GetNewMethodSize();
std::string hexStringNewBytes = PrintHex(newBytes, newSize);
g_debugLogger << "New ILBytes " << hexStringNewBytes << std::endl;
{
// Replace calls to DateTime.Now
// This is just a reference sample
// It is easy to replace methods with other methods having the exact same signature
// It is just a question of changing the "function pointer", the mdMemberRef token
COR_ILMETHOD_TINY* tiny = reinterpret_cast<COR_ILMETHOD_TINY*>(newBytes);
ULONG codeSize = 0;
BYTE* codeOffset = nullptr;
if (tiny->IsTiny())
{
codeSize = tiny->GetCodeSize();
codeOffset = tiny->GetCode();
}
else
{
COR_ILMETHOD_FAT* fat = reinterpret_cast<COR_ILMETHOD_FAT*>(newBytes);
codeSize = fat->CodeSize;
codeOffset = fat->GetCode();
}
ULONG replaceCount = InterceptAPI::ReplaceDateTimeNowCalls(m_corProfilerInfo, functionInfo->GetModuleID(), codeOffset, codeSize);
if (replaceCount != 0)
{
g_debugLogger << "Replaced DateTime::Now #" << replaceCount << " times" << std::endl;
}
}
Check(m_corProfilerInfo->SetILFunctionBody(functionInfo->GetModuleID(), functionInfo->GetToken(), newBytes));
}
else
{
g_debugLogger << "CanRewrite == False" << std::endl;
}
LeaveCriticalSection(&g_cs_ilRewite);
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITCompilationFinished(FunctionID functionID, HRESULT hrStatus, BOOL fIsSafeToBlock)
{
std::ostringstream o;
o << "ILRewriteProfilerImpl::JITCompilationFinished(";
o << functionID;
o << ")" << std::endl << std::endl;
std::string msg = o.str();
g_debugLogger << msg.c_str();
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITCachedFunctionSearchStarted(FunctionID functionID, BOOL *pbUseCachedFunction)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITCachedFunctionSearchFinished(FunctionID functionID, COR_PRF_JIT_CACHE result)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITFunctionPitched(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::JITInlining(FunctionID callerID, FunctionID calleeID, BOOL *pfShouldInline)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::UnmanagedToManagedTransition(FunctionID functionID, COR_PRF_TRANSITION_REASON reason)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ManagedToUnmanagedTransition(FunctionID functionID, COR_PRF_TRANSITION_REASON reason)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ThreadCreated(ThreadID threadID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ThreadDestroyed(ThreadID threadID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingClientInvocationStarted()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingClientSendingMessage(GUID *pCookie, BOOL fIsAsync)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingClientReceivingReply(GUID *pCookie, BOOL fIsAsync)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingClientInvocationFinished()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingServerReceivingMessage(GUID *pCookie, BOOL fIsAsync)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingServerInvocationStarted()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingServerInvocationReturned()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RemotingServerSendingReply(GUID *pCookie, BOOL fIsAsync)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeSuspendFinished()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeSuspendAborted()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeResumeStarted()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeResumeFinished()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeThreadSuspended(ThreadID threadID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RuntimeThreadResumed(ThreadID threadID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::MovedReferences(ULONG cmovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], ObjectID newObjectIDRangeStart[], ULONG cObjectIDRangeLength[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ObjectAllocated(ObjectID objectID, ClassID classID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ObjectsAllocatedByClass(ULONG classCount, ClassID classIDs[], ULONG objects[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ObjectReferences(ObjectID objectID, ClassID classID, ULONG objectRefs, ObjectID objectRefIDs[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RootReferences(ULONG rootRefs, ObjectID rootRefIDs[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionThrown(ObjectID thrownObjectID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionUnwindFunctionEnter(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionUnwindFunctionLeave()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionSearchFunctionEnter(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionSearchFunctionLeave()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionSearchFilterEnter(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionSearchFilterLeave()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionSearchCatcherFound(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionCLRCatcherFound()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionCLRCatcherExecute()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionOSHandlerEnter(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionOSHandlerLeave(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionUnwindFinallyEnter(FunctionID functionID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionUnwindFinallyLeave()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionCatcherEnter(FunctionID functionID,
ObjectID objectID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ExceptionCatcherLeave()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::COMClassicVTableCreated(ClassID wrappedClassID, REFGUID implementedIID, void *pVTable, ULONG cSlots)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::COMClassicVTableDestroyed(ClassID wrappedClassID, REFGUID implementedIID, void *pVTable)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::ThreadNameChanged(ThreadID threadID, ULONG cchName, WCHAR name[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::SurvivingReferences(ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], ULONG cObjectIDRangeLength[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::GarbageCollectionFinished()
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::FinalizeableObjectQueued(DWORD finalizerFlags, ObjectID objectID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::RootReferences2(ULONG cRootRefs, ObjectID rootRefIDs[], COR_PRF_GC_ROOT_KIND rootKinds[], COR_PRF_GC_ROOT_FLAGS rootFlags[], UINT_PTR rootIDs[])
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::HandleCreated(GCHandleID handleID, ObjectID initialObjectID)
{
return S_OK;
}
STDMETHODIMP ILRewriteProfilerImpl::HandleDestroyed(GCHandleID handleID)
{
return S_OK;
}