Inheritance: IDisposable
Beispiel #1
0
        public FullPeWriter(
            EmitContext context,
            CommonMessageProvider messageProvider,
            PdbWriter pdbWriter,
            bool allowMissingMethodBodies,
            bool deterministic,
            CancellationToken cancellationToken)
            : base(context, messageProvider, pdbWriter, allowMissingMethodBodies, deterministic, cancellationToken)
        {
            // EDMAURER make some intelligent guesses for the initial sizes of these things.
            int numMethods           = this.module.HintNumberOfMethodDefinitions;
            int numTypeDefsGuess     = numMethods / 6;
            int numFieldDefsGuess    = numTypeDefsGuess * 4;
            int numPropertyDefsGuess = numMethods / 4;

            this.typeDefs          = new DefinitionIndex <ITypeDefinition>(numTypeDefsGuess);
            this.eventDefs         = new DefinitionIndex <IEventDefinition>(0);
            this.fieldDefs         = new DefinitionIndex <IFieldDefinition>(numFieldDefsGuess);
            this.methodDefs        = new DefinitionIndex <IMethodDefinition>(numMethods);
            this.propertyDefs      = new DefinitionIndex <IPropertyDefinition>(numPropertyDefsGuess);
            this.parameterDefs     = new DefinitionIndex <IParameterDefinition>(numMethods);
            this.genericParameters = new DefinitionIndex <IGenericParameter>(0);

            this.fieldDefIndex      = new Dictionary <ITypeDefinition, uint>(numTypeDefsGuess);
            this.methodDefIndex     = new Dictionary <ITypeDefinition, uint>(numTypeDefsGuess);
            this.parameterListIndex = new Dictionary <IMethodDefinition, uint>(numMethods);

            this.assemblyRefIndex         = new HeapOrReferenceIndex <IAssemblyReference>(this, AssemblyReferenceComparer.Instance);
            this.moduleRefIndex           = new HeapOrReferenceIndex <string>(this);
            this.memberRefIndex           = new InstanceAndStructuralReferenceIndex <ITypeMemberReference>(this, new MemberRefComparer(this));
            this.methodSpecIndex          = new InstanceAndStructuralReferenceIndex <IGenericMethodInstanceReference>(this, new MethodSpecComparer(this));
            this.typeRefIndex             = new HeapOrReferenceIndex <ITypeReference>(this);
            this.typeSpecIndex            = new InstanceAndStructuralReferenceIndex <ITypeReference>(this, new TypeSpecComparer(this));
            this.standAloneSignatureIndex = new HeapOrReferenceIndex <uint>(this);
        }
Beispiel #2
0
        public bool TrimBinaries(string sourceDir, string outputDir)
        {
            bool fSuccess = true;

            foreach (TrimAssembly trimAssembly in _includeSet.GetAllAssemblies())
            {
                _currentTrimAssembly = trimAssembly;

                try
                {
                    string sourceFile = Path.Combine(sourceDir, trimAssembly.Name + ".dll");
                    string outputFile = Path.Combine(outputDir, trimAssembly.Name + ".dll");

                    Console.WriteLine("loading assembly '" + sourceFile + "'");
                    IModule module = host.LoadUnitFrom(sourceFile) as IModule;

                    if (module == null || module == Dummy.Module || module == Dummy.Assembly)
                    {
                        throw new Exception(sourceFile + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it.");
                    }

                    // Working around bug 
                    DummyTraverser dummyTraverser = new DummyTraverser();

                    PdbReader pdbReader = null;
                    PdbWriter pdbWriter = null;
                    string pdbSourceFile = Path.ChangeExtension(sourceFile, "pdb");
                    string pdbOutputFile = Path.ChangeExtension(outputFile, "pdb");
                    if (File.Exists(pdbSourceFile))
                    {
                        Stream pdbStream = File.OpenRead(pdbSourceFile);
                        pdbReader = new PdbReader(pdbStream, host);
                        pdbWriter = new PdbWriter(Path.GetFullPath(pdbOutputFile), pdbReader);
                    }

                    IAssembly/*?*/ assembly = module as IAssembly;
                    if (assembly != null)
                    {
                        dummyTraverser.Visit(assembly);
                        module = this.Rewrite(assembly);
                    }
                    else
                    {
                        dummyTraverser.Visit(module);
                        module = this.Rewrite(module);
                    }
                    PeWriter.WritePeToStream(module, host, File.Create(outputFile), pdbReader, pdbReader, pdbWriter);
                }
                catch (Exception e)
                {
                    Console.WriteLine(trimAssembly.Key + ": " + e.Message);
                    throw;
                }
            }

            if (!fSuccess)
                Console.Error.WriteLine(String.Format("At least one of the assemblies could not be processed!"));

            return fSuccess;
        }
        private void WriteModule(string assemblyPath)
        {
            Contract.Requires(!String.IsNullOrEmpty(assemblyPath));

            var module = this.host.MutatedAssembly;
            PdbReader _pdbReader;
            if (!this.host.TryGetMutatedPdbReader(out _pdbReader))
                _pdbReader = null;

            // write module to disk
            var newAssemblyPath = Path.ChangeExtension(assemblyPath, ".ccs") + Path.GetExtension(assemblyPath);
            var pdbPath = Path.ChangeExtension(assemblyPath, ".pdb");
            var newPdbPath = Path.ChangeExtension(newAssemblyPath, ".pdb");
            this.host.Event(CcsEventLevel.Message, "rewriting {0} -> {1}", assemblyPath, newAssemblyPath);
            using (var peStream = File.Create(newAssemblyPath))
            {
                if (_pdbReader == null)
                    PeWriter.WritePeToStream(module, this.host, peStream);
                else
                {
                    Contract.Assert(_pdbReader != null);
                    this.host.Event(CcsEventLevel.Message, "rewriting {0} -> {1}", pdbPath, newPdbPath);
                    using (var pdbWriter = new PdbWriter(newPdbPath, _pdbReader))
                        PeWriter.WritePeToStream(module, this.host, peStream, _pdbReader, _pdbReader, pdbWriter);
                }
            }
        }
Beispiel #4
0
 private PeWriter(IModule module, PdbWriter nativePdbWriter, bool deterministic)
 {
     _module = module;
     _emitRuntimeStartupStub = module.RequiresStartupStub;
     _nativePdbWriter = nativePdbWriter;
     _deterministic = deterministic;
     _sizeOfImportAddressTable = _emitRuntimeStartupStub ? (!_module.Requires64bits ? 8u : 16u) : 0;
 }
Beispiel #5
0
    static int Main(string[] args) {

        /*
      if (args == null || args.Length < 1) {
        Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]");
        return 1;
      }
         */

        String inputFile = @"c:\Users\typ\Documents\Visual Studio 2013\Projects\vererbung\vererbung\bin\Debug\vererbung.exe";


      using (var host = new PeReader.DefaultHost()) {
        //IModule/*?*/ module = host.LoadUnitFrom(args[0]) as IModule;
        IModule/*?*/ module = host.LoadUnitFrom(inputFile) 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);

          module = RewriteStoreLocal.RewriteModule(host, localScopeProvider, pdbReader, module);

          string newName;
          if (args.Length == 2) {
            //newName = args[1];
            newName = @"e:\mutated.exe";
          } 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);
            newName = @"e:\mutated.exe";
          }

          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
      }
    }
    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);
              }
            }
          }
        }
      }
    }
