コード例 #1
0
        private static int Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.Error.WriteLine("Usage CheckForAppCrash <trace.etl>");
                return(-1);
            }

            string tracePath = args[0];

            using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
            {
                IPendingResult <IProcessDataSource> pendingProcesses = trace.UseProcesses();

                trace.Process();

                IProcessDataSource processData = pendingProcesses.Result;

                foreach (IProcess process in processData.Processes)
                {
                    if (string.Equals("werfault.exe", process.ImageName, StringComparison.OrdinalIgnoreCase))
                    {
                        return(1);
                    }
                }
            }

            return(0);
        }
コード例 #2
0
        protected void CheckLocationSettings()
        {
            IPendingResult result = LocationServices.SettingsApi.CheckLocationSettings(
                mGoogleApiClient, mLocationSettingsRequest);

            result.SetResultCallback(this);
        }
コード例 #3
0
        private static void Process(string path)
        {
            try
            {
                if (string.IsNullOrEmpty(path))
                {
                    Console.Error.WriteLine("ETL file location not provided...");
                    return;
                }

                using (ITraceProcessor trace = TraceProcessor.Create(path))
                {
                    IPendingResult <IProcessDataSource> pendingProcessData = trace.UseProcesses();

                    trace.Process();

                    IProcessDataSource processData = pendingProcessData.Result;

                    foreach (IProcess process in processData.Processes)
                    {
                        log.Info(process.CommandLine);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occured while processing. {ex}");
                throw ex;
            }
        }
コード例 #4
0
    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]}");
        }
    }
コード例 #5
0
        private static IReadOnlyList <string> GetServices(string tracePath)
        {
            using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
            {
                IPendingResult <IServiceDataSource> pendingServices = trace.UseServices();

                trace.Process();

                IServiceDataSource serviceData = pendingServices.Result;

                return(serviceData.Services.Select(s => Cleanup(s.Name)).ToArray());
            }
        }
コード例 #6
0
    static void Run(string tracePath)
    {
        using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
        {
            IPendingResult <IProcessDataSource> pendingProcessData = trace.UseProcesses();

            trace.Process();

            IProcessDataSource processData = pendingProcessData.Result;

            Console.WriteLine(processData.Processes.Count);
        }
    }
コード例 #7
0
ファイル: TraceData.cs プロジェクト: Donpedro13/etwprof
        private void GatherTraceData()
        {
            using (ITraceProcessor trace = TraceProcessor.Create(EtlPath))
            {
                IPendingResult <IProcessDataSource>       pendingProcessData       = trace.UseProcesses();
                IPendingResult <IThreadDataSource>        pendingThreadData        = trace.UseThreads();
                IPendingResult <ICpuSampleDataSource>     pendingCpuSampleData     = trace.UseCpuSamplingData();
                IPendingResult <ICpuSchedulingDataSource> pendingCpuSchedulingData = trace.UseCpuSchedulingData();

                trace.Process();

                GatherProcessData(pendingProcessData.Result);
                GatherThreadData(pendingThreadData.Result);
                GatherCpuSampleData(pendingCpuSampleData.Result);
                GatherCpuSchedulingData(pendingCpuSchedulingData.Result);
            }
        }
コード例 #8
0
ファイル: Program.cs プロジェクト: madhub/DotNetSamples
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.Error.WriteLine("Usage: <trace.etl>");
                return;
            }

            using (ITraceProcessor trace = TraceProcessor.Create(args[0]))
            {
                IPendingResult <IProcessDataSource> pendingProcessData = trace.UseProcesses();
                trace.Process();
                IProcessDataSource processData = pendingProcessData.Result;

                foreach (IProcess process in processData.Processes)
                {
                    Console.WriteLine(process.CommandLine);
                }
            }
        }
コード例 #9
0
    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);
        }
    }
