Beispiel #1
0
    public static (ControlFlowGraph, string) Decompile(ControlFlowGraph graph)
    {
        if (graph == null)
        {
            throw new ArgumentNullException(nameof(graph));
        }
        foreach (var head in graph.GetDfsPostOrder())
        {
            var(trueChild, falseChild) = graph.GetBinaryChildren(head);
            if (!trueChild.HasValue || !falseChild.HasValue)
            {
                continue;
            }

            int after = -1;
            var then  = -1;
            // Func<string> vis = () => graph.ToVis().AddPointer("head", head).AddPointer("after", after).AddPointer("then", then).ToString(); // For VS Code debug visualisation

            var parents0 = graph.Parents(trueChild.Value);
            var parents1 = graph.Parents(falseChild.Value);
            if (parents0.Length == 1)
            {
                var grandChildren = graph.Children(trueChild.Value);
                if (grandChildren.Length == 1 && grandChildren[0] == falseChild.Value)
                {
                    then  = trueChild.Value;
                    after = falseChild.Value;
                }
            }
            else if (parents1.Length == 1)
            {
                var grandChildren = graph.Children(falseChild.Value);
                if (grandChildren.Length == 1 && grandChildren[0] == trueChild.Value)
                {
                    then  = falseChild.Value;
                    after = trueChild.Value;
                }
            }

            if (after == -1 || then == -1 || after == head)
            {
                continue;
            }

            var condition = then == falseChild.Value ? Emit.Negation(graph.Nodes[head]) : graph.Nodes[head];
            var newNode   = Emit.If(condition, graph.Nodes[then]);
            return(graph.RemoveNode(then).ReplaceNode(head, newNode), Description);
        }

        return(graph, null);
    }
Beispiel #2
0
    public static (ControlFlowGraph, string) Decompile(ControlFlowGraph graph)
    {
        if (graph == null)
        {
            throw new ArgumentNullException(nameof(graph));
        }
        foreach (var head in graph.GetDfsPostOrder())
        {
            var(trueChild, falseChild) = graph.GetBinaryChildren(head);
            if (!trueChild.HasValue || !falseChild.HasValue)
            {
                continue;
            }

            var left  = trueChild.Value;
            var right = falseChild.Value;
            // Func<string> vis = () => graph.ToVis().AddPointer("head", head).AddPointer("after", after).AddPointer("left", left).AddPointer("right", right).ToString(); // For VS Code debug visualisation

            var leftParents   = graph.Parents(left);
            var rightParents  = graph.Parents(right);
            var leftChildren  = graph.Children(left);
            var rightChildren = graph.Children(right);

            if (leftParents.Length != 1 || rightParents.Length != 1) // Branches of an if can't be jump destinations from elsewhere
            {
                continue;
            }

            bool isRegularIfThenElse =
                leftChildren.Length == 1 && rightChildren.Length == 1 &&
                leftChildren[0] == rightChildren[0];

            bool isTerminalIfThenElse = leftChildren.Length == 0 && rightChildren.Length == 0;

            if (!isRegularIfThenElse && !isTerminalIfThenElse)
            {
                continue;
            }

            var after = isRegularIfThenElse ? leftChildren[0] : -1;

            if (after == head)
            {
                continue;
            }

            var newNode = Emit.IfElse(
                graph.Nodes[head],
                graph.Nodes[left],
                graph.Nodes[right]);

            var updated = graph;
            if (isRegularIfThenElse)
            {
                updated = updated.AddEdge(head, after, CfgEdge.True);
            }

            return(updated
                   .RemoveNode(left)
                   .RemoveNode(right)
                   .ReplaceNode(head, newNode), Description);
        }

        return(graph, null);
    }