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); }
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); } } }
private PeWriter(IModule module, PdbWriter nativePdbWriter, bool deterministic) { _module = module; _emitRuntimeStartupStub = module.RequiresStartupStub; _nativePdbWriter = nativePdbWriter; _deterministic = deterministic; _sizeOfImportAddressTable = _emitRuntimeStartupStub ? (!_module.Requires64bits ? 8u : 16u) : 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); } } } } } }
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); } }
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); } } } } } }
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); }
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)); } } }
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; }
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); } } }
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 }
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; }
/// <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); } } } } }
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 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); } } }
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; }
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; }
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); }
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); } } } } }
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; }
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); }
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); } } }
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); } }
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)); }