Skip to content

Commit

Permalink
Fix type of Level argument; improvements to RT and File trace stoppin…
Browse files Browse the repository at this point in the history
…g; TdhUnloadManifest bug.
  • Loading branch information
lilhoser committed Oct 14, 2024
1 parent b382de2 commit 55e5a82
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 42 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ jobs:
steps:
# setup .NET using setup-dotnet action
- name: Setup .NET
uses: actions/setup-dotnet@v3.0.3
uses: actions/setup-dotnet@v4
- name: checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
uses: microsoft/setup-msbuild@v2
- name: Setup NuGet
uses: nuget/setup-nuget@v1
- uses: actions/cache@v3
uses: nuget/setup-nuget@v2
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
Expand All @@ -25,4 +25,4 @@ jobs:
run: |
msbuild.exe etwlib.sln /nologo /nr:false /p:platform="Any CPU" /p:configuration="Release"
- name: Test
run: sudo dotnet test --no-restore --verbosity normal
run: dotnet test --no-restore --verbosity normal
4 changes: 2 additions & 2 deletions EnabledProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public void SetFilteredPackageId(string PackageId)
m_FilterDescriptors.Add(descriptor);
}

public void SetStackwalkLevelKw(EventTraceLevel Level, ulong MatchAnyKeyword, ulong MatchAllKeyword, bool FilterIn)
public void SetStackwalkLevelKw(byte Level, ulong MatchAnyKeyword, ulong MatchAllKeyword, bool FilterIn)
{
foreach (var desc in m_FilterDescriptors)
{
Expand All @@ -419,7 +419,7 @@ public void SetStackwalkLevelKw(EventTraceLevel Level, ulong MatchAnyKeyword, ul
}

var filter = new EVENT_FILTER_LEVEL_KW();
filter.Level = (byte)Level;
filter.Level = Level;
filter.MatchAllKeyword = MatchAllKeyword;
filter.MatchAnyKeyword = MatchAnyKeyword;
filter.FilterIn = FilterIn;
Expand Down
14 changes: 14 additions & 0 deletions FileTrace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,24 @@ public FileTrace(string EtlFileName)

public override void Start()
{
//
// A FileTrace opens an existing ETL, so there is no start operation.
//
Trace(TraceLoggerType.FileTrace,
TraceEventType.Information,
$"Starting FileTrace for log {m_LogFile.LogFileName}");
return;
}

public override void Stop()
{
//
// A FileTrace opens an existing ETL, so there is no stop operation.
//
Trace(TraceLoggerType.FileTrace,
TraceEventType.Information,
$"Stopping FileTrace for log {m_LogFile.LogFileName}");
return;
}
}
}
40 changes: 39 additions & 1 deletion ParsedEtwManifestEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,45 @@ public int CompareTo(ParsedEtwManifestEvent? Other)
public override string ToString()
{
return $"Id={Id}, Version={Version}, Task={Task}, Opcode={Opcode}, " +
$"Channel={Channel}, Level={Level}, Keywords={Keywords}";
$"Channel={Channel}, Level={Level}, Keywords={Keywords}, Template={Template}";
}

