| 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 | |