Beispiel #7
0
        public static void Process(ILoggerContext logger, ProjectDetails assemblyDetails, string tempFolder = null)
        {
            if (!assemblyDetails.Verify(logger))
                return;

            tempFolder = tempFolder ?? Path.GetTempPath();

            string pdbFile = Path.ChangeExtension(assemblyDetails.AssemblyPath, ".pdb");

            var newAssemblyPath = Path.Combine(tempFolder, String.Format("{0}.weavr{1}", Path.GetFileNameWithoutExtension(assemblyDetails.AssemblyPath), Path.GetExtension(assemblyDetails.AssemblyPath)));
            var newPdbPath = File.Exists(pdbFile) ? Path.ChangeExtension(newAssemblyPath, ".pdb") : null;

            using (var host = new PeReader.DefaultHost())
            {
                var targetAssembly = (IAssembly)host.LoadUnitFrom(assemblyDetails.AssemblyPath);

                using (var pdbStream = newPdbPath != null ? File.OpenRead(pdbFile) : null)
                using (var pdbReader = newPdbPath != null ? new PdbReader(pdbStream, host) : null)
                {
                    var decompiled = Decompiler.GetCodeModelFromMetadataModel(host, targetAssembly, pdbReader);
                    decompiled = new CodeDeepCopier(host, pdbReader).Copy(decompiled);

                    var engine = new Engine(logger, host);
                    engine.Process(assemblyDetails, decompiled);

                    using (var peStream = File.Create(newAssemblyPath))
                    {
                        if (pdbReader == null)
                        {
                            PeWriter.WritePeToStream(decompiled, host, peStream);
                        }
                        else
                        {
                            using (var pdbWriter = new PdbWriter(newPdbPath, pdbReader))
                            {
                                PeWriter.WritePeToStream(decompiled, host, peStream, pdbReader, pdbReader, pdbWriter);
                            }
                        }
                    }
                }
            }

            File.Delete(assemblyDetails.AssemblyPath);
            File.Move(newAssemblyPath, assemblyDetails.AssemblyPath);

            if (!string.IsNullOrEmpty(newPdbPath))
            {
                File.Delete(pdbFile);
                File.Move(newPdbPath, pdbFile);
            }
        }
Beispiel #8
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func<Stream> getPeStream,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool deterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var peWriter = new PeWriter(context.Module, pdbPathOpt, deterministic);
            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken);

            return peWriter.WritePeToStream(mdWriter, getPeStream, nativePdbWriterOpt);
        }
        public FullPeWriter(
            Microsoft.CodeAnalysis.Emit.Context context,
            CommonMessageProvider messageProvider,
            PdbWriter pdbWriter,
            bool allowMissingMethodBodies,
            bool foldIdenticalMethodBodies,
            CancellationToken cancellationToken) :
            base(context, messageProvider, pdbWriter, allowMissingMethodBodies, foldIdenticalMethodBodies, cancellationToken)
        {
            // EDMAURER make some intelligent guesses for the initial sizes of these things.
            int numMethods           = this.module.HintNumberOfMethodDefinitions;
            int numTypeDefsGuess     = numMethods / 6;
            int numFieldDefsGuess    = numTypeDefsGuess * 4;
            int numPropertyDefsGuess = numMethods / 4;

            this.typeDefs          = new DefinitionIndex <ITypeDefinition>(numTypeDefsGuess);
            this.eventDefs         = new DefinitionIndex <IEventDefinition>(0);
            this.fieldDefs         = new DefinitionIndex <IFieldDefinition>(numFieldDefsGuess);
            this.methodDefs        = new DefinitionIndex <IMethodDefinition>(numMethods);
            this.propertyDefs      = new DefinitionIndex <IPropertyDefinition>(numPropertyDefsGuess);
            this.parameterDefs     = new DefinitionIndex <IParameterDefinition>(numMethods);
            this.genericParameters = new DefinitionIndex <IGenericParameter>(0);

            this.fieldDefIndex      = new Dictionary <ITypeDefinition, uint>(numTypeDefsGuess);
            this.methodDefIndex     = new Dictionary <ITypeDefinition, uint>(numTypeDefsGuess);
            this.parameterListIndex = new Dictionary <IMethodDefinition, uint>(numMethods);

            this.assemblyRefIndex         = new HeapOrReferenceIndex <IAssemblyReference>(this, AssemblyReferenceComparer.Instance);
            this.moduleRefIndex           = new HeapOrReferenceIndex <string>(this);
            this.memberRefIndex           = new InstanceAndStructuralReferenceIndex <ITypeMemberReference>(this, new MemberRefComparer(this));
            this.methodSpecIndex          = new InstanceAndStructuralReferenceIndex <IGenericMethodInstanceReference>(this, new MethodSpecComparer(this));
            this.typeRefIndex             = new HeapOrReferenceIndex <ITypeReference>(this);
            this.typeSpecIndex            = new InstanceAndStructuralReferenceIndex <ITypeReference>(this, new TypeSpecComparer(this));
            this.standAloneSignatureIndex = new HeapOrReferenceIndex <uint>(this);

            // Add zero-th entry for indexed tables in full metadata. (For delta
            // metadata, the indexed tables will be concatenated with the full
            // metadata by the CLR, so the zero-th entries are not needed.)
            this.blobWriter.WriteByte(0);
            this.stringWriter.WriteByte(0);
            this.userStringWriter.WriteByte(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);
              }
            }
          }
        }
      }
    }
Beispiel #11
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);
    }
Beispiel #12
0
        internal static CompilationDifference EmitDifference(
            this Compilation compilation,
            EmitBaseline baseline,
            ImmutableArray <SemanticEdit> edits)
        {
            Stream pdbStream;
            CompilationTestData testData = new CompilationTestData();

            var pdbName = Path.ChangeExtension(compilation.SourceModule.Name, "pdb");

            pdbStream = new MemoryStream();
            using (var pdbWriter = new Cci.PdbWriter(pdbName, new ComStreamWrapper(pdbStream)))
            {
                using (MemoryStream mdStream = new MemoryStream(), ilStream = new MemoryStream())
                {
                    var updatedMethodTokens = new List <uint>();
                    var result = compilation.EmitDifference(
                        baseline,
                        edits,
                        mdStream,
                        ilStream,
                        pdbStream,
                        updatedMethodTokens,
                        testData,
                        default(CancellationToken));

                    pdbStream.Seek(0, SeekOrigin.Begin);

                    return(new CompilationDifference(
                               mdStream.ToImmutable(),
                               ilStream.ToImmutable(),
                               pdbStream,
                               result.Baseline,
                               testData,
                               result));
                }
            }
        }
Beispiel #13
0
        public static void WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Stream peStream,
            PdbWriter nativePdbWriterOpt,
            bool allowMissingMethodBodies,
            bool deterministic,
            CancellationToken cancellationToken)
        {
            var peWriter = new PeWriter(context.Module, nativePdbWriterOpt, deterministic);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken);

            if (nativePdbWriterOpt != null)
            {
                nativePdbWriterOpt.SetMetadataEmitter(mdWriter);
            }

            uint entryPointToken;
            peWriter.WritePeToStream(mdWriter, peStream, nativePdbWriterOpt, out entryPointToken);

            if (nativePdbWriterOpt != null)
            {
                if (entryPointToken != 0)
                {
                    nativePdbWriterOpt.SetEntryPoint(entryPointToken);
                }

                var assembly = context.Module.AsAssembly;
                if (assembly != null && assembly.Kind == ModuleKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(context.Module.GetSymbolToLocationMap());
                }
            }
        }
 public CustomDebugInfoWriter(PdbWriter pdbWriter)
 {
     Debug.Assert(pdbWriter != null);
     _pdbWriter = pdbWriter;
 }
Beispiel #15
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);
         }
     }
 }
Beispiel #16
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
        }
Beispiel #17
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func<Stream> getPeStream,
            Func<Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.Properties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup;
            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;
            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);
            
            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return false;
            }

            ContentId nativePdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(ContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer();

            var peBuilder = new PEBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit,
                deterministicIdProvider: isDeterministic ? new Func<BlobBuilder, ContentId>(content => ContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null);

            ContentId portablePdbContentId;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                Debug.Assert(getPortablePdbStreamOpt != null);

                var debugMetadataBuilder = new BlobBuilder();
                var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle);
                debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, peBuilder.IdProvider, out portablePdbContentId);

                // write to Portable PDB stream:
                Stream portablePdbStream = getPortablePdbStreamOpt();
                if (portablePdbStream != null)
                {
                    debugMetadataBuilder.WriteContentTo(portablePdbStream);
                }
            }
            else
            {
                portablePdbContentId = default(ContentId);
            }

            var peDirectoriesBuilder = new PEDirectoriesBuilder();

            peBuilder.AddManagedSections(
                peDirectoriesBuilder,
                metadataSerializer,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                pdbPathOpt,
                nativePdbContentId,
                portablePdbContentId,
                properties.CorFlags);

            var peBlob = new BlobBuilder();
            ContentId peContentId;
            peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId);

            // Patch MVID
            if (!mvidFixup.IsDefault)
            {
                var mvidWriter = new BlobWriter(mvidFixup);
                mvidWriter.WriteBytes(peContentId.Guid);
                Debug.Assert(mvidWriter.RemainingBytes == 0);
            }

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when (!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return true;
        }
