static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            Console.Error.WriteLine("Usage: GetCpuSampleDuration.exe <trace.etl> <imageName> <functionName>");
            return;
        }

        string tracePath    = args[0];
        string imageName    = args[1];
        string functionName = args[2];

        Dictionary <string, Duration> matchDurationByCommandLine = new Dictionary <string, Duration>();

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
        {
            IPendingResult <ISymbolDataSource>    pendingSymbolData      = trace.UseSymbols();
            IPendingResult <ICpuSampleDataSource> pendingCpuSamplingData = trace.UseCpuSamplingData();

            trace.Process();

            ISymbolDataSource    symbolData      = pendingSymbolData.Result;
            ICpuSampleDataSource cpuSamplingData = pendingCpuSamplingData.Result;

            symbolData.LoadSymbolsForConsoleAsync(SymCachePath.Automatic, SymbolPath.Automatic).GetAwaiter().GetResult();
            Console.WriteLine();

            IThreadStackPattern pattern = AnalyzerThreadStackPattern.Parse($"{imageName}!{functionName}");

            foreach (ICpuSample sample in cpuSamplingData.Samples)
            {
                if (sample.IsExecutingDeferredProcedureCall == true || sample.IsExecutingInterruptServicingRoutine == true)
                {
                    continue;
                }

                if (sample.Stack != null && sample.Stack.Matches(pattern))
                {
                    string commandLine = sample.Process.CommandLine;

                    if (!matchDurationByCommandLine.ContainsKey(commandLine))
                    {
                        matchDurationByCommandLine.Add(commandLine, Duration.Zero);
                    }

                    matchDurationByCommandLine[commandLine] += sample.Weight;
                }
            }
        }

        foreach (string commandLine in matchDurationByCommandLine.Keys)
        {
            Console.WriteLine($"{commandLine}: {matchDurationByCommandLine[commandLine]}");
        }
    }
    public static int Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: FindZombieProcess.exe <trace.etl>");
            return(1);
        }

        string tracePath = args[0];

        TraceProcessorSettings settings = new TraceProcessorSettings {
            AllowLostEvents = true
        };

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath, settings))
        {
            IPendingResult <IHandleDataSource> pendingHandleData = trace.UseHandles();
            IPendingResult <ISymbolDataSource> pendingSymbolData = trace.UseSymbols();

            trace.Process();

            IHandleDataSource handleData = pendingHandleData.Result;
            ISymbolDataSource symbolData = pendingSymbolData.Result;

            symbolData.LoadSymbolsForConsoleAsync(SymCachePath.Automatic, SymbolPath.Automatic).GetAwaiter().GetResult();

            foreach (IProcessHandle processHandle in handleData.ProcessHandles)
            {
                // Zombie processes are processes which have exited but which still have a running process holding a handle to them
                if (processHandle.Process != null && !processHandle.CloseTime.HasValue &&
                    processHandle.Process.ExitTime.HasValue)
                {
                    string owningProcessName = processHandle.Owner?.ImageName ?? "Unknown";
                    string targetProcessName = processHandle.Process?.ImageName ?? "Unknown";
                    Console.WriteLine($"Owning process: {owningProcessName} has handle to: {targetProcessName}");
                }
            }

            return(0);
        }
    }
