Esempio n. 1
0
    void AssertWriteToPeFile(PeVerifyResult expectedResult, IAssembly assembly, string pdbPath)
    {
        var validator = new MetadataValidator(this.host);
        List <Microsoft.Cci.ErrorEventArgs> errorEvents = new List <Microsoft.Cci.ErrorEventArgs>();

        this.host.Errors += (object sender, Microsoft.Cci.ErrorEventArgs e) => errorEvents.Add(e);
        validator.Validate(assembly);
        Debug.Assert(errorEvents.Count == 0);
        using (var rewrittenFile = File.Create(assembly.Location)) {
            if (pdbPath != null)
            {
                using (var f = File.OpenRead(pdbPath)) {
                    using (var pdbReader = new PdbReader(f, host)) {
                        using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), pdbReader)) {
                            PeWriter.WritePeToStream(assembly, host, rewrittenFile, pdbReader, pdbReader, pdbWriter);
                        }
                    }
                }
            }
            else
            {
                using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), null)) {
                    PeWriter.WritePeToStream(assembly, host, rewrittenFile, null, null, pdbWriter);
                }
            }
        }

        Assert.True(File.Exists(assembly.Location));
        PeVerify.Assert(expectedResult, PeVerify.VerifyAssembly(assembly.Location, true));
    }
Esempio n. 2
0
        private static void TranslateToExe(SpecSharpOptions commandLineOptions)
        //^ requires commandLineOptions.FileNames.Count > 0;
        {
            HostEnvironment hostEnvironment = new HostEnvironment();

            hostEnvironment.Errors         += hostEnvironment.HandleErrors;
            hostEnvironment.displayFileName = true;
            List <IAssemblyReference>      assemblyReferences = GetAssemblyReferences(commandLineOptions, hostEnvironment);
            List <IModuleReference>        moduleReferences   = new List <IModuleReference>();
            List <SpecSharpSourceDocument> programSources     = new List <SpecSharpSourceDocument>(1);
            IName                      name   = hostEnvironment.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(commandLineOptions.FileNames[0]));
            SpecSharpAssembly          assem  = new SpecSharpAssembly(name, Path.GetFullPath(name.Value), hostEnvironment, commandLineOptions, assemblyReferences, moduleReferences, programSources);
            SpecSharpCompilationHelper helper = new SpecSharpCompilationHelper(assem.Compilation);

            foreach (string fileName in commandLineOptions.FileNames)
            {
                name = hostEnvironment.NameTable.GetNameFor(fileName);
                StreamReader instream = File.OpenText(fileName);
                programSources.Add(new SpecSharpSourceDocument(helper, name, Path.GetFullPath(fileName), instream));
            }

            if (assem.Compilation.HasErrors)
            {
                return;
            }
            var sourceLocationProvider = assem.Compilation.SourceLocationProvider;
            var localScopeProvider     = assem.Compilation.LocalScopeProvider;

            using (var pdbWriter = new PdbWriter(Path.ChangeExtension(assem.Location, "pdb"), sourceLocationProvider)) {
                PeWriter.WritePeToStream(assem, hostEnvironment, File.Create(Path.ChangeExtension(assem.Location, "exe")), sourceLocationProvider, localScopeProvider, pdbWriter);
            }
        }
Esempio n. 3
0
        private static void OutputFacadeToFile(string facadePath, HostEnvironment seedHost, Assembly facade, IAssembly contract, string pdbLocation = null)
        {
            // Use the filename (including extension .dll/.winmd) so people can have some control over the output facade file name.
            string facadeFileName   = Path.GetFileName(contract.Location);
            string facadeOutputPath = Path.Combine(facadePath, facadeFileName);

            using (Stream peOutStream = File.Create(facadeOutputPath))
            {
                if (pdbLocation != null)
                {
                    if (File.Exists(pdbLocation))
                    {
                        string pdbOutputPath = Path.Combine(facadePath, contract.Name + ".pdb");
                        using (Stream pdbReadStream = File.OpenRead(pdbLocation))
                            using (PdbReader pdbReader = new PdbReader(pdbReadStream, seedHost))
                                using (PdbWriter pdbWriter = new PdbWriter(pdbOutputPath, pdbReader))
                                {
                                    PeWriter.WritePeToStream(facade, seedHost, peOutStream, pdbReader, pdbReader, pdbWriter);
                                }
                    }
                    else
                    {
                        throw new FacadeGenerationException("Couldn't find the pdb at the given location: " + pdbLocation);
                    }
                }
                else
                {
                    PeWriter.WritePeToStream(facade, seedHost, peOutStream);
                }
            }
        }
Esempio n. 4
0
        static void Main(string[] args)
        {
            using (var host = new HelloHost()) {
                var nameTable    = host.NameTable;
                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);

                var aname   = nameTable.GetNameFor("hello");
                var mname   = nameTable.GetNameFor("hello.exe");
                var arefs   = IteratorHelper.GetSingletonEnumerable <IAssemblyReference>(coreAssembly);
                var source  = new HelloSourceDocument(aname);
                var sources = IteratorHelper.GetSingletonEnumerable <HelloSourceDocument>(source);

                var helloAssembly          = new HelloAssembly(aname, host, mname, arefs, sources);
                var sourceLocationProvider = helloAssembly.Compilation.SourceLocationProvider;
                var localScopeProvider     = helloAssembly.Compilation.LocalScopeProvider;

                using (var sourceFile = File.CreateText("hello.cs")) {
                    sourceFile.WriteLine("hello");
                }
                using (var peStream = File.Create("hello.exe")) {
                    using (var pdbWriter = new PdbWriter("hello.pdb", sourceLocationProvider)) {
                        PeWriter.WritePeToStream(helloAssembly, host, peStream, helloAssembly.Compilation.SourceLocationProvider, helloAssembly.Compilation.LocalScopeProvider, pdbWriter);
                    }
                }
            }
        }
        static void Main(string[] argv)
        {
            if (argv == null || argv.Length < 1)
            {
                Console.WriteLine("Usage: Main <assemblys> [<outputPath>]");
            }

            using (var host = new PeReader.DefaultHost()) {
                var module = host.LoadUnitFrom(argv[0]) as IModule;
                if (module == null || module == Dummy.Module || module == Dummy.Assembly)
                {
                    throw new Exception(argv[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                }

                PdbReader pdbReader = null;
                string    pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                if (File.Exists(pdbFile))
                {
                    using (var pdbStream = File.OpenRead(pdbFile)) {
                        pdbReader = new PdbReader(pdbStream, host);
                    }
                }
                else
                {
                    Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway.");
                }

                using (pdbReader) {
                    var copy = new MetadataDeepCopier(host).Copy(module);
                    var shadowFieldsAddedAssembly           = new ShadowFieldRewriter(host).Rewrite(copy);
                    var shadowFieldsAndMethodsAddedAssembly = new ShadowMethodRewriter(host).Rewrite(shadowFieldsAddedAssembly);
                    var rewrittenAssembly = new FinalizeMethodRewriter(host).Rewrite(shadowFieldsAndMethodsAddedAssembly);

                    var main = rewrittenAssembly.EntryPoint.ResolvedMethod;
                    if (main != Dummy.Method)
                    {
                        var body = main.Body as MethodBody;
                        if (body != null)
                        {
                            new AddGCWaitForFinalization(host, body).Rewrite();
                        }
                    }

                    var validator = new MetadataValidator(host);
                    validator.Validate(rewrittenAssembly as IAssembly);

                    string outputPath     = rewrittenAssembly.Location + ".meta";
                    var    outputFileName = Path.GetFileNameWithoutExtension(outputPath);

                    // Need to not pass in a local scope provider until such time as we have one that will use the mutator
                    // to remap things (like the type of a scope constant) from the original assembly to the mutated one.
                    using (var peStream = File.Create(outputPath)) {
                        using (var pdbWriter = new PdbWriter(outputFileName + ".pdb", pdbReader)) {
                            PeWriter.WritePeToStream(rewrittenAssembly, host, peStream, pdbReader, null, pdbWriter);
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        private static void OutputFacadeToFile(string facadePath, HostEnvironment seedHost, Assembly facade, IAssembly contract, string pdbLocation = null)
        {
            bool   needsConversion    = false;
            string pdbOutputPath      = Path.Combine(facadePath, contract.Name + ".pdb");
            string finalPdbOutputPath = pdbOutputPath;

            // Use the filename (including extension .dll/.winmd) so people can have some control over the output facade file name.
            string facadeFileName   = Path.GetFileName(contract.Location);
            string facadeOutputPath = Path.Combine(facadePath, facadeFileName);

            using (Stream peOutStream = File.Create(facadeOutputPath))
            {
                if (pdbLocation != null)
                {
                    if (File.Exists(pdbLocation))
                    {
                        // Convert from portable to windows PDBs if necessary.  If we convert
                        // set the pdbOutput path to a *.windows.pdb file so we can convert it back
                        // to 'finalPdbOutputPath'.
                        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                        {
                            needsConversion = ConvertFromPortableIfNecessary(facade.Location, ref pdbLocation);
                        }
                        if (needsConversion)
                        {
                            // We want to keep the same file name for the PDB because it is used as a key when looking it up on a symbol server
                            string pdbOutputPathPdbDir = Path.Combine(Path.GetDirectoryName(pdbOutputPath), "WindowsPdb");
                            Directory.CreateDirectory(pdbOutputPathPdbDir);
                            pdbOutputPath = Path.Combine(pdbOutputPathPdbDir, Path.GetFileName(pdbOutputPath));
                        }

                        // do the main GenFacades logic (which today only works with windows PDBs).
                        using (Stream pdbReadStream = File.OpenRead(pdbLocation))
                            using (PdbReader pdbReader = new PdbReader(pdbReadStream, seedHost))
                                using (PdbWriter pdbWriter = new PdbWriter(pdbOutputPath, pdbReader))
                                {
                                    PeWriter.WritePeToStream(facade, seedHost, peOutStream, pdbReader, pdbReader, pdbWriter);
                                }
                    }
                    else
                    {
                        throw new FacadeGenerationException("Couldn't find the pdb at the given location: " + pdbLocation);
                    }
                }
                else
                {
                    PeWriter.WritePeToStream(facade, seedHost, peOutStream);
                }
            }

            // If we started with Portable PDBs we need to convert the output to portable again.
            // We have to do this after facadeOutputPath is closed for writing.
            if (needsConversion)
            {
                Trace.TraceInformation("Converting PDB generated by GenFacades " + pdbOutputPath + " to portable format " + finalPdbOutputPath);
                ConvertFromWindowsPdb(facadeOutputPath, pdbOutputPath, finalPdbOutputPath);
            }
        }
Esempio n. 7
0
        static int Main(string[] args)
        {
            if (args == null || args.Length < 1)
            {
                Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]");
                return(1);
            }

            using (var host = new PeReader.DefaultHost()) {
                IModule /*?*/ module = host.LoadUnitFrom(args[0]) as IModule;
                if (module == null || module is Dummy)
                {
                    Console.WriteLine(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                    return(1);
                }
                module = new MetadataDeepCopier(host).Copy(module);

                PdbReader /*?*/ pdbReader = null;
                string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                if (File.Exists(pdbFile))
                {
                    using (var pdbStream = File.OpenRead(pdbFile)) {
                        pdbReader = new PdbReader(pdbStream, host);
                    }
                }
                else
                {
                    Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway.");
                }
                using (pdbReader) {
                    var       localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader);
                    ILMutator mutator            = new ILMutator(host, pdbReader);
                    module = mutator.Rewrite(module);

                    string newName;
                    if (args.Length == 2)
                    {
                        newName = args[1];
                    }
                    else
                    {
                        var loc      = module.Location;
                        var path     = Path.GetDirectoryName(loc) ?? "";
                        var fileName = Path.GetFileNameWithoutExtension(loc);
                        var ext      = Path.GetExtension(loc);
                        newName = Path.Combine(path, fileName + "1" + ext);
                    }

                    using (var peStream = File.Create(newName)) {
                        using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) {
                            PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                        }
                    }
                }
                return(0); // success
            }
        }
Esempio n. 8
0
        public override string Run(string tempFolder)
        {
            var assembly   = Generate();
            var fileName   = assembly.Kind == ModuleKind.DynamicallyLinkedLibrary ? DllName : ExeName;
            var resultPath = Path.Combine(tempFolder, fileName);

            using (var fs = File.Create(resultPath))
                PeWriter.WritePeToStream(assembly, Host, fs);
            return(resultPath);
        }
Esempio n. 9
0
 void AssertWriteToPeFile(PeVerifyResult expectedResult, IAssembly assembly, PdbReader pdbReader)
 {
     using (var rewrittenFile = File.Create(assembly.Location)) {
         using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), pdbReader)) {
             PeWriter.WritePeToStream(assembly, host, rewrittenFile, pdbReader, pdbReader, pdbWriter);
         }
     }
     Assert.True(File.Exists(assembly.Location));
     PeVerify.Assert(expectedResult, PeVerify.VerifyAssembly(assembly.Location, true));
 }
Esempio n. 10
0
    void AssertWriteToPeFile(PeVerifyResult expectedResult, IAssembly assembly)
    {
        using (FileStream rewrittenFile = File.Create(assembly.Location)) {
            using (this.pdbReader) {
                PeWriter.WritePeToStream(assembly, this.host, rewrittenFile, this.pdbReader, this.pdbReader, this.pdbWriter);
            }
        }

        Assert.True(File.Exists(assembly.Location));
        PeVerify.Assert(expectedResult, PeVerify.VerifyAssembly(assembly.Location));
    }
Esempio n. 11
0
        internal static void EmitCorLibWithAssemblyReferences(
            Compilation comp,
            string pdbPath,
            Func <CommonPEModuleBuilder, EmitOptions, CommonPEModuleBuilder> getModuleBuilder,
            out ImmutableArray <byte> peBytes,
            out ImmutableArray <byte> pdbBytes)
        {
            var diagnostics   = DiagnosticBag.GetInstance();
            var emitOptions   = EmitOptions.Default.WithRuntimeMetadataVersion("0.0.0.0").WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
            var moduleBuilder = comp.CheckOptionsAndCreateModuleBuilder(
                diagnostics,
                null,
                emitOptions,
                null,
                null,
                null,
                null,
                default(CancellationToken));

            // Wrap the module builder in a module builder that
            // reports the "System.Object" type as having no base type.
            moduleBuilder = getModuleBuilder(moduleBuilder, emitOptions);
            bool result = comp.Compile(
                moduleBuilder,
                emittingPdb: pdbPath != null,
                diagnostics: diagnostics,
                filterOpt: null,
                cancellationToken: default(CancellationToken));

            using (var peStream = new MemoryStream())
            {
                using (var pdbStream = new MemoryStream())
                {
                    PeWriter.WritePeToStream(
                        new EmitContext(moduleBuilder, null, diagnostics, metadataOnly: false, includePrivateMembers: true),
                        comp.MessageProvider,
                        () => peStream,
                        () => pdbStream,
                        null, null,
                        metadataOnly: true,
                        isDeterministic: false,
                        emitTestCoverageData: false,
                        privateKeyOpt: null,
                        cancellationToken: default(CancellationToken));

                    peBytes  = peStream.ToImmutable();
                    pdbBytes = pdbStream.ToImmutable();
                }
            }

            diagnostics.Verify();
            diagnostics.Free();
        }
Esempio n. 12
0
        private static int RunTest(HostEnvironment hostEnvironment, string suiteName, string test, StringBuilder actualOutput, List <string> compilerParameters, List <string> testCaseParameters)
        {
            hostEnvironment.hasError = false;
            IName                     name               = hostEnvironment.NameTable.GetNameFor(suiteName);
            SpecSharpOptions          options            = new SpecSharpOptions(); //TODO: extract from params
            List <IAssemblyReference> assemblyReferences = new List <IAssemblyReference>();
            List <IModuleReference>   moduleReferences   = new List <IModuleReference>();

            assemblyReferences.Add(hostEnvironment.LoadAssembly(hostEnvironment.CoreAssemblySymbolicIdentity));
            IUnit unit;
            SpecSharpAssembly /*?*/    assem = null;
            SpecSharpCompilationHelper helper;

            if (hostEnvironment.previousDocument != null && compilerParameters.Contains("/incremental"))
            {
                unit   = hostEnvironment.GetIncrementalUnit(test);
                helper = (SpecSharpCompilationHelper)hostEnvironment.previousDocument.SpecSharpCompilationPart.Helper;
            }
            else
            {
                List <SpecSharpSourceDocument> programSources = new List <SpecSharpSourceDocument>(1);
                assem  = new SpecSharpAssembly(name, "", hostEnvironment, options, assemblyReferences, moduleReferences, programSources);
                helper = new SpecSharpCompilationHelper(assem.Compilation);
                programSources.Add(hostEnvironment.previousDocument = new SpecSharpSourceDocument(helper, name, "", test));
                unit = assem;
            }
            if (assem != null && assem.Compilation.HasErrors)
            {
                return(0);
            }
            if (assem != null && assem.EntryPoint.ResolvedMethod != Dummy.Method)
            {
                var memStream = new MemoryStream();
                PeWriter.WritePeToStream(assem, hostEnvironment, memStream);
                if (hostEnvironment.hasError)
                {
                    return(0);
                }
                var runtimeAssembly = System.Reflection.Assembly.Load(memStream.ToArray());
                var result          = runtimeAssembly.EntryPoint.Invoke(null, null);
                if (result is int)
                {
                    return((int)result);
                }
                return(0);
            }

            BaseCodeTraverser traverser = new BaseCodeTraverser();

            unit.Dispatch(traverser);
            return(0);
        }
Esempio n. 13
0
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("usage: EdgeProfiler [path]fileName.ext");
                return;
            }
            using (var host = new PeReader.DefaultHost()) {
                IModule /*?*/ module = host.LoadUnitFrom(args[0]) as IModule;
                if (module == null || module is Dummy)
                {
                    Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly.");
                    return;
                }

                var coreIdentity = host.CoreAssemblySymbolicIdentity; //force host to let args[0] determine the target platform
                var profiler     = (IAssembly)host.LoadUnitFrom(typeof(Program).Assembly.Location);
                var logger       = (INamespaceTypeDefinition)UnitHelper.FindType(host.NameTable, profiler, "Logger");

                PdbReader /*?*/ pdbReader = null;
                string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                if (File.Exists(pdbFile))
                {
                    using (var pdbStream = File.OpenRead(pdbFile)) {
                        pdbReader = new PdbReader(pdbStream, host);
                    }
                }

                using (pdbReader) {
                    var instrumentedModule = Instrumenter.GetInstrumented(host, module, pdbReader, logger);
                    var newRoot            = Path.GetFileNameWithoutExtension(module.Location) + ".instrumented";
                    var newName            = newRoot + Path.GetExtension(module.Location);
                    using (var peStream = File.Create(newName)) {
                        if (pdbReader == null)
                        {
                            PeWriter.WritePeToStream(instrumentedModule, host, peStream);
                        }
                        else
                        {
                            var localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader);
                            using (var pdbWriter = new PdbWriter(newRoot + ".pdb", pdbReader)) {
                                PeWriter.WritePeToStream(instrumentedModule, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                            }
                        }
                    }
                }
            }
        }
        public void WriteToStream(IModuleInfo moduleInfo, FileStream stream, string filePath)
        {
            var module = (ModuleInfo)moduleInfo;

            if (module.PdbReader == null)
            {
                PeWriter.WritePeToStream(module.Module, _host, stream);
            }
            else
            {
                using (var pdbWriter = new PdbWriter(Path.ChangeExtension(filePath, "pdb"), module.PdbReader)) {
                    PeWriter.WritePeToStream(module.Module, _host, stream, module.PdbReader,
                                             module.PdbReader, pdbWriter);
                }
            }
        }
Esempio n. 15
0
        static void Main(string[] args)
        {
            if (args == null || args.Length != 2)
            {
                Console.WriteLine("usage: asmmeta <input> <output>");
                return;
            }
            HostEnvironment host   = new HostEnvironment();
            IModule /*?*/   module = host.LoadUnitFrom(args[0]) as IModule;

            if (module == null || module == Dummy.Module || module == Dummy.Assembly)
            {
                Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly.");
                return;
            }

            string outputFile    = args[1];
            string outputPDBFile = Path.ChangeExtension(args[1], "pdb");

            PdbReader /*?*/ pdbReader = null;
            PdbWriter /*?*/ pdbWriter = null;
            string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");

            if (File.Exists(pdbFile))
            {
                Stream pdbStream = File.OpenRead(pdbFile);
                pdbReader = new PdbReader(pdbStream, host);
                pdbWriter = new PdbWriter(Path.GetFullPath(outputPDBFile), pdbReader);
            }

            MetadataMutator mutator  = new MetadataMutator(host);
            IAssembly /*?*/ assembly = module as IAssembly;

            if (assembly != null)
            {
                var mutable = mutator.GetMutableCopy(assembly);
                mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(args[1]));
                module       = mutator.Visit(mutable);
            }
            else
            {
                var mutable = mutator.GetMutableCopy(module);
                mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(args[1]));
                module       = mutator.Visit(mutable);
            }
            PeWriter.WritePeToStream(module, host, File.Create(Path.GetFullPath(outputFile)), pdbReader, pdbReader, pdbWriter);
        }
Esempio n. 16
0
        private static void RewriteBinary(
            Assembly copy,
            AssemblyReport assemblyReport,
            MetadataReaderHost host,
            string outputPath,
            MethodRemoval methodRemoval,
            StubMethodBodyEmitter stubEmitter)
        {
            /* This is an attempt to decouple the MethodRemoval commandline options
             * from the tree shaker, but it doesn't really seem to be working.
             * Might be better to just pass the method removal directly to
             * the rewriter.
             */

            bool removeMethods  = (methodRemoval == MethodRemoval.Remove);
            bool fullDebugStubs = (methodRemoval == MethodRemoval.Debug);
            bool dryRun         = (methodRemoval == MethodRemoval.None);

            PdbReader /*?*/ pdbReader = null;
            string          pdbFile   = Path.ChangeExtension(copy.Location, "pdb");

            if (File.Exists(pdbFile))
            {
                using (var pdbStream = File.OpenRead(pdbFile)) {
                    pdbReader = new PdbReader(pdbStream, host);
                }
            }
            else
            {
                Console.WriteLine("Could not load the PDB file for '" + copy.Name.Value + "' . Proceeding anyway.");
            }

            using (pdbReader) {
                var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader);
                var pdbPath            = Path.ChangeExtension(outputPath, ".pdb");
                var outputFileName     = Path.GetFileNameWithoutExtension(outputPath);
                using (var peStream = File.Create(outputPath)) {
                    using (var pdbWriter = new PdbWriter(pdbPath, pdbReader)) {
                        var       rewriter      = new TreeShakingRewriter(host, assemblyReport, dryRun, removeMethods, fullDebugStubs, stubEmitter);
                        IAssembly rewrittenCopy = rewriter.Rewrite(copy);

                        PeWriter.WritePeToStream(rewrittenCopy, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                    }
                }
            }
        }
Esempio n. 17
0
        public void Save(string fileName)
        {
            var pdbName = Path.ChangeExtension(fileName, "pdb");

            using (var peStream = File.Create(fileName))
            {
                if (this.PdbReader == null)
                {
                    PeWriter.WritePeToStream(this.Module, this.Host, peStream);
                }
                else
                {
                    using (var pdbWriter = new PdbWriter(pdbName, this.PdbReader))
                        PeWriter.WritePeToStream(this.Module, this.Host, peStream, this.PdbReader, this.PdbReader, pdbWriter);
                }
            }
        }
Esempio n. 18
0
        public void Save(CciAssembly assembly, string path)
        {
            Contract.Requires(assembly != null);
            Contract.Requires(!string.IsNullOrEmpty(path));

            var sourceLocationProvider = GetPdbReader(assembly.Module);

            lock (turnstile)
            {
                ContractHelper.InjectContractCalls(host, assembly.Module, assembly.ContractProvider, sourceLocationProvider);
            }
            using (var peStream = File.Create(path))
            {
                lock (turnstile)
                {
                    PeWriter.WritePeToStream(assembly.Module, host, peStream);
                }
            }
        }
Esempio n. 19
0
        public static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("Usage: PInvokeCompiler Input.dll Output.dll");
                return;
            }

            var inputFile  = args[0];
            var outputFile = args[1];

            using (var host = new PeReader.DefaultHost())
            {
                var unit     = host.LoadUnitFrom(inputFile);
                var assembly = unit as IAssembly;

                if (assembly == null)
                {
                    Console.WriteLine("Error: Input file not loadable as assembly");
                    return;
                }

                Assembly mutable = new MetadataDeepCopier(host).Copy(assembly);

                var interopHelperReference = new InteropHelperReferences(host, mutable);

                var pinvokeMethodMetadataTraverser = new PInvokeMethodMetadataTraverser(interopHelperReference.PInvokeHelpers);
                pinvokeMethodMetadataTraverser.TraverseChildren(mutable);

                var methodTransformationMetadataRewriter = new MethodTransformationMetadataRewriter(interopHelperReference.LoadLibrary, interopHelperReference.GetProcAddress, interopHelperReference.IsLibraryInitialized, host, pinvokeMethodMetadataTraverser);
                methodTransformationMetadataRewriter.RewriteChildren(mutable);

                var pinvokeMethodMetadataRewriter = new PInvokeMethodMetadataRewriter(interopHelperReference, host, methodTransformationMetadataRewriter);
                pinvokeMethodMetadataRewriter.RewriteChildren(mutable);

                using (var stream = File.Create(outputFile))
                {
                    PeWriter.WritePeToStream(mutable, host, stream);
                }
            }
        }
Esempio n. 20
0
        public MemoryStream WriteToStream(IModuleInfo moduleInfo)
        {
            var module = (ModuleInfo)moduleInfo;

            _log.Info("CommonCompilerInfra.WriteToFile:" + module.Name);
            MemoryStream stream = new MemoryStream();

            if (module.PdbReader == null)
            {
                PeWriter.WritePeToStream(module.Module, _host, stream);
            }
            else
            {
                throw new NotImplementedException();
                //                using (var pdbWriter = new PdbWriter(Path.ChangeExtension(filePath, "pdb"), module.PdbReader))
                //                {
                //                    PeWriter.WritePeToStream(module.Module, _host, stream, module.SourceLocationProvider,
                //                        module.LocalScopeProvider, pdbWriter);
                //                }
            }
            stream.Position = 0;

            return(stream);
        }
