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> /// Collect roots information. /// </summary> /// <param name="heap">Clr heap of current runtime.</param> /// <param name="instances">Instance addresses.</param> /// <param name="types">Instance types.</param> /// <param name="idDct">String id dictionary.</param> /// <returns>Roots info, <see cref="ClrtRoots"/></returns> public static ClrtRoots GetRootInfos(ClrHeap heap, ulong[] instances, int[] types, ulong[] rootAddresses, StringIdDct idDct) { var rootDct = new SortedDictionary <ulong, List <ClrtRoot> >(); var finalizeQue = new List <ulong>(1024 * 1024); var finalizeQueInstIds = new List <int>(1024 * 1024); List <ClrRoot> lstNotFoundObject = new List <ClrRoot>(); List <ClrtRoot> lstRoots = new List <ClrtRoot>(1024 * 64); foreach (var root in heap.EnumerateRoots(true)) { var rootObj = root.Object; if (root.Kind == GCRootKind.Finalizer) { finalizeQue.Add(rootObj); var obj = Utils.AddressSearch(instances, rootObj); finalizeQueInstIds.Add(obj); continue; } var rootAddr = root.Address; List <ClrtRoot> lst; if (rootDct.TryGetValue(rootAddr, out lst)) { int i = 0; int icnt = lst.Count; var rkind = root.Kind; for (; i < icnt; ++i) { if (rootObj == lst[i].Object && rkind == ClrtRoot.GetGCRootKind(lst[i].RootKind)) { break; } } if (i == icnt) { var rname = root.Name ?? Constants.NullName; var rnameId = idDct.JustGetId(rname); var obj = Utils.AddressSearch(instances, rootObj); if (obj < 0) { lstNotFoundObject.Add(root); } var typeId = obj < 0 ? Constants.InvalidIndex : types[obj]; var clrtRoot = new ClrtRoot(root, typeId, rnameId, Constants.InvalidIndex, Constants.InvalidThreadId, Constants.InvalidIndex); lst.Add(clrtRoot); lstRoots.Add(clrtRoot); } } else { var rname = root.Name ?? Constants.NullName; var rnameId = idDct.JustGetId(rname); var obj = Utils.AddressSearch(instances, rootObj); if (obj < 0) { lstNotFoundObject.Add(root); } var typeId = obj < 0 ? Constants.InvalidIndex : types[obj]; var clrtRoot = new ClrtRoot(root, typeId, rnameId, Constants.InvalidIndex, Constants.InvalidThreadId, Constants.InvalidIndex); rootDct.Add(rootAddr, new List <ClrtRoot>() { clrtRoot }); lstRoots.Add(clrtRoot); } } var rootAry = lstRoots.ToArray(); lstRoots.Clear(); lstRoots = null; ulong[] sortedObjs; int[] kindOffsets; int[] objMap; ulong[] sortedAddrs; int[] addrMap; SortRoots(rootAry, out kindOffsets, out sortedAddrs, out addrMap, out sortedObjs, out objMap); var finQueAry = finalizeQue.ToArray(); var finQueInstIdsAry = finalizeQueInstIds.ToArray(); Array.Sort(finQueAry, finQueInstIdsAry); return(new ClrtRoots(rootAry, kindOffsets, sortedAddrs, addrMap, sortedObjs, objMap, finQueAry, finQueInstIdsAry)); }
public static ValueTuple <ulong[], int, int> GetFlaggedRoots(ClrHeap heap, string[] typeNames, StringIdDct strIds, string rootPath, out string error) { error = null; try { Dictionary <ulong, ulong> dct = new Dictionary <ulong, ulong>(1024 * 512); 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); } var roots = heap.EnumerateRoots(true); //ulong savedAddr; int finalizerCount = 0; int rootCount = 0; foreach (var root in roots) { ulong rootAddr = root.Address; ulong objAddr = root.Object; ulong flaggedRootAddr = rootAddr; ulong flaggedObjAddr = objAddr; 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); switch (root.Kind) { case GCRootKind.Finalizer: ++finalizerCount; if (objAddr != 0UL) { flaggedObjAddr = Utils.SetAsFinalizer(flaggedObjAddr); } if (rootAddr != 0UL) { flaggedRootAddr = Utils.SetAsFinalizer(flaggedRootAddr); } break; case GCRootKind.LocalVar: if (objAddr != 0UL) { flaggedObjAddr = Utils.SetAsLocal(flaggedObjAddr); } if (rootAddr != 0UL) { flaggedRootAddr = Utils.SetAsLocal(flaggedRootAddr); } break; default: ++rootCount; flaggedObjAddr = Utils.SetAsRoot(flaggedObjAddr); if (objAddr != 0UL) { flaggedObjAddr = Utils.SetAsRoot(flaggedObjAddr); } if (rootAddr != 0UL) { flaggedRootAddr = Utils.SetAsRoot(flaggedRootAddr); } break; } SetFlaggedAddress(dct, objAddr, flaggedObjAddr); SetFlaggedAddress(dct, rootAddr, flaggedRootAddr); } var rootCmp = new ClrtRootObjCmp(); for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i) { ourRoots[i].Sort(rootCmp); } Save(rootPath, ourRoots, out error); ulong[] rootAddrs = dct.Values.ToArray(); Utils.SortAddresses(rootAddrs); return(rootAddrs, rootCount, finalizerCount); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(null, 0, 0); } }