Browse Source

Fixed all bugs that prevented the decompiler from running.

The output of decompilation is saved in file output.cs
Unsupported expressions are handled a bit more gracefully -
for example: IL__callvirt(set_AutoSize(), (IL__ldfld(titleLabel, @this)), 1);
this is will eventually become this.titleLabel.AutoSize = 1;
pull/1/head^2
David Srbecký 18 years ago
parent
commit
40e1edd7d9
  1. 88
      bin/Debug/output.cs
  2. 6
      src/AstBuilder.cs
  3. 18
      src/AstMetodBodyBuilder.cs
  4. 15
      src/ByteCode.Type.cs
  5. 17
      src/ByteCode.cs
  6. 3
      src/CilStack.cs
  7. 7
      src/MainForm.cs
  8. 5
      src/StackExpression.cs

88
bin/Debug/output.cs

@ -0,0 +1,88 @@
using System;
namespace Reversi
{
public class AboutDialog : System.Windows.Forms.Form
{
private System.Windows.Forms.PictureBox iconPictureBox;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.Label titleLabel;
private System.Windows.Forms.Label versionLabel;
private System.Windows.Forms.Label copyrightLabel;
private System.ComponentModel.Container components;
protected virtual void Dispose(bool disposing)
{
if (!(!disposing)) {
if (!(!(IL__ldfld(components, @this)))) {
IL__callvirt(Dispose(), (IL__ldfld(components, @this)));
goto BasicBlock_4;
}
else {
goto BasicBlock_4;
}
}
BasicBlock_4:
@this.Dispose(disposing);
}
private void InitializeComponent()
{
System.Resources.ResourceManager V_0 = (IL__newobj(.ctor(), Type.GetTypeFromHandle((IL__ldtoken(Reversi.AboutDialog)))));
IL__stfld(iconPictureBox, @this, (IL__newobj(.ctor())));
IL__stfld(titleLabel, @this, (IL__newobj(.ctor())));
IL__stfld(versionLabel, @this, (IL__newobj(.ctor())));
IL__stfld(okButton, @this, (IL__newobj(.ctor())));
IL__stfld(copyrightLabel, @this, (IL__newobj(.ctor())));
@this.SuspendLayout();
IL__callvirt(set_Location(), (IL__ldfld(iconPictureBox, @this)), (IL__newobj(.ctor(), 77, 56)));
IL__callvirt(set_Name(), (IL__ldfld(iconPictureBox, @this)), "iconPictureBox");
IL__callvirt(set_Size(), (IL__ldfld(iconPictureBox, @this)), (IL__newobj(.ctor(), 96, 96)));
IL__callvirt(set_TabIndex(), (IL__ldfld(iconPictureBox, @this)), 0);
IL__callvirt(set_TabStop(), (IL__ldfld(iconPictureBox, @this)), 0);
IL__callvirt(set_AutoSize(), (IL__ldfld(titleLabel, @this)), 1);
IL__callvirt(set_Font(), (IL__ldfld(titleLabel, @this)), (IL__newobj(.ctor(), "Microsoft Sans Serif", 8.25f, 1, 3, 0)));
IL__callvirt(set_Location(), (IL__ldfld(titleLabel, @this)), (IL__newobj(.ctor(), 103, 16)));
IL__callvirt(set_Name(), (IL__ldfld(titleLabel, @this)), "titleLabel");
IL__callvirt(set_Size(), (IL__ldfld(titleLabel, @this)), (IL__newobj(.ctor(), 44, 16)));
IL__callvirt(set_TabIndex(), (IL__ldfld(titleLabel, @this)), 0);
IL__callvirt(set_Text(), (IL__ldfld(titleLabel, @this)), "Reversi");
IL__callvirt(set_TextAlign(), (IL__ldfld(titleLabel, @this)), 32);
IL__callvirt(set_AutoSize(), (IL__ldfld(versionLabel, @this)), 1);
IL__callvirt(set_Location(), (IL__ldfld(versionLabel, @this)), (IL__newobj(.ctor(), 95, 32)));
IL__callvirt(set_Name(), (IL__ldfld(versionLabel, @this)), "versionLabel");
IL__callvirt(set_Size(), (IL__ldfld(versionLabel, @this)), (IL__newobj(.ctor(), 61, 16)));
IL__callvirt(set_TabIndex(), (IL__ldfld(versionLabel, @this)), 1);
IL__callvirt(set_Text(), (IL__ldfld(versionLabel, @this)), "Version 2.0");
IL__callvirt(set_TextAlign(), (IL__ldfld(versionLabel, @this)), 32);
IL__callvirt(set_DialogResult(), (IL__ldfld(okButton, @this)), 1);
IL__callvirt(set_Location(), (IL__ldfld(okButton, @this)), (IL__newobj(.ctor(), 88, 192)));
IL__callvirt(set_Name(), (IL__ldfld(okButton, @this)), "okButton");
IL__callvirt(set_TabIndex(), (IL__ldfld(okButton, @this)), 3);
IL__callvirt(set_Text(), (IL__ldfld(okButton, @this)), "OK");
IL__callvirt(set_AutoSize(), (IL__ldfld(copyrightLabel, @this)), 1);
IL__callvirt(set_Location(), (IL__ldfld(copyrightLabel, @this)), (IL__newobj(.ctor(), 36, 160)));
IL__callvirt(set_Name(), (IL__ldfld(copyrightLabel, @this)), "copyrightLabel");
IL__callvirt(set_Size(), (IL__ldfld(copyrightLabel, @this)), (IL__newobj(.ctor(), 178, 16)));
IL__callvirt(set_TabIndex(), (IL__ldfld(copyrightLabel, @this)), 2);
IL__callvirt(set_Text(), (IL__ldfld(copyrightLabel, @this)), "Copyright 2003-2005 by Mike Hall.");
IL__callvirt(set_TextAlign(), (IL__ldfld(copyrightLabel, @this)), 32);
@this.set_AcceptButton((IL__ldfld(okButton, @this)));
IL__callvirt(set_AutoScaleBaseSize(), @this, (IL__newobj(.ctor(), 5, 13)));
@this.set_CancelButton((IL__ldfld(okButton, @this)));
@this.set_ClientSize((IL__newobj(.ctor(), 250, 224)));
@this.set_ControlBox(0);
IL__callvirt(Add(), @this.get_Controls(), (IL__ldfld(copyrightLabel, @this)));
IL__callvirt(Add(), @this.get_Controls(), (IL__ldfld(versionLabel, @this)));
IL__callvirt(Add(), @this.get_Controls(), (IL__ldfld(titleLabel, @this)));
IL__callvirt(Add(), @this.get_Controls(), (IL__ldfld(okButton, @this)));
IL__callvirt(Add(), @this.get_Controls(), (IL__ldfld(iconPictureBox, @this)));
@this.set_FormBorderStyle(3);
@this.set_Icon((IL__castclass(System.Drawing.Icon, (IL__callvirt(GetObject(), V_0, "$this.Icon")))));
@this.set_MaximizeBox(0);
@this.set_MinimizeBox(0);
@this.set_Name("AboutDialog");
@this.set_ShowInTaskbar(0);
@this.set_StartPosition(4);
IL__callvirt(set_Text(), @this, "About Reversi");
@this.ResumeLayout(0);
}
}
}