Beispiel #18
0
        /// <inheritdoc />
        /// <remarks>
        /// This implementation will save the file in-place based on the path of the target assembly
        /// that we're instrumenting, but with a .instrumented tacked on before the original file's
        /// extension.
        /// </remarks>
        public IAssemblyTarget Save()
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException("Unable to save, object already disposed!");
            }

            var path = this.MutableAssembly.Location;
            var originalExt = Path.GetExtension(path);
            path = Path.ChangeExtension(path, ".instrumented" + originalExt);

            using (var file = File.Create(path))
            {
                if (this.pdbReader == null)
                {
                    PeWriter.WritePeToStream(this.MutableAssembly, host, file);
                }
                else
                {
                    // Assumption: LocalScopeProvider shouldn't be null if the PDBReader isn't null.
                    using (var pdbWriter = new PdbWriter(path + ".pdb", this.PdbReader))
                    {
                        PeWriter.WritePeToStream(
                            this.MutableAssembly,
                            this.Host,
                            file,
                            this.SourceLocationProvider,
                            this.LocalScopeProvider,
                            pdbWriter);
                    }
                }

                return AssemblyTarget.FromPath(new Uri(path), path, GetAssemblyName(this.MutableAssembly));
            }
        }
    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);
            }
          }
        }
      }
    }
Beispiel #20
0
        static int RealMain(string[] args)
        {
            int errorReturnValue = -1;

            #region Check options

            ILMerge.options = new ILMergeOptions();
            options.Parse(args);

            if (options.HelpRequested)
            {
                options.PrintOptions("");
                return(errorReturnValue);
            }
            if (options.HasErrors)
            {
                options.PrintErrorsAndExit(Console.Out);
            }

            if (options.breakIntoDebugger)
            {
                System.Diagnostics.Debugger.Break();
            }
            #endregion

            Version version = null;
            if (options.version != null)
            {
                TryGetVersionNumber(options.version, out version);
            }

            using (var host = new ILMergeHost(options.libpaths)) {
                if (options.libpaths != null)
                {
                    foreach (var libpath in options.libpaths)
                    {
                        host.AddLibPath(libpath);
                    }
                }

                Assembly /*?*/ primaryAssembly = null;
                var            modules         = new List <Module>();
                var            unit2SourceLocationProviderMap = new Dictionary <IUnit, ISourceLocationProvider>();
                var            unit2LocalScopeProviderMap     = new Dictionary <IUnit, ILocalScopeProvider>();
                try {
                    for (int i = 0; i < options.GeneralArguments.Count; i++)
                    {
                        var unitName = options.GeneralArguments[i];
                        var u        = host.LoadUnitFrom(unitName) as IModule;
                        if (i == 0)
                        {
                            IAssembly /*?*/ assembly = u as IAssembly;
                            if (assembly == null || assembly is Dummy)
                            {
                                Console.WriteLine(unitName + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
                                return(errorReturnValue);
                            }
                            // Use (the copy of) the first input assembly as the merged assembly!
                            primaryAssembly = new MetadataDeepCopier(host).Copy(assembly);
                        }
                        else
                        {
                            var copier        = new MetadataDeepCopier(host, primaryAssembly);
                            var mutableModule = copier.Copy(u);
                            modules.Add(mutableModule);
                        }
                        PdbReader /*?*/ pdbReader = null;
                        string          pdbFile   = Path.ChangeExtension(u.Location, "pdb");
                        if (File.Exists(pdbFile))
                        {
                            using (var pdbStream = File.OpenRead(pdbFile)) {
                                pdbReader = new PdbReader(pdbStream, host);
                            }
                            unit2SourceLocationProviderMap.Add(u, pdbReader);
                            unit2LocalScopeProviderMap.Add(u, pdbReader);
                        }
                        else
                        {
                            Console.WriteLine("Could not load the PDB file for the unit '" + u.Name.Value + "' . Proceeding anyway.");
                            unit2SourceLocationProviderMap.Add(u, null);
                        }
                    }

                    //PdbWriter/*?*/ pdbWriter = null;

                    RewriteUnitReferences renamer = new RewriteUnitReferences(host, modules, options);
                    renamer.targetAssembly           = primaryAssembly;
                    renamer.originalAssemblyIdentity = primaryAssembly.AssemblyIdentity;

                    int totalNumberOfTypes = primaryAssembly.AllTypes.Count;

                    #region Pass 1: Mutate each input module (including the primary assembly) so everything is re-parented to the merged assembly
                    renamer.RewriteChildren(primaryAssembly);
                    for (int i = 0, n = modules.Count; i < n; i++)
                    {
                        var mutableModule = modules[i];
                        // call Rewrite and not RewriteChildren so dynamic dispatch can call the right rewriter method
                        // otherwise, it just rewrites it as a module, not whatever subtype it is.
                        renamer.Rewrite(mutableModule);
                        // However, the rewriter does *not* rewrite parents. So need to re-parent the root unit namespace
                        // of the mutable assembly so it points to the merged assembly. Otherwise, interning (among other
                        // things) will not work correctly.
                        var rootUnitNs = (RootUnitNamespace)mutableModule.UnitNamespaceRoot;
                        rootUnitNs.Unit     = primaryAssembly;
                        totalNumberOfTypes += mutableModule.AllTypes.Count;
                    }
                    #endregion

                    #region Pass 2: Collect all of the types into the merged assembly

                    var mergedTypes = new List <INamedTypeDefinition>(totalNumberOfTypes);

                    #region Merge together all of the <Module> classes from the input assemblies
                    // TODO: Merge all of the <Module> classes, i.e., type 0 from each of the input assemblies
                    mergedTypes.Add(primaryAssembly.AllTypes[0]);
                    #endregion

                    var internedKeys = new HashSet <string>(); // keep track of all namespace type definitions

                    #region Types from the primary assembly
                    for (int i = 1, n = primaryAssembly.AllTypes.Count; i < n; i++)
                    {
                        var t = primaryAssembly.AllTypes[i];
                        mergedTypes.Add(t);
                        if (t is INamespaceTypeDefinition) // don't care about nested types
                        {
                            var key = TypeHelper.GetTypeName(t, NameFormattingOptions.None);
                            internedKeys.Add(key);
                        }
                    }
                    #endregion

                    #region Types from the other input assemblies, taking care of duplicates

                    for (int i = 0, n = modules.Count; i < n; i++)
                    {
                        var module   = modules[i];
                        var unitName = module.Name.Value;
                        for (int j = 1, m = module.AllTypes.Count; j < m; j++)
                        {
                            var t = module.AllTypes[j];
                            var namespaceTypeDefinition = t as NamespaceTypeDefinition;
                            // duplicates can be only at the top-level: namespace type definitions
                            // if a namespace type definition is unique, then so are all of its nested types
                            if (namespaceTypeDefinition != null)
                            {
                                var typeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix);
                                if (internedKeys.Contains(typeName)) // error: duplicate!
                                {
                                    if (!namespaceTypeDefinition.IsPublic || options.allowDup)
                                    {
                                        var newName = String.Format("{0}_from_{1}", namespaceTypeDefinition.Name.Value, unitName);
                                        namespaceTypeDefinition.Name = host.NameTable.GetNameFor(newName);
                                        var newTypeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix);
                                        Console.WriteLine("Adding '{0}' as '{1}'", typeName, newTypeName);
                                        internedKeys.Add(typeName);
                                        t = namespaceTypeDefinition;
                                    }
                                    else
                                    {
                                        Console.WriteLine("Error: Duplicate type '{0}'", typeName);
                                        continue; //TODO: set a flag somewhere to force a failure.
                                    }
                                }
                                else
                                {
                                    //Console.WriteLine("Adding '{0}'", typeName);
                                    internedKeys.Add(typeName);
                                }
                            }
                            mergedTypes.Add(t);
                        }
                    }
                    #endregion

                    primaryAssembly.AllTypes = mergedTypes;

                    #endregion

                    CopyResourcesToPrimaryAssembly(primaryAssembly, modules);

                    if (version != null)
                    {
                        primaryAssembly.Version = version;
                    }

                    string outputPath;
                    if (options.output != null)
                    {
                        outputPath = options.output;
                    }
                    else
                    {
                        outputPath = primaryAssembly.Name.Value + Path.GetExtension(options.GeneralArguments[0]) + ".meta";
                    }

                    using (var aggregateSourceLocationProvider = new AggregatingSourceLocationProvider(unit2SourceLocationProviderMap)) {
                        using (var aggregateLocalScopeProvider = new AggregatingLocalScopeProvider(unit2LocalScopeProviderMap)) {
                            using (var peStream = File.Create(outputPath)) {
                                using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), aggregateSourceLocationProvider)) {
                                    PeWriter.WritePeToStream(primaryAssembly, host, peStream, aggregateSourceLocationProvider, aggregateLocalScopeProvider, pdbWriter);
                                }
                            }
                        }
                    }
                } finally {
                }

                return(0); // success
            }
        }
 public CustomDebugInfoWriter(PdbWriter pdbWriter)
 {
     Debug.Assert(pdbWriter != null);
     _pdbWriter = 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);
                }
            }
        }