Esempio n. 21
0
        static void Main(string[] args)
        {
            var nameTable = new NameTable();

            using (var host = new PeReader.DefaultHost(nameTable)) {
                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);

                var assembly = new Assembly()
                {
                    Name                 = nameTable.GetNameFor("hello"),
                    ModuleName           = nameTable.GetNameFor("hello.exe"),
                    PlatformType         = host.PlatformType,
                    Kind                 = ModuleKind.ConsoleApplication,
                    RequiresStartupStub  = host.PointerSize == 4,
                    TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion,
                };
                assembly.AssemblyReferences.Add(coreAssembly);

                var rootUnitNamespace = new RootUnitNamespace();
                assembly.UnitNamespaceRoot = rootUnitNamespace;
                rootUnitNamespace.Unit     = assembly;

                var moduleClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass = true,
                    Name    = nameTable.GetNameFor("<Module>"),
                };
                assembly.AllTypes.Add(moduleClass);

                var testClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass  = true,
                    IsPublic = true,
                    Methods  = new List <IMethodDefinition>(1),
                    Name     = nameTable.GetNameFor("Test"),
                };
                rootUnitNamespace.Members.Add(testClass);
                assembly.AllTypes.Add(testClass);
                testClass.BaseClasses = new List <ITypeReference>()
                {
                    host.PlatformType.SystemObject
                };

                var mainMethod = new MethodDefinition()
                {
                    ContainingTypeDefinition = testClass,
                    InternFactory            = host.InternFactory,
                    IsCil      = true,
                    IsStatic   = true,
                    Name       = nameTable.GetNameFor("Main"),
                    Type       = host.PlatformType.SystemVoid,
                    Visibility = TypeMemberVisibility.Public,
                };
                assembly.EntryPoint = mainMethod;
                testClass.Methods.Add(mainMethod);

                var ilGenerator = new ILGenerator(host, mainMethod);

                var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console");
                var writeLine     = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString);

                ilGenerator.Emit(OperationCode.Ldstr, "hello");
                ilGenerator.Emit(OperationCode.Call, writeLine);
                ilGenerator.Emit(OperationCode.Ret);

                var body = new ILGeneratorMethodBody(ilGenerator, true, 1, mainMethod, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty);
                mainMethod.Body = body;

                using (var peStream = File.Create("hello.exe")) {
                    PeWriter.WritePeToStream(assembly, host, peStream);
                }
            }
        }
Esempio n. 22
0
        public void Compile(string fileName)
        {
            string appName = Path.GetFileNameWithoutExtension(fileName);
            string exeName = appName + ".exe";
            string src     = "";

            using (TextReader file = new StreamReader(fileName))
            {
                src = file.ReadToEnd();
            }

            var nameTable = new NameTable();

            using (var host = new PeReader.DefaultHost(nameTable))
            {
                // Load Mirage types

                IModule module = host.LoadUnitFrom("Mirage.dll") as IModule;
                if (module == null || module is Dummy)
                {
                    return;
                }
                var machineType = module.GetAllTypes().First(x => x.Name.Value == "Machine");
                var inputType   = module.GetAllTypes().First(x => x.Name.Value == "ConsoleInput");
                var outputType  = module.GetAllTypes().First(x => x.Name.Value == "ConsoleOutput");

                // Create assembly

                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);
                var assembly     = new Assembly()
                {
                    Name                 = nameTable.GetNameFor(appName),
                    ModuleName           = nameTable.GetNameFor(exeName),
                    PlatformType         = host.PlatformType,
                    Kind                 = ModuleKind.ConsoleApplication,
                    RequiresStartupStub  = host.PointerSize == 4,
                    TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion,
                };
                assembly.AssemblyReferences.Add(coreAssembly);

                // Create namespace

                var rootUnitNamespace = new RootUnitNamespace();
                assembly.UnitNamespaceRoot = rootUnitNamespace;
                rootUnitNamespace.Unit     = assembly;

                // Create module class

                var moduleClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass = true,
                    Name    = nameTable.GetNameFor("<Module>"),
                };
                assembly.AllTypes.Add(moduleClass);

                // Create program class

                var programClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass  = true,
                    IsPublic = true,
                    Methods  = new List <IMethodDefinition>(1),
                    Name     = nameTable.GetNameFor("Program"),
                };
                programClass.BaseClasses = new List <ITypeReference>()
                {
                    host.PlatformType.SystemObject
                };
                rootUnitNamespace.Members.Add(programClass);

                // Add types to the assembly

                assembly.AllTypes.Add(machineType);
                foreach (var t in machineType.NestedTypes)
                {
                    assembly.AllTypes.Add(t);
                }
                assembly.AllTypes.Add(inputType);
                assembly.AllTypes.Add(outputType);
                assembly.AllTypes.Add(programClass);

                // Create main method

                var mainMethod = new MethodDefinition()
                {
                    ContainingTypeDefinition = programClass,
                    InternFactory            = host.InternFactory,
                    IsCil      = true,
                    IsStatic   = true,
                    Name       = nameTable.GetNameFor("Main"),
                    Type       = host.PlatformType.SystemVoid,
                    Visibility = TypeMemberVisibility.Public,
                };
                assembly.EntryPoint = mainMethod;
                programClass.Methods.Add(mainMethod);

                // Create constructors and methods

                IMethodReference machineConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    machineType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );

                IMethodReference inputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    inputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );
                var inputCast = TypeHelper.GetMethod(inputType, nameTable.GetNameFor("op_Implicit"), inputType);

                IMethodReference outputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    outputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );
                var outputCast = TypeHelper.GetMethod(outputType, nameTable.GetNameFor("op_Implicit"), outputType);

                var opIncPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncPointers"));
                var opDecPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecPointers"));
                var opIncHiPointer     = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncHiPointer"));
                var opDecHiPointer     = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecHiPointer"));
                var opReflectHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("ReflectHiPointer"));
                var opLoadHiPointer    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadHiPointer"));
                var opDragLoPointer    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DragLoPointer"));
                var opXchPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("XchPointers"));

                var opClear = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Clear"));
                var opAdd   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Add"));
                var opDec   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Dec"));
                var opNot   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Not"));
                var opAnd   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("And"));
                var opOr    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Or"));
                var opXor   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Xor"));
                var opSal   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sal"));
                var opSar   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sar"));

                var opLoadData = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadData"), host.PlatformType.SystemString);
                var opInput    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Input"), inputCast.Type);
                var opOutput   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Output"), outputCast.Type);

                var opJz = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Jz"));

                // Create program code

                var labels = new Stack <ILGeneratorLabel>(100);

                var ilGenerator = new ILGenerator(host, mainMethod);
                ilGenerator.Emit(OperationCode.Newobj, machineConstructor);
                ilGenerator.Emit(OperationCode.Stloc_0);
                ilGenerator.Emit(OperationCode.Newobj, inputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_1);
                ilGenerator.Emit(OperationCode.Newobj, outputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_2);

                int pc = 0;
                while (pc < src.Length)
                {
                    char opcode = src[pc++];

                    switch (opcode)
                    {
                    case '>':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opIncPointers);
                        break;

                    case '<':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDecPointers);
                        break;

                    case ']':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opIncHiPointer);
                        break;

                    case '[':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDecHiPointer);
                        break;

                    case '#':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opReflectHiPointer);
                        break;

                    case '$':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opLoadHiPointer);
                        break;

                    case '=':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDragLoPointer);
                        break;

                    case '%':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opXchPointers);
                        break;

                    case '_':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opClear);
                        break;

                    case '+':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opAdd);
                        break;

                    case '-':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDec);
                        break;

                    case '~':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opNot);
                        break;

                    case '&':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opAnd);
                        break;

                    case '|':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opOr);
                        break;

                    case '^':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opXor);
                        break;

                    case '*':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opSal);
                        break;

                    case '/':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opSar);
                        break;

                    case '(':
                        int dataStart = pc;
                        int dataEnd   = dataStart;
                        while (src[pc++] != ')')
                        {
                            dataEnd = pc;
                        }
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldstr, src.Substring(dataStart, dataEnd - dataStart));
                        ilGenerator.Emit(OperationCode.Callvirt, opLoadData);
                        break;

                    case '?':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldloc_1);
                        ilGenerator.Emit(OperationCode.Call, inputCast);
                        ilGenerator.Emit(OperationCode.Callvirt, opInput);
                        break;

                    case '!':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldloc_2);
                        ilGenerator.Emit(OperationCode.Call, outputCast);
                        ilGenerator.Emit(OperationCode.Callvirt, opOutput);
                        break;

                    case '{':
                        var cycleStart = new ILGeneratorLabel();
                        var cycleEnd   = new ILGeneratorLabel();
                        labels.Push(cycleStart);
                        labels.Push(cycleEnd);
                        ilGenerator.Emit(OperationCode.Br, cycleEnd);
                        ilGenerator.MarkLabel(cycleStart);
                        break;

                    case '}':
                        ilGenerator.MarkLabel(labels.Pop());
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opJz);
                        ilGenerator.Emit(OperationCode.Ldc_I4_0);
                        ilGenerator.Emit(OperationCode.Ceq);
                        ilGenerator.Emit(OperationCode.Stloc_3);
                        ilGenerator.Emit(OperationCode.Ldloc_3);
                        ilGenerator.Emit(OperationCode.Brtrue, labels.Pop());
                        break;

                    default:
                        break;
                    }
                }

                ilGenerator.Emit(OperationCode.Ret);

                mainMethod.Body = new ILGeneratorMethodBody(
                    ilGenerator,
                    true,
                    8,
                    mainMethod,
                    new List <ILocalDefinition>()
                {
                    new LocalDefinition()
                    {
                        Type = machineType
                    },
                    new LocalDefinition()
                    {
                        Type = inputType
                    },
                    new LocalDefinition()
                    {
                        Type = outputType
                    },
                    new LocalDefinition()
                    {
                        Type = host.PlatformType.SystemInt32
                    },
                },
                    Enumerable <ITypeDefinition> .Empty
                    );

                using (var peStream = File.Create(exeName))
                {
                    PeWriter.WritePeToStream(assembly, host, peStream);
                }
            }
        }
