Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 56 additions & 26 deletions src/TraceEvent/RegisteredTraceEventParser.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
using FastSerialization;
using Microsoft.Diagnostics.Tracing.Compatibility;
using Microsoft.Diagnostics.Tracing.Extensions;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -88,7 +87,7 @@ public static string GetManifestForRegisteredProvider(string providerName)
public static string GetManifestForRegisteredProvider(Guid providerGuid)
{
int buffSize = 84000; // Still in the small object heap.
byte* buffer = (byte*)System.Runtime.InteropServices.Marshal.AllocHGlobal(buffSize);
var buffer = new byte[buffSize]; // Still in the small object heap.
byte* enumBuffer = null;

TraceEventNativeMethods.EVENT_RECORD eventRecord = new TraceEventNativeMethods.EVENT_RECORD();
Expand Down Expand Up @@ -129,32 +128,53 @@ public static string GetManifestForRegisteredProvider(Guid providerGuid)
}
}

for (int ver = 0; ver <= 255; ver++)
int status;

for (; ; )
{
eventRecord.EventHeader.Version = (byte) ver;
int count;
int status;
for (; ; )
int size = buffer.Length;
status = TdhEnumerateManifestProviderEvents(eventRecord.EventHeader.ProviderId, buffer, ref size);
if (status != 122 || 20000000 < size) // 122 == Insufficient buffer keep it under 2Meg
{
int dummy;
status = ETWParsing.TdhGetAllEventsInformation(&eventRecord, IntPtr.Zero, out dummy, out count, buffer, ref buffSize);
if (status != 122 || 20000000 < buffSize) // 122 == Insufficient buffer keep it under 2Meg
{
break;
}
break;
}

buffer = new byte[size];
}

Marshal.FreeHGlobal((IntPtr)buffer);
buffer = (byte*)Marshal.AllocHGlobal(buffSize);
if (status == 0)
{
const int NumberOfEventsOffset = 0;
const int FirstDescriptorOffset = 8;
int eventCount = BitConverter.ToInt32(buffer, NumberOfEventsOffset);
var descriptors = new EVENT_DESCRIPTOR[eventCount];
fixed (EVENT_DESCRIPTOR* pDescriptors = descriptors)
{
Marshal.Copy(buffer, FirstDescriptorOffset, (IntPtr)pDescriptors, descriptors.Length * sizeof(EVENT_DESCRIPTOR));
}

// TODO FIX NOW deal with too small of a buffer.
if (status == 0)
foreach (var descriptor in descriptors)
{
TRACE_EVENT_INFO** eventInfos = (TRACE_EVENT_INFO**)buffer;
for (int i = 0; i < count; i++)
for (; ; )
{
int size = buffer.Length;
status = TdhGetManifestEventInformation(eventRecord.EventHeader.ProviderId, descriptor, buffer, ref size);
if (status != 122 || 20000000 < size) // 122 == Insufficient buffer keep it under 2Meg
{
break;
}

buffer = new byte[size];
}

if (status != 0)
{
continue;
}

fixed (byte* eventInfoBuff = buffer)
{
TRACE_EVENT_INFO* eventInfo = eventInfos[i];
byte* eventInfoBuff = (byte*)eventInfo;
var eventInfo = (TRACE_EVENT_INFO*)eventInfoBuff;
EVENT_PROPERTY_INFO* propertyInfos = &eventInfo->EventPropertyInfoArray;

if (providerName == null)
Expand Down Expand Up @@ -406,17 +426,12 @@ public static string GetManifestForRegisteredProvider(Guid providerGuid)
eventWriter.WriteLine("/>");
}
}
else if (status == 1168 && ver != 0) // Not Found give up
{
break;
}
}
if (enumBuffer != null)
{
System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)enumBuffer);
}

