示例#1
0
		/// <summary>
		/// Compiles and decompiles a source code.
		/// </summary>
		/// <param name="code">The source code to copile.</param>
		/// <returns>The decompilation result of compiled source code.</returns>
		static string RoundtripCode(string code)
		{
			DecompilerSettings settings = new DecompilerSettings();
			settings.FullyQualifyAmbiguousTypeNames = false;
			AssemblyDefinition assembly = Compile(code);
			AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule) { Settings = settings });
			decompiler.AddAssembly(assembly);
			new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
			StringWriter output = new StringWriter();
			decompiler.GenerateCode(new PlainTextOutput(output));
			return output.ToString();
		}
示例#2
0
 public CallBuilder(ExpressionBuilder expressionBuilder, IDecompilerTypeSystem typeSystem, DecompilerSettings settings)
 {
     this.expressionBuilder = expressionBuilder;
     this.resolver          = expressionBuilder.resolver;
     this.settings          = settings;
     this.typeSystem        = typeSystem;
 }
示例#3
0
        async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
        {
            var vbFile  = Path.Combine(TestCasePath, testName + ".vb");
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe";

            if (options.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            var executable = await Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile).ConfigureAwait(false);

            var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings).ConfigureAwait(false);

            CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
        }
示例#4
0
        public static int ShowDuplicateImports(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);

            Dictionary <string, List <string> > dllImportsToClassNames = new Dictionary <string, List <string> >();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                if (type1.Kind != TypeKind.Class)
                {
                    continue;
                }

                foreach (var method in type1.GetMethods())
                {
                    if (!method.IsStatic)
                    {
                        continue;
                    }

                    var dllImportAttr = method.GetAttribute(KnownAttribute.DllImport);
                    if (dllImportAttr != null)
                    {
                        string entryPoint    = method.Name;
                        var    dllName       = (string)(dllImportAttr.FixedArguments[0].Value);
                        var    entryPointVar = dllImportAttr.NamedArguments.FirstOrDefault(a => a.Name == "EntryPoint");
                        if (entryPointVar.Name != null)
                        {
                            entryPoint = (string)entryPointVar.Value;
                        }

                        string fullImport = $"{dllName}:{entryPoint}";
                        string archInfo   = GetArchInfo(method.GetAttributes());
                        if (!string.IsNullOrEmpty(archInfo))
                        {
                            fullImport += $"({archInfo})";
                        }

                        if (!dllImportsToClassNames.TryGetValue(fullImport, out var classNames))
                        {
                            classNames = new List <string>();
                            dllImportsToClassNames[fullImport] = classNames;
                        }

                        classNames.Add(type1.FullName);
                    }
                }
            }

            bool dupsFound = false;

            foreach (var pair in dllImportsToClassNames)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicated imports detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var imp in pair.Value)
                    {
                        console?.Out.Write($"  {imp}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate imports found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
示例#5
0
        public static int ShowDuplicateConstants(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);
            Dictionary <string, List <string> > nameToOwner = new Dictionary <string, List <string> >();

            foreach (var type in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type.FullName == "<Module>")
                {
                    continue;
                }

                if (type.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                // Skip enums marked as a scoped enum (like a C++ class enum).
                // We don't count these in the duplicated constants
                if (type.Kind == TypeKind.Enum)
                {
                    if (type.GetAttributes().Any(a => a.AttributeType.Name == "ScopedEnumAttribute"))
                    {
                        continue;
                    }
                }

                if (type.Kind == TypeKind.Enum || (type.Kind == TypeKind.Class && type.Name == "Apis"))
                {
                    foreach (var field in type.GetFields(options: GetMemberOptions.IgnoreInheritedMembers))
                    {
                        if (field.Name == "value__")
                        {
                            continue;
                        }

                        if (!nameToOwner.TryGetValue(field.Name, out var owners))
                        {
                            owners = new List <string>();
                            nameToOwner[field.Name] = owners;
                        }

                        owners.Add(type.FullName);
                    }
                }
            }

            bool dupsFound = false;

            foreach (var pair in nameToOwner)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicate constants/enum names detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var owner in pair.Value)
                    {
                        console?.Out.Write($"  {owner}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate constants/enum names found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
示例#6
0
 public StatementBuilder(IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, IMethod currentMethod, ILFunction currentFunction, DecompilerSettings settings, CancellationToken cancellationToken)
 {
     Debug.Assert(typeSystem != null && decompilationContext != null && currentMethod != null);
     this.exprBuilder       = new ExpressionBuilder(typeSystem, decompilationContext, settings, cancellationToken);
     this.currentFunction   = currentFunction;
     this.currentMethod     = currentMethod;
     this.settings          = settings;
     this.cancellationToken = cancellationToken;
 }
示例#7
0
 public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, IDebugInfoProvider debugInfo, DecompilerSettings settings = null)
 {
     this.Function   = function ?? throw new ArgumentNullException(nameof(function));
     this.TypeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
     this.Settings   = settings ?? new DecompilerSettings();
     this.DebugInfo  = debugInfo;
     Stepper         = new Stepper();
 }
        public static async Task <List <ReferenceSegment> > DecompileAsync(TextEditor data, AssemblyLoader assemblyLoader, Func <CSharpDecompiler, SyntaxTree> decompile, DecompilerSettings settings = null, DecompileFlags flags = null)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (assemblyLoader == null)
            {
                throw new ArgumentNullException(nameof(assemblyLoader));
            }

            return(await Task.Run(async delegate {
                settings = settings ?? GetDecompilerSettings(data, publicOnly: flags.PublicOnly);
                var csharpDecompiler = assemblyLoader.CSharpDecompiler;
                try {
                    var syntaxTree = decompile(csharpDecompiler);
                    if (!flags.MethodBodies)
                    {
                        MethodBodyRemoveVisitor.RemoveMethodBodies(syntaxTree);
                    }
                    return await Runtime.RunInMainThread(delegate {
                        if (data.IsDisposed)
                        {
                            return new List <ReferenceSegment> ();
                        }
                        var output = new ColoredCSharpFormatter(data);
                        TokenWriter tokenWriter = new TextTokenWriter(output, settings, csharpDecompiler.TypeSystem)
                        {
                            FoldBraces = settings.FoldBraces
                        };
                        var formattingPolicy = settings.CSharpFormattingOptions;
                        syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, formattingPolicy));
                        output.SetDocumentData();
                        return output.ReferencedSegments;
                    });
                } catch (Exception e) {
                    await Runtime.RunInMainThread(delegate {
                        data.InsertText(data.Length, "/* decompilation failed: \n" + e + " */");
                    });
                }
                return new List <ReferenceSegment> ();
            }));
        }