Esempio n. 23
0
        public static void RunBclRewriter(string[] args)
        {
            #region Parse the command-line arguments.
            if (!Parser.ParseArgumentsWithUsage(args, typeof(Program)))
            {
                throw new UsageException();
            }
            #endregion

            #region Figure out paths
            s_assemblyName = Path.GetFullPath(s_assemblyName); // this has to be specified

            string outputBaseName = null;
            if (!String.IsNullOrEmpty(s_output))
            {
                s_output       = Path.GetFullPath(s_output);
                outputBaseName = Path.GetFileNameWithoutExtension(s_output);
            }
            else
            {
                s_output       = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(s_assemblyName) + ".small" + Path.GetExtension(s_assemblyName));
                outputBaseName = s_assemblyName;
            }

            string pdbSourceFile = Path.ChangeExtension(s_assemblyName, "pdb");
            string outputPdb     = Path.ChangeExtension(s_output, "pdb");
            string outputFolder  = Path.GetDirectoryName(s_output);

            // if the user wants to do an in-place rewrite, we copy the file to a temp file
            if (s_output == s_assemblyName)
            {
                String tempPath    = s_assemblyName + TempExtension;
                String tempPdbPath = pdbSourceFile + TempExtension;

                File.Copy(s_assemblyName, tempPath, true);
                s_assemblyName = tempPath;

                if (File.Exists(pdbSourceFile))
                {
                    File.Copy(pdbSourceFile, tempPdbPath, true);
                    pdbSourceFile = tempPdbPath;
                }
            }

            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            #endregion

            #region Load input files
            HostEnvironment host = new HostEnvironment(new NameTable(), s_assemblyDependencyPaths, s_referencedAssemblies);

            IAssembly /*?*/ assembly = host.LoadUnitFrom(s_assemblyName) as IAssembly;
            // TODO: Handle multimodule assemblies
            if (assembly == null || assembly == Dummy.Assembly)
            {
                throw new UsageException(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
            }

            if (!File.Exists(s_includeListFile))
            {
                throw new UsageException(String.Format("ERROR: Can't find code model file '{0}'", s_includeListFile));
            }

            ThinModel model = new ThinModel(new ThinnerOptions(host, new AssemblyIdentity[] { assembly.AssemblyIdentity }));
            model.LoadModel(s_includeListFile, new ModelReaderOptions(s_platform, s_architecture, s_flavor, s_treatFxInternalAsPublic, s_defines));
            #endregion

            #region Calculate api closure.
            ConsoleTimer.StartTimer("Calculating api closure");
            model.LoadMetadataFrom(assembly);

            ThinModel apiClosure = model.CalculateApiClosure();
            if (s_keepTempFiles)
            {
                apiClosure.SaveModel(Path.ChangeExtension(s_output, ".apiClosure.xml"));
            }
            ConsoleTimer.EndTimer("Calculating api closure");
            #endregion

            #region Calculate impl closure.
            ConsoleTimer.StartTimer("Calculating implementation closure");
            apiClosure.LoadMetadataFrom(assembly);

            ThinModel implClosure = apiClosure.CalculateImplementationClosure(true, FieldOptions.KeepAll);

            if (s_keepTempFiles)
            {
                implClosure.SaveModel(Path.ChangeExtension(s_output, ".implClosure.xml"));
            }
            ConsoleTimer.EndTimer("Calculating implementation closure");
            #endregion

            #region Trim.
            ConsoleTimer.StartTimer("Trimming assembly");
            IncludeSet includeSet = new IncludeSet();
            includeSet.LoadFrom(implClosure);

            var      copier         = new MetadataDeepCopier(host);
            Assembly copiedAssembly = copier.Copy(assembly);

            Trimmer trimmer = new Trimmer(includeSet, true, false, true, host, s_removeSerializable);
            trimmer.RewriteChildren(copiedAssembly);
            Assembly mutableAssembly = copiedAssembly;
            assembly = mutableAssembly;

            ConsoleTimer.EndTimer("Trimming assembly");
            #endregion

            #region Update assembly name.
            ConsoleTimer.StartTimer("Updating assembly name");

            // If the output assembly name is different, update the internal assembly name to match.
            AssemblyIdentity originalAssemblyIdentity = mutableAssembly.AssemblyIdentity;
            if (!outputBaseName.Equals(originalAssemblyIdentity.Name.ToString(), StringComparison.OrdinalIgnoreCase))
            {
                mutableAssembly.Name       = host.NameTable.GetNameFor(outputBaseName);
                mutableAssembly.ModuleName = mutableAssembly.Name;
            }

            // If we changed the assembly identity, update references to it.
            if (!mutableAssembly.AssemblyIdentity.Equals(originalAssemblyIdentity))
            {
                trimmer.UpdateAssemblyReferences(originalAssemblyIdentity, mutableAssembly.AssemblyIdentity);
            }

            ConsoleTimer.EndTimer("Updating assembly name");
            #endregion

            #region Write out the assembly
            ConsoleTimer.StartTimer("Writing assembly");
            PdbReader pdbReader = null;
            PdbWriter pdbWriter = null;
            if (File.Exists(pdbSourceFile))
            {
                Stream pdbStream = File.OpenRead(pdbSourceFile);
                pdbReader = new PdbReader(pdbStream, host);
                pdbWriter = new PdbWriter(outputPdb, pdbReader);
                Console.WriteLine("Writing pdb: {0}", outputPdb);
            }

            Console.WriteLine("Writing assembly: {0}", s_output);
            FileStream file = File.Create(s_output);

            try
            {
                PeWriter.WritePeToStream(assembly, host, file, pdbReader, pdbReader, pdbWriter);
            }
            finally
            {
                if (file != null)
                {
                    file.Dispose();
                }

                if (pdbWriter != null)
                {
                    pdbWriter.Dispose();
                }
            }

            ConsoleTimer.EndTimer("Writing assembly");
            #endregion
        }
Esempio n. 24
0
        static void Main(string[] args)
        {
            var nameTable = new NameTable();

            using (var host = new PeReader.DefaultHost(nameTable)) {
                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);

                var assembly = new Assembly()
                {
                    Name                 = nameTable.GetNameFor("hello"),
                    ModuleName           = nameTable.GetNameFor("hello.exe"),
                    Kind                 = ModuleKind.ConsoleApplication,
                    PlatformType         = host.PlatformType,
                    RequiresStartupStub  = host.PointerSize == 4,
                    TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion,
                };
                assembly.AssemblyReferences.Add(coreAssembly);

                var rootUnitNamespace = new RootUnitNamespace();
                assembly.UnitNamespaceRoot = rootUnitNamespace;
                rootUnitNamespace.Unit     = assembly;

                var moduleClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass = true,
                    Name    = nameTable.GetNameFor("<Module>"),
                };
                assembly.AllTypes.Add(moduleClass);

                var testClass = new NamespaceTypeDefinition()
                {
                    BaseClasses = new List <ITypeReference>(1)
                    {
                        host.PlatformType.SystemObject
                    },
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass  = true,
                    IsPublic = true,
                    Methods  = new List <IMethodDefinition>(1),
                    Name     = nameTable.GetNameFor("Test"),
                };
                rootUnitNamespace.Members.Add(testClass);
                assembly.AllTypes.Add(testClass);

                var mainMethod = new MethodDefinition()
                {
                    ContainingTypeDefinition = testClass,
                    InternFactory            = host.InternFactory,
                    IsCil      = true,
                    IsStatic   = true,
                    Name       = nameTable.GetNameFor("Main"),
                    Type       = host.PlatformType.SystemVoid,
                    Visibility = TypeMemberVisibility.Public,
                };
                assembly.EntryPoint = mainMethod;
                testClass.Methods.Add(mainMethod);

                var body = new SourceMethodBody(host)
                {
                    MethodDefinition = mainMethod,
                    LocalsAreZeroed  = true
                };
                mainMethod.Body = body;

                var block = new BlockStatement();
                body.Block = block;

                var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console");
                var writeLine     = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString);

                var call = new MethodCall()
                {
                    IsStaticCall = true, MethodToCall = writeLine, Type = host.PlatformType.SystemVoid
                };
                call.Arguments.Add(new CompileTimeConstant()
                {
                    Type = host.PlatformType.SystemString, Value = "hello"
                });
                block.Statements.Add(new ExpressionStatement()
                {
                    Expression = call
                });
                block.Statements.Add(new ReturnStatement());

                using (var peStream = File.Create("hello.exe")) {
                    PeWriter.WritePeToStream(assembly, host, peStream);
                }
            }
        }