示例#3
0
        static void RunWithOptions(Options opts)
        {
            using (ITraceProcessor trace = TraceProcessor.Create(opts.etlFileName))
            {
                IPendingResult <ICpuSampleDataSource> pendingCpuSampleData = trace.UseCpuSamplingData();
                IPendingResult <ISymbolDataSource>    pendingSymbolData    = trace.UseSymbols();

                trace.Process();

                ISymbolDataSource    symbolData    = pendingSymbolData.Result;
                ICpuSampleDataSource cpuSampleData = pendingCpuSampleData.Result;

                var symbolProgress = new Progress <SymbolLoadingProgress>(progress =>
                {
                    Console.Write("\r{0:P} {1} of {2} symbols processed ({3} loaded)",
                                  (double)progress.ImagesProcessed / progress.ImagesTotal,
                                  progress.ImagesProcessed,
                                  progress.ImagesTotal,
                                  progress.ImagesLoaded);
                });
                symbolData.LoadSymbolsAsync(
                    SymCachePath.Automatic, SymbolPath.Automatic, symbolProgress)
                .GetAwaiter().GetResult();
                Console.WriteLine();

                var profileWriter = new ProfileWriter(opts.etlFileName,
                                                      opts.includeInlinedFunctions,
                                                      opts.includeProcessAndThreadIds,
                                                      opts.stripSourceFileNamePrefix);

                var timeStart = opts.timeStart ?? 0;
                var timeEnd   = opts.timeEnd ?? decimal.MaxValue;

                var exportAllProcesses = opts.processFilter == "*";
                var processFilterSet   = new HashSet <string>(
                    opts.processFilter.Trim().Split(",", StringSplitOptions.RemoveEmptyEntries));

                for (int i = 0; i < cpuSampleData.Samples.Count; i++)
                {
                    if (i % 100 == 0)
                    {
                        Console.Write("\r{0:P} {1} of {2} samples processed",
                                      (double)i / cpuSampleData.Samples.Count, i, cpuSampleData.Samples.Count);
                    }

                    var cpuSample = cpuSampleData.Samples[i];

                    if ((cpuSample.IsExecutingDeferredProcedureCall ?? false) ||
                        (cpuSample.IsExecutingInterruptServicingRoutine ?? false))
                    {
                        continue;
                    }

                    if (!exportAllProcesses)
                    {
                        var processImage = cpuSample.Process.Images
                                           .FirstOrDefault(image => image.FileName == cpuSample.Process.ImageName);

                        string imagePath = processImage?.Path ?? cpuSample.Process.ImageName;

                        if (!processFilterSet.Any(filter => imagePath.Contains(filter.Replace("/", "\\"))))
                        {
                            continue;
                        }
                    }

                    var timestamp = cpuSample.Timestamp.RelativeTimestamp.TotalSeconds;
                    if (timestamp < timeStart || timestamp > timeEnd)
                    {
                        continue;
                    }

                    profileWriter.AddSample(cpuSample);
                }
                Console.WriteLine();

                long outputSize = profileWriter.Write(opts.outputFileName);
                Console.WriteLine("Wrote {0:N0} bytes to {1}", outputSize, opts.outputFileName);
            }
        }