コード例 #10
0
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: ListImages.exe <trace.etl>");
            return;
        }

        string tracePath = args[0];

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
        {
            IPendingResult <IProcessDataSource> pendingProcessData = trace.UseProcesses();

            trace.Process();

            IProcessDataSource processData = pendingProcessData.Result;

            foreach (IProcess process in processData.Processes)
            {
                foreach (IImage image in process.Images)
                {
                    DataSize    ImageSize       = image.Size;
                    long        TimeDataStamp   = image.Timestamp;
                    string      OrigFileName    = image.OriginalFileName;
                    string      FileDescription = image.FileDescription;
                    string      FileVersion     = image.FileVersion;
                    Version     BinFileVersion  = image.FileVersionNumber;
                    CultureInfo VerLanguage     = image.Locale;
                    string      ProductName     = image.ProductName;
                    string      CompanyName     = image.CompanyName;
                    string      ProductVersion  = image.ProductVersion;
                    string      FileId          = image.CompatibilityFileId;
                    string      ProgramId       = image.CompatibilityProgramId;
                }
            }
        }
    }
コード例 #11
0
        private static IReadOnlyDictionary <PageKey, uint> GetResidentSetPageCounts(string tracePath,
                                                                                    Timestamp startTime, Timestamp stopTime)
        {
            using (ITraceProcessor trace = TraceProcessor.Create(tracePath))
            {
                IPendingResult <IResidentSetDataSource> pendingResidentSet = trace.UseResidentSetData();

                trace.Process();

                IResidentSetDataSource residentSetData = pendingResidentSet.Result;

                Dictionary <PageKey, uint> pageCounts = new Dictionary <PageKey, uint>();

                foreach (IResidentSetSnapshot snapshot in residentSetData.Snapshots)
                {
                    if (snapshot.Timestamp < startTime || snapshot.Timestamp > stopTime)
                    {
                        continue;
                    }

                    foreach (IResidentSetPage page in snapshot.Pages)
                    {
                        PageKey key = new PageKey(snapshot.Timestamp, page.MemoryManagerListType, page.Priority);

                        if (!pageCounts.ContainsKey(key))
                        {
                            pageCounts.Add(key, 0);
                        }

                        ++pageCounts[key];
                    }
                }

                return(pageCounts);
            }
        }