Esempio n. 25
0
        public bool WriteSliceToFile(ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice, string directory, out string dll)
        {
#if TRACE_PERFORMANCE
            var stopWatch = new Stopwatch();
            stopWatch.Start();
#endif

            var newAssembly = Prune.PruneAssembly(host, slice);

#if TRACE_PERFORMANCE
            Console.WriteLine("Time to prune the assembly: {0}", stopWatch.Elapsed);
#endif

            var errors = ValidateAssembly(host, newAssembly);
            if (/*errors != null && */ 0 < errors.Count)
            {
#if !DEBUG_SLICE
                dll = null;
                return(false);
#endif
            }

            //Get a PDB reader if there is a PDB file.
            PdbReader /*?*/ pdbReader = null;
            string          pdbFile   = slice.ContainingAssembly.ResolvedAssembly.DebugInformationLocation;
            if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile))
            {
                pdbFile = Path.ChangeExtension(slice.ContainingAssembly.ResolvedAssembly.Location, "pdb");
            }
            if (File.Exists(pdbFile))
            {
                using (var pdbStream = File.OpenRead(pdbFile)) {
                    pdbReader = new PdbReader(pdbStream, host);
                }
            }
            using (pdbReader) {
                ISourceLocationProvider sourceLocationProvider = pdbReader;
                ILocalScopeProvider     localScopeProvider     = pdbReader;

                Contract.Assume(sourceLocationProvider != null, "why??");
                if (!MakeSureSliceHasAtLeastMethodSourceLocation(slice, sourceLocationProvider))
                {
                    dll = null;
                    return(false);
                }

                dll = Path.Combine(directory, slice.Name + ".dll");

#if TRACE_PERFORMANCE
                stopWatch.Reset();
#endif

                using (var peStream = File.Create(dll)) {
                    if (pdbReader == null)
                    {
                        PeWriter.WritePeToStream(newAssembly, host, peStream);
                    }
                    else
                    {
                        using (var pdbWriter = new PdbWriter(dll.Replace(".dll", ".pdb"), pdbReader, emitTokenSourceInfo: true)) {
                            PeWriter.WritePeToStream(newAssembly, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter);
                        }
                    }
                }

#if TRACE_PERFORMANCE
                Console.WriteLine("Time spent to write on the disk: {0}", stopWatch.Elapsed);
#endif
            }

#if !DEBUG_SLICE
            if (errors != null && 0 < errors.Count)
            {
                using (var tw = new StreamWriter(File.Create(Path.Combine(directory, slice.Name + ".errors.txt"))))
                {
                    // something is performed asynchronously and may not be terminated here, that is wrong!
                    lock (errors)
                    {
                        foreach (var err in errors)
                        {
                            tw.WriteLine(err.Location);
                            foreach (var e in err.Errors)
                            {
                                tw.WriteLine("{0} {1} {2}", e.IsWarning ? "WARNING" : "ERROR ", e.Code, e.Message);
                            }
                            tw.WriteLine();
                        }
                    }
                }

                return(false);
            }
#endif

            // Can this be checked before writing it out?
            if (newAssembly.AssemblyReferences.Any(ar => ar.AssemblyIdentity.Equals(slice.ContainingAssembly.AssemblyIdentity)))
            {
            }

            return(true);
        }
Esempio n. 26
0
        internal int Run()
        {
            SecurityKeepOptions securityKeepOptions = options.onlySecurityTransparent ? SecurityKeepOptions.OnlyNonCritical : SecurityKeepOptions.All;

            if (options.doBreak)
            {
                System.Diagnostics.Debugger.Launch();
            }

            string assemblyName = null;

            if (options.GeneralArguments.Count == 1)
            {
                assemblyName = options.GeneralArguments[0];
            }
            if (assemblyName == null)
            {
                errorLogger("Must specify an input file.");
                return(1);
            }

            using (var host = new AsmMetaHostEnvironment(options.libPaths.ToArray(), options.searchGAC))
            {
                foreach (var p in options.resolvedPaths)
                {
                    host.AddResolvedPath(p);
                }

                IAssembly /*?*/ assembly = host.LoadUnitFrom(assemblyName) as IAssembly;
                if (assembly == null || assembly is Dummy)
                {
                    errorLogger(assemblyName + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                    return(1);
                }

                var rewrittenAttribute = CreateTypeReference(host, assembly, "System.Diagnostics.Contracts.RuntimeContractsAttribute");
                if (AttributeHelper.Contains(assembly.Attributes, rewrittenAttribute))
                {
                    errorLogger(assemblyName + " is already rewritten, cannot generate a reference assembly from it.");
                    return(1);
                }

                if (options.backwardCompatibility)
                { // redundant because RemoveMethodBodies.ctor also does this when the flag is set
                    options.whatToEmit     = KeepOptions.ExtVis;
                    options.emitAttributes = false;
                }

                PdbReader /*?*/ pdbReader = null;
                if (options.includeSourceTextInContract)
                { // No point getting the PDB file unless we want to use it for source text
                    string pdbFile = Path.ChangeExtension(assembly.Location, "pdb");
                    if (File.Exists(pdbFile))
                    {
                        using (var pdbStream = File.OpenRead(pdbFile))
                        {
                            pdbReader = new PdbReader(pdbStream, host);
                        }
                    }
                    else
                    {
                        errorLogger("Could not load the PDB file for the assembly '" + assembly.Name.Value + "' . Source text will not be preserved in the reference assembly. Proceeding anyway.");
                    }
                }
                using (pdbReader)
                {
                    // We might be working on the assembly that defines the contract class and/or the type System.Void.
                    // (Or any other platform type!)
                    // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones.
                    // This is OK, except if the assembly is being renamed.
                    this.compilerGeneratedAttributeType = host.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute;
                    this.contractClassType   = host.PlatformType.SystemDiagnosticsContractsContract;
                    this.systemAttributeType = host.PlatformType.SystemAttribute;
                    this.systemBooleanType   = host.PlatformType.SystemBoolean;
                    this.systemStringType    = host.PlatformType.SystemString;
                    this.systemObjectType    = host.PlatformType.SystemObject;
                    this.systemVoidType      = host.PlatformType.SystemVoid;
                    //new FindPlatformTypes(this).Traverse(assembly); //update the above fields if any of those types are defined in mutable

                    Assembly mutable = new MetadataDeepCopier(host).Copy(assembly);

                    #region Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity

                    if (options.rename)
                    {
                        if (options.output != null)
                        {
                            mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(options.output));
                        }
                        else
                        {
                            mutable.Name = host.NameTable.GetNameFor(assembly.Name.Value + ".Contracts");
                        }
                        mutable.ModuleName = mutable.Name;
                        mutable.Kind       = ModuleKind.DynamicallyLinkedLibrary;
                        mutable            = (Assembly)RenameAssembly.ReparentAssemblyIdentity(host, assembly.AssemblyIdentity, mutable.AssemblyIdentity, mutable);
                    }

                    #endregion Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity
                    if (!options.renameOnly)
                    {
                        if (options.contracts)
                        {
                            if (options.rename)
                            {
                                // We might be working on the assembly that defines the contract class and/or the type System.Void.
                                // (Or any other platform type!)
                                // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones.
                                // This is OK, except if the assembly is being renamed.

                                var systemNamespace = GetFirstMatchingNamespace(host, mutable.UnitNamespaceRoot, "System");
                                if (systemNamespace != null)
                                {
                                    var typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Attribute");
                                    if (typeDefinition != null)
                                    {
                                        this.systemAttributeType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Boolean");
                                    if (typeDefinition != null)
                                    {
                                        this.systemBooleanType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Object");
                                    if (typeDefinition != null)
                                    {
                                        this.systemObjectType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "String");
                                    if (typeDefinition != null)
                                    {
                                        this.systemStringType = typeDefinition;
                                    }
                                    typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Void");
                                    if (typeDefinition != null)
                                    {
                                        this.systemVoidType = typeDefinition;
                                    }

                                    var systemRuntimeNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Runtime");
                                    if (systemRuntimeNamespace != null)
                                    {
                                        var systemRuntimeCompilerServicesNamespace = GetFirstMatchingNamespace(host, systemRuntimeNamespace, "CompilerServices");
                                        if (systemRuntimeCompilerServicesNamespace != null)
                                        {
                                            typeDefinition = GetFirstMatchingTypeDefinition(host, systemRuntimeCompilerServicesNamespace, "CompilerGeneratedAttribute");
                                            if (typeDefinition != null)
                                            {
                                                this.compilerGeneratedAttributeType = typeDefinition;
                                            }
                                        }
                                    }

                                    var systemDiagnosticsNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Diagnostics");
                                    if (systemDiagnosticsNamespace != null)
                                    {
                                        var systemDiagnosticsContractsNamespace = GetFirstMatchingNamespace(host, systemDiagnosticsNamespace, "Contracts");
                                        if (systemDiagnosticsContractsNamespace != null)
                                        {
                                            typeDefinition = GetFirstMatchingTypeDefinition(host, systemDiagnosticsContractsNamespace, "Contract");
                                            if (typeDefinition != null)
                                            {
                                                this.contractClassType = typeDefinition;
                                            }
                                        }
                                    }
                                }
                            }

                            mutable = AsmMetaRewriter.RewriteModule(host,
                                                                    pdbReader,
                                                                    mutable,
                                                                    contractClassType,
                                                                    compilerGeneratedAttributeType,
                                                                    systemAttributeType,
                                                                    systemBooleanType,
                                                                    systemObjectType,
                                                                    systemStringType,
                                                                    systemVoidType
                                                                    ) as Assembly;
                        }
                        #region Delete things that are not to be kept
                        if (options.backwardCompatibility || options.whatToEmit != KeepOptions.All || !options.emitAttributes || (options.attrs != null && 0 < options.attrs.Count))
                        {
                            DeleteThings thinner = new DeleteThings(host, options.whatToEmit, securityKeepOptions, options.emitAttributes, options.attrs.ToArray(), options.backwardCompatibility);
                            if (securityKeepOptions == SecurityKeepOptions.OnlyNonCritical && host.platformType.SystemSecuritySecurityCriticalAttribute.ResolvedType is Dummy)
                            {
                                errorLogger("You asked to remove security critical methods, but the version of mscorlib doesn't support the SecurityCriticalAttribute.");
                                return(1);
                            }
                            thinner.RewriteChildren(mutable);
                            #region Fix up dangling references to things that were deleted
                            FixUpReferences patcher = new FixUpReferences(host, thinner.WhackedMethods, thinner.WhackedTypes);
                            patcher.RewriteChildren(mutable);
                            #endregion Fix up dangling references to things that were deleted
                        }
                        #endregion Delete things that are not to be kept
                        #region Output is always a dll, so mark the assembly as that
                        mutable.EntryPoint = Dummy.MethodReference;
                        mutable.Kind       = ModuleKind.DynamicallyLinkedLibrary;
                        #endregion Output is always a dll, so mark the assembly as that
                    }

                    assembly = mutable;

                    string outputPath;
                    if (options.output != null) // user specified, they'd better make sure it doesn't conflict with anything
                    {
                        outputPath = options.output;
                    }
                    else if (options.rename) // A.dll ==> A.Contracts.dll (Always! Even if the input is an exe!)
                    {
                        outputPath = assembly.Name.Value + ".dll";
                    }
                    else // A.dll ==> A.dll.meta
                    {
                        outputPath = assembly.Name.Value + Path.GetExtension(assemblyName) + ".meta";
                    }
                    // NB: Do *not* pass a pdbWriter to WritePeToStream. No need to create a PDB file and if
                    // it is provided, then it might find things (like constants in a scope) that don't get
                    // visited and so don't have any type references modified as they should be.
                    using (var outputFile = File.Create(outputPath))
                    {
                        if (pdbReader != null && options.writePDB)
                        {
                            using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), pdbReader))
                            {
                                // Need to not pass in a local scope provider until such time as we have one that will use the mutator
                                // to remap things (like the type of a scope constant) from the original assembly to the mutated one.
                                PeWriter.WritePeToStream(assembly, host, outputFile, pdbReader, null /*pdbReader*/, pdbWriter);
                            }
                        }
                        else
                        {
                            PeWriter.WritePeToStream(assembly, host, outputFile);
                        }
                    }
                }
            }
            return(0); // success
        }
