Browse Source

Move code from Util class to

- ByteCode.PopCount
 - ByteCode.PushCount
pull/1/head^2
David Srbecký 18 years ago
parent
commit
475eab39cf
  1. 6
      src/AstMetodBodyBuilder.cs
  2. 109
      src/ByteCode.cs
  3. 38
      src/ByteCodeCollection.cs
  4. 6
      src/StackAnalysis.cs
  5. 74
      src/Util.cs

6
src/AstMetodBodyBuilder.cs

@ -18,7 +18,7 @@ namespace Decompiler
methodDef.Body.Simplify(); methodDef.Body.Simplify();
ByteCodeCollection body = new ByteCodeCollection(methodDef.Body.Instructions); ByteCodeCollection body = new ByteCodeCollection(methodDef);
StackAnalysis stackAnalysis = new StackAnalysis(methodDef, body); StackAnalysis stackAnalysis = new StackAnalysis(methodDef, body);
foreach(VariableDefinition varDef in methodDef.Body.Variables) { foreach(VariableDefinition varDef in methodDef.Body.Variables) {
@ -41,7 +41,7 @@ namespace Decompiler
Ast.Statement astStatement = null; Ast.Statement astStatement = null;
try { try {
int argCount = Util.GetNumberOfInputs(methodDef, byteCode); int argCount = byteCode.PopCount;
Ast.Expression[] args = new Ast.Expression[argCount]; Ast.Expression[] args = new Ast.Expression[argCount];
for(int i = 0; i < argCount; i++) { for(int i = 0; i < argCount; i++) {
ByteCode allocBy = stackAnalysis.StackBefore[byteCode].Peek(argCount - i).AllocadedBy; ByteCode allocBy = stackAnalysis.StackBefore[byteCode].Peek(argCount - i).AllocadedBy;
@ -53,7 +53,7 @@ namespace Decompiler
byteCode, byteCode,
args); args);
if (codeExpr is Ast.Expression) { if (codeExpr is Ast.Expression) {
if (Util.GetNumberOfOutputs(methodDef, byteCode) == 1) { if (byteCode.PushCount == 1) {
string type = stackAnalysis.GetTypeOf(byteCode).FullName; string type = stackAnalysis.GetTypeOf(byteCode).FullName;
string name = string.Format("expr{0:X2}", byteCode.Offset); string name = string.Format("expr{0:X2}", byteCode.Offset);
Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString())); Ast.LocalVariableDeclaration astLocal = new Ast.LocalVariableDeclaration(new Ast.TypeReference(type.ToString()));

109
src/ByteCode.cs

@ -9,17 +9,42 @@ namespace Decompiler
{ {
public class ByteCode public class ByteCode
{ {
ByteCode previous;
ByteCode next; ByteCode next;
List<ByteCode> nestedByteCodes = new List<ByteCode>();
MethodDefinition methodDef;
int offset; int offset;
OpCode opCode; OpCode opCode;
object operand; object operand;
public ByteCode Previous {
get { return previous; }
set { previous = value; }
}
public ByteCode Next { public ByteCode Next {
get { return next; } get { return next; }
set { next = value; } set { next = value; }
} }
public int PopCount {
get {
return GetNumberOfInputs(methodDef, this);
}
}
public int PushCount {
get {
return GetNumberOfOutputs(methodDef, this);
}
}
public List<ByteCode> NestedByteCodes {
get { return nestedByteCodes; }
}
public int Offset { public int Offset {
get { return offset; } get { return offset; }
set { offset = value; } set { offset = value; }
@ -48,18 +73,86 @@ namespace Decompiler
} }
} }
public ByteCode(int offset, OpCode opCode, object operand) public ByteCode(MethodDefinition methodDef, Instruction inst)
{
this.offset = offset;
this.opCode = opCode;
this.operand = operand;
}
public ByteCode(Instruction inst)
{ {
this.methodDef = methodDef;
this.offset = inst.Offset; this.offset = inst.Offset;
this.opCode = inst.OpCode; this.opCode = inst.OpCode;
this.operand = inst.Operand; this.operand = inst.Operand;
} }
static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(byteCode.OpCode.StackBehaviourPop) {
case StackBehaviour.Pop0: return 0;
case StackBehaviour.Pop1: return 1;
case StackBehaviour.Popi: return 1;
case StackBehaviour.Popref: return 1;
case StackBehaviour.Pop1_pop1: return 2;
case StackBehaviour.Popi_pop1: return 2;
case StackBehaviour.Popi_popi: return 2;
case StackBehaviour.Popi_popi8: return 2;
case StackBehaviour.Popi_popr4: return 2;
case StackBehaviour.Popi_popr8: return 2;
case StackBehaviour.Popref_pop1: return 2;
case StackBehaviour.Popref_popi: return 2;
case StackBehaviour.Popi_popi_popi: return 3;
case StackBehaviour.Popref_popi_popi: return 3;
case StackBehaviour.Popref_popi_popi8: return 3;
case StackBehaviour.Popref_popi_popr4: return 3;
case StackBehaviour.Popref_popi_popr8: return 3;
case StackBehaviour.Popref_popi_popref: return 3;
case StackBehaviour.PopAll: throw new Exception("PopAll");
case StackBehaviour.Varpop:
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.HasThis) {
return cecilMethod.Parameters.Count + 1 /* this */;
} else {
return cecilMethod.Parameters.Count;
}
case Code.Calli: throw new NotImplementedException();
case Code.Callvirt: throw new NotImplementedException();
case Code.Ret:
if (methodDef.ReturnType.ReturnType.FullName == Constants.Void) {
return 0;
} else {
return 1;
}
case Code.Newobj: throw new NotImplementedException();
default: throw new Exception("Unknown Varpop opcode");
}
default: throw new Exception("Unknown pop behaviour: " + byteCode.OpCode.StackBehaviourPop);
}
}
static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(byteCode.OpCode.StackBehaviourPush) {
case StackBehaviour.Push0: return 0;
case StackBehaviour.Push1: return 1;
case StackBehaviour.Push1_push1: return 2;
case StackBehaviour.Pushi: return 1;
case StackBehaviour.Pushi8: return 1;
case StackBehaviour.Pushr4: return 1;
case StackBehaviour.Pushr8: return 1;
case StackBehaviour.Pushref: return 1;
case StackBehaviour.Varpush: // Happens only for calls
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.ReturnType.ReturnType.FullName == Constants.Void) {
return 0;
} else {
return 1;
}
case Code.Calli: throw new NotImplementedException();
case Code.Callvirt: throw new NotImplementedException();
default: throw new Exception("Unknown Varpush opcode");
}
default: throw new Exception("Unknown push behaviour: " + byteCode.OpCode.StackBehaviourPush);
}
}
} }
} }