Beispiel #23
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func<Stream> getPeStream,
            Func<Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.SerializationProperties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup, mvidStringFixup;
            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup,
                out mvidStringFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;
            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);
            
            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                // embedded text not currently supported for native PDB and we should have validated that
                Debug.Assert(!mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments.Any());
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return false;
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(BlobContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion = 0;
            var metadataRootBuilder = mdWriter.GetRootBuilder();

            var peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            var deterministicIdProvider = isDeterministic ?
                new Func<IEnumerable<Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) :
                null;

            BlobBuilder portablePdbToEmbed = null;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);

                var portablePdbBlob = new BlobBuilder();
                var portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes, debugEntryPointHandle, deterministicIdProvider);
                pdbContentId = portablePdbBuilder.Serialize(portablePdbBlob);
                portablePdbVersion = portablePdbBuilder.FormatVersion;

                if (getPortablePdbStreamOpt == null)
                {
                    // embed to debug directory:
                    portablePdbToEmbed = portablePdbBlob;
                }
                else
                {
                    // write to Portable PDB stream:
                    Stream portablePdbStream = getPortablePdbStreamOpt();
                    if (portablePdbStream != null)
                    {
                        portablePdbBlob.WriteContentTo(portablePdbStream);
                    }
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }

                if (portablePdbToEmbed != null)
                {
                    debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion);
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            var peBuilder = new ManagedPEBuilder(
                peHeaderBuilder,
                metadataRootBuilder,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                properties.CorFlags,
                deterministicIdProvider);

            var peBlob = new BlobBuilder();
            var peContentId = peBuilder.Serialize(peBlob);

            PatchModuleVersionIds(mvidFixup, mvidStringFixup, peContentId.Guid);

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when (!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return true;
        }
    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 outputFileName = Path.GetFileNameWithoutExtension(outputPath);
        using (var peStream = File.Create(outputPath)) {
          using (var pdbWriter = new PdbWriter(outputFileName + ".pdb", pdbReader)) {
            var rewriter = new TreeShakingRewriter(host, assemblyReport, dryRun, removeMethods, fullDebugStubs, stubEmitter);
            IAssembly rewrittenCopy = rewriter.Rewrite(copy);

            PeWriter.WritePeToStream(rewrittenCopy, host, peStream, pdbReader, localScopeProvider, pdbWriter);
          }
        }
      }
    }
        private static List<ErrorReportItem> RewriteAssembly(CodeContractAwareHostEnvironment host, string assemblyFullPath, MemoryContractsInformation memoryContractsInformation, PointsToInformation pointsToInformation)
        {
            var module = host.LoadUnitFrom(assemblyFullPath) as IModule;

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

            if (module != null && module != Dummy.Module && module != Dummy.Assembly)
            {
                var mutableModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader);

                using (pdbReader)
                {
                    var contractProvider = Microsoft.Cci.MutableContracts.ContractHelper.ExtractContracts(host, mutableModule, pdbReader, pdbReader);

                    var mutator = new MemoryVisitor(host, pdbReader, contractProvider, memoryContractsInformation, pointsToInformation);

                    mutator.Visit(mutableModule);

                    Microsoft.Cci.MutableContracts.ContractHelper.InjectContractCalls(host, mutableModule, contractProvider, pdbReader);

                    Stream peStream = File.Create(Path.ChangeExtension(mutableModule.Location, ".mod.dll"));

                    if (pdbReader == null)
                    {
                        PeWriter.WritePeToStream(mutableModule, host, peStream);
                    }
                    else
                    {
                        using (var pdbWriter = new PdbWriter(Path.ChangeExtension(pdbFile, ".mod.pdb"), pdbReader))
                        {
                            PeWriter.WritePeToStream(mutableModule, host, peStream, pdbReader, pdbReader, pdbWriter);
                        }
                    }

                    peStream.Close();

                    return mutator.ErrorReportItems;
                }
            }

            return null;
        }
