in src/InstrumentationEngine/ProfilerManager.h [38:960]
class __declspec(uuid("324F817A-7420-4E6D-B3C1-143FBED6D855"))
CProfilerManager :
public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
#ifndef PLATFORM_UNIX
public ATL::CComCoClass<CProfilerManager, &__uuidof(CProfilerManager)>,
#else
public ATL::CComCoClass<CProfilerManager, &CLSID_CProfilerManager>,
#endif
public IProfilerManagerContract,
public ICorProfilerCallback7
{
private:
// Instrumentation methods can disabling profiling on this process before it starts by calling this during initialize.
bool m_bProfilingDisabled;
// Critical section that ensures sequencing of AppDomain unloading
CRITICAL_SECTION m_csForAppDomains;
// Critical section that protects data structures in this object that are manipulated on multiple threads
CRITICAL_SECTION m_cs;
// Critical section that synchronized JIT compilation callbacks to avoid
// data corruption when two threads attempt to compile the same method simultaneously
CRITICAL_SECTION m_csForJIT;
// Consider: expose this in the api? I'd rather there be a clr api for this instead.
ClrVersion m_attachedClrVersion;
COR_PRF_RUNTIME_TYPE m_runtimeType;
#ifndef PLATFORM_UNIX
// Free threaded marshaller instance.
CComPtr<IMarshal> m_pFTM;
#endif
// Pointer to the real ICorProfilerInfo from the clr
CComPtr<ICorProfilerInfo> m_pRealProfilerInfo;
// The wrapped ICorProfilerInfo implementation that allows for instrumentation method cooperation
CComPtr<ICorProfilerInfo> m_pWrappedProfilerInfo;
// list of instrumentation method configuration sources
vector<CComPtr<CConfigurationSource>> m_configSources;
// The configuration xml for profiler attach.
tstring m_tstrConfigXml;
// list of loaded instrumentation method guids
std::vector<GUID> m_instrumentationMethodGuids;
// Event that is used to synchronize the callback thread with the loading of the config path xml objects
CHandle m_hLoadInstrumentationMethodsCompleteEvent;
// list of instrumentation methods
TInstrumentationMethodsCollection m_instrumentationMethods;
// Event mask passed by raw handlers and instrumentation methods during initialize. This is bitwise union of the event mask
// from each of these sources. Note that this lives here instead of profiler manager because of the GetEventMask method
// that this object must return.
DWORD m_dwEventMask;
// High event mask used if raw handlers call SetEventMask2
DWORD m_dwEventMaskHigh;
// True if the call to Initialize is still on the stack
bool m_bIsInInitialize;
// True if we are currently initializing instrumentation method
bool m_bIsInitializingInstrumentationMethod;
// Flags set by instrumentation method
DWORD m_dwInstrumentationMethodFlags;
// If flag set - only trusted instrumentation methods can be loaded
bool m_bValidateCodeSignature;
// Map of method infos by function id. This is needed becasue some raw profiler
// callbacks only take a FunctionID instead of a moduleid / functionid
// these are cleaned up after instrumentation for the method is over.
std::unordered_map<FunctionID, CComPtr<CMethodInfo>> m_methodInfos;
// private nested class for holding the raw pointers to the callbacks.
// This just makes it easy to have the destructor do Release while allowing for
// caching the qi results.
class CProfilerCallbackHolder
{
// !!! Do NOT reference these fields directly !!!
// The CLR allows real-world profilers to return just the highest ICorProfilerCallback version in their QI
// which can cause nullptrs to appear when casting to a CComPTR of a different interface:
//
// // This code will implicitly QI the raw profiler for ICorProfilerCallback.
// CComPtr<ICorProfilerCallback> a = CProfilerCallbackHolder.m_CorProfilerCallback2;
//
// You should instead call GetMemberForInterface which will return the field matching the
// interface. The fields are populated via interface inheritance in order to match the CLR contract (see AddRawProfilerHook()).
public:
CComPtr<ICorProfilerCallback> m_CorProfilerCallback;
CComPtr<ICorProfilerCallback2> m_CorProfilerCallback2;
CComPtr<ICorProfilerCallback3> m_CorProfilerCallback3;
CComPtr<ICorProfilerCallback4> m_CorProfilerCallback4;
CComPtr<ICorProfilerCallback5> m_CorProfilerCallback5;
CComPtr<ICorProfilerCallback6> m_CorProfilerCallback6;
CComPtr<ICorProfilerCallback7> m_CorProfilerCallback7;
public:
IUnknown* GetMemberForInterface(REFGUID guidInterface)
{
if (guidInterface == __uuidof(ICorProfilerCallback))
{
return m_CorProfilerCallback;
}
else if (guidInterface == __uuidof(ICorProfilerCallback2))
{
return m_CorProfilerCallback2;
}
else if (guidInterface == __uuidof(ICorProfilerCallback3))
{
return m_CorProfilerCallback3;
}
else if (guidInterface == __uuidof(ICorProfilerCallback4))
{
return m_CorProfilerCallback4;
}
else if (guidInterface == __uuidof(ICorProfilerCallback5))
{
return m_CorProfilerCallback5;
}
else if (guidInterface == __uuidof(ICorProfilerCallback6))
{
return m_CorProfilerCallback6;
}
else if (guidInterface == __uuidof(ICorProfilerCallback7))
{
return m_CorProfilerCallback7;
}
else
{
CLogging::LogError(_T("CProfilerCallbackHolder::GetMemberForInterface Bogus interface member requested"));
return NULL;
}
}
};
// This is the client that asked to receive the raw ICorProfiler event
// model rather than using the simplified instrumentation method model.
//
// We use a raw pointer here to address perf issues around locks & critical sections
// that cause thread context switching. This implementation uses InterlockedExchange functions
// to read/write the pointer and will produce an expected memory leak since there are no
// lock-free guarantees to delete the object.
CProfilerCallbackHolder* m_profilerCallbackHolder;
CComPtr<CAppDomainCollection> m_pAppDomainCollection;
// Indicates that this profiler instance was initialized via attach (instead of initialized at CLR startup).
bool m_bAttach;
#ifndef PLATFORM_UNIX
CModuleHandle m_hRawProfilerModule;
#endif
public:
CProfilerManager();
~CProfilerManager();
// Public non interface methods
public:
#ifndef PLATFORM_UNIX
DECLARE_PROTECT_FINAL_CONSTRUCT()
DECLARE_REGISTRY_RESOURCEID(IDR_INSTRUMENTATIONENGINE)
#endif
HRESULT FinalConstruct();
static void FinalRelease();
void SetIsInInitialize(_In_ bool val);
bool GetIsInInitialize() const;
void SetIsInitializingInstrumentationMethod(_In_ bool val);
bool GetIsInitializingInstrumentationMethod() const;
void SetInitializingInstrumentationMethodFlags(_In_ DWORD dwFlags);
DWORD GetInitializingInstrumentationMethodFlags() const;
HRESULT GetEventMask(_Out_ DWORD* dwEventMask);
HRESULT SetEventMask(DWORD dwEventMask);
HRESULT GetEventMask2(_Out_ DWORD* dwEventMaskLow, _Out_ DWORD* dwEventMaskHigh);
HRESULT SetEventMask2(_In_ DWORD dwEventMaskLow, _In_ DWORD dwEventMaskHigh);
ClrVersion GetAttachedClrVersion() const;
// Returns the raw unwrapped profiler info instance.
HRESULT GetRealCorProfilerInfo(ICorProfilerInfo** ppRealProfilerInfo);
HRESULT CreateMethodInfo(
_In_ FunctionID functionId,
_Out_ CMethodInfo** ppMethodInfo
);
HRESULT CreateNewMethodInfo(_In_ FunctionID functionId, _Out_ CMethodInfo** ppMethodInfo);
HRESULT AddMethodInfoToMap(_In_ FunctionID functionId, _In_ CMethodInfo* pMethodInfo);
HRESULT RemoveMethodInfoFromMap(_In_ FunctionID functionId);
HRESULT GetMethodInfoById(_In_ FunctionID functionId, _Out_ CMethodInfo** ppMethodInfo);
// IUnknown
public:
BEGIN_COM_MAP(CProfilerManager)
COM_INTERFACE_ENTRY(IProfilerManager)
COM_INTERFACE_ENTRY(IProfilerManager2)
COM_INTERFACE_ENTRY(IProfilerManager3)
COM_INTERFACE_ENTRY(IProfilerManager4)
COM_INTERFACE_ENTRY(IProfilerManager5)
COM_INTERFACE_ENTRY(IProfilerStringManager)
COM_INTERFACE_ENTRY(IProfilerManagerLogging)
COM_INTERFACE_ENTRY(ICorProfilerCallback)
COM_INTERFACE_ENTRY(ICorProfilerCallback2)
COM_INTERFACE_ENTRY(ICorProfilerCallback3)
COM_INTERFACE_ENTRY(ICorProfilerCallback4)
COM_INTERFACE_ENTRY(ICorProfilerCallback5)
COM_INTERFACE_ENTRY(ICorProfilerCallback6)
COM_INTERFACE_ENTRY(ICorProfilerCallback7)
#ifndef PLATFORM_UNIX
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM.p)
#endif
END_COM_MAP()
// Private Helpers
private:
DWORD CalculateEventMask(DWORD dwAdditionalFlags);
HRESULT InitializeCore(
_In_ IUnknown* pCorProfilerInfoUnk
);
// The CLR doesn't initialize com before calling the profiler, and the profiler manager cannot do so itself
// as that would screw up the com state for the application thread. This thread allows the profiler manager
// to co create a free threaded version of msxml on a thread that it owns to avoid this.
//
// lpParameter points to the this pointer so m_configSources can be accessed. This is safe because the thread proc
// blocks until this is complete.
static DWORD WINAPI InstrumentationMethodThreadProc(
_In_ LPVOID lpParameter
);
// lpParameter points to the this pointer so m_wszConfigXml can be accessed. This is safe because the thread proc
// blocks until this is complete.
static DWORD WINAPI ParseAttachConfigurationThreadProc(
_In_ LPVOID lpParameter
);
/* Parses the following XML block of <Setting /> nodes into map of key-value pairs.
* Name and Value attributes for <Setting /> nodes are required.
* Duplicates are ignored.
* <Settings>
* <Setting Name="Key1" Value="Val1" />
* <Setting Name="Key2" Value="Val2" />
* <Setting Name="Key3" Value="Val3" />
* ...
* </Settings>
*/
static HRESULT ParseSettingsConfigurationNode(
_In_ const CComPtr<CXmlNode>& parentNode,
_Inout_ unordered_map<tstring, tstring>& settings);
HRESULT LoadInstrumentationMethods(_In_ CConfigurationSource* pConfigurationSource);
HRESULT DetermineClrVersion();
// Set the default event mask. This is union'd with the event mask from instrumentation methods and the host.
static DWORD GetDefaultEventMask();
//Template method to either QI or simple copy the InstrumentionMethod ComPtr. These methods support CopyInstrumentationMethods.
template<typename TInterfaceType>
HRESULT GetInterfaceType(CComPtr<IInstrumentationMethod>& pRawInstrumentationMethod, TInterfaceType** pInterface)
{
return pRawInstrumentationMethod->QueryInterface(__uuidof(TInterfaceType), (void**)pInterface);
}
template<>
HRESULT GetInterfaceType(CComPtr<IInstrumentationMethod>& pRawInstrumentationMethod, IInstrumentationMethod** pInterface)
{
return pRawInstrumentationMethod.CopyTo(pInterface);
}
template<typename TInterfaceType>
HRESULT CopyInstrumentationMethods(std::vector<CComPtr<TInterfaceType>>& callbackVector)
{
CCriticalSectionHolder lock(&m_cs);
HRESULT hr;
// Holding the lock during the callback functions is dangerous since rentrant
// events and calls will block. Copy the collection under the lock, then release it and finally call the callbacks
for (auto pCurrInstrumentationMethod : m_instrumentationMethods)
{
CComPtr<IInstrumentationMethod> pRawInstrumentationMethod;
IfFailRet(pCurrInstrumentationMethod.first->GetRawInstrumentationMethod(&pRawInstrumentationMethod));
CComPtr<TInterfaceType> pInterface;
if (SUCCEEDED(GetInterfaceType(pRawInstrumentationMethod, &pInterface)))
{
callbackVector.push_back(pInterface);
}
}
return S_OK;
}
template<typename TInterfaceType, typename TReturnType, typename... TParameters>
HRESULT SendEventToInstrumentationMethods(TReturnType(__stdcall TInterfaceType::*method)(TParameters...), TParameters... parameters)
{
HRESULT hr = S_OK;
vector<CComPtr<TInterfaceType>> callbackVector;
IfFailRet(CopyInstrumentationMethods(callbackVector));
// Send event to instrumentation methods
for (CComPtr<TInterfaceType> pInstrumentationMethod : callbackVector)
{
hr = (pInstrumentationMethod->*method)(parameters...);
CLogging::LogMessage(_T("Finished sending event to Instrumentation Method. hr=%04x"), hr);
}
return hr;
}
template<typename TFunc, typename... TParameters>
HRESULT ForEachInstrumentationMethod(TFunc func, TParameters... parameters)
{
HRESULT hr = S_OK;
vector<CComPtr<IInstrumentationMethod>> callbackVector;
IfFailRet(CopyInstrumentationMethods(callbackVector));
for (auto pInstrumentationMethod : callbackVector)
{
hr = func(pInstrumentationMethod, parameters...);
}
return hr;
}
template<typename TInterfaceType, typename TReturnType, typename... TParameters>
HRESULT SendEventToRawProfilerCallback(TReturnType(__stdcall TInterfaceType::*method)(TParameters...), TParameters... parameters)
{
HRESULT hr = S_OK;
CComPtr<TInterfaceType> pCallback;
CProfilerCallbackHolder* pProfilerCallbackHolder = static_cast<CProfilerCallbackHolder*>(InterlockedCompareExchangePointer(
(volatile PVOID*)&m_profilerCallbackHolder,
nullptr,
nullptr));
if (pProfilerCallbackHolder != nullptr)
{
pCallback = (TInterfaceType*)(pProfilerCallbackHolder->GetMemberForInterface(__uuidof(TInterfaceType)));
}
if (pCallback != nullptr)
{
hr = (pCallback->*method)(parameters...);
CLogging::LogMessage(_T("Finished Sending event to raw ICorProfilerCallback. hr=%04x"), hr);
}
return S_OK;
}
HRESULT ConstructAppDomainInfo(
_In_ AppDomainID appDomainId,
_Out_ IAppDomainInfo** ppAppDomainInfo
);
HRESULT ConstructAssemblyInfo(
_In_ AssemblyID assemblyId,
_Out_ IAssemblyInfo** ppAssemblInfo
);
HRESULT ConstructModuleInfo(
_In_ ModuleID moduleId,
_Out_ IModuleInfo** ppModuleInfo
);
HRESULT CreateMethodInfoForRejit(
_In_ ModuleID moduleId,
_In_ mdMethodDef methodToken,
_In_ ICorProfilerFunctionControl* pFunctionControl,
_Out_ CMethodInfo** ppMethodInfo
);
HRESULT SendFabricatedModuleUnloads(_In_ CAppDomainInfo* pRawAppdomainInfo);
HRESULT SendFabricatedAssemblyUnloads(_In_ CAppDomainInfo* pRawAppdomainInfo);
HRESULT ModuleUnloadStartedImpl(_In_ ModuleID moduleId);
HRESULT ModuleUnloadFinishedImpl(_In_ ModuleID moduleId, _In_ HRESULT hrStatus);
HRESULT AssemblyUnloadStartedImpl(_In_ AssemblyID assemblyId);
HRESULT AssemblyUnloadFinishedImpl(_In_ AssemblyID assemblyId, _In_ HRESULT hrStatus);
HRESULT InvokeThreadRoutine(
_In_ LPTHREAD_START_ROUTINE threadRoutine
);
#ifndef PLATFORM_UNIX
HRESULT SetupRawProfiler();
#endif
// IProfilerManager methods
public:
STDMETHOD(SetupProfilingEnvironment)(_In_reads_(numConfigPaths) BSTR bstrConfigPaths[], _In_ UINT numConfigPaths);
STDMETHOD(AddRawProfilerHook)(
_In_ IUnknown *pUnkProfilerCallback
);
STDMETHOD(RemoveRawProfilerHook)(
);
STDMETHOD(GetCorProfilerInfo)(
_Outptr_ IUnknown **ppCorProfiler
);
STDMETHOD(GetRuntimeType)(_Out_ COR_PRF_RUNTIME_TYPE* pRuntimeType);
// return the profiler host instance
STDMETHOD(GetProfilerHost)(_Out_ IProfilerManagerHost** ppProfilerManagerHost);
// Returns an instance of IProfilerManagerLogging which instrumentation methods can use
// to log to the profiler manager or optionally to the profiler host.
STDMETHOD(GetLoggingInstance)(_Out_ IProfilerManagerLogging** ppLogging);
// By default, logging messages are written to the debug output port. However,
// hosts can optionally signup to receive them through an instance of IProfilerManagerLoggingHost
STDMETHOD(SetLoggingHost)(_In_opt_ IProfilerManagerLoggingHost* pLoggingHost);
STDMETHOD(GetAppDomainCollection)(_Out_ IAppDomainCollection** ppAppDomainCollection);
STDMETHOD(CreateSignatureBuilder)(_Out_ ISignatureBuilder ** ppSignatureBuilder);
// Query the profiler manager for a pointer to another instrumentation method.
// Consumers can call QueryInterface to obtain an interface specific to that
// instrumentation method
STDMETHOD(GetInstrumentationMethod)(_In_ REFGUID cslid, _Out_ IUnknown** ppUnknown);
STDMETHOD(RemoveInstrumentationMethod)(_In_opt_ IInstrumentationMethod* pInstrumentationMethod);
// Registers a new instrumentation method in the profiler manager. Also calls its Initialize() method.
STDMETHOD(AddInstrumentationMethod)(_In_ BSTR bstrModulePath, _In_ BSTR bstrName, _In_ BSTR bstrDescription, _In_ BSTR bstrModule, _In_ BSTR bstrClassGuid, _In_ DWORD dwPriority, _Out_ IInstrumentationMethod** ppInstrumentationMethod);
// IProfilerManager2 Methods
public:
STDMETHOD(DisableProfiling)();
STDMETHOD(ApplyMetadata)(_In_ IModuleInfo* pMethodInfo);
// IProfilerManager3 Methods
public:
STDMETHOD(GetApiVersion)(_Out_ DWORD* pApiVer);
// IProfilerManager4 Methods
public:
STDMETHOD(GetGlobalLoggingInstance)(_Out_ IProfilerManagerLogging** ppLogging);
// IProfilerManager5 Methods
public:
STDMETHOD(IsInstrumentationMethodRegistered)(_In_ REFGUID clsid, _Out_ BOOL* pfRegistered);
// IProfilerManagerLogging Methods
public:
// If trace logging in enabled in the profiler manager, trace messages are sent to the
// profiler manager through this function.
STDMETHOD(LogMessage)(_In_ const WCHAR* wszMessage);
// Errors detected during profiling will be sent to the host through this method
STDMETHOD(LogError)(_In_ const WCHAR* wszError);
// If instrumentation result tracing is enabled, the detailed results of each instrumented
// method will be sent to the profiler manager host through this method.
STDMETHOD(LogDumpMessage)(_In_ const WCHAR* wszMessage);
// Called to cause logging to be written to the debug output port (via DebugOutputString) as well
// as to the host.
STDMETHOD(EnableDiagnosticLogToDebugPort)(_In_ BOOL enable);
// Allows instrumentation methods and hosts to ask for the current logging flags
STDMETHOD(GetLoggingFlags)(_Out_ LoggingFlags* pLoggingFlags);
// Allows instrumentation methods and hosts to modify the current logging flags
STDMETHOD(SetLoggingFlags)(_In_ LoggingFlags loggingFlags);
// IProfilerStringManager Methods
public:
STDMETHOD(FreeString)(_In_opt_ BSTR bstr)
{
return InstrumentationEngineFreeString(bstr);
}
// ICorProfilerCallback methods
public:
STDMETHOD(Initialize)(
_In_ IUnknown *pICorProfilerInfoUnk);
STDMETHOD(Shutdown)();
STDMETHOD(AppDomainCreationStarted)(
_In_ AppDomainID appDomainId
);
STDMETHOD(AppDomainCreationFinished)(
_In_ AppDomainID appDomainId,
_In_ HRESULT hrStatus
);
STDMETHOD(AppDomainShutdownStarted)(
_In_ AppDomainID appDomainId
);
STDMETHOD(AppDomainShutdownFinished)(
_In_ AppDomainID appDomainId,
_In_ HRESULT hrStatus
);
STDMETHOD(AssemblyLoadStarted)(
_In_ AssemblyID assemblyId
);
STDMETHOD(AssemblyLoadFinished)(
_In_ AssemblyID assemblyId,
_In_ HRESULT hrStatus
);
STDMETHOD(AssemblyUnloadStarted)(
_In_ AssemblyID assemblyId
);
STDMETHOD(AssemblyUnloadFinished)(
_In_ AssemblyID assemblyId,
_In_ HRESULT hrStatus
);
STDMETHOD(ModuleLoadStarted)(
_In_ ModuleID moduleId
);
STDMETHOD(ModuleLoadFinished)(
_In_ ModuleID moduleId,
_In_ HRESULT hrStatus
);
STDMETHOD(ModuleUnloadStarted)(
_In_ ModuleID moduleId
);
STDMETHOD(ModuleUnloadFinished)(
_In_ ModuleID moduleId,
_In_ HRESULT hrStatus
);
STDMETHOD(ModuleAttachedToAssembly)(
_In_ ModuleID moduleId,
_In_ AssemblyID AssemblyId
);
STDMETHOD(ClassLoadStarted)(
_In_ ClassID classId);
STDMETHOD(ClassLoadFinished)(
_In_ ClassID classId,
_In_ HRESULT hrStatus
);
STDMETHOD(ClassUnloadStarted)(
_In_ ClassID classId
);
STDMETHOD(ClassUnloadFinished)(
_In_ ClassID classId,
_In_ HRESULT hrStatus
);
STDMETHOD(FunctionUnloadStarted)(
_In_ FunctionID functionId
);
STDMETHOD(JITCompilationStarted)(
_In_ FunctionID functionId,
_In_ BOOL fIsSafeToBlock
);
STDMETHOD(JITCompilationFinished)(
_In_ FunctionID functionId,
_In_ HRESULT hrStatus,
_In_ BOOL fIsSafeToBlock
);
STDMETHOD(JITCachedFunctionSearchStarted)(
_In_ FunctionID functionId,
/* [out] */ BOOL *pbUseCachedFunction
);
STDMETHOD(JITCachedFunctionSearchFinished)(
_In_ FunctionID functionId,
_In_ COR_PRF_JIT_CACHE result
);
STDMETHOD(JITFunctionPitched)(
_In_ FunctionID functionId
);
STDMETHOD(JITInlining)(
_In_ FunctionID callerId,
_In_ FunctionID calleeId,
/* [out] */ BOOL *pfShouldInline
);
STDMETHOD(ThreadCreated)(
_In_ ThreadID threadId
);
STDMETHOD(ThreadDestroyed)(
_In_ ThreadID threadId
);
STDMETHOD(ThreadAssignedToOSThread)(
_In_ ThreadID managedThreadId,
_In_ DWORD osThreadId
);
STDMETHOD(RemotingClientInvocationStarted)();
STDMETHOD(RemotingClientSendingMessage)(
_In_ GUID *pCookie,
_In_ BOOL fIsAsync);
STDMETHOD(RemotingClientReceivingReply)(
_In_ GUID *pCookie,
_In_ BOOL fIsAsync);
STDMETHOD(RemotingClientInvocationFinished)();
STDMETHOD(RemotingServerReceivingMessage)(
_In_ GUID *pCookie,
_In_ BOOL fIsAsync
);
STDMETHOD(RemotingServerInvocationStarted)();
STDMETHOD(RemotingServerInvocationReturned)();
STDMETHOD(RemotingServerSendingReply)(
_In_ GUID *pCookie,
_In_ BOOL fIsAsync
);
STDMETHOD(UnmanagedToManagedTransition)(
_In_ FunctionID functionId,
_In_ COR_PRF_TRANSITION_REASON reason
);
STDMETHOD(ManagedToUnmanagedTransition)(
_In_ FunctionID functionId,
_In_ COR_PRF_TRANSITION_REASON reason
);
STDMETHOD(RuntimeSuspendStarted)(
_In_ COR_PRF_SUSPEND_REASON suspendReason
);
STDMETHOD(RuntimeSuspendFinished)();
STDMETHOD(RuntimeSuspendAborted)();
STDMETHOD(RuntimeResumeStarted)();
STDMETHOD(RuntimeResumeFinished)();
STDMETHOD(RuntimeThreadSuspended)(
_In_ ThreadID threadId);
STDMETHOD(RuntimeThreadResumed)(
_In_ ThreadID threadId
);
STDMETHOD(MovedReferences)(
_In_ ULONG cMovedObjectIDRanges,
_In_reads_(cMovedObjectIDRanges) ObjectID oldObjectIDRangeStart[],
_In_reads_(cMovedObjectIDRanges) ObjectID newObjectIDRangeStart[],
_In_reads_(cMovedObjectIDRanges) ULONG cObjectIDRangeLength[]
);
STDMETHOD(ObjectAllocated)(
_In_ ObjectID objectId,
_In_ ClassID classId
);
STDMETHOD(ObjectsAllocatedByClass)(
_In_ ULONG cClassCount,
_In_reads_(cClassCount) ClassID classIds[],
_In_reads_(cClassCount) ULONG cObjects[]
);
STDMETHOD(ObjectReferences)(
_In_ ObjectID objectId,
_In_ ClassID classId,
_In_ ULONG cObjectRefs,
_In_reads_(cObjectRefs) ObjectID objectRefIds[]
);
STDMETHOD(RootReferences)(
_In_ ULONG cRootRefs,
_In_reads_(cRootRefs) ObjectID rootRefIds[]
);
STDMETHOD(ExceptionThrown)(
_In_ ObjectID thrownObjectId
);
STDMETHOD(ExceptionSearchFunctionEnter)(
_In_ FunctionID functionId
);
STDMETHOD(ExceptionSearchFunctionLeave)();
STDMETHOD(ExceptionSearchFilterEnter)(
_In_ FunctionID functionId);
STDMETHOD(ExceptionSearchFilterLeave)();
STDMETHOD(ExceptionSearchCatcherFound)(
_In_ FunctionID functionId
);
STDMETHOD(ExceptionOSHandlerEnter)(
_In_ UINT_PTR __unused
);
STDMETHOD(ExceptionOSHandlerLeave)(
_In_ UINT_PTR __unused
);
STDMETHOD(ExceptionUnwindFunctionEnter)(
_In_ FunctionID functionId
);
STDMETHOD(ExceptionUnwindFunctionLeave)();
STDMETHOD(ExceptionUnwindFinallyEnter)(
_In_ FunctionID functionId
);
STDMETHOD(ExceptionUnwindFinallyLeave)();
STDMETHOD(ExceptionCatcherEnter)(
_In_ FunctionID functionId,
_In_ ObjectID objectId
);
STDMETHOD(ExceptionCatcherLeave)();
STDMETHOD(COMClassicVTableCreated)(
_In_ ClassID wrappedClassId,
_In_ REFGUID implementedIID,
_In_ void *pVTable,
_In_ ULONG cSlots
);
STDMETHOD(COMClassicVTableDestroyed)(
_In_ ClassID wrappedClassId,
_In_ REFGUID implementedIID,
_In_ void *pVTable
);
STDMETHOD(ExceptionCLRCatcherFound)();
STDMETHOD(ExceptionCLRCatcherExecute)();
// ICorProfilerCallback2 methods
public:
STDMETHOD(ThreadNameChanged)(
_In_ ThreadID threadId,
_In_ ULONG cchName,
_In_reads_opt_(cchName) WCHAR name[]
);
STDMETHOD(GarbageCollectionStarted)(
_In_ int cGenerations,
_In_reads_(cGenerations) BOOL generationCollected[],
_In_ COR_PRF_GC_REASON reason
);
STDMETHOD(SurvivingReferences)(
_In_ ULONG cSurvivingObjectIDRanges,
_In_reads_(cSurvivingObjectIDRanges) ObjectID objectIDRangeStart[],
_In_reads_(cSurvivingObjectIDRanges) ULONG cObjectIDRangeLength[]
);
STDMETHOD(GarbageCollectionFinished)();
STDMETHOD(FinalizeableObjectQueued)(
_In_ DWORD finalizerFlags,
_In_ ObjectID objectID
);
STDMETHOD(RootReferences2)(
_In_ ULONG cRootRefs,
_In_reads_(cRootRefs) ObjectID rootRefIds[],
_In_reads_(cRootRefs) COR_PRF_GC_ROOT_KIND rootKinds[],
_In_reads_(cRootRefs) COR_PRF_GC_ROOT_FLAGS rootFlags[],
_In_reads_(cRootRefs) UINT_PTR rootIds[]
);
STDMETHOD(HandleCreated)(
_In_ GCHandleID handleId,
_In_ ObjectID initialObjectId
);
STDMETHOD(HandleDestroyed)(
_In_ GCHandleID handleId
);
// ICorProfilerCallback3 methods
public:
STDMETHOD(InitializeForAttach)(
_In_ IUnknown *pCorProfilerInfoUnk,
_In_ void *pvClientData,
_In_ UINT cbClientData
);
STDMETHOD(ProfilerAttachComplete)(void);
STDMETHOD(ProfilerDetachSucceeded)(void);
// ICorProfilerCallback4 methods
public:
STDMETHOD(ReJITCompilationStarted)(
_In_ FunctionID functionId,
_In_ ReJITID rejitId,
_In_ BOOL fIsSafeToBlock
);
STDMETHOD(GetReJITParameters)(
_In_ ModuleID moduleId,
_In_ mdMethodDef methodToken,
_In_ ICorProfilerFunctionControl* pFunctionControl
);
STDMETHOD(ReJITCompilationFinished)(
_In_ FunctionID functionId,
_In_ ReJITID rejitId,
_In_ HRESULT hrStatus,
_In_ BOOL fIsSafeToBlock
);
STDMETHOD(ReJITError)(
_In_ ModuleID moduleId,
_In_ mdMethodDef methodId,
_In_ FunctionID functionId,
_In_ HRESULT hrStatus
);
STDMETHOD(MovedReferences2)(
_In_ ULONG cMovedObjectIDRanges,
_In_reads_(cMovedObjectIDRanges) ObjectID oldObjectIDRangeStart[],
_In_reads_(cMovedObjectIDRanges) ObjectID newObjectIDRangeStart[],
_In_reads_(cMovedObjectIDRanges) SIZE_T cObjectIDRangeLength[]
);
STDMETHOD(SurvivingReferences2)(
_In_ ULONG cSurvivingObjectIDRanges,
_In_reads_(cSurvivingObjectIDRanges) ObjectID objectIDRangeStart[],
_In_reads_(cSurvivingObjectIDRanges) SIZE_T cObjectIDRangeLength[]
);
// ICorProfilerCallback5 methods
public:
STDMETHOD(ConditionalWeakTableElementReferences)(
_In_ ULONG cRootRefs,
_In_reads_(cRootRefs) ObjectID keyRefIds[],
_In_reads_(cRootRefs) ObjectID valueRefIds[],
_In_reads_(cRootRefs) GCHandleID rootIds[]
);
//ICorProfilerCallback6 methods
public:
STDMETHOD(GetAssemblyReferences)(
_In_ const WCHAR *wszAssemblyPath,
_In_ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider);
//ICorProfilerCallback7 methods
public:
STDMETHOD(ModuleInMemorySymbolsUpdated)(
_In_ ModuleID moduleId);
// Internal public methods that are not part of interfaces.
public:
STDMETHOD(LogMessageEx)(_In_ const WCHAR* wszMessage, ...);
STDMETHOD(LogErrorEx)(_In_ const WCHAR* wszError, ...);
STDMETHOD(LogDumpMessageEx)(_In_ const WCHAR* wszMessage, ...);
private:
// Call ShouldInstrument on each instrumentation method. Return those that return true in pToInstrument
HRESULT CallShouldInstrumentOnInstrumentationMethods(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Inout_ vector<CComPtr<IInstrumentationMethod>>* pToInstrument);
// Call CallBeforeInstrumentMethodOnInstrumentationMethods on each instrumentation method.
HRESULT CallBeforeInstrumentMethodOnInstrumentationMethods(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _In_ vector<CComPtr<IInstrumentationMethod>>& toInstrument);
// Call InstrumentMethod on each instrumentation method.
HRESULT CallInstrumentOnInstrumentationMethods(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _In_ vector<CComPtr<IInstrumentationMethod>>& toInstrument);
// Call InstrumentMethod on each instrumentation method.
HRESULT CallOnInstrumentationComplete(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit);
HRESULT CallAllowInlineOnInstrumentationMethods(_In_ IMethodInfo* pInlineeMethodInfo, _In_ IMethodInfo* pInlineSiteMethodInfo, _Out_ BOOL* pbShouldInline);
// Registers a new instrumentation method in the profiler manager. Also calls its Initialize() method.
HRESULT AddInstrumentationMethod(_In_ CInstrumentationMethod* method, _In_ IEnumInstrumentationMethodSettings* pSettingsEnum, _Out_ IInstrumentationMethod** ppInstrumentationMethod);
HRESULT ClearILTransformationStatus(_In_ FunctionID functionId);
HRESULT ClearILTransformationStatus(_In_ ModuleID, _In_ mdMethodDef functionToken);
};