Commits

Mathias Kluba committed fa8e46c

GCRoot support

  • Participants
  • Parent commits 0d4de2b

Comments (0)

Files changed (6)

SOS.Net.Core/Cdb/Commands/ReferenceInfoCommand.cs

+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace SOS.Net.Core.Cdb.Commands
+{
+    public class ReferenceInfoCommand :  ICdbCommand<CdbQueryable<ReferenceInfo>>
+    {
+        private readonly string instanceAddress;
+
+        public ReferenceInfoCommand(string instanceAddress)
+        {
+            this.instanceAddress = instanceAddress;
+        }
+
+        public IEnumerable<CdbQueryable<ReferenceInfo>> Result(CdbProcess process)
+        {
+            var output = process.ExecuteCommand(string.Format("!GCRoot {0}", this.instanceAddress));
+
+            var match = Regex.Match(output, string.Format("([A-Za-z0-9]*)\\(([^\\(]*)\\)->\\r\\n{0}", this.instanceAddress));
+
+            var result = new List<CdbQueryable<ReferenceInfo>>();
+
+            if(match.Success)
+            {
+                var refInfo = new ReferenceInfo
+                {
+                    Address = match.Groups[1].Value,
+                    Name = match.Groups[2].Value
+                };
+                result.Add(new CdbQueryable<ReferenceInfo>(refInfo, process));
+            }
+
+            return result;
+        }
+    }
+}

SOS.Net.Core/ReferenceInfo.cs

+namespace SOS.Net.Core
+{
+    public class ReferenceInfo
+    {
+        public string Address { get; set; }
+
+        public string Name { get; set; }
+    }
+}

SOS.Net.Core/SOS.Net.Core.csproj

     <Compile Include="Cdb\Commands\AppDomainInfoCommand.cs" />
     <Compile Include="Cdb\Commands\ArrayInstanceInfoCommand.cs" />
     <Compile Include="Cdb\Commands\InstanceFieldInfoCommand.cs" />
+    <Compile Include="Cdb\Commands\ReferenceInfoCommand.cs" />
     <Compile Include="Cdb\Extensions\AppDomainInfoExtensions.cs" />
     <Compile Include="Cdb\Commands\AssemblyInfoCommand.cs" />
     <Compile Include="Cdb\ICdbCommand.cs" />
     <Compile Include="InstanceInfo.cs" />
     <Compile Include="InstanceInfoDetails.cs" />
     <Compile Include="InstanceFieldInfo.cs" />
+    <Compile Include="ReferenceInfo.cs" />
     <Compile Include="TypeInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>

SOS.Net/FormMain.Designer.cs

             this.columnHeaderProcessId = new System.Windows.Forms.ColumnHeader();
             this.columnHeaderProcessName = new System.Windows.Forms.ColumnHeader();
             this.columnHeaderProcessPath = new System.Windows.Forms.ColumnHeader();
+            this.columnHeaderProcessCommandLine = new System.Windows.Forms.ColumnHeader();
+            this.columnHeaderIsDotNet = new System.Windows.Forms.ColumnHeader();
             this.panelSearchProcesses = new System.Windows.Forms.Panel();
             this.textBoxSearchProcesses = new System.Windows.Forms.TextBox();
             this.labelSearchProcesses = new System.Windows.Forms.Label();
             this.helpOnlineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.timerFilter = new System.Windows.Forms.Timer(this.components);
             this.timerTypeFilter = new System.Windows.Forms.Timer(this.components);
-            this.columnHeaderProcessCommandLine = new System.Windows.Forms.ColumnHeader();
-            this.columnHeaderIsDotNet = new System.Windows.Forms.ColumnHeader();
+            this.splitContainerObjectRef = new System.Windows.Forms.SplitContainer();
+            this.listViewObjectRef = new System.Windows.Forms.ListView();
+            this.columnHeaderObjectRefAddress = new System.Windows.Forms.ColumnHeader();
+            this.columnHeaderObjectRefType = new System.Windows.Forms.ColumnHeader();
             this.tabControlMain.SuspendLayout();
             this.tabPageProcesses.SuspendLayout();
             this.panelSearchProcesses.SuspendLayout();
             this.tableLayoutPanelHELPSOSEX.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxHelpSOSEX)).BeginInit();
             this.toolStripSettings.SuspendLayout();
