Browse Source

GUI debugging controls

pull/1/head^2
David Srbecký 18 years ago
parent
commit
b310187433
  1. 1
      Decompiler.csproj
  2. 2
      src/AstBuilder.cs
  3. 11
      src/AstMetodBodyBuilder.cs
  4. 8
      src/ByteCode.cs
  5. 53
      src/ControlFlow/Node.cs
  6. 28
      src/ControlFlow/Nodes.cs
  7. 113
      src/MainForm.Designer.cs
  8. 50
      src/MainForm.cs
  9. 10
      src/Options.cs
  10. 14
      src/Program.cs
  11. 6
      src/StackExpression.cs
  12. 1
      src/StackExpressionCollection.cs

1
Decompiler.csproj

@ -49,6 +49,7 @@
<Compile Include="src\ControlFlow\Node.cs" /> <Compile Include="src\ControlFlow\Node.cs" />
<Compile Include="src\MainForm.cs" /> <Compile Include="src\MainForm.cs" />
<Compile Include="src\MainForm.Designer.cs" /> <Compile Include="src\MainForm.Designer.cs" />
<Compile Include="src\Options.cs" />
<Compile Include="src\Program.cs" /> <Compile Include="src\Program.cs" />
<Compile Include="src\ByteCode.StackAnalysis.cs" /> <Compile Include="src\ByteCode.StackAnalysis.cs" />
<Compile Include="src\StackExpression.cs" /> <Compile Include="src\StackExpression.cs" />

2
src/AstBuilder.cs

@ -32,7 +32,7 @@ namespace Decompiler
code = code.Replace(":\r\n\t", ": "); code = code.Replace(":\r\n\t", ": ");
code = code.Replace(": }", ":\r\n\t}"); code = code.Replace(": }", ":\r\n\t}");
code = code.Replace("\t", " "); code = code.Replace("\t", " ");
code = code.Replace("\"/*", "//"); code = code.Replace("\"/*", "");
code = code.Replace("*/\";", ""); code = code.Replace("*/\";", "");
// Post processing commands // Post processing commands

11
src/AstMetodBodyBuilder.cs

@ -36,6 +36,7 @@ namespace Decompiler
exprCollection.Optimize(); exprCollection.Optimize();
MethodBodyGraph bodyGraph = new MethodBodyGraph(exprCollection); MethodBodyGraph bodyGraph = new MethodBodyGraph(exprCollection);
bodyGraph.Optimize();
foreach(VariableDefinition varDef in methodDef.Body.Variables) { foreach(VariableDefinition varDef in methodDef.Body.Variables) {
localVarTypes[varDef.Name] = varDef.VariableType; localVarTypes[varDef.Name] = varDef.VariableType;
@ -63,10 +64,10 @@ namespace Decompiler
IEnumerable<Ast.INode> TransformNode(Node node) IEnumerable<Ast.INode> TransformNode(Node node)
{ {
yield return MakeComment(node.ToString()); yield return MakeComment("// " + node.ToString());
if (node is BasicBlock) { if (node is BasicBlock) {
yield return new Ast.LabelStatement(string.Format("BasicBlock_{0}", ((BasicBlock)node).Id)); yield return new Ast.LabelStatement(((BasicBlock)node).Label);
foreach(StackExpression expr in ((BasicBlock)node).Body) { foreach(StackExpression expr in ((BasicBlock)node).Body) {
yield return TransformExpression(expr); yield return TransformExpression(expr);
} }
@ -86,6 +87,8 @@ namespace Decompiler
} else { } else {
throw new Exception("Bad node type"); throw new Exception("Bad node type");
} }
yield return MakeComment("");
} }
Ast.Statement TransformExpression(StackExpression expr) Ast.Statement TransformExpression(StackExpression expr)
@ -119,7 +122,7 @@ namespace Decompiler
static Ast.ExpressionStatement MakeComment(string text) static Ast.ExpressionStatement MakeComment(string text)
{ {
text = "/* " + text + "*/"; text = "/*" + text + "*/";
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text)); return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
} }
@ -146,7 +149,7 @@ namespace Decompiler
object operand = byteCode.Operand; object operand = byteCode.Operand;
Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null; Ast.TypeReference operandAsTypeRef = operand is Cecil.TypeReference ? new Ast.TypeReference(((Cecil.TypeReference)operand).FullName) : null;
ByteCode operandAsByteCode = operand as ByteCode; ByteCode operandAsByteCode = operand as ByteCode;
string operandAsByteCodeLabel = operand is ByteCode ? String.Format("IL_{0:X2}", ((ByteCode)operand).Offset) : null; string operandAsByteCodeLabel = operand is ByteCode ? ((ByteCode)operand).Expression.BasicBlock.Label : null;
Ast.Expression arg1 = args.Length >= 1 ? args[0] : null; Ast.Expression arg1 = args.Length >= 1 ? args[0] : null;
Ast.Expression arg2 = args.Length >= 2 ? args[1] : null; Ast.Expression arg2 = args.Length >= 2 ? args[1] : null;
Ast.Expression arg3 = args.Length >= 3 ? args[2] : null; Ast.Expression arg3 = args.Length >= 3 ? args[2] : null;

