/// <summary> /// Default ctor /// </summary> public AstBuilder(MethodDefinition methodDef, bool optimize, DecompilerContext context) { this.methodDef = methodDef; this.optimize = optimize; this.context = context; module = context.CurrentModule; }
/// <summary> /// Convert the given method into optimized Ast format. /// </summary> internal protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source, bool generateSetNextInstructionCode, StopAstConversion debugStop = StopAstConversion.None, AstOptimizationStep debugStopOptimizing = AstOptimizationStep.None ) { // Build AST DecompilerContext context; AstBlock ast; if (source.IsDotNet) { context = new DecompilerContext(source.Method); var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context); var children = astBuilder.Build(); ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children); if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum() || x.Name.EndsWith(NameConstants.Atomic.FieldUpdaterPostfix)))) { // Ensure all fields are initialized AddFieldInitializationCode(compiler, source, ast); } if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor")) { // Add code to save the generic instance type parameter into the generic instance field. AddGenericInstanceFieldInitializationCode(source, ast, compiler.Module.TypeSystem); } } else if (source.IsJava) { var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true); context = new DecompilerContext(source.Method); ast = astBuilder.Build(); } else if (source.IsAst) { context = new DecompilerContext(source.Method); ast = source.Ast; } else { throw new NotSupportedException("Unknown source"); } if (debugStop == StopAstConversion.AfterILConversion) return ast; // Optimize AST var astOptimizer = new AstOptimizer(context, ast); astOptimizer.Optimize(debugStopOptimizing); if (debugStop == StopAstConversion.AfterOptimizing) return ast; // Optimize AST towards the target TargetConverters.Convert(context, ast, source, compiler, debugStop); if(generateSetNextInstructionCode) SetNextInstructionGenerator.Convert(ast, source, compiler); // Return return return ast; }
/// <summary> /// Convert the given method into optimized Ast format. /// </summary> protected static AstNode CreateOptimizedAst(AssemblyCompiler compiler, MethodSource source) { // Build AST DecompilerContext context; AstBlock ast; if (source.IsDotNet) { context = new DecompilerContext(source.Method); var astBuilder = new IL2Ast.AstBuilder(source.ILMethod, true, context); var children = astBuilder.Build(); ast = new AstBlock(children.Select(x => x.SourceLocation).FirstOrDefault(), children); if ((source.ILMethod.IsConstructor) && (source.Method.DeclaringType.Fields.Any(x => x.FieldType.IsEnum()))) { // Ensure all fields are initialized AddFieldInitializationCode(source, ast); } if (source.Method.NeedsGenericInstanceTypeParameter && (source.Name == ".ctor")) { // Add code to safe the generic instance type parameter into the generic instance field. AddGenericInstanceFieldInitializationCode(ast); } } else if (source.IsJava) { var astBuilder = new Java2Ast.AstBuilder(compiler.Module, source.JavaMethod, source.Method.DeclaringType, true); context = new DecompilerContext(source.Method); ast = astBuilder.Build(); } else if (source.IsAst) { context = new DecompilerContext(source.Method); ast = source.Ast; } else { throw new NotSupportedException("Unknown source"); } // Optimize AST var astOptimizer = new AstOptimizer(context, ast); astOptimizer.Optimize(); // Optimize AST towards the target TargetConverters.Convert(context, ast, source, compiler); // Return return return ast; }
/// <summary> /// Load the text to display /// </summary> protected override string LoadText(ISpyContext settings) { var nl = Environment.NewLine; var sb = new StringBuilder(); sb.AppendFormat("AccessFlags: {0} (0x{1:X4}){2}", AccessFlagsAsString(methodDef.AccessFlags), (int)methodDef.AccessFlags, nl); sb.AppendFormat("Descriptor: {0}{1}", methodDef.Descriptor, nl); sb.AppendFormat("Signature: {0}{1}", (methodDef.Signature != null) ? methodDef.Signature.Original : "<none>", nl); sb.AppendFormat("Annotations: {0}{1}", TextNode.LoadAnnotations(methodDef), nl); var code = methodDef.Attributes.OfType<CodeAttribute>().FirstOrDefault(); if (code != null) { sb.AppendFormat("Max locals: {0}{1}", code.MaxLocals, nl); sb.AppendFormat("Max stack: {0}{1}", code.MaxStack, nl); sb.AppendLine("Code:"); foreach (var i in code.Instructions) { sb.AppendFormat("\t{0:x4} {1} {2} {3} {4}", i.Offset, Format(i.Opcode), FormatOperand(i.Operand), FormatOperand(i.Operand2), nl); } sb.AppendLine(); if (code.ExceptionHandlers.Any()) { sb.AppendLine("Exception handlers:"); foreach (var handler in code.ExceptionHandlers.OrderBy(x => x.StartPc)) { sb.AppendFormat("\t{0:x4}-{1:x4} => {2:x4} ({3}) {4}", handler.StartPc, handler.EndPc, handler.HandlerPc, handler.CatchType, nl); } sb.AppendLine(); } if (code.Attributes.OfType<LocalVariableTableAttribute>().Any()) { var locVarAttr = code.Attributes.OfType<LocalVariableTableAttribute>().First(); sb.AppendLine("Local variables:"); foreach (var locVar in locVarAttr.Variables.OrderBy(x => x.StartPc)) { sb.AppendFormat("\t{0:x4}-{1:x4} => {2} ({3}) {4}", locVar.StartPc, locVar.EndPc, locVar.Name, locVar.Index, nl); } sb.AppendLine(); } #if DEBUG if (settings.ShowAst) { sb.AppendLine("\n\nAST:\n"); try { var module = settings.Module; var xMethod = CompilerLib.XModel.Java.XBuilder.AsMethodDefinition(module, methodDef); var astBuilder = new CompilerLib.Java2Ast.AstBuilder(module, methodDef, xMethod.DeclaringType, true); var context = new DecompilerContext(xMethod); var ast = astBuilder.Build(); var writer = new PlainTextOutput(new StringWriter(sb)); ast.WriteTo(writer); writer.WriteLine(); // Optimize AST sb.AppendLine("\n\nOptimized AST:\n"); var astOptimizer = new AstOptimizer(context, ast); astOptimizer.Optimize(); ast.WriteTo(writer); writer.WriteLine(); } catch (Exception ex) { sb.Append(string.Format("Error: {0}\n\n{1}", ex.Message, ex.StackTrace)); } } #endif } return sb.ToString(); }