Created
December 9, 2018 10:21
-
-
Save tanaka-takayoshi/2a8d61792c73b9207ff428b4dad1b299 to your computer and use it in GitHub Desktop.
ClrMD example for .NET Core on Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Microsoft.Diagnostics.Runtime; | |
namespace ClrMDExample | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
using (var target = DataTarget.LoadCrashDump(@"C:\Users\User\AppData\Local\Temp\dotnet.DMP")) | |
//using (var target = DataTarget.AttachToProcess(20612, 5000)) | |
{ | |
foreach (var version in target.ClrVersions) | |
{ | |
Console.WriteLine("Found CLR Version:" + version.Version.ToString()); | |
// This is the data needed to request the dac from the symbol server: | |
ModuleInfo dacInfo = version.DacInfo; | |
Console.WriteLine("Filesize: {0:X}", dacInfo.FileSize); | |
Console.WriteLine("Timestamp: {0:X}", dacInfo.TimeStamp); | |
Console.WriteLine("Dac File: {0}", dacInfo.FileName); | |
var runtime = version.CreateRuntime(); | |
foreach (ClrAppDomain domain in runtime.AppDomains) | |
{ | |
Console.WriteLine("ID: {0}", domain.Id); | |
Console.WriteLine("Name: {0}", domain.Name); | |
Console.WriteLine("Address: {0}", domain.Address); | |
} | |
foreach (ClrThread thread in runtime.Threads) | |
{ | |
if (!thread.IsAlive) | |
continue; | |
Console.WriteLine("Thread {0:X}:", thread.OSThreadId); | |
foreach (ClrStackFrame frame in thread.StackTrace) | |
Console.WriteLine("{0,12:X} {1,12:X} {2}", frame.StackPointer, frame.InstructionPointer, frame.ToString()); | |
Console.WriteLine(); | |
} | |
foreach (var region in (from r in runtime.EnumerateMemoryRegions() | |
where r.Type != ClrMemoryRegionType.ReservedGCSegment | |
group r by r.Type into g | |
let total = g.Sum(p => (uint)p.Size) | |
orderby total descending | |
select new | |
{ | |
TotalSize = total, | |
Count = g.Count(), | |
Type = g.Key | |
})) | |
{ | |
Console.WriteLine("{0,6:n0} {1,12:n0} {2}", region.Count, region.TotalSize, region.Type.ToString()); | |
} | |
var heap = runtime.Heap; | |
foreach (ulong obj in runtime.EnumerateFinalizerQueueObjectAddresses()) | |
{ | |
var type = heap.GetObjectType(obj); | |
// If heap corruption, continue past this object. | |
if (type == null) | |
continue; | |
ulong size = type.GetSize(obj); | |
Console.WriteLine("{0,12:X} {1,8:n0} {2}", obj, size, type.Name); | |
} | |
foreach (var handle in runtime.EnumerateHandles()) | |
{ | |
string objectType = heap.GetObjectType(handle.Object).Name; | |
Console.WriteLine("{0,12:X} {1,12:X} {2,12} {3}", handle.Address, handle.Object, handle.Type.ToString(), objectType); | |
} | |
Console.WriteLine("{0,12} {1,12} {2,12} {3,12} {4,4} {5}", "Start", "End", "Committed", "Reserved", "Heap", "Type"); | |
foreach (var segment in heap.Segments) | |
{ | |
string type; | |
if (segment.IsEphemeral) | |
type = "Ephemeral"; | |
else if (segment.IsLarge) | |
type = "Large"; | |
else | |
type = "Gen2"; | |
Console.WriteLine("{0,12:X} {1,12:X} {2,12:X} {3,12:X} {4,4} {5}", segment.Start, segment.End, segment.CommittedEnd, segment.ReservedEnd, segment.ProcessorAffinity, type); | |
} | |
foreach (var item in (from seg in heap.Segments | |
group seg by seg.ProcessorAffinity into g | |
orderby g.Key | |
select new | |
{ | |
Heap = g.Key, | |
Size = g.Sum(p=>(uint)p.Length) | |
})) | |
{ | |
Console.WriteLine("Heap {0,2}: {1:n0} bytes", item.Heap, item.Size); | |
} | |
if (!heap.CanWalkHeap) | |
{ | |
Console.WriteLine("Cannot walk the heap!"); | |
} | |
else | |
{ | |
foreach (var seg in heap.Segments) | |
{ | |
for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj)) | |
{ | |
var type = heap.GetObjectType(obj); | |
// If heap corruption, continue past this object. | |
if (type == null) | |
continue; | |
ulong size = type.GetSize(obj); | |
Console.WriteLine("{0,12:X} {1,8:n0} {2,1:n0} {3}", obj, size, seg.GetGeneration(obj), type.Name); | |
} | |
} | |
} | |
foreach (var type in heap.EnumerateTypes()) | |
{ | |
foreach (var appDomain in runtime.AppDomains) | |
{ | |
foreach (var thread in runtime.Threads) | |
{ | |
foreach (var field in type.ThreadStaticFields) | |
{ | |
if (field.HasSimpleValue) | |
Console.WriteLine("{0}.{1} ({2}, {3:X}) = {4}", type.Name, field.Name, appDomain.Id, thread.OSThreadId, field.GetValue(appDomain, thread)); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment