1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // File: eventtracebase.h |
6 | // Abstract: This module implements base Event Tracing support (excluding some of the |
7 | // CLR VM-specific ETW helpers). |
8 | // |
9 | |
10 | // |
11 | |
12 | // |
13 | // |
14 | // #EventTracing |
15 | // Windows |
16 | // ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable |
17 | // tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are |
18 | // four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. |
19 | // An event provider is a logical entity that writes events to ETW sessions. The event provider must register |
20 | // a provider ID with ETW through the registration API. A provider first registers with ETW and writes events |
21 | // from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by |
22 | // the ETW controller application, calls to the logging API sends events to a specific trace session |
23 | // designated by the controller. Each event sent by the event provider to the trace session consists of a |
24 | // fixed header that includes event metadata and additional variable user-context data. CLR is an event |
25 | // provider. |
26 | // ============================================================================ |
27 | |
28 | #ifndef _ETWTRACER_HXX_ |
29 | #define _ETWTRACER_HXX_ |
30 | |
31 | struct EventStructTypeData; |
32 | void InitializeEventTracing(); |
33 | |
34 | // !!!!!!! NOTE !!!!!!!! |
35 | // The flags must match those in the ETW manifest exactly |
36 | // !!!!!!! NOTE !!!!!!!! |
37 | |
38 | // These flags need to be defined either when FEATURE_EVENT_TRACE is enabled or the |
39 | // PROFILING_SUPPORTED is set, since they are used both by event tracing and profiling. |
40 | |
41 | enum EtwTypeFlags |
42 | { |
43 | kEtwTypeFlagsDelegate = 0x1, |
44 | kEtwTypeFlagsFinalizable = 0x2, |
45 | kEtwTypeFlagsExternallyImplementedCOMObject = 0x4, |
46 | kEtwTypeFlagsArray = 0x8, |
47 | }; |
48 | |
49 | enum EtwThreadFlags |
50 | { |
51 | kEtwThreadFlagGCSpecial = 0x00000001, |
52 | kEtwThreadFlagFinalizer = 0x00000002, |
53 | kEtwThreadFlagThreadPoolWorker = 0x00000004, |
54 | }; |
55 | |
56 | #ifndef FEATURE_REDHAWK |
57 | |
58 | #if defined(FEATURE_EVENT_TRACE) |
59 | |
60 | #if defined(FEATURE_PERFTRACING) |
61 | #define EVENT_PIPE_ENABLED() (EventPipeHelper::Enabled()) |
62 | #else |
63 | #define EVENT_PIPE_ENABLED() (FALSE) |
64 | #endif |
65 | |
66 | #if !defined(FEATURE_PAL) |
67 | |
68 | // |
69 | // Use this macro at the least before calling the Event Macros |
70 | // |
71 | |
72 | #define ETW_TRACING_INITIALIZED(RegHandle) \ |
73 | ((g_pEtwTracer && RegHandle) || EVENT_PIPE_ENABLED()) |
74 | |
75 | // |
76 | // Use this macro to check if an event is enabled |
77 | // if the fields in the event are not cheap to calculate |
78 | // |
79 | #define ETW_EVENT_ENABLED(Context, EventDescriptor) \ |
80 | ((MCGEN_ENABLE_CHECK(Context, EventDescriptor)) || EVENT_PIPE_ENABLED()) |
81 | |
82 | // |
83 | // Use this macro to check if a category of events is enabled |
84 | // |
85 | |
86 | #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) \ |
87 | ((Context.IsEnabled && McGenEventProviderEnabled(&Context, Level, Keyword)) || EVENT_PIPE_ENABLED()) |
88 | |
89 | |
90 | // This macro only checks if a provider is enabled |
91 | // It does not check the flags and keywords for which it is enabled |
92 | #define ETW_PROVIDER_ENABLED(ProviderSymbol) \ |
93 | ((ProviderSymbol##_Context.IsEnabled) || EVENT_PIPE_ENABLED()) |
94 | |
95 | |
96 | #else //defined(FEATURE_PAL) |
97 | #if defined(FEATURE_PERFTRACING) |
98 | #define ETW_INLINE |
99 | #define ETWOnStartup(StartEventName, EndEventName) |
100 | #define ETWFireEvent(EventName) |
101 | |
102 | #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) |
103 | #define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::Enabled() || XplatEventLogger::IsEventLoggingEnabled()) |
104 | #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::Enabled() || XplatEventLogger::IsEventLoggingEnabled()) |
105 | #define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) |
106 | #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::Enabled() || XplatEventLogger::IsEventLoggingEnabled()) |
107 | #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) |
108 | #else //defined(FEATURE_PERFTRACING) |
109 | #define ETW_INLINE |
110 | #define ETWOnStartup(StartEventName, EndEventName) |
111 | #define ETWFireEvent(EventName) |
112 | |
113 | #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) |
114 | #define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsEventLoggingEnabled()) |
115 | #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) |
116 | #define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) |
117 | #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) |
118 | #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) |
119 | #endif // defined(FEATURE_PERFTRACING) |
120 | #endif // !defined(FEATURE_PAL) |
121 | |
122 | #else // FEATURE_EVENT_TRACE |
123 | |
124 | #define ETWOnStartup(StartEventName, EndEventName) |
125 | #define ETWFireEvent(EventName) |
126 | |
127 | #define ETW_TRACING_INITIALIZED(RegHandle) (FALSE) |
128 | #define ETW_EVENT_ENABLED(Context, EventDescriptor) (FALSE) |
129 | #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) |
130 | #define ETW_TRACING_ENABLED(Context, EventDescriptor) (FALSE) |
131 | #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) |
132 | #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) |
133 | |
134 | #endif // FEATURE_EVENT_TRACE |
135 | |
136 | #endif // FEATURE_REDHAWK |
137 | |
138 | // During a heap walk, this is the storage for keeping track of all the nodes and edges |
139 | // being batched up by ETW, and for remembering whether we're also supposed to call into |
140 | // a profapi profiler. This is allocated toward the end of a GC and passed to us by the |
141 | // GC heap walker. |
142 | struct ProfilerWalkHeapContext |
143 | { |
144 | public: |
145 | ProfilerWalkHeapContext(BOOL fProfilerPinnedParam, LPVOID pvEtwContextParam) |
146 | { |
147 | fProfilerPinned = fProfilerPinnedParam; |
148 | pvEtwContext = pvEtwContextParam; |
149 | } |
150 | |
151 | BOOL fProfilerPinned; |
152 | LPVOID pvEtwContext; |
153 | }; |
154 | |
155 | #ifdef FEATURE_EVENT_TRACE |
156 | |
157 | class Object; |
158 | #if !defined(FEATURE_PAL) |
159 | |
160 | /***************************************/ |
161 | /* Tracing levels supported by CLR ETW */ |
162 | /***************************************/ |
163 | #define ETWMAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported |
164 | #define TRACE_LEVEL_NONE 0 // Tracing is not on |
165 | #define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination |
166 | #define TRACE_LEVEL_ERROR 2 // Severe errors that need logging |
167 | #define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure |
168 | #define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit |
169 | #define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps |
170 | |
171 | struct ProfilingScanContext; |
172 | |
173 | // |
174 | // Use this macro to check if ETW is initialized and the event is enabled |
175 | // |
176 | #define ETW_TRACING_ENABLED(Context, EventDescriptor) \ |
177 | ((Context.IsEnabled && ETW_TRACING_INITIALIZED(Context.RegistrationHandle) && ETW_EVENT_ENABLED(Context, EventDescriptor)) || EVENT_PIPE_ENABLED()) |
178 | |
179 | // |
180 | // Using KEYWORDZERO means when checking the events category ignore the keyword |
181 | // |
182 | #define KEYWORDZERO 0x0 |
183 | |
184 | // |
185 | // Use this macro to check if ETW is initialized and the category is enabled |
186 | // |
187 | #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) \ |
188 | ((ETW_TRACING_INITIALIZED(Context.RegistrationHandle) && ETW_CATEGORY_ENABLED(Context, Level, Keyword)) || EVENT_PIPE_ENABLED()) |
189 | |
190 | #define ETWOnStartup(StartEventName, EndEventName) \ |
191 | ETWTraceStartup trace##StartEventName##(Microsoft_Windows_DotNETRuntimePrivateHandle, &StartEventName, &StartupId, &EndEventName, &StartupId); |
192 | #define ETWFireEvent(EventName) \ |
193 | ETWTraceStartup::StartupTraceEvent(Microsoft_Windows_DotNETRuntimePrivateHandle, &EventName, &StartupId); |
194 | |
195 | #ifndef FEATURE_REDHAWK |
196 | // Headers |
197 | #include <initguid.h> |
198 | #include <wmistr.h> |
199 | #include <evntrace.h> |
200 | #include <evntprov.h> |
201 | #endif //!FEATURE_REDHAWK |
202 | #endif //!defined(FEATURE_PAL) |
203 | |
204 | |
205 | #else // FEATURE_EVENT_TRACE |
206 | |
207 | #include "etmdummy.h" |
208 | #endif // FEATURE_EVENT_TRACE |
209 | |
210 | #ifndef FEATURE_REDHAWK |
211 | |
212 | #include "corprof.h" |
213 | |
214 | // g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. |
215 | // This enables both the VM and Utilcode to raise ETW events. |
216 | extern UINT32 g_nClrInstanceId; |
217 | |
218 | #define GetClrInstanceId() (static_cast<UINT16>(g_nClrInstanceId)) |
219 | |
220 | #if defined(FEATURE_PERFTRACING) |
221 | class EventPipeHelper |
222 | { |
223 | public: |
224 | static bool Enabled(); |
225 | }; |
226 | #endif // defined(FEATURE_PERFTRACING) |
227 | |
228 | #if defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) |
229 | |
230 | #include "clrconfig.h" |
231 | class XplatEventLogger |
232 | { |
233 | public: |
234 | inline static BOOL IsEventLoggingEnabled() |
235 | { |
236 | static ConfigDWORD configEventLogging; |
237 | return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); |
238 | } |
239 | }; |
240 | |
241 | #endif //defined(FEATURE_EVENT_TRACE) |
242 | |
243 | #if defined(FEATURE_EVENT_TRACE) |
244 | |
245 | struct EventFilterDescriptor; |
246 | |
247 | VOID EventPipeEtwCallbackDotNETRuntimeStress( |
248 | _In_ LPCGUID SourceId, |
249 | _In_ ULONG ControlCode, |
250 | _In_ UCHAR Level, |
251 | _In_ ULONGLONG MatchAnyKeyword, |
252 | _In_ ULONGLONG MatchAllKeyword, |
253 | _In_opt_ EventFilterDescriptor* FilterData, |
254 | _Inout_opt_ PVOID CallbackContext); |
255 | |
256 | VOID EventPipeEtwCallbackDotNETRuntime( |
257 | _In_ LPCGUID SourceId, |
258 | _In_ ULONG ControlCode, |
259 | _In_ UCHAR Level, |
260 | _In_ ULONGLONG MatchAnyKeyword, |
261 | _In_ ULONGLONG MatchAllKeyword, |
262 | _In_opt_ EventFilterDescriptor* FilterData, |
263 | _Inout_opt_ PVOID CallbackContext); |
264 | |
265 | VOID EventPipeEtwCallbackDotNETRuntimeRundown( |
266 | _In_ LPCGUID SourceId, |
267 | _In_ ULONG ControlCode, |
268 | _In_ UCHAR Level, |
269 | _In_ ULONGLONG MatchAnyKeyword, |
270 | _In_ ULONGLONG MatchAllKeyword, |
271 | _In_opt_ EventFilterDescriptor* FilterData, |
272 | _Inout_opt_ PVOID CallbackContext); |
273 | |
274 | VOID EventPipeEtwCallbackDotNETRuntimePrivate( |
275 | _In_ LPCGUID SourceId, |
276 | _In_ ULONG ControlCode, |
277 | _In_ UCHAR Level, |
278 | _In_ ULONGLONG MatchAnyKeyword, |
279 | _In_ ULONGLONG MatchAllKeyword, |
280 | _In_opt_ EventFilterDescriptor* FilterData, |
281 | _Inout_opt_ PVOID CallbackContext); |
282 | |
283 | #ifndef FEATURE_PAL |
284 | // Callback and stack support |
285 | #if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) |
286 | extern "C" { |
287 | /* ETW control callback |
288 | * Desc: This function handles the ETW control |
289 | * callback. |
290 | * Ret: success or failure |
291 | ***********************************************/ |
292 | VOID EtwCallback( |
293 | _In_ LPCGUID SourceId, |
294 | _In_ ULONG ControlCode, |
295 | _In_ UCHAR Level, |
296 | _In_ ULONGLONG MatchAnyKeyword, |
297 | _In_ ULONGLONG MatchAllKeyword, |
298 | _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, |
299 | _Inout_opt_ PVOID CallbackContext); |
300 | } |
301 | |
302 | // |
303 | // User defined callback |
304 | // |
305 | #define MCGEN_PRIVATE_ENABLE_CALLBACK(RequestCode, Context, InOutBufferSize, Buffer) \ |
306 | EtwCallback(NULL /* SourceId */, (RequestCode==WMI_ENABLE_EVENTS) ? EVENT_CONTROL_CODE_ENABLE_PROVIDER : EVENT_CONTROL_CODE_DISABLE_PROVIDER, 0 /* Level */, 0 /* MatchAnyKeyword */, 0 /* MatchAllKeyword */, NULL /* FilterData */, Context) |
307 | |
308 | // |
309 | // User defined callback2 |
310 | // |
311 | #define MCGEN_PRIVATE_ENABLE_CALLBACK_V2(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) \ |
312 | EtwCallback(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) |
313 | |
314 | extern "C" { |
315 | /* ETW callout |
316 | * Desc: This function handles the ETW callout |
317 | * Ret: success or failure |
318 | ***********************************************/ |
319 | VOID EtwCallout( |
320 | REGHANDLE RegHandle, |
321 | PCEVENT_DESCRIPTOR Descriptor, |
322 | ULONG ArgumentCount, |
323 | PEVENT_DATA_DESCRIPTOR EventData); |
324 | } |
325 | |
326 | // |
327 | // Call user defined callout |
328 | // |
329 | #define MCGEN_CALLOUT(RegHandle, Descriptor, NumberOfArguments, EventData) \ |
330 | EtwCallout(RegHandle, Descriptor, NumberOfArguments, EventData) |
331 | #endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE |
332 | |
333 | #endif //!FEATURE_PAL |
334 | |
335 | #include "clretwallmain.h" |
336 | |
337 | #endif // FEATURE_EVENT_TRACE |
338 | |
339 | /**************************/ |
340 | /* CLR ETW infrastructure */ |
341 | /**************************/ |
342 | // #CEtwTracer |
343 | // On Windows Vista, ETW has gone through a major upgrade, and one of the most significant changes is the |
344 | // introduction of the unified event provider model and APIs. The older architecture used the classic ETW |
345 | // events. The new ETW architecture uses the manifest based events. To support both types of events at the |
346 | // same time, we use the manpp tool for generating event macros that can be directly used to fire ETW events |
347 | // from various components within the CLR. |
348 | // (http://diagnostics/sites/etw/Lists/Announcements/DispForm.aspx?ID=10&Source=http%3A%2F%2Fdiagnostics%2Fsites%2Fetw%2Fdefault%2Easpx) |
349 | // Every ETW provider has to Register itself to the system, so that when enabled, it is capable of firing |
350 | // ETW events. file:../VM/eventtrace.cpp#Registration is where the actual Provider Registration takes place. |
351 | // At process shutdown, a registered provider need to be unregistered. |
352 | // file:../VM/eventtrace.cpp#Unregistration. Since ETW can also be enabled at any instant after the process |
353 | // has started, one may want to do something useful when that happens (e.g enumerate all the loaded modules |
354 | // in the system). To enable this, we have to implement a callback routine. |
355 | // file:../VM/eventtrace.cpp#EtwCallback is CLR's implementation of the callback. |
356 | // |
357 | |
358 | #include "daccess.h" |
359 | class Module; |
360 | class Assembly; |
361 | class MethodDesc; |
362 | class MethodTable; |
363 | class BaseDomain; |
364 | class AppDomain; |
365 | class SString; |
366 | class CrawlFrame; |
367 | class LoaderAllocator; |
368 | class AssemblyLoaderAllocator; |
369 | struct AllLoggedTypes; |
370 | class CrstBase; |
371 | class BulkTypeEventLogger; |
372 | class TypeHandle; |
373 | class Thread; |
374 | |
375 | |
376 | // All ETW helpers must be a part of this namespace |
377 | // We have auto-generated macros to directly fire the events |
378 | // but in some cases, gathering the event payload information involves some work |
379 | // and it can be done in a relevant helper class like the one's in this namespace |
380 | namespace ETW |
381 | { |
382 | // Class to wrap the ETW infrastructure logic |
383 | #if !defined(FEATURE_PAL) |
384 | class CEtwTracer |
385 | { |
386 | #if defined(FEATURE_EVENT_TRACE) |
387 | ULONG RegGuids(LPCGUID ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle); |
388 | #endif |
389 | |
390 | public: |
391 | #ifdef FEATURE_EVENT_TRACE |
392 | // Registers all the Event Tracing providers |
393 | HRESULT Register(); |
394 | |
395 | // Unregisters all the Event Tracing providers |
396 | HRESULT UnRegister(); |
397 | #else |
398 | HRESULT Register() |
399 | { |
400 | return S_OK; |
401 | } |
402 | HRESULT UnRegister() |
403 | { |
404 | return S_OK; |
405 | } |
406 | #endif // FEATURE_EVENT_TRACE |
407 | }; |
408 | #endif // !defined(FEATURE_PAL) |
409 | |
410 | class LoaderLog; |
411 | class MethodLog; |
412 | // Class to wrap all the enumeration logic for ETW |
413 | class EnumerationLog |
414 | { |
415 | friend class ETW::LoaderLog; |
416 | friend class ETW::MethodLog; |
417 | #ifdef FEATURE_EVENT_TRACE |
418 | static VOID SendThreadRundownEvent(); |
419 | static VOID IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions); |
420 | static VOID IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions); |
421 | static VOID IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions); |
422 | static VOID IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions); |
423 | static VOID IterateModule(Module *pModule, DWORD enumerationOptions); |
424 | static VOID EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions); |
425 | static DWORD GetEnumerationOptionsFromRuntimeKeywords(); |
426 | public: |
427 | typedef union _EnumerationStructs |
428 | { |
429 | typedef enum _EnumerationOptions |
430 | { |
431 | None= 0x00000000, |
432 | DomainAssemblyModuleLoad= 0x00000001, |
433 | DomainAssemblyModuleUnload= 0x00000002, |
434 | DomainAssemblyModuleDCStart= 0x00000004, |
435 | DomainAssemblyModuleDCEnd= 0x00000008, |
436 | JitMethodLoad= 0x00000010, |
437 | JitMethodUnload= 0x00000020, |
438 | JitMethodDCStart= 0x00000040, |
439 | JitMethodDCEnd= 0x00000080, |
440 | NgenMethodLoad= 0x00000100, |
441 | NgenMethodUnload= 0x00000200, |
442 | NgenMethodDCStart= 0x00000400, |
443 | NgenMethodDCEnd= 0x00000800, |
444 | ModuleRangeLoad= 0x00001000, |
445 | ModuleRangeDCStart= 0x00002000, |
446 | ModuleRangeDCEnd= 0x00004000, |
447 | ModuleRangeLoadPrivate= 0x00008000, |
448 | MethodDCStartILToNativeMap= 0x00010000, |
449 | MethodDCEndILToNativeMap= 0x00020000, |
450 | JitMethodILToNativeMap= 0x00040000, |
451 | TypeUnload= 0x00080000, |
452 | |
453 | // Helpers |
454 | ModuleRangeEnabledAny = ModuleRangeLoad | ModuleRangeDCStart | ModuleRangeDCEnd | ModuleRangeLoadPrivate, |
455 | JitMethodLoadOrDCStartAny = JitMethodLoad | JitMethodDCStart | MethodDCStartILToNativeMap, |
456 | JitMethodUnloadOrDCEndAny = JitMethodUnload | JitMethodDCEnd | MethodDCEndILToNativeMap, |
457 | }EnumerationOptions; |
458 | }EnumerationStructs; |
459 | |
460 | static VOID ProcessShutdown(); |
461 | static VOID ModuleRangeRundown(); |
462 | static VOID StartRundown(); |
463 | static VOID EndRundown(); |
464 | static VOID EnumerateForCaptureState(); |
465 | #else |
466 | public: |
467 | static VOID ProcessShutdown() {}; |
468 | static VOID StartRundown() {}; |
469 | static VOID EndRundown() {}; |
470 | #endif // FEATURE_EVENT_TRACE |
471 | }; |
472 | |
473 | |
474 | // Class to wrap all the sampling logic for ETW |
475 | |
476 | class SamplingLog |
477 | { |
478 | #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) |
479 | public: |
480 | typedef enum _EtwStackWalkStatus |
481 | { |
482 | Completed = 0, |
483 | UnInitialized = 1, |
484 | InProgress = 2 |
485 | } EtwStackWalkStatus; |
486 | private: |
487 | static const UINT8 s_MaxStackSize=100; |
488 | UINT32 m_FrameCount; |
489 | SIZE_T m_EBPStack[SamplingLog::s_MaxStackSize]; |
490 | VOID Append(SIZE_T currentFrame); |
491 | EtwStackWalkStatus SaveCurrentStack(int skipTopNFrames=1); |
492 | public: |
493 | static ULONG SendStackTrace(MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid); |
494 | EtwStackWalkStatus GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack); |
495 | #endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) |
496 | }; |
497 | |
498 | // Class to wrap all Loader logic for ETW |
499 | class LoaderLog |
500 | { |
501 | friend class ETW::EnumerationLog; |
502 | #if defined(FEATURE_EVENT_TRACE) |
503 | static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE); |
504 | static ULONG SendModuleRange(__in Module *pModule, __in DWORD dwEventOptions); |
505 | static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions); |
506 | static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); |
507 | public: |
508 | typedef union _LoaderStructs |
509 | { |
510 | typedef enum _AppDomainFlags |
511 | { |
512 | DefaultDomain=0x1, |
513 | ExecutableDomain=0x2, |
514 | SharedDomain=0x4 |
515 | }AppDomainFlags; |
516 | |
517 | typedef enum _AssemblyFlags |
518 | { |
519 | DomainNeutralAssembly=0x1, |
520 | DynamicAssembly=0x2, |
521 | NativeAssembly=0x4, |
522 | CollectibleAssembly=0x8, |
523 | ReadyToRunAssembly=0x10, |
524 | }AssemblyFlags; |
525 | |
526 | typedef enum _ModuleFlags |
527 | { |
528 | DomainNeutralModule=0x1, |
529 | NativeModule=0x2, |
530 | DynamicModule=0x4, |
531 | ManifestModule=0x8, |
532 | IbcOptimized=0x10, |
533 | ReadyToRunModule=0x20, |
534 | }ModuleFlags; |
535 | |
536 | typedef enum _RangeFlags |
537 | { |
538 | HotRange=0x0 |
539 | }RangeFlags; |
540 | |
541 | }LoaderStructs; |
542 | |
543 | static VOID DomainLoadReal(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL); |
544 | |
545 | static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName = NULL) |
546 | { |
547 | if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) |
548 | { |
549 | DomainLoadReal(pDomain, wszFriendlyName); |
550 | } |
551 | } |
552 | |
553 | static VOID DomainUnload(AppDomain *pDomain); |
554 | static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator); |
555 | static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule); |
556 | #else |
557 | public: |
558 | static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL) {}; |
559 | static VOID DomainUnload(AppDomain *pDomain) {}; |
560 | static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) {}; |
561 | static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule) {}; |
562 | #endif // FEATURE_EVENT_TRACE |
563 | }; |
564 | |
565 | // Class to wrap all Method logic for ETW |
566 | class MethodLog |
567 | { |
568 | friend class ETW::EnumerationLog; |
569 | #ifdef FEATURE_EVENT_TRACE |
570 | static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); |
571 | static VOID SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, |
572 | LoaderAllocator *pLoaderAllocatorFilter, |
573 | DWORD dwEventOptions, |
574 | BOOL fLoadOrDCStart, |
575 | BOOL fUnloadOrDCEnd, |
576 | BOOL fSendMethodEvent, |
577 | BOOL fSendILToNativeMapEvent, |
578 | BOOL fGetReJitIDs); |
579 | static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); |
580 | static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); |
581 | static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, SIZE_T pCode, ReJITID rejitID); |
582 | static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); |
583 | static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); |
584 | public: |
585 | typedef union _MethodStructs |
586 | { |
587 | typedef enum _MethodFlags |
588 | { |
589 | DynamicMethod=0x1, |
590 | GenericMethod=0x2, |
591 | SharedGenericCode=0x4, |
592 | JittedMethod=0x8, |
593 | JitHelperMethod=0x10, |
594 | ProfilerRejectedPrecompiledCode=0x20, |
595 | ReadyToRunRejectedPrecompiledCode=0x40, |
596 | }MethodFlags; |
597 | |
598 | typedef enum _MethodExtent |
599 | { |
600 | HotSection=0x00000000, |
601 | ColdSection=0x10000000 |
602 | }MethodExtent; |
603 | |
604 | }MethodStructs; |
605 | |
606 | static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); |
607 | static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); |
608 | static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); |
609 | static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers); |
610 | static VOID MethodRestored(MethodDesc * pMethodDesc); |
611 | static VOID MethodTableRestored(MethodTable * pMethodTable); |
612 | static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc); |
613 | #else // FEATURE_EVENT_TRACE |
614 | public: |
615 | static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL) {}; |
616 | static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE) {}; |
617 | static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; |
618 | static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; |
619 | static VOID MethodRestored(MethodDesc * pMethodDesc) {}; |
620 | static VOID MethodTableRestored(MethodTable * pMethodTable) {}; |
621 | static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc) {}; |
622 | #endif // FEATURE_EVENT_TRACE |
623 | }; |
624 | |
625 | // Class to wrap all Security logic for ETW |
626 | class SecurityLog |
627 | { |
628 | #ifdef FEATURE_EVENT_TRACE |
629 | public: |
630 | static VOID StrongNameVerificationStart(DWORD dwInFlags, __in LPWSTR strFullyQualifiedAssemblyName); |
631 | static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, __in LPWSTR strFullyQualifiedAssemblyName); |
632 | |
633 | static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, |
634 | LPCWSTR wszModuleName, |
635 | DWORD dwAppDomain); |
636 | static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, |
637 | LPCWSTR wszModuleName, |
638 | DWORD dwAppDomain, |
639 | BOOL fIsCritical, |
640 | BOOL fIsTreatAsSafe); |
641 | |
642 | static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, |
643 | LPCWSTR wszModuleName, |
644 | DWORD dwAppDomain); |
645 | static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, |
646 | LPCWSTR wszModuleName, |
647 | DWORD dwAppDomain, |
648 | BOOL fIsCritical, |
649 | BOOL fIsTreatAsSafe); |
650 | |
651 | static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain); |
652 | static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, |
653 | DWORD dwAppDomain, |
654 | BOOL fIsAllCritical, |
655 | BOOL fIsAllTransparent, |
656 | BOOL fIsTreatAsSafe, |
657 | BOOL fIsOpportunisticallyCritical, |
658 | DWORD dwSecurityRuleSet); |
659 | |
660 | static void FireTokenTransparencyComputationStart(DWORD dwToken, |
661 | LPCWSTR wszModuleName, |
662 | DWORD dwAppDomain); |
663 | static void FireTokenTransparencyComputationEnd(DWORD dwToken, |
664 | LPCWSTR wszModuleName, |
665 | DWORD dwAppDomain, |
666 | BOOL fIsCritical, |
667 | BOOL fIsTreatAsSafe); |
668 | |
669 | static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, |
670 | LPCWSTR wszModuleName, |
671 | DWORD dwAppDomain); |
672 | static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, |
673 | LPCWSTR wszModuleName, |
674 | DWORD dwAppDomain, |
675 | BOOL fIsAllCritical, |
676 | BOOL fIsAllTransparent, |
677 | BOOL fIsCritical, |
678 | BOOL fIsTreatAsSafe); |
679 | #else |
680 | public: |
681 | static VOID StrongNameVerificationStart(DWORD dwInFlags, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; |
682 | static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; |
683 | |
684 | static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, |
685 | LPCWSTR wszModuleName, |
686 | DWORD dwAppDomain) {}; |
687 | static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, |
688 | LPCWSTR wszModuleName, |
689 | DWORD dwAppDomain, |
690 | BOOL fIsCritical, |
691 | BOOL fIsTreatAsSafe) {}; |
692 | |
693 | static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, |
694 | LPCWSTR wszModuleName, |
695 | DWORD dwAppDomain) {}; |
696 | static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, |
697 | LPCWSTR wszModuleName, |
698 | DWORD dwAppDomain, |
699 | BOOL fIsCritical, |
700 | BOOL fIsTreatAsSafe) {}; |
701 | |
702 | static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain) {}; |
703 | static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, |
704 | DWORD dwAppDomain, |
705 | BOOL fIsAllCritical, |
706 | BOOL fIsAllTransparent, |
707 | BOOL fIsTreatAsSafe, |
708 | BOOL fIsOpportunisticallyCritical, |
709 | DWORD dwSecurityRuleSet) {}; |
710 | |
711 | static void FireTokenTransparencyComputationStart(DWORD dwToken, |
712 | LPCWSTR wszModuleName, |
713 | DWORD dwAppDomain) {}; |
714 | static void FireTokenTransparencyComputationEnd(DWORD dwToken, |
715 | LPCWSTR wszModuleName, |
716 | DWORD dwAppDomain, |
717 | BOOL fIsCritical, |
718 | BOOL fIsTreatAsSafe) {}; |
719 | |
720 | static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, |
721 | LPCWSTR wszModuleName, |
722 | DWORD dwAppDomain) {}; |
723 | static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, |
724 | LPCWSTR wszModuleName, |
725 | DWORD dwAppDomain, |
726 | BOOL fIsAllCritical, |
727 | BOOL fIsAllTransparent, |
728 | BOOL fIsCritical, |
729 | BOOL fIsTreatAsSafe) {}; |
730 | #endif // FEATURE_EVENT_TRACE |
731 | }; |
732 | |
733 | // Class to wrap all Binder logic for ETW |
734 | class BinderLog |
735 | { |
736 | public: |
737 | typedef union _BinderStructs { |
738 | typedef enum _NGENBINDREJECT_REASON { |
739 | NGEN_BIND_START_BIND = 0, |
740 | NGEN_BIND_NO_INDEX = 1, |
741 | NGEN_BIND_SYSTEM_ASSEMBLY_NOT_AVAILABLE = 2, |
742 | NGEN_BIND_NO_NATIVE_IMAGE = 3, |
743 | NGEN_BIND_REJECT_CONFIG_MASK = 4, |
744 | NGEN_BIND_FAIL = 5, |
745 | NGEN_BIND_INDEX_CORRUPTION = 6, |
746 | NGEN_BIND_REJECT_TIMESTAMP = 7, |
747 | NGEN_BIND_REJECT_NATIVEIMAGE_NOT_FOUND = 8, |
748 | NGEN_BIND_REJECT_IL_SIG = 9, |
749 | NGEN_BIND_REJECT_LOADER_EVAL_FAIL = 10, |
750 | NGEN_BIND_MISSING_FOUND = 11, |
751 | NGEN_BIND_REJECT_HOSTASM = 12, |
752 | NGEN_BIND_REJECT_IL_NOT_FOUND = 13, |
753 | NGEN_BIND_REJECT_APPBASE_NOT_FILE = 14, |
754 | NGEN_BIND_BIND_DEPEND_REJECT_REF_DEF_MISMATCH = 15, |
755 | NGEN_BIND_BIND_DEPEND_REJECT_NGEN_SIG = 16, |
756 | NGEN_BIND_APPLY_EXTERNAL_RELOCS_FAILED = 17, |
757 | NGEN_BIND_SYSTEM_ASSEMBLY_NATIVEIMAGE_NOT_AVAILABLE = 18, |
758 | NGEN_BIND_ASSEMBLY_HAS_DIFFERENT_GRANT = 19, |
759 | NGEN_BIND_ASSEMBLY_NOT_DOMAIN_NEUTRAL = 20, |
760 | NGEN_BIND_NATIVEIMAGE_VERSION_MISMATCH = 21, |
761 | NGEN_BIND_LOADFROM_NOT_ALLOWED = 22, |
762 | NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY = 23 |
763 | } NGENBINDREJECT_REASON; |
764 | } BinderStructs; |
765 | }; |
766 | |
767 | // Class to wrap all Exception logic for ETW |
768 | class ExceptionLog |
769 | { |
770 | public: |
771 | #ifdef FEATURE_EVENT_TRACE |
772 | static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException); |
773 | static VOID ExceptionThrownEnd(); |
774 | static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); |
775 | static VOID ExceptionCatchEnd(); |
776 | static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); |
777 | static VOID ExceptionFinallyEnd(); |
778 | static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); |
779 | static VOID ExceptionFilterEnd(); |
780 | |
781 | #else |
782 | static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) {}; |
783 | static VOID ExceptionThrownEnd() {}; |
784 | static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; |
785 | static VOID ExceptionCatchEnd() {}; |
786 | static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; |
787 | static VOID ExceptionFinallyEnd() {}; |
788 | static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; |
789 | static VOID ExceptionFilterEnd() {}; |
790 | #endif // FEATURE_EVENT_TRACE |
791 | typedef union _ExceptionStructs |
792 | { |
793 | typedef enum _ExceptionThrownFlags |
794 | { |
795 | HasInnerException=0x1, |
796 | IsNestedException=0x2, |
797 | IsReThrownException=0x4, |
798 | IsCSE=0x8, |
799 | IsCLSCompliant=0x10 |
800 | }ExceptionThrownFlags; |
801 | }ExceptionStructs; |
802 | }; |
803 | // Class to wrap all Contention logic for ETW |
804 | class ContentionLog |
805 | { |
806 | public: |
807 | typedef union _ContentionStructs |
808 | { |
809 | typedef enum _ContentionFlags { |
810 | ManagedContention=0, |
811 | NativeContention=1 |
812 | } ContentionFlags; |
813 | } ContentionStructs; |
814 | }; |
815 | // Class to wrap all Interop logic for ETW |
816 | class InteropLog |
817 | { |
818 | public: |
819 | }; |
820 | |
821 | // Class to wrap all Information logic for ETW |
822 | class InfoLog |
823 | { |
824 | public: |
825 | typedef union _InfoStructs |
826 | { |
827 | typedef enum _StartupMode |
828 | { |
829 | ManagedExe=0x1, |
830 | HostedCLR=0x2, |
831 | IJW=0x4, |
832 | COMActivated=0x8, |
833 | Other=0x10 |
834 | }StartupMode; |
835 | |
836 | typedef enum _Sku |
837 | { |
838 | DesktopCLR=0x1, |
839 | CoreCLR=0x2 |
840 | }Sku; |
841 | |
842 | typedef enum _EtwMode |
843 | { |
844 | Normal=0x0, |
845 | Callback=0x1 |
846 | }EtwMode; |
847 | }InfoStructs; |
848 | |
849 | #ifdef FEATURE_EVENT_TRACE |
850 | static VOID RuntimeInformation(INT32 type); |
851 | #else |
852 | static VOID RuntimeInformation(INT32 type) {}; |
853 | #endif // FEATURE_EVENT_TRACE |
854 | }; |
855 | |
856 | class CodeSymbolLog |
857 | { |
858 | public: |
859 | #ifdef FEATURE_EVENT_TRACE |
860 | static VOID EmitCodeSymbols(Module* pModule); |
861 | static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes); |
862 | static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, |
863 | DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead); |
864 | #else |
865 | static VOID EmitCodeSymbols(Module* pModule) {} |
866 | static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes) { return S_OK; } |
867 | static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, |
868 | DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead) { return S_OK; } |
869 | #endif // FEATURE_EVENT_TRACE |
870 | }; |
871 | }; |
872 | |
873 | |
874 | #define ETW_IS_TRACE_ON(level) ( FALSE ) // for fusion which is eventually going to get removed |
875 | #define ETW_IS_FLAG_ON(flag) ( FALSE ) // for fusion which is eventually going to get removed |
876 | |
877 | // Commonly used constats for ETW Assembly Loader and Assembly Binder events. |
878 | #define ETWLoadContextNotAvailable (LOADCTX_TYPE_HOSTED + 1) |
879 | #define ETWAppDomainIdNotAvailable 0 // Valid AppDomain IDs start from 1 |
880 | |
881 | #define ETWFieldUnused 0 // Indicates that a particular field in the ETW event payload template is currently unused. |
882 | |
883 | #define ETWLoaderLoadTypeNotAvailable 0 // Static or Dynamic Load is only valid at LoaderPhaseStart and LoaderPhaseEnd events - for other events, 0 indicates "not available" |
884 | #define ETWLoaderStaticLoad 0 // Static reference load |
885 | #define ETWLoaderDynamicLoad 1 // Dynamic assembly load |
886 | |
887 | #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) |
888 | // |
889 | // The ONE and only ONE global instantiation of this class |
890 | // |
891 | extern ETW::CEtwTracer * g_pEtwTracer; |
892 | |
893 | // |
894 | // Special Handling of Startup events |
895 | // |
896 | |
897 | // "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; |
898 | // on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so |
899 | // we manually place it here. |
900 | ETW_INLINE |
901 | ULONG |
902 | CoMofTemplate_h( |
903 | __in REGHANDLE RegHandle, |
904 | __in PCEVENT_DESCRIPTOR Descriptor, |
905 | __in_opt LPCGUID EventGuid, |
906 | __in const unsigned short ClrInstanceID |
907 | ) |
908 | { |
909 | #define ARGUMENT_COUNT_h 1 |
910 | ULONG Error = ERROR_SUCCESS; |
911 | typedef struct _MCGEN_TRACE_BUFFER { |
912 | EVENT_TRACE_HEADER Header; |
913 | EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_h]; |
914 | } MCGEN_TRACE_BUFFER; |
915 | |
916 | MCGEN_TRACE_BUFFER TraceBuf; |
917 | PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; |
918 | |
919 | EventDataDescCreate(&EventData[0], &ClrInstanceID, sizeof(const unsigned short) ); |
920 | |
921 | |
922 | { |
923 | Error = EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_h, EventData); |
924 | |
925 | } |
926 | |
927 | #ifdef MCGEN_CALLOUT |
928 | MCGEN_CALLOUT(RegHandle, |
929 | Descriptor, |
930 | ARGUMENT_COUNT_h, |
931 | EventData); |
932 | #endif |
933 | |
934 | return Error; |
935 | } |
936 | |
937 | class ETWTraceStartup { |
938 | REGHANDLE TraceHandle; |
939 | PCEVENT_DESCRIPTOR EventStartDescriptor; |
940 | LPCGUID EventStartGuid; |
941 | PCEVENT_DESCRIPTOR EventEndDescriptor; |
942 | LPCGUID EventEndGuid; |
943 | public: |
944 | ETWTraceStartup(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventStartDescriptor, LPCGUID _EventStartGuid, PCEVENT_DESCRIPTOR _EventEndDescriptor, LPCGUID _EventEndGuid) { |
945 | TraceHandle = _TraceHandle; |
946 | EventStartDescriptor = _EventStartDescriptor; |
947 | EventEndDescriptor = _EventEndDescriptor; |
948 | EventStartGuid = _EventStartGuid; |
949 | EventEndGuid = _EventEndGuid; |
950 | StartupTraceEvent(TraceHandle, EventStartDescriptor, EventStartGuid); |
951 | } |
952 | ~ETWTraceStartup() { |
953 | StartupTraceEvent(TraceHandle, EventEndDescriptor, EventEndGuid); |
954 | } |
955 | static void StartupTraceEvent(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventDescriptor, LPCGUID _EventGuid) { |
956 | EVENT_DESCRIPTOR desc = *_EventDescriptor; |
957 | if(ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, desc)) |
958 | { |
959 | CoMofTemplate_h(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context.RegistrationHandle, _EventDescriptor, _EventGuid, GetClrInstanceId()); |
960 | } |
961 | } |
962 | }; |
963 | // "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; |
964 | // on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so |
965 | // we manually place it here. |
966 | FORCEINLINE |
967 | BOOLEAN __stdcall |
968 | McGenEventTracingEnabled( |
969 | __in PMCGEN_TRACE_CONTEXT EnableInfo, |
970 | __in PCEVENT_DESCRIPTOR EventDescriptor |
971 | ) |
972 | { |
973 | |
974 | if(!EnableInfo){ |
975 | return FALSE; |
976 | } |
977 | |
978 | |
979 | // |
980 | // Check if the event Level is lower than the level at which |
981 | // the channel is enabled. |
982 | // If the event Level is 0 or the channel is enabled at level 0, |
983 | // all levels are enabled. |
984 | // |
985 | |
986 | if ((EventDescriptor->Level <= EnableInfo->Level) || // This also covers the case of Level == 0. |
987 | (EnableInfo->Level == 0)) { |
988 | |
989 | // |
990 | // Check if Keyword is enabled |
991 | // |
992 | |
993 | if ((EventDescriptor->Keyword == (ULONGLONG)0) || |
994 | ((EventDescriptor->Keyword & EnableInfo->MatchAnyKeyword) && |
995 | ((EventDescriptor->Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { |
996 | return TRUE; |
997 | } |
998 | } |
999 | |
1000 | return FALSE; |
1001 | } |
1002 | |
1003 | |
1004 | ETW_INLINE |
1005 | ULONG |
1006 | ETW::SamplingLog::SendStackTrace( |
1007 | MCGEN_TRACE_CONTEXT TraceContext, |
1008 | PCEVENT_DESCRIPTOR Descriptor, |
1009 | LPCGUID EventGuid) |
1010 | { |
1011 | #define ARGUMENT_COUNT_CLRStackWalk 5 |
1012 | ULONG Result = ERROR_SUCCESS; |
1013 | typedef struct _MCGEN_TRACE_BUFFER { |
1014 | EVENT_TRACE_HEADER Header; |
1015 | EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_CLRStackWalk]; |
1016 | } MCGEN_TRACE_BUFFER; |
1017 | |
1018 | REGHANDLE RegHandle = TraceContext.RegistrationHandle; |
1019 | if(!TraceContext.IsEnabled || !McGenEventTracingEnabled(&TraceContext, Descriptor)) |
1020 | { |
1021 | return Result; |
1022 | } |
1023 | |
1024 | PVOID *Stack = NULL; |
1025 | UINT32 FrameCount = 0; |
1026 | ETW::SamplingLog stackObj; |
1027 | if(stackObj.GetCurrentThreadsCallStack(&FrameCount, &Stack) == ETW::SamplingLog::Completed) |
1028 | { |
1029 | UCHAR Reserved1=0, Reserved2=0; |
1030 | UINT16 ClrInstanceId = GetClrInstanceId(); |
1031 | MCGEN_TRACE_BUFFER TraceBuf; |
1032 | PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; |
1033 | |
1034 | EventDataDescCreate(&EventData[0], &ClrInstanceId, sizeof(const UINT16) ); |
1035 | |
1036 | EventDataDescCreate(&EventData[1], &Reserved1, sizeof(const UCHAR) ); |
1037 | |
1038 | EventDataDescCreate(&EventData[2], &Reserved2, sizeof(const UCHAR) ); |
1039 | |
1040 | EventDataDescCreate(&EventData[3], &FrameCount, sizeof(const unsigned int) ); |
1041 | |
1042 | EventDataDescCreate(&EventData[4], Stack, sizeof(PVOID) * FrameCount ); |
1043 | |
1044 | return EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_CLRStackWalk, EventData); |
1045 | } |
1046 | return Result; |
1047 | }; |
1048 | |
1049 | #endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) |
1050 | #ifdef FEATURE_EVENT_TRACE |
1051 | #ifdef _TARGET_X86_ |
1052 | struct CallStackFrame |
1053 | { |
1054 | struct CallStackFrame* m_Next; |
1055 | SIZE_T m_ReturnAddress; |
1056 | }; |
1057 | #endif // _TARGET_X86_ |
1058 | #endif // FEATURE_EVENT_TRACE |
1059 | |
1060 | #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) |
1061 | FORCEINLINE |
1062 | BOOLEAN __stdcall |
1063 | McGenEventProviderEnabled( |
1064 | __in PMCGEN_TRACE_CONTEXT Context, |
1065 | __in UCHAR Level, |
1066 | __in ULONGLONG Keyword |
1067 | ) |
1068 | { |
1069 | if(!Context) { |
1070 | return FALSE; |
1071 | } |
1072 | |
1073 | // |
1074 | // Check if the event Level is lower than the level at which |
1075 | // the channel is enabled. |
1076 | // If the event Level is 0 or the channel is enabled at level 0, |
1077 | // all levels are enabled. |
1078 | // |
1079 | |
1080 | if ((Level <= Context->Level) || // This also covers the case of Level == 0. |
1081 | (Context->Level == 0)) { |
1082 | |
1083 | // |
1084 | // Check if Keyword is enabled |
1085 | // |
1086 | |
1087 | if ((Keyword == (ULONGLONG)0) || |
1088 | ((Keyword & Context->MatchAnyKeyword) && |
1089 | ((Keyword & Context->MatchAllKeyword) == Context->MatchAllKeyword))) { |
1090 | return TRUE; |
1091 | } |
1092 | } |
1093 | return FALSE; |
1094 | } |
1095 | #endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) |
1096 | |
1097 | |
1098 | #endif // !FEATURE_REDHAWK |
1099 | |
1100 | // These parts of the ETW namespace are common for both FEATURE_REDHAWK and |
1101 | // !FEATURE_REDHAWK builds. |
1102 | |
1103 | |
1104 | struct ProfilingScanContext; |
1105 | class Object; |
1106 | |
1107 | namespace ETW |
1108 | { |
1109 | // Class to wrap the logging of threads (runtime and rundown providers) |
1110 | class ThreadLog |
1111 | { |
1112 | private: |
1113 | static DWORD GetEtwThreadFlags(Thread * pThread); |
1114 | |
1115 | public: |
1116 | static VOID FireThreadCreated(Thread * pThread); |
1117 | static VOID FireThreadDC(Thread * pThread); |
1118 | }; |
1119 | }; |
1120 | |
1121 | |
1122 | #endif //_ETWTRACER_HXX_ |
1123 | |