Inheritance: IAddressData, ITypeNameData
Exemplo n.º 1
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);
        }