Esempio n. 27
0
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("usage: PeToPe [path]fileName.ext");
                return;
            }

            using (var host = new PeReader.DefaultHost()) {
                var module = host.LoadUnitFrom(args[0]) as IModule;
                if (module == null || module is Dummy)
                {
                    Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly.");
                    return;
                }

                PdbReader /*?*/ pdbReader = null;
                string          pdbFile   = module.DebugInformationLocation;
                if (string.IsNullOrEmpty(pdbFile))
                {
                    pdbFile = Path.ChangeExtension(module.Location, "pdb");
                }
                if (File.Exists(pdbFile))
                {
                    Stream pdbStream = File.OpenRead(pdbFile);
                    pdbReader = new PdbReader(pdbStream, host);
                }

                using (pdbReader) {
                    //Make a mutable copy of the module.
                    var copier        = new MetadataDeepCopier(host);
                    var mutableModule = copier.Copy(module);

                    //Traverse the module. In a real application the MetadataVisitor and/or the MetadataTravers will be subclasses
                    //and the traversal will gather information to use during rewriting.
                    var traverser = new MetadataTraverser()
                    {
                        PreorderVisitor = new MetadataVisitor(), TraverseIntoMethodBodies = true
                    };
                    traverser.Traverse(mutableModule);

                    //Rewrite the mutable copy. In a real application the rewriter would be a subclass of MetadataRewriter that actually does something.
                    var rewriter        = new MetadataRewriter(host);
                    var rewrittenModule = rewriter.Rewrite(mutableModule);

                    //Write out rewritten module.
                    using (var peStream = File.Create(rewrittenModule.Location + ".pe")) {
                        if (pdbReader == null)
                        {
                            PeWriter.WritePeToStream(rewrittenModule, host, peStream);
                        }
                        else
                        {
                            //Note that the default copier and rewriter preserves the locations collections, so the original pdbReader is still a valid ISourceLocationProvider.
                            //However, if IL instructions were rewritten, the pdbReader will no longer be an accurate ILocalScopeProvider
                            using (var pdbWriter = new PdbWriter(pdbFile + ".pdb", pdbReader)) {
                                PeWriter.WritePeToStream(rewrittenModule, host, peStream, pdbReader, pdbReader, pdbWriter);
                            }
                        }
                    }
                }
            }
        }
Esempio n. 28
0
        static int Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("usage: HelloContracts [path]fileName.Contracts.dll [-libpaths ...]* [-p [-i] | -inject]");
                return(1);
            }
            #region Parse options
            var options = new Options();
            options.Parse(args);
            if (options.HelpRequested)
            {
                options.PrintOptions("");
                return(1);
            }
            if (options.HasErrors)
            {
                options.PrintErrorsAndExit(Console.Out);
            }
            #endregion

            var fileName = String.IsNullOrEmpty(options.assembly) ? options.GeneralArguments[0] : options.assembly;

            if (options.printContracts)
            {
                #region Collect and write contracts
                using (var host = new CodeContractAwareHostEnvironment(options.libpaths)) {
                    IModule module = host.LoadUnitFrom(fileName) as IModule;
                    if (module == null || module is Dummy)
                    {
                        Console.WriteLine("'{0}' is not a PE file containing a CLR module or assembly.", fileName);
                        Environment.Exit(1);
                    }
                    var t = new Traverser(host, options.inherited);
                    t.Traverse(module);
                }
                #endregion
                return(0);
            }
            else
            {
                using (var host = new CodeContractAwareHostEnvironment(options.libpaths, true, true)) {
                    // Read the Metadata Model from the PE file
                    var module = host.LoadUnitFrom(fileName) as IModule;
                    if (module == null || module is Dummy)
                    {
                        Console.WriteLine(fileName + " is not a PE file containing a CLR module or assembly.");
                        return(1);
                    }

                    // Get a PDB reader if there is a PDB file.
                    PdbReader /*?*/ pdbReader = null;
                    string          pdbFile   = Path.ChangeExtension(module.Location, "pdb");
                    if (File.Exists(pdbFile))
                    {
                        using (var pdbStream = File.OpenRead(pdbFile)) {
                            pdbReader = new PdbReader(pdbStream, host);
                        }
                    }

                    using (pdbReader) {
                        ISourceLocationProvider sourceLocationProvider = pdbReader;

                        // Construct a Code Model from the Metadata model via decompilation
                        var mutableModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, DecompilerOptions.AnonymousDelegates | DecompilerOptions.Loops);
                        ILocalScopeProvider localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader);

                        // Extract contracts (side effect: removes them from the method bodies)
                        var contractProvider = Microsoft.Cci.MutableContracts.ContractHelper.ExtractContracts(host, mutableModule, pdbReader, localScopeProvider);

                        // Inject non-null postconditions
                        if (options.inject)
                        {
                            new NonNullInjector(host, contractProvider).Traverse(mutableModule);
                        }

                        // Put the contracts back in as method calls at the beginning of each method
                        Microsoft.Cci.MutableContracts.ContractHelper.InjectContractCalls(host, mutableModule, contractProvider, sourceLocationProvider);

                        // Write out the resulting module. Each method's corresponding IL is produced
                        // lazily using CodeModelToILConverter via the delegate that the mutator stored in the method bodies.
                        using (var peStream = File.Create(mutableModule.Location + ".pe")) {
                            if (pdbReader == null)
                            {
                                PeWriter.WritePeToStream(mutableModule, host, peStream);
                            }
                            else
                            {
                                using (var pdbWriter = new PdbWriter(mutableModule.Location + ".pdb", sourceLocationProvider)) {
                                    PeWriter.WritePeToStream(mutableModule, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter);
                                }
                            }
                        }
                    }
                }
                return(0);
            }
        }
