From 55dec5389c27ff7f9512373bb279d42bb071af51 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 8 Apr 2011 23:41:23 +0200 Subject: [PATCH] Fix crash when decompiling calli instruction. Closes #113. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 5 -- ICSharpCode.Decompiler/CecilExtensions.cs | 12 ++-- .../Disassembler/DisassemblerHelpers.cs | 6 +- .../FlowAnalysis/SsaFormBuilder.cs | 2 +- ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 4 +- ICSharpCode.Decompiler/ILAst/ILCodes.cs | 71 ------------------- .../Tests/DecompilerTestBase.cs | 2 +- ICSharpCode.Decompiler/Tests/TestRunner.cs | 2 +- 8 files changed, 16 insertions(+), 88 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 3fd0595cb..6e43265d5 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -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('`'); diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs index 38e21e100..df7a9b0b6 100644 --- a/ICSharpCode.Decompiler/CecilExtensions.cs +++ b/ICSharpCode.Decompiler/CecilExtensions.cs @@ -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 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 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) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 1b4f680d6..e1c7e79e2 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -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; diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs index a59442c93..e6b7498c1 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs @@ -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"); diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index e265cecfd..df88a3f23 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -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; diff --git a/ICSharpCode.Decompiler/ILAst/ILCodes.cs b/ICSharpCode.Decompiler/ILAst/ILCodes.cs index 3e29f53bc..e26c8d265 100644 --- a/ICSharpCode.Decompiler/ILAst/ILCodes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILCodes.cs @@ -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) { diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs index 792088222..15787f0a2 100644 --- a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs +++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs @@ -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(); diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index 5fe7ce09a..57775beb3 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -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();