8
src/ByteCode.cs

@ -9,7 +9,7 @@ namespace Decompiler
{ {
public partial class ByteCode public partial class ByteCode
{ {
StackExpression owner; StackExpression expression;
ByteCode previous; ByteCode previous;
ByteCode next; ByteCode next;
@ -18,9 +18,9 @@ namespace Decompiler
OpCode opCode; OpCode opCode;
object operand; object operand;
public StackExpression Owner { public StackExpression Expression {
get { return owner; } get { return expression; }
set { owner = value; } set { expression = value; }
} }
public ByteCode Previous { public ByteCode Previous {

53
src/ControlFlow/Node.cs

@ -23,12 +23,19 @@ namespace Decompiler.ControlFlow
public abstract class Node public abstract class Node
{ {
public static int NextNodeID = 1;
int id;
Node parent; Node parent;
Node headChild; Node headChild;
Set<Node> childs = new Set<Node>(); Set<Node> childs = new Set<Node>();
Set<Node> predecessors = new Set<Node>(); Set<Node> predecessors = new Set<Node>();
Set<Node> successors = new Set<Node>(); Set<Node> successors = new Set<Node>();
public int ID {
get { return id; }
}
public Node Parent { public Node Parent {
get { return parent; } get { return parent; }
} }
@ -53,6 +60,7 @@ namespace Decompiler.ControlFlow
public Node(Node parent) public Node(Node parent)
{ {
this.parent = parent; this.parent = parent;
this.id = NextNodeID++;
} }
public void Optimize() public void Optimize()
@ -60,6 +68,7 @@ namespace Decompiler.ControlFlow
for(int i = 0; i < this.Childs.Count;) { for(int i = 0; i < this.Childs.Count;) {
Node child = childs[i]; Node child = childs[i];
if (child.Predecessors.Count == 1) { if (child.Predecessors.Count == 1) {
if (Options.ReduceGraph-- <= 0) return;
MergeChilds(child.Predecessors[0], child); MergeChilds(child.Predecessors[0], child);
i = 0; // Restart i = 0; // Restart
} else { } else {
@ -146,5 +155,49 @@ namespace Decompiler.ControlFlow
node.Predecessors.Clear(); node.Predecessors.Clear();
node.Successors.Clear(); node.Successors.Clear();
} }
public override string ToString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(this.GetType().Name);
sb.Append(" ");
sb.Append(ID);
sb.Append(" ");
if (this.Predecessors.Count > 0 || this.Successors.Count > 0) {
sb.Append("(");
if (this.Predecessors.Count > 0) {
sb.Append("Predecessors:");
bool isFirst = true;
foreach(Node predecessor in this.Predecessors) {
if (isFirst) {
isFirst = false;
} else {
sb.Append(",");
}
sb.Append(predecessor.ID);
}
}
if (this.Predecessors.Count > 0 && this.Successors.Count > 0) {
sb.Append(" ");
}
if (this.Successors.Count > 0) {
sb.Append("Successors:");
bool isFirst = true;
foreach(Node successor in this.Successors) {
if (isFirst) {
isFirst = false;
} else {
sb.Append(",");
}
sb.Append(successor.ID);
}
}
sb.Append(")");
}
return sb.ToString();
}
} }
} }

28
src/ControlFlow/Nodes.cs

@ -11,14 +11,13 @@ namespace Decompiler.ControlFlow
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs"); if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs");
BasicBlock basicBlock = null; BasicBlock basicBlock = null;
int basicBlockId = 1;
for(int i = 0; i < exprs.Count; i++) { for(int i = 0; i < exprs.Count; i++) {
// Start new basic block if // Start new basic block if
// - this is first expression // - this is first expression
// - last expression was branch // - last expression was branch
// - this expression is branch target // - this expression is branch target
if (i == 0 || exprs[i - 1].BranchTarget != null || exprs[i].BranchesHere.Count > 0){ if (i == 0 || exprs[i - 1].BranchTarget != null || exprs[i].BranchesHere.Count > 0){
basicBlock = new BasicBlock(this, basicBlockId++); basicBlock = new BasicBlock(this);
this.Childs.Add(basicBlock); this.Childs.Add(basicBlock);
} }
basicBlock.Body.Add(exprs[i]); basicBlock.Body.Add(exprs[i]);
@ -54,11 +53,6 @@ namespace Decompiler.ControlFlow
public AcyclicGraph(Node parent): base(parent){ public AcyclicGraph(Node parent): base(parent){
} }
public override string ToString()
{
return "AcyclicGraph";
}
} }
public class Loop: Node public class Loop: Node
@ -66,34 +60,24 @@ namespace Decompiler.ControlFlow
public Loop(Node parent): base(parent){ public Loop(Node parent): base(parent){
} }
public override string ToString()
{
return "Loop";
}
} }
public class BasicBlock: Node public class BasicBlock: Node
{ {
int id;
List<StackExpression> body = new List<StackExpression>(); List<StackExpression> body = new List<StackExpression>();
public int Id { public string Label {
get { return id; } get {
return "BasicBlock_" + ID;
}
} }
public List<StackExpression> Body { public List<StackExpression> Body {
get { return body; } get { return body; }
} }
public BasicBlock(Node parent, int id): base(parent) public BasicBlock(Node parent): base(parent)
{
this.id = id;
}
public override string ToString()
{ {
return string.Format("BasicBlock {0}", id, body.Count);
} }
} }
} }

