-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy pathCorProfilerCallback.h
More file actions
346 lines (313 loc) · 19.2 KB
/
Copy pathCorProfilerCallback.h
File metadata and controls
346 lines (313 loc) · 19.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.
#pragma once
// from dotnet coreclr includes
#include "cor.h"
#include "corprof.h"
// end
#include "AllocationsProvider.h"
#include "ApplicationStore.h"
#include "CallstackProvider.h"
#include "EventPipeEventsManager.h"
#include "ExceptionsProvider.h"
#include "IAppDomainStore.h"
#include "IClrLifetime.h"
#include "IConfiguration.h"
#include "IDebugInfoStore.h"
#include "IExporter.h"
#include "IFrameStore.h"
#include "IMetricsSender.h"
#include "ISamplesProvider.h"
#include "ISsiManager.h"
#include "WallTimeProvider.h"
#include "CpuTimeProvider.h"
#include "SamplesCollector.h"
#include "GarbageCollectionProvider.h"
#include "StopTheWorldGCProvider.h"
#include "LiveObjectsProvider.h"
#include "IRuntimeInfo.h"
#include "IEnabledProfilers.h"
#include "MemoryResourceManager.h"
#include "MetricsRegistry.h"
#include "ProxyMetric.h"
#include "IAllocationsRecorder.h"
#include "IMetadataProvider.h"
#include "shared/src/native-src/string.h"
#include "ThreadLifetimeProvider.h"
#ifdef LINUX
#include "RingBuffer.h"
#include "TimerCreateCpuProfiler.h"
#endif
#include "IEtwEventsManager.h"
#include "ISsiLifetime.h"
#include "HeapSnapshotManager.h"
#include "GCThreadsCpuProvider.h"
#include "PInvoke.h"
#include "shared/src/native-src/dd_memory_resource.hpp"
#include <atomic>
#include <memory>
#include <vector>
class ContentionProvider;
class IService;
class IThreadsCpuManager;
class IManagedThreadList;
class INativeThreadList;
class StackSamplerLoop;
class StackSamplerLoopManager;
class StackFramesCollectorBase;
class IConfiguration;
class IExporter;
class RawSampleTransformer;
class RuntimeIdStore;
class CpuSampleProvider;
class ManagedCodeCache;
class NetworkProvider;
class IUnwinder;
class UnwindingRecorderFactory;
#ifdef LINUX
class SystemCallsShield;
#endif
namespace shared {
class Loader;
}
class CorProfilerCallback : public ICorProfilerCallback10, public ISsiLifetime
{
public:
CorProfilerCallback(std::shared_ptr<IConfiguration> pConfiguration);
virtual ~CorProfilerCallback();
// use STDMETHODCALLTYPE macro to match the CLR declaration.
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override;
ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override;
ULONG STDMETHODCALLTYPE GetRefCount() const;
HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk) override;
HRESULT STDMETHODCALLTYPE Shutdown() override;
HRESULT STDMETHODCALLTYPE AppDomainCreationStarted(AppDomainID appDomainId) override;
HRESULT STDMETHODCALLTYPE AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE AppDomainShutdownStarted(AppDomainID appDomainId) override;
HRESULT STDMETHODCALLTYPE AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE AssemblyLoadStarted(AssemblyID assemblyId) override;
HRESULT STDMETHODCALLTYPE AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE AssemblyUnloadStarted(AssemblyID assemblyId) override;
HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE ModuleLoadStarted(ModuleID moduleId) override;
HRESULT STDMETHODCALLTYPE ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE ModuleUnloadStarted(ModuleID moduleId) override;
HRESULT STDMETHODCALLTYPE ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) override;
HRESULT STDMETHODCALLTYPE ClassLoadStarted(ClassID classId) override;
HRESULT STDMETHODCALLTYPE ClassLoadFinished(ClassID classId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE ClassUnloadStarted(ClassID classId) override;
HRESULT STDMETHODCALLTYPE ClassUnloadFinished(ClassID classId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE FunctionUnloadStarted(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchStarted(FunctionID functionId, BOOL* pbUseCachedFunction) override;
HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result) override;
HRESULT STDMETHODCALLTYPE JITFunctionPitched(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE JITInlining(FunctionID callerId, FunctionID calleeId, BOOL* pfShouldInline) override;
HRESULT STDMETHODCALLTYPE ThreadCreated(ThreadID threadId) override;
HRESULT STDMETHODCALLTYPE ThreadDestroyed(ThreadID threadId) override;
HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) override;
HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted() override;
HRESULT STDMETHODCALLTYPE RemotingClientSendingMessage(GUID* pCookie, BOOL fIsAsync) override;
HRESULT STDMETHODCALLTYPE RemotingClientReceivingReply(GUID* pCookie, BOOL fIsAsync) override;
HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished() override;
HRESULT STDMETHODCALLTYPE RemotingServerReceivingMessage(GUID* pCookie, BOOL fIsAsync) override;
HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted() override;
HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned() override;
HRESULT STDMETHODCALLTYPE RemotingServerSendingReply(GUID* pCookie, BOOL fIsAsync) override;
HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override;
HRESULT STDMETHODCALLTYPE ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override;
HRESULT STDMETHODCALLTYPE RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) override;
HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished() override;
HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted() override;
HRESULT STDMETHODCALLTYPE RuntimeResumeStarted() override;
HRESULT STDMETHODCALLTYPE RuntimeResumeFinished() override;
HRESULT STDMETHODCALLTYPE RuntimeThreadSuspended(ThreadID threadId) override;
HRESULT STDMETHODCALLTYPE RuntimeThreadResumed(ThreadID threadId) override;
HRESULT STDMETHODCALLTYPE MovedReferences(ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], ObjectID newObjectIDRangeStart[], ULONG cObjectIDRangeLength[]) override;
HRESULT STDMETHODCALLTYPE ObjectAllocated(ObjectID objectId, ClassID classId) override;
HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]) override;
HRESULT STDMETHODCALLTYPE ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]) override;
HRESULT STDMETHODCALLTYPE RootReferences(ULONG cRootRefs, ObjectID rootRefIds[]) override;
HRESULT STDMETHODCALLTYPE ExceptionThrown(ObjectID thrownObjectId) override;
HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave() override;
HRESULT STDMETHODCALLTYPE ExceptionSearchFilterEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave() override;
HRESULT STDMETHODCALLTYPE ExceptionSearchCatcherFound(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionOSHandlerEnter(UINT_PTR __unused) override;
HRESULT STDMETHODCALLTYPE ExceptionOSHandlerLeave(UINT_PTR __unused) override;
HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave() override;
HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave() override;
HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) override;
HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave() override;
HRESULT STDMETHODCALLTYPE COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void* pVTable, ULONG cSlots) override;
HRESULT STDMETHODCALLTYPE COMClassicVTableDestroyed(ClassID wrappedClassId, REFGUID implementedIID, void* pVTable) override;
HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound() override;
HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute() override;
HRESULT STDMETHODCALLTYPE ThreadNameChanged(ThreadID threadId, ULONG cchName, WCHAR name[]) override;
HRESULT STDMETHODCALLTYPE GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) override;
HRESULT STDMETHODCALLTYPE SurvivingReferences(ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], ULONG cObjectIDRangeLength[]) override;
HRESULT STDMETHODCALLTYPE GarbageCollectionFinished() override;
HRESULT STDMETHODCALLTYPE FinalizeableObjectQueued(DWORD finalizerFlags, ObjectID objectID) override;
HRESULT STDMETHODCALLTYPE RootReferences2(ULONG cRootRefs, ObjectID rootRefIds[], COR_PRF_GC_ROOT_KIND rootKinds[], COR_PRF_GC_ROOT_FLAGS rootFlags[], UINT_PTR rootIds[]) override;
HRESULT STDMETHODCALLTYPE HandleCreated(GCHandleID handleId, ObjectID initialObjectId) override;
HRESULT STDMETHODCALLTYPE HandleDestroyed(GCHandleID handleId) override;
HRESULT STDMETHODCALLTYPE InitializeForAttach(IUnknown* pCorProfilerInfoUnk, void* pvClientData, UINT cbClientData) override;
HRESULT STDMETHODCALLTYPE ProfilerAttachComplete() override;
HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded() override;
HRESULT STDMETHODCALLTYPE ReJITCompilationStarted(FunctionID functionId, ReJITID rejitId, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl* pFunctionControl) override;
HRESULT STDMETHODCALLTYPE ReJITCompilationFinished(FunctionID functionId, ReJITID rejitId, HRESULT hrStatus, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) override;
HRESULT STDMETHODCALLTYPE MovedReferences2(ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], ObjectID newObjectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) override;
HRESULT STDMETHODCALLTYPE SurvivingReferences2(ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) override;
HRESULT STDMETHODCALLTYPE ConditionalWeakTableElementReferences(ULONG cRootRefs, ObjectID keyRefIds[], ObjectID valueRefIds[], GCHandleID rootIds[]) override;
HRESULT STDMETHODCALLTYPE GetAssemblyReferences(const WCHAR* wszAssemblyPath, ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) override;
HRESULT STDMETHODCALLTYPE ModuleInMemorySymbolsUpdated(ModuleID moduleId) override;
HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) override;
HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE DynamicMethodUnloaded(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE EventPipeEventDelivered(EVENTPIPE_PROVIDER provider,
DWORD eventId,
DWORD eventVersion,
ULONG cbMetadataBlob,
LPCBYTE metadataBlob,
ULONG cbEventData,
LPCBYTE eventData,
LPCGUID pActivityId,
LPCGUID pRelatedActivityId,
ThreadID eventThread,
ULONG numStackFrames,
UINT_PTR stackFrames[]) override;
HRESULT STDMETHODCALLTYPE EventPipeProviderCreated(EVENTPIPE_PROVIDER provider) override;
public:
// One and only instance of CorProfilerCallback
// from which services could be retrieved
static CorProfilerCallback* GetInstance()
{
return _this;
}
std::string const& GetRuntimeDescription()
{
return _runtimeDescription;
}
IClrLifetime* GetClrLifetime() const;
// ISsiLifetime implementation
// for SSI, the services need to be started after the runtime is initialized
void OnStartDelayedProfiling() override;
// for Stable Configuration, the managed layer will enable/disable the profiler
// but also will provide values "dynamically" computed for environment/version/service name
bool SetConfiguration(shared::StableConfig::SharedConfig config);
// Access to global services
// All services are allocated/started and stopped/deleted by the CorProfilerCallback (no need to use unique_ptr/shared_ptr)
// Their lifetime lasts between Initialize() and Shutdown()
public:
IThreadsCpuManager* GetThreadsCpuManager() { return _pThreadsCpuManager; }
IManagedThreadList* GetManagedThreadList() { return _pManagedThreadList; }
IManagedThreadList* GetCodeHotspotThreadList() { return _pCodeHotspotsThreadList; }
//IStackSamplerLoopManager* GetStackSamplerLoopManager() { return _pStackSamplerLoopManager; }
IApplicationStore* GetApplicationStore() { return _pApplicationStore; }
IExporter* GetExporter() { return _pExporter.get(); }
SamplesCollector* GetSamplesCollector() { return _pSamplesCollector; }
void TraceContextHasBeenSet() { _pSsiManager->OnSpanCreated(); }
private :
static CorProfilerCallback* _this;
std::string _runtimeDescription;
std::unique_ptr<IClrLifetime> _pClrLifetime = nullptr;
std::atomic<ULONG> _refCount{0};
ICorProfilerInfo5* _pCorProfilerInfo = nullptr;
ICorProfilerInfo12* _pCorProfilerInfoEvents = nullptr;
ICorProfilerInfo13* _pCorProfilerInfoLiveHeap = nullptr;
std::unique_ptr<EventPipeEventsManager> _pEventPipeEventsManager = nullptr;
EVENTPIPE_SESSION _session{0};
inline static bool _isNet46OrGreater = false;
std::shared_ptr<IMetricsSender> _metricsSender;
std::atomic<bool> _isInitialized{false}; // pay attention to keeping ProfilerEngineStatus::IsProfilerEngiveActive in sync with this!
// The pointer here are observable pointer which means that they are used only to access the data.
// Their lifetime is managed by the _services vector.
IThreadsCpuManager* _pThreadsCpuManager = nullptr;
StackSamplerLoopManager* _pStackSamplerLoopManager = nullptr;
StackSamplerLoop* _pStackSamplerLoop = nullptr;
IManagedThreadList* _pManagedThreadList = nullptr;
IManagedThreadList* _pCodeHotspotsThreadList = nullptr;
IApplicationStore* _pApplicationStore = nullptr;
ExceptionsProvider* _pExceptionsProvider = nullptr;
WallTimeProvider* _pWallTimeProvider = nullptr;
CpuTimeProvider* _pCpuTimeProvider = nullptr;
AllocationsProvider* _pAllocationsProvider = nullptr;
ContentionProvider* _pContentionProvider = nullptr;
SamplesCollector* _pSamplesCollector = nullptr;
StopTheWorldGCProvider* _pStopTheWorldProvider = nullptr;
GarbageCollectionProvider* _pGarbageCollectionProvider = nullptr;
LiveObjectsProvider* _pLiveObjectsProvider = nullptr;
ThreadLifetimeProvider* _pThreadLifetimeProvider = nullptr;
NetworkProvider* _pNetworkProvider = nullptr;
RuntimeIdStore* _pRuntimeIdStore = nullptr;
HeapSnapshotManager* _pHeapSnapshotManager = nullptr;
INativeThreadList* _pNativeThreadList = nullptr;
#ifdef LINUX
SystemCallsShield* _systemCallsShield = nullptr;
std::unique_ptr<TimerCreateCpuProfiler> _pCpuProfiler = nullptr;
std::unique_ptr<IUnwinder> _pUnwinder = nullptr;
CpuSampleProvider* _pCpuSampleProvider = nullptr;
std::unique_ptr<RingBuffer> _pCpuProfilerRb = nullptr;
std::unique_ptr<UnwindingRecorderFactory> _pUnwindingRecorderFactory = nullptr;
#endif // LINUX
std::vector<std::unique_ptr<IService>> _services;
// Shared by StackSamplerLoopManager and StackSamplerLoop (both registered in _services above).
// StackFramesCollectorBase is not itself an IService (no Start/Stop lifecycle), so it - and the
// CallstackProvider backing it - are owned directly here instead, and handed to both as a raw,
// non-owning pointer.
CallstackProvider _callstackProvider;
std::unique_ptr<StackFramesCollectorBase> _pStackFramesCollector;
std::unique_ptr<IExporter> _pExporter = nullptr;
std::shared_ptr<IConfiguration> _pConfiguration = nullptr;
bool _IsManagedConfigurationSet = false; // profiler can't start before this becomes true
std::unique_ptr<IAppDomainStore> _pAppDomainStore = nullptr;
std::unique_ptr<IFrameStore> _pFrameStore = nullptr;
std::unique_ptr<IRuntimeInfo> _pRuntimeInfo = nullptr;
bool _isFrameworkVersionKnown = false;
std::unique_ptr<IEnabledProfilers> _pEnabledProfilers = nullptr;
std::unique_ptr<IAllocationsRecorder> _pAllocationsRecorder = nullptr;
std::unique_ptr<IDebugInfoStore> _pDebugInfoStore = nullptr;
MetricsRegistry _metricsRegistry;
std::shared_ptr<ProxyMetric> _managedThreadsMetric;
std::shared_ptr<ProxyMetric> _managedThreadsWithContextMetric;
// Note: can't use an interface because this class is implementing... 2 needed interfaces
std::unique_ptr<GCThreadsCpuProvider> _gcThreadsCpuProvider = nullptr;
std::unique_ptr<IMetadataProvider> _pMetadataProvider = nullptr;
std::unique_ptr<IEtwEventsManager> _pEtwEventsManager = nullptr;
bool _isETWStarted = false;
MemoryResourceManager _memoryResourceManager;
std::unique_ptr<ISsiManager> _pSsiManager = nullptr;
std::unique_ptr<RawSampleTransformer> _rawSampleTransformer;
std::unique_ptr<ManagedCodeCache> _managedCodeCache = nullptr;
private:
static void ConfigureDebugLog();
static void InspectRuntimeCompatibility(IUnknown* corProfilerInfoUnk, uint16_t& runtimeMajor, uint16_t& runtimeMinor);
static void InspectProcessorInfo();
static const char* SysInfoProcessorArchitectureToStr(WORD wProcArch);
static void PrintEnvironmentVariables();
static void OnThreadRoutineFinished();
void InspectRuntimeVersion(ICorProfilerInfo5* pCorProfilerInfo, USHORT& major, USHORT& minor, COR_PRF_RUNTIME_TYPE& runtimeType);
#ifdef _WINDOWS
void GetFullFrameworkVersion(ModuleID moduleId);
#endif
void DisposeInternal();
void InitializeServices();
bool DisposeServices();
bool StartServices();
bool StopServices();
void StartEtwCommunication();
template <class T, typename... ArgTypes>
T* RegisterService(ArgTypes&&... args)
{
_services.push_back(std::make_unique<T>(std::forward<ArgTypes>(args)...));
return dynamic_cast<T*>(_services.back().get());
}
};