Example #1
0
        /// <summary>
        /// Compile an assembly into a dex file.
        /// </summary>
        private static void CompileAssembly(CommandLineOptions options, NameConverter nsConverter)
        {
            // Load resource type usage info file
            var usedTypeNames = LoadResourceTypeUsageInformation(options);

            // Load assemblies
            var assemblies       = new List <AssemblyDefinition>();
            var module           = new XModule();
            var classLoader      = new AssemblyClassLoader(module.OnClassLoaded);
            var resolver         = new AssemblyResolver(options.ReferenceFolders, classLoader, module.OnAssemblyLoaded);
            var readerParameters = new ReaderParameters(ReadingMode.Immediate)
            {
                AssemblyResolver     = resolver,
                SymbolReaderProvider = new SafeSymbolReaderProvider(),
                ReadSymbols          = true
            };

            foreach (var asmPath in options.Assemblies)
            {
                var asm = resolver.Load(asmPath, readerParameters);
                module.OnAssemblyLoaded(asm);
                classLoader.LoadAssembly(asm);
                assemblies.Add(asm);
            }
            // Load references
            var references = new List <AssemblyDefinition>();

            foreach (var refPath in options.References)
            {
                var asm = resolver.Load(refPath, readerParameters);
                module.OnAssemblyLoaded(asm);
                classLoader.LoadAssembly(asm);
                references.Add(asm);
            }

            // Load resources
            Table table;

            using (var stream = new FileStream(options.InputResources, FileMode.Open, FileAccess.Read))
            {
                table = new Table(stream);
            }

            // Create compiler
            var compiler = new AssemblyCompiler(options.CompilationMode, assemblies, references, table, nsConverter, options.DebugInfo, classLoader, usedTypeNames, module);

            compiler.Compile();
            compiler.Save(options.OutputFolder, options.FreeAppsKeyPath);
        }
Example #2
0
        private SourceFile(ApkFile apk, JarFile jar, ISpySettings settings, MapFile mapFile, string singleFilePath = null)
        {
            this.apk            = apk;
            this.jar            = jar;
            this.settings       = settings;
            this.mapFile        = mapFile;
            this.singleFilePath = singleFilePath;

#if DEBUG
            classLoader = new AssemblyClassLoader(module.OnClassLoaded);
            var modParams = new ModuleParameters
            {
                AssemblyResolver = new AssemblyResolver(new[] { Frameworks.Instance.FirstOrDefault().Folder }, classLoader, module.OnAssemblyLoaded),
                Kind             = ModuleKind.Dll
            };
            assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("spy", Version.Parse("1.0.0.0")), "main", modParams);
            classLoader.LoadAssembly(assembly);

            var dot42Assembly = modParams.AssemblyResolver.Resolve("dot42");

            // Force loading of classes
            if (jar != null)
            {
                foreach (var fileName in jar.ClassFileNames)
                {
                    OpenClass(fileName);
                }
            }
#endif
        }
Example #3
0
        /// <summary>
        /// Resolve an assembly by name with given parameters.
        /// </summary>
        public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
        {
            AssemblyDefinition result;

            if (references.TryGetValue(name.Name, out result))
            {
                return(result);
            }

            var path = ResolvePath(name.Name);

            if (path == null)
            {
                DLog.Error(DContext.CompilerAssemblyResolver, "Failed to resolve assembly {0} in {1}", name, string.Join(";  ", referenceFolders));
                throw new AssemblyResolutionException(name);
            }

            try
            {
                Console.WriteLine(string.Format("Loading {0}", name.Name));
                var reference = AssemblyDefinition.ReadAssembly(path, parameters);
                references[name.Name] = reference;
                VerifyFrameworkAssembly(reference, path);
                if (assemblyLoaded != null)
                {
                    assemblyLoaded(reference);
                }
                if (classLoader != null)
                {
                    classLoader.LoadAssembly(reference);
                }
                return(reference);
            }
            catch (Exception ex)
            {
                // Unload the reference
                references.Remove(name.Name);
#if DEBUG
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
#endif
                // Log the error
                DLog.Error(DContext.CompilerAssemblyResolver, "Failed to load assembly {0}", ex, name);

                // Pass the error on
                throw new AssemblyResolutionException(name);
            }
        }