Beispiel #26
0
        private bool WritePeToStream(MetadataWriter mdWriter, Func<Stream> getPeStream, Func<Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt)
        {
            // TODO: we can precalculate the exact size of IL stream
            var ilWriter = new BlobBuilder(32 * 1024);
            var metadataWriter = new BlobBuilder(16 * 1024);
            var mappedFieldDataWriter = new BlobBuilder();
            var managedResourceWriter = new BlobBuilder(1024);

            var debugMetadataWriterOpt = (getPortablePdbStreamOpt != null) ? new BlobBuilder(16 * 1024) : null;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(_properties.PersistentIdentifier == default(Guid));

            int sectionCount = 1;
            if (_properties.RequiresStartupStub) sectionCount++; //.reloc
            if (!IteratorHelper.EnumerableIsEmpty(_nativeResourcesOpt) || _nativeResourceSectionOpt != null) sectionCount++; //.rsrc;

            int sizeOfPeHeaders = ComputeSizeOfPeHeaders(sectionCount);
            int textSectionRva = BitArithmeticUtilities.Align(sizeOfPeHeaders, _properties.SectionAlignment);

            int moduleVersionIdOffsetInMetadataStream;
            int methodBodyStreamRva = textSectionRva + OffsetToILStream;

            int entryPointToken;
            MetadataSizes metadataSizes;
            mdWriter.SerializeMetadataAndIL(
                metadataWriter,
                debugMetadataWriterOpt,
                nativePdbWriterOpt,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                methodBodyStreamRva,
                mdSizes => CalculateMappedFieldDataStreamRva(textSectionRva, mdSizes),
                out moduleVersionIdOffsetInMetadataStream,
                out entryPointToken,
                out metadataSizes);

            ContentId nativePdbContentId;
            if (nativePdbWriterOpt != null)
            {
                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                nativePdbContentId = nativePdbWriterOpt.GetContentId();

                // the writer shall not be used after this point for writing:
                nativePdbWriterOpt = null;
            }
            else
            {
                nativePdbContentId = default(ContentId);
            }
            
            // write to Portable PDB stream:
            ContentId portablePdbContentId;
            Stream portablePdbStream = getPortablePdbStreamOpt?.Invoke();
            if (portablePdbStream != null)
            {
                debugMetadataWriterOpt.WriteContentTo(portablePdbStream);

                if (_deterministic)
                {
                    portablePdbContentId = ContentId.FromHash(CryptographicHashProvider.ComputeSha1(portablePdbStream));
                }
                else
                {
                    portablePdbContentId = new ContentId(Guid.NewGuid().ToByteArray(), BitConverter.GetBytes(_timeStamp));
                }
            }
            else
            {
                portablePdbContentId = default(ContentId);
            }

            // Only the size of the fixed part of the debug table goes here.
            DirectoryEntry debugDirectory = default(DirectoryEntry);
            DirectoryEntry importTable = default(DirectoryEntry);
            DirectoryEntry importAddressTable = default(DirectoryEntry);
            int entryPointAddress = 0;

            if (EmitPdb)
            {
                debugDirectory = new DirectoryEntry(textSectionRva + ComputeOffsetToDebugTable(metadataSizes), ImageDebugDirectoryBaseSize);
            }

            if (_properties.RequiresStartupStub)
            {
                importAddressTable = new DirectoryEntry(textSectionRva, SizeOfImportAddressTable);
                entryPointAddress = CalculateMappedFieldDataStreamRva(textSectionRva, metadataSizes) - (_is32bit ? 6 : 10); // TODO: constants
                importTable = new DirectoryEntry(textSectionRva + ComputeOffsetToImportTable(metadataSizes), (_is32bit ? 66 : 70) + 13); // TODO: constants
            }

            var corHeaderDirectory = new DirectoryEntry(textSectionRva + SizeOfImportAddressTable, size: CorHeaderSize);

            long ntHeaderTimestampPosition;
            long metadataPosition;

            List<SectionHeader> sectionHeaders = CreateSectionHeaders(metadataSizes, sectionCount);

            CoffHeader coffHeader;
            NtHeader ntHeader;
            FillInNtHeader(sectionHeaders, entryPointAddress, corHeaderDirectory, importTable, importAddressTable, debugDirectory, out coffHeader, out ntHeader);

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return false;
            }

            WriteHeaders(peStream, ntHeader, coffHeader, sectionHeaders, out ntHeaderTimestampPosition);

            WriteTextSection(
                peStream,
                sectionHeaders[0],
                importTable.RelativeVirtualAddress,
                importAddressTable.RelativeVirtualAddress,
                entryPointToken,
                metadataWriter,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                metadataSizes,
                nativePdbContentId,
                portablePdbContentId,
                out metadataPosition);

            var resourceSection = sectionHeaders.FirstOrDefault(s => s.Name == ResourceSectionName);
            if (resourceSection != null)
            {
                WriteResourceSection(peStream, resourceSection);
            }

            var relocSection = sectionHeaders.FirstOrDefault(s => s.Name == RelocationSectionName);
            if (relocSection != null)
            {
                WriteRelocSection(peStream, relocSection, entryPointAddress);
            }

            if (_deterministic)
            {
                var mvidPosition = metadataPosition + moduleVersionIdOffsetInMetadataStream;
                WriteDeterministicGuidAndTimestamps(peStream, mvidPosition, ntHeaderTimestampPosition);
            }

            return true;
        }
Beispiel #27
0
        internal static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool metadataOnly,
            bool isDeterministic,
            bool emitTestCoverageData,
            RSAParameters?privateKeyOpt,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, metadataOnly, isDeterministic,
                                                     emitTestCoverageData, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.SerializationProperties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup, mvidStringFixup;

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup,
                out mvidStringFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;

            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint(MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                if (context.Module.SourceLinkStreamOpt != null)
                {
                    nativePdbWriterOpt.EmbedSourceLink(context.Module.SourceLinkStreamOpt);
                }

                if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                nativePdbWriterOpt.WriteRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default;

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion  = 0;
            var    metadataRootBuilder = mdWriter.GetRootBuilder();

            var peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            // TODO: replace SHA1 with non-crypto alg: https://github.com/dotnet/roslyn/issues/24737
            var peIdProvider = isDeterministic ?
                               new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeHash(HashAlgorithmName.SHA1, content))) :
                               null;

            // We need to calculate the PDB checksum, so we may as well use the calculated hash for PDB ID regardless of whether deterministic build is requested.
            var portablePdbContentHash = default(ImmutableArray <byte>);

            BlobBuilder portablePdbToEmbed = null;
            if (mdWriter.EmitPortableDebugMetadata)
            {
                mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);

                // The algorithm must be specified for deterministic builds (checked earlier).
                Debug.Assert(!isDeterministic || context.Module.PdbChecksumAlgorithm.Name != null);

                var portablePdbIdProvider = (context.Module.PdbChecksumAlgorithm.Name != null) ?
                                            new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(portablePdbContentHash = CryptographicHashProvider.ComputeHash(context.Module.PdbChecksumAlgorithm, content))) :
                                            null;

                var portablePdbBlob    = new BlobBuilder();
                var portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes.RowCounts, debugEntryPointHandle, portablePdbIdProvider);
                pdbContentId       = portablePdbBuilder.Serialize(portablePdbBlob);
                portablePdbVersion = portablePdbBuilder.FormatVersion;

                if (getPortablePdbStreamOpt == null)
                {
                    // embed to debug directory:
                    portablePdbToEmbed = portablePdbBlob;
                }
                else
                {
                    // write to Portable PDB stream:
                    Stream portablePdbStream = getPortablePdbStreamOpt();
                    if (portablePdbStream != null)
                    {
                        try
                        {
                            portablePdbBlob.WriteContentTo(portablePdbStream);
                        }
                        catch (Exception e) when(!(e is OperationCanceledException))
                        {
                            throw new SymUnmanagedWriterException(e.Message, e);
                        }
                    }
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);

                    if (!portablePdbContentHash.IsDefault)
                    {
                        // Emit PDB Checksum entry for Portable and Embedded PDBs. The checksum is not as useful when the PDB is embedded,
                        // however it allows the client to efficiently validate a standalone Portable PDB that
                        // has been extracted from Embedded PDB and placed next to the PE file.
                        debugDirectoryBuilder.AddPdbChecksumEntry(context.Module.PdbChecksumAlgorithm.Name, portablePdbContentHash);
                    }
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }

                if (portablePdbToEmbed != null)
                {
                    debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion);
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            var strongNameProvider = context.Module.CommonCompilation.Options.StrongNameProvider;
            var corFlags           = properties.CorFlags;

            var peBuilder = new ExtendedPEBuilder(
                peHeaderBuilder,
                metadataRootBuilder,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module, privateKeyOpt),
                entryPointHandle,
                corFlags,
                peIdProvider,
                metadataOnly && !context.IncludePrivateMembers);

            var peBlob      = new BlobBuilder();
            var peContentId = peBuilder.Serialize(peBlob, out Blob mvidSectionFixup);

            PatchModuleVersionIds(mvidFixup, mvidSectionFixup, mvidStringFixup, peContentId.Guid);

            if (privateKeyOpt != null && corFlags.HasFlag(CorFlags.StrongNameSigned))
            {
                Debug.Assert(strongNameProvider.Capability == SigningCapability.SignsPeBuilder);
                strongNameProvider.SignPeBuilder(peBuilder, peBlob, privateKeyOpt.Value);
            }

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }
Beispiel #28
0
        static void Main(string[] args) {

            //String inputFile = @"c:\Users\typ\Documents\Visual Studio 2013\Projects\vererbung\vererbung\bin\Debug\vererbung.exe";
            String inputFile = @"e:\dile_v0_2_12_x86\Dile.exe";

            

            globalLog = new Log(@"e:\merge_logfile.txt");

            System.Console.WriteLine(inputFile);

            /*
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]");
                return;
            }
            */




            using (var host = new PeReader.DefaultHost()) {
                //IModule/*?*/ module = host.LoadUnitFrom(args[0]) as IModule;
                IModule/*?*/ module = host.LoadUnitFrom(inputFile) 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.");
                    Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly.");
                    return;
                }

                module = new MetadataDeepCopier(host).Copy(module);

                if (module as Assembly == null) {
                    globalLog.writeLine("File does not have CIL assembly");
                    return;
                }


                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 {
                    globalLog.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway.");
                }

                using (pdbReader) {

                    Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null;
                    if (pdbReader != null) {
                        localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader);
                    }











                    // AB HIER DER INTERESSANTE PART ZUM MERGEN, DAVOR NUR INIT CRAP

                    // search for class in namespace
                    NamespaceTypeDefinition foundClass = null;
                    foreach (var asdf in module.GetAllTypes()) {
                        //if (asdf.ToString() == "vererbung.Erber") {
                        if (asdf.ToString() == "Dile.Disassemble.Assembly") {                            
                            foundClass = (asdf as NamespaceTypeDefinition);
                            break;
                        }
                    }
                    if (foundClass == null) {
                        globalLog.writeLine("Class not found!");
                        return;
                    }

                    // merge class
                    globalLog.writeLine("Merge class \"" + foundClass.ToString() + "\" with all ancestors");
                    mergeClassWithAllAncestors(foundClass, host);






                    string newName;
                    if (args.Length == 2) {
                        newName = args[1];
                        //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe";
                        newName = @"e:\test.exe";
                    }
                    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);
                        //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe";
                        newName = @"e:\test.exe";
                    }

                    using (var peStream = File.Create(newName)) {
                        using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) {
                            PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                        }
                    }
                }
            }
        }
