public EtwDeserializer(string fileName) { this.MethodILNativeMap = new Dictionary <ulong, ManagedMethodILToNativeMapping>(); this.ImageToDebugInfoMap = new Dictionary <ProcessImageId, DbgId>(); this.ManagedModuleInfoMap = new Dictionary <ProcessModuleId, ManagedModuleInfo>(); this.ImageLoadMap = new Dictionary <uint, List <ImageInfo> >(); this.MethodLoadMap = new Dictionary <uint, List <ManagedMethodInfo> >(); this.Stacks = new List <StackInfo>(); this.Frames = new List <Frame>(); this.Samples = new List <StackSourceSample>(); this.PseudoFrames = new List <string>(); this.EventStacks = new Dictionary <int, StackEventType>(); this.ProcessIdToNameMap = new Dictionary <uint, string>(); var fileSessions = new EVENT_TRACE_LOGFILEW[1]; var handles = new ulong[1]; unsafe { fileSessions[0] = new EVENT_TRACE_LOGFILEW { LogFileName = fileName, EventRecordCallback = this.Deserialize, BufferCallback = this.BufferCallback, LogFileMode = Etw.PROCESS_TRACE_MODE_EVENT_RECORD | Etw.PROCESS_TRACE_MODE_RAW_TIMESTAMP }; } handles[0] = Etw.OpenTrace(ref fileSessions[0]); unchecked { if (handles[0] == (ulong)~0) { switch (Marshal.GetLastWin32Error()) { case 0x57: throw new Exception($"ERROR: For file: {fileName} Windows returned 0x57 -- The Logfile parameter is NULL."); case 0xA1: throw new Exception($"ERROR: For file: {fileName} Windows returned 0xA1 -- The specified path is invalid."); case 0x5: throw new Exception($"ERROR: For file: {fileName} Windows returned 0x5 -- Access is denied."); default: throw new Exception($"ERROR: For file: {fileName} Windows returned an unknown error."); } } } this.perfFreq = fileSessions[0].LogfileHeader.PerfFreq; this.pidEipToFrameIndexTable = new Dictionary <Frame, int>(); this.stackIndexTable = new Dictionary <StackInfo, int>(); this.threadPseudoFrameMappingTable = new Dictionary <uint, int>(); this.processPseudoFrameMappingTable = new Dictionary <uint, int>(); this.callerIdsNeedingUpdates = new HashSet <int>(); this.samplesTimeStampMap = new Dictionary <CorrelatedStackEvent, int>(); this.etwProviderInfoMap = new Dictionary <EtwProviderInfo, StackEventType>(); EtwDeserializerEventSource.Logger.BeginProcessTrace(); Etw.ProcessTrace(handles, (uint)handles.Length, IntPtr.Zero, IntPtr.Zero); EtwDeserializerEventSource.Logger.EndProcessTrace(); Etw.CloseTrace(handles[0]); unsafe { fileSessions[0] = new EVENT_TRACE_LOGFILEW { LogFileName = fileName, EventRecordCallback = this.Deserialize2ndPass, BufferCallback = this.BufferCallback, LogFileMode = Etw.PROCESS_TRACE_MODE_EVENT_RECORD | Etw.PROCESS_TRACE_MODE_RAW_TIMESTAMP }; } handles[0] = Etw.OpenTrace(ref fileSessions[0]); EtwDeserializerEventSource.Logger.BeginProcessTrace(); Etw.ProcessTrace(handles, (uint)handles.Length, IntPtr.Zero, IntPtr.Zero); EtwDeserializerEventSource.Logger.EndProcessTrace(); Etw.CloseTrace(handles[0]); GC.KeepAlive(fileSessions); EtwDeserializerEventSource.Logger.BeginMapProcessIdToNames(); foreach (var pseudoFrameInfo in this.processPseudoFrameMappingTable) { this.PseudoFrames[pseudoFrameInfo.Value] = this.ProcessIdToNameMap.TryGetValue(pseudoFrameInfo.Key, out var processName) ? $"Process {processName} ({pseudoFrameInfo.Key})" : $"Process ({pseudoFrameInfo.Key})"; } foreach (var pseudoFrameInfo in this.threadPseudoFrameMappingTable) { this.PseudoFrames[pseudoFrameInfo.Value] = $"Thread ({pseudoFrameInfo.Key})"; } EtwDeserializerEventSource.Logger.EndMapProcessIdToNames(); this.pidEipToFrameIndexTable = null; this.stackIndexTable = null; this.threadPseudoFrameMappingTable = null; this.processPseudoFrameMappingTable = null; this.samplesTimeStampMap = null; this.etwProviderInfoMap = null; this.PseudoFramesStartOffset = this.Frames.Count; EtwDeserializerEventSource.Logger.BeginFixupCallerIndices(); foreach (var callerId in this.callerIdsNeedingUpdates) { var frameIndex = this.Frames.Count; var stack = this.Stacks[callerId]; this.Stacks[callerId] = new StackInfo(stack.CallerID, frameIndex); this.Frames.Add(new Frame((uint)stack.FrameID, 0)); // hack alert: we reuse the pid field as a pseudo frame id } this.callerIdsNeedingUpdates = null; EtwDeserializerEventSource.Logger.EndFixupCallerIndices(); EtwDeserializerEventSource.Logger.BeginSortImages(); foreach (var elem in this.ImageLoadMap.Values) { elem.Sort(); } EtwDeserializerEventSource.Logger.EndSortImages(); EtwDeserializerEventSource.Logger.BeginSortMethods(); foreach (var elem in this.MethodLoadMap.Values) { elem.Sort(); } EtwDeserializerEventSource.Logger.EndSortMethods(); EtwDeserializerEventSource.Logger.BeginPopulateInstructionPointers(); var frames = this.Frames; foreach (var frame in frames) { if (this.ImageLoadMap.TryGetValue(frame.ProcessId, out var imageList)) { var eip = frame.InstructionPointer; var result = RangeBinarySearch(imageList, eip); if (result >= 0) { imageList[result].InstructionPointers.Add(eip); } } } /* special process */ var pidZeroList = this.ImageLoadMap[0]; foreach (var frame in frames) { var eip = frame.InstructionPointer; var result = RangeBinarySearch(pidZeroList, eip); if (result >= 0) { // add eips encountered in other processes to this one. // we do this so when we lookup pdbs we have all eips // for these images pidZeroList[result].InstructionPointers.Add(eip); } } EtwDeserializerEventSource.Logger.EndPopulateInstructionPointers(); }
internal static extern UInt64 OpenTrace([In][Out] ref EVENT_TRACE_LOGFILEW Logfile);