113
src/MainForm.Designer.cs generated

@ -32,34 +32,119 @@ namespace Decompiler
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.sourceCode = new System.Windows.Forms.TextBox(); this.collapseCount = new System.Windows.Forms.NumericUpDown();
this.reduceCount = new System.Windows.Forms.NumericUpDown();
this.collapseBtn = new System.Windows.Forms.Button();
this.reduceBtn = new System.Windows.Forms.Button();
this.decompileBtn = new System.Windows.Forms.Button();
this.sourceCodeBox = new System.Windows.Forms.RichTextBox();
((System.ComponentModel.ISupportInitialize)(this.collapseCount)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.reduceCount)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// sourceCode // collapseCount
// //
this.sourceCode.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.collapseCount.Location = new System.Drawing.Point(12, 12);
this.collapseCount.Maximum = new decimal(new int[] {
100000,
0,
0,
0});
this.collapseCount.Name = "collapseCount";
this.collapseCount.Size = new System.Drawing.Size(120, 26);
this.collapseCount.TabIndex = 1;
this.collapseCount.Value = new decimal(new int[] {
1000,
0,
0,
0});
this.collapseCount.ValueChanged += new System.EventHandler(this.CollapseCountValueChanged);
//
// reduceCount
//
this.reduceCount.Location = new System.Drawing.Point(308, 12);
this.reduceCount.Maximum = new decimal(new int[] {
100000,
0,
0,
0});
this.reduceCount.Name = "reduceCount";
this.reduceCount.Size = new System.Drawing.Size(120, 26);
this.reduceCount.TabIndex = 2;
this.reduceCount.Value = new decimal(new int[] {
1000,
0,
0,
0});
this.reduceCount.ValueChanged += new System.EventHandler(this.ReduceCountValueChanged);
//
// collapseBtn
//
this.collapseBtn.Location = new System.Drawing.Point(138, 12);
this.collapseBtn.Name = "collapseBtn";
this.collapseBtn.Size = new System.Drawing.Size(164, 26);
this.collapseBtn.TabIndex = 3;
this.collapseBtn.Text = "Collapse expression";
this.collapseBtn.UseVisualStyleBackColor = true;
this.collapseBtn.Click += new System.EventHandler(this.CollapseBtnClick);
//
// reduceBtn
//
this.reduceBtn.Location = new System.Drawing.Point(434, 12);
this.reduceBtn.Name = "reduceBtn";
this.reduceBtn.Size = new System.Drawing.Size(143, 26);
this.reduceBtn.TabIndex = 4;
this.reduceBtn.Text = "Reduce graph";
this.reduceBtn.UseVisualStyleBackColor = true;
this.reduceBtn.Click += new System.EventHandler(this.ReduceBtnClick);
//
// decompileBtn
//
this.decompileBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.decompileBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.decompileBtn.Location = new System.Drawing.Point(639, 12);
this.decompileBtn.Name = "decompileBtn";
this.decompileBtn.Size = new System.Drawing.Size(109, 26);
this.decompileBtn.TabIndex = 5;
this.decompileBtn.Text = "Decompile";
this.decompileBtn.UseVisualStyleBackColor = true;
this.decompileBtn.Click += new System.EventHandler(this.DecompileBtnClick);
//
// sourceCodeBox
//
this.sourceCodeBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.sourceCode.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.sourceCodeBox.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.sourceCode.Location = new System.Drawing.Point(12, 12); this.sourceCodeBox.Location = new System.Drawing.Point(12, 45);
this.sourceCode.Multiline = true; this.sourceCodeBox.Name = "sourceCodeBox";
this.sourceCode.Name = "sourceCode"; this.sourceCodeBox.Size = new System.Drawing.Size(736, 632);
this.sourceCode.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.sourceCodeBox.TabIndex = 6;
this.sourceCode.Size = new System.Drawing.Size(736, 665); this.sourceCodeBox.Text = "";
this.sourceCode.TabIndex = 0; this.sourceCodeBox.WordWrap = false;
this.sourceCode.WordWrap = false;
// //
// MainForm // MainForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(760, 689); this.ClientSize = new System.Drawing.Size(760, 689);
this.Controls.Add(this.sourceCode); this.Controls.Add(this.sourceCodeBox);
this.Controls.Add(this.decompileBtn);
this.Controls.Add(this.reduceBtn);
this.Controls.Add(this.collapseBtn);
this.Controls.Add(this.reduceCount);
this.Controls.Add(this.collapseCount);
this.Name = "MainForm"; this.Name = "MainForm";
this.Text = "Decompiler"; this.Text = "Decompiler";
((System.ComponentModel.ISupportInitialize)(this.collapseCount)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.reduceCount)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout();
} }
private System.Windows.Forms.TextBox sourceCode; private System.Windows.Forms.RichTextBox sourceCodeBox;
private System.Windows.Forms.Button decompileBtn;
private System.Windows.Forms.Button reduceBtn;
private System.Windows.Forms.Button collapseBtn;
private System.Windows.Forms.NumericUpDown reduceCount;
private System.Windows.Forms.NumericUpDown collapseCount;
} }
} }