Beispiel #29
0
        private bool WritePeToStream(MetadataWriter mdWriter, Func<Stream> getPeStream, Func<Stream> getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt)
        {
            // TODO: we can precalculate the exact size of IL stream
            var ilWriter = new BlobWriter(32 * 1024);
            var metadataWriter = new BlobWriter(16 * 1024);
            var mappedFieldDataWriter = new BlobWriter();
            var managedResourceWriter = new BlobWriter(1024);

            var debugMetadataWriterOpt = (getPortablePdbStreamOpt != null) ? new BlobWriter(16 * 1024) : null;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(_module.PersistentIdentifier == default(Guid));

            int moduleVersionIdOffsetInMetadataStream;
            var calculateMethodBodyStreamRva = new Func<MetadataSizes, int>(mdSizes =>
            {
                FillInTextSectionHeader(mdSizes);
                return (int)_textSection.RelativeVirtualAddress + _sizeOfImportAddressTable + 72;
            });

            int entryPointToken;
            MetadataSizes metadataSizes;
            mdWriter.SerializeMetadataAndIL(
                metadataWriter,
                debugMetadataWriterOpt,
                nativePdbWriterOpt,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                calculateMethodBodyStreamRva,
                CalculateMappedFieldDataStreamRva,
                out moduleVersionIdOffsetInMetadataStream,
                out entryPointToken,
                out metadataSizes);

            ContentId nativePdbContentId;
            if (nativePdbWriterOpt != null)
            {
                if (entryPointToken != 0)
                {
                    nativePdbWriterOpt.SetEntryPoint((uint)entryPointToken);
                }

                var assembly = _module.AsAssembly;
                if (assembly != null && assembly.Kind == ModuleKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(_module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(_module.GetSymbolToLocationMap());
#endif
                }

                nativePdbContentId = nativePdbWriterOpt.GetContentId();

                // the writer shall not be used after this point for writing:
                nativePdbWriterOpt = null;
            }
            else
            {
                nativePdbContentId = default(ContentId);
            }

            FillInSectionHeaders();

            // fill in header fields.
            FillInNtHeader(metadataSizes, CalculateMappedFieldDataStreamRva(metadataSizes));
            var corHeader = CreateCorHeader(metadataSizes, entryPointToken);

            // write to PE stream.
            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return false;
            }

            long ntHeaderTimestampPosition;
            long metadataPosition;

            WriteHeaders(peStream, out ntHeaderTimestampPosition);

            WriteTextSection(
                peStream,
                corHeader,
                metadataWriter,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                metadataSizes,
                nativePdbContentId,
                out metadataPosition);

            WriteRdataSection(peStream);
            WriteSdataSection(peStream);
            WriteCoverSection(peStream);
            WriteTlsSection(peStream);
            WriteResourceSection(peStream);
            WriteRelocSection(peStream);

            if (_deterministic)
            {
                var mvidPosition = metadataPosition + moduleVersionIdOffsetInMetadataStream;
                WriteDeterministicGuidAndTimestamps(peStream, mvidPosition, ntHeaderTimestampPosition);
            }

            return true;
        }
