static void ReadMutateAndResolve(string sourceLocation) { ExtractAndCompile(sourceLocation); string dllLocation = Path.ChangeExtension(sourceLocation, ".dll"); using (var host = new PeReader.DefaultHost()) { //Read the Metadata Model from the PE file var module = host.LoadUnitFrom(dllLocation) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(dllLocation + " is not a PE file containing a CLR module or assembly."); return; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } module = MetadataCopier.DeepCopy(host, module); module = new MetadataRewriter(host).Rewrite(module); TestResolution resolver = new TestResolution(host); resolver.Visit(module); string result = resolver.Output.ToString(); Assert.True(!result.Contains("Dummy")); } }
/// <summary> /// Generate the comparability information for the given assembly. /// </summary> private static AssemblySummary GenerateComparability(CeleriacArgs celeriacArgs, TypeManager typeManager, IMetadataHost host, IModule module, PdbReader pdbReader, ref Assembly mutable) { AssemblySummary comparabilityManager = null; IAssembly assembly = module as IAssembly; mutable = MetadataCopier.DeepCopy(host, assembly); typeManager.SetAssemblyIdentity(UnitHelper.GetAssemblyIdentity(mutable)); if (celeriacArgs.StaticComparability || celeriacArgs.GenerateComparability) { if (celeriacArgs.ComparabilityFile != null) { using (var cmp = File.Open(celeriacArgs.ComparabilityFile, FileMode.Open)) { comparabilityManager = (AssemblySummary) new BinaryFormatter().Deserialize(cmp); } } else { if (celeriacArgs.VerboseMode) { Console.WriteLine("Generating Comparability Information"); } Assembly decompiled = Decompiler.GetCodeModelFromMetadataModel(typeManager.Host, mutable, pdbReader, DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators); comparabilityManager = AssemblySummary.MakeSummary(decompiled, typeManager); if (celeriacArgs.VerboseMode) { Console.WriteLine("Finished Generating Comparability Information"); } using (var cmp = File.Open(celeriacArgs.AssemblyPath + CeleriacArgs.ComparabilityFileExtension, FileMode.Create)) { new BinaryFormatter().Serialize(cmp, comparabilityManager); } } } return(comparabilityManager); }
internal static void Amend(params string[] targets) { // Ensure that at least one target assembly was specified if (targets == null || targets.Length == 0) { throw new ArgumentException("At least one target assembly must be specified."); } // Ensure that the target assemblies exist foreach (var path in targets) { if (!File.Exists(path)) { throw new ArgumentException("The specified target assembly, " + path + ", does not exist."); } } // Determine the set of target directories and backup locations var directories = targets .Select(path => Path.GetDirectoryName(path).ToLower()) .Distinct() .Select(directory => new { SourcePath = directory, BackupPath = Directory.CreateDirectory(Path.Combine(directory, "Backup")).FullName }); // Determine the set of dlls, pdbs, and backup files var assemblies = targets .Select(dllPath => new { DllPath = dllPath, DllBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileName(dllPath)), PdbPath = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".pdb"), PdbBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileNameWithoutExtension(dllPath) + ".pdb") }); // Backup the directories containing the targeted dll and pdb files foreach (var directory in directories) { foreach (var file in Directory.GetFiles(directory.SourcePath)) { if (file.ToLower().EndsWith("exe") || file.ToLower().EndsWith("dll") || file.ToLower().EndsWith("pdb")) { File.Copy(file, Path.Combine(directory.BackupPath, Path.GetFileName(file)), true); } } } // Register an assembly resolver to look in backup folders when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { try { return(System.Reflection.Assembly.Load(e.Name)); } catch { foreach (var directory in directories) { var dependency = Path.Combine(directory.BackupPath, e.Name.Substring(0, e.Name.IndexOf(',')) + ".dll"); if (File.Exists(dependency)) { return(System.Reflection.Assembly.LoadFrom(dependency)); } } return(null); } }; // Get the set of amendments to apply from all of the specified assemblies var amendments = assemblies.SelectMany(a => AmendmentAttribute.GetAmendments(System.Reflection.Assembly.LoadFrom(a.DllBackupPath))).ToList(); // Exit immediately if there are no amendments in the target assemblies if (amendments.Count == 0) { return; } // Process each target assembly individually foreach (var assembly in assemblies) { Console.Write("Amending " + Path.GetFileName(assembly.DllPath)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(assembly.DllBackupPath) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new ArgumentException(assembly.DllBackupPath + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } // Copy the assembly to enable it to be mutated module = MetadataCopier.DeepCopy(host, module); // Load the debug file if it exists PdbReader pdbReader = null; if (File.Exists(assembly.PdbBackupPath)) { using (var pdbStream = File.OpenRead(assembly.PdbBackupPath)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, amendments); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory using (var pdbWriter = pdbReader != null ? new PdbWriter(assembly.PdbPath, pdbReader) : null) { using (var dllStream = File.Create(assembly.DllPath)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, null, pdbWriter); } } } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); } }