50
src/MainForm.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using Mono.Cecil;
namespace Decompiler namespace Decompiler
{ {
/// <summary> /// <summary>
@ -10,18 +12,60 @@ namespace Decompiler
/// </summary> /// </summary>
public partial class MainForm : Form public partial class MainForm : Form
{ {
public MainForm() string filename;
public MainForm(string filename)
{ {
this.filename = filename;
InitializeComponent(); InitializeComponent();
} }
public string SourceCode { public string SourceCode {
get { get {
return sourceCode.Text; return sourceCodeBox.Text;
} }
set { set {
sourceCode.Text = value; sourceCodeBox.Text = value;
}
} }
public void Decompile()
{
ControlFlow.Node.NextNodeID = 0;
Options.CollapseExpression = (int)collapseCount.Value;
Options.ReduceGraph = (int)reduceCount.Value;
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddAssembly(assembly);
SourceCode = codeDomBuilder.GenerateCode();
}
void CollapseBtnClick(object sender, EventArgs e)
{
collapseCount.Value++;
Decompile();
}
void ReduceBtnClick(object sender, EventArgs e)
{
reduceCount.Value++;
Decompile();
}
void DecompileBtnClick(object sender, EventArgs e)
{
Decompile();
}
void CollapseCountValueChanged(object sender, EventArgs e)
{
Decompile();
}
void ReduceCountValueChanged(object sender, EventArgs e)
{
Decompile();
} }
} }
} }