6
src/AstBuilder.cs

@ -47,8 +47,8 @@ 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
while(true) { while(true) {
@ -111,7 +111,7 @@ namespace Decompiler
public void AddType(TypeDefinition typeDef) public void AddType(TypeDefinition typeDef)
{ {
if (Options.TypeFilter != null && !typeDef.Name.EndsWith(Options.TypeFilter)) return; if (Options.TypeFilter != null && typeDef.Name != Options.TypeFilter) return;
TypeDeclaration astType = CreateType(typeDef); TypeDeclaration astType = CreateType(typeDef);
NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace); NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);

18
src/AstMetodBodyBuilder.cs

@ -119,7 +119,10 @@ namespace Decompiler
lastStatement = TransformExpression(expr); lastStatement = TransformExpression(expr);
yield return lastStatement; yield return lastStatement;
} }
Ast.IfElseStatement ifElseStmt = (Ast.IfElseStatement)lastStatement; Ast.IfElseStatement ifElseStmt = lastStatement as Ast.IfElseStatement;
if (ifElseStmt == null) {
ifElseStmt = new IfElseStatement(Ast.Expression.Null, Ast.Statement.Null, Ast.Statement.Null);
}
Ast.Statement oldTrueBody = ifElseStmt.TrueStatement[0]; Ast.Statement oldTrueBody = ifElseStmt.TrueStatement[0];
ifElseStmt.TrueStatement.Clear(); ifElseStmt.TrueStatement.Clear();
// Swap the method bodies // Swap the method bodies
@ -152,7 +155,6 @@ namespace Decompiler
Ast.Statement TransformExpression(StackExpression expr) Ast.Statement TransformExpression(StackExpression expr)
{ {
Ast.Statement astStatement = null; Ast.Statement astStatement = null;
try {
List<Ast.Expression> args = new List<Ast.Expression>(); List<Ast.Expression> args = new List<Ast.Expression>();
foreach(CilStackSlot stackSlot in expr.StackBefore.PeekCount(expr.PopCount)) { foreach(CilStackSlot stackSlot in expr.StackBefore.PeekCount(expr.PopCount)) {
string name = string.Format("expr{0:X2}", stackSlot.AllocadedBy.Offset); string name = string.Format("expr{0:X2}", stackSlot.AllocadedBy.Offset);
@ -172,15 +174,12 @@ namespace Decompiler
} else if (codeExpr is Ast.Statement) { } else if (codeExpr is Ast.Statement) {
astStatement = (Ast.Statement)codeExpr; astStatement = (Ast.Statement)codeExpr;
} }
} catch (NotImplementedException) {
astStatement = MakeComment(expr.LastByteCode.Description);
}
return astStatement; return astStatement;
} }
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));
} }
@ -215,7 +214,14 @@ namespace Decompiler
allArgs.Add(astExpr); allArgs.Add(astExpr);
} }
} }
try {
return MakeCodeDomExpression(methodDef, expr.LastByteCode, allArgs.ToArray()); return MakeCodeDomExpression(methodDef, expr.LastByteCode, allArgs.ToArray());
} catch (NotImplementedException) {
if (expr.LastByteCode.Operand != null) {
allArgs.Insert(0, new IdentifierExpression(expr.LastByteCode.FormatedOperand));
}
return new Ast.InvocationExpression(new IdentifierExpression("IL__" + expr.LastByteCode.OpCode.Name), allArgs);
}
} }
static object MakeCodeDomExpression(MethodDefinition methodDef, ByteCode byteCode, params Ast.Expression[] args) static object MakeCodeDomExpression(MethodDefinition methodDef, ByteCode byteCode, params Ast.Expression[] args)

15
src/ByteCode.Type.cs

@ -110,7 +110,7 @@ namespace Decompiler
case Code.Stelem_R4: case Code.Stelem_R4:
case Code.Stelem_R8: case Code.Stelem_R8:
case Code.Stelem_Ref: case Code.Stelem_Ref:
case Code.Stelem_Any: return null; case Code.Stelem_Any: return TypeVoid;
#endregion #endregion
#region Branching #region Branching
case Code.Br: case Code.Br:
@ -125,7 +125,7 @@ namespace Decompiler
case Code.Ble_Un: case Code.Ble_Un:
case Code.Blt: case Code.Blt:
case Code.Blt_Un: case Code.Blt_Un:
case Code.Bne_Un: return null; case Code.Bne_Un: return TypeVoid;
#endregion #endregion
#region Comparison #region Comparison
case Code.Ceq: case Code.Ceq:
@ -211,7 +211,10 @@ namespace Decompiler
case Code.Initobj: throw new NotImplementedException(); case Code.Initobj: throw new NotImplementedException();
case Code.Isinst: throw new NotImplementedException(); case Code.Isinst: throw new NotImplementedException();
case Code.Jmp: throw new NotImplementedException(); case Code.Jmp: throw new NotImplementedException();
case Code.Ldarg: return ((ParameterDefinition)operand).ParameterType; case Code.Ldarg:
Cecil.TypeReference typeRef = ((ParameterDefinition)operand).ParameterType;
// 'this' returns null; TODO: Return proper type of this
return typeRef ?? TypeObject;
case Code.Ldarga: throw new NotImplementedException(); case Code.Ldarga: throw new NotImplementedException();
case Code.Ldc_I4: return TypeInt32; case Code.Ldc_I4: return TypeInt32;
case Code.Ldc_I8: throw new NotImplementedException(); case Code.Ldc_I8: throw new NotImplementedException();
@ -234,18 +237,18 @@ namespace Decompiler
case Code.Mkrefany: throw new NotImplementedException(); case Code.Mkrefany: throw new NotImplementedException();
case Code.Newobj: throw new NotImplementedException(); case Code.Newobj: throw new NotImplementedException();
case Code.No: throw new NotImplementedException(); case Code.No: throw new NotImplementedException();
case Code.Nop: return null; case Code.Nop: return TypeVoid;
case Code.Or: throw new NotImplementedException(); case Code.Or: throw new NotImplementedException();
case Code.Pop: throw new NotImplementedException(); case Code.Pop: throw new NotImplementedException();
case Code.Readonly: throw new NotImplementedException(); case Code.Readonly: throw new NotImplementedException();
case Code.Refanytype: throw new NotImplementedException(); case Code.Refanytype: throw new NotImplementedException();
case Code.Refanyval: throw new NotImplementedException(); case Code.Refanyval: throw new NotImplementedException();
case Code.Ret: return null; case Code.Ret: return TypeVoid;
case Code.Rethrow: throw new NotImplementedException(); case Code.Rethrow: throw new NotImplementedException();
case Code.Sizeof: throw new NotImplementedException(); case Code.Sizeof: throw new NotImplementedException();
case Code.Starg: throw new NotImplementedException(); case Code.Starg: throw new NotImplementedException();
case Code.Stfld: throw new NotImplementedException(); case Code.Stfld: throw new NotImplementedException();
case Code.Stloc: return null; case Code.Stloc: return TypeVoid;
case Code.Stobj: throw new NotImplementedException(); case Code.Stobj: throw new NotImplementedException();
case Code.Stsfld: throw new NotImplementedException(); case Code.Stsfld: throw new NotImplementedException();
case Code.Switch: throw new NotImplementedException(); case Code.Switch: throw new NotImplementedException();

17
src/ByteCode.cs

@ -69,6 +69,11 @@ namespace Decompiler
this.operand = inst.Operand; this.operand = inst.Operand;
} }
public override string ToString()
{
return this.OpCode + " " + FormatByteCodeOperand(this.Operand);
}
public string Description { public string Description {
get { get {
return string.Format( return string.Format(
@ -83,7 +88,13 @@ namespace Decompiler
} }
} }
static object FormatByteCodeOperand(object operand) public string FormatedOperand {
get {
return FormatByteCodeOperand(this.Operand);
}
}
static string FormatByteCodeOperand(object operand)
{ {
if (operand == null) { if (operand == null) {
return string.Empty; return string.Empty;
@ -97,12 +108,14 @@ namespace Decompiler
return ((VariableDefinition)operand).Name; return ((VariableDefinition)operand).Name;
} else if (operand is ParameterDefinition) { } else if (operand is ParameterDefinition) {
return ((ParameterDefinition)operand).Name; return ((ParameterDefinition)operand).Name;
} else if (operand is FieldReference) {
return ((FieldReference)operand).Name;
} else if (operand is string) { } else if (operand is string) {
return "\"" + operand + "\""; return "\"" + operand + "\"";
} else if (operand is int) { } else if (operand is int) {
return operand.ToString(); return operand.ToString();
} else { } else {
return "(" + operand.GetType() + ")"; return operand.ToString();
} }
} }
} }

3
src/CilStack.cs

@ -25,6 +25,9 @@ namespace Decompiler
public CilStackSlot(ByteCode allocadedBy, Cecil.TypeReference type) public CilStackSlot(ByteCode allocadedBy, Cecil.TypeReference type)
{ {
if (allocadedBy == null) throw new ArgumentNullException();
if (type == null) throw new ArgumentNullException();
this.allocadedBy = allocadedBy; this.allocadedBy = allocadedBy;
this.type = type; this.type = type;
} }

7
src/MainForm.cs

@ -1,4 +1,5 @@
using System; using System;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Reflection; using System.Reflection;
@ -38,8 +39,8 @@ namespace Decompiler
x += checkBox.Width + 10; x += checkBox.Width + 10;
} }
} }
collapseCount.Value = 0; collapseCount.Value = 10000;
reduceCount.Value = 0; reduceCount.Value = 10000;
filter.Text = "AboutDialog"; filter.Text = "AboutDialog";
} }
@ -64,6 +65,8 @@ namespace Decompiler
AstBuilder codeDomBuilder = new AstBuilder(); AstBuilder codeDomBuilder = new AstBuilder();
codeDomBuilder.AddAssembly(assembly); codeDomBuilder.AddAssembly(assembly);
SourceCode = codeDomBuilder.GenerateCode(); SourceCode = codeDomBuilder.GenerateCode();
File.WriteAllText("output.cs", SourceCode);
} }
void CollapseBtnClick(object sender, EventArgs e) void CollapseBtnClick(object sender, EventArgs e)

5
src/StackExpression.cs

@ -138,6 +138,11 @@ namespace Decompiler
this.lastByteCode.Expression = this; this.lastByteCode.Expression = this;
} }
public override string ToString()
{
return this.LastByteCode.ToString();
}
public bool MustBeParenthesized { public bool MustBeParenthesized {
get { get {
switch(this.LastByteCode.OpCode.Code) { switch(this.LastByteCode.OpCode.Code) {

Loading…
Cancel
Save