diff options
Diffstat (limited to 'src/inc/eventtracebase.h')
-rw-r--r-- | src/inc/eventtracebase.h | 1082 |
1 files changed, 1082 insertions, 0 deletions
diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h new file mode 100644 index 0000000000..f773a7c375 --- /dev/null +++ b/src/inc/eventtracebase.h @@ -0,0 +1,1082 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: eventtracebase.h +// Abstract: This module implements base Event Tracing support (excluding some of the +// CLR VM-specific ETW helpers). +// + +// + +// +// +// #EventTracing +// Windows +// ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable +// tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are +// four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. +// An event provider is a logical entity that writes events to ETW sessions. The event provider must register +// a provider ID with ETW through the registration API. A provider first registers with ETW and writes events +// from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by +// the ETW controller application, calls to the logging API sends events to a specific trace session +// designated by the controller. Each event sent by the event provider to the trace session consists of a +// fixed header that includes event metadata and additional variable user-context data. CLR is an event +// provider. +// ============================================================================ + +#ifndef _ETWTRACER_HXX_ +#define _ETWTRACER_HXX_ + +struct EventStructTypeData; +void InitializeEventTracing(); + +// !!!!!!! NOTE !!!!!!!! +// The flags must match those in the ETW manifest exactly +// !!!!!!! NOTE !!!!!!!! + +// These flags need to be defined either when FEATURE_EVENT_TRACE is enabled or the +// PROFILING_SUPPORTED is set, since they are used both by event tracing and profiling. + +enum EtwGCRootFlags +{ + kEtwGCRootFlagsPinning = 0x1, + kEtwGCRootFlagsWeakRef = 0x2, + kEtwGCRootFlagsInterior = 0x4, + kEtwGCRootFlagsRefCounted = 0x8, +}; + +enum EtwGCRootKind +{ + kEtwGCRootKindStack = 0, + kEtwGCRootKindFinalizer = 1, + kEtwGCRootKindHandle = 2, + kEtwGCRootKindOther = 3, +}; + +enum EtwTypeFlags +{ + kEtwTypeFlagsDelegate = 0x1, + kEtwTypeFlagsFinalizable = 0x2, + kEtwTypeFlagsExternallyImplementedCOMObject = 0x4, + kEtwTypeFlagsArray = 0x8, +}; + +enum EtwThreadFlags +{ + kEtwThreadFlagGCSpecial = 0x00000001, + kEtwThreadFlagFinalizer = 0x00000002, + kEtwThreadFlagThreadPoolWorker = 0x00000004, +}; + +#ifndef FEATURE_REDHAWK + +#if defined(FEATURE_EVENT_TRACE) +#if !defined(FEATURE_PAL) + +// +// Use this macro at the least before calling the Event Macros +// + +#define ETW_TRACING_INITIALIZED(RegHandle) \ + (g_pEtwTracer && RegHandle) + +// +// Use this macro to check if an event is enabled +// if the fields in the event are not cheap to calculate +// +#define ETW_EVENT_ENABLED(Context, EventDescriptor) \ + (MCGEN_ENABLE_CHECK(Context, EventDescriptor)) + +// +// Use this macro to check if a category of events is enabled +// + +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) \ + (Context.IsEnabled && McGenEventProviderEnabled(&Context, Level, Keyword)) + + +// This macro only checks if a provider is enabled +// It does not check the flags and keywords for which it is enabled +#define ETW_PROVIDER_ENABLED(ProviderSymbol) \ + ProviderSymbol##_Context.IsEnabled + + +#else //defined(FEATURE_PAL) + +#define ETW_INLINE +#define ETWOnStartup(StartEventName, EndEventName) +#define ETWFireEvent(EventName) + +#define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsEventLoggingEnabled()) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsEventLoggingEnabled()) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) + +#endif // !defined(FEATURE_PAL) + +#else // FEATURE_EVENT_TRACE + +#define ETWOnStartup(StartEventName, EndEventName) +#define ETWFireEvent(EventName) + +#define ETW_TRACING_INITIALIZED(RegHandle) (FALSE) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (FALSE) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (FALSE) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) + +#endif // FEATURE_EVENT_TRACE + +#endif // FEATURE_REDHAWK + +// During a heap walk, this is the storage for keeping track of all the nodes and edges +// being batched up by ETW, and for remembering whether we're also supposed to call into +// a profapi profiler. This is allocated toward the end of a GC and passed to us by the +// GC heap walker. +struct ProfilerWalkHeapContext +{ +public: + ProfilerWalkHeapContext(BOOL fProfilerPinnedParam, LPVOID pvEtwContextParam) + { + fProfilerPinned = fProfilerPinnedParam; + pvEtwContext = pvEtwContextParam; + } + + BOOL fProfilerPinned; + LPVOID pvEtwContext; +}; + +#ifdef FEATURE_EVENT_TRACE + +class Object; +#if !defined(FEATURE_PAL) +/******************************/ +/* CLR ETW supported versions */ +/******************************/ +#define ETW_SUPPORTED_MAJORVER 5 // ETW is supported on win2k and above +#define ETW_ENABLED_MAJORVER 6 // OS versions >= to this we enable ETW registration by default, since on XP and Windows 2003, registration is too slow. + +/***************************************/ +/* Tracing levels supported by CLR ETW */ +/***************************************/ +#define ETWMAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported +#define TRACE_LEVEL_NONE 0 // Tracing is not on +#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination +#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging +#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure +#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit +#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps + +struct ProfilingScanContext; + +// +// Use this macro to check if ETW is initialized and the event is enabled +// +#define ETW_TRACING_ENABLED(Context, EventDescriptor) \ + (Context.IsEnabled && ETW_TRACING_INITIALIZED(Context.RegistrationHandle) && ETW_EVENT_ENABLED(Context, EventDescriptor)) + +// +// Using KEYWORDZERO means when checking the events category ignore the keyword +// +#define KEYWORDZERO 0x0 + +// +// Use this macro to check if ETW is initialized and the category is enabled +// +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) \ + (ETW_TRACING_INITIALIZED(Context.RegistrationHandle) && ETW_CATEGORY_ENABLED(Context, Level, Keyword)) + + #define ETWOnStartup(StartEventName, EndEventName) \ + ETWTraceStartup trace##StartEventName##(Microsoft_Windows_DotNETRuntimePrivateHandle, &StartEventName, &StartupId, &EndEventName, &StartupId); + #define ETWFireEvent(EventName) \ + ETWTraceStartup::StartupTraceEvent(Microsoft_Windows_DotNETRuntimePrivateHandle, &EventName, &StartupId); + +#ifndef FEATURE_REDHAWK +// Headers +#include <initguid.h> +#include <wmistr.h> +#include <evntrace.h> +#include <evntprov.h> +#if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) +#define GetVersionEx(Version) (GetOSVersion((LPOSVERSIONINFOW)Version)) +#else +#define GetVersionEx(Version) (WszGetVersionEx((LPOSVERSIONINFOW)Version)) +#endif // !DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE +#endif //!FEATURE_REDHAWK +#endif //!defined(FEATURE_PAL) + + +#else // FEATURE_EVENT_TRACE + +#include "etmdummy.h" +#endif // FEATURE_EVENT_TRACE + +#ifndef FEATURE_REDHAWK + +#include "corprof.h" + +// g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. +// This enables both the VM and Utilcode to raise ETW events. +extern UINT32 g_nClrInstanceId; +extern BOOL g_fEEManagedEXEStartup; +extern BOOL g_fEEIJWStartup; + +#define GetClrInstanceId() (static_cast<UINT16>(g_nClrInstanceId)) + +#if defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) + +#include "clrconfig.h" + class XplatEventLogger +{ + public: + inline static BOOL IsEventLoggingEnabled() + { + static ConfigDWORD configEventLogging; + return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); + } +}; + +#endif //defined(FEATURE_EVENT_TRACE) + +#if defined(FEATURE_EVENT_TRACE) + +#ifndef FEATURE_PAL +// Callback and stack support +#if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) +extern "C" { + /* ETW control callback + * Desc: This function handles the ETW control + * callback. + * Ret: success or failure + ***********************************************/ + VOID EtwCallback( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext); +} + +// +// User defined callback +// +#define MCGEN_PRIVATE_ENABLE_CALLBACK(RequestCode, Context, InOutBufferSize, Buffer) \ + 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) + +// +// User defined callback2 +// +#define MCGEN_PRIVATE_ENABLE_CALLBACK_V2(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) \ + EtwCallback(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) + +extern "C" { + /* ETW callout + * Desc: This function handles the ETW callout + * Ret: success or failure + ***********************************************/ + VOID EtwCallout( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR Descriptor, + ULONG ArgumentCount, + PEVENT_DATA_DESCRIPTOR EventData); +} + +// +// Call user defined callout +// +#define MCGEN_CALLOUT(RegHandle, Descriptor, NumberOfArguments, EventData) \ + EtwCallout(RegHandle, Descriptor, NumberOfArguments, EventData) +#endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE + +#endif //!FEATURE_PAL + +#include "clretwallmain.h" + +#endif // FEATURE_EVENT_TRACE + +/**************************/ +/* CLR ETW infrastructure */ +/**************************/ +// #CEtwTracer +// On Windows Vista, ETW has gone through a major upgrade, and one of the most significant changes is the +// introduction of the unified event provider model and APIs. The older architecture used the classic ETW +// events. The new ETW architecture uses the manifest based events. To support both types of events at the +// same time, we use the manpp tool for generating event macros that can be directly used to fire ETW events +// from various components within the CLR. +// (http://diagnostics/sites/etw/Lists/Announcements/DispForm.aspx?ID=10&Source=http%3A%2F%2Fdiagnostics%2Fsites%2Fetw%2Fdefault%2Easpx) +// Every ETW provider has to Register itself to the system, so that when enabled, it is capable of firing +// ETW events. file:../VM/eventtrace.cpp#Registration is where the actual Provider Registration takes place. +// At process shutdown, a registered provider need to be unregistered. +// file:../VM/eventtrace.cpp#Unregistration. Since ETW can also be enabled at any instant after the process +// has started, one may want to do something useful when that happens (e.g enumerate all the loaded modules +// in the system). To enable this, we have to implement a callback routine. +// file:../VM/eventtrace.cpp#EtwCallback is CLR's implementation of the callback. +// + +#include "daccess.h" +class Module; +class Assembly; +class MethodDesc; +class MethodTable; +class BaseDomain; +class AppDomain; +class SString; +class CrawlFrame; +class LoaderAllocator; +class AssemblyLoaderAllocator; +struct AllLoggedTypes; +class CrstBase; +class BulkTypeEventLogger; +class TypeHandle; +class Thread; + + +// All ETW helpers must be a part of this namespace +// We have auto-generated macros to directly fire the events +// but in some cases, gathering the event payload information involves some work +// and it can be done in a relevant helper class like the one's in this namespace +namespace ETW +{ + // Class to wrap the ETW infrastructure logic +#if !defined(FEATURE_PAL) + class CEtwTracer + { +#if defined(FEATURE_EVENT_TRACE) + ULONG RegGuids(LPCGUID ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle); +#endif + + public: +#ifdef FEATURE_EVENT_TRACE + // Registers all the Event Tracing providers + HRESULT Register(); + + // Unregisters all the Event Tracing providers + HRESULT UnRegister(); +#else + HRESULT Register() + { + return S_OK; + } + HRESULT UnRegister() + { + return S_OK; + } +#endif // FEATURE_EVENT_TRACE + }; +#endif // !defined(FEATURE_PAL) + + class LoaderLog; + class MethodLog; + // Class to wrap all the enumeration logic for ETW + class EnumerationLog + { + friend class ETW::LoaderLog; + friend class ETW::MethodLog; +#ifdef FEATURE_EVENT_TRACE + static VOID SendThreadRundownEvent(); + static VOID IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions); + static VOID IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions); + static VOID IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions); + static VOID IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions); + static VOID IterateModule(Module *pModule, DWORD enumerationOptions); + static VOID EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions); + static DWORD GetEnumerationOptionsFromRuntimeKeywords(); + public: + typedef union _EnumerationStructs + { + typedef enum _EnumerationOptions + { + None= 0x00000000, + DomainAssemblyModuleLoad= 0x00000001, + DomainAssemblyModuleUnload= 0x00000002, + DomainAssemblyModuleDCStart= 0x00000004, + DomainAssemblyModuleDCEnd= 0x00000008, + JitMethodLoad= 0x00000010, + JitMethodUnload= 0x00000020, + JitMethodDCStart= 0x00000040, + JitMethodDCEnd= 0x00000080, + NgenMethodLoad= 0x00000100, + NgenMethodUnload= 0x00000200, + NgenMethodDCStart= 0x00000400, + NgenMethodDCEnd= 0x00000800, + ModuleRangeLoad= 0x00001000, + ModuleRangeDCStart= 0x00002000, + ModuleRangeDCEnd= 0x00004000, + ModuleRangeLoadPrivate= 0x00008000, + MethodDCStartILToNativeMap= 0x00010000, + MethodDCEndILToNativeMap= 0x00020000, + JitMethodILToNativeMap= 0x00040000, + TypeUnload= 0x00080000, + + // Helpers + ModuleRangeEnabledAny = ModuleRangeLoad | ModuleRangeDCStart | ModuleRangeDCEnd | ModuleRangeLoadPrivate, + JitMethodLoadOrDCStartAny = JitMethodLoad | JitMethodDCStart | MethodDCStartILToNativeMap, + JitMethodUnloadOrDCEndAny = JitMethodUnload | JitMethodDCEnd | MethodDCEndILToNativeMap, + }EnumerationOptions; + }EnumerationStructs; + + static VOID ProcessShutdown(); + static VOID ModuleRangeRundown(); + static VOID StartRundown(); + static VOID EndRundown(); + static VOID EnumerateForCaptureState(); +#else + public: + static VOID ProcessShutdown() {}; + static VOID StartRundown() {}; + static VOID EndRundown() {}; +#endif // FEATURE_EVENT_TRACE + }; + + + // Class to wrap all the sampling logic for ETW + + class SamplingLog + { +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) + public: + typedef enum _EtwStackWalkStatus + { + Completed = 0, + UnInitialized = 1, + InProgress = 2 + } EtwStackWalkStatus; + private: + static const UINT8 s_MaxStackSize=100; + UINT32 m_FrameCount; + SIZE_T m_EBPStack[SamplingLog::s_MaxStackSize]; + VOID Append(SIZE_T currentFrame); + EtwStackWalkStatus SaveCurrentStack(int skipTopNFrames=1); + public: + static ULONG SendStackTrace(MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid); + EtwStackWalkStatus GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack); +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) + }; + + // Class to wrap all Loader logic for ETW + class LoaderLog + { + friend class ETW::EnumerationLog; +#if defined(FEATURE_EVENT_TRACE) + static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE); + static ULONG SendModuleRange(__in Module *pModule, __in DWORD dwEventOptions); + static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions); + static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); + public: + typedef union _LoaderStructs + { + typedef enum _AppDomainFlags + { + DefaultDomain=0x1, + ExecutableDomain=0x2, + SharedDomain=0x4 + }AppDomainFlags; + + typedef enum _AssemblyFlags + { + DomainNeutralAssembly=0x1, + DynamicAssembly=0x2, + NativeAssembly=0x4, + CollectibleAssembly=0x8, + }AssemblyFlags; + + typedef enum _ModuleFlags + { + DomainNeutralModule=0x1, + NativeModule=0x2, + DynamicModule=0x4, + ManifestModule=0x8, + IbcOptimized=0x10 + }ModuleFlags; + + typedef enum _RangeFlags + { + HotRange=0x0 + }RangeFlags; + + }LoaderStructs; + + static VOID DomainLoadReal(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL); + + static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName = NULL) + { + if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) + { + DomainLoadReal(pDomain, wszFriendlyName); + } + } + + static VOID DomainUnload(AppDomain *pDomain); + static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator); + static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule); +#else + public: + static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL) {}; + static VOID DomainUnload(AppDomain *pDomain) {}; + static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) {}; + static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Method logic for ETW + class MethodLog + { + friend class ETW::EnumerationLog; +#ifdef FEATURE_EVENT_TRACE + static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); + static VOID SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, + LoaderAllocator *pLoaderAllocatorFilter, + DWORD dwEventOptions, + BOOL fLoadOrDCStart, + BOOL fUnloadOrDCEnd, + BOOL fSendMethodEvent, + BOOL fSendILToNativeMapEvent, + BOOL fGetReJitIDs); + static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); + static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); + static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, ReJITID rejitID); + 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); + static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); + public: + typedef union _MethodStructs + { + typedef enum _MethodFlags + { + DynamicMethod=0x1, + GenericMethod=0x2, + SharedGenericCode=0x4, + JittedMethod=0x8, + JitHelperMethod=0x10 + }MethodFlags; + + typedef enum _MethodExtent + { + HotSection=0x00000000, + ColdSection=0x10000000 + }MethodExtent; + + }MethodStructs; + + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0); + static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); + static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers); + static VOID MethodRestored(MethodDesc * pMethodDesc); + static VOID MethodTableRestored(MethodTable * pMethodTable); + static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc); +#else // FEATURE_EVENT_TRACE + public: + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL) {}; + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0) {}; + static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; + static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; + static VOID MethodRestored(MethodDesc * pMethodDesc) {}; + static VOID MethodTableRestored(MethodTable * pMethodTable) {}; + static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Security logic for ETW + class SecurityLog + { +#ifdef FEATURE_EVENT_TRACE + public: + static VOID StrongNameVerificationStart(DWORD dwInFlags, __in LPWSTR strFullyQualifiedAssemblyName); + static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, __in LPWSTR strFullyQualifiedAssemblyName); + + static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain); + static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet); + + static void FireTokenTransparencyComputationStart(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireTokenTransparencyComputationEnd(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); +#else + public: + static VOID StrongNameVerificationStart(DWORD dwInFlags, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; + static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; + + static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain) {}; + static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet) {}; + + static void FireTokenTransparencyComputationStart(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireTokenTransparencyComputationEnd(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Binder logic for ETW + class BinderLog + { + public: + typedef union _BinderStructs { + typedef enum _NGENBINDREJECT_REASON { + NGEN_BIND_START_BIND = 0, + NGEN_BIND_NO_INDEX = 1, + NGEN_BIND_SYSTEM_ASSEMBLY_NOT_AVAILABLE = 2, + NGEN_BIND_NO_NATIVE_IMAGE = 3, + NGEN_BIND_REJECT_CONFIG_MASK = 4, + NGEN_BIND_FAIL = 5, + NGEN_BIND_INDEX_CORRUPTION = 6, + NGEN_BIND_REJECT_TIMESTAMP = 7, + NGEN_BIND_REJECT_NATIVEIMAGE_NOT_FOUND = 8, + NGEN_BIND_REJECT_IL_SIG = 9, + NGEN_BIND_REJECT_LOADER_EVAL_FAIL = 10, + NGEN_BIND_MISSING_FOUND = 11, + NGEN_BIND_REJECT_HOSTASM = 12, + NGEN_BIND_REJECT_IL_NOT_FOUND = 13, + NGEN_BIND_REJECT_APPBASE_NOT_FILE = 14, + NGEN_BIND_BIND_DEPEND_REJECT_REF_DEF_MISMATCH = 15, + NGEN_BIND_BIND_DEPEND_REJECT_NGEN_SIG = 16, + NGEN_BIND_APPLY_EXTERNAL_RELOCS_FAILED = 17, + NGEN_BIND_SYSTEM_ASSEMBLY_NATIVEIMAGE_NOT_AVAILABLE = 18, + NGEN_BIND_ASSEMBLY_HAS_DIFFERENT_GRANT = 19, + NGEN_BIND_ASSEMBLY_NOT_DOMAIN_NEUTRAL = 20, + NGEN_BIND_NATIVEIMAGE_VERSION_MISMATCH = 21, + NGEN_BIND_LOADFROM_NOT_ALLOWED = 22, + NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY = 23 + } NGENBINDREJECT_REASON; + } BinderStructs; + }; + + // Class to wrap all Exception logic for ETW + class ExceptionLog + { + public: +#ifdef FEATURE_EVENT_TRACE + static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException); + static VOID ExceptionThrownEnd(); + static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionCatchEnd(); + static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionFinallyEnd(); + static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionFilterEnd(); + +#else + static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) {}; + static VOID ExceptionThrownEnd() {}; + static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionCatchEnd() {}; + static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionFinallyEnd() {}; + static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionFilterEnd() {}; +#endif // FEATURE_EVENT_TRACE + typedef union _ExceptionStructs + { + typedef enum _ExceptionThrownFlags + { + HasInnerException=0x1, + IsNestedException=0x2, + IsReThrownException=0x4, + IsCSE=0x8, + IsCLSCompliant=0x10 + }ExceptionThrownFlags; + }ExceptionStructs; + }; + // Class to wrap all Contention logic for ETW + class ContentionLog + { + public: + typedef union _ContentionStructs + { + typedef enum _ContentionFlags { + ManagedContention=0, + NativeContention=1 + } ContentionFlags; + } ContentionStructs; + }; + // Class to wrap all Interop logic for ETW + class InteropLog + { + public: + }; + + // Class to wrap all Information logic for ETW + class InfoLog + { + public: + typedef union _InfoStructs + { + typedef enum _StartupMode + { + ManagedExe=0x1, + HostedCLR=0x2, + IJW=0x4, + COMActivated=0x8, + Other=0x10 + }StartupMode; + + typedef enum _Sku + { + DesktopCLR=0x1, + CoreCLR=0x2 + }Sku; + + typedef enum _EtwMode + { + Normal=0x0, + Callback=0x1 + }EtwMode; + }InfoStructs; + +#ifdef FEATURE_EVENT_TRACE + static VOID RuntimeInformation(INT32 type); +#else + static VOID RuntimeInformation(INT32 type) {}; +#endif // FEATURE_EVENT_TRACE + }; + + class CodeSymbolLog + { + public: +#ifdef FEATURE_EVENT_TRACE + static VOID EmitCodeSymbols(Module* pModule); + static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes); + static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, + DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead); +#else + static VOID EmitCodeSymbols(Module* pModule) {} + static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes) { return S_OK; } + static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, + DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead) { return S_OK; } +#endif // FEATURE_EVENT_TRACE + }; +}; + + +#define ETW_IS_TRACE_ON(level) ( FALSE ) // for fusion which is eventually going to get removed +#define ETW_IS_FLAG_ON(flag) ( FALSE ) // for fusion which is eventually going to get removed + +// Commonly used constats for ETW Assembly Loader and Assembly Binder events. +#define ETWLoadContextNotAvailable (LOADCTX_TYPE_HOSTED + 1) +#define ETWAppDomainIdNotAvailable 0 // Valid AppDomain IDs start from 1 + +#define ETWFieldUnused 0 // Indicates that a particular field in the ETW event payload template is currently unused. + +#define ETWLoaderLoadTypeNotAvailable 0 // Static or Dynamic Load is only valid at LoaderPhaseStart and LoaderPhaseEnd events - for other events, 0 indicates "not available" +#define ETWLoaderStaticLoad 0 // Static reference load +#define ETWLoaderDynamicLoad 1 // Dynamic assembly load + +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +// +// The ONE and only ONE global instantiation of this class +// +extern ETW::CEtwTracer * g_pEtwTracer; + +// +// Special Handling of Startup events +// + +// "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; +// on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so +// we manually place it here. +ETW_INLINE +ULONG +CoMofTemplate_h( + __in REGHANDLE RegHandle, + __in PCEVENT_DESCRIPTOR Descriptor, + __in_opt LPCGUID EventGuid, + __in const unsigned short ClrInstanceID + ) +{ +#define ARGUMENT_COUNT_h 1 + ULONG Error = ERROR_SUCCESS; +typedef struct _MCGEN_TRACE_BUFFER { + EVENT_TRACE_HEADER Header; + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_h]; +} MCGEN_TRACE_BUFFER; + + MCGEN_TRACE_BUFFER TraceBuf; + PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; + + EventDataDescCreate(&EventData[0], &ClrInstanceID, sizeof(const unsigned short) ); + + + { + Error = EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_h, EventData); + + } + +#ifdef MCGEN_CALLOUT +MCGEN_CALLOUT(RegHandle, + Descriptor, + ARGUMENT_COUNT_h, + EventData); +#endif + + return Error; +} + +class ETWTraceStartup { + REGHANDLE TraceHandle; + PCEVENT_DESCRIPTOR EventStartDescriptor; + LPCGUID EventStartGuid; + PCEVENT_DESCRIPTOR EventEndDescriptor; + LPCGUID EventEndGuid; +public: + ETWTraceStartup(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventStartDescriptor, LPCGUID _EventStartGuid, PCEVENT_DESCRIPTOR _EventEndDescriptor, LPCGUID _EventEndGuid) { + TraceHandle = _TraceHandle; + EventStartDescriptor = _EventStartDescriptor; + EventEndDescriptor = _EventEndDescriptor; + EventStartGuid = _EventStartGuid; + EventEndGuid = _EventEndGuid; + StartupTraceEvent(TraceHandle, EventStartDescriptor, EventStartGuid); + } + ~ETWTraceStartup() { + StartupTraceEvent(TraceHandle, EventEndDescriptor, EventEndGuid); + } + static void StartupTraceEvent(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventDescriptor, LPCGUID _EventGuid) { + EVENT_DESCRIPTOR desc = *_EventDescriptor; + if(ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, desc)) + { + CoMofTemplate_h(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context.RegistrationHandle, _EventDescriptor, _EventGuid, GetClrInstanceId()); + } + } +}; +// "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; +// on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so +// we manually place it here. +FORCEINLINE +BOOLEAN __stdcall +McGenEventTracingEnabled( + __in PMCGEN_TRACE_CONTEXT EnableInfo, + __in PCEVENT_DESCRIPTOR EventDescriptor + ) +{ + + if(!EnableInfo){ + return FALSE; + } + + + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((EventDescriptor->Level <= EnableInfo->Level) || // This also covers the case of Level == 0. + (EnableInfo->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((EventDescriptor->Keyword == (ULONGLONG)0) || + ((EventDescriptor->Keyword & EnableInfo->MatchAnyKeyword) && + ((EventDescriptor->Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { + return TRUE; + } + } + + return FALSE; +} + + +ETW_INLINE +ULONG +ETW::SamplingLog::SendStackTrace( + MCGEN_TRACE_CONTEXT TraceContext, + PCEVENT_DESCRIPTOR Descriptor, + LPCGUID EventGuid) +{ +#define ARGUMENT_COUNT_CLRStackWalk 5 + ULONG Result = ERROR_SUCCESS; +typedef struct _MCGEN_TRACE_BUFFER { + EVENT_TRACE_HEADER Header; + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_CLRStackWalk]; +} MCGEN_TRACE_BUFFER; + + REGHANDLE RegHandle = TraceContext.RegistrationHandle; + if(!TraceContext.IsEnabled || !McGenEventTracingEnabled(&TraceContext, Descriptor)) + { + return Result; + } + + PVOID *Stack = NULL; + UINT32 FrameCount = 0; + ETW::SamplingLog stackObj; + if(stackObj.GetCurrentThreadsCallStack(&FrameCount, &Stack) == ETW::SamplingLog::Completed) + { + UCHAR Reserved1=0, Reserved2=0; + UINT16 ClrInstanceId = GetClrInstanceId(); + MCGEN_TRACE_BUFFER TraceBuf; + PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; + + EventDataDescCreate(&EventData[0], &ClrInstanceId, sizeof(const UINT16) ); + + EventDataDescCreate(&EventData[1], &Reserved1, sizeof(const UCHAR) ); + + EventDataDescCreate(&EventData[2], &Reserved2, sizeof(const UCHAR) ); + + EventDataDescCreate(&EventData[3], &FrameCount, sizeof(const unsigned int) ); + + EventDataDescCreate(&EventData[4], Stack, sizeof(PVOID) * FrameCount ); + + return EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_CLRStackWalk, EventData); + } + return Result; +}; + +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) +#ifdef FEATURE_EVENT_TRACE +#ifdef _TARGET_X86_ +struct CallStackFrame +{ + struct CallStackFrame* m_Next; + SIZE_T m_ReturnAddress; +}; +#endif // _TARGET_X86_ +#endif // FEATURE_EVENT_TRACE + +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +FORCEINLINE +BOOLEAN __stdcall +McGenEventProviderEnabled( + __in PMCGEN_TRACE_CONTEXT Context, + __in UCHAR Level, + __in ULONGLONG Keyword + ) +{ + if(!Context) { + return FALSE; + } + + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((Level <= Context->Level) || // This also covers the case of Level == 0. + (Context->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((Keyword == (ULONGLONG)0) || + ((Keyword & Context->MatchAnyKeyword) && + ((Keyword & Context->MatchAllKeyword) == Context->MatchAllKeyword))) { + return TRUE; + } + } + return FALSE; +} +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) + + +#endif // !FEATURE_REDHAWK + +// These parts of the ETW namespace are common for both FEATURE_REDHAWK and +// !FEATURE_REDHAWK builds. + + +struct ProfilingScanContext; +class Object; + +namespace ETW +{ + // Class to wrap the logging of threads (runtime and rundown providers) + class ThreadLog + { + private: + static DWORD GetEtwThreadFlags(Thread * pThread); + + public: + static VOID FireThreadCreated(Thread * pThread); + static VOID FireThreadDC(Thread * pThread); + }; +}; + + +#endif //_ETWTRACER_HXX_ |