10
src/Options.cs

@ -0,0 +1,10 @@
using System;
namespace Decompiler
{
public static class Options
{
public static int CollapseExpression = 0;
public static int ReduceGraph = 0;
}
}

14
src/Program.cs

@ -21,21 +21,13 @@ namespace Decompiler
[STAThread] [STAThread]
private static void Main(string[] args) private static void Main(string[] args)
{ {
string sourceCode = Decompile(@"..\..\tests\QuickSort\bin\Release\QuickSort.exe"); string sourceFilename = @"..\..\tests\QuickSort\bin\Release\QuickSort.exe";
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
MainForm mainForm = new MainForm(); MainForm mainForm = new MainForm(sourceFilename);
mainForm.SourceCode = sourceCode; mainForm.Decompile();
Application.Run(mainForm); Application.Run(mainForm);
} }
static string Decompile(string filename)
{
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddAssembly(assembly);
return codeDomBuilder.GenerateCode();
}
} }
} }

6
src/StackExpression.cs

@ -63,7 +63,7 @@ namespace Decompiler
get { get {
List<StackExpression> branchesHere = new List<StackExpression>(); List<StackExpression> branchesHere = new List<StackExpression>();
foreach(ByteCode byteCode in this.FirstByteCode.BranchesHere) { foreach(ByteCode byteCode in this.FirstByteCode.BranchesHere) {
branchesHere.Add(byteCode.Owner); branchesHere.Add(byteCode.Expression);
} }
return branchesHere; return branchesHere;
} }
@ -74,7 +74,7 @@ namespace Decompiler
if (this.lastByteCode.BranchTarget == null) { if (this.lastByteCode.BranchTarget == null) {
return null; return null;
} else { } else {
return this.lastByteCode.BranchTarget.Owner; return this.lastByteCode.BranchTarget.Expression;
} }
} }
} }
@ -135,7 +135,7 @@ namespace Decompiler
{ {
this.owner = owner; this.owner = owner;
this.lastByteCode = lastByteCode; this.lastByteCode = lastByteCode;
this.lastByteCode.Owner = this; this.lastByteCode.Expression = this;
} }
public bool MustBeParenthesized { public bool MustBeParenthesized {

1
src/StackExpressionCollection.cs

@ -27,6 +27,7 @@ namespace Decompiler
!expr.IsBranchTarget && !expr.IsBranchTarget &&
prevExpr.IsClosed) prevExpr.IsClosed)
{ {
if (Options.CollapseExpression-- <= 0) return;
this.RemoveAt(i - 1); i--; this.RemoveAt(i - 1); i--;
expr.LastArguments.Insert(0, prevExpr); expr.LastArguments.Insert(0, prevExpr);
i--; i--;

Loading…
Cancel
Save