Browse Source

Fix crash when decompiling calli instruction. Closes #113.

pull/124/head
Daniel Grunwald 14 years ago
parent
commit
55dec5389c
  1. 5
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 12
      ICSharpCode.Decompiler/CecilExtensions.cs
  3. 6
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  4. 2
      ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs
  5. 4
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  6. 71
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  7. 2
      ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
  8. 2
      ICSharpCode.Decompiler/Tests/TestRunner.cs

5
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -291,11 +291,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -291,11 +291,6 @@ namespace ICSharpCode.Decompiler.Ast
return result;
}
public void Transform(IAstTransform transform)
{
transform.Run(astCompileUnit);
}
internal static string CleanName(string name)
{
int pos = name.LastIndexOf('`');

12
ICSharpCode.Decompiler/CecilExtensions.cs

@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler
throw new NotSupportedException ();
}
public static int GetPopDelta(this Instruction instruction, MethodDefinition current, int currentStackSize)
public static int? GetPopDelta(this Instruction instruction)
{
OpCode code = instruction.OpCode;
switch (code.StackBehaviourPop) {
@ -88,18 +88,18 @@ namespace ICSharpCode.Decompiler @@ -88,18 +88,18 @@ namespace ICSharpCode.Decompiler
return 3;
case StackBehaviour.PopAll:
return currentStackSize;
return null;
case StackBehaviour.Varpop:
if (code == OpCodes.Ret)
return IsVoid (current.ReturnType) ? 0 : 1;
return null;
if (code.FlowControl != FlowControl.Call)
break;
IMethodSignature method = (IMethodSignature) instruction.Operand;
int count = method.HasParameters ? method.Parameters.Count : 0;
if (method.HasThis && code != OpCodes.Newobj)
if (code == OpCodes.Calli || (method.HasThis && code != OpCodes.Newobj))
++count;
return count;
@ -110,7 +110,9 @@ namespace ICSharpCode.Decompiler @@ -110,7 +110,9 @@ namespace ICSharpCode.Decompiler
public static bool IsVoid(this TypeReference type)
{
return type.FullName == "System.Void" && !(type is TypeSpecification);
while (type is OptionalModifierType || type is RequiredModifierType)
type = ((TypeSpecification)type).ElementType;
return type.MetadataType == MetadataType.Void;
}
public static bool IsValueTypeOrVoid(this TypeReference type)

6
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -88,8 +88,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -88,8 +88,10 @@ namespace ICSharpCode.Decompiler.Disassembler
writer.Write("instance ");
method.ReturnType.WriteTo(writer);
writer.Write(' ');
method.DeclaringType.WriteTo(writer, true);
writer.Write("::");
if (method.DeclaringType != null) {
method.DeclaringType.WriteTo(writer, true);
writer.Write("::");
}
writer.WriteReference(method.Name, method);
writer.Write("(");
var parameters = method.Parameters;

2
ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs

@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
continue;
}
int popCount = inst.GetPopDelta(method, stackSize);
int popCount = inst.GetPopDelta() ?? stackSize;
stackSize -= popCount;
if (stackSize < 0)
throw new InvalidProgramException("IL stack underflow");

4
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -240,8 +240,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -240,8 +240,8 @@ namespace ICSharpCode.Decompiler.ILAst
EndOffset = inst.Next != null ? inst.Next.Offset : methodDef.Body.CodeSize,
Code = code,
Operand = operand,
PopCount = inst.GetPopCount(),
PushCount = inst.GetPushCount()
PopCount = inst.GetPopDelta(),
PushCount = inst.GetPushDelta()
};
if (prefixes != null) {
instrToByteCode[prefixes[0]] = byteCode;

71
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -343,77 +343,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -343,77 +343,6 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
public static int? GetPopCount(this Instruction inst)
{
switch(inst.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: return null;
case StackBehaviour.Varpop:
switch(inst.OpCode.Code) {
case Code.Call:
case Code.Callvirt:
MethodReference cecilMethod = ((MethodReference)inst.Operand);
if (cecilMethod.HasThis) {
return cecilMethod.Parameters.Count + 1 /* this */;
} else {
return cecilMethod.Parameters.Count;
}
case Code.Calli: throw new NotImplementedException();
case Code.Ret: return null;
case Code.Newobj:
MethodReference ctorMethod = ((MethodReference)inst.Operand);
return ctorMethod.Parameters.Count;
default: throw new Exception("Unknown Varpop opcode");
}
default: throw new Exception("Unknown pop behaviour: " + inst.OpCode.StackBehaviourPop);
}
}
public static int GetPushCount(this Instruction inst)
{
switch(inst.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(inst.OpCode.Code) {
case Code.Call:
case Code.Callvirt:
MethodReference cecilMethod = ((MethodReference)inst.Operand);
if (cecilMethod.ReturnType.FullName == "System.Void") {
return 0;
} else {
return 1;
}
case Code.Calli: throw new NotImplementedException();
default: throw new Exception("Unknown Varpush opcode");
}
default: throw new Exception("Unknown push behaviour: " + inst.OpCode.StackBehaviourPush);
}
}
public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody)
{
switch (code) {

2
ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests
AssemblyDefinition assembly = Compile(code);
AstBuilder decompiler = new AstBuilder(new DecompilerContext());
decompiler.AddAssembly(assembly);
decompiler.Transform(new Helpers.RemoveCompilerAttribute());
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
StringWriter output = new StringWriter();
decompiler.GenerateCode(new PlainTextOutput(output));
return output.ToString();

2
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler.Tests
AssemblyDefinition assembly = Compile(code);
AstBuilder decompiler = new AstBuilder(new DecompilerContext());
decompiler.AddAssembly(assembly);
decompiler.Transform(new Helpers.RemoveCompilerAttribute());
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
StringWriter output = new StringWriter();
decompiler.GenerateCode(new PlainTextOutput(output));
StringWriter diff = new StringWriter();

Loading…
Cancel
Save