예제 #1
0
        protected void OptimizeAll()
        {
            var pr = new ProgressReporter();
            if (Optimizing != null)
                Optimizing(pr);

            int i = 0;
            while (FunctionCache.OptimizationQueue.Count > 0) {
                var id = FunctionCache.OptimizationQueue.First();
                FunctionCache.OptimizationQueue.Remove(id);

                var e = FunctionCache.Cache[id];
                if (e.Expression == null) {
                    i++;
                    continue;
                }

                pr.OnProgressChanged(i++, i + FunctionCache.OptimizationQueue.Count);
                OptimizeFunction(e.SpecialIdentifiers, e.ParameterNames, e.Variables, e.Expression);
            }

            pr.OnFinished();
        }
예제 #2
0
        protected AssemblyDefinition[] LoadAssembly(string path, bool useSymbols, bool includeDependencies)
        {
            if (String.IsNullOrWhiteSpace(path))
                throw new InvalidDataException("Path was empty.");

            var readerParameters = GetReaderParameters(useSymbols, path);

            var pr = new ProgressReporter();
            if (LoadingAssembly != null)
                LoadingAssembly(path, pr);

            var assembly = AssemblyDefinition.ReadAssembly(
                path, readerParameters
            );

            var result = new List<AssemblyDefinition>();
            result.Add(assembly);

            if (includeDependencies) {
                var modulesToVisit = new Queue<ModuleDefinition>(assembly.Modules);
                var visitedModules = new HashSet<string>();

                var assemblyNames = new HashSet<string>();
                while (modulesToVisit.Count > 0) {
                    var module = modulesToVisit.Dequeue();
                    if (visitedModules.Contains(module.FullyQualifiedName))
                        continue;

                    visitedModules.Add(module.FullyQualifiedName);

                    foreach (var reference in module.AssemblyReferences) {
                        bool ignored = false;
                        foreach (var ia in IgnoredAssemblies) {
                            if (ia.IsMatch(reference.FullName)) {
                                ignored = true;
                                break;
                            }
                        }

                        if (ignored)
                            continue;
                        if (assemblyNames.Contains(reference.FullName))
                            continue;

                        var childParameters = new ReaderParameters {
                            ReadingMode = ReadingMode.Deferred,
                            ReadSymbols = true,
                            SymbolReaderProvider = SymbolProvider
                        };

                        var pr2 = new ProgressReporter();
                        if (LoadingAssembly != null)
                            LoadingAssembly(reference.Name, pr2);

                        AssemblyDefinition refAssembly = null;
                        assemblyNames.Add(reference.FullName);
                        try {
                            refAssembly = readerParameters.AssemblyResolver.Resolve(reference, readerParameters);
                        } catch (Exception ex) {
                            if (useSymbols) {
                                try {
                                    refAssembly = readerParameters.AssemblyResolver.Resolve(reference, GetReaderParameters(false, path));
                                    if (CouldNotLoadSymbols != null)
                                        CouldNotLoadSymbols(reference.Name, ex);
                                } catch (Exception ex2) {
                                    if (CouldNotResolveAssembly != null)
                                        CouldNotResolveAssembly(reference.FullName, ex2);
                                }
                            } else {
                                if (CouldNotResolveAssembly != null)
                                    CouldNotResolveAssembly(reference.FullName, ex);
                            }
                        }

                        if (refAssembly != null) {
                            result.Add(refAssembly);
                            foreach (var refModule in refAssembly.Modules)
                                modulesToVisit.Enqueue(refModule);
                        }

                        pr2.OnFinished();
                    }
                }
            }

            pr.OnFinished();
            return result.ToArray();
        }
예제 #3
0
        public AssemblyDefinition[] Translate(string assemblyPath, Stream outputStream = null, bool scanForProxies = true)
        {
            var assemblies = LoadAssembly(assemblyPath);

            if (scanForProxies)
                TypeInfoProvider.AddProxyAssemblies(assemblies);

            GeneratedFiles.Add(assemblyPath);

            var context = new DecompilerContext(assemblies.First().MainModule);

            context.Settings.YieldReturn = false;
            context.Settings.AnonymousMethods = true;
            context.Settings.QueryExpressions = false;
            context.Settings.LockStatement = false;
            context.Settings.FullyQualifyAmbiguousTypeNames = true;
            context.Settings.ForEachStatement = false;

            var pr = new ProgressReporter();
            if (Decompiling != null)
                Decompiling(pr);

            for (int i = 0; i < assemblies.Length; i++) {
                pr.OnProgressChanged(i, assemblies.Length);
                Analyze(context, assemblies[i]);
            }

            pr.OnFinished();

            OptimizeAll();

            Action<AssemblyDefinition> handler;

            if (outputStream == null) {
                handler = (assembly) => {
                    var outputPath = Path.Combine(OutputDirectory, assembly.Name + ".js");

                    if (File.Exists(outputPath))
                        File.Delete(outputPath);

                    using (outputStream = File.OpenWrite(outputPath))
                        Translate(context, assembly, outputStream);
                };

                if (!Directory.Exists(OutputDirectory))
                    Directory.CreateDirectory(OutputDirectory);
            } else {
                handler = (assembly) =>
                    Translate(context, assembly, outputStream);
            }

            pr = new ProgressReporter();
            if (Writing != null)
                Writing(pr);

            for (int i = 0; i < assemblies.Length; i++) {
                pr.OnProgressChanged(i, assemblies.Length);
                handler(assemblies[i]);
            }

            pr.OnFinished();

            return assemblies;
        }
