private static void PrintDiagnosticInfo(DataTarget dt, ClrRuntime runtime, ClrHeap heap) { Console.WriteLine("DataTarget Info:"); Console.WriteLine(" ClrVersions: " + String.Join(", ", dt.ClrVersions)); Console.WriteLine(" IsMinidump: " + dt.IsMinidump); Console.WriteLine(" Architecture: " + dt.Architecture); Console.WriteLine(" PointerSize: " + dt.PointerSize); Console.WriteLine(" SymbolPath: " + dt.GetSymbolPath()); Console.WriteLine("ClrRuntime Info:"); Console.WriteLine(" ServerGC: " + runtime.ServerGC); Console.WriteLine(" HeapCount: " + runtime.HeapCount); Console.WriteLine(" Thread Count: " + runtime.Threads.Count); Console.WriteLine("ClrRuntime Modules:"); foreach (var module in runtime.EnumerateModules()) { Console.WriteLine(" {0,26} Id:{1}, {2,10:N0} bytes @ 0x{3:X8}", Path.GetFileName(module.FileName), module.AssemblyId, module.Size, module.ImageBase); } Console.WriteLine("ClrHeap Info:"); Console.WriteLine(" TotalHeapSize: " + heap.TotalHeapSize); Console.WriteLine(" Segments: " + heap.Segments.Count); Console.WriteLine(" Gen0 Size: " + heap.GetSizeByGen(0)); Console.WriteLine(" Gen1 Size: " + heap.GetSizeByGen(1)); Console.WriteLine(" Gen2 Size: " + heap.GetSizeByGen(2)); Console.WriteLine(" Gen3 Size: " + heap.GetSizeByGen(3)); }
public StopwatchInfo?GetStopwatchInfo() { foreach (var runtimeModule in _runtime.EnumerateModules()) { var clrType = runtimeModule.GetTypeByName("System.Diagnostics.Stopwatch"); if (clrType == null) { continue; } var tickFrequencyStaticField = clrType.GetStaticFieldByName("tickFrequency"); var isHighResolutionStaticField = clrType.GetStaticFieldByName("IsHighResolution"); foreach (var appDomain in _runtime.AppDomains) { var isTickFrequencyInitialized = tickFrequencyStaticField !.IsInitialized(appDomain); var isHighResolutionInitialized = isHighResolutionStaticField !.IsInitialized(appDomain); if (isTickFrequencyInitialized && isHighResolutionInitialized) { var tickFrequency = tickFrequencyStaticField.Read <double>(appDomain); var isHighResolution = isHighResolutionStaticField.Read <bool>(appDomain); return(new StopwatchInfo(tickFrequency, isHighResolution)); } } } return(null); }
public void StaticValueAppDomainTests() { using DataTarget dt = TestTargets.AppDomains.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrModule[] sharedModules = runtime.EnumerateModules().Where(m => Path.GetFileName(m.FileName).Equals("sharedlibrary.dll", StringComparison.OrdinalIgnoreCase)).ToArray(); Assert.Equal(2, sharedModules.Length); Assert.NotEqual(sharedModules[0].AppDomain, sharedModules[1].AppDomain); ClrType staticType1 = sharedModules[0].GetTypeByName("SharedStaticTest"); ClrType staticType2 = sharedModules[1].GetTypeByName("SharedStaticTest"); Assert.NotNull(staticType1); Assert.NotNull(staticType2); Assert.NotEqual(staticType1, staticType2); int value2 = staticType1.StaticFields.Single().Read <int>(); int value42 = staticType2.StaticFields.Single().Read <int>(); if (value2 > value42) { int tmp = value2; value2 = value42; value42 = tmp; } Assert.Equal(2, value2); Assert.Equal(42, value42); }
private void TouchOtherRegions(DumpReaderLogger readerLogger, ClrRuntime runtime) { // Touch all threads, stacks, frames foreach (var t in runtime.Threads) { foreach (var f in t.StackTrace) { try { f.GetFileAndLineNumber(); } catch (Exception) { } } } // Touch all modules runtime.EnumerateModules().Count(); // Touch all heap regions, roots, types var heap = runtime.GetHeap(); heap.EnumerateRoots(enumerateStatics: false).Count(); heap.EnumerateTypes().Count(); // TODO Check if it's faster to construct sorted inside ReaderWrapper foreach (var kvp in readerLogger.Ranges) { _otherClrRegions.Add(kvp.Key, kvp.Value); } }
public static IEnumerable <(ClrStaticField Field, ClrObject Object)> EnumerateAllStaticVariables(this ClrRuntime runtime) { if (runtime is null) { throw new ArgumentNullException(nameof(runtime)); } foreach (ClrModule module in runtime.EnumerateModules()) { foreach ((ulong mt, int _) in module.EnumerateTypeDefToMethodTableMap()) { ClrType?type = runtime.GetTypeByMethodTable(mt); if (type is null) { continue; } foreach (ClrStaticField field in type.StaticFields) { if (field.IsObjectReference) { foreach (ClrAppDomain domain in runtime.AppDomains) { ClrObject obj = field.ReadObject(domain); if (obj.IsValid && !obj.IsNull) { yield return(field, obj); } } } } } } }
public void MethodHandleMultiDomainTests() { ulong[] methodDescs; using (DataTarget dt = TestTargets.AppDomains.LoadFullDump()) { using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrType[] types = runtime.EnumerateModules().Where(m => m.Name.EndsWith("sharedlibrary.dll", System.StringComparison.OrdinalIgnoreCase)).Select(m => m.GetTypeByName("Foo")).Where(t => t != null).ToArray(); Assert.Equal(2, types.Length); methodDescs = types.Select(t => t.Methods.Single(m => m.Name == "Bar")).Select(m => m.MethodDesc).ToArray(); Assert.Equal(2, methodDescs.Length); } using (DataTarget dt = TestTargets.AppDomains.LoadFullDump()) { using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrMethod method = runtime.GetMethodByHandle(methodDescs[0]); Assert.NotNull(method); Assert.Equal("Bar", method.Name); Assert.Equal("Foo", method.Type.Name); } using (DataTarget dt = TestTargets.AppDomains.LoadFullDump()) { using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrMethod method = runtime.GetMethodByHandle(methodDescs[1]); Assert.NotNull(method); Assert.Equal("Bar", method.Name); Assert.Equal("Foo", method.Type.Name); } }
/// <summary> /// Note: https://github.com/microsoft/clrmd/issues/567#issuecomment-601314348 /// </summary> /// <param name="runtime"></param> /// <param name="predicate"></param> /// <returns></returns> public static IEnumerable <ClrType> GetConstructedTypeDefinitions(this ClrRuntime runtime, Func <ClrType, bool> predicate) { return(runtime.EnumerateModules() .SelectMany(m => m.EnumerateTypeDefToMethodTableMap()) .Select(t => runtime.GetTypeByMethodTable(t.MethodTable)) .Where(predicate)); }
private MetadataRegion FindRegion(ulong address) { if (!_regionInitialized) { // Need to set this before enumerating the runtimes to prevent reentrancy _regionInitialized = true; var runtimes = RuntimeService.EnumerateRuntimes(); if (runtimes.Any()) { foreach (IRuntime runtime in runtimes) { Trace.TraceInformation($"FindRegion: initializing regions for runtime #{runtime.Id}"); ClrRuntime clrRuntime = runtime.Services.GetService <ClrRuntime>(); if (clrRuntime != null) { Trace.TraceInformation($"FindRegion: initializing regions for CLR runtime #{runtime.Id}"); _regions = clrRuntime.EnumerateModules() .Where((module) => module.MetadataAddress != 0 && module.IsPEFile && !module.IsDynamic) .Select((module) => new MetadataRegion(this, module)) .ToImmutableArray() .Sort(); } } } else { // If there are no runtimes, try again next time around _regionInitialized = false; } } if (_regions != null) { int min = 0, max = _regions.Length - 1; while (min <= max) { int mid = (min + max) / 2; MetadataRegion region = _regions[mid]; if (address >= region.StartAddress && address < region.EndAddress) { return(region); } if (region.StartAddress < address) { min = mid + 1; } else { max = mid - 1; } } } return(null); }
public void ModuleEqualityTest() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrModule[] oldModules = runtime.EnumerateModules().ToArray(); Assert.NotEmpty(oldModules); runtime.FlushCachedData(); ClrModule[] newModules = runtime.EnumerateModules().ToArray(); Assert.Equal(oldModules.Length, newModules.Length); for (int i = 0; i < newModules.Length; i++) { Assert.Equal(oldModules[i], newModules[i]); Assert.NotSame(oldModules[i], newModules[i]); } }
public void TestModuleSize() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); foreach (ClrModule module in runtime.EnumerateModules()) { Assert.True(module.IsDynamic || module.Size > 0); } }
public void TestModulesNames() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); foreach (ClrModule module in runtime.EnumerateModules()) { Assert.True(File.Exists(module.Name)); Assert.True(File.Exists(module.AssemblyName)); } }
private void PrintRuntimeDiagnosticInfo(DataTarget dataTarget, ClrRuntime runtime) { logger?.WriteLine(LogKind.Header, "\nRuntime Diagnostic Information"); logger?.WriteLine(LogKind.Header, "------------------------------"); logger?.WriteLine(LogKind.Header, "\nDataTarget Info:"); logger?.WriteLine(LogKind.Info, string.Format(" ClrVersion{0}: {1}", dataTarget.ClrVersions.Count > 1 ? "s" : "", string.Join(", ", dataTarget.ClrVersions))); logger?.WriteLine(LogKind.Info, " Architecture: " + dataTarget.Architecture); logger?.WriteLine(LogKind.Info, string.Format(" PointerSize: {0} ({1}-bit)", dataTarget.PointerSize, dataTarget.PointerSize == 8 ? 64 : 32)); logger?.WriteLine(LogKind.Info, " SymbolPath: " + dataTarget.GetSymbolPath()); logger?.WriteLine(LogKind.Header, "\nClrRuntime Info:"); logger?.WriteLine(LogKind.Info, " ServerGC: " + runtime.ServerGC); logger?.WriteLine(LogKind.Info, " HeapCount: " + runtime.HeapCount); logger?.WriteLine(LogKind.Info, " Thread Count: " + runtime.Threads.Count); logger?.WriteLine(LogKind.Header, "\nClrRuntime Modules:"); foreach (var module in runtime.EnumerateModules()) { logger?.WriteLine(LogKind.Info, string.Format( " {0,36} Id:{1} - {2,10:N0} bytes @ 0x{3:X16}", Path.GetFileName(module.FileName), module.AssemblyId.ToString().PadRight(10), module.Size, module.ImageBase)); } ClrHeap heap = runtime.GetHeap(); logger?.WriteLine(LogKind.Header, "\nClrHeap Info:"); logger?.WriteLine(LogKind.Info, string.Format(" TotalHeapSize: {0:N0} bytes ({1:N2} MB)", heap.TotalHeapSize, heap.TotalHeapSize / 1024.0 / 1024.0)); logger?.WriteLine(LogKind.Info, string.Format(" Gen0: {0,10:N0} bytes", heap.GetSizeByGen(0))); logger?.WriteLine(LogKind.Info, string.Format(" Gen1: {0,10:N0} bytes", heap.GetSizeByGen(1))); logger?.WriteLine(LogKind.Info, string.Format(" Gen2: {0,10:N0} bytes", heap.GetSizeByGen(2))); logger?.WriteLine(LogKind.Info, string.Format(" LOH: {0,10:N0} bytes", heap.GetSizeByGen(3))); logger?.WriteLine(LogKind.Info, " Segments: " + heap.Segments.Count); foreach (var segment in heap.Segments) { logger?.WriteLine(LogKind.Info, string.Format(" Segment: {0,10:N0} bytes, {1,10}, Gen0: {2,10:N0} bytes, Gen1: {3,10:N0} bytes, Gen2: {4,10:N0} bytes", segment.Length, segment.IsLarge ? "Large" : (segment.IsEphemeral ? "Ephemeral" : "Unknown"), segment.Gen0Length, segment.Gen1Length, segment.Gen2Length)); } logger?.WriteLine(); }
private MetadataRegion FindRegion(ulong address) { if (!_regionInitialized) { _regionInitialized = true; Trace.TraceInformation($"FindRegion: initializing regions for runtime #{_runtime.Id}"); ClrRuntime clrruntime = _runtime.Services.GetService <ClrRuntime>(); if (clrruntime != null) { _regions = clrruntime.EnumerateModules() .Where((module) => module.MetadataAddress != 0 && module.IsPEFile && !module.IsDynamic) .Select((module) => new MetadataRegion(this, module)) .ToImmutableArray() .Sort(); } } if (_regions != null) { int min = 0, max = _regions.Length - 1; while (min <= max) { int mid = (min + max) / 2; MetadataRegion region = _regions[mid]; if (address >= region.StartAddress && address < region.EndAddress) { return(region); } if (region.StartAddress < address) { min = mid + 1; } else { max = mid - 1; } } } return(null); }
public void NoDuplicateModules() { // Modules should have a unique .Address. // https://github.com/microsoft/clrmd/issues/440 using DataTarget dt = TestTargets.AppDomains.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); HashSet <ulong> seen = new HashSet <ulong> { 0 }; HashSet <ClrModule> seenModules = new HashSet <ClrModule> { null }; foreach (ClrModule module in runtime.EnumerateModules()) { Assert.True(seenModules.Add(module)); Assert.True(seen.Add(module.Address)); } }
public void RuntimeTests(TestHost host) { // The current Linux test assets are not alpine/musl if (OS.IsAlpine) { throw new SkipTestException("Not supported on Alpine Linux"); } var runtimeService = host.Target.Services.GetService <IRuntimeService>(); Assert.NotNull(runtimeService); var contextService = host.Target.Services.GetService <IContextService>(); Assert.NotNull(contextService); Assert.NotNull(contextService.GetCurrentRuntime()); foreach (ImmutableDictionary <string, TestDataReader.Value> runtimeData in host.TestData.Runtimes) { if (runtimeData.TryGetValue("Id", out int id)) { IRuntime runtime = runtimeService.EnumerateRuntimes().FirstOrDefault((r) => r.Id == id); Assert.NotNull(runtime); runtimeData.CompareMembers(runtime); ClrInfo clrInfo = runtime.Services.GetService <ClrInfo>(); Assert.NotNull(clrInfo); ClrRuntime clrRuntime = runtime.Services.GetService <ClrRuntime>(); Assert.NotNull(clrRuntime); Assert.NotEmpty(clrRuntime.AppDomains); Assert.NotEmpty(clrRuntime.Threads); Assert.NotEmpty(clrRuntime.EnumerateModules()); if (!host.DumpFile.Contains("Triage")) { Assert.NotEmpty(clrRuntime.EnumerateHandles()); } } } }
public void TestTypeMapRoundTrip() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); int badTypes = 0; foreach (ClrModule module in runtime.EnumerateModules()) { foreach ((ulong mt, int token) in module.EnumerateTypeDefToMethodTableMap()) { Assert.NotEqual(0, token); Assert.True((token & 0x02000000) == 0x02000000); ClrType type = runtime.GetTypeByMethodTable(mt); if (type == null) { // We really want to Assert.NotNull(type), but it turns out that one type // (System.Runtime.Remoting.Proxies.__TransparentProxy) cannot be constructed because // GetMethodTableData returns null for it. This is an issue with the dac so we'll // simply count types that are null and assert there's only one badTypes++; continue; } Assert.NotNull(type); ClrType typeFromToken = module.ResolveToken(token); Assert.NotNull(typeFromToken); Assert.Same(type, typeFromToken); } } Assert.True(badTypes <= 1); }
public void PdbEqualityTest() { // Ensure all methods in our source file is in the pdb. using DataTarget dt = TestTargets.NestedException.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); PdbInfo[] allPdbs = runtime.EnumerateModules().Select(m => m.Pdb).Where(pdb => pdb != null).ToArray(); Assert.True(allPdbs.Length > 1); for (int i = 0; i < allPdbs.Length; i++) { Assert.NotNull(allPdbs[i]); Assert.True(allPdbs[i].Equals(allPdbs[i])); for (int j = i + 1; j < allPdbs.Length; j++) { if (allPdbs[i].Path != allPdbs[j].Path) { Assert.False(allPdbs[i].Equals(allPdbs[j])); Assert.False(allPdbs[j].Equals(allPdbs[i])); } } } }
public void TypeEqualityTest() { // This test ensures that only one ClrType is created when we have a type loaded into two different AppDomains with two different // method tables. const string TypeName = "Foo"; using DataTarget dt = TestTargets.AppDomains.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; ClrType[] types = (from obj in heap.EnumerateObjects() let t = heap.GetObjectType(obj.Address) where t.Name == TypeName orderby t.MethodTable select t).ToArray(); Assert.Equal(2, types.Length); Assert.NotSame(types[0], types[1]); ClrType[] typesFromModule = (from module in runtime.EnumerateModules() let name = Path.GetFileNameWithoutExtension(module.Name) where name.Equals("sharedlibrary", StringComparison.OrdinalIgnoreCase) let type = module.GetTypeByName(TypeName) select type).ToArray(); Assert.Equal(2, typesFromModule.Length); Assert.NotSame(types[0], types[1]); Assert.NotEqual(types[0], types[1]); if (dt.CacheOptions.CacheTypes) { Assert.Same(types[0], typesFromModule[0]); Assert.Same(types[1], typesFromModule[1]); } else { Assert.Equal(types[0], typesFromModule[0]); Assert.Equal(types[1], typesFromModule[1]); } // Get new types runtime.FlushCachedData(); ClrType[] newTypes = (from module in runtime.EnumerateModules() let name = Path.GetFileNameWithoutExtension(module.Name) where name.Equals("sharedlibrary", StringComparison.OrdinalIgnoreCase) let type = module.GetTypeByName(TypeName) select type).ToArray(); Assert.Equal(2, newTypes.Length); for (int i = 0; i < newTypes.Length; i++) { Assert.NotSame(typesFromModule[i], newTypes[i]); Assert.Equal(typesFromModule[i], newTypes[i]); } // Even though these are the same underlying type defined in sharedlibrary's metadata, // they have different MethodTables, Parent modules, and parent domains. These do not // compare as equal. Assert.NotEqual(typesFromModule[0], typesFromModule[1]); }
public void EnsureFlushClearsData() { using DataTarget dt = TestTargets.AppDomains.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); var oldShared = runtime.SharedDomain; var oldSystem = runtime.SystemDomain; var oldDomains = runtime.AppDomains; var oldHeap = runtime.Heap; var oldModules = runtime.EnumerateModules().ToArray(); var oldObjects = oldHeap.EnumerateObjects().Take(20).ToArray(); var oldFields = oldObjects.SelectMany(o => o.Type.Fields).ToArray(); var oldStaticFields = oldObjects.SelectMany(o => o.Type.StaticFields).ToArray(); var oldMethods = oldObjects.SelectMany(o => o.Type.Methods).ToArray(); var oldThreads = runtime.Threads; // Ensure names are read and cached foreach (var obj in oldObjects) { _ = obj.Type.Name; foreach (var item in obj.Type.Methods) { _ = item.Name; } foreach (var item in obj.Type.Fields) { _ = item.Name; } foreach (var item in obj.Type.StaticFields) { _ = item.Name; } } foreach (var module in oldModules) { _ = module.Name; _ = module.FileName; _ = module.AssemblyName; } // Ensure we have some data to compare against Assert.NotEmpty(oldDomains); Assert.NotEmpty(oldModules); Assert.NotEmpty(oldObjects); Assert.NotEmpty(oldThreads); Assert.NotEmpty(oldFields); Assert.NotEmpty(oldStaticFields); Assert.NotEmpty(oldMethods); // Make sure we aren't regenerating this list every time. Assert.Same(oldDomains, runtime.AppDomains); // Clear all cached data. runtime.FlushCachedData(); CheckDomainNotSame(oldShared, runtime.SharedDomain); CheckDomainNotSame(oldSystem, runtime.SystemDomain); Assert.Equal(oldDomains.Count, runtime.AppDomains.Count); for (int i = 0; i < oldDomains.Count; i++) { CheckDomainNotSame(oldDomains[i], runtime.AppDomains[i]); } var newModules = runtime.EnumerateModules().ToArray(); for (int i = 0; i < oldModules.Length; i++) { CheckModuleNotSame(oldModules[i], newModules[i]); } ClrHeap newHeap = runtime.Heap; var newObjs = newHeap.EnumerateObjects().Take(20).ToArray(); Assert.Equal(oldObjects.Length, newObjs.Length); for (int i = 0; i < oldObjects.Length; i++) { Assert.Equal(oldObjects[i].Address, newObjs[i].Address); CheckTypeNotSame(oldObjects[i].Type, newObjs[i].Type); } var newThreads = runtime.Threads; Assert.Same(newThreads, runtime.Threads); Assert.Equal(oldThreads.Count, newThreads.Count); for (int i = 0; i < oldThreads.Count; i++) { Assert.Equal(oldThreads[i].OSThreadId, newThreads[i].OSThreadId); Assert.NotSame(oldThreads[i], newThreads[i]); } }