System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)buffer);
if (providerName == null)
{
throw new ApplicationException("Could not find provider with at GUID of " + providerGuid.ToString());
Expand Down Expand Up @@ -979,6 +994,21 @@ internal static extern int TdhGetEventMapInformation(
ref int infoSize
);

[DllImport("tdh.dll")]
internal static extern int TdhEnumerateManifestProviderEvents(
in Guid Guid,
[Out] byte[] pBuffer, // PROVIDER_EVENT_INFO*
ref int pBufferSize
);

[DllImport("tdh.dll")]
internal static extern int TdhGetManifestEventInformation(
in Guid Guid,
in EVENT_DESCRIPTOR eventDesc,
[Out] byte[] pBuffer, // TRACE_EVENT_INFORMATION*
ref int pBufferSize
);

[Flags]
internal enum MAP_FLAGS
{
Expand Down
7 changes: 6 additions & 1 deletion src/TraceEvent/TraceEvent.Tests/Parsing/DispatchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ public event Action<EmptyTraceData> Event039
/// Test code to ensure that the TraceEventDispatcher works properly in the face of lots of
/// adds and deletes.
/// </summary>
public class DispatcherTester
public class DispatcherTester : IDisposable
{
public DispatcherTester(ITestOutputHelper output)
{
Expand All @@ -600,6 +600,11 @@ public DispatcherTester(ITestOutputHelper output)
Output = output;
}

public void Dispose()
{
this.m_dispatcher.Dispose();
}

private ITestOutputHelper Output
{
get;
Expand Down
13 changes: 13 additions & 0 deletions src/TraceEvent/TraceEventNativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ internal enum TRACE_INFO_CLASS

TraceLbrConfigurationInfo = 20, // Filter flags
TraceLbrEventListInfo = 21, // int array

// Win 10 build 19582+
TraceStackCachingInfo = 24, // TRACE_STACK_CACHING_INFO
};

internal struct CLASSIC_EVENT_ID
Expand All @@ -290,6 +293,16 @@ internal struct CLASSIC_EVENT_ID
public int Interval;
};

internal struct TRACE_STACK_CACHING_INFO
{
public byte Enabled;
public byte Padding1;
public byte Padding2;
public byte Padding3;
public int CacheSize;
public int BucketCount;
}

internal struct PROFILE_SOURCE_INFO
{
public int NextEntryOffset; // relative to the start of this structure, 0 indicates end.
Expand Down
29 changes: 23 additions & 6 deletions src/TraceEvent/TraceEventSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// It is available from http://www.codeplex.com/hyperAddin
//
using Microsoft.Diagnostics.Tracing.Compatibility;
using Microsoft.Diagnostics.Tracing.Extensions;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Utilities;
using Microsoft.Win32;
Expand All @@ -18,6 +17,10 @@
using System.Threading;
using Utilities;

using STACK_TRACING_EVENT_ID = Microsoft.Diagnostics.Tracing.Extensions.STACK_TRACING_EVENT_ID; // Same as CLASSIC_EVENT_ID
using EVENT_TRACE_MERGE_EXTENDED_DATA = Microsoft.Diagnostics.Tracing.Extensions.EVENT_TRACE_MERGE_EXTENDED_DATA;
using ETWKernelControl = Microsoft.Diagnostics.Tracing.Extensions.ETWKernelControl;

namespace Microsoft.Diagnostics.Tracing.Session
{
/// <summary>
Expand Down Expand Up @@ -657,8 +660,12 @@ public unsafe bool EnableKernelProvider(KernelTraceEventParser.Keywords flags, K
throw new ApplicationException("CPU Sampling interval is too large.");
}

var succeeded = ETWControl.SetCpuSamplingRate((int)cpu100ns); // Always try to set, since it may not be the default
if (!succeeded && CpuSampleIntervalMSec != 1.0F)
// Always try to set, since it may not be the default
var interval = new TraceEventNativeMethods.TRACE_PROFILE_INTERVAL { Interval = (int)cpu100ns };
var result = TraceEventNativeMethods.TraceSetInformation(0,
TraceEventNativeMethods.TRACE_INFO_CLASS.TraceSampledProfileIntervalInfo,
&interval, sizeof(TraceEventNativeMethods.TRACE_PROFILE_INTERVAL));
if (result != 0 && CpuSampleIntervalMSec != 1.0F)
{
throw new ApplicationException("Can't set CPU sampling to " + CpuSampleIntervalMSec.ToString("f3") + "MSec.");
}
Expand Down Expand Up @@ -733,9 +740,14 @@ public unsafe bool EnableKernelProvider(KernelTraceEventParser.Keywords flags, K
Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRFromWin32(dwErr));
m_IsActive = true;

if (OperatingSystemVersion.AtLeast(62) && StackCompression)
if (StackCompression && OperatingSystemVersion.AtLeast(OperatingSystemVersion.Win10))
{
ETWControl.EnableStackCaching(m_SessionHandle.DangerousGetHandle());
var info = new TraceEventNativeMethods.TRACE_STACK_CACHING_INFO{ Enabled = 1 };
TraceEventNativeMethods.TraceSetInformation(
m_SessionHandle,
TraceEventNativeMethods.TRACE_INFO_CLASS.TraceStackCachingInfo,
&info,
sizeof(TraceEventNativeMethods.TRACE_STACK_CACHING_INFO));
}

EnableLastBranchRecordingIfConfigured();
Expand Down Expand Up @@ -878,7 +890,12 @@ public bool Stop(bool noThrow = false)
}
catch (Exception) { Debug.Assert(false); }

ETWControl.SetCpuSamplingRate(10000); // Set sample rate back to default 1 Msec
// Set sample rate back to default 1 Msec
var interval = new TraceEventNativeMethods.TRACE_PROFILE_INTERVAL { Interval = (int)10000 };
TraceEventNativeMethods.TraceSetInformation(0,
TraceEventNativeMethods.TRACE_INFO_CLASS.TraceSampledProfileIntervalInfo,
&interval, sizeof(TraceEventNativeMethods.TRACE_PROFILE_INTERVAL));

var propertiesBuff = stackalloc byte[PropertiesSize];
var properties = GetProperties(propertiesBuff);
int hr = TraceEventNativeMethods.ControlTrace(0UL, m_SessionName, properties, TraceEventNativeMethods.EVENT_TRACE_CONTROL_STOP);
Expand Down