示例#4
0
        static int Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.Error.WriteLine("Usage: PotentialDelayLoads.exe <trace.etl>");
                return(1);
            }

            string tracePath = args[0];

            var settings = new TraceProcessorSettings
            {
                AllowLostEvents = true,
            };

            using (ITraceProcessor trace = TraceProcessor.Create(tracePath, settings))
            {
                IPendingResult <IReferenceSetDataSource> pendingReferenceSet  = trace.UseReferenceSetData();
                IPendingResult <IProcessDataSource>      pendingProcesses     = trace.UseProcesses();
                IPendingResult <ISymbolDataSource>       pendingSymbols       = trace.UseSymbols();
                IPendingResult <IImageSectionDataSource> pendingImageSections = trace.UseImageSections();

                trace.Process();

                IProcessDataSource      processData      = pendingProcesses.Result;
                IReferenceSetDataSource referenceSetData = pendingReferenceSet.Result;
                ISymbolDataSource       symbolData       = pendingSymbols.Result;
                IImageSectionDataSource imageSectionData = pendingImageSections.Result;

                symbolData.LoadSymbolsForConsoleAsync(SymCachePath.Automatic, SymbolPath.Automatic).GetAwaiter().GetResult();

                //
                // Create a mapping of all static images loaded into all processes during the course of the trace.
                // This is a mapping of images to a dictionary of [processes, IsPotentialDelayLoadTarget]
                //
                Dictionary <string, Dictionary <string, bool> > potentialDelayLoads = new Dictionary <string, Dictionary <string, bool> >();

                //
                // Keep track of the image data for all of the images we've seen loaded. We use this later to look up
                // section names for the offsets being accessed.
                //
                Dictionary <string, IImage> imageData = new Dictionary <string, IImage>();

                foreach (var proc in processData.Processes)
                {
                    foreach (var image in proc.Images)
                    {
                        string processName = GenerateProcessNameString(proc);
                        if (image.LoadTime != null)
                        {
                            Dictionary <string, bool> processDict;
                            if (!potentialDelayLoads.ContainsKey(image.Path))
                            {
                                processDict = new Dictionary <string, bool>();
                                potentialDelayLoads.Add(image.Path, processDict);
                            }
                            else
                            {
                                processDict = potentialDelayLoads[image.Path];
                            }

                            if (!processDict.ContainsKey(processName))
                            {
                                bool eligibleForDelayLoad = (image.LoadReason == ImageLoadReason.StaticDependency);
                                processDict.Add(processName, eligibleForDelayLoad);
                            }

                            //
                            // Save off whether or not this image is a potential delay load target. We only consider
                            // static dependencies for delay loads.
                            //
                            processDict[processName] = processDict[processName] && (image.LoadReason == ImageLoadReason.StaticDependency);

                            //
                            // Save off a pointer to the image data for this image so we can look up sections later
                            //
                            if (!imageData.ContainsKey(image.Path))
                            {
                                imageData.Add(image.Path, image);
                            }
                        }
                    }
                }

                //
                // Enumerate every page access. We're going to check each one to see if it was a 'code' page being accessed,
                // and if it was we conclude that code from this image was used during the trace by that process. Therefore,
                // it's not something that should be delay loaded.
                //
                foreach (IReferenceSetInterval refSetInterval in referenceSetData.Intervals)
                {
                    foreach (IReferenceSetAccessedPage pageAccess in refSetInterval.PageAccesses)
                    {
                        //
                        // Make sure the page was accessed from the usermode process.
                        //
                        if (pageAccess.ImpactedProcess == null)
                        {
                            continue;
                        }

                        //
                        // Ignore the memory compression process. This is a system service.
                        //
                        if (pageAccess.ImpactedProcess.ImageName.Equals("MemCompression"))
                        {
                            continue;
                        }

                        //
                        // Make sure we have a file path
                        //
                        if (pageAccess?.Page?.Path == null)
                        {
                            continue;
                        }
                        var fileBeingAccessed = pageAccess?.Page?.Path;

                        //
                        // Not all file paths are images (think MFT or data files). Make sure this is in our image
                        // dictionary.
                        //
                        if (!imageData.ContainsKey(pageAccess.Page.Path))
                        {
                            continue;
                        }

                        //
                        // Make sure that this image was listed in the image data
                        //
                        if (!potentialDelayLoads.ContainsKey(fileBeingAccessed))
                        {
                            continue;
                        }

                        //
                        // Grab the image data, and use this to get the info on the page that was being accessed.
                        //
                        var data        = imageData[pageAccess.Page.Path];
                        var sectionName = GetSectionNameFromPage(pageAccess, data, imageSectionData, pageAccess.ImpactedProcess);

                        //
                        // We really only want consider .text pages, as we want to find images where the 'code' is never
                        // used. We have to include "unknown" as well since this is what shows up for images that we
                        // can't find symbols for. This effectively means for images without symbols we consider all pages.
                        //
                        if (!(sectionName.Contains(".text") || sectionName.Contains("Unknown")))
                        {
                            continue;
                        }

                        //
                        // If the loader accessed the page, it's still a potential delay load candidiate.
                        //
                        if (IsLoaderAccessedPage(pageAccess))
                        {
                            continue;
                        }

                        //
                        // A .text page was accessed from somewhere other then the loader. This image isn't
                        // a delay load candidate for this process.
                        //
                        string processName = GenerateProcessNameString(pageAccess.ImpactedProcess);
                        if ((potentialDelayLoads[fileBeingAccessed]).ContainsKey(processName))
                        {
                            if ((potentialDelayLoads[fileBeingAccessed])[processName])
                            {
                                (potentialDelayLoads[fileBeingAccessed])[processName] = false;
                            }
                        }
                        else
                        {
                            potentialDelayLoads[fileBeingAccessed].Add(processName, false);
                        }
                    }
                }

                //
                // Print out all potential delays loads we found. We modify the output format to be in
                // process->image style for easier consumption from the console.
                //
                List <Tuple <string, string> > delayLoads = new List <Tuple <string, string> >();
                foreach (var imagesLoaded in potentialDelayLoads)
                {
                    foreach (var processesDict in imagesLoaded.Value)
                    {
                        if (processesDict.Value == true)
                        {
                            delayLoads.Add(new Tuple <string, string>(processesDict.Key, imagesLoaded.Key));
                        }
                    }
                }
                delayLoads.Sort();
                foreach (var delayload in delayLoads)
                {
                    Console.WriteLine("{0} can delay load {1}", delayload.Item1, delayload.Item2);
                }
            }

            return(0);
        }