|
|
|
@ -1,41 +1,30 @@
@@ -1,41 +1,30 @@
|
|
|
|
|
using System; |
|
|
|
|
using System.CodeDom; |
|
|
|
|
using System.CodeDom.Compiler; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Windows.Forms; |
|
|
|
|
using Microsoft.CSharp; |
|
|
|
|
|
|
|
|
|
using Ast = ICSharpCode.NRefactory.Ast; |
|
|
|
|
using ICSharpCode.NRefactory.Ast; |
|
|
|
|
using ICSharpCode.NRefactory.PrettyPrinter; |
|
|
|
|
|
|
|
|
|
using Mono.Cecil; |
|
|
|
|
using Mono.Cecil.Cil; |
|
|
|
|
|
|
|
|
|
namespace Decompiler |
|
|
|
|
{ |
|
|
|
|
public class CodeDomBuilder |
|
|
|
|
public class ASTBuilder |
|
|
|
|
{ |
|
|
|
|
CodeCompileUnit codeCompileUnit = new CodeCompileUnit(); |
|
|
|
|
Dictionary<string, CodeNamespace> codeNamespaces = new Dictionary<string, CodeNamespace>(); |
|
|
|
|
CompilationUnit astCompileUnit = new CompilationUnit(); |
|
|
|
|
Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>(); |
|
|
|
|
|
|
|
|
|
public string GenerateCode() |
|
|
|
|
{ |
|
|
|
|
CSharpCodeProvider provider = new CSharpCodeProvider(); |
|
|
|
|
|
|
|
|
|
TextWriter stringWriter = new StringWriter(); |
|
|
|
|
CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor(); |
|
|
|
|
|
|
|
|
|
CodeGeneratorOptions options = new CodeGeneratorOptions(); |
|
|
|
|
options.BlankLinesBetweenMembers = true; |
|
|
|
|
options.BracingStyle = "C"; |
|
|
|
|
options.ElseOnClosing = true; |
|
|
|
|
options.IndentString = " "; |
|
|
|
|
options.VerbatimOrder = true; |
|
|
|
|
astCompileUnit.AcceptVisitor(csOutVisitor, null); |
|
|
|
|
|
|
|
|
|
provider.GenerateCodeFromCompileUnit(codeCompileUnit, stringWriter, options); |
|
|
|
|
|
|
|
|
|
// Remove the generated comments at the start
|
|
|
|
|
string code = stringWriter.ToString(); |
|
|
|
|
while(code.StartsWith("//") || code.StartsWith("\r\n")) { |
|
|
|
|
code = code.Remove(0, code.IndexOf("\r\n") + "\r\n".Length); |
|
|
|
|
} |
|
|
|
|
string code = csOutVisitor.Text.Replace("\t", " "); |
|
|
|
|
|
|
|
|
|
// Post processing commands
|
|
|
|
|
while(true) { |
|
|
|
@ -77,142 +66,152 @@ namespace Decompiler
@@ -77,142 +66,152 @@ namespace Decompiler
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CodeNamespace GetCodeNamespace(string name) |
|
|
|
|
NamespaceDeclaration GetCodeNamespace(string name) |
|
|
|
|
{ |
|
|
|
|
if (codeNamespaces.ContainsKey(name)) { |
|
|
|
|
return codeNamespaces[name]; |
|
|
|
|
if (astNamespaces.ContainsKey(name)) { |
|
|
|
|
return astNamespaces[name]; |
|
|
|
|
} else { |
|
|
|
|
// Create the namespace
|
|
|
|
|
CodeNamespace codeNamespace = new CodeNamespace(name); |
|
|
|
|
codeCompileUnit.Namespaces.Add(codeNamespace); |
|
|
|
|
codeNamespaces[name] = codeNamespace; |
|
|
|
|
return codeNamespace; |
|
|
|
|
NamespaceDeclaration astNamespace = new NamespaceDeclaration(name); |
|
|
|
|
astCompileUnit.Children.Add(astNamespace); |
|
|
|
|
astNamespaces[name] = astNamespace; |
|
|
|
|
return astNamespace; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void AddType(TypeDefinition typeDef) |
|
|
|
|
{ |
|
|
|
|
CodeTypeDeclaration codeType = CreateType(typeDef); |
|
|
|
|
GetCodeNamespace(typeDef.Namespace).Types.Add(codeType); |
|
|
|
|
TypeDeclaration astType = CreateType(typeDef); |
|
|
|
|
GetCodeNamespace(typeDef.Namespace).Children.Add(astType); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public CodeTypeDeclaration CreateType(TypeDefinition typeDef) |
|
|
|
|
public TypeDeclaration CreateType(TypeDefinition typeDef) |
|
|
|
|
{ |
|
|
|
|
CodeTypeDeclaration codeType = new CodeTypeDeclaration(); |
|
|
|
|
codeType.Name = typeDef.Name; |
|
|
|
|
|
|
|
|
|
// Copy modifiers across (includes 'is interface' attribute)
|
|
|
|
|
codeType.TypeAttributes = (System.Reflection.TypeAttributes)typeDef.Attributes; |
|
|
|
|
|
|
|
|
|
// Is struct or enum?
|
|
|
|
|
if (typeDef.IsValueType) { |
|
|
|
|
if (typeDef.IsEnum) { // NB: Enum is value type
|
|
|
|
|
codeType.IsEnum = true; |
|
|
|
|
} else { |
|
|
|
|
codeType.IsStruct = true; |
|
|
|
|
} |
|
|
|
|
TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>()); |
|
|
|
|
astType.Name = typeDef.Name; |
|
|
|
|
|
|
|
|
|
if (typeDef.IsEnum) { // NB: Enum is value type
|
|
|
|
|
astType.Type = ClassType.Enum; |
|
|
|
|
} else if (typeDef.IsValueType) { |
|
|
|
|
astType.Type = ClassType.Struct; |
|
|
|
|
} else if (typeDef.IsInterface) { |
|
|
|
|
astType.Type = ClassType.Interface; |
|
|
|
|
} else { |
|
|
|
|
astType.Type = ClassType.Class; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Nested types
|
|
|
|
|
foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) { |
|
|
|
|
codeType.Members.Add(CreateType(nestedTypeDef)); |
|
|
|
|
astType.Children.Add(CreateType(nestedTypeDef)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Base type
|
|
|
|
|
if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) { |
|
|
|
|
codeType.BaseTypes.Add(typeDef.BaseType.FullName); |
|
|
|
|
astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AddTypeMembers(codeType, typeDef); |
|
|
|
|
AddTypeMembers(astType, typeDef); |
|
|
|
|
|
|
|
|
|
return codeType; |
|
|
|
|
return astType; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MemberAttributes GetMethodAttributes(MethodDefinition methodDef) |
|
|
|
|
Modifiers ConvertModifiers(TypeDefinition typeDef) |
|
|
|
|
{ |
|
|
|
|
MemberAttributes noAttribs = (MemberAttributes)0; |
|
|
|
|
return |
|
|
|
|
// Access modifiers
|
|
|
|
|
(methodDef.IsCompilerControlled ? noAttribs : noAttribs) | |
|
|
|
|
(methodDef.IsPrivate ? MemberAttributes.Private : noAttribs) | |
|
|
|
|
(methodDef.IsFamilyAndAssembly ? MemberAttributes.FamilyAndAssembly : noAttribs) | |
|
|
|
|
(methodDef.IsAssembly ? MemberAttributes.Assembly : noAttribs) | |
|
|
|
|
(methodDef.IsFamily ? MemberAttributes.Family : noAttribs) | |
|
|
|
|
(methodDef.IsFamilyOrAssembly ? MemberAttributes.FamilyOrAssembly : noAttribs) | |
|
|
|
|
(methodDef.IsPublic ? MemberAttributes.Public : noAttribs) | |
|
|
|
|
// Others
|
|
|
|
|
(methodDef.IsStatic ? MemberAttributes.Static : noAttribs) | |
|
|
|
|
// Method specific
|
|
|
|
|
(methodDef.IsFinal ? MemberAttributes.Final : noAttribs) | |
|
|
|
|
(methodDef.IsAbstract ? MemberAttributes.Abstract : noAttribs); |
|
|
|
|
(typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) | |
|
|
|
|
(typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
|
|
|
|
|
(typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) | |
|
|
|
|
(typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(typeDef.IsPublic ? Modifiers.Public : Modifiers.None) | |
|
|
|
|
(typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AddTypeMembers(CodeTypeDeclaration codeType, TypeDefinition typeDef) |
|
|
|
|
Modifiers ConvertModifiers(FieldDefinition fieldDef) |
|
|
|
|
{ |
|
|
|
|
MemberAttributes noAttribs = (MemberAttributes)0; |
|
|
|
|
return |
|
|
|
|
(fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) | |
|
|
|
|
(fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
|
|
|
|
|
(fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) | |
|
|
|
|
(fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) | |
|
|
|
|
(fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) | |
|
|
|
|
(fieldDef.IsStatic ? Modifiers.Static : Modifiers.None); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Modifiers ConvertModifiers(MethodDefinition methodDef) |
|
|
|
|
{ |
|
|
|
|
return |
|
|
|
|
(methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) | |
|
|
|
|
(methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) | |
|
|
|
|
(methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
|
|
|
|
|
(methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) | |
|
|
|
|
(methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) | |
|
|
|
|
(methodDef.IsPublic ? Modifiers.Public : Modifiers.None) | |
|
|
|
|
(methodDef.IsStatic ? Modifiers.Static : Modifiers.None) | |
|
|
|
|
(methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) | |
|
|
|
|
(methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) |
|
|
|
|
{ |
|
|
|
|
// Add fields
|
|
|
|
|
foreach(FieldDefinition fieldDef in typeDef.Fields) { |
|
|
|
|
CodeMemberField codeField = new CodeMemberField(); |
|
|
|
|
codeField.Name = fieldDef.Name; |
|
|
|
|
codeField.Type = new CodeTypeReference(fieldDef.FieldType.FullName); |
|
|
|
|
codeField.Attributes = |
|
|
|
|
// Access modifiers
|
|
|
|
|
(fieldDef.IsCompilerControlled ? noAttribs : noAttribs) | |
|
|
|
|
(fieldDef.IsPrivate ? MemberAttributes.Private : noAttribs) | |
|
|
|
|
(fieldDef.IsFamilyAndAssembly ? MemberAttributes.FamilyAndAssembly : noAttribs) | |
|
|
|
|
(fieldDef.IsAssembly ? MemberAttributes.Assembly : noAttribs) | |
|
|
|
|
(fieldDef.IsFamily ? MemberAttributes.Family : noAttribs) | |
|
|
|
|
(fieldDef.IsFamilyOrAssembly ? MemberAttributes.FamilyOrAssembly : noAttribs) | |
|
|
|
|
(fieldDef.IsPublic ? MemberAttributes.Public : noAttribs) | |
|
|
|
|
// Others
|
|
|
|
|
(fieldDef.IsLiteral ? MemberAttributes.Const : noAttribs) | |
|
|
|
|
(fieldDef.IsStatic ? MemberAttributes.Static : noAttribs); |
|
|
|
|
|
|
|
|
|
codeType.Members.Add(codeField); |
|
|
|
|
Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>()); |
|
|
|
|
astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name)); |
|
|
|
|
astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName); |
|
|
|
|
astField.Modifier = ConvertModifiers(fieldDef); |
|
|
|
|
|
|
|
|
|
astType.Children.Add(astField); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add properties
|
|
|
|
|
foreach(PropertyDefinition propDef in typeDef.Properties) { |
|
|
|
|
CodeMemberProperty codeProp = new CodeMemberProperty(); |
|
|
|
|
codeProp.Name = propDef.Name; |
|
|
|
|
codeProp.Type = new CodeTypeReference(propDef.PropertyType.FullName); |
|
|
|
|
codeProp.Attributes = GetMethodAttributes(propDef.GetMethod); |
|
|
|
|
|
|
|
|
|
codeType.Members.Add(codeProp); |
|
|
|
|
Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration( |
|
|
|
|
ConvertModifiers(propDef.GetMethod), |
|
|
|
|
new List<AttributeSection>(), |
|
|
|
|
propDef.Name, |
|
|
|
|
new List<ParameterDeclarationExpression>() |
|
|
|
|
); |
|
|
|
|
astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName); |
|
|
|
|
astType.Children.Add(astProp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
foreach(EventDefinition eventDef in typeDef.Events) { |
|
|
|
|
CodeMemberEvent codeEvent = new CodeMemberEvent(); |
|
|
|
|
codeEvent.Name = eventDef.Name; |
|
|
|
|
codeEvent.Type = new CodeTypeReference(eventDef.EventType.FullName); |
|
|
|
|
codeEvent.Attributes = GetMethodAttributes(eventDef.AddMethod); |
|
|
|
|
Ast.EventDeclaration astEvent = new Ast.EventDeclaration(); |
|
|
|
|
astEvent.Name = eventDef.Name; |
|
|
|
|
astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName); |
|
|
|
|
astEvent.Modifier = ConvertModifiers(eventDef.AddMethod); |
|
|
|
|
|
|
|
|
|
codeType.Members.Add(codeEvent); |
|
|
|
|
astType.Children.Add(astEvent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
foreach(MethodDefinition methodDef in typeDef.Methods) { |
|
|
|
|
if (methodDef.IsSpecialName) continue; |
|
|
|
|
|
|
|
|
|
CodeMemberMethod codeMethod = new CodeMemberMethod(); |
|
|
|
|
codeMethod.Name = methodDef.Name; |
|
|
|
|
codeMethod.ReturnType = new CodeTypeReference(methodDef.ReturnType.ReturnType.FullName); |
|
|
|
|
codeMethod.Attributes = GetMethodAttributes(methodDef); |
|
|
|
|
Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration(); |
|
|
|
|
astMethod.Name = methodDef.Name; |
|
|
|
|
astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.ReturnType.FullName); |
|
|
|
|
astMethod.Modifier = ConvertModifiers(methodDef); |
|
|
|
|
|
|
|
|
|
foreach(ParameterDefinition paramDef in methodDef.Parameters) { |
|
|
|
|
CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(); |
|
|
|
|
codeParam.Name = paramDef.Name; |
|
|
|
|
codeParam.Type = new CodeTypeReference(paramDef.ParameterType.FullName); |
|
|
|
|
if (paramDef.IsIn && !paramDef.IsOut) codeParam.Direction = FieldDirection.In; |
|
|
|
|
if (!paramDef.IsIn && paramDef.IsOut) codeParam.Direction = FieldDirection.Out; |
|
|
|
|
if (paramDef.IsIn && paramDef.IsOut) codeParam.Direction = FieldDirection.Ref; |
|
|
|
|
|
|
|
|
|
codeMethod.Parameters.Add(codeParam); |
|
|
|
|
Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression( |
|
|
|
|
new Ast.TypeReference(paramDef.ParameterType.FullName), |
|
|
|
|
paramDef.Name |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if (paramDef.IsIn && !paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.In; |
|
|
|
|
if (!paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Out; |
|
|
|
|
if (paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Ref; |
|
|
|
|
|
|
|
|
|
astMethod.Parameters.Add(astParam); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
codeMethod.Statements.AddRange(CodeDomMetodBodyBuilder.CreateMetodBody(methodDef)); |
|
|
|
|
//astMethod.Statements.AddRange(ASTMetodBodyBuilder.CreateMetodBody(methodDef));
|
|
|
|
|
|
|
|
|
|
codeType.Members.Add(codeMethod); |
|
|
|
|
astType.Children.Add(astMethod); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|