public static long CountTargets(ClrDump clrDump, ClrType clrType) { long count = 0; var targetField = clrType.GetFieldByName(TargetFieldName); var invocCountField = clrType.GetFieldByName(InvocationCountFieldName); foreach (ulong address in clrDump.EnumerateInstances(clrType)) { count += CountTargets(address, clrType, targetField, invocCountField); } return(count); }
internal static List <ArraysInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { CancellationTokenSource token = new CancellationTokenSource(); var arrays = new List <ArraysInformation>(); msgBus.BeginTask("Analyzing arrays...", token); int n = 0; clrDump.Run(() => { var arrayTypes = clrDump.AllTypes.Where(t => t.IsArray); int nbArrayType = arrayTypes.Count(); foreach (var type in arrayTypes) { string typeName = type.Name; msgBus.Status($"Analyzing array type: {typeName} ({n:###,###,###,##0}/{nbArrayType:###,###,###,##0})"); if (token.IsCancellationRequested) { return; } n++; ulong nbInstances = 0; ulong totalSize = 0; ulong totalLength = 0; ulong maxLength = 0; foreach (var address in clrDump.EnumerateInstances(type)) { nbInstances++; var length = (ulong)(type.GetArrayLength(address)); maxLength = Math.Max(maxLength, length); totalSize += type.GetSize(address); totalLength += length; if (nbInstances % 512 == 0) { msgBus.Status($"Analyzing array: #{nbInstances:###,###,###,##0} for type: {typeName}"); if (token.IsCancellationRequested) { return; } } } arrays.Add(new ArraysInformation(new ClrDumpType(clrDump, type), nbInstances, totalLength, maxLength, totalSize)); } }); msgBus.EndTask($"Arrays analyzed. Types: {n:###,###,###,##0}"); return(arrays); }
internal static List <StringInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { var stringType = clrDump.GetClrType(typeof(string).FullName); var stringInstances = clrDump.EnumerateInstances(stringType); int nbStrings = clrDump.CountInstances(stringType); Dictionary <string, List <ulong> > result = new Dictionary <string, List <ulong> >(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing strings...", token); int n = 0; clrDump.Run(() => { foreach (var address in stringInstances) { if (token.IsCancellationRequested) { return; } n++; var value = SimpleValueHelper.GetSimpleValue(address, stringType, false) as string; if (value == null) { continue; } List <ulong> addresses; if (!result.TryGetValue(value, out addresses)) { addresses = new List <ulong>(); result[value] = addresses; } addresses.Add(address); if (n % 1024 == 0) { float pct = (float)n / nbStrings; msgBus.Status($"Analyzing strings: {pct:p2}, n= {n:###,###,###,##0} / {nbStrings:###,###,###,##0}"); } } }); msgBus.EndTask($"Strings analyzed. Instances: {n:###,###,###,##0}, unique values: {result.Count:###,###,###,##0}"); var strings = result.Select(kvp => new StringInformation(kvp.Key, kvp.Value)).ToList(); return(strings); }
internal static List<ArraysInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { CancellationTokenSource token = new CancellationTokenSource(); var arrays = new List<ArraysInformation>(); msgBus.BeginTask("Analyzing arrays...", token); int n = 0; clrDump.Run(() => { var arrayTypes = clrDump.AllTypes.Where(t => t.IsArray); int nbArrayType = arrayTypes.Count(); foreach (var type in arrayTypes) { string typeName = type.Name; msgBus.Status($"Analyzing array type: {typeName} ({n:###,###,###,##0}/{nbArrayType:###,###,###,##0})"); if ( token.IsCancellationRequested ) { return; } n++; ulong nbInstances = 0; ulong totalSize = 0; ulong totalLength = 0; ulong maxLength = 0; foreach (var address in clrDump.EnumerateInstances(type)) { nbInstances++; var length = (ulong)(type.GetArrayLength(address)); maxLength = Math.Max(maxLength, length); totalSize += type.GetSize(address); totalLength += length; if (nbInstances % 512 == 0) { msgBus.Status($"Analyzing array: #{nbInstances:###,###,###,##0} for type: {typeName}"); if (token.IsCancellationRequested) { return; } } } arrays.Add(new ArraysInformation(new ClrDumpType(clrDump, type), nbInstances, totalLength, maxLength, totalSize)); } }); msgBus.EndTask($"Arrays analyzed. Types: {n:###,###,###,##0}"); return arrays; }
internal static List<StringInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { var stringType = clrDump.GetClrType(typeof(string).FullName); var stringInstances = clrDump.EnumerateInstances(stringType); int nbStrings = clrDump.CountInstances(stringType); Dictionary <string, List<ulong>> result = new Dictionary<string, List<ulong>>(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing strings...", token); int n = 0; clrDump.Run(() => { foreach (var address in stringInstances) { if( token.IsCancellationRequested) { return; } n++; var value = SimpleValueHelper.GetSimpleValue(address, stringType, false) as string; if (value == null) { continue; } List<ulong> addresses; if( ! result.TryGetValue(value, out addresses)) { addresses = new List<ulong>(); result[value] = addresses; } addresses.Add(address); if( n % 1024 == 0) { float pct = (float)n / nbStrings; msgBus.Status($"Analyzing strings: {pct:p2}, n= {n:###,###,###,##0} / {nbStrings:###,###,###,##0}"); } } }); msgBus.EndTask($"Strings analyzed. Instances: {n:###,###,###,##0}, unique values: {result.Count:###,###,###,##0}"); var strings = result.Select(kvp => new StringInformation(kvp.Key, kvp.Value)).ToList(); return strings; }
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 long CountTargets(ClrDump clrDump, ClrType clrType) { long count = 0; var targetField = clrType.GetFieldByName(TargetFieldName); var invocCountField = clrType.GetFieldByName(InvocationCountFieldName); foreach (ulong address in clrDump.EnumerateInstances(clrType)) { count += CountTargets(address, clrType, targetField, invocCountField); } return count; }
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); }
internal IEnumerable <ulong> EnumerateInstances() { return(ClrDump.EnumerateInstances(ClrType)); }
internal IEnumerable <ulong> EnumerateInstances() => ClrDump.EnumerateInstances(ClrType);