public AllocationTickMemoryProfiler(TraceEventSession session, int pid, ProcessAllocationInfo allocations, bool verbose = false) { if (session == null) { throw new NullReferenceException(nameof(session)); } _session = session; if (allocations == null) { throw new NullReferenceException(nameof(allocations)); } _allocations = allocations; _pid = pid; _verbose = verbose; _symbolLookupMessages = new StringWriter(); // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath); _symbolReader = new SymbolReader(_symbolLookupMessages, symbolPath.ToString()); // By default the symbol reader will NOT read PDBs from 'unsafe' locations (like next to the EXE) // because hackers might make malicious PDBs. If you wish ignore this threat, you can override this // check to always return 'true' for checking that a PDB is 'safe'. _symbolReader.SecurityCheck = (path => true); }
private void AddMSSymbolsClicked(object sender, RoutedEventArgs e) { var symPath = new SymbolPath(GetValue()); symPath.Add("SRV*http://msdl.microsoft.com/download/symbols"); SymbolPathTextBox.Text = symPath.InsureHasCache(symPath.DefaultSymbolCache()).CacheFirst().ToString(); GetValue(); }
public CpuSampleProfilerBase() { _symbolLookupMessages = new StringWriter(); // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath); _symbolReader = new SymbolReader(_symbolLookupMessages, symbolPath.ToString()); // By default the symbol reader will NOT read PDBs from 'unsafe' locations (like next to the EXE) // because hackers might make malicious PDBs. If you wish ignore this threat, you can override this // check to always return 'true' for checking that a PDB is 'safe'. _symbolReader.SecurityCheck = (path => true); }
protected SymbolBuilderBase(SymbolPath path, ISymbol symbol, Location location) { Path = path ?? throw new ArgumentNullException(nameof(path)); Symbol = symbol ?? throw new ArgumentNullException(nameof(symbol)); Location = location ?? throw new ArgumentNullException(nameof(location)); }
public static void Run() { var monitoringTimeSec = 10; Out.WriteLine("******************** RealTimeTraceLog DEMO (win8) ********************"); Out.WriteLine("This program Shows how to use the real-time support in TraceLog"); Out.WriteLine("We do this by showing how to monitor exceptions in real time "); Out.WriteLine(); Out.WriteLine("This code depends on a Feature of Windows 8.1 (combined user and kernel sessions)"); Out.WriteLine(); Out.WriteLine("Note that this support is currently experimental and subject to change"); Out.WriteLine(); Out.WriteLine("Monitoring .NET Module load and Exception events (with stacks)."); Out.WriteLine("Run some managed code (ideally that has exceptions) while the monitor is running."); Out.WriteLine(); if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62) { Out.WriteLine("This demo only works on Win8 / Win 2012 an above)"); return; } TraceEventSession session = null; // Set up Ctrl-C to stop both user mode and kernel mode sessions Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) => { if (session != null) { session.Dispose(); } cancelArgs.Cancel = true; }; // Cause an exception to be thrown a few seconds in (so we have something interesting to look at) var exceptionGeneationTask = Task.Factory.StartNew(delegate { Thread.Sleep(3000); ThrowException(); }); Timer timer = null; // Create the new session to receive the events. // Because we are on Win 8 this single session can handle both kernel and non-kernel providers. using (session = new TraceEventSession("TraceLogSession")) { // Enable the events we care about for the kernel // For this instant the session will buffer any incoming events. // Enabling kernel events must be done before anything else. // This will fail on Win7. // // Note that if you turn on the KernelTraceEventParser.Keywords.Profile, you can also get stacks for CPU sampling // (every millisecond). (You can use the traceLogSource.Kernel.PerfInfoSample callback). Out.WriteLine("Enabling Image load, Process and Thread events. These are needed to look up native method names."); session.EnableKernelProvider( // KernelTraceEventParser.Keywords.Profile | // If you want CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want context switch events // KernelTraceEventParser.Keywords.Thread | // If you want context switch events you also need thread start events. KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process, /****** The second parameter indicates which kernel events should have stacks *****/ // KernelTraceEventParser.Keywords.ImageLoad | // If you want Stacks image load (load library) events // KernelTraceEventParser.Keywords.Profile | // If you want Stacks for CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want Stacks for context switch events KernelTraceEventParser.Keywords.None ); Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)"); // We are monitoring exception events (with stacks) and module load events (with stacks) session.EnableProvider( ClrTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)(ClrTraceEventParser.Keywords.Jit | // Turning on JIT events is necessary to resolve JIT compiled code ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // You must include loader events as well to resolve JIT compiled code. ClrTraceEventParser.Keywords.Exception | // We want to see the exception events. ClrTraceEventParser.Keywords.Stack)); // And stacks on all CLR events where it makes sense. // The CLR events turned on above will let you resolve JIT compiled code as long as the JIT compilation // happens AFTER the session has started. To handle the case for JIT compiled code that was already // compiled we need to tell the CLR to dump 'Rundown' events for all existing JIT compiled code. We // do that here. Out.WriteLine("Enabling CLR Events to 'catch up' on JIT compiled code in running processes."); session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)(ClrTraceEventParser.Keywords.Jit | // We need JIT events to be rundown to resolve method names ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // As well as the module load events. ClrTraceEventParser.Keywords.StartEnumeration)); // This indicates to do the rundown now (at enable time) // Because we care about symbols in native code or NGEN images, we need a SymbolReader to decode them. // There is a lot of messages associated with looking up symbols, but we don't want to clutter up // The output by default, so we save it to an internal buffer you can ToString in debug code. // A real app should make this available somehow to the user, because sooner or later you DO need it. TextWriter SymbolLookupMessages = new StringWriter(); // TextWriter SymbolLookupMessages = Out; // If you want the symbol debug spew to go to the output, use this. // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath); SymbolReader symbolReader = new SymbolReader(SymbolLookupMessages, symbolPath.ToString()); Out.WriteLine("Open a real time TraceLog session (which understands how to decode stacks)."); using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session)) { // We use this action in the particular callbacks below. Basically we pass in a symbol reader so we can decode the stack. // Often the symbol reader is a global variable instead. Action <TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader)); // We will print Exceptions and ModuleLoad events. (with stacks). traceLogSource.Clr.ExceptionStart += PrintEvent; traceLogSource.Clr.LoaderModuleLoad += PrintEvent; // traceLogSource.Clr.All += PrintEvent; // If you want to see stacks for various other kernel events, uncomment these (you also need to turn on the events above) traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader)); // traceLogSource.Kernel.ImageLoad += ((ImageLoadTraceData data) => Print(data, symbolReader)); // process events until Ctrl-C is pressed or timeout expires Out.WriteLine("Waiting {0} sec for Events. Run managed code to see data. ", monitoringTimeSec); Out.WriteLine("Keep in mind there is a several second buffering delay"); // Set up a timer to stop processing after monitoringTimeSec timer = new Timer(delegate(object state) { Out.WriteLine("Stopped Monitoring after {0} sec", monitoringTimeSec); if (session != null) { session.Dispose(); } session = null; }, null, monitoringTimeSec * 1000, Timeout.Infinite); traceLogSource.Process(); } } Out.WriteLine("Finished"); if (timer != null) { timer.Dispose(); // Turn off the timer. } }
public SymbolReference(SymbolPath path, string name, string fullName, SymbolType type, SourceSpan location) : base(path, name, fullName, type, location) { }
public ICallTreeDataProvider Get() { var queryString = this.httpRequest.Query; string filename = queryString["filename"]; string stacktype = queryString["stacktype"]; if (string.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } if (string.IsNullOrEmpty(stacktype)) { throw new ArgumentNullException("stacktype"); } /* symbols and sources related parameters */ string sympathStr = (string)queryString["sympath"] ?? SymbolPath.MicrosoftSymbolServerPath; SymbolPath symPath = new SymbolPath(sympathStr); string defaultSymbolCache = symPath.DefaultSymbolCache(); // Normalize the symbol path. symPath = symPath.InsureHasCache(defaultSymbolCache); sympathStr = symPath.ToString(); string srcpath = (string)queryString["srcpath"]; //TODO FIX NOW: Dont spew to the Console, send it back to the client. SymbolReader symbolReader = new SymbolReader(Console.Out, sympathStr); if (srcpath != null) { symbolReader.SourcePath = srcpath; } string modulePatStr = (string)queryString["symLookupPats"] ?? @"^(clr|ntoskrnl|ntdll|.*\.ni)"; /* filtering parameters */ string start = (string)queryString["start"] ?? string.Empty; string end = (string)queryString["end"] ?? string.Empty; string incpats = (string)queryString["incpats"] ?? string.Empty; string excpats = (string)queryString["excpats"] ?? string.Empty; string foldpats = (string)queryString["foldpats"] ?? string.Empty; string grouppats = (string)queryString["grouppats"] ?? string.Empty; string foldpct = (string)queryString["foldpct"] ?? string.Empty; string find = (string)queryString["find"] ?? string.Empty; EtlxFile etlxFile; // Do it twice so that XXX.etl.zip becomes XXX. string etlxFilePath = Path.ChangeExtension(Path.ChangeExtension(filename, null), ".etlx"); lock (this.etlxCache) { if (this.etlxCache.TryGetValue(filename, out etlxFile)) { if (etlxFile == null) { throw new ArgumentNullException("etlxFile"); } } else { etlxFile = new EtlxFile(filename) { Pending = true }; this.etlxCache.Set(filename, etlxFile, this.cacheExpirationTime); } } lock (etlxFile) { if (etlxFile.Pending) { if (!File.Exists(etlxFilePath)) { // if it's a zip file if (string.Equals(Path.GetExtension(filename), ".zip", StringComparison.OrdinalIgnoreCase)) { //TODO FIX NOW: Dont spew to the Console, send it back to the client. ZippedETLReader reader = new ZippedETLReader(filename, Console.Out); reader.SymbolDirectory = defaultSymbolCache; reader.EtlFileName = Path.ChangeExtension(etlxFilePath, etlExtension); reader.UnpackAchive(); TraceLog.CreateFromEventTraceLogFile(reader.EtlFileName, etlxFilePath); } else { TraceLog.CreateFromEventTraceLogFile(filename, etlxFilePath); } } etlxFile.TraceLog = TraceLog.OpenOrConvert(etlxFilePath); etlxFile.Pending = false; } Regex modulePat = new Regex(modulePatStr, RegexOptions.IgnoreCase); foreach (var moduleFile in etlxFile.TraceLog.ModuleFiles) { if (modulePat.IsMatch(moduleFile.Name)) { etlxFile.TraceLog.CodeAddresses.LookupSymbolsForModule(symbolReader, moduleFile); } } } StackViewerSession stackViewerSession; lock (this.stackViewerSessionCache) { var filterParams = new FilterParams { Name = filename + stacktype, StartTimeRelativeMSec = start, EndTimeRelativeMSec = end, MinInclusiveTimePercent = foldpct, FoldRegExs = foldpats, IncludeRegExs = incpats, ExcludeRegExs = excpats, GroupRegExs = grouppats }; var keyBuilder = new StringBuilder(); keyBuilder.Append(filterParams.Name).Append("?" + filterParams.StartTimeRelativeMSec).Append("?" + filterParams.EndTimeRelativeMSec).Append("?" + filterParams.MinInclusiveTimePercent).Append("?" + filterParams.FoldRegExs).Append("?" + filterParams.IncludeRegExs).Append("?" + filterParams.ExcludeRegExs).Append("?" + filterParams.GroupRegExs).Append("?" + find); var stackViewerKey = keyBuilder.ToString(); if (this.stackViewerSessionCache.TryGetValue(stackViewerKey, out stackViewerSession)) { if (stackViewerSession == null) { throw new ArgumentNullException("stackViewerSession"); } } else { stackViewerSession = new StackViewerSession(filename, stacktype, etlxFile.TraceLog, filterParams, symbolReader); this.stackViewerSessionCache.Set(stackViewerKey, stackViewerSession, cacheExpirationTime); } } lock (stackViewerSession) { if (stackViewerSession.Pending) { stackViewerSession.InitializeDataProvider(); stackViewerSession.Pending = false; } } return(stackViewerSession.GetDataProvider()); }
public static void Run() { var monitoringTimeSec = 10; Out.WriteLine("******************** RealTimeTraceLog DEMO (win8) ********************"); Out.WriteLine("This program Shows how to use the real-time support in TraceLog"); Out.WriteLine("We do this by showing how to monitor exceptions in real time "); Out.WriteLine(); Out.WriteLine("This code depends on a Feature of Windows 8.1 (combined user and kernel sessions)"); Out.WriteLine(); Out.WriteLine("Note that this support is currently experimental and subject to change"); Out.WriteLine(); Out.WriteLine("Monitoring .NET Module load and Exception events (with stacks)."); Out.WriteLine("Run some managed code (ideally that has exceptions) while the monitor is running."); Out.WriteLine(); if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62) { Out.WriteLine("This demo only works on Win8 / Win 2012 and above)"); return; } TraceEventSession session = null; // Set up Ctrl-C to stop both user mode and kernel mode sessions Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) => { if (session != null) session.Dispose(); cancelArgs.Cancel = true; }; // Cause an exception to be thrown a few seconds in (so we have something interesting to look at) var exceptionGeneationTask = Task.Factory.StartNew(delegate { Thread.Sleep(3000); ThrowException(); }); Timer timer = null; // Create the new session to receive the events. // Because we are on Win 8 this single session can handle both kernel and non-kernel providers. using (session = new TraceEventSession("TraceLogSession")) { // Enable the events we care about for the kernel // For this instant the session will buffer any incoming events. // Enabling kernel events must be done before anything else. // This will fail on Win7. // // Note that if you turn on the KernelTraceEventParser.Keywords.Profile, you can also get stacks for CPU sampling // (every millisecond). (You can use the traceLogSource.Kernel.PerfInfoSample callback). Out.WriteLine("Enabling Image load, Process and Thread events. These are needed to look up native method names."); session.EnableKernelProvider( // KernelTraceEventParser.Keywords.Profile | // If you want CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want context switch events // KernelTraceEventParser.Keywords.Thread | // If you want context switch events you also need thread start events. KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process, /****** The second parameter indicates which kernel events should have stacks *****/ // KernelTraceEventParser.Keywords.ImageLoad | // If you want Stacks image load (load library) events // KernelTraceEventParser.Keywords.Profile | // If you want Stacks for CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want Stacks for context switch events KernelTraceEventParser.Keywords.None ); Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)"); // We are monitoring exception events (with stacks) and module load events (with stacks) session.EnableProvider( ClrTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)(ClrTraceEventParser.Keywords.Jit | // Turning on JIT events is necessary to resolve JIT compiled code ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // You must include loader events as well to resolve JIT compiled code. ClrTraceEventParser.Keywords.Exception | // We want to see the exception events. ClrTraceEventParser.Keywords.Stack)); // And stacks on all CLR events where it makes sense. // The CLR events turned on above will let you resolve JIT compiled code as long as the JIT compilation // happens AFTER the session has started. To handle the case for JIT compiled code that was already // compiled we need to tell the CLR to dump 'Rundown' events for all existing JIT compiled code. We // do that here. Out.WriteLine("Enabling CLR Events to 'catch up' on JIT compiled code in running processes."); session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)(ClrTraceEventParser.Keywords.Jit | // We need JIT events to be rundown to resolve method names ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // As well as the module load events. ClrTraceEventParser.Keywords.StartEnumeration)); // This indicates to do the rundown now (at enable time) // Because we care about symbols in native code or NGEN images, we need a SymbolReader to decode them. // There is a lot of messages associated with looking up symbols, but we don't want to clutter up // The output by default, so we save it to an internal buffer you can ToString in debug code. // A real app should make this available somehow to the user, because sooner or later you DO need it. TextWriter SymbolLookupMessages = new StringWriter(); // TextWriter SymbolLookupMessages = Out; // If you want the symbol debug spew to go to the output, use this. // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath); SymbolReader symbolReader = new SymbolReader(SymbolLookupMessages, symbolPath.ToString()); Out.WriteLine("Open a real time TraceLog session (which understands how to decode stacks)."); using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session)) { // We use this action in the particular callbacks below. Basically we pass in a symbol reader so we can decode the stack. // Often the symbol reader is a global variable instead. Action<TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader)); // We will print Exceptions and ModuleLoad events. (with stacks). traceLogSource.Clr.ExceptionStart += PrintEvent; traceLogSource.Clr.LoaderModuleLoad += PrintEvent; // traceLogSource.Clr.All += PrintEvent; // If you want to see stacks for various other kernel events, uncomment these (you also need to turn on the events above) traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader)); // traceLogSource.Kernel.ImageLoad += ((ImageLoadTraceData data) => Print(data, symbolReader)); // process events until Ctrl-C is pressed or timeout expires Out.WriteLine("Waiting {0} sec for Events. Run managed code to see data. ", monitoringTimeSec); Out.WriteLine("Keep in mind there is a several second buffering delay"); // Set up a timer to stop processing after monitoringTimeSec timer = new Timer(delegate(object state) { Out.WriteLine("Stopped Monitoring after {0} sec", monitoringTimeSec); if (session != null) session.Dispose(); session = null; }, null, monitoringTimeSec * 1000, Timeout.Infinite); traceLogSource.Process(); } } Out.WriteLine("Finished"); if (timer != null) timer.Dispose(); // Turn off the timer. }
public SymbolDefinitionBuilder(SymbolPath path, ISymbol symbol, Location location) : base(path, symbol, location) { }
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); }
public SymbolReferenceBuilder(SymbolPath path, ISymbol symbol, Location location) : base(path, symbol, location) { }