Пример #1
0
        private void ImportEntries(EntryListTab[] entries)
        {
            foreach (EntryListTab entry in entries.Where(x => x.Path.GetHash() != 0))
            {
                var type = (entry.Type & 0x400000) == 0 ? EntryType.File : EntryType.Dir;

                if (type == EntryType.Dir)
                {
                    var node = Nodes[entry.Path.GetHash()];
                    if (node.NameHash != entry.Name.GetHash() || node.ParentHash != entry.Parent.GetHash())
                    {
                        Console.WriteLine("Importing hash mismatch");
                    }

                    node.NextSiblingIndex = entry.NextSiblingIndex == 0xFFFFFF ? -1 : entry.NextSiblingIndex;
                    node.Type             = type;
                    EntryNodes.Add(node);
                }
                else if (type == EntryType.File)
                {
                    var node = new FsNode();
                    node.PathHash         = entry.Path.GetHash();
                    node.ParentHash       = entry.Parent.GetHash();
                    node.NameHash         = entry.Name.GetHash();
                    node.ExtensionHash    = entry.Extension.GetHash();
                    node.NextSiblingIndex = entry.NextSiblingIndex == 0xFFFFFF ? -1 : entry.NextSiblingIndex;
                    node.Type             = type;

                    EntryNodes.Add(node);
                    Nodes.Add(node.PathHash, node);
                }
            }
        }
Пример #2
0
        public void RemoveFrameworkEntryPoints(HashSet <string> frameworkAssemblies)
        {
            var removing = new List <ICallGraphNode>(EntryNodes.Count);

            foreach (var entryNode in EntryNodes.Values)
            {
                if (!frameworkAssemblies.Contains(entryNode.AssemblyName))
                {
                    continue;
                }

                RemoveUnavailableNodesFrom(entryNode);
                removing.Add(entryNode);
            }

            foreach (var entryNode in removing)
            {
                EntryNodes.Remove(entryNode.MethodSignature);
            }
        }
Пример #3
0
        private void RemoveUnavailableNodesTo(ICallGraphNode node)
        {
            Debug.Assert(node.OutNodes.Count == 0);

            Nodes.Remove(node.MethodSignature);
            if (node.InNodes.Count == 0)
            {
                EntryNodes.Remove(node.MethodSignature);
            }

            for (var i = 0; i < node.InNodes.Count; i++)
            {
                var inNode = node.InNodes[i];
                inNode.OutNodes.Remove(node);
                if (inNode.OutNodes.Count == 0)
                {
                    RemoveUnavailableNodesTo(inNode);
                }
            }
        }
Пример #4
0
        public void RemoveNonPublicEntryNodes()
        {
            var processingNodes = new Queue <ICallGraphNode>(EntryNodes.Values);

            while (processingNodes.Count > 0)
            {
                var node = processingNodes.Dequeue();
                if (node.IsPublic)
                {
                    continue;
                }

                foreach (var outNode in node.OutNodes)
                {
                    if (outNode == node)
                    {
                        continue;
                    }

                    outNode.InNodes.Remove(node);
                    if ((outNode.InNodes.Count == 0) ||
                        (outNode.InNodes.Count == 1 && outNode.Equals(outNode.InNodes[0])))    // simple recursive calls
                    {
                        // TODO: Add detection of recursive calls like A() -> B() -> A()
                        if (outNode.IsPublic)
                        {
                            EntryNodes.Add(outNode.MethodSignature, outNode);
                        }
                        else
                        {
                            processingNodes.Enqueue(outNode);
                        }
                    }
                }

                EntryNodes.Remove(node.MethodSignature);
                Nodes.Remove(node.MethodSignature);
            }
        }
