summaryrefslogtreecommitdiff
path: root/src/inc/eventtracebase.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/eventtracebase.h')
-rw-r--r--src/inc/eventtracebase.h1082
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_