コード例 #12
0
    // Scan through a trace and print a summary of the Chrome processes, optionally with
    // CPU Usage details for Chrome and other key processes.
    static void ProcessTrace(ITraceProcessor trace, bool showCPUUsage)
    {
        var pendingProcessData = trace.UseProcesses();
        // Only request CPU scheduling data when it is actually needed, to avoid
        // unecessary trace processing costs. Unfortunately this means that the
        // scheduling data sources can't be declared with 'var'.
        IPendingResult <ICpuSchedulingDataSource> pendingSchedulingData = null;

        if (showCPUUsage)
        {
            pendingSchedulingData = trace.UseCpuSchedulingData();
        }

        trace.Process();

        ICpuSchedulingDataSource schedulingData = null;

        if (showCPUUsage)
        {
            schedulingData = pendingSchedulingData.Result;
        }

        // Get a List<ProcessSummary> of all Chrome processes.
        var processSummaries = GetChromePaths(pendingProcessData.Result);

        // Group all of the chrome.exe processes by browser Pid, then by type.
        // pathByBrowserPid just maps from the browser Pid to the disk path to
        // chrome.exe
        var pathByBrowserPid = new Dictionary <int, string>();

        // processesByBrowserPid is a dictionary that is indexed by the browser Pid.
        // It contains a dictionary that is indexed by process type with each
        // entry's payload being a list of Pids (for example, a list of renderer
        // processes).
        var processesByBrowserPid = new Dictionary <int, Dictionary <string, List <int> > >();

        // parentPids is a dictionary that maps from Pids to parent Pids.
        var parentPids = new Dictionary <int, int>();

        // Dictionary of Pids and their types.
        var typesByPid = new Dictionary <int, string>();

        // Find the space-terminated word after 'type='.
        // Mark the first .* as lazy/ungreedy/reluctant so that if there are multiple
        // --type options (such as with the V8 Proxy Resolver utility process) the
        // first one will win. Or, at least, that's what the comments in the Python
        // version of this said.
        var r = new Regex(@".*? --type=(?<type>[^ ]*) .*");

        foreach (var entry in processSummaries)
        {
            var process = entry.Key;
            var exePath = entry.Value;
            if (process.ImageName == "chrome.exe")
            {
                int pid = process.Id;
                parentPids[pid] = process.ParentId;

                // Look for the process type on the command-line in the
                // --type= option. If no type is found then assume it is the
                // browser process. I could have looked for chrome.dll, but
                // that may fail in the future. I could have looked for a chrome
                // process whose parent is not chrome, but I didn't. There are
                // many ways to do this.
                string type;
                int    browserPid;
                var    match = r.Match(process.CommandLine);
                if (match.Success)
                {
                    type = match.Groups["type"].ToString();
                    if (type == "crashpad-handler")
                    {
                        type = "crashpad"; // Shorten the tag for better formatting
                    }
                    if (type == "renderer" && process.CommandLine.Contains(" --extension-process "))
                    {
                        // Extension processes are renderers with --extension-process on the command line.
                        type = "extension";
                    }
                    browserPid = process.ParentId;
                }
                else
                {
                    type       = "browser";
                    browserPid = pid;
                    pathByBrowserPid[browserPid] = exePath;
                }

                typesByPid[pid] = type;

                // Retrieve or create the list of processes associated with this
                // browser (parent) pid.
                // This involves a lot of redundant dictionary lookups, but it is
                // the cleanest way to do it.
                if (!processesByBrowserPid.ContainsKey(browserPid))
                {
                    processesByBrowserPid[browserPid] = new Dictionary <string, List <int> >();
                }
                if (!processesByBrowserPid[browserPid].ContainsKey(type))
                {
                    processesByBrowserPid[browserPid][type] = new List <int>();
                }
                var pidList = processesByBrowserPid[browserPid][type];
                pidList.Add(pid);
            }
        }

        // Clean up the data, because process trees are never simple.
        // Iterate through a copy of the keys so that we can modify the dictionary.
        foreach (var browserPid in new List <int>(processesByBrowserPid.Keys))
        {
            var childPids = processesByBrowserPid[browserPid];
            if (childPids.Count == 1)
            {
                // Linq magic to get the one-and-only key.
                string childType = childPids.Keys.First();
                string destType  = null;

                // In many cases there are two crash-handler processes and one is the
                // parent of the other. This seems to be related to --monitor-self.
                // This script will initially report the parent crashpad process as being a
                // browser process, leaving the child orphaned. This fixes that up by
                // looking for singleton crashpad browsers and then finding their real
                // crashpad parent. This will then cause two crashpad processes to be
                // listed, which is correct.
                if (childType == "crashpad")
                {
                    destType = childType;
                }

                // Also look for entries with parents in the list and no children. These
                // represent child processes whose --type= option was too far along in the
                // command line for ETW's 512-character capture to get. See crbug.com/614502
                // for how this happened.
                // Checking that there is only one entry (itself) in the list is important
                // to avoid problems caused by Pid reuse that could cause one browser process
                // to appear to be another browser process' parent.
                else if (childType == "browser")
                {
                    destType = "gpu???";
                }

                // The browserPid *should* always be present, but in a large enough corpus
                // of traces, all bets are off. This assumption failed in a 20-hour heap
                // snapshot trace.
                if (parentPids.ContainsKey(browserPid))
                {
                    // The childPids["browser"] entry needs to be appended to its
                    // parent/grandparent process since that is its browser process.
                    int parentPid = parentPids[browserPid];
                    // Create the destination type if necessary (needed for gpu???,
                    // not needed for crashpad). Handle missing data.
                    if (processesByBrowserPid.ContainsKey(parentPid))
                    {
                        if (!processesByBrowserPid[parentPid].ContainsKey(destType))
                        {
                            processesByBrowserPid[parentPid][destType] = new List <int>();
                        }
                        processesByBrowserPid[parentPid][destType].Add(childPids[childType][0]);

                        // Remove the fake 'browser' entry so that we don't try to print it.
                        processesByBrowserPid.Remove(browserPid);
                    }
                }
            }
        }

        // Map from PID to CPUUsageDetails.
        var execTimes = new Dictionary <int, CPUUsageDetails>();

        if (showCPUUsage)
        {
            var names = new string[] { "chrome.exe", "dwm.exe", "audiodg.exe", "System", "MsMpEng.exe", "software_reporter_tool.exe" };
            // Scan through the context-switch data to build up how much time
            // was spent by interesting process.
            foreach (var slice in schedulingData.CpuTimeSlices)
            {
                // Yep, this happens.
                if (slice.Process == null)
                {
                    continue;
                }
                // Ignore non-interesting names. Only accumulate for chrome.exe and
                // processes that are known to be related or interesting.
                // An existence check in an array is O(n) but because the array is
                // short this is probably faster than using a dictionary.
                if (!names.Contains(slice.Process.ImageName))
                {
                    continue;
                }
                execTimes.TryGetValue(slice.Process.Id, out CPUUsageDetails last);
                last.imageName              = slice.Process.ImageName;
                last.ns                    += slice.Duration.Nanoseconds;
                last.contextSwitches       += 1;
                execTimes[slice.Process.Id] = last;
            }

            foreach (var times in execTimes)
            {
                CPUUsageDetails details = times.Value;
                // Print details about other interesting processes:
                if (details.imageName != "chrome.exe")
                {
                    Console.WriteLine("{0,11} - {1,6} context switches, {2,8:0.00} ms CPU", details.imageName, details.contextSwitches, details.ns / 1e6);
                }
            }
            Console.WriteLine();
        }

        if (processesByBrowserPid.Count > 0)
        {
            Console.WriteLine("Chrome PIDs by process type:");
        }
        else
        {
            Console.WriteLine("No Chrome processes found.");
        }
        var browserPids = new List <int>(processesByBrowserPid.Keys);

        browserPids.Sort();
        foreach (var browserPid in browserPids)
        {
            // |processes| is a Dictionary<type, List<pid>>
            var processes = processesByBrowserPid[browserPid];

            // Total up how many processes there are in this instance.
            var detailsByType = new Dictionary <string, CPUUsageDetails>();

            int totalProcesses = 0;
            var detailsTotal   = new CPUUsageDetails();
            foreach (var type in processes)
            {
                totalProcesses += type.Value.Count;
                if (showCPUUsage)
                {
                    var detailsSubTotal = new CPUUsageDetails();
                    foreach (int pid in type.Value)
                    {
                        execTimes.TryGetValue(pid, out CPUUsageDetails details);
                        detailsTotal.ns += details.ns;
                        detailsTotal.contextSwitches += details.contextSwitches;

                        detailsSubTotal.ns += details.ns;
                        detailsSubTotal.contextSwitches += details.contextSwitches;
                    }

                    detailsByType[type.Key] = detailsSubTotal;
                }
            }

            // Print the browser path.
            if (showCPUUsage)
            {
                Console.WriteLine("{0} ({1}) - {2} context switches, {3,8:0.00} ms CPU, {4} processes",
                                  pathByBrowserPid[browserPid], browserPid, detailsTotal.contextSwitches,
                                  detailsTotal.ns / 1e6, totalProcesses);
            }
            else
            {
                // See earlier note about how the browserPid may be missing.
                string browserPath = "Unknown parent";
                if (pathByBrowserPid.ContainsKey(browserPid))
                {
                    browserPath = pathByBrowserPid[browserPid];
                }
                Console.WriteLine("{0} ({1}) - {2} processes", browserPath, browserPid, totalProcesses);
            }

            // Sort the types alphabetically for consistent printing.
            var types = new List <KeyValuePair <string, List <int> > >(processes);
            types.Sort((x, y) => x.Key.CompareTo(y.Key));

            // Print all of the child processes, grouped by type.
            foreach (var type in types)
            {
                // |type| contains type and List<pid>
                // TODO: change this to ,12 for ppapi-broker
                if (showCPUUsage)
                {
                    CPUUsageDetails detailsSum = detailsByType[type.Key];
                    Console.Write("    {0,-11} : total - {1,6} context switches, {2,8:0.00} ms CPU", type.Key, detailsSum.contextSwitches, detailsSum.ns / 1e6);
                }
                else
                {
                    Console.Write("    {0,-11} : ", type.Key);
                }
                type.Value.Sort();
                foreach (var pid in type.Value)
                {
                    if (showCPUUsage)
                    {
                        Console.Write("\n        ");
                        execTimes.TryGetValue(pid, out CPUUsageDetails details);
                        if (details.contextSwitches > 0)
                        {
                            Console.Write("{0,5} - {1,6} context switches, {2,8:0.00} ms CPU", pid, details.contextSwitches, details.ns / 1e6);
                        }
                        else
                        {
                            Console.Write("{0,5}", pid);
                        }
                    }
                    else
                    {
                        Console.Write("{0} ", pid);
                    }
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
コード例 #13
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);
            }
        }
コード例 #14
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);
        }