public static ParsedEtwManifestEvent? FromString(string Value)
{
var values = Value.Split(',', StringSplitOptions.RemoveEmptyEntries);
if (values.Length != 8)
{
return null;
}
var dict = new Dictionary<string, string>();
foreach (var v in values)
{
var kvp = v.Split('=', StringSplitOptions.RemoveEmptyEntries);
if (kvp.Length < 1)
{
return null;
}
var key = kvp[0];
var val = string.Empty;
if (kvp.Length == 2)
{
val = kvp[1];
}
if (dict.ContainsKey(key))
{
return null;
}
dict.Add(key, val);
}
return new ParsedEtwManifestEvent(
dict["Id"],
dict["Version"],
dict["Opcode"],
dict["Channel"],
dict["Level"],
dict["Keywords"],
dict["Task"],
dict["Template"]);
}
}
}
15 changes: 14 additions & 1 deletion ProviderParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public static class ProviderParser
{
var parsedManifest = new ParsedEtwManifest();
var fieldResults = new List<ParsedEtwManifestField>();
var manifestLoaded = false;

//
// If a manifest location was provided, ask TDH to load it.
Expand All @@ -172,6 +173,7 @@ public static class ProviderParser
try
{
LoadProviderManifest(ManifestLocation);
manifestLoaded = true;
}
catch (Exception ex)
{
Expand Down Expand Up @@ -492,20 +494,31 @@ public static class ProviderParser
parsedManifest.StringTable = parsedManifest.StringTable.Distinct().ToList();
parsedManifest.StringTable.Sort();

if (manifestLoaded)
{
_ = TdhUnloadManifest(ManifestLocation);
}
return parsedManifest;
}

public
static
Dictionary<ParsedEtwProvider, ParsedEtwManifest>
GetManifests()
GetManifests(int Limit = 0)
{
var results = new Dictionary<ParsedEtwProvider, ParsedEtwManifest>();
var providers = GetProviders();
foreach (var provider in providers)
{
try
{
if (Limit > 0 && results.Count >= Limit)
{
Trace(TraceLoggerType.EtwProviderParser,
TraceEventType.Verbose,
$"Processed {Limit} providers, stopping.");
break;
}
if (results.ContainsKey(provider))
{
//
Expand Down
90 changes: 61 additions & 29 deletions RealTimeTrace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ public class RealTimeTrace : TraceSession
private nint m_PropertiesBuffer;
private long m_SessionHandle;

public RealTimeTrace(string SessionName)
public RealTimeTrace(string SessionName) : base()
{
m_SessionName = SessionName;
m_SessionGuid = Guid.NewGuid();
m_PropertiesBuffer = nint.Zero;
m_SessionHandle = 0;
m_SessionHandle = nint.Zero;
m_LogFile.LoggerName = m_SessionName;
m_LogFile.ProcessTraceMode = ProcessTraceMode.EventRecord | ProcessTraceMode.RealTime;
}
Expand All @@ -60,33 +60,7 @@ protected override void Dispose(bool disposing)
TraceEventType.Information,
"Disposing RealTimeTrace");

if (m_SessionHandle != 0 && m_SessionHandle != -1)
{
uint result;
foreach (var provider in m_EnabledProviders)
{
result = provider.Disable(m_SessionHandle);
if (result != ERROR_SUCCESS)
{
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Error,
$"RealTimeTrace dispose could not disable provider: " +
$"{result:X}");
}
}
result = ControlTrace(
m_SessionHandle,
m_SessionName,
m_PropertiesBuffer,
ControlCode.Stop);
if (result != ERROR_SUCCESS)
{
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Error,
$"RealTimeTrace dispose could not stop trace: " +
$"{result:X}");
}
}
Stop();

if (m_PropertiesBuffer != nint.Zero)
{
Expand Down Expand Up @@ -183,6 +157,64 @@ public override void Start()
}
}

public override void Stop()
{
if (m_SessionHandle != 0 && m_SessionHandle != -1)
{
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Information,
$"Stopping RealTimeTrace {m_SessionName}...");
uint result;
foreach (var provider in m_EnabledProviders)
{
result = provider.Disable(m_SessionHandle);
if (result != ERROR_SUCCESS)
{
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Error,
$"RealTimeTrace dispose could not disable provider: " +
$"{result:X}");
}
}
result = ControlTrace(
m_SessionHandle,
m_SessionName,
m_PropertiesBuffer,
ControlCode.Stop);
if (result != ERROR_SUCCESS)
{
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Error,
$"RealTimeTrace dispose could not stop trace: " +
$"{result:X}");
}
}
}

public static long Open(string Name)
{
EVENT_TRACE_LOGFILE logfile = new EVENT_TRACE_LOGFILE();
logfile.LoggerName = Name;
logfile.ProcessTraceMode = ProcessTraceMode.EventRecord | ProcessTraceMode.RealTime;
Trace(TraceLoggerType.RealTimeTrace,
TraceEventType.Information,
$"Opening existing RealTimeTrace {Name}...");
var logFilePointer = Marshal.AllocHGlobal(Marshal.SizeOf(logfile));
Marshal.StructureToPtr(logfile, logFilePointer, false);
var handle = OpenTrace(logFilePointer);
Marshal.FreeHGlobal(logFilePointer);
if (handle == -1 || handle == 0)
{
var error = "OpenTrace() returned an invalid handle: 0x" +
Marshal.GetLastWin32Error().ToString("X");
Trace(TraceLoggerType.TraceSession,
TraceEventType.Error,
error);
throw new Exception(error);
}
return handle;
}

private
void
GenerateTraceProperties()
Expand Down
1 change: 1 addition & 0 deletions TraceSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public void AddProvider(EnabledProvider Provider)
}

public abstract void Start();
public abstract void Stop();

public void Consume(
EventRecordCallback EventCallback,
Expand Down
2 changes: 1 addition & 1 deletion UnitTests/FilterByStackwalkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void LevelKw(
{
var provider = trace.AddProvider(
s_WinKernelRegistryGuid, "WinKernelReg", Level, (ulong)MatchAnyKeyword, 0);
provider.SetStackwalkLevelKw(Level, (ulong)MatchAnyKeyword, 0, Enable);
provider.SetStackwalkLevelKw((byte)Level, (ulong)MatchAnyKeyword, 0, Enable);
trace.Start();

//
Expand Down
Loading

0 comments on commit 55e5a82

Please sign in to comment.