38
src/ByteCodeCollection.cs

@ -10,27 +10,27 @@ namespace Decompiler
{ {
public class ByteCodeCollection: IEnumerable<ByteCode> public class ByteCodeCollection: IEnumerable<ByteCode>
{ {
List<ByteCode> byteCodes = new List<ByteCode>(); List<ByteCode> list = new List<ByteCode>();
public IEnumerator<ByteCode> GetEnumerator() public IEnumerator<ByteCode> GetEnumerator()
{ {
return byteCodes.GetEnumerator(); return list.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return byteCodes.GetEnumerator(); return list.GetEnumerator();
} }
public int Count { public int Count {
get { get {
return byteCodes.Count; return list.Count;
} }
} }
public ByteCode this[int index] { public ByteCode this[int index] {
get { get {
return byteCodes[index]; return list[index];
} }
} }
@ -44,18 +44,38 @@ namespace Decompiler
throw new Exception("Not found"); throw new Exception("Not found");
} }
public ByteCodeCollection(InstructionCollection instCol) public int IndexOf(ByteCode byteCode)
{ {
foreach(Instruction inst in instCol) { return list.IndexOf(byteCode);
byteCodes.Add(new ByteCode(inst)); }
public void Remove(ByteCode byteCode)
{
int index = IndexOf(byteCode);
list.RemoveAt(index);
byteCode.Next = null;
byteCode.Previous = null;
UpdateNextPrevious();
}
public ByteCodeCollection(MethodDefinition methodDef)
{
foreach(Instruction inst in methodDef.Body.Instructions) {
list.Add(new ByteCode(methodDef, inst));
} }
foreach(ByteCode byteCode in this) { foreach(ByteCode byteCode in this) {
if (byteCode.CanBranch) { if (byteCode.CanBranch) {
byteCode.Operand = GetByOffset(((Instruction)byteCode.Operand).Offset); byteCode.Operand = GetByOffset(((Instruction)byteCode.Operand).Offset);
} }
} }
for(int i = 0; i < byteCodes.Count - 1; i++) { UpdateNextPrevious();
}
void UpdateNextPrevious()
{
for(int i = 0; i < list.Count - 1; i++) {
this[i].Next = this[i + 1]; this[i].Next = this[i + 1];
this[i + 1].Previous = this[i];
} }
} }
} }

6
src/StackAnalysis.cs