Example #4
0
        /// <summary>
        /// this is fully reentrant and multithreading capable, but will itself block.
        /// </summary>
        private AssemblyDefinition Load(AssemblyNameReference name, string assemblyFilename, ReaderParameters parameters)
        {
            AssemblyDefinition ret = null;
            TaskCompletionSource <AssemblyDefinition> loadingTaskSource = new TaskCompletionSource <AssemblyDefinition>();

            bool nameRegistered = false, filenameRegistered = false;

            try
            {
                // First, make sure we are the only one loading.
                while (true)
                {
                    Task <AssemblyDefinition> loadingTask;
                    if (name != null && !nameRegistered)
                    {
                        if (loadingTasks.TryGetValue(name.Name, out loadingTask))
                        {
                            ret = loadingTask.Result;
                            return(ret);
                        }

                        if (!loadingTasks.TryAdd(name.Name, loadingTaskSource.Task))
                        {
                            continue;
                        }
                        nameRegistered = true;
                    }

                    if (loadingTasks.TryAdd(assemblyFilename, loadingTaskSource.Task))
                    {
                        filenameRegistered = true;
                        break;
                    }
                    if (loadingTasks.TryGetValue(assemblyFilename, out loadingTask))
                    {
                        if (loadingTask == loadingTaskSource.Task)
                        {
                            break;
                        }

                        ret = loadingTask.Result;
                        return(ret);
                    }
                }

                // now check if it has already been loaded.
                if (name != null)
                {
                    if (referencesByName.TryGetValue(name.Name, out ret))
                    {
                        return(ret);
                    }
                }

                ret = fileNamesByAssembly.FirstOrDefault(v => v.Value.Equals(assemblyFilename, StringComparison.InvariantCultureIgnoreCase)).Key;
                if (ret != null)
                {
                    return(ret);
                }

                // now load the assembly.
                Console.WriteLine("Loading {0}...", Path.GetFileName(assemblyFilename));

                AssemblyDefinition assm = AssemblyDefinition.ReadAssembly(assemblyFilename, parameters);

                VerifyFrameworkAssembly(assm, assemblyFilename);

                // have to use a lock to update both data structures at the same time.
                lock (referencesByName)
                {
                    // now check again by the assembly name if it has been loaded before.
                    // This can happen if we were only provided a file name
                    if (!referencesByName.TryAdd(assm.Name.Name, assm))
                    {
                        ret = referencesByName[assm.Name.Name];
                        return(ret);
                    }

                    fileNamesByAssembly[assm] = assemblyFilename;
                }

                ret = assm;

                // now notify any listeners. note that if we were called on multiple threads
                // these might be called reentrantly as well.

                if (assemblyLoaded != null)
                {
                    assemblyLoaded(ret);
                }

                if (classLoader != null)
                {
                    classLoader.LoadAssembly(ret);
                }

                // done.
                return(ret);
            }
            catch (Exception ex)
            {
#if DEBUG
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
#endif
                // Log the error
                var assemblyName = name == null?assemblyFilename:name.ToString();
                DLog.Error(DContext.CompilerAssemblyResolver, "Failed to load assembly {0}: {1}", assemblyName, ex.Message);

                // Pass the error on
                var exn = new AssemblyResolutionException(name ?? new AssemblyNameDefinition(assemblyFilename, new Version()));
                loadingTaskSource.SetException(exn);
                throw exn;
            }
            finally
            {
                loadingTaskSource.TrySetResult(ret);

                // cleanup our registrations
                Task <AssemblyDefinition> ignore;
                if (nameRegistered)
                {
                    loadingTasks.TryRemove(name.Name, out ignore);
                }
                if (filenameRegistered)
                {
                    loadingTasks.TryRemove(assemblyFilename, out ignore);
                }
            }
        }