diff --git a/src/AstMetodBodyBuilder.cs b/src/AstMetodBodyBuilder.cs index 61a488cac..347c1e1e5 100644 --- a/src/AstMetodBodyBuilder.cs +++ b/src/AstMetodBodyBuilder.cs @@ -64,13 +64,20 @@ namespace Decompiler IEnumerable TransformNode(Node node) { - yield return MakeComment("// " + node.ToString()); + if (Options.NodeComments) { + yield return MakeComment("// " + node.ToString()); + } + + yield return new Ast.LabelStatement(node.Label); if (node is BasicBlock) { - yield return new Ast.LabelStatement(((BasicBlock)node).Label); foreach(StackExpression expr in ((BasicBlock)node).Body) { yield return TransformExpression(expr); } + Node next = ((BasicBlock)node).FallThroughBasicBlock; + if (next != null) { + yield return new Ast.GotoStatement(next.Label); + } } else if (node is AcyclicGraph) { Ast.BlockStatement blockStatement = new Ast.BlockStatement(); blockStatement.Children.AddRange(TransformNodes(node.Childs)); @@ -88,7 +95,9 @@ namespace Decompiler throw new Exception("Bad node type"); } - yield return MakeComment(""); + if (Options.NodeComments) { + yield return MakeComment(""); + } } Ast.Statement TransformExpression(StackExpression expr) diff --git a/src/ControlFlow/Node.cs b/src/ControlFlow/Node.cs index 61a24c54e..65fbc8bfa 100644 --- a/src/ControlFlow/Node.cs +++ b/src/ControlFlow/Node.cs @@ -57,6 +57,12 @@ namespace Decompiler.ControlFlow get { return successors; } } + public string Label { + get { + return this.GetType().Name + "_" + ID; + } + } + public Node(Node parent) { this.parent = parent; @@ -75,6 +81,11 @@ namespace Decompiler.ControlFlow i++; // Next } } + // If it result is single acyclic node, eliminate it + if (this.Childs.Count == 1 && this.Childs[0] is AcyclicGraph) { + this.headChild = this.Childs[0].HeadChild; + this.childs = this.Childs[0].Childs; + } } static void MergeChilds(Node head, Node tail) diff --git a/src/ControlFlow/Nodes.cs b/src/ControlFlow/Nodes.cs index c72c92031..25c17ccdb 100644 --- a/src/ControlFlow/Nodes.cs +++ b/src/ControlFlow/Nodes.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Mono.Cecil.Cil; + namespace Decompiler.ControlFlow { public class MethodBodyGraph: Node @@ -24,14 +26,20 @@ namespace Decompiler.ControlFlow exprs[i].BasicBlock = basicBlock; } - // Add fall-though links + // Add fall-through links for(int i = 0; i < exprs.Count - 1; i++) { BasicBlock node = exprs[i].BasicBlock; BasicBlock target = exprs[i + 1].BasicBlock; - if (node != target) { - node.Successors.Add(target); - target.Predecessors.Add(node); - } + + // Still same basic block - ignore + if (node == target) continue; + + // Non-conditional branch does not fall-through + if (exprs[i].LastByteCode.OpCode.Code == Code.Br) continue; + + node.FallThroughBasicBlock = target; + node.Successors.Add(target); + target.Predecessors.Add(node); } // Add branch links @@ -39,6 +47,8 @@ namespace Decompiler.ControlFlow if (exprs[i].BranchTarget != null) { BasicBlock node = exprs[i].BasicBlock; BasicBlock target = exprs[i].BranchTarget.BasicBlock; + + node.BranchBasicBlock = target; node.Successors.Add(target); target.Predecessors.Add(node); } @@ -65,17 +75,23 @@ namespace Decompiler.ControlFlow public class BasicBlock: Node { List body = new List(); - - public string Label { - get { - return "BasicBlock_" + ID; - } - } + BasicBlock fallThroughBasicBlock; + BasicBlock branchBasicBlock; public List Body { get { return body; } } + public BasicBlock FallThroughBasicBlock { + get { return fallThroughBasicBlock; } + set { fallThroughBasicBlock = value; } + } + + public BasicBlock BranchBasicBlock { + get { return branchBasicBlock; } + set { branchBasicBlock = value; } + } + public BasicBlock(Node parent): base(parent) { } diff --git a/src/MainForm.Designer.cs b/src/MainForm.Designer.cs index 9fd25b039..60b9ebe3c 100644 --- a/src/MainForm.Designer.cs +++ b/src/MainForm.Designer.cs @@ -38,6 +38,7 @@ namespace Decompiler this.reduceBtn = new System.Windows.Forms.Button(); this.decompileBtn = new System.Windows.Forms.Button(); this.sourceCodeBox = new System.Windows.Forms.RichTextBox(); + this.nodeComments = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.collapseCount)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.reduceCount)).BeginInit(); this.SuspendLayout(); @@ -116,18 +117,30 @@ namespace Decompiler | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.sourceCodeBox.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.sourceCodeBox.Location = new System.Drawing.Point(12, 45); + this.sourceCodeBox.Location = new System.Drawing.Point(12, 74); this.sourceCodeBox.Name = "sourceCodeBox"; - this.sourceCodeBox.Size = new System.Drawing.Size(736, 632); + this.sourceCodeBox.Size = new System.Drawing.Size(736, 603); this.sourceCodeBox.TabIndex = 6; this.sourceCodeBox.Text = ""; this.sourceCodeBox.WordWrap = false; // + // nodeComments + // + this.nodeComments.AutoSize = true; + this.nodeComments.Location = new System.Drawing.Point(12, 44); + this.nodeComments.Name = "nodeComments"; + this.nodeComments.Size = new System.Drawing.Size(147, 24); + this.nodeComments.TabIndex = 7; + this.nodeComments.Text = "Node comments"; + this.nodeComments.UseVisualStyleBackColor = true; + this.nodeComments.CheckedChanged += new System.EventHandler(this.NodeCommentsCheckedChanged); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(760, 689); + this.Controls.Add(this.nodeComments); this.Controls.Add(this.sourceCodeBox); this.Controls.Add(this.decompileBtn); this.Controls.Add(this.reduceBtn); @@ -139,7 +152,9 @@ namespace Decompiler ((System.ComponentModel.ISupportInitialize)(this.collapseCount)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.reduceCount)).EndInit(); this.ResumeLayout(false); + this.PerformLayout(); } + private System.Windows.Forms.CheckBox nodeComments; private System.Windows.Forms.RichTextBox sourceCodeBox; private System.Windows.Forms.Button decompileBtn; private System.Windows.Forms.Button reduceBtn; diff --git a/src/MainForm.cs b/src/MainForm.cs index 36de821f9..8dceb351a 100644 --- a/src/MainForm.cs +++ b/src/MainForm.cs @@ -34,6 +34,7 @@ namespace Decompiler ControlFlow.Node.NextNodeID = 0; Options.CollapseExpression = (int)collapseCount.Value; Options.ReduceGraph = (int)reduceCount.Value; + Options.NodeComments = nodeComments.Checked; AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename); AstBuilder codeDomBuilder = new AstBuilder(); @@ -67,5 +68,10 @@ namespace Decompiler { Decompile(); } + + void NodeCommentsCheckedChanged(object sender, EventArgs e) + { + Decompile(); + } } } diff --git a/src/Options.cs b/src/Options.cs index fd56768f7..d294220c0 100644 --- a/src/Options.cs +++ b/src/Options.cs @@ -4,7 +4,8 @@ namespace Decompiler { public static class Options { - public static int CollapseExpression = 0; - public static int ReduceGraph = 0; + public static int CollapseExpression = int.MaxValue; + public static int ReduceGraph = int.MaxValue; + public static bool NodeComments = false; } }