@ -124,7 +124,7 @@ namespace Decompiler
public Cecil.TypeReference GetTypeOf(ByteCode byteCode) public Cecil.TypeReference GetTypeOf(ByteCode byteCode)
{ {
if (Util.GetNumberOfOutputs(methodDef, byteCode) == 0) { if (byteCode.PushCount == 0) {
return TypeVoid; return TypeVoid;
} else { } else {
return StackAfter[byteCode].Peek(1).Type; return StackAfter[byteCode].Peek(1).Type;
@ -179,12 +179,12 @@ namespace Decompiler
CilStack ChangeStack(CilStack oldStack, ByteCode byteCode) CilStack ChangeStack(CilStack oldStack, ByteCode byteCode)
{ {
CilStack newStack = oldStack.Clone(); CilStack newStack = oldStack.Clone();
CilStackSlot[] popedSlots = newStack.PopCount(Util.GetNumberOfInputs(methodDef, byteCode)); CilStackSlot[] popedSlots = newStack.PopCount(byteCode.PopCount);
List<Cecil.TypeReference> typeArgs = new List<Cecil.TypeReference>(); List<Cecil.TypeReference> typeArgs = new List<Cecil.TypeReference>();
foreach(CilStackSlot slot in popedSlots) { foreach(CilStackSlot slot in popedSlots) {
typeArgs.Add(slot.Type); typeArgs.Add(slot.Type);
} }
for (int i = 0; i < Util.GetNumberOfOutputs(methodDef, byteCode); i++) { for (int i = 0; i < byteCode.PushCount; i++) {
newStack.Push(new CilStackSlot(byteCode, GetType(methodDef, byteCode, typeArgs.ToArray()))); newStack.Push(new CilStackSlot(byteCode, GetType(methodDef, byteCode, typeArgs.ToArray())));
} }
return newStack; return newStack;

74
src/Util.cs

@ -11,78 +11,6 @@ namespace Decompiler
{ {
public static class Util public static class Util
{ {
public static int GetNumberOfInputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(byteCode.OpCode.StackBehaviourPop) {
case StackBehaviour.Pop0: return 0;
case StackBehaviour.Pop1: return 1;
case StackBehaviour.Popi: return 1;
case StackBehaviour.Popref: return 1;
case StackBehaviour.Pop1_pop1: return 2;
case StackBehaviour.Popi_pop1: return 2;
case StackBehaviour.Popi_popi: return 2;
case StackBehaviour.Popi_popi8: return 2;
case StackBehaviour.Popi_popr4: return 2;
case StackBehaviour.Popi_popr8: return 2;
case StackBehaviour.Popref_pop1: return 2;
case StackBehaviour.Popref_popi: return 2;
case StackBehaviour.Popi_popi_popi: return 3;
case StackBehaviour.Popref_popi_popi: return 3;
case StackBehaviour.Popref_popi_popi8: return 3;
case StackBehaviour.Popref_popi_popr4: return 3;
case StackBehaviour.Popref_popi_popr8: return 3;
case StackBehaviour.Popref_popi_popref: return 3;
case StackBehaviour.PopAll: throw new Exception("PopAll");
case StackBehaviour.Varpop:
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.HasThis) {
return cecilMethod.Parameters.Count + 1 /* this */;
} else {
return cecilMethod.Parameters.Count;
}
case Code.Calli: throw new NotImplementedException();
case Code.Callvirt: throw new NotImplementedException();
case Code.Ret:
if (methodDef.ReturnType.ReturnType.FullName == Constants.Void) {
return 0;
} else {
return 1;
}
case Code.Newobj: throw new NotImplementedException();
default: throw new Exception("Unknown Varpop opcode");
}
default: throw new Exception("Unknown pop behaviour: " + byteCode.OpCode.StackBehaviourPop);
}
}
public static int GetNumberOfOutputs(MethodDefinition methodDef, ByteCode byteCode)
{
switch(byteCode.OpCode.StackBehaviourPush) {
case StackBehaviour.Push0: return 0;
case StackBehaviour.Push1: return 1;
case StackBehaviour.Push1_push1: return 2;
case StackBehaviour.Pushi: return 1;
case StackBehaviour.Pushi8: return 1;
case StackBehaviour.Pushr4: return 1;
case StackBehaviour.Pushr8: return 1;
case StackBehaviour.Pushref: return 1;
case StackBehaviour.Varpush: // Happens only for calls
switch(byteCode.OpCode.Code) {
case Code.Call:
Cecil.MethodReference cecilMethod = ((MethodReference)byteCode.Operand);
if (cecilMethod.ReturnType.ReturnType.FullName == Constants.Void) {
return 0;
} else {
return 1;
}
case Code.Calli: throw new NotImplementedException();
case Code.Callvirt: throw new NotImplementedException();
default: throw new Exception("Unknown Varpush opcode");
}
default: throw new Exception("Unknown push behaviour: " + byteCode.OpCode.StackBehaviourPush);
}
}
} }
} }

Loading…
Cancel
Save