Esempio n. 29
0
        public void Save(bool autoHandleDependencies = false)
        {
            lock (this) {
                if (_manifest != null)
                {
                    _pendingChanges = _manifest.Modified || _pendingChanges;
                }
                // Logger.Message("Saving Binary '{0}' : Pending Changes: {1} ", _filename, _pendingChanges);
                if (_pendingChanges)
                {
                    // saves any changes made to the binary.
                    // work on a back up of the file
                    var tmpFilename = _filename.CreateWritableWorkingCopy();

                    try {
                        // remove any digital signatures from the binary before doing anything
                        if (!IsManaged)
                        {
                            StripSignatures(tmpFilename); // this is irrelevant if the binary is managed--we'll be writing out a new one.
                        }
                        // rewrite any native resources that we want to change.

                        if (IsManaged && ILOnly)
                        {
                            // we can only edit the file if it's IL only, mixed mode assemblies can only be strong named, signed and native-resource-edited.
                            // set the strong name key data
                            MutableAssembly.PublicKey = StrongNameKey.ToList();

                            // change any assembly attributes we need to change
                            if (MutableAssembly != null)
                            {
                                if (StrongNameKeyCertificate != null)
                                {
                                    foreach (var ar in MutableAssembly.AssemblyReferences)
                                    {
                                        if (!ar.PublicKeyToken.Any())
                                        {
                                            var dep = FindAssembly(ar.Name.Value, ar.Version.ToString());
                                            if (dep == null)
                                            {
                                                // can't strong name a file that doesn't have its deps all strong named.
                                                throw new ClrPlusException("dependent assembly '{0}-{1}' not available for strong naming".format(ar.Name.Value, ar.Version.ToString()));
                                            }

                                            lock (dep) {
                                                // this should wait until the dependency is finished saving, right?
                                            }

                                            if (dep.MutableAssembly.PublicKey.IsNullOrEmpty())
                                            {
                                                if (autoHandleDependencies)
                                                {
                                                    Console.WriteLine(
                                                        "Warning: Non-strong-named dependent reference found: '{0}-{1}' updating with same strong-name-key.",
                                                        ar.Name, ar.Version);
                                                    dep.StrongNameKeyCertificate = StrongNameKeyCertificate;
                                                    dep.SigningCertificate       = SigningCertificate;

                                                    dep.AssemblyCopyright = AssemblyCopyright;
                                                    dep.AssemblyCompany   = AssemblyCompany;
                                                    dep.AssemblyProduct   = AssemblyProduct;

                                                    dep.Save();
                                                }
                                                else
                                                {
                                                    throw new ClrPlusException("dependent assembly '{0}-{1}' not strong named".format(ar.Name.Value, ar.Version.ToString()));
                                                }
                                            }
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKeyToken = dep.MutableAssembly.PublicKeyToken.ToList();
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKey      = dep.MutableAssembly.PublicKey;
                                        }
                                    }
                                }

                                // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones.
                                try {
                                    foreach (var a in MutableAssembly.AssemblyAttributes)
                                    {
                                        var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant);
                                        if (attributeArgument != null)
                                        {
                                            var attributeName = a.Type.ToString();
                                            switch (attributeName)
                                            {
                                            case "System.Reflection.AssemblyTitleAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyTitle) ? string.Empty : AssemblyTitle;
                                                break;

                                            case "System.Reflection.AssemblyDescriptionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyDescription) ? string.Empty : AssemblyDescription;
                                                break;

                                            case "System.Reflection.AssemblyCompanyAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyCompany) ? string.Empty : AssemblyCompany;
                                                break;

                                            case "System.Reflection.AssemblyProductAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyProduct) ? string.Empty : AssemblyProduct;
                                                break;

                                            case "System.Reflection.AssemblyVersionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyVersion) ? string.Empty : AssemblyVersion;
                                                break;

                                            case "System.Reflection.AssemblyFileVersionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyFileVersion) ? string.Empty : AssemblyFileVersion;
                                                break;

                                            case "System.Reflection.AssemblyCopyrightAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyCopyright) ? string.Empty : AssemblyCopyright;
                                                break;

                                            case "System.Reflection.AssemblyTrademarkAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyTrademark) ? string.Empty : AssemblyTrademark;
                                                break;

                                            case "BugTrackerAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(BugTracker) ? string.Empty : BugTracker;
                                                break;
                                            }
                                        }
                                    }
                                } catch {
                                    // hmm. carry on.
                                }
                            }

                            // save it to disk
                            using (var peStream = File.Create(tmpFilename)) {
                                PeWriter.WritePeToStream(MutableAssembly, _host, peStream);
                            }
                        }

                        // update native metadata
                        try {
                            var ri = new ResourceInfo();

                            ri.Load(tmpFilename);

                            if (_manifest != null && _manifest.Modified)
                            {
                                // GS01: We only support one manifest right now.
                                // so we're gonna remove the extra ones.
                                // figure out the bigger case later.
                                var manifestKeys = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_MANIFEST).ToArray();
                                foreach (var k in manifestKeys)
                                {
                                    ri.Resources.Remove(k);
                                }

                                var manifestResource = new ManifestResource();
                                manifestResource.ManifestText = _manifest.ToString();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_MANIFEST), new List <Resource> {
                                    manifestResource
                                });
                                manifestResource.SaveTo(tmpFilename);
                            }

                            VersionResource versionResource;
                            StringTable     versionStringTable;

                            var versionKey = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_VERSION).FirstOrDefault();
                            if (versionKey != null)
                            {
                                versionResource    = ri.Resources[versionKey].First() as VersionResource;
                                versionStringTable = (versionResource["StringFileInfo"] as StringFileInfo).Strings.Values.First();
                            }
                            else
                            {
                                versionResource = new VersionResource();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_VERSION), new List <Resource> {
                                    versionResource
                                });

                                var sfi = new StringFileInfo();
                                versionResource["StringFileInfo"] = sfi;
                                sfi.Strings["040904b0"]           = (versionStringTable = new StringTable("040904b0"));

                                var vfi = new VarFileInfo();
                                versionResource["VarFileInfo"] = vfi;
                                var translation = new VarTable("Translation");
                                vfi.Vars["Translation"] = translation;
                                translation[0x0409]     = 0x04b0;
                            }

                            versionResource.FileVersion    = FileVersion;
                            versionResource.ProductVersion = ProductVersion;

                            versionStringTable["ProductName"]      = ProductName;
                            versionStringTable["CompanyName"]      = CompanyName;
                            versionStringTable["FileDescription"]  = FileDescription;
                            versionStringTable["Comments"]         = _comments;
                            versionStringTable["Assembly Version"] = _assemblyVersion;
                            versionStringTable["FileVersion"]      = _fileVersion;
                            versionStringTable["ProductVersion"]   = _productVersion;
                            versionStringTable["InternalName"]     = _internalName;
                            versionStringTable["OriginalFilename"] = _originalFilename;
                            versionStringTable["LegalCopyright"]   = _legalCopyright;
                            versionStringTable["LegalTrademarks"]  = _legalTrademarks;
                            versionStringTable["BugTracker"]       = _bugTracker;

                            versionResource.SaveTo(tmpFilename);
                        } catch (Exception e) {
                            Console.WriteLine("{0} -- {1}", e.Message, e.StackTrace);
                        }

                        // strong name the binary
                        if (IsManaged && StrongNameKeyCertificate != null && (StrongNameKeyCertificate.Certificate.PrivateKey is RSACryptoServiceProvider))
                        {
                            ApplyStrongName(tmpFilename, StrongNameKeyCertificate);
                        }

                        // sign the binary
                        if (_signingCertificate != null)
                        {
                            SignFile(tmpFilename, SigningCertificate.Certificate);
                        }

                        _filename.TryHardToDelete();
                        File.Move(tmpFilename, _filename);
                    } catch (Exception e) {
#if TODO
                        Logger.Error(e);
#endif
                        // get rid of whatever we tried
                        tmpFilename.TryHardToDelete();

                        // as you were...
                        throw;
                    }
                }
                _pendingChanges = false;
                if (_manifest != null)
                {
                    _manifest.Modified = false;
                }
            }
        }
Esempio n. 30
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
            for (int i = 0; i < targets.Length; i++)
            {
                var path = targets[i] = Path.GetFullPath(targets[i]);
                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 = AmendmentAttribute.GetAmendments(assemblies.Select(a => System.Reflection.Assembly.LoadFrom(a.DllBackupPath)).ToArray()).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)
            {
                var assemblyAmendments = amendments.Where(a => a.Type.Assembly.Location == assembly.DllBackupPath).ToArray();
                if (assemblyAmendments.Length == 0)
                {
                    continue;
                }

                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 = new MetadataDeepCopier(host).Copy(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, assemblyAmendments);
                        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)");
            }
        }