public static string GetFileDistinctPath(string folderPath, string fileName) { if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath)) { return(null); } fileName = DumpFileMoniker.GetValidFileName(fileName); string path = folderPath; if (folderPath[folderPath.Length - 1] != System.IO.Path.DirectorySeparatorChar) { path = path + System.IO.Path.DirectorySeparatorChar; } path = path + fileName; var orgPath = string.Copy(path); var dotPos = path.LastIndexOf('.'); Debug.Assert(dotPos > 0); // we should use kind of standard file names int ndx = 1; while (File.Exists(path)) { string num = "(" + ndx + ")"; ++ndx; path = orgPath.Insert(dotPos, num); } return(path); }
public static ClrtRootInfo Load(int rtm, DumpFileMoniker fileMoniker, out string error) { error = null; BinaryReader bw = null; try { var path = fileMoniker.GetFilePath(rtm, Constants.MapRootsInfoFilePostfix); bw = new BinaryReader(File.Open(path, FileMode.Open)); // root details // int count = bw.ReadInt32(); ClrtRoot[][] roots = new ClrtRoot[count][]; for (int i = 0; i < count; ++i) { int kindCount = bw.ReadInt32(); roots[i] = new ClrtRoot[kindCount]; for (int j = 0; j < kindCount; ++j) { roots[i][j] = ClrtRoot.Load(bw); } } return(new ClrtRootInfo(roots)); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(null); } finally { bw?.Close(); } }
public static bool Save(int rtm, List <ClrtRoot>[] ourRoots, DumpFileMoniker fileMoniker, out string error) { error = null; BinaryWriter bw = null; try { var path = fileMoniker.GetFilePath(rtm, Constants.MapRootsInfoFilePostfix); bw = new BinaryWriter(File.Open(path, FileMode.Create)); // root details by kind // bw.Write(ourRoots.Length); for (int i = 0, icnt = ourRoots.Length; i < icnt; ++i) { var kindRoots = ourRoots[i]; bw.Write(kindRoots.Count); for (int j = 0, jcnt = kindRoots.Count; j < jcnt; ++j) { kindRoots[j].Dump(bw); } } return(true); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(false); } finally { bw?.Close(); } }
public static bool InstanceReferenceFilesAvailable(int runtmNdx, DumpFileMoniker moniker, out string error) { error = null; try { string[] fileList = new string[(int)RefFile.Count]; fileList[0] = moniker.GetFilePath(runtmNdx, Constants.MapRefFwdOffsetsFilePostfix); fileList[1] = moniker.GetFilePath(runtmNdx, Constants.MapFwdRefsFilePostfix); fileList[2] = moniker.GetFilePath(runtmNdx, Constants.MapRefBwdOffsetsFilePostfix); fileList[3] = moniker.GetFilePath(runtmNdx, Constants.MapBwdRefsFilePostfix); for (int i = 0, icnt = fileList.Length; i < icnt; ++i) { if (!File.Exists(fileList[i])) { return(false); } } return(true); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(false); } }
public IndexProxy(ClrtDump dump, ulong[] instances, int[] instanceTypes, string[] typeNames, ClrElementKind[] typeKinds, ClrtRootInfo roots, DumpFileMoniker fileMoniker) { Dump = dump; Instances = instances; InstanceTypes = instanceTypes; TypeNames = typeNames; TypeKinds = typeKinds; Roots = roots; FileMoniker = fileMoniker; }
public InstanceReferences(ulong[] instances, int runtmNdx, DumpFileMoniker moniker) { _instances = instances; _fileList = new string[(int)RefFile.Count]; _fileList[0] = moniker.GetFilePath(runtmNdx, Constants.MapRefFwdOffsetsFilePostfix); _fileList[1] = moniker.GetFilePath(runtmNdx, Constants.MapFwdRefsFilePostfix); _fileList[2] = moniker.GetFilePath(runtmNdx, Constants.MapRefBwdOffsetsFilePostfix); _fileList[3] = moniker.GetFilePath(runtmNdx, Constants.MapBwdRefsFilePostfix); _maps = new MemoryMappedFile[(int)RefFile.Count]; _views = new MemoryMappedViewAccessor[(int)RefFile.Count]; _readers = new BinaryReader[(int)RefFile.Count]; _readers = new BinaryReader[(int)RefFile.Count]; }
/// <summary> /// /// </summary> /// <param name="rtmNdx"></param> /// <param name="segments"></param> /// <param name="instances"></param> /// <param name="sizes"></param> /// <param name="fileMoniker"></param> /// <param name="hasUnrootedInfo"></param> /// <returns></returns> public static Tuple <int[], ulong[], int[], ulong[], int[], ulong[]> GetTotalGenerationDistributions(int rtmNdx, ClrtSegment[] segments, ulong[] instances, uint[] sizes, DumpFileMoniker fileMoniker, bool hasUnrootedInfo) { var genTotalCount = new int[4]; var genTotalSize = new ulong[4]; var genTotalUnrootedCount = new int[4]; var genTotalUnrootedSize = new ulong[4]; var freeTotalGenCount = new int[4]; var freeTotalGenSize = new ulong[4]; // check unrooted // if (!hasUnrootedInfo) { for (int i = 0, icnt = instances.Length; i < icnt; ++i) { if (!Utils.IsRooted(instances[i])) { var addr = instances[i]; var seg = ClrtSegment.FindSegment(segments, addr); if (seg == null) { continue; } var gen = seg.GetGeneration(addr); if (gen == Generation.Uknown) { continue; } seg.IncUnrooted(gen, sizes[i]); } } string error; ClrtSegment.DumpSegments(fileMoniker.GetFilePath(rtmNdx, Constants.MapSegmentInfoFilePostfix), segments, out error, true); } for (int i = 0, icnt = segments.Length; i < icnt; ++i) { var seg = segments[i]; if (seg.Large) { genTotalCount[(int)Generation.Large] += seg.Gen0Count; genTotalSize[(int)Generation.Large] += seg.Gen0Size; freeTotalGenCount[(int)Generation.Large] += seg.Gen0FreeCount; freeTotalGenSize[(int)Generation.Large] += seg.Gen0FreeSize; genTotalUnrootedCount[(int)Generation.Large] += seg.Gen0UnrootedCount; genTotalSize[(int)Generation.Large] += seg.Gen0UnrootedSize; continue; } genTotalCount[(int)Generation.Gen0] += seg.Gen0Count; genTotalSize[(int)Generation.Gen0] += seg.Gen0Size; genTotalUnrootedCount[(int)Generation.Gen0] += seg.Gen0UnrootedCount; genTotalUnrootedSize[(int)Generation.Gen0] += seg.Gen0UnrootedSize; freeTotalGenCount[(int)Generation.Gen0] += seg.Gen0FreeCount; freeTotalGenSize[(int)Generation.Gen0] += seg.Gen0FreeSize; genTotalCount[(int)Generation.Gen1] += seg.Gen1Count; genTotalSize[(int)Generation.Gen1] += seg.Gen1Size; genTotalUnrootedCount[(int)Generation.Gen1] += seg.Gen1UnrootedCount; genTotalUnrootedSize[(int)Generation.Gen1] += seg.Gen1UnrootedSize; freeTotalGenCount[(int)Generation.Gen1] += seg.Gen1FreeCount; freeTotalGenSize[(int)Generation.Gen1] += seg.Gen1FreeSize; genTotalCount[(int)Generation.Gen2] += seg.Gen2Count; genTotalSize[(int)Generation.Gen2] += seg.Gen2Size; genTotalUnrootedCount[(int)Generation.Gen2] += seg.Gen2UnrootedCount; genTotalUnrootedSize[(int)Generation.Gen2] += seg.Gen2UnrootedSize; freeTotalGenCount[(int)Generation.Gen2] += seg.Gen2FreeCount; freeTotalGenSize[(int)Generation.Gen2] += seg.Gen2FreeSize; } return(Tuple.Create(genTotalCount, genTotalSize, freeTotalGenCount, freeTotalGenSize, genTotalUnrootedCount, genTotalUnrootedSize)); }
public static bool FinalyzerAddressFixup(int rtm, ulong[] finalyzerAddresses, DumpFileMoniker fileMoniker, out string error) { error = null; FileWriter fw = null; try { var path = fileMoniker.GetFilePath(rtm, Constants.MapRootsInfoFilePostfix); fw = new FileWriter(path, FileMode.Open, FileAccess.Write, FileShare.None); fw.Seek(sizeof(int), SeekOrigin.Begin); for (int i = 0, icnt = finalyzerAddresses.Length; i < icnt; ++i) { fw.Write(finalyzerAddresses[i]); } return(true); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(false); } finally { fw?.Dispose(); } }
public static ValueTuple <ulong[], ulong[]> SetupRootAddresses(int rtm, ClrHeap heap, string[] typeNames, StringIdDct strIds, DumpFileMoniker fileMoniker, out string error) { error = null; try { var roots = heap.EnumerateRoots(true); var objSet = new HashSet <ulong>(new Utils.AddressEqualityComparer()); var finlSet = new HashSet <ulong>(new Utils.AddressEqualityComparer()); List <ClrtRoot>[] ourRoots = new List <ClrtRoot> [(int)GCRootKind.Max + 1]; for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i) { ourRoots[i] = new List <ClrtRoot>(256); } foreach (var root in roots) { ulong rootAddr = root.Address; ulong objAddr = root.Object; int typeId; string typeName; if (root.Type == null) { var clrType = heap.GetObjectType(objAddr); typeName = clrType == null ? Constants.UnknownName : clrType.Name; } else { typeName = root.Type.Name; } typeId = Array.BinarySearch(typeNames, typeName, StringComparer.Ordinal); if (typeId < 0) { typeId = Constants.InvalidIndex; } string rootName = root.Name == null ? Constants.UnknownName : root.Name; var nameId = strIds.JustGetId(rootName); var clrtRoot = new ClrtRoot(root, typeId, nameId); ourRoots[(int)root.Kind].Add(clrtRoot); if (objAddr != 0UL) { if (root.Kind == GCRootKind.Finalizer) { objAddr = Utils.SetAsFinalizer(objAddr); finlSet.Add(objAddr); } else { objAddr = Utils.SetRooted(objAddr); objSet.Add(objAddr); } } if (rootAddr != 0UL) { if (root.Kind == GCRootKind.Finalizer) { rootAddr = Utils.SetAsFinalizer(rootAddr); finlSet.Add(rootAddr); } else { rootAddr = Utils.SetRooted(rootAddr); objSet.Add(rootAddr); } } } // root infos TODO JRD -- Fix this // var rootCmp = new ClrtRootObjCmp(); for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i) { ourRoots[i].Sort(rootCmp); } // unique addresses // var addrAry = objSet.ToArray(); Array.Sort(addrAry, new Utils.AddressComparison()); var finlAry = finlSet.ToArray(); Array.Sort(finlAry, new Utils.AddressComparison()); if (!ClrtRootInfo.Save(rtm, ourRoots, fileMoniker, out error)) { return(new ValueTuple <ulong[], ulong[]>(null, null)); } return(new ValueTuple <ulong[], ulong[]>(addrAry, finlAry)); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(new ValueTuple <ulong[], ulong[]>(null, null)); } }
///// <summary> ///// We are persisting string statistics (System.String) when they are asked for, ///// so second request might be served faster. ///// </summary> ///// <param name="runtimeIndex">Mostly we have just one runtime [0].</param> ///// <param name="dumpPath">Process dump file.</param> ///// <returns>True if we have files with string information.</returns> //public static bool StringStatsFilesExist(int runtimeIndex, string dumpPath) //{ // var strDatPath = DumpFileMoniker.GetRuntimeFilePath(runtimeIndex, dumpPath, Constants.MapDumpStringsInfoPostfix); // if (!File.Exists(strDatPath)) return false; // return true; //} public static StringStats GetStringsInfoFromFiles(int runtimeIndex, string dumpPath, out string error) { error = null; string[] strings = null; StringStats strStats = null; BinaryReader br = null; try { string dataPath = DumpFileMoniker.GetRuntimeFilePath(runtimeIndex, dumpPath, Constants.MapDumpStringsInfoPostfix); br = new BinaryReader(File.Open(dataPath, FileMode.Open)); int totalStringCount = br.ReadInt32(); long totalStringSize = br.ReadInt64(); long totalUniqueSize = br.ReadInt64(); long strOffsetOffset = br.ReadInt64(); int uniqueStrCount = br.ReadInt32(); uint[] sizes = new uint[uniqueStrCount]; int[] counts = new int[uniqueStrCount]; ulong[][] adddresses = new ulong[uniqueStrCount][]; for (int i = 0; i < uniqueStrCount; ++i) { int strInstCount = br.ReadInt32(); uint strSize = br.ReadUInt32(); counts[i] = strInstCount; sizes[i] = strSize; adddresses[i] = new ulong[strInstCount]; for (int j = 0; j < strInstCount; ++j) { adddresses[i][j] = br.ReadUInt64(); } } strings = new string[uniqueStrCount]; long[] addroffs = new long[uniqueStrCount]; for (int i = 0; i < uniqueStrCount; ++i) { addroffs[i] = br.ReadInt64(); strings[i] = br.ReadString(); } br.Close(); br = null; strStats = new StringStats() { _strings = strings, _sizes = sizes, _counts = counts, _adddresses = adddresses, _totalSize = totalStringSize, _totalUniqueSize = totalUniqueSize, _totalCount = totalStringCount }; } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(null); } finally { br?.Close(); } return(strStats); }
public static DisplayableFinalizerQueue GetDisplayableFinalizerQueue(ulong[] heapInstances, ClrtRoot[] data, ulong[] instances, string[] typeNames, DumpFileMoniker fileMoniker) { if (data == null || data.Length < 1) { return(new DisplayableFinalizerQueue()); // empty } int prevTypeId = data[0].TypeId; List <FinalizerQueueDisplayableItem> items = new List <FinalizerQueueDisplayableItem>(1024); List <KeyValuePair <int, int> > lst = new List <KeyValuePair <int, int> >(256); List <ulong> typeAddresses = new List <ulong>(1024); int totalCount = 0; int totalUnrootedCount = 0; int typeCount = 0; int notRooted = 0; for (int i = 0, icnt = data.Length; i < icnt; ++i) { if (prevTypeId != data[i].TypeId) { string typeName = prevTypeId < 0 ? Constants.UnknownTypeName : typeNames[prevTypeId]; var item = new FinalizerQueueDisplayableItem(typeCount, notRooted, typeName, typeAddresses.ToArray()); items.Add(item); typeCount = 0; notRooted = 0; lst.Clear(); typeAddresses.Clear(); prevTypeId = data[i].TypeId; } int instNdx = Utils.AddressSearch(instances, data[i].Object); ulong addr = instNdx < 0 ? data[i].Object : instances[instNdx]; int heapIndx = Utils.AddressSearch(heapInstances, addr); if (heapIndx >= 0) { addr = heapInstances[heapIndx]; } typeAddresses.Add(addr); ++typeCount; ++totalCount; if (!Utils.IsRooted(addr)) { ++notRooted; ++totalUnrootedCount; } } if (typeCount > 0) { string typeName = prevTypeId < 0 ? Constants.UnknownTypeName : typeNames[prevTypeId]; var item = new FinalizerQueueDisplayableItem(typeCount, notRooted, typeName, typeAddresses.ToArray()); items.Add(item); } var itemsAry = items.ToArray(); Array.Sort(itemsAry, new FinalizerQueueDisplayableItemCmp(2, true)); return(new DisplayableFinalizerQueue(items.ToArray(), totalCount, totalUnrootedCount, fileMoniker)); }
public DisplayableFinalizerQueue(FinalizerQueueDisplayableItem[] items, int totalCount, int totalUnrootedCount, DumpFileMoniker fileMoniker) { Items = items; TotalCount = totalCount; TotalUnrootedCount = totalUnrootedCount; Information = "Crash dump: " + fileMoniker.DumpFileName + Environment.NewLine + "Total count: " + Utils.CountString(totalCount) + Environment.NewLine + "Total unrooted count: " + Utils.CountString(totalUnrootedCount); }
public static string GetOutputPathWithDumpPrefix(DumpFileMoniker monkr, string fileName) { return(GetOuputFolder(monkr.Path) + System.IO.Path.DirectorySeparatorChar + monkr.FileName + "." + fileName); }
public static bool GetConfigSettings(out string error) { error = null; DacFolder = string.Empty; DumpsFolder = string.Empty; ProcDumpFolder = string.Empty; RecentIndexList = new List <string>(); RecentAdhocList = new List <string>(); StringBuilder errors = StringBuilderCache.Acquire(256); try { #if DEBUG //string myfolder = @"D:\Jerzy\WinDbgStuff\MDRDesk\"; string myfolder = @"C:\WinDbgStuff\MDRDesk\"; #else string myfolder = DumpFileMoniker.MyFolder; #endif string installFolder = DumpFileMoniker.GetParentFolder(myfolder); var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var appSettings = (AppSettingsSection)config.GetSection("appSettings"); if (appSettings.Settings.Count != 0) { foreach (string key in appSettings.Settings.AllKeys) { var ky = key.ToLower(); if (Utils.SameStrings(ky, "dacfolder")) { var folder = appSettings.Settings[key].Value.Trim(); if (Directory.Exists(folder)) { DacFolder = folder; } string path = installFolder + @"mscordacwks"; if (Directory.Exists(path)) { DacFolder = path; } else { errors.AppendLine("Dac folder does not exist: " + folder); } } else if (Utils.SameStrings(ky, "mapfolder")) { var folder = appSettings.Settings[key].Value.Trim(); if (Directory.Exists(folder)) { DumpsFolder = folder; } else { // if dumps folder exists, add it to config string path = installFolder + @"dumps"; if (Directory.Exists(path)) { DumpsFolder = path; } else { errors.AppendLine("Dumps folder does not exist: " + folder); } } } else if (Utils.SameStrings(ky, "procdumpfolder")) { var folder = appSettings.Settings[key].Value.Trim(); if (Directory.Exists(folder)) { ProcDumpFolder = folder; } else { ProcDumpFolder = ""; } // else errors.AppendLine("procdum.exe folder does not exist: " + folder); } else if (Utils.SameStrings(ky, "helpfolder")) { var folder = appSettings.Settings[key].Value.Trim(); if (Directory.Exists(folder)) { HelpFolder = folder; } else { string path = myfolder + @"Documentation"; if (Directory.Exists(path)) { HelpFolder = myfolder; } else { errors.AppendLine("Documentation folder does not exist: " + folder); } } } else if (Utils.SameStrings(ky, "refbuilder")) { var val = appSettings.Settings[key].Value.Trim(); CppRefBuilder = string.Compare(val, "c++", StringComparison.OrdinalIgnoreCase) == 0; } else if (Utils.SameStrings(ky, "refreader")) { var val = appSettings.Settings[key].Value.Trim(); MapRefReader = string.Compare(val, "map", StringComparison.OrdinalIgnoreCase) == 0; } else if (Utils.SameStrings(ky, "wnddbgfolder")) { var folder = appSettings.Settings[key].Value.Trim(); if (Directory.Exists(folder)) { WndDbgFolder = folder; } //else errors.AppendLine("help folder does not exist: " + folder); } else if (Utils.SameStrings(ky, "graphproxy")) { GraphDbJar = appSettings.Settings[key].Value.Trim(); } else if (Utils.SameStrings(ky, "graphport")) { GraphPort = Int32.Parse(appSettings.Settings[key].Value.Trim()); } else if (Utils.SameStrings(ky, "recentindices")) { GetSemicolonDelimitedFolderPaths(RecentIndexList, appSettings.Settings[key].Value); } else if (Utils.SameStrings(ky, "recentadhocs")) { GetSemicolonDelimitedFilePaths(RecentAdhocList, appSettings.Settings[key].Value); } else if (Utils.SameStrings(ky, "typedisplaymode")) { TypesDisplayMode = appSettings.Settings[key].Value.Trim(); } } } else { error = "The appSettings section is empty."; } if (errors.Length > 0) { return(false); } return(true); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(false); } finally { if (errors.Length > 0) { error = "Initialization Failed" + Constants.HeavyGreekCrossPadded + "Setup.GetConfigSettings()" + Constants.HeavyGreekCrossPadded + "MDRDesk application config file is invalid." + Environment.NewLine + "See details." + Constants.HeavyGreekCrossPadded + StringBuilderCache.GetStringAndRelease(errors); } else { StringBuilderCache.Release(errors); } } }