Beispiel #30
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            var properties = context.Module.Properties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            var ilBuilder = new BlobBuilder(32 * 1024);
            var mappedFieldDataBuilder = new BlobBuilder();
            var managedResourceBuilder = new BlobBuilder(1024);

            Blob mvidFixup;

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out mvidFixup);

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;

            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(BlobContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion = 0;
            var    metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer();

            var peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            var deterministicIdProvider = isDeterministic ?
                                          new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) :
                                          null;

            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                Debug.Assert(getPortablePdbStreamOpt != null);

                var debugMetadataBuilder    = new BlobBuilder();
                var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle, deterministicIdProvider);
                debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, out pdbContentId);
                portablePdbVersion = debugMetadataSerializer.FormatVersion;

                // write to Portable PDB stream:
                Stream portablePdbStream = getPortablePdbStreamOpt();
                if (portablePdbStream != null)
                {
                    debugMetadataBuilder.WriteContentTo(portablePdbStream);
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            var peBuilder = new ManagedPEBuilder(
                peHeaderBuilder,
                metadataSerializer,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                properties.CorFlags,
                deterministicIdProvider);

            var           peBlob = new BlobBuilder();
            BlobContentId peContentId;
            peBuilder.Serialize(peBlob, out peContentId);

            // Patch MVID
            if (!mvidFixup.IsDefault)
            {
                var writer = new BlobWriter(mvidFixup);
                writer.WriteGuid(peContentId.Guid);
                Debug.Assert(writer.RemainingBytes == 0);
            }

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }
Beispiel #31
0
        static void Main(string[] args) {
            String inputFile;
            String targetFile;
            String targetNamespace;
            String targetClass;
            String targetMethod;
            int depth;
            int dimension;
            int numberValidPaths;
            int duplicateBasicBlockWeight;
            int duplicateBasicBlockCorrectionValue;
            int stateChangeWeight;
            int stateChangeCorrectionValue;
            int insertOpaquePredicateWeight;
            int seed;

            // Add debugging code into the obfuscated method (dump obfuscation graphs and so on)
            bool graphTransformerDebug = false;

            // Should the obfuscated code contain information to trace the control flow?
            bool basicBlockTrace = false;

            // When debugging is active, should the whole obfuscation graph be dumped or only the vpaths in it?
            bool graphOnlyDumpVPaths = true;

            // The number of random interfaces that are added to the program
            int numberRandomInterfaces = 100;

            if (args.Length != 14) {
                System.Console.WriteLine("Needed parameters: <inputBinary> <outputBinary> <namespace> <class> <method> <depth> <dimension> <numberValidPaths> <duplicateBasicBlockWeight> <duplicateBasicBlockCorrectionValue> <stateChangeWeight> <stateChangeCorrectionValue> <insertOpaquePredicateWeight> <seed>");
                return;
            }
            else {
                inputFile = args[0];
                targetFile = args[1];
                targetNamespace = args[2];
                targetClass = args[3];
                targetMethod = args[4];
                depth = Convert.ToInt32(args[5]);
                dimension = Convert.ToInt32(args[6]);
                numberValidPaths = Convert.ToInt32(args[7]);
                duplicateBasicBlockWeight = Convert.ToInt32(args[8]);
                duplicateBasicBlockCorrectionValue = Convert.ToInt32(args[9]);
                stateChangeWeight = Convert.ToInt32(args[10]);
                stateChangeCorrectionValue = Convert.ToInt32(args[11]);
                insertOpaquePredicateWeight = Convert.ToInt32(args[12]);
                seed = Convert.ToInt32(args[13]);
            }

            String logDir = Path.GetDirectoryName(targetFile);
            Log.Log logger = new Log.Log(logDir, "probfuscation_logfile.txt");

            System.Console.WriteLine("Obfuscating: " + inputFile);
            logger.writeLine("Obfuscating: " + inputFile);
            System.Console.WriteLine("Output file: " + targetFile);
            logger.writeLine("Output file: " + targetFile);
            System.Console.WriteLine("Target namespace: " + targetNamespace);
            logger.writeLine("Target namespace: " + targetNamespace);
            System.Console.WriteLine("Target class: " + targetClass);
            logger.writeLine("Target class: " + targetClass);
            System.Console.WriteLine("Target method: " + targetMethod);
            logger.writeLine("Target method: " + targetMethod);
            System.Console.WriteLine("Depth: " + depth);
            logger.writeLine("Depth: " + depth);
            System.Console.WriteLine("Dimension: " + dimension);
            logger.writeLine("Dimension: " + dimension);
            System.Console.WriteLine("Number of vpaths: " + numberValidPaths);
            logger.writeLine("Number of vpaths: " + numberValidPaths);
            System.Console.WriteLine("Basic Block duplication weight: " + duplicateBasicBlockWeight);
            logger.writeLine("Basic Block duplication weight: " + duplicateBasicBlockWeight);
            System.Console.WriteLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue);
            logger.writeLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue);
            System.Console.WriteLine("State change weight: " + stateChangeWeight);
            logger.writeLine("State change weight: " + stateChangeWeight);
            System.Console.WriteLine("State change correction value: " + stateChangeCorrectionValue);
            logger.writeLine("State change correction value: " + stateChangeCorrectionValue);
            System.Console.WriteLine("Opaque predicate weight: " + insertOpaquePredicateWeight);
            logger.writeLine("Opaque predicate weight: " + insertOpaquePredicateWeight);
            System.Console.WriteLine("Seed: " + seed);
            logger.writeLine("Seed: " + seed);

            // Seed PRNG for interfaces
            PRNGRandomInterfaces = new Random(seed);

            using (var host = new PeReader.DefaultHost()) {
                IModule/*?*/ module = host.LoadUnitFrom(inputFile) as IModule;

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

                module = new MetadataDeepCopier(host).Copy(module);

                if (module as Assembly == null) {
                    logger.writeLine("File does not have CIL assembly");
                    return;
                }

                // create analyzer object object                
                CfgBuilder analyze = new Cfg.CfgBuilder(module, host, 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);
                    }
                }
                else {
                    logger.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway.");
                }

                using (pdbReader) {

                    Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null;
                    if (pdbReader != null) {
                        localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader);
                    }

                    // search the namespace the interface should be added to
                    IUnitNamespace foundNamespace = null;
                    foreach (var tempMember in module.UnitNamespaceRoot.Members) {

                        if ((tempMember as IUnitNamespace) == null) {
                            continue;
                        }

                        IUnitNamespace tempNamespace = (tempMember as IUnitNamespace);

                        if (tempNamespace.ToString() == targetNamespace) {
                            foundNamespace = tempNamespace;
                            break;
                        }
                    }
                    if (foundNamespace == null) {
                        throw new ArgumentException("Not able to find target namespace.");
                    }

                    // add created interface (and implemented methods) to all classes
                    bool classFound = false;
                    foreach (var tempClass in module.GetAllTypes()) {
                        if ((tempClass as NamespaceTypeDefinition) == null
                            || tempClass.IsAbstract) {
                            continue;
                        }

                        NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition);

                        if (foundClass.ContainingUnitNamespace.ToString() == "") {
                            continue;
                        }
                        if (foundClass.ToString() != targetNamespace + "." + targetClass) {
                            continue;
                        }
                        classFound = true;

                        Random prng = new Random();
                        GraphTransformer graphTransformer = new GraphTransformer(module, host, logger, prng, foundNamespace, foundClass, depth, dimension, graphTransformerDebug);

                        graphTransformer.duplicateBasicBlockWeight = duplicateBasicBlockWeight;
                        graphTransformer.duplicateBasicBlockCorrectionValue = duplicateBasicBlockCorrectionValue;
                        graphTransformer.stateChangeWeight = stateChangeWeight;
                        graphTransformer.stateChangeCorrectionValue = stateChangeCorrectionValue;
                        graphTransformer.insertOpaquePredicateWeight = insertOpaquePredicateWeight;
                        graphTransformer.trace = basicBlockTrace;
                        graphTransformer.graphOnlyDumpVPaths = graphOnlyDumpVPaths;
                        graphTransformer.debuggingDumpLocation = logDir;

                        // Add 100 random interfaces to the namespace
                        Helper testHelper = new Helper(module, host, logger);
                        List<NamespaceTypeDefinition> randomInterfaces = new List<NamespaceTypeDefinition>();
                        for (int i = 0; i < numberRandomInterfaces; i++) {
                            String randName = randomString(20);
                            NamespaceTypeDefinition temp = testHelper.createNewInterface(randName, foundNamespace);
                            randomInterfaces.Add(temp);
                        }

                        InterfaceTransformer interfaceTransformer = new InterfaceTransformer(module, host, logger);
                        foreach (var classToAdd in module.GetAllTypes()) {
                            if ((classToAdd as NamespaceTypeDefinition) == null
                                || classToAdd.IsAbstract
                                || classToAdd.IsInterface
                                || classToAdd.IsEnum
                                || classToAdd.IsDelegate
                                || classToAdd.IsGeneric
                                || classToAdd.IsStruct) {
                                continue;
                            }

                            if (((NamespaceTypeDefinition)classToAdd).ContainingUnitNamespace.ToString() == "") {
                                continue;
                            }

                            /*
                            // Use this code if you want to add standard interfaces to the target class
                            interfaceTransformer.addStdInterfacesGivenByFile(@"e:\code\dotnet_standard_interfaces.txt");

                            // add std interfaces to class
                            if (foundClass != (classToAdd as NamespaceTypeDefinition)) {
                                foreach (ITypeDefinition temp in interfaceTransformer.getInterfacesList()) {
                                    interfaceTransformer.addInterface((classToAdd as NamespaceTypeDefinition), temp);
                                }
                            }
                            */

                            // Add random interfaces to the classes
                            List<NamespaceTypeDefinition> alreadyAdded = new List<NamespaceTypeDefinition>();
                            int max = PRNGRandomInterfaces.Next(numberRandomInterfaces);
                            NamespaceTypeDefinition interfaceClass = (classToAdd as NamespaceTypeDefinition);
                            logger.writeLine("Adding " + max + " random interfaces to class \"" + interfaceClass.ToString() + "\"");
                            for (int i = 0; i < max; i++) {
                                NamespaceTypeDefinition randInterface = randomInterfaces.ElementAt(PRNGRandomInterfaces.Next(randomInterfaces.Count));
                                if (alreadyAdded.Contains(randInterface)) {
                                    continue;
                                }
                                alreadyAdded.Add(randInterface);
                                logger.writeLine("Adding interface: \"" + randInterface.ToString() + "\"");

                                // add nodes interface to class
                                if (interfaceClass.Interfaces != null) {
                                    interfaceClass.Interfaces.Add(randInterface);
                                }
                                else {
                                    interfaceClass.Interfaces = new List<ITypeReference>();
                                    interfaceClass.Interfaces.Add(randInterface);
                                }
                            }
                            logger.writeLine("");

                            // Add special interface for the obfuscation scheme to the class
                            // (makes sure that all needed attributes and methods are implemented)
                            graphTransformer.addNodeInterfaceToTargetClass((classToAdd as NamespaceTypeDefinition));
                        }

                        // Prepare obfuscation graph
                        graphTransformer.generateGraph(numberValidPaths);
                        graphTransformer.createGraphMethods();

                        // Search method to obfuscate
                        MethodDefinition methodToObfu = null;
                        foreach (MethodDefinition tempMethod in foundClass.Methods) {
                            if (tempMethod.Name.ToString() == targetMethod) {
                                methodToObfu = tempMethod;
                                break;
                            }
                        }
                        if (methodToObfu == null) {
                            throw new ArgumentException("Not able to find target method.");
                        }

                        // Obfuscate target method
                        MethodCfg cfg = analyze.buildCfgForMethod(methodToObfu);
                        logger.dumpMethodCfg(cfg, "before");
                        graphTransformer.addObfuscationToMethod(cfg);
                        analyze.createMethodFromCfg(cfg);
                        logger.dumpMethodCfg(cfg, "after");

                        break;
                    }
                    if (!classFound) {
                        throw new ArgumentException("Not able to find target class.");
                    }


                    /*
                     * This code can be used if not only one specific method should be obfuscated,
                     * but the whole class.
                    List<ClassCfg> classCfgList = new List<ClassCfg>();
                    foreach (var tempClass in module.GetAllTypes()) {
                        if ((tempClass as NamespaceTypeDefinition) == null
                            || tempClass.IsAbstract) {
                            continue;
                        }

                        // create basic blocks
                        NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition);

                        logger.writeLine("Create CFG for class \"" + foundClass.Name.ToString() + "\"");
                        ClassCfg temp = analyze.buildCfgForClass(foundClass);
                        classCfgList.Add(temp);
                        logger.writeLine("\n---------------------------------\n");
                    }

                    // transform each function
                    NopTransformer transformator = new NopTransformer(module, host, logger);
                    foreach (ClassCfg tempClassCfg in classCfgList) {
                        foreach (MethodCfg tempMethodCfg in tempClassCfg.methodCfgs) {
                            logger.writeLine("Transform method CFG of \"" + tempMethodCfg.method.ToString() + "\"");
                            transformator.addNopsToCfg(tempMethodCfg);
                            logger.writeLine("\n---------------------------------\n");
                        }
                    }

                    foreach (ClassCfg tempClassCfg in classCfgList) {
                        logger.writeLine("Create class from CFG for \"" + tempClassCfg.classObj.Name.ToString() + "\"");
                        analyze.createClassFromCfg(tempClassCfg);
                        logger.writeLine("\n---------------------------------\n");
                    }
                    */

                    using (var peStream = File.Create(targetFile)) {
                        using (var pdbWriter = new PdbWriter(Path.ChangeExtension(targetFile, ".pdb"), pdbReader)) {
                            PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                        }
                    }
                }
            }
        }
        internal static CompilationDifference EmitDifference(
            this Compilation compilation,
            EmitBaseline baseline,
            ImmutableArray<SemanticEdit> edits)
        {
            Stream pdbStream;
            CompilationTestData testData = new CompilationTestData();

            var pdbName = Path.ChangeExtension(compilation.SourceModule.Name, "pdb");
            pdbStream = new MemoryStream();
            using (var pdbWriter = new Cci.PdbWriter(pdbName, new ComStreamWrapper(pdbStream)))
            {
                using (MemoryStream mdStream = new MemoryStream(), ilStream = new MemoryStream())
                {
                    var updatedMethodTokens = new List<uint>();
                    var result = compilation.EmitDifference(
                        baseline,
                        edits,
                        mdStream,
                        ilStream,
                        pdbStream,
                        updatedMethodTokens,
                        testData,
                        default(CancellationToken));

                    pdbStream.Seek(0, SeekOrigin.Begin);

                    return new CompilationDifference(
                        mdStream.ToImmutable(),
                        ilStream.ToImmutable(),
                        pdbStream,
                        result.Baseline,
                        testData,
                        result);
                }
            }
        }
