/// <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); }
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 }
/// <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); } }
/// <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); } } }