コード例 #15
0
    public static int Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: CyclesPerInstruction.exe <trace.etl>");
            return(1);
        }

        string tracePath = args[0];

        TraceProcessorSettings settings = new TraceProcessorSettings {
            AllowLostEvents = true
        };

        using (ITraceProcessor trace = TraceProcessor.Create(tracePath, settings))
        {
            IPendingResult <IProcessorCounterDataSource> pendingCounterData = trace.UseProcessorCounters();

            trace.Process();

            IProcessorCounterDataSource counterData = pendingCounterData.Result;

            if (!counterData.HasCycleCount)
            {
                Console.Error.WriteLine("Trace does not contain cycle count data.");
                return(2);
            }

            if (!counterData.HasInstructionCount)
            {
                Console.Error.WriteLine("Trace does not contain instruction count data.");
                return(2);
            }

            Dictionary <string, ulong> cyclesByProcess       = new Dictionary <string, ulong>();
            Dictionary <string, ulong> instructionsByProcess = new Dictionary <string, ulong>();

            foreach (IProcessorCounterContextSwitchDelta delta in counterData.ContextSwitchCounterDeltas)
            {
                string processName = delta.Thread?.Process?.ImageName ?? "Unknown";

                if (!cyclesByProcess.ContainsKey(processName))
                {
                    cyclesByProcess.Add(processName, 0);
                    instructionsByProcess.Add(processName, 0);
                }

                cyclesByProcess[processName]       += delta.CycleCount.Value;
                instructionsByProcess[processName] += delta.InstructionCount.Value;
            }

            foreach (string processName in cyclesByProcess.Keys.OrderBy(p => p, StringComparer.OrdinalIgnoreCase))
            {
                ulong   cycles               = cyclesByProcess[processName];
                ulong   instructions         = instructionsByProcess[processName];
                decimal cyclesPerInstruction = ((decimal)cycles) / instructions;
                Console.WriteLine($"{processName}: Cycles: {cycles}; Instructions: {instructions}; " +
                                  $"CPI: {cyclesPerInstruction:0.####}");
            }

            return(0);
        }
    }