Beispiel #33
0
        private void WritePeToStream(MetadataWriter mdWriter, Stream peStream, PdbWriter nativePdbWriterOpt, out uint entryPointToken)
        {
            // TODO: we can precalculate the exact size of IL stream
            var ilBuffer = new MemoryStream(32 * 1024);
            var ilWriter = new BinaryWriter(ilBuffer);
            var metadataBuffer = new MemoryStream(16 * 1024);
            var metadataWriter = new BinaryWriter(metadataBuffer);
            var mappedFieldDataBuffer = new MemoryStream();
            var mappedFieldDataWriter = new BinaryWriter(mappedFieldDataBuffer);
            var managedResourceBuffer = new MemoryStream(1024);
            var managedResourceWriter = new BinaryWriter(managedResourceBuffer);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(_module.PersistentIdentifier == default(Guid));

            uint moduleVersionIdOffsetInMetadataStream;
            var calculateMethodBodyStreamRva = new Func<MetadataSizes, int>(mdSizes =>
            {
                FillInTextSectionHeader(mdSizes);
                return (int)(_textSection.RelativeVirtualAddress + _sizeOfImportAddressTable + 72);
            });

            MetadataSizes metadataSizes;
            mdWriter.SerializeMetadataAndIL(
                nativePdbWriterOpt,
                metadataWriter,
                ilWriter,
                mappedFieldDataWriter,
                managedResourceWriter,
                calculateMethodBodyStreamRva,
                CalculateMappedFieldDataStreamRva,
                out moduleVersionIdOffsetInMetadataStream,
                out entryPointToken,
                out metadataSizes);

            FillInSectionHeaders();

            // fill in header fields.
            FillInNtHeader(metadataSizes, CalculateMappedFieldDataStreamRva(metadataSizes));
            var corHeader = CreateCorHeader(metadataSizes, entryPointToken);

            // write to pe stream.
            long positionOfHeaderTimestamp;
            WriteHeaders(peStream, out positionOfHeaderTimestamp);

            long startOfMetadataStream;
            long positionOfDebugTableTimestamp;

            WriteTextSection(
                peStream,
                corHeader,
                metadataBuffer,
                ilBuffer,
                mappedFieldDataBuffer,
                managedResourceBuffer,
                out startOfMetadataStream,
                out positionOfDebugTableTimestamp);

            WriteRdataSection(peStream);
            WriteSdataSection(peStream);
            WriteCoverSection(peStream);
            WriteTlsSection(peStream);
            WriteResourceSection(peStream);
            WriteRelocSection(peStream);

            if (_deterministic)
            {
                var positionOfModuleVersionId = startOfMetadataStream + moduleVersionIdOffsetInMetadataStream;
                WriteDeterministicGuidAndTimestamps(peStream, positionOfModuleVersionId, positionOfHeaderTimestamp, positionOfDebugTableTimestamp);
            }
        }
Beispiel #34
0
        static int Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: ILWeave [Assembly]");

                return 1;
            }

            string tmpDir, newName, newPdb;

            using (var host = new PeReader.DefaultHost())
            {
                var module = host.LoadUnitFrom(args[0]) as IModule;

                if (module == null || module is Dummy)
                {
                    Console.WriteLine("{0} is not a PE file containing a CLR assembly, or an error occurred when loading it.", args[0]);

                    return 1;
                }

                module = new MetadataDeepCopier(host).Copy(module);
                PdbReader pdbReader = null;
                var 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);

                    try
                    {
                        module = PropertyChangedWeaver.RewriteModule(
                            host,
                            localScopeProvider,
                            pdbReader,
                            module);
                    }
                    catch (InvalidOperationException e)
                    {
                        Console.WriteLine("Error: {0}", e);
                        Environment.Exit(5);
                    }

                    tmpDir = Directory.CreateDirectory(Path.GetRandomFileName()).FullName;
                    newName = Path.Combine(tmpDir, Path.GetFileName(args[0]));

                    using (var peStream = File.Create(newName))
                    {
                        newPdb = Path.ChangeExtension(newName, ".pdb");

                        using (var pdbWriter = new PdbWriter(newPdb, pdbReader))
                        {
                            PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter);
                        }
                    }
                }
            }

            var dst = Path.GetDirectoryName(args[0]);

            foreach (var s in Directory.GetFiles(tmpDir))
            {
                File.Copy(s, Path.Combine(dst, Path.GetFileName(s)), true);
            }

            Directory.Delete(tmpDir, true);

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