diff --git a/ETWAnalyzer/Commands/DumpCommand.cs b/ETWAnalyzer/Commands/DumpCommand.cs index ad0c6e2..28a1209 100644 --- a/ETWAnalyzer/Commands/DumpCommand.cs +++ b/ETWAnalyzer/Commands/DumpCommand.cs @@ -397,13 +397,14 @@ class DumpCommand : ArgParser " ObjectRef -filedir/fd Extract\\ or xx.json7z" + Environment.NewLine + " [-TimeFmt s,Local,LocalTime,UTC,UTCTime,Here,HereTime] [-csv xx.csv] [-NoCSVSeparator] [-NoCmdLine] [-Clip] [-TestsPerRun dd -SkipNTests dd] [-TestRunIndex dd -TestRunCount dd] [-MinMaxMsTestTimes xx-yy ...] [-ProcessName/pn xx.exe(pid)] " + Environment.NewLine + " [-RelatedProcess xx.exe(pid)] [-MinMaxDuration minS [maxS]] [-MinMaxId min [max]] [-CreateStack filter] [-DestroyStack filter] [-StackFilter filter] [-Object filter] [-ObjectName filter] [-Handle filter] [-ShowRef]" + Environment.NewLine + - " [-ShowStack] [-Type filter] [-Leak] [-MultiProcess] [-Map [0,1]] [-PtrInMap 0x...] [-MinMaxMapSize min [max]] [-Overlapped] [-Showtotal Total,File,None]" + Environment.NewLine + + " [-ShowStack] [-Type filter] [-Leak] [-MultiProcess] [-Map [0,1]] [-PtrInMap 0x...] [-MinMaxMapSize min [max]] [-MinMaxTime min [max]] [-Overlapped] [-Showtotal Total,File,None]" + Environment.NewLine + " [-NewProcess 0/1/-1/-2/2] [-PlainProcessNames] [-CmdLine substring]" + Environment.NewLine; static readonly string ObjectRefHelpString = ObjectRefHelpStringHeader + " -ProcessName/pn xx.exe(pid) Filter for processes which did create the object." + Environment.NewLine + " -RelatedProcess xx.exe(pid) Filter in all events for this process. You can also use a negative filter to exclude specific processes like -pn *creator.exe -realatedprocess !other.exe" + Environment.NewLine + " -MinMaxDuration minS [maxS] Filter for handle lifetime. Never closed handles get a lifetime of 9999 s which serves as magic marker value." + Environment.NewLine + " -MinMaxId min [max] Filter for one or a range of objects. E.g. -MinMaxId 500 600 to filter for all object events with id 500-600. The ids are sorted by object creation time." + Environment.NewLine + + " -MinMaxTime min [max] Remove all events which are not within time filter. Time is specified in ETW session time in seconds." +Environment.NewLine + " -CreateStack filter Keep all object events (create/objRef/duplicate...) where the create stack matches." + Environment.NewLine + " -DestroyStack filter Keep all object events (create/objRef/duplicate...) where the destroy stack matches." + Environment.NewLine + " -StackFilter filter Keep only the events where the stack matches and throw away all other events. To keep all events which have e.g. CreateWebRequest in their stack use -StackFilter *CreateWebRequest*" + Environment.NewLine + @@ -883,6 +884,8 @@ internal enum ZeroTimeModes public KeyValuePair> StackFilter { get; private set; } = new(null, _ => true); public KeyValuePair> TypeFilter { get; private set; } = new(null, _ => true); + public MinMaxRange MinMaxTime { get; private set; } = new(); + // Dump Exception specific Flags public bool FilterExceptions { get; private set; } @@ -1562,6 +1565,12 @@ public override void Parse() Tuple minMaxTimeMsDouble = minTimeMs.GetMinMaxDouble(maxTimeMs, MSUnit); MinMaxTimeMs = new MinMaxRange(minMaxTimeMsDouble.Item1, minMaxTimeMsDouble.Item2); break; + case "-minmaxtime": + string minTime = GetNextNonArg("-minmaxtime"); + string maxTime = GetNextNonArg("-minmaxtime", false); // optional + Tuple minMaxTimeDouble = minTime.GetMinMaxDouble(maxTime, 1); + MinMaxTime = new MinMaxRange(minMaxTimeDouble.Item1, minMaxTimeDouble.Item2); + break; case "-minmaxtotaltimems": string minTotalTimeMs = GetNextNonArg("-minmaxtimems"); string maxTotalTimeMs = GetNextNonArg("-minmaxtimems", false); // optional @@ -2474,6 +2483,7 @@ public override void Run() ViewBaseFilter = ViewBaseFilter, HandleFilter = HandleFilter, MinMaxDurationS = MinMaxDurationS, + MinMaxTime = MinMaxTime, ShowStack = ShowStack, ShowRef = ShowRef, Leak = Leak, diff --git a/ETWAnalyzer/Documentation/DumpObjectRefCommand.md b/ETWAnalyzer/Documentation/DumpObjectRefCommand.md index 4761a8e..cf96667 100644 --- a/ETWAnalyzer/Documentation/DumpObjectRefCommand.md +++ b/ETWAnalyzer/Documentation/DumpObjectRefCommand.md @@ -76,7 +76,9 @@ reason we have 108 Create handle calls which is disturbing because this means th Before diving deeper lets explain what data is shown: -The Id is a unique number which can be used with ```-MinMaxId``` filter to select a specific object instance or a range of them. The kernel object pointer is printed, but +The Id is a unique number which can be used with ```-MinMaxId``` filter to select a specific object instance or a range of them. You can also filter by time with ```-MinMaxTime min max``` which +will throw away all events not passing the time filter. Time is entered in ETW session time in seconds since trace start (use ```-Timefmt s``` to display instead of local time). +The kernel object pointer is printed, but this value can be reused so it is not always unique (can be filtered with ```-Object``` filter). After the kernel pointer the object name (can be filtered with ```-ObjectName``` filter) is printed, if present. Then the object lifetime is printed or 9999s is used to mark objects which were never closed (can be filtered with ```-MinMaxDuration```). Then the individual events grouped by type sorted by time are printed. Each line contains diff --git a/ETWAnalyzer/ETWAnalyzer.csproj b/ETWAnalyzer/ETWAnalyzer.csproj index 75537e0..b3c8fbc 100644 --- a/ETWAnalyzer/ETWAnalyzer.csproj +++ b/ETWAnalyzer/ETWAnalyzer.csproj @@ -22,7 +22,7 @@ True https://github.com/Siemens-Healthineers/ETWAnalyzer ProgramaticAccess.md - 3.0.0.8 + 3.0.0.9 x64 true 1 diff --git a/ETWAnalyzer/EventDump/DumpObjectRef.cs b/ETWAnalyzer/EventDump/DumpObjectRef.cs index 9c51601..e8fa11a 100644 --- a/ETWAnalyzer/EventDump/DumpObjectRef.cs +++ b/ETWAnalyzer/EventDump/DumpObjectRef.cs @@ -75,6 +75,7 @@ public string HandleType public bool Inherit { get; internal set; } public KeyValuePair> TypeFilter { get; internal set; } public SkipTakeRange TopN { get; internal set; } = new(); + public MinMaxRange MinMaxTime { get; internal set; } Dictionary myStackFilterResult = new(); @@ -312,6 +313,16 @@ private List ReadFileData() } } + + if( !MinMaxTime.IsDefault ) + { + ThrowAwayAllEventsNotMatchingTimeFilter(MinMaxTime, handle); + if( handle.IsEmpty ) + { + continue; + } + } + if( StackFilter.Key != null) { ThrowAwayAllEventsWithNotMatchingStacks(stacks, handle); @@ -434,6 +445,7 @@ private List ReadFileData() } + private void HarmonizeFilterSettings() { if (HandleFilter.Key != null || ObjectNameFilter.Key != null) // disable map events when handle specific filters are enabled @@ -583,6 +595,28 @@ private void ThrowAwayAllEventsWithNotMatchingStacks(IStackCollection stacks, Ob handle.FileUnmapEvents = handle.FileUnmapEvents.Where(x => CachingStackFilter(stacks, x.StackIdx)).ToList(); } + private void ThrowAwayAllEventsNotMatchingTimeFilter(MinMaxRange minMaxTime, ObjectRefTrace handle) + { + const double Giga = 1_000_000_000.0d; + if ( handle.CreateEvent != null && !minMaxTime.IsWithin(handle.CreateEvent.TimeNs/Giga) ) + { + handle.CreateEvent = null; + } + + if( handle.DestroyEvent != null && !minMaxTime.IsWithin(handle.DestroyEvent.TimeNs/Giga) ) + { + handle.DestroyEvent = null; + } + + Func timeFilter = x => minMaxTime.IsWithin(x.TimeNs / Giga); + handle.HandleCreateEvents = handle.HandleCreateEvents.Where(timeFilter).Cast().ToList(); + handle.HandleCloseEvents = handle.HandleCloseEvents.Where(timeFilter).Cast().ToList(); + handle.HandleDuplicateEvents = handle.HandleDuplicateEvents.Where(timeFilter).Cast().ToList(); + handle.RefChanges = handle.RefChanges.Where(timeFilter).Cast().ToList(); + handle.FileMapEvents = handle.FileMapEvents.Where(timeFilter).Cast().ToList(); + handle.FileUnmapEvents = handle.FileUnmapEvents.Where(timeFilter).Cast().ToList(); + } + class Totals { public int ObjectCreateCount { get; internal set; } diff --git a/ETWAnalyzer/Extractors/Handle/ObjectRefExtractor.cs b/ETWAnalyzer/Extractors/Handle/ObjectRefExtractor.cs index bc8306a..7ae0b29 100644 --- a/ETWAnalyzer/Extractors/Handle/ObjectRefExtractor.cs +++ b/ETWAnalyzer/Extractors/Handle/ObjectRefExtractor.cs @@ -507,6 +507,10 @@ public override void Extract(ITraceProcessor processor, ETWExtract results) }; OpenHandles.Add(hTrace.ObjectPtr, hTrace); } + else + { + hTrace.Name = dcEnd.Name; // when no handle close handle was called add object name form DCEndEvent + } if( hTrace.Existing == null ) { diff --git a/ETWAnalyzer/Properties/AssemblyInfo.cs b/ETWAnalyzer/Properties/AssemblyInfo.cs index 3f4ab37..38dcb90 100644 --- a/ETWAnalyzer/Properties/AssemblyInfo.cs +++ b/ETWAnalyzer/Properties/AssemblyInfo.cs @@ -42,4 +42,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("3.0.0.8")] +[assembly: AssemblyFileVersion("3.0.0.9")]