private void LookupWarmNGENSymbols() { TraceEventStackSource asTraceEventStackSource = GetTraceEventStackSource(_rawStackSource); if (asTraceEventStackSource == null) { return; } SymbolReaderOptions savedOptions = _symbolReader.Options; try { // NGEN PDBs (even those not yet produced) are considered to be in the cache. _symbolReader.Options = SymbolReaderOptions.CacheOnly; // Resolve all NGEN images. asTraceEventStackSource.LookupWarmSymbols(1, _symbolReader, _rawStackSource, s => s.Name.EndsWith(".ni", StringComparison.OrdinalIgnoreCase)); // Invalidate cached data structures to finish resolving symbols. InvalidateCachedStructures(); } finally { _symbolReader.Options = savedOptions; } }
/// <summary> /// Get the call tree node for the specified symbol. /// </summary> /// <param name="symbolName">The symbol.</param> /// <returns>The call tree node representing the symbol, or null if the symbol is not found.</returns> public CallTreeNodeBase GetCallTreeNode(string symbolName) { string[] symbolParts = symbolName.Split(SymbolSeparator); if (symbolParts.Length != 2) { return(null); } // Try to get the call tree node. CallTreeNodeBase node = FindNodeByName(Regex.Escape(symbolName)); // Check to see if the node matches. if (node.Name.StartsWith(symbolName, StringComparison.OrdinalIgnoreCase)) { return(node); } // Check to see if we should attempt to load symbols. if (_traceLog != null && _symbolReader != null && !_resolvedSymbolModules.Contains(symbolParts[0])) { // Look for an unresolved symbols node for the module. string unresolvedSymbolsNodeName = symbolParts[0] + "!?"; node = FindNodeByName(unresolvedSymbolsNodeName); if (node.Name.Equals(unresolvedSymbolsNodeName, StringComparison.OrdinalIgnoreCase)) { // Symbols haven't been resolved yet. Try to resolve them now. TraceModuleFile moduleFile = _traceLog.ModuleFiles.Where(m => m.Name.Equals(symbolParts[0], StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (moduleFile != null) { // Special handling for NGEN images. if (symbolParts[0].EndsWith(".ni", StringComparison.OrdinalIgnoreCase)) { SymbolReaderOptions options = _symbolReader.Options; try { _symbolReader.Options = SymbolReaderOptions.CacheOnly; _traceLog.CallStacks.CodeAddresses.LookupSymbolsForModule(_symbolReader, moduleFile); } finally { _symbolReader.Options = options; } } else { _traceLog.CallStacks.CodeAddresses.LookupSymbolsForModule(_symbolReader, moduleFile); } InvalidateCachedStructures(); } } // Mark the module as resolved so that we don't try again. _resolvedSymbolModules.Add(symbolParts[0]); // Try to get the call tree node one more time. node = FindNodeByName(Regex.Escape(symbolName)); // Check to see if the node matches. if (node.Name.StartsWith(symbolName, StringComparison.OrdinalIgnoreCase)) { return(node); } } return(null); }
public static SymbolReader GetSymbolReader(string additionalPath, string etlFilePath = null, SymbolReaderOptions symbolFlags = SymbolReaderOptions.None) { string localSymbolPath = @"D:\home\data\DaaS\symbols"; if (!Directory.Exists(@"D:\home\data\DaaS")) { localSymbolPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "symbols"); } SymbolPath symPath = new SymbolPath(string.Format(@"srv*{0}*http://msdl.microsoft.com/download/symbols", localSymbolPath)); if ((symbolFlags & SymbolReaderOptions.CacheOnly) != 0) { symPath = new SymbolPath("SRV*" + symPath.DefaultSymbolCache()); } var assemblyDir = Assembly.GetEntryAssembly().Location; // // This is required if we ever don't end up caching the symbols of // our images on the symbol server. In those cases, the DAAS package // should be updated with the Symbols folder for ngen binaries. // var daasPath = assemblyDir.Substring(0, assemblyDir.IndexOf("bin", StringComparison.InvariantCultureIgnoreCase)); var daasSymbolPath = Path.Combine(daasPath, "Symbols"); if (!Directory.Exists(daasSymbolPath)) { daasSymbolPath = ""; } symPath.Insert(@"srv*d:\NdpCorePdb*"); symPath.Insert(@"srv*D:\home\data\DaaS\symbols*" + daasSymbolPath); string localSymDir = symPath.DefaultSymbolCache(); if (etlFilePath != null) { // Add the directory where the file resides and a 'symbols' subdirectory var filePathDir = Path.GetDirectoryName(etlFilePath); if (filePathDir.Length != 0) { // Then the directory where the .ETL file lives. symPath.Insert(filePathDir); // If there is a 'symbols' directory next to the data file, look for symbols there // as well. Note that we also put copies of any symbols here as well (see below) string potentiallocalSymDir = Path.Combine(filePathDir, "symbols"); if (Directory.Exists(potentiallocalSymDir)) { symPath.Insert(potentiallocalSymDir); symPath.Insert("SRV*" + potentiallocalSymDir); localSymDir = potentiallocalSymDir; } // WPR conventions add any .etl.ngenPDB directory to the path too. has higher priority still. var wprSymDir = etlFilePath + ".NGENPDB"; if (Directory.Exists(wprSymDir)) { symPath.Insert("SRV*" + wprSymDir); } else { // I have now seen both conventions .etl.ngenpdb and .ngenpdb, so look for both. wprSymDir = Path.ChangeExtension(etlFilePath, ".NGENPDB"); if (Directory.Exists(wprSymDir)) { symPath.Insert("SRV*" + wprSymDir); } } // VS uses .NGENPDBS as a convention. wprSymDir = etlFilePath + ".NGENPDBS"; if (Directory.Exists(wprSymDir)) { symPath.Insert("SRV*" + wprSymDir); } if (Directory.Exists(additionalPath)) { symPath.Insert(additionalPath); } } } DaaS.Logger.LogInfo("Symbol reader _NT_SYMBOL_PATH="); foreach (var element in symPath.Elements) { DaaS.Logger.LogInfo($" {element};"); } TextWriter textWriter = null; if (Trace.Listeners["TextWriterTraceListener"] != null) { var textWriterListener = Trace.Listeners["TextWriterTraceListener"] as System.Diagnostics.TextWriterTraceListener; textWriter = textWriterListener.Writer; } else { textWriter = Console.Out; } SymbolReader ret = new SymbolReader(textWriter, symPath.ToString()) { Options = symbolFlags }; ret.SecurityCheck = (pdbFile => true); if (localSymDir != null) { ret.OnSymbolFileFound += (pdbPath, pdbGuid, pdbAge) => CacheInLocalSymDir(localSymDir, pdbPath, pdbGuid, pdbAge, Console.Out); } return(ret); }