+            this.splitContainerObjectRef.Panel1.SuspendLayout();
+            this.splitContainerObjectRef.Panel2.SuspendLayout();
+            this.splitContainerObjectRef.SuspendLayout();
             this.SuspendLayout();
             // 
             // tabControlMain
             this.columnHeaderProcessPath.Text = "Path";
             this.columnHeaderProcessPath.Width = 300;
             // 
+            // columnHeaderProcessCommandLine
+            // 
+            this.columnHeaderProcessCommandLine.DisplayIndex = 4;
+            this.columnHeaderProcessCommandLine.Text = "Command line";
+            this.columnHeaderProcessCommandLine.Width = 300;
+            // 
+            // columnHeaderIsDotNet
+            // 
+            this.columnHeaderIsDotNet.DisplayIndex = 0;
+            this.columnHeaderIsDotNet.Text = "DotNet?";
+            this.columnHeaderIsDotNet.Width = 55;
+            // 
             // panelSearchProcesses
             // 
             this.panelSearchProcesses.Controls.Add(this.textBoxSearchProcesses);
             // 
             // splitContainerObjectDumpDetails.Panel1
             // 
-            this.splitContainerObjectDumpDetails.Panel1.Controls.Add(this.listViewObjectDump);
+            this.splitContainerObjectDumpDetails.Panel1.Controls.Add(this.splitContainerObjectRef);
             // 
             // splitContainerObjectDumpDetails.Panel2
             // 
             this.timerTypeFilter.Interval = 500;
             this.timerTypeFilter.Tick += new System.EventHandler(this.timerTypeFilter_Tick);
             // 
-            // columnHeaderProcessCommandLine
+            // splitContainerObjectRef
             // 
-            this.columnHeaderProcessCommandLine.DisplayIndex = 4;
-            this.columnHeaderProcessCommandLine.Text = "Command line";
-            this.columnHeaderProcessCommandLine.Width = 300;
+            this.splitContainerObjectRef.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitContainerObjectRef.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+            this.splitContainerObjectRef.Location = new System.Drawing.Point(0, 0);
+            this.splitContainerObjectRef.Name = "splitContainerObjectRef";
+            this.splitContainerObjectRef.Orientation = System.Windows.Forms.Orientation.Horizontal;
             // 
-            // columnHeaderIsDotNet
+            // splitContainerObjectRef.Panel1
             // 
-            this.columnHeaderIsDotNet.DisplayIndex = 0;
-            this.columnHeaderIsDotNet.Text = "DotNet?";
-            this.columnHeaderIsDotNet.Width = 55;
+            this.splitContainerObjectRef.Panel1.Controls.Add(this.listViewObjectRef);
+            this.splitContainerObjectRef.Panel1Collapsed = true;
+            // 
+            // splitContainerObjectRef.Panel2
+            // 
+            this.splitContainerObjectRef.Panel2.Controls.Add(this.listViewObjectDump);
+            this.splitContainerObjectRef.Size = new System.Drawing.Size(723, 405);
+            this.splitContainerObjectRef.SplitterDistance = 105;
+            this.splitContainerObjectRef.TabIndex = 5;
+            // 
+            // listViewObjectRef
+            // 
+            this.listViewObjectRef.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.columnHeaderObjectRefAddress,
+            this.columnHeaderObjectRefType});
+            this.listViewObjectRef.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.listViewObjectRef.FullRowSelect = true;
+            this.listViewObjectRef.GridLines = true;
+            this.listViewObjectRef.HideSelection = false;
+            this.listViewObjectRef.Location = new System.Drawing.Point(0, 0);
+            this.listViewObjectRef.Name = "listViewObjectRef";
+            this.listViewObjectRef.Size = new System.Drawing.Size(723, 105);
+            this.listViewObjectRef.TabIndex = 5;
+            this.listViewObjectRef.UseCompatibleStateImageBehavior = false;
+            this.listViewObjectRef.View = System.Windows.Forms.View.Details;
+            this.listViewObjectRef.DoubleClick += new System.EventHandler(this.listViewObjectRef_DoubleClick);
+            this.listViewObjectRef.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listView_ColumnClick);
+            // 
+            // columnHeaderObjectRefAddress
+            // 
+            this.columnHeaderObjectRefAddress.Text = "Ref Address";
+            this.columnHeaderObjectRefAddress.Width = 137;
+            // 
+            // columnHeaderObjectRefType
+            // 
+            this.columnHeaderObjectRefType.Text = "Type";
+            this.columnHeaderObjectRefType.Width = 150;
             // 
             // FormMain
             // 
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxHelpSOSEX)).EndInit();
             this.toolStripSettings.ResumeLayout(false);
             this.toolStripSettings.PerformLayout();
+            this.splitContainerObjectRef.Panel1.ResumeLayout(false);
+            this.splitContainerObjectRef.Panel2.ResumeLayout(false);
+            this.splitContainerObjectRef.ResumeLayout(false);
             this.ResumeLayout(false);
             this.PerformLayout();
 
         private System.Windows.Forms.Label labelObjectDumpAddress;
         private System.Windows.Forms.ColumnHeader columnHeaderProcessCommandLine;
         private System.Windows.Forms.ColumnHeader columnHeaderIsDotNet;
+        private System.Windows.Forms.SplitContainer splitContainerObjectRef;
+        private System.Windows.Forms.ListView listViewObjectRef;
+        private System.Windows.Forms.ColumnHeader columnHeaderObjectRefAddress;
+        private System.Windows.Forms.ColumnHeader columnHeaderObjectRefType;
     }
 }
 

SOS.Net/FormMain.cs

                 this.splitContainerObjectDumpDetails.Panel2Collapsed = true;
             }
 
+            var refs = this.controller.GetInstanceRef(address);
+            if(refs.Length > 0)
+            {
+                this.splitContainerObjectRef.Panel1Collapsed = false;
+                this.listViewObjectRef.BeginUpdate();
+                this.listViewObjectRef.Items.Clear();
+                this.listViewObjectRef.Items.AddRange(refs);
+                this.listViewObjectRef.EndUpdate();
+            }
+            else
+            {
+                this.splitContainerObjectRef.Panel1Collapsed = true;
+                this.listViewObjectRef.Items.Clear();
+            }
+
             currentInstance = ((InstanceInfoDetails)button.Tag);
         }
 
                 this.flowLayoutPanelBreadcrumb.Controls.AddRange(items.ToArray());
 
                 this.OnInstanceSelected(newInstance);
-
             }
         }
 
             // Turn display back on.
             listview.EndUpdate();
         }
+
+        private void listViewObjectRef_DoubleClick(object sender, EventArgs e)
+        {
+            if (this.listViewObjectRef.SelectedIndices != null && this.listViewObjectRef.SelectedIndices.Count > 0)
+            {
+                var selected = this.listViewObjectRef.Items[this.listViewObjectRef.SelectedIndices[0]];
+
+                var selectedType = selected.SubItems[1].Text;
+
+                var selectedAddress = selected.SubItems[0].Text;
+
+                if (selectedType.EndsWith("[]") || selectedType.Equals("SZARRAY"))
+                {
+                    // the type is an array, display the collection
+                    this.splitContainerObjectDumpDetails.Panel2Collapsed = false;
+                    this.listViewFieldArray.BeginUpdate();
+                    this.listViewFieldArray.Items.Clear();
+                    this.listViewFieldArray.Items.AddRange(this.controller.GetArrayInstances(selectedAddress));
+                    this.listViewFieldArray.EndUpdate();
+                }
+                else
+                {
+                    Button newInstance = CreateInstanceButton(selectedAddress);
+                    DisplayInstanceDetails(newInstance);
+                }
+            }
+        }
     }
 }

SOS.Net/SosController.cs

 
             List<string> dotnetProcesses = new List<string>();
 
-            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_PerfFormattedData_NETFramework_NETCLRLoading");
+            /*ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Name FROM Win32_PerfFormattedData_NETFramework_NETCLRLoading");
             foreach (ManagementObject item in searcher.Get())
             {
                 string name = item.Properties["Name"].Value.ToString();
 
                     dotnetProcesses.Add(name);
                 }
-            }
+            }*/
 
-            searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
+            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
             foreach (ManagementObject item in searcher.Get())
             {
                 string name = item.Properties["Name"].Value.ToSafeString();
                 })).ToArray();
 
         }
+
+        public ListViewItem[] GetInstanceRef(string selectedAddress)
+        {
+            return this.cdb.ExecuteCommand(new ReferenceInfoCommand(selectedAddress))
+                .Select(a => a.Value)
+                .Select(a => new ListViewItem(new string[]
+                {
+                    a.Address,
+                    a.Name
+                })).ToArray();
+        }
     }
 
     internal static class StringExtensions