Пример #5
0
        public void RemoveSameClasses()
        {
            var handledNodes    = new HashSet <ICallGraphNode>(Nodes.Count);
            var processingNodes = new Queue <(ICallGraphNode, ICallGraphNode)>();

            EntryNodes.Clear();
            Nodes.Clear();
            var roots = Roots.Values;

            Roots = new Dictionary <MethodUniqueSignature, ICallGraphNode>();
            foreach (var rootNode in roots)
            {
                // we keep all parents of root(s)
                if (!handledNodes.Add(rootNode))
                {
                    continue;
                }

                var mappedRootNode = new CallInfoNode(rootNode.Info);
                Roots.Add(mappedRootNode.MethodSignature, mappedRootNode);
                Nodes.Add(mappedRootNode.MethodSignature, mappedRootNode);
                if (rootNode.InNodes.Count == 0 && !EntryNodes.ContainsKey(mappedRootNode.MethodSignature))
                {
                    EntryNodes.Add(mappedRootNode.MethodSignature, mappedRootNode);
                }

                foreach (var inNode in rootNode.InNodes)
                {
                    var mappedNode = new CallInfoNode(inNode.Info);
                    mappedRootNode.InNodes.Add(mappedNode);
                    mappedNode.OutNodes.Add(mappedRootNode);

                    if (!Nodes.ContainsKey(mappedNode.MethodSignature))
                    {
                        Nodes.Add(mappedNode.MethodSignature, mappedNode);
                        if (inNode.InNodes.Count == 0)
                        {
                            if (!EntryNodes.ContainsKey(mappedNode.MethodSignature))
                            {
                                EntryNodes.Add(mappedNode.MethodSignature, mappedNode);
                            }
                        }
                        else
                        {
                            processingNodes.Enqueue((inNode, mappedNode));
                        }
                    }
                }
            }

            // and keep only different classes for other parents
            while (processingNodes.Count > 0)
            {
                var(node, mappedNode) = processingNodes.Dequeue();
                if (!handledNodes.Add(node))
                {
                    continue;
                }

                var mappedInNodes = new HashSet <ICallGraphNode>(mappedNode.InNodes);
                foreach (var inNode in node.InNodes)
                {
                    var classSignature = new MethodUniqueSignature(inNode.MethodSignature.ToClassName());
                    if (Nodes.TryGetValue(classSignature, out var mappedInNode))
                    {
                        if (mappedInNode != mappedNode && mappedInNodes.Add(mappedInNode))
                        {
                            mappedInNode.OutNodes.Add(mappedNode);
                        }
                    }
                    else
                    {
                        mappedInNode = new CallInfoNode(new CallInfo(
                                                            0,
                                                            null,
                                                            inNode.AssemblyInfo,
                                                            classSignature,
                                                            inNode.IsPublic,
                                                            null));

                        mappedInNodes.Add(mappedInNode);
                        mappedInNode.OutNodes.Add(mappedNode);
                        Nodes.Add(mappedInNode.MethodSignature, mappedInNode);
                    }

                    if (inNode.InNodes.Count == 0)
                    {
                        if (!EntryNodes.ContainsKey(mappedInNode.MethodSignature))
                        {
                            EntryNodes.Add(mappedInNode.MethodSignature, mappedInNode);
                        }
                    }
                    else
                    {
                        processingNodes.Enqueue((inNode, mappedInNode));
                    }
                }

                if (mappedNode.InNodes.Count != mappedInNodes.Count)
                {
                    mappedNode.InNodes.Clear();
                    mappedNode.InNodes.AddRange(mappedInNodes);
                }
            }
        }
Пример #6
0
        public void RemoveNonPublicMiddleNodes()
        {
            var cache           = new Dictionary <ICallGraphNode, List <ICallGraphNode> >();
            var processingNodes = new HashSet <ICallGraphNode>(EntryNodes.Values);

            while (processingNodes.Count > 0)
            {
                var node = processingNodes.First();
                processingNodes.Remove(node);
                for (var i = node.OutNodes.Count - 1; i >= 0; i--)
                {
                    var outNode = node.OutNodes[i];
                    if (outNode.OutNodes.Count == 0)
                    {
                        continue;
                    }

                    if (outNode.IsPublic)
                    {
                        processingNodes.Add(outNode);
                        continue;
                    }

                    node.OutNodes.RemoveAt(i);
                    var publicNodes = FindPublicOutNodes(outNode);
                    node.OutNodes.AddRange(publicNodes);
                    foreach (var graphNode in publicNodes)
                    {
                        processingNodes.Add(graphNode);
                    }
                }

                for (var i = node.InNodes.Count - 1; i >= 0; i--)
                {
                    var inNode = node.InNodes[i];
                    if (!inNode.IsPublic && !EntryNodes.ContainsKey(inNode.MethodSignature))
                    {
                        node.InNodes.RemoveAt(i);
                    }
                }
            }

            List <ICallGraphNode> FindPublicOutNodes(ICallGraphNode node)
            {
                if (cache.TryGetValue(node, out var result))
                {
                    return(result);
                }

                result = new List <ICallGraphNode>();
                foreach (var outNode in node.OutNodes)
                {
                    if (outNode.IsPublic || outNode.OutNodes.Count == 0)
                    {
                        result.Add(outNode);
                    }
                    else
                    {
                        result.AddRange(FindPublicOutNodes(outNode));
                    }
                }

                if (node.InNodes.Count > 1)
                {
                    cache.Add(node, result);
                }

                Nodes.Remove(node.MethodSignature);
                return(result);
            }
        }