コード例 #16
0
    public static int Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: OutstandingHandleCountByProcess.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();

            trace.Process();

            IHandleDataSource handleData = pendingHandleData.Result;
            // Dictionary Key is Owning Process Name
            // Dictionary Value is a struct containing outstanding handle counts by type (Process Handles & Other Handles)
            Dictionary <string, HandleCounts> outstandingHandleCounts = new Dictionary <string, HandleCounts>();

            foreach (IProcessHandle processHandle in handleData.ProcessHandles)
            {
                if (!processHandle.CloseTime.HasValue)
                {
                    string owningProcessName = processHandle.Owner?.ImageName ?? "Unknown";

                    if (outstandingHandleCounts.ContainsKey(owningProcessName))
                    {
                        HandleCounts handleCounts = outstandingHandleCounts[owningProcessName];
                        ++handleCounts.ProcessHandleCount;
                        outstandingHandleCounts[owningProcessName] = handleCounts;
                    }
                    else
                    {
                        outstandingHandleCounts[owningProcessName] = new HandleCounts(1, 0);
                    }
                }
            }

            foreach (IHandle otherHandle in handleData.OtherHandles)
            {
                if (!otherHandle.CloseTime.HasValue)
                {
                    string owningProcessName = otherHandle.Owner?.ImageName ?? "Unknown";

                    if (outstandingHandleCounts.ContainsKey(owningProcessName))
                    {
                        HandleCounts handleCounts = outstandingHandleCounts[owningProcessName];
                        ++handleCounts.OtherHandleCount;
                        outstandingHandleCounts[owningProcessName] = handleCounts;
                    }
                    else
                    {
                        outstandingHandleCounts[owningProcessName] = new HandleCounts(0, 1);
                    }
                }
            }

            foreach (string process in outstandingHandleCounts.Keys)
            {
                int openProcessHandleCount = outstandingHandleCounts[process].ProcessHandleCount;
                int openOtherHandleCount   = outstandingHandleCounts[process].OtherHandleCount;
                Console.WriteLine($"Owning process: {process}");
                Console.WriteLine($"\t{openProcessHandleCount} outstanding Process Handles" +
                                  $"\t{openOtherHandleCount} outstanding Other Handles");
            }

            return(0);
        }
    }