public static ulong FindOwner(ulong address, ClrDump clrDump, ClrType delegateType, ClrType arrayObjType, HashSet <ulong> visited) { if (visited.Contains(address)) { return(0); } var type = clrDump.GetObjectType(address); if (type == null) { return(0); } if (type != arrayObjType && (type.BaseType == null || type.BaseType != delegateType)) { return(address); } visited.Add(address); foreach (var newAddress in clrDump.GetReferers(address)) { var owner = FindOwner(newAddress, clrDump, delegateType, arrayObjType, visited); if (owner != 0) { return(owner); } } return(0); }
public InstanceInformation(ClrDump clrDump, ulong address) { ClrDump = clrDump; Address = address; ClrType = ClrDump.GetObjectType(Address); if (ClrType != null) { TypeName = ClrType.Name; } }
public static List <RootPathInformation> AnalyzeRootPath(MessageBus msgBus, ClrDumpObject clrDumpObject) { ClrDump clrDump = clrDumpObject.ClrDump; ulong address = clrDumpObject.Address; CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analysing Root Path...", token); if (token.IsCancellationRequested) { msgBus.EndTask("Root Path analysis: cancelled."); return(null); } msgBus.Status("Analysing Root Path: collecting root instances..."); var roots = new HashSet <ulong>(clrDump.EnumerateClrRoots.Select(clrRoot => clrRoot.Object)); if (logger.IsDebugEnabled) { logger.Debug("Roots: " + Str(roots)); } List <ulong> bestPath = null; var currentPath = new List <ulong>(); bool result = FindShortestPath(address, currentPath, ref bestPath, clrDump.GetReferers, roots.Contains, new Dictionary <ulong, List <ulong> >()); if (!result) { currentPath = new List <ulong>(); FindShortestPath(address, currentPath, ref bestPath, clrDump.GetReferers, (addr) => !clrDump.HasReferers(addr), new Dictionary <ulong, List <ulong> >()); } List <RootPathInformation> path = new List <RootPathInformation>(); ulong prevAddress = address; if (bestPath != null) { foreach (var refAddress in bestPath) { var refClrDumpObject = new ClrDumpObject(clrDump, clrDump.GetObjectType(refAddress), refAddress); var fieldName = refAddress == address ? " - " : clrDump.GetFieldNameReference(prevAddress, refAddress); fieldName = TypeHelpers.RealName(fieldName); path.Add(new RootPathInformation(refClrDumpObject, fieldName)); prevAddress = refAddress; } msgBus.EndTask("Root Path found."); } else { msgBus.EndTask("Root Path NOT found."); } return(path); }
private void OnCellClick(object sender, CellClickEventArgs e) { if (e.ClickCount == 2 && e.Model != null) { var arrayInstance = dlvArrays.SelectedObject <ArrayInstanceInformation>(); if (arrayInstance != null) { var address = arrayInstance.Address; var type = ClrDump.GetObjectType(address); if (type == null) { Log($"Can't find type for instance: {address:X}", LogLevelType.Error); return; } var clrDumpObject = new ClrDumpObject(ClrDump, type, address); InstanceDetailsCommand.Display(this, clrDumpObject); } } }
public static ulong FindOwner(ulong address, ClrDump clrDump, ClrType delegateType, ClrType arrayObjType, HashSet<ulong> visited) { if( visited.Contains(address)) { return 0; } var type = clrDump.GetObjectType(address); if (type == null) { return 0; } if( type != arrayObjType && (type.BaseType == null || type.BaseType != delegateType ) ) { return address; } visited.Add(address); var refs = clrDump.GetReferers(address); foreach(var newAddress in refs) { var owner = FindOwner(newAddress, clrDump, delegateType, arrayObjType, visited); if( owner != 0) { return owner; } } return 0; }
public static List<LoneTargetInformation> GetLoneTargetInformations(ClrDump clrDump) { CancellationTokenSource token = new CancellationTokenSource(); clrDump.MessageBus.BeginTask("Analyzing lone targets...", token); Dictionary<ClrObject, ClrObject> loneTargetAddresses = new Dictionary<ClrObject, ClrObject>(); // For each instance of every delegate types // let's find all the target objects // and select those with only referenced once var types = GetDelegateTypes(clrDump); foreach(var type in types) { clrDump.MessageBus.Status($"Analyzing delegate type: {type.Name}"); if (token.IsCancellationRequested) { break; } int n = 0; foreach (var address in clrDump.EnumerateInstances(type)) { if (n++ % 128 == 0) { clrDump.MessageBus.Status($"Analyzing delegate type: {type.Name}, instance #{n:###,###,###,##0}"); } var handlerObject = new ClrObject(address, type); foreach(var subHandlerObject in EnumerateHandlers(handlerObject)) { if (token.IsCancellationRequested) { break; } var target = subHandlerObject[TargetFieldName]; int count = clrDump.CountReferers(target.Address); if( count == 1) { loneTargetAddresses[target] = subHandlerObject; } } } } List<LoneTargetInformation> loneTargets = new List<LoneTargetInformation>(); // foreach lone target, in its reference tree, we try to find the first // object that is not a delegate type or an array of object (ie invocationList) var delegateType = clrDump.GetClrType(typeof(MulticastDelegate).FullName); var arrayObjType = clrDump.GetClrType(typeof(object[]).FullName); HashSet<ulong> visited = new HashSet<ulong>(); foreach (var kvp in loneTargetAddresses) { var loneTarget = kvp.Key; var handler = kvp.Value; var methInfo = GetDelegateMethod(clrDump, handler, loneTarget); visited.Clear(); ulong ownerAddress = FindOwner(handler.Address, clrDump, delegateType, arrayObjType, visited); ClrObject owner = new ClrObject(ownerAddress, clrDump.GetObjectType(ownerAddress)); var loneTargetInformation = new LoneTargetInformation(clrDump, loneTarget, methInfo, owner); loneTargets.Add(loneTargetInformation); } string status = token.IsCancellationRequested ? "cancelled" : "done"; clrDump.MessageBus.EndTask($"Analyzing lone targets: {status}. Found: {loneTargets.Count}"); return loneTargets; }
public static List <LoneTargetInformation> GetLoneTargetInformations(ClrDump clrDump) { CancellationTokenSource token = new CancellationTokenSource(); clrDump.MessageBus.BeginTask("Analyzing lone targets...", token); Dictionary <ClrObject, ClrObject> loneTargetAddresses = new Dictionary <ClrObject, ClrObject>(); // For each instance of every delegate types // let's find all the target objects // and select those with only referenced once foreach (var type in GetDelegateTypes(clrDump)) { clrDump.MessageBus.Status($"Analyzing delegate type: {type.Name}"); if (token.IsCancellationRequested) { break; } int n = 0; foreach (var address in clrDump.EnumerateInstances(type)) { if (n++ % 128 == 0) { clrDump.MessageBus.Status($"Analyzing delegate type: {type.Name}, instance #{n:###,###,###,##0}"); } var handlerObject = new ClrObject(address, type); foreach (var subHandlerObject in EnumerateHandlers(handlerObject)) { if (token.IsCancellationRequested) { break; } var target = subHandlerObject[TargetFieldName]; int count = clrDump.CountReferers(target.Address); if (count == 1) { loneTargetAddresses[target] = subHandlerObject; } } } } List <LoneTargetInformation> loneTargets = new List <LoneTargetInformation>(); // foreach lone target, in its reference tree, we try to find the first // object that is not a delegate type or an array of object (ie invocationList) var delegateType = clrDump.GetClrType(typeof(MulticastDelegate).FullName); var arrayObjType = clrDump.GetClrType(typeof(object[]).FullName); HashSet <ulong> visited = new HashSet <ulong>(); foreach (var kvp in loneTargetAddresses) { var loneTarget = kvp.Key; var handler = kvp.Value; var methInfo = GetDelegateMethod(clrDump, handler, loneTarget); visited.Clear(); ulong ownerAddress = FindOwner(handler.Address, clrDump, delegateType, arrayObjType, visited); ClrObject owner = new ClrObject(ownerAddress, clrDump.GetObjectType(ownerAddress)); var loneTargetInformation = new LoneTargetInformation(clrDump, loneTarget, methInfo, owner); loneTargets.Add(loneTargetInformation); } string status = token.IsCancellationRequested ? "cancelled" : "done"; clrDump.MessageBus.EndTask($"Analyzing lone targets: {status}. Found: {loneTargets.Count}"); return(loneTargets); }
public static List <ReferersInformation> AnalyzeReferers(MessageBus msgBus, ClrDump clrDump, HashSet <ulong> addresses) { var referers = new List <ReferersInformation>(); var dicoByRefererType = new Dictionary <ClrType, Dictionary <string, ReferersInformation> >(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing referers...", token); Application.DoEvents(); // todo: avoid this call to Application.DoEvents() int count = addresses.Count; int i = 0; foreach (var address in addresses) { i++; if (token.IsCancellationRequested) { msgBus.EndTask("Referers analyze: cancelled."); return(referers); } if (i % 1024 == 0) { msgBus.Status($"Analyzing referers: {(double)i/count:p2}, {i:###,###,###,##0} / {count:###,###,###,##0}..."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() } foreach (var refererAddress in clrDump.EnumerateReferers(address)) { var type = clrDump.GetObjectType(refererAddress); string field; if (type.IsArray) { field = "[ x ]"; } else { field = clrDump.GetFieldNameReference(address, refererAddress); field = TypeHelpers.RealName(field); } Dictionary <string, ReferersInformation> dicoRefInfoByFieldName; if (!dicoByRefererType.TryGetValue(type, out dicoRefInfoByFieldName)) { dicoRefInfoByFieldName = new Dictionary <string, ReferersInformation>(); dicoByRefererType[type] = dicoRefInfoByFieldName; } ReferersInformation referersInformation; if (!dicoRefInfoByFieldName.TryGetValue(field, out referersInformation)) { referersInformation = new ReferersInformation(clrDump, type, field, msgBus, count); dicoRefInfoByFieldName[field] = referersInformation; } referersInformation.References.Add(address); referersInformation.Instances.Add(refererAddress); } } foreach (var kvpType in dicoByRefererType) { var type = kvpType.Key; foreach (var kvpField in kvpType.Value) { var refInfo = kvpField.Value; referers.Add(refInfo); refInfo.Init(); } } msgBus.EndTask("Referers analyzed."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() return(referers); }
public static List<ReferersInformation> AnalyzeReferers(MessageBus msgBus, ClrDump clrDump, HashSet<ulong> addresses) { var referers = new List<ReferersInformation>(); var dicoByRefererType = new Dictionary<ClrType, Dictionary<string, ReferersInformation>>(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing referers...", token); Application.DoEvents(); // todo: avoid this call to Application.DoEvents() int count = addresses.Count; int i = 0; foreach(var address in addresses) { i++; if( token.IsCancellationRequested) { msgBus.EndTask("Referers analyze: cancelled."); return referers; } if ( i % 1024 == 0) { msgBus.Status($"Analyzing referers: {(double)i/count:p2}, {i:###,###,###,##0} / {count:###,###,###,##0}..."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() } foreach( var refererAddress in clrDump.EnumerateReferers(address)) { var type = clrDump.GetObjectType(refererAddress); string field; if (type.IsArray) { field = "[ x ]"; } else { field = clrDump.GetFieldNameReference(address, refererAddress); field = TypeHelpers.RealName(field); } Dictionary<string, ReferersInformation> dicoRefInfoByFieldName; if( ! dicoByRefererType.TryGetValue(type, out dicoRefInfoByFieldName)) { dicoRefInfoByFieldName = new Dictionary<string, ReferersInformation>(); dicoByRefererType[type] = dicoRefInfoByFieldName; } ReferersInformation referersInformation; if ( ! dicoRefInfoByFieldName.TryGetValue(field, out referersInformation)) { referersInformation = new ReferersInformation(clrDump, type, field, msgBus, count); dicoRefInfoByFieldName[field] = referersInformation; } referersInformation.References.Add(address); referersInformation.Instances.Add(refererAddress); } } foreach(var kvpType in dicoByRefererType) { var type = kvpType.Key; foreach(var kvpField in kvpType.Value) { var refInfo = kvpField.Value; referers.Add(refInfo); refInfo.Init(); } } msgBus.EndTask("Referers analyzed."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() return referers; }