示例#9
0
        async Task RunInternal(string dir, string fileToRoundtrip, Action <string> testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false)
        {
            if (!Directory.Exists(TestDir))
            {
                Assert.Ignore($"Assembly-roundtrip test ignored: test directory '{TestDir}' needs to be checked out separately." + Environment.NewLine +
                              $"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\"");
            }
            string inputDir      = Path.Combine(TestDir, dir);
            string decompiledDir = inputDir + "-decompiled";
            string outputDir     = inputDir + "-output";

            if (inputDir.EndsWith("TestCases"))
            {
                // make sure output dir names are unique so that we don't get trouble due to parallel test execution
                decompiledDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString();
                outputDir     += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString();
            }
            ClearDirectory(decompiledDir);
            ClearDirectory(outputDir);
            string projectFile = null;

            foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories))
            {
                if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
                {
                    Assert.Fail($"Unexpected file name: {file}");
                }
                string relFile = file.Substring(inputDir.Length + 1);
                Directory.CreateDirectory(Path.Combine(outputDir, Path.GetDirectoryName(relFile)));
                if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase))
                {
                    Console.WriteLine($"Decompiling {fileToRoundtrip}...");
                    Stopwatch w = Stopwatch.StartNew();
                    using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
                    {
                        PEFile module   = new PEFile(file, fileStream, PEStreamOptions.PrefetchEntireImage);
                        var    resolver = new TestAssemblyResolver(file, inputDir, module.Metadata.DetectTargetFrameworkId());
                        resolver.AddSearchDirectory(inputDir);
                        resolver.RemoveSearchDirectory(".");

                        // use a fixed GUID so that we can diff the output between different ILSpy runs without spurious changes
                        var projectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}");

                        var settings = new DecompilerSettings(languageVersion);
                        if (useOldProjectFormat)
                        {
                            settings.UseSdkStyleProjectFormat = false;
                        }

                        var decompiler = new TestProjectDecompiler(projectGuid, resolver, resolver, settings);

                        if (snkFilePath != null)
                        {
                            decompiler.StrongNameKeyFile = Path.Combine(inputDir, snkFilePath);
                        }
                        decompiler.DecompileProject(module, decompiledDir);
                        Console.WriteLine($"Decompiled {fileToRoundtrip} in {w.Elapsed.TotalSeconds:f2}");
                        projectFile = Path.Combine(decompiledDir, module.Name + ".csproj");
                    }
                }
                else
                {
                    File.Copy(file, Path.Combine(outputDir, relFile));
                }
            }
            Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}");

            await Compile(projectFile, outputDir);

            testAction(outputDir);
        }
 public CSharpVBDecompilerSettings(DecompilerSettings decompilerSettings = null)
 {
     this.decompilerSettings = decompilerSettings ?? new DecompilerSettings();
     options = CreateOptions().ToArray();
 }
示例#11
0
        /// <summary>
        /// Gets/sets an optional state of a decompiler text view.
        /// </summary>
        /// <remarks>
        /// This state is used to restore test view's state when decompilation is started by Go Back/Forward action.
        /// </remarks>
        //public ICSharpCode.ILSpy.TextView.DecompilerTextViewState TextViewState { get; set; }

        public DecompilationOptions()
        {
            //this.DecompilerSettings = DecompilerSettingsPanel.CurrentDecompilerSettings;
            this.DecompilerSettings = new DecompilerSettings();
            this.FullDecompilation  = false;
        }
 private static string Decompile(Assemblies.AssemblyDefinition asm, IEnumerable<TypeDefinition> types)
 {
     DecompilerSettings settings = new DecompilerSettings();
     settings.FullyQualifyAmbiguousTypeNames = false;
     var ctx = new DecompilerContext(asm.MainModule) { Settings = settings };
     var decompiler = new AstBuilder(ctx);
     foreach (var t in types)
     {
         decompiler.AddType(t);
     }
     new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
     var output = new StringWriter();
     decompiler.GenerateCode(new PlainTextOutput(output));
     return output.ToString().Trim();
 }
 public static void Decompile(string path)
 {
     var asm = AssemblyDefinition.ReadAssembly(path);
     var settings = new DecompilerSettings();
     settings.FullyQualifyAmbiguousTypeNames = false;
     var ctx = new DecompilerContext(asm.MainModule) { Settings = settings };
     var decompiler = new AstBuilder(ctx);
     decompiler.AddAssembly(asm);
     new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
     var output = new StringWriter();
     decompiler.GenerateCode(new PlainTextOutput(output));
 }
示例#14
0
        public void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilerSettings options)
        {
            AddReferenceWarningMessage(property.Module.Assembly, output);
            WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
            CSharpDecompiler decompiler = CreateDecompiler(property.Module, options);

            WriteCode(output, options, decompiler.Decompile(property), decompiler.TypeSystem);
        }
示例#15
0
 void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
 {
     Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);
 }
示例#16
0
        // Extraction of strings
        private void ExtractEncryptedStrings(object sender, DoWorkEventArgs args)
        {
            // Get assembly name from arguments
            string assemblyName = (string)args.Argument;

            // Build new payload object
            Payload payload = new Payload();

            // Setup decompiler
            DecompilerSettings settings = new DecompilerSettings();

            settings.FullyQualifyAmbiguousTypeNames = true;
            var resolver = new DefaultAssemblyResolver();

            resolver.AddSearchDirectory(Environment.CurrentDirectory);

            var parameters = new ReaderParameters
            {
                AssemblyResolver = resolver,
            };

            AssemblyDefinition assembly1 = AssemblyDefinition.ReadAssembly(assemblyName);

            // Add assembly to the decompiler
            AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly1.MainModule)
            {
                Settings = settings
            });

            decompiler.AddAssembly(assembly1);

            // Generate the code
            StringWriter output = new StringWriter();

            decompiler.GenerateCode(new PlainTextOutput(output));

            // Get the code from the decompiler into a string
            byte[]     byteArray  = Encoding.ASCII.GetBytes(output.ToString());
            TextReader codeReader = new StreamReader(new MemoryStream(byteArray));
            string     code       = codeReader.ReadToEnd();

            // Build regex to extract strings
            List <string> SharedSecretPatterns = new List <string>()
            {
                @"private static string msaltpassss = \""(?<SharedSecret>.+)\"";",
                @"private static string e1 = \""(?<SharedSecret>.+)\"";"
            };
            List <string> SaltPatterns = new List <string>()
            {
                @"private static byte\[\] _salt = Encoding.ASCII.GetBytes\(\""(?<Salt>.+)\""\);"
            };
            List <string> EncryptedStringsPatterns = new List <string>()
            {
                @"encc.DecryptStringAES\(\""(?<String>.+)\"",",
                @"encc.myff11\(\""(?<String>.+)\"",",
                @"\""(?<String>([A-F0-9]{2})*)\"""
            };

            // Enumerate the shared secret patterns
            foreach (string SharedSecretPattern in SharedSecretPatterns)
            {
                // Match regex
                Match SharedSecretMatch = Regex.Match(code, SharedSecretPattern);

                // Check for success
                if (SharedSecretMatch.Success)
                {
                    // Extract the value
                    payload.SharedSecret = SharedSecretMatch.Groups["SharedSecret"].Value;
                    break;
                }
            }

            // Enumerate the salt patterns
            foreach (string SaltPattern in SaltPatterns)
            {
                // Match regex
                Match SaltMatch = Regex.Match(code, SaltPattern);

                // Check for success
                if (SaltMatch.Success)
                {
                    // Extract the value
                    payload.Salt = SaltMatch.Groups["Salt"].Value;
                    break;
                }
            }

            // Enumerate encrypted string patterns
            foreach (string EncryptedStringsPattern in EncryptedStringsPatterns)
            {
                // Match regex
                MatchCollection StringsMatch = Regex.Matches(code, EncryptedStringsPattern);

                // Check for success
                if (StringsMatch.Count > 0)
                {
                    // Extract the value
                    payload.Strings = StringsMatch.Cast <Match>().Select(m => m.Groups["String"].Value).ToList();
                    break;
                }
            }

            // Set the payload object as the result
            args.Result = payload;
        }
示例#17
0
 public TestProjectDecompiler(Guid projecGuid, IAssemblyResolver resolver, AssemblyReferenceClassifier assemblyReferenceClassifier, DecompilerSettings settings)
     : base(settings, projecGuid, resolver, assemblyReferenceClassifier, debugInfoProvider: null)
 {
 }
示例#18
0
        internal static DecompilerSettings CreateDecompilerSettings_DecompileTypeMethods(DecompilerSettings settings, bool useUsingDeclarations, bool showAll)
        {
            var s = CreateDecompilerSettings(settings, useUsingDeclarations);

            // Make sure the ctor is shown if the user tries to edit an empty ctor/cctor
            s.RemoveEmptyDefaultConstructors = false;
            if (!showAll)
            {
                // Inline all field initialization code
                s.AllowFieldInitializers = false;
            }
            return(s);
        }
        /// <summary>
        /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
        /// </summary>
        internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings settings)
        {
            if (binary.IsLifted)
            {
                if (!NullableType.IsNullable(type))
                {
                    return(false);
                }
                type = NullableType.GetUnderlyingType(type);
            }
            if (type.Kind == TypeKind.Unknown)
            {
                return(false);                // avoid introducing a potentially-incorrect compound assignment
            }
            else if (type.Kind == TypeKind.Enum)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                case BinaryNumericOperator.BitAnd:
                case BinaryNumericOperator.BitOr:
                case BinaryNumericOperator.BitXor:
                    break;                             // OK

                default:
                    return(false);                            // operator not supported on enum types
                }
            }
            else if (type.Kind == TypeKind.Pointer)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                    // ensure that the byte offset is a multiple of the pointer size
                    return(PointerArithmeticOffset.Detect(
                               binary.Right,
                               ((PointerType)type).ElementType,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            else if (type.IsKnownType(KnownTypeCode.IntPtr) || type.IsKnownType(KnownTypeCode.UIntPtr))
            {
                // "target.intptr *= 2;" is compiler error, but
                // "target.intptr *= (nint)2;" works
                if (settings != null && !settings.NativeIntegers)
                {
                    // But if native integers are not available, we cannot use compound assignment.
                    return(false);
                }
                // The trick with casting the RHS to n(u)int doesn't work for shifts:
                switch (binary.Operator)
                {
                case BinaryNumericOperator.ShiftLeft:
                case BinaryNumericOperator.ShiftRight:
                    return(false);
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.IsCSharpSmallIntegerType())
                {
                    // C# will use numeric promotion to int, binary op must be signed
                    if (binary.Sign != Sign.Signed)
                    {
                        return(false);
                    }
                }
                else
                {
                    // C# will use sign from type
                    if (type.GetSign() != binary.Sign)
                    {
                        return(false);
                    }
                }
            }
            // Can't transform if the RHS value would be need to be truncated for the LHS type.
            if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, null, binary.IsLifted))
            {
                return(false);
            }
            return(true);
        }
 public CSharpVBDecompilerSettings(DecompilerSettings?decompilerSettings = null)
 {
     this.decompilerSettings = decompilerSettings ?? new DecompilerSettings();
     options = CreateOptions().ToArray();
     this.decompilerSettings.SettingsVersionChanged += DecompilerSettings_SettingsVersionChanged;
 }
示例#21
0
        public static List <ReferenceSegment> Decompile(TextEditor data, AssemblyLoader assemblyLoader, Func <CSharpDecompiler, SyntaxTree> decompile, DecompilerSettings settings = null, DecompileFlags flags = null)
        {
            settings = settings ?? GetDecompilerSettings(data, publicOnly: flags.PublicOnly);
            var csharpDecompiler = assemblyLoader.CSharpDecompiler;

            try {
                var syntaxTree = decompile(csharpDecompiler);
                if (!flags.MethodBodies)
                {
                    MethodBodyRemoveVisitor.RemoveMethodBodies(syntaxTree);
                }

                var         output      = new ColoredCSharpFormatter(data);
                TokenWriter tokenWriter = new TextTokenWriter(output, settings, csharpDecompiler.TypeSystem)
                {
                    FoldBraces = settings.FoldBraces
                };
                var formattingPolicy = settings.CSharpFormattingOptions;
                syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, formattingPolicy));
                output.SetDocumentData();
                return(output.ReferencedSegments);
            } catch (Exception e) {
                data.InsertText(data.Length, "/* decompilation failed: \n" + e + " */");
            }
            return(null);
        }
示例#22
0
        public static int CompareWinmds(FileInfo first, FileInfo second, string exclusions, IConsole console)
        {
            bool same = true;

            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(first.FullName, settings);
            DecompilerTypeSystem winmd2 = CreateTypeSystemFromFile(second.FullName, settings);

            var winmd1Types = GetSelfDefinedWinmdToplevelTypes(winmd1);
            var winmd2Types = GetSelfDefinedWinmdToplevelTypes(winmd2);

            same &= CompareTypes(winmd1Types, winmd2Types, console);

            var apiNameToMembers1 = GetApiMemberNamesToMemberDefinitions(winmd1);
            var apiNameToMembers2 = GetApiMemberNamesToMemberDefinitions(winmd2);

            HashSet <string> visitedM2Names = new HashSet <string>();

            foreach (var api1MemberInfo in apiNameToMembers1)
            {
                if (apiNameToMembers2.TryGetValue(api1MemberInfo.Key, out var api2Members))
                {
                    foreach (var m1 in api1MemberInfo.Value)
                    {
                        string m1FullName = GetFullMemberName(m1);
                        bool   found      = false;

                        foreach (var m2 in api2Members)
                        {
                            if (m1.GetType() == m2.GetType())
                            {
                                string m2FullName = GetFullMemberName(m2);

                                bool membersSame;
                                if (m1 is IField)
                                {
                                    membersSame = CompareFields((IField)m1, (IField)m2, console);
                                }
                                else
                                {
                                    membersSame = CompareMethods((IMethod)m1, (IMethod)m2, null);

                                    // If the members aren't the same on the methods and the namespaces also aren't
                                    // the same, then assume these aren't the same methods and keep going
                                    if (!membersSame && (m1.Namespace != m2.Namespace))
                                    {
                                        continue;
                                    }

                                    if (!membersSame && console != null)
                                    {
                                        CompareMethods((IMethod)m1, (IMethod)m2, console);
                                    }
                                }

                                if (membersSame)
                                {
                                    if (m1.Namespace != m2.Namespace)
                                    {
                                        console?.Out.Write($"{m1FullName} => {m2FullName}\r\n");
                                        membersSame = false;
                                    }
                                }

                                same &= membersSame;

                                visitedM2Names.Add(m2FullName);
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n");
                        }
                    }
                }
                else
                {
                    foreach (var m1 in api1MemberInfo.Value)
                    {
                        string m1FullName = GetFullMemberName(m1);
                        console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n");
                        same = false;
                    }
                }
            }

            foreach (var api2MemberInfo in apiNameToMembers2)
            {
                foreach (var api2Member in api2MemberInfo.Value)
                {
                    string m2FullName = GetFullMemberName(api2Member);
                    if (!visitedM2Names.Contains(m2FullName))
                    {
                        console?.Out.Write($"{m2FullName} not found in 1st winmd\r\n");
                        same = false;
                    }
                }
            }

            if (same)
            {
                console.Out.Write($"No differences in winmd contents.\r\n");
            }

            return(same ? 0 : -1);
        }
示例#23
0
        void Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
        {
            var vbFile  = Path.Combine(TestCasePath, testName + ".vb");
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe";

            if (options.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            var executable = Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile);
            var decompiled = Tester.DecompileCSharp(executable.PathToAssembly, settings);

            CodeAssert.FilesAreEqual(csFile, decompiled);
        }
示例#24
0
        public static int ShowDuplicateTypes(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);

            Dictionary <string, List <string> > nameToNamespaces = new Dictionary <string, List <string> >();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                var typeName = type1.Name;
                if (type1.Kind == TypeKind.Class && typeName == "Apis")
                {
                    continue;
                }

                StringBuilder members = new StringBuilder();
                foreach (var m in type1.Members)
                {
                    if (type1.Kind == TypeKind.Enum && m.Name == "value__")
                    {
                        continue;
                    }

                    if (m.Name == ".ctor")
                    {
                        continue;
                    }

                    if (members.Length != 0)
                    {
                        members.Append(',');
                    }

                    members.Append(m.Name);
                }

                if (members.Length != 0)
                {
                    typeName += $"({members})";
                }

                string archInfo = GetArchInfo(type1.GetAttributes());
                if (!string.IsNullOrEmpty(archInfo))
                {
                    typeName += $"({archInfo})";
                }

                if (!nameToNamespaces.TryGetValue(typeName, out var namespaces))
                {
                    namespaces = new List <string>();
                    nameToNamespaces[typeName] = namespaces;
                }

                namespaces.Add(type1.Namespace);
            }

            bool dupsFound = false;

            foreach (var pair in nameToNamespaces)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicate types detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var ns in pair.Value)
                    {
                        console?.Out.Write($"  {ns}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate types found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
示例#25
0
        public static List <ReferenceSegment> Decompile(TextEditor data, ModuleDefinition module, TypeDefinition currentType, Action <AstBuilder> setData, DecompilerSettings settings)
        {
            var context = new DecompilerContext(module);
            var source  = new CancellationTokenSource();

            context.CancellationToken = source.Token;
            context.CurrentType       = currentType;
            context.Settings          = settings;
            try {
                var astBuilder = new AstBuilder(context);
                setData(astBuilder);
                astBuilder.RunTransformations(o => false);
                GeneratedCodeSettings.Default.Apply(astBuilder.SyntaxTree);
                var output = new ColoredCSharpFormatter(data);
                astBuilder.GenerateCode(output);
                output.SetDocumentData();
                return(output.ReferencedSegments);
            } catch (Exception e) {
                // exception  -> try to decompile without method bodies
                try {
                    var astBuilder = new AstBuilder(context);
                    astBuilder.DecompileMethodBodies = false;
                    setData(astBuilder);
                    astBuilder.RunTransformations(o => false);
                    GeneratedCodeSettings.Default.Apply(astBuilder.SyntaxTree);
                    var output = new ColoredCSharpFormatter(data);
                    astBuilder.GenerateCode(output);
                    output.SetDocumentData();
                    data.InsertText(data.Length, "/* body decompilation failed: \n" + e + " */");
                } catch (Exception e2) {
                    data.Text = "/* fallback decompilation failed: \n" + e2 + "*/";
                }
            }
            return(null);
        }
示例#26
0
        public static List <ReferenceSegment> Decompile(TextEditorData data, ModuleDefinition module, TypeDefinition currentType, Action <AstBuilder> setData, DecompilerSettings settings)
        {
            try {
                var context = new DecompilerContext(module);
                var source  = new CancellationTokenSource();

                context.CancellationToken = source.Token;
                context.CurrentType       = currentType;

                context.Settings = settings;

                AstBuilder astBuilder = new AstBuilder(context);

                setData(astBuilder);

                astBuilder.RunTransformations(o => false);
                GeneratedCodeSettings.Default.Apply(astBuilder.SyntaxTree);
                var output = new ColoredCSharpFormatter(data.Document);
                astBuilder.GenerateCode(output);
                output.SetDocumentData();
                return(output.ReferencedSegments);
            } catch (Exception e) {
                data.Text = "Decompilation failed: \n" + e;
            }
            return(null);
        }
示例#27
0
        public void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilerSettings options)
        {
            AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true);

            codeDomBuilder.AddProperty(property);
            RunTransformsAndGenerateCode(codeDomBuilder, output, options);
        }
示例#28
0
        void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
        {
            var csFile  = Path.Combine(TestCasePath, testName + ".cs");
            var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe";

            if (cscOptions.HasFlag(CompilerOptions.Library))
            {
                exeFile = Path.ChangeExtension(exeFile, ".dll");
            }

            // 1. Compile
            CompilerResults output = null;

            try {
                output = Tester.CompileCSharp(csFile, cscOptions, exeFile);
            } finally {
                if (output != null)
                {
                    output.TempFiles.Delete();
                }
            }

            // 2. Decompile
            var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions));

            // 3. Compile
            CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
        }
示例#29
0
        private async Task <List <TestResult> > RunTestOnHardwareAsync(List <TestCase> tests)
        {
            _logger.LogMessage(
                "Setting up test runner in *** CONNECTED DEVICE ***",
                Settings.LoggingLevel.Detailed);

            List <TestResult> results    = PrepareListResult(tests);
            List <byte[]>     assemblies = new List <byte[]>();
            int    retryCount            = 0;
            string port = _settings.RealHardwarePort == string.Empty ? "COM4" : _settings.RealHardwarePort;
            //var serialDebugClient = PortBase.CreateInstanceForSerial("", null, true, new List<string>() { port });
            var serialDebugClient = PortBase.CreateInstanceForSerial(true, null);

retryConnection:
            _logger.LogMessage($"Checking device on port {port}.", Settings.LoggingLevel.Verbose);
            while (!serialDebugClient.IsDevicesEnumerationComplete)
            {
                Thread.Sleep(1);
            }

            _logger.LogMessage($"Found: {serialDebugClient.NanoFrameworkDevices.Count} devices", Settings.LoggingLevel.Verbose);

            if (serialDebugClient.NanoFrameworkDevices.Count == 0)
            {
                if (retryCount > _numberOfRetries)
                {
                    results.First().Outcome      = TestOutcome.Failed;
                    results.First().ErrorMessage = $"Couldn't find any device, please try to disable the device scanning in the Visual Studio Extension! If the situation persists reboot the device as well.";
                    return(results);
                }
                else
                {
                    retryCount++;
                    serialDebugClient.ReScanDevices();
                    goto retryConnection;
                }
            }

            retryCount = 0;
            NanoDeviceBase device;

            if (serialDebugClient.NanoFrameworkDevices.Count > 1)
            {
                device = serialDebugClient.NanoFrameworkDevices.Where(m => m.SerialNumber == port).First();
            }
            else
            {
                device = serialDebugClient.NanoFrameworkDevices[0];
            }

            _logger.LogMessage(
                $"Getting things with {device.Description}",
                Settings.LoggingLevel.Detailed);

            // check if debugger engine exists
            if (device.DebugEngine == null)
            {
                device.CreateDebugEngine();
                _logger.LogMessage($"Debug engine created.", Settings.LoggingLevel.Verbose);
            }

            bool deviceIsInInitializeState = false;

retryDebug:
            bool connectResult = device.DebugEngine.Connect(5000, true, true);

            _logger.LogMessage($"Device connect result is {connectResult}. Attempt {retryCount}/{_numberOfRetries}", Settings.LoggingLevel.Verbose);

            if (!connectResult)
            {
                if (retryCount < _numberOfRetries)
                {
                    // Give it a bit of time
                    await Task.Delay(100);

                    retryCount++;
                    goto retryDebug;
                }
                else
                {
                    results.First().Outcome      = TestOutcome.Failed;
                    results.First().ErrorMessage = $"Couldn't connect to the device, please try to disable the device scanning in the Visual Studio Extension! If the situation persists reboot the device as well.";
                    return(results);
                }
            }

            retryCount = 0;
retryErase:
            // erase the device
            _logger.LogMessage($"Erase deployment block storage. Attempt {retryCount}/{_numberOfRetries}.", Settings.LoggingLevel.Verbose);

            var eraseResult = device.Erase(
                EraseOptions.Deployment,
                null,
                null);

            _logger.LogMessage($"Erase result is {eraseResult}.", Settings.LoggingLevel.Verbose);
            if (!eraseResult)
            {
                if (retryCount < _numberOfRetries)
                {
                    // Give it a bit of time
                    await Task.Delay(400);

                    retryCount++;
                    goto retryErase;
                }
                else
                {
                    results.First().Outcome      = TestOutcome.Failed;
                    results.First().ErrorMessage = $"Couldn't erase the device, please try to disable the device scanning in the Visual Studio Extension! If the situation persists reboot the device as well.";
                    return(results);
                }
            }

            retryCount = 0;
            // initial check
            if (device.DebugEngine.IsDeviceInInitializeState())
            {
                _logger.LogMessage($"Device status verified as being in initialized state. Requesting to resume execution. Attempt {retryCount}/{_numberOfRetries}.", Settings.LoggingLevel.Error);
                // set flag
                deviceIsInInitializeState = true;

                // device is still in initialization state, try resume execution
                device.DebugEngine.ResumeExecution();
            }

            // handle the workflow required to try resuming the execution on the device
            // only required if device is not already there
            // retry 5 times with a 500ms interval between retries
            while (retryCount++ < _numberOfRetries && deviceIsInInitializeState)
            {
                if (!device.DebugEngine.IsDeviceInInitializeState())
                {
                    _logger.LogMessage($"Device has completed initialization.", Settings.LoggingLevel.Verbose);
                    // done here
                    deviceIsInInitializeState = false;
                    break;
                }

                _logger.LogMessage($"Waiting for device to report initialization completed ({retryCount}/{_numberOfRetries}).", Settings.LoggingLevel.Verbose);
                // provide feedback to user on the 1st pass
                if (retryCount == 0)
                {
                    _logger.LogMessage($"Waiting for device to initialize.", Settings.LoggingLevel.Verbose);
                }

                if (device.DebugEngine.IsConnectedTonanoBooter)
                {
                    _logger.LogMessage($"Device reported running nanoBooter. Requesting to load nanoCLR.", Settings.LoggingLevel.Verbose);
                    // request nanoBooter to load CLR
                    device.DebugEngine.ExecuteMemory(0);
                }
                else if (device.DebugEngine.IsConnectedTonanoCLR)
                {
                    _logger.LogMessage($"Device reported running nanoCLR. Requesting to reboot nanoCLR.", Settings.LoggingLevel.Error);
                    await Task.Run(delegate
                    {
                        // already running nanoCLR try rebooting the CLR
                        device.DebugEngine.RebootDevice(RebootOptions.ClrOnly);
                    });
                }

                // wait before next pass
                // use a back-off strategy of increasing the wait time to accommodate slower or less responsive targets (such as networked ones)
                await Task.Delay(TimeSpan.FromMilliseconds(_timeoutMiliseconds * (retryCount + 1)));

                await Task.Yield();
            }

            // check if device is still in initialized state
            if (!deviceIsInInitializeState)
            {
                // device has left initialization state
                _logger.LogMessage($"Device is initialized and ready!", Settings.LoggingLevel.Verbose);
                await Task.Yield();


                //////////////////////////////////////////////////////////
                // sanity check for devices without native assemblies ?!?!
                if (device.DeviceInfo.NativeAssemblies.Count == 0)
                {
                    _logger.LogMessage($"Device reporting no assemblies loaded. This can not happen. Sanity check failed.", Settings.LoggingLevel.Error);
                    // there are no assemblies deployed?!
                    results.First().Outcome      = TestOutcome.Failed;
                    results.First().ErrorMessage = $"Couldn't find any native assemblies deployed in {device.Description}, {device.TargetName} on {device.SerialNumber}! If the situation persists reboot the device.";
                    return(results);
                }

                _logger.LogMessage($"Computing deployment blob.", Settings.LoggingLevel.Verbose);

                // build a list with the full path for each DLL, referenced DLL and EXE
                List <DeploymentAssembly> assemblyList = new List <DeploymentAssembly>();

                var source           = tests.First().Source;
                var workingDirectory = Path.GetDirectoryName(source);
                var allPeFiles       = Directory.GetFiles(workingDirectory, "*.pe");

                var decompilerSettings = new DecompilerSettings
                {
                    LoadInMemory = false,
                    ThrowOnAssemblyResolveErrors = false
                };

                foreach (string assemblyPath in allPeFiles)
                {
                    // load assembly in order to get the versions
                    var file = Path.Combine(workingDirectory, assemblyPath.Replace(".pe", ".dll"));
                    if (!File.Exists(file))
                    {
                        // Check with an exe
                        file = Path.Combine(workingDirectory, assemblyPath.Replace(".pe", ".exe"));
                    }

                    var decompiler         = new CSharpDecompiler(file, decompilerSettings);;
                    var assemblyProperties = decompiler.DecompileModuleAndAssemblyAttributesToString();

                    // AssemblyVersion
                    string pattern         = @"(?<=AssemblyVersion\("")(.*)(?=\""\)])";
                    var    match           = Regex.Matches(assemblyProperties, pattern, RegexOptions.IgnoreCase);
                    string assemblyVersion = match[0].Value;

                    // AssemblyNativeVersion
                    pattern = @"(?<=AssemblyNativeVersion\("")(.*)(?=\""\)])";
                    match   = Regex.Matches(assemblyProperties, pattern, RegexOptions.IgnoreCase);

                    // only class libs have this attribute, therefore sanity check is required
                    string nativeVersion = "";
                    if (match.Count == 1)
                    {
                        nativeVersion = match[0].Value;
                    }

                    assemblyList.Add(new DeploymentAssembly(Path.Combine(workingDirectory, assemblyPath), assemblyVersion, nativeVersion));
                }

                _logger.LogMessage($"Added {assemblyList.Count} assemblies to deploy.", Settings.LoggingLevel.Verbose);
                await Task.Yield();

                // Keep track of total assembly size
                long totalSizeOfAssemblies = 0;

                // now we will re-deploy all system assemblies
                foreach (DeploymentAssembly peItem in assemblyList)
                {
                    // append to the deploy blob the assembly
                    using (FileStream fs = File.Open(peItem.Path, FileMode.Open, FileAccess.Read))
                    {
                        long length = (fs.Length + 3) / 4 * 4;
                        _logger.LogMessage($"Adding {Path.GetFileNameWithoutExtension(peItem.Path)} v{peItem.Version} ({length} bytes) to deployment bundle", Settings.LoggingLevel.Verbose);
                        byte[] buffer = new byte[length];

                        await Task.Yield();

                        await fs.ReadAsync(buffer, 0, (int)fs.Length);

                        assemblies.Add(buffer);

                        // Increment totalizer
                        totalSizeOfAssemblies += length;
                    }
                }

                _logger.LogMessage($"Deploying {assemblyList.Count:N0} assemblies to device... Total size in bytes is {totalSizeOfAssemblies}.", Settings.LoggingLevel.Verbose);
                // need to keep a copy of the deployment blob for the second attempt (if needed)
                var assemblyCopy = new List <byte[]>(assemblies);

                await Task.Yield();

                var deploymentLogger = new Progress <string>((m) => _logger.LogMessage(m, Settings.LoggingLevel.Detailed));

                await Task.Run(async delegate
                {
                    // OK to skip erase as we just did that
                    // no need to reboot device
                    if (!device.DebugEngine.DeploymentExecute(
                            assemblyCopy,
                            false,
                            false,
                            null,
                            deploymentLogger))
                    {
                        // if the first attempt fails, give it another try

                        // wait before next pass
                        await Task.Delay(TimeSpan.FromSeconds(1));

                        await Task.Yield();

                        _logger.LogMessage("Deploying assemblies. Second attempt.", Settings.LoggingLevel.Verbose);

                        // !! need to use the deployment blob copy
                        assemblyCopy = new List <byte[]>(assemblies);

                        // can't skip erase as we just did that
                        // no need to reboot device
                        if (!device.DebugEngine.DeploymentExecute(
                                assemblyCopy,
                                false,
                                false,
                                null,
                                deploymentLogger))
                        {
                            _logger.LogMessage("Deployment failed.", Settings.LoggingLevel.Error);

                            // throw exception to signal deployment failure
                            results.First().Outcome      = TestOutcome.Failed;
                            results.First().ErrorMessage = $"Deployment failed in {device.Description}, {device.TargetName} on {device.SerialNumber}! If the situation persists reboot the device.";
                        }
                    }
                });

                await Task.Yield();

                // If there has been an issue before, the first test is marked as failed
                if (results.First().Outcome == TestOutcome.Failed)
                {
                    return(results);
                }

                StringBuilder output     = new StringBuilder();
                bool          isFinished = false;
                // attach listener for messages
                device.DebugEngine.OnMessage += (message, text) =>
                {
                    _logger.LogMessage(text, Settings.LoggingLevel.Verbose);
                    output.Append(text);
                    if (text.Contains(Done))
                    {
                        isFinished = true;
                    }
                };

                device.DebugEngine.RebootDevice(RebootOptions.ClrOnly);

                while (!isFinished)
                {
                    Thread.Sleep(1);
                }

                _logger.LogMessage($"Tests finished.", Settings.LoggingLevel.Verbose);
                CheckAllTests(output.ToString(), results);
            }
            else
            {
                _logger.LogMessage("Failed to initialize device.", Settings.LoggingLevel.Error);
            }


            return(results);
        }
示例#30
0
        internal static DecompilerSettings CreateDecompilerSettings_DecompileTypeMethods(DecompilerSettings settings, bool useUsingDeclarations)
        {
            var s = CreateDecompilerSettings(settings, useUsingDeclarations);

            // Make sure the ctor is shown if the user tries to edit an empty ctor/cctor
            s.RemoveEmptyDefaultConstructors = false;
            return(s);
        }
示例#31
0
 static bool ValidateCompoundAssign(BinaryNumericInstruction binary, Conv conv, IType targetType, DecompilerSettings settings)
 {
     if (!NumericCompoundAssign.IsBinaryCompatibleWithType(binary, targetType, settings))
     {
         return(false);
     }
     if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow))
     {
         return(false);                // conv does not match binary operation
     }
     return(true);
 }
示例#32
0
        void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
        {
            var ilFile       = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il";
            var csFile       = Path.Combine(TestCasePath, testName + ".cs");
            var expectedFile = Path.Combine(TestCasePath, testName + ".Expected.cs");

            if (!File.Exists(ilFile))
            {
                // re-create .il file if necessary
                CompilerResults output = null;
                try
                {
                    output = Tester.CompileCSharp(csFile, cscOptions);
                    Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions);
                }
                finally
                {
                    if (output != null)
                    {
                        output.TempFiles.Delete();
                    }
                }
            }

            var executable = Tester.AssembleIL(ilFile, asmOptions);
            var decompiled = Tester.DecompileCSharp(executable, decompilerSettings);

            CodeAssert.FilesAreEqual(expectedFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
        }
示例#33
0
 public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
     : this(mainModule, assemblyResolver, GetOptions(settings ?? throw new ArgumentNullException(nameof(settings))))