예제 #1
0
        /// <summary>
        /// Returns the list of path names to the NGEN pdbs for any NGEN image in 'etlFile' that has
        /// any samples in it.
        /// </summary>
        internal static List <string> GetNGenPdbs(string etlFile, SymbolReader symbolReader, TextWriter log)
        {
            // Generate the NGen images for any NGEN image needing symbolic information.
            var pdbFileList = new List <string>(100);

            foreach (var imageName in ETWTraceEventSource.GetModulesNeedingSymbols(etlFile))
            {
                Debug.Assert(0 <= imageName.IndexOf(".ni.", StringComparison.OrdinalIgnoreCase));
                var pdbName = symbolReader.GenerateNGenSymbolsForModule(imageName);
                if (pdbName != null)
                {
                    pdbFileList.Add(pdbName);
                    log.WriteLine("Found NGEN pdb {0}", pdbName);
                }
            }
            return(pdbFileList);
        }
예제 #2
0
        /// <summary>
        /// Returns the list of path names to the NGEN pdbs for any NGEN image in 'etlFile' that has
        /// any samples in it.
        /// </summary>
        internal static List <string> GetNGenPdbs(string etlFile, SymbolReader symbolReader, TextWriter log)
        {
            // Generate the NGen images for any NGEN image needing symbolic information.
            var pdbFileList = new List <string>(100);

            foreach (var imageName in ETWTraceEventSource.GetModulesNeedingSymbols(etlFile))
            {
                var sw      = Stopwatch.StartNew();
                var pdbName = symbolReader.GenerateNGenSymbolsForModule(imageName);
                if (pdbName != null)
                {
                    pdbFileList.Add(pdbName);
                    log.WriteLine("Found NGEN pdb {0}", pdbName);
                }
                log.WriteLine("NGEN PDB creation for {0} took {1:n2} Sec", imageName, sw.Elapsed.TotalSeconds);
            }
            return(pdbFileList);
        }
예제 #3
0
        /// <summary>
        /// Create an ETWReloggerTraceEventSource that can takes its input from a variety of sources (either a single file,
        /// a set of files, or a real time ETW session (based on 'type'), and can write these events to a new ETW output
        /// file 'outputFileName.
        /// </summary>
        public ETWReloggerTraceEventSource(string fileOrSessionName, TraceEventSourceType type, string outputFileName)
            : base()
        {
            var version = Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor;

            if (version < 62)
            {
                throw new NotSupportedException("System Tracing is only supported on Windows 8 and above.");
            }

            m_relogger = new CTraceRelogger();
            if (type == TraceEventSourceType.FileOnly)
            {
                m_traceHandleForFirstStream = m_relogger.AddLogfileTraceStream(fileOrSessionName, IntPtr.Zero);
            }
            else if (type == TraceEventSourceType.Session)
            {
                m_traceHandleForFirstStream = m_relogger.AddRealtimeTraceStream(fileOrSessionName, IntPtr.Zero);
            }
            else
            {
                Debug.Assert(type == TraceEventSourceType.MergeAll);
                List <string> logFileNames = ETWTraceEventSource.GetMergeAllLogFiles(fileOrSessionName);
                bool          first        = true;
                foreach (var logFileName in logFileNames)
                {
                    var handle = m_relogger.AddLogfileTraceStream(logFileName, IntPtr.Zero);
                    if (first)
                    {
                        m_traceHandleForFirstStream = handle;
                        first = false;
                    }
                }
            }

            m_relogger.SetOutputFilename(outputFileName);
            m_myCallbacks = new ReloggerCallbacks(this);
            m_relogger.RegisterCallback(m_myCallbacks);
        }
예제 #4
0
        /// <summary>
        /// Given an ETL file, returns a list of the full paths to DLLs that were loaded in the trace that need symbolic
        /// information (PDBs) so that the stack traces and CPU samples can be properly resolved.   By default this only
        /// returns NGEN images since these are the ones that need to be resolved and generated at collection time.
        /// </summary>
        public static IEnumerable <string> GetModulesNeedingSymbols(string etlFile, ModuleSymbolOptions options = ModuleSymbolOptions.OnlyNGENImages)
        {
            var images        = new List <ImageData>(300);
            var addressCounts = new Dictionary <Address, int>();

            // Get the name of all DLLS (in the file, and the set of all address-process pairs in the file.
            using (var source = new ETWTraceEventSource(etlFile))
            {
                source.Kernel.ImageGroup += delegate(ImageLoadTraceData data)
                {
                    var fileName = data.FileName;
                    if (fileName.IndexOf(".ni.", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        // READY_TO_RUN support generate PDBs for ready-to-run images.
                        // TODO can rip this out when we don't package ready-to-run images
                        var windowsIdx = fileName.IndexOf(@"\windows\", StringComparison.OrdinalIgnoreCase);
                        if (0 <= windowsIdx && windowsIdx <= 2)
                        {
                            return;
                        }
                        if (!File.Exists(fileName))
                        {
                            return;
                        }
                        try
                        {
                            using (var peFile = new PEFile.PEFile(fileName))
                            {
                                if (!peFile.IsManagedReadyToRun)
                                {
                                    return;
                                }
                            }
                        }
                        catch { return; }
                    }

                    var processId = data.ProcessID;
                    images.Add(new ImageData(processId, fileName, data.ImageBase, data.ImageSize));
                };

                source.Kernel.StackWalkStack += delegate(StackWalkStackTraceData data)
                {
                    if (data.ProcessID == 0)
                    {
                        return;
                    }
                    var processId = data.ProcessID;
                    for (int i = 0; i < data.FrameCount; i++)
                    {
                        var address = (data.InstructionPointer(i) & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF));
                        addressCounts[address] = 1;
                    }
                };

                source.Clr.ClrStackWalk += delegate(ClrStackWalkTraceData data)
                {
                    var processId = data.ProcessID;
                    for (int i = 0; i < data.FrameCount; i++)
                    {
                        var address = (data.InstructionPointer(i) & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF));
                        addressCounts[address] = 1;
                    }
                };

                source.Kernel.PerfInfoSample += delegate(SampledProfileTraceData data)
                {
                    if (data.ProcessID == 0)
                    {
                        return;
                    }
                    var processId = data.ProcessID;
                    var address   = (data.InstructionPointer & 0xFFFFFFFFFFFF0000L) + ((Address)(processId & 0xFFFF));
                    addressCounts[address] = 1;
                };

                source.Process();
            }

            // imageNames is a set of names that we want symbols for.
            var imageNames = new Dictionary <string, string>(100);

            foreach (var image in images)
            {
                if (!imageNames.ContainsKey(image.DllName))
                {
                    for (uint offset = 0; offset < (uint)image.Size; offset += 0x10000)
                    {
                        var key = image.BaseAddress + offset + (uint)(image.ProcessID & 0xFFFF);
                        if (addressCounts.ContainsKey(key))
                        {
                            imageNames[image.DllName] = image.DllName;
                            break;
                        }
                    }
                }
            }

            // Find the PDBS for the given images.
            return(new List <string>(imageNames.Keys));
        }