예제 #1
0
        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);
        }
예제 #3
0
        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)");
            }
        }