예제 #4
0
        internal JSFunctionExpression TranslateMethodExpression(DecompilerContext context, MethodReference method, MethodDefinition methodDef)
        {
            var oldMethod = context.CurrentMethod;
            try {
                if (method == null)
                    throw new ArgumentNullException("method");
                if (methodDef == null)
                    throw new ArgumentNullException("methodDef");

                var methodInfo = TypeInfoProvider.GetMemberInformation<JSIL.Internal.MethodInfo>(methodDef);

                var identifier = new QualifiedMemberIdentifier(
                    methodInfo.DeclaringType.Identifier, methodInfo.Identifier
                );
                JSFunctionExpression function = null;

                if (FunctionCache.TryGetExpression(identifier, out function))
                    return function;

                if (methodInfo.IsExternal) {
                    FunctionCache.CreateNull(methodInfo, method, identifier);
                    return null;
                }

                var bodyDef = methodDef;
                if (methodInfo.IsFromProxy && methodInfo.Member.HasBody)
                    bodyDef = methodInfo.Member;

                var pr = new ProgressReporter();

                context.CurrentMethod = methodDef;
                if ((methodDef.Body.Instructions.Count > LargeMethodThreshold) && (this.DecompilingMethod != null))
                    this.DecompilingMethod(method.FullName, pr);

                ILBlock ilb;
                var decompiler = new ILAstBuilder();
                var optimizer = new ILAstOptimizer();

                try {
                    ilb = new ILBlock(decompiler.Build(bodyDef, true));
                    optimizer.Optimize(context, ilb);
                } catch (Exception exception) {
                    if (CouldNotDecompileMethod != null)
                        CouldNotDecompileMethod(bodyDef.FullName, exception);

                    FunctionCache.CreateNull(methodInfo, method, identifier);
                    pr.OnFinished();
                    return null;
                }

                var allVariables = ilb.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
                    .Where(v => v != null && !v.IsParameter).Distinct();

                foreach (var v in allVariables) {
                    if (ILBlockTranslator.IsIgnoredType(v.Type)) {
                        FunctionCache.CreateNull(methodInfo, method, identifier);
                        pr.OnFinished();
                        return null;
                    }
                }

                NameVariables.AssignNamesToVariables(context, decompiler.Parameters, allVariables, ilb);

                var translator = new ILBlockTranslator(
                    this, context, method, methodDef,
                    ilb, decompiler.Parameters, allVariables
                );
                var body = translator.Translate();

                if (body == null) {
                    FunctionCache.CreateNull(methodInfo, method, identifier);
                    pr.OnFinished();
                    return null;
                }

                var parameters = from p in translator.ParameterNames select translator.Variables[p];

                if (method.HasGenericParameters) {
                    var type = new TypeReference("System", "Type", context.CurrentModule.TypeSystem.Object.Module, context.CurrentModule.TypeSystem.Object.Scope);
                    parameters = (from gp in method.GenericParameters select new JSVariable(gp.Name, type, method)).Concat(parameters);
                }

                function = FunctionCache.Create(
                    methodInfo, methodDef, method, identifier,
                    translator, parameters, body
                );

                pr.OnFinished();
                return function;
            } finally {
                context.CurrentMethod = oldMethod;
            }
        }
예제 #5
0
        protected void OptimizeAll()
        {
            var pr = new ProgressReporter();
            if (Optimizing != null)
                Optimizing(pr);

            int i = 0, c = FunctionCache.Cache.Count;
            foreach (var e in FunctionCache.Cache.Values) {
                if (e.Expression == null) {
                    i++;
                    continue;
                }

                pr.OnProgressChanged(i++, c);
                OptimizeFunction(e.SpecialIdentifiers, e.ParameterNames, e.Variables, e.Expression);
            }

            pr.OnFinished();
        }