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. 54
      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 @@ @@ -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 @@ -47,8 +47,8 @@ namespace Decompiler
// code = code.Replace(":\r\n\t", ": ");
// code = code.Replace(": }", ":\r\n\t}");
code = code.Replace("\t", " ");
code = code.Replace("\"/*", "");
code = code.Replace("*/\";", "");
code = code.Replace("\"/***", "");
code = code.Replace("***/\";", "");
// Post processing commands
while(true) {
@ -111,7 +111,7 @@ namespace Decompiler @@ -111,7 +111,7 @@ namespace Decompiler
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);
NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);

54
src/AstMetodBodyBuilder.cs

@ -119,7 +119,10 @@ namespace Decompiler @@ -119,7 +119,10 @@ namespace Decompiler
lastStatement = TransformExpression(expr);
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];
ifElseStmt.TrueStatement.Clear();
// Swap the method bodies
@ -152,35 +155,31 @@ namespace Decompiler @@ -152,35 +155,31 @@ namespace Decompiler
Ast.Statement TransformExpression(StackExpression expr)
{
Ast.Statement astStatement = null;
try {
List<Ast.Expression> args = new List<Ast.Expression>();
foreach(CilStackSlot stackSlot in expr.StackBefore.PeekCount(expr.PopCount)) {
string name = string.Format("expr{0:X2}", stackSlot.AllocadedBy.Offset);
args.Add(new Ast.IdentifierExpression(name));
}
object codeExpr = MakeCodeDomExpression(methodDef, expr, args.ToArray());
if (codeExpr is Ast.Expression) {
if (expr.PushCount == 1) {
string type = expr.LastByteCode.Type.FullName;
string name = string.Format("expr{0:X2}", expr.LastByteCode.Offset);
Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString()));
astLocal.Variables.Add(new Ast.VariableDeclaration(name, (Ast.Expression)codeExpr));
astStatement = astLocal;
} else {
astStatement = new ExpressionStatement((Ast.Expression)codeExpr);
}
} else if (codeExpr is Ast.Statement) {
astStatement = (Ast.Statement)codeExpr;
List<Ast.Expression> args = new List<Ast.Expression>();
foreach(CilStackSlot stackSlot in expr.StackBefore.PeekCount(expr.PopCount)) {
string name = string.Format("expr{0:X2}", stackSlot.AllocadedBy.Offset);
args.Add(new Ast.IdentifierExpression(name));
}
object codeExpr = MakeCodeDomExpression(methodDef, expr, args.ToArray());
if (codeExpr is Ast.Expression) {
if (expr.PushCount == 1) {
string type = expr.LastByteCode.Type.FullName;
string name = string.Format("expr{0:X2}", expr.LastByteCode.Offset);
Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString()));
astLocal.Variables.Add(new Ast.VariableDeclaration(name, (Ast.Expression)codeExpr));
astStatement = astLocal;
} else {
astStatement = new ExpressionStatement((Ast.Expression)codeExpr);
}
} catch (NotImplementedException) {
astStatement = MakeComment(expr.LastByteCode.Description);
} else if (codeExpr is Ast.Statement) {
astStatement = (Ast.Statement)codeExpr;
}
return astStatement;
}
static Ast.ExpressionStatement MakeComment(string text)
{
text = "/*" + text + "*/";
text = "/***" + text + "***/";
return new Ast.ExpressionStatement(new PrimitiveExpression(text, text));
}
@ -215,7 +214,14 @@ namespace Decompiler @@ -215,7 +214,14 @@ namespace Decompiler
allArgs.Add(astExpr);
}
}
return MakeCodeDomExpression(methodDef, expr.LastByteCode, allArgs.ToArray());
try {
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)

15
src/ByteCode.Type.cs

@ -110,7 +110,7 @@ namespace Decompiler @@ -110,7 +110,7 @@ namespace Decompiler
case Code.Stelem_R4:
case Code.Stelem_R8:
case Code.Stelem_Ref:
case Code.Stelem_Any: return null;
case Code.Stelem_Any: return TypeVoid;
#endregion
#region Branching
case Code.Br:
@ -125,7 +125,7 @@ namespace Decompiler @@ -125,7 +125,7 @@ namespace Decompiler
case Code.Ble_Un:
case Code.Blt:
case Code.Blt_Un:
case Code.Bne_Un: return null;
case Code.Bne_Un: return TypeVoid;
#endregion
#region Comparison
case Code.Ceq:
@ -211,7 +211,10 @@ namespace Decompiler @@ -211,7 +211,10 @@ namespace Decompiler
case Code.Initobj: throw new NotImplementedException();
case Code.Isinst: 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.Ldc_I4: return TypeInt32;
case Code.Ldc_I8: throw new NotImplementedException();
@ -234,18 +237,18 @@ namespace Decompiler @@ -234,18 +237,18 @@ namespace Decompiler
case Code.Mkrefany: throw new NotImplementedException();
case Code.Newobj: 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.Pop: throw new NotImplementedException();
case Code.Readonly: throw new NotImplementedException();
case Code.Refanytype: 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.Sizeof: throw new NotImplementedException();
case Code.Starg: 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.Stsfld: throw new NotImplementedException();
case Code.Switch: throw new NotImplementedException();

17
src/ByteCode.cs

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

3
src/CilStack.cs

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

7
src/MainForm.cs

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

5
src/StackExpression.cs

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

Loading…
Cancel
Save