Skip to content

Instantly share code, notes, and snippets.

@mattwarren
Forked from goldshtn/clrmd-sdd-demo.cs
Created May 23, 2016 20:30
Show Gist options
  • Save mattwarren/c5197426c16590fc4c35422862affa78 to your computer and use it in GitHub Desktop.
Save mattwarren/c5197426c16590fc4c35422862affa78 to your computer and use it in GitHub Desktop.
CLRMD demo shown at SDD 2016
using Microsoft.Diagnostics.Runtime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SDDTriage
{
class Program
{
static void Main(string[] args)
{
var target = DataTarget.LoadCrashDump(@"C:\temp\sdddumps\FileExplorer.exe.5448.dmp");
//var target = DataTarget.AttachToProcess(
// pid: Process.GetProcessesByName("devenv")[0].Id,
// msecTimeout: 1000,
// attachFlag: AttachFlag.Passive
// );
foreach (var clr in target.ClrVersions)
{
Console.WriteLine(clr.Version);
}
var runtime = target.ClrVersions[0].CreateRuntime();
var heap = runtime.GetHeap();
Console.WriteLine("ONLY LIVE OBJECTS:");
var allLiveObjects = new HashSet<ulong>();
EnumerateLiveObjects(runtime, allLiveObjects);
HeapAnalysis(heap, allLiveObjects);
// StringAnalysis(runtime);
Console.WriteLine("ALL OBJECTS, LIVE AND DEAD:");
HeapAnalysis(heap, heap.EnumerateObjectAddresses());
// CrashTriage(runtime);
}
private static void EnumerateLiveObjects(ClrRuntime runtime,
HashSet<ulong> allLiveObjects)
{
var heap = runtime.GetHeap();
foreach (var root in heap.EnumerateRoots())
{
EnumerateLiveObjectsHelper(heap, root.Object, allLiveObjects);
}
}
private static void EnumerateLiveObjectsHelper(
ClrHeap heap, ulong @object, HashSet<ulong> allLiveObjects)
{
if (allLiveObjects.Contains(@object))
return;
allLiveObjects.Add(@object);
heap.GetObjectType(@object).EnumerateRefsOfObject(@object, (referencedObj, _) =>
{
EnumerateLiveObjectsHelper(heap, referencedObj, allLiveObjects);
});
}
private static void StringAnalysis(ClrRuntime runtime)
{
ClrHeap heap = runtime.GetHeap();
foreach (var objAddr in heap.EnumerateObjectAddresses())
{
var type = heap.GetObjectType(objAddr);
if (type != null && !type.IsString)
continue;
// m_stringLength
var field = type.GetFieldByName("m_stringLength");
int stringLength = (int)field.GetValue(objAddr);
if (stringLength > 500)
{
Console.WriteLine(type.GetValue(objAddr));
Console.ReadLine();
}
}
}
private static void HeapAnalysis(ClrHeap heap, IEnumerable<ulong> targetObjects)
{
var query = from objAddr in targetObjects
let objType = heap.GetObjectType(objAddr)
where objType != null && !objType.IsFree
let size = (long)objType.GetSize(objAddr)
group size by objType.Name into g
let count = g.Count()
let totalSize = g.Sum()
orderby totalSize descending
select new { Type = g.Key, Count = count, TotalSize = totalSize };
foreach (var kvp in query.Take(10))
{
Console.WriteLine($"size = {kvp.TotalSize} count = {kvp.Count} instances of {kvp.Type}");
}
}
private static void CrashTriage(ClrRuntime runtime)
{
foreach (var thread in runtime.Threads)
{
Console.WriteLine(thread.OSThreadId);
if (thread.CurrentException != null)
{
Console.WriteLine($"\t*** {thread.CurrentException.Type} - {thread.CurrentException.Message}");
}
foreach (var frame in thread.StackTrace)
{
Console.WriteLine($"\t{frame.DisplayString}");
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment