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); } } }
static void Main(string[] args) { using (var host = new HelloHost()) { var nameTable = host.NameTable; var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var aname = nameTable.GetNameFor("hello"); var mname = nameTable.GetNameFor("hello.exe"); var arefs = IteratorHelper.GetSingletonEnumerable <IAssemblyReference>(coreAssembly); var source = new HelloSourceDocument(aname); var sources = IteratorHelper.GetSingletonEnumerable <HelloSourceDocument>(source); var helloAssembly = new HelloAssembly(aname, host, mname, arefs, sources); var sourceLocationProvider = helloAssembly.Compilation.SourceLocationProvider; var localScopeProvider = helloAssembly.Compilation.LocalScopeProvider; using (var sourceFile = File.CreateText("hello.cs")) { sourceFile.WriteLine("hello"); } using (var peStream = File.Create("hello.exe")) { using (var pdbWriter = new PdbWriter("hello.pdb", sourceLocationProvider)) { PeWriter.WritePeToStream(helloAssembly, host, peStream, helloAssembly.Compilation.SourceLocationProvider, helloAssembly.Compilation.LocalScopeProvider, pdbWriter); } } } }
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)); }
private static void TranslateToExe(SpecSharpOptions commandLineOptions) //^ requires commandLineOptions.FileNames.Count > 0; { HostEnvironment hostEnvironment = new HostEnvironment(); hostEnvironment.Errors += hostEnvironment.HandleErrors; hostEnvironment.displayFileName = true; List <IAssemblyReference> assemblyReferences = GetAssemblyReferences(commandLineOptions, hostEnvironment); List <IModuleReference> moduleReferences = new List <IModuleReference>(); List <SpecSharpSourceDocument> programSources = new List <SpecSharpSourceDocument>(1); IName name = hostEnvironment.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(commandLineOptions.FileNames[0])); SpecSharpAssembly assem = new SpecSharpAssembly(name, Path.GetFullPath(name.Value), hostEnvironment, commandLineOptions, assemblyReferences, moduleReferences, programSources); SpecSharpCompilationHelper helper = new SpecSharpCompilationHelper(assem.Compilation); foreach (string fileName in commandLineOptions.FileNames) { name = hostEnvironment.NameTable.GetNameFor(fileName); StreamReader instream = File.OpenText(fileName); programSources.Add(new SpecSharpSourceDocument(helper, name, Path.GetFullPath(fileName), instream)); } if (assem.Compilation.HasErrors) { return; } var sourceLocationProvider = assem.Compilation.SourceLocationProvider; var localScopeProvider = assem.Compilation.LocalScopeProvider; using (var pdbWriter = new PdbWriter(Path.ChangeExtension(assem.Location, "pdb"), sourceLocationProvider)) { PeWriter.WritePeToStream(assem, hostEnvironment, File.Create(Path.ChangeExtension(assem.Location, "exe")), sourceLocationProvider, localScopeProvider, pdbWriter); } }
private static void TranslateToExe(SpecSharpOptions commandLineOptions) //^ requires commandLineOptions.FileNames.Count > 0; { HostEnvironment hostEnvironment = new HostEnvironment(); hostEnvironment.Errors += hostEnvironment.HandleErrors; hostEnvironment.displayFileName = true; List<IAssemblyReference> assemblyReferences = GetAssemblyReferences(commandLineOptions, hostEnvironment); List<IModuleReference> moduleReferences = new List<IModuleReference>(); List<SpecSharpSourceDocument> programSources = new List<SpecSharpSourceDocument>(1); IName name = hostEnvironment.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(commandLineOptions.FileNames[0])); SpecSharpAssembly assem = new SpecSharpAssembly(name, Path.GetFullPath(name.Value), hostEnvironment, commandLineOptions, assemblyReferences, moduleReferences, programSources); SpecSharpCompilationHelper helper = new SpecSharpCompilationHelper(assem.Compilation); foreach (string fileName in commandLineOptions.FileNames) { name = hostEnvironment.NameTable.GetNameFor(fileName); StreamReader instream = File.OpenText(fileName); programSources.Add(new SpecSharpSourceDocument(helper, name, Path.GetFullPath(fileName), instream)); } if (assem.Compilation.HasErrors) return; var sourceLocationProvider = assem.Compilation.SourceLocationProvider; var localScopeProvider = assem.Compilation.LocalScopeProvider; using (var pdbWriter = new PdbWriter(Path.ChangeExtension(assem.Location, "pdb"), sourceLocationProvider)) { PeWriter.WritePeToStream(assem, hostEnvironment, File.Create(Path.ChangeExtension(assem.Location, "exe")), sourceLocationProvider, localScopeProvider, pdbWriter); } }
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); } } } } }
private static void OutputFacadeToFile(string facadePath, HostEnvironment seedHost, Assembly facade, IAssembly contract, string pdbLocation = null) { bool needsConversion = false; string pdbOutputPath = Path.Combine(facadePath, contract.Name + ".pdb"); string finalPdbOutputPath = pdbOutputPath; // Use the filename (including extension .dll/.winmd) so people can have some control over the output facade file name. string facadeFileName = Path.GetFileName(contract.Location); string facadeOutputPath = Path.Combine(facadePath, facadeFileName); using (Stream peOutStream = File.Create(facadeOutputPath)) { if (pdbLocation != null) { if (File.Exists(pdbLocation)) { // Convert from portable to windows PDBs if necessary. If we convert // set the pdbOutput path to a *.windows.pdb file so we can convert it back // to 'finalPdbOutputPath'. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { needsConversion = ConvertFromPortableIfNecessary(facade.Location, ref pdbLocation); } if (needsConversion) { // We want to keep the same file name for the PDB because it is used as a key when looking it up on a symbol server string pdbOutputPathPdbDir = Path.Combine(Path.GetDirectoryName(pdbOutputPath), "WindowsPdb"); Directory.CreateDirectory(pdbOutputPathPdbDir); pdbOutputPath = Path.Combine(pdbOutputPathPdbDir, Path.GetFileName(pdbOutputPath)); } // do the main GenFacades logic (which today only works with windows PDBs). using (Stream pdbReadStream = File.OpenRead(pdbLocation)) using (PdbReader pdbReader = new PdbReader(pdbReadStream, seedHost)) using (PdbWriter pdbWriter = new PdbWriter(pdbOutputPath, pdbReader)) { PeWriter.WritePeToStream(facade, seedHost, peOutStream, pdbReader, pdbReader, pdbWriter); } } else { throw new FacadeGenerationException("Couldn't find the pdb at the given location: " + pdbLocation); } } else { PeWriter.WritePeToStream(facade, seedHost, peOutStream); } } // If we started with Portable PDBs we need to convert the output to portable again. // We have to do this after facadeOutputPath is closed for writing. if (needsConversion) { Trace.TraceInformation("Converting PDB generated by GenFacades " + pdbOutputPath + " to portable format " + finalPdbOutputPath); ConvertFromWindowsPdb(facadeOutputPath, pdbOutputPath, finalPdbOutputPath); } }
static int Main(string[] args) { if (args == null || args.Length < 1) { Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]"); return(1); } using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return(1); } module = new MetadataDeepCopier(host).Copy(module); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); ILMutator mutator = new ILMutator(host, pdbReader); module = mutator.Rewrite(module); string newName; if (args.Length == 2) { newName = args[1]; } else { var loc = module.Location; var path = Path.GetDirectoryName(loc) ?? ""; var fileName = Path.GetFileNameWithoutExtension(loc); var ext = Path.GetExtension(loc); newName = Path.Combine(path, fileName + "1" + ext); } using (var peStream = File.Create(newName)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } return(0); // success } }
void AssertWriteToPeFile(PeVerifyResult expectedResult, IAssembly assembly, PdbReader pdbReader) { using (var rewrittenFile = File.Create(assembly.Location)) { using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), pdbReader)) { PeWriter.WritePeToStream(assembly, host, rewrittenFile, pdbReader, pdbReader, pdbWriter); } } Assert.True(File.Exists(assembly.Location)); PeVerify.Assert(expectedResult, PeVerify.VerifyAssembly(assembly.Location, true)); }
private void Add(string name, SymbolInfo symbol) { int hashVal = (int)PdbWriter.Hash(name, HASH_MODULO); if (!m_occupiedHash[hashVal]) { m_occupiedHash[hashVal] = true; m_table[hashVal] = new List <KeyValuePair <string, SymbolInfo> >(); } m_table[hashVal].Add(new KeyValuePair <string, SymbolInfo>(name, symbol)); m_numGlobals++; }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: EdgeProfiler [path]fileName.ext"); return; } using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); return; } var coreIdentity = host.CoreAssemblySymbolicIdentity; //force host to let args[0] determine the target platform var profiler = (IAssembly)host.LoadUnitFrom(typeof(Program).Assembly.Location); var logger = (INamespaceTypeDefinition)UnitHelper.FindType(host.NameTable, profiler, "Logger"); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { var instrumentedModule = Instrumenter.GetInstrumented(host, module, pdbReader, logger); var newRoot = Path.GetFileNameWithoutExtension(module.Location) + ".instrumented"; var newName = newRoot + Path.GetExtension(module.Location); using (var peStream = File.Create(newName)) { if (pdbReader == null) { PeWriter.WritePeToStream(instrumentedModule, host, peStream); } else { var localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); using (var pdbWriter = new PdbWriter(newRoot + ".pdb", pdbReader)) { PeWriter.WritePeToStream(instrumentedModule, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } } }
public void WriteToStream(IModuleInfo moduleInfo, FileStream stream, string filePath) { var module = (ModuleInfo)moduleInfo; if (module.PdbReader == null) { PeWriter.WritePeToStream(module.Module, _host, stream); } else { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(filePath, "pdb"), module.PdbReader)) { PeWriter.WritePeToStream(module.Module, _host, stream, module.PdbReader, module.PdbReader, pdbWriter); } } }
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); }
/// <summary> /// Write the PDB file. The caller should send the PDB events before and after calling this /// method. /// </summary> protected void WritePdbFile() { if (!CanWritePdb()) { return; } if (debugDirectory == null) { throw new InvalidOperationException("debugDirectory is null but WritePdb is true"); } var pdbState = Module.PdbState; if (pdbState == null) { Error("TheOptions.WritePdb is true but module has no PdbState"); debugDirectory.DontWriteAnything = true; return; } var symWriter = GetSymbolWriter2(); if (symWriter == null) { Error("Could not create a PDB symbol writer. A Windows OS might be required."); debugDirectory.DontWriteAnything = true; return; } var pdbWriter = new PdbWriter(symWriter, pdbState, metaData); try { pdbWriter.Logger = TheOptions.Logger; pdbWriter.Write(); debugDirectory.Data = pdbWriter.GetDebugInfo(out debugDirectory.debugDirData); debugDirectory.TimeDateStamp = GetTimeDateStamp(); pdbWriter.Dispose(); } catch { pdbWriter.Dispose(); DeleteFileNoThrow(createdPdbFileName); throw; } }
public void Save(string fileName) { var pdbName = Path.ChangeExtension(fileName, "pdb"); using (var peStream = File.Create(fileName)) { if (this.PdbReader == null) { PeWriter.WritePeToStream(this.Module, this.Host, peStream); } else { using (var pdbWriter = new PdbWriter(pdbName, this.PdbReader)) PeWriter.WritePeToStream(this.Module, this.Host, peStream, this.PdbReader, this.PdbReader, pdbWriter); } } }
private static void RewriteBinary( Assembly copy, AssemblyReport assemblyReport, MetadataReaderHost host, string outputPath, MethodRemoval methodRemoval, StubMethodBodyEmitter stubEmitter) { /* This is an attempt to decouple the MethodRemoval commandline options * from the tree shaker, but it doesn't really seem to be working. * Might be better to just pass the method removal directly to * the rewriter. */ bool removeMethods = (methodRemoval == MethodRemoval.Remove); bool fullDebugStubs = (methodRemoval == MethodRemoval.Debug); bool dryRun = (methodRemoval == MethodRemoval.None); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(copy.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + copy.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); var pdbPath = Path.ChangeExtension(outputPath, ".pdb"); var outputFileName = Path.GetFileNameWithoutExtension(outputPath); using (var peStream = File.Create(outputPath)) { using (var pdbWriter = new PdbWriter(pdbPath, pdbReader)) { var rewriter = new TreeShakingRewriter(host, assemblyReport, dryRun, removeMethods, fullDebugStubs, stubEmitter); IAssembly rewrittenCopy = rewriter.Rewrite(copy); PeWriter.WritePeToStream(rewrittenCopy, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } }
private static void Compile(string fileName) { HostEnvironment hostEnvironment = new HostEnvironment(); IName name = hostEnvironment.NameTable.GetNameFor(fileName); IDictionary<string, string> options = new Dictionary<string, string>(); List<IAssemblyReference> assemblyReferences = new List<IAssemblyReference>(); List<IModuleReference> moduleReferences = new List<IModuleReference>(); assemblyReferences.Add(hostEnvironment.LoadAssembly(hostEnvironment.CoreAssemblySymbolicIdentity)); assemblyReferences.Add((IAssembly)hostEnvironment.LoadUnitFrom(typeof(Microsoft.SmallBasic.Library.ConsoleWindow).Assembly.Location)); StreamReader instream = File.OpenText(fileName); List<SmallBasicDocument> programSources = new List<SmallBasicDocument>(1); SmallBasicAssembly assem = new SmallBasicAssembly(name, Path.GetFullPath(fileName), hostEnvironment, options, assemblyReferences, moduleReferences, programSources); SmallBasicCompilationHelper helper = new SmallBasicCompilationHelper(assem.Compilation); programSources.Add(new SmallBasicDocument(helper, name, Path.GetFullPath(fileName), instream)); var exeFile = File.Create(Path.ChangeExtension(fileName, "exe")); var sourceLocationProvider = assem.Compilation.SourceLocationProvider; //var localScopeProvider = assem.Compilation.LocalScopeProvider; using (var pdbWriter = new PdbWriter(Path.ChangeExtension(fileName, "pdb"), sourceLocationProvider)) { PeWriter.WritePeToStream(assem, hostEnvironment, exeFile, sourceLocationProvider, null, pdbWriter); } }
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); } } } } } }
internal void Write(PdbWriter writer) { writer.Write(this); }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext [decompile] [noStack]"); return; } bool decompile = args.Length >= 2; bool noStack = args.Length >= 3; using (var host = new HostEnvironment()) { //Read the Metadata Model from the PE file 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; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = module.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile)) { pdbFile = Path.ChangeExtension(module.Location, "pdb"); } if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { ISourceLocationProvider sourceLocationProvider = pdbReader; ILocalScopeProvider localScopeProvider = pdbReader; if (decompile) { //Construct a Code Model from the Metadata model via decompilation var options = DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators | DecompilerOptions.Loops; if (noStack) { options |= DecompilerOptions.Unstack; } module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, options); if (pdbReader != null) { localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); } } MetadataRewriter rewriter; MetadataDeepCopier copier; if (decompile) { copier = new CodeDeepCopier(host, pdbReader, pdbReader); rewriter = new CodeRewriter(host); } else { copier = new MetadataDeepCopier(host); rewriter = new MetadataRewriter(host); } var mutableModule = copier.Copy(module); module = rewriter.Rewrite(mutableModule); //var validator = new MetadataValidator(host); //List<Microsoft.Cci.ErrorEventArgs> errorEvents = new List<Microsoft.Cci.ErrorEventArgs>(); //host.Errors += (object sender, Microsoft.Cci.ErrorEventArgs e) => errorEvents.Add(e); //var assem = module as IAssembly; //validator.Validate(assem); //if (errorEvents.Count != 0) //{ // foreach (var e in errorEvents) // { // foreach (var err in e.Errors) // { // Console.WriteLine(err.Message); // } // } //} #if DEBUG var newRoot = Path.GetFileNameWithoutExtension(module.Location) + "1"; var newName = newRoot + Path.GetExtension(module.Location); using (Stream peStream = File.Create(newName)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(newRoot + ".pdb", pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #else using (Stream peStream = File.Create(module.Location)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(pdbFile, pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #endif } } }
/// <summary> /// Outputs specified headers, sections, methods or runtime functions for one ReadyToRun image /// </summary> /// <param name="r2r">The structure containing the info of the ReadyToRun image</param> public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); bool standardDump = !(_options.EntryPoints || _options.CreatePDB); if (_options.Header && standardDump) { _dumper.WriteDivider("R2R Header"); _dumper.DumpHeader(true); } bool haveQuery = false; if (_options.Section != null) { haveQuery = true; QuerySection(r2r, _options.Section); } if (_options.RuntimeFunction != null) { haveQuery = true; QueryRuntimeFunction(r2r, _options.RuntimeFunction); } if (_options.Query != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Query", _options.Query, true); } if (_options.Keyword != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Keyword", _options.Keyword, false); } if (!haveQuery) { // Dump all sections and methods if no queries specified if (_options.EntryPoints) { _dumper.DumpEntryPoints(); } if (_options.CreatePDB) { string pdbPath = _options.PdbPath; if (String.IsNullOrEmpty(pdbPath)) { pdbPath = Path.GetDirectoryName(r2r.Filename); } var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None); pdbWriter.WritePDBData(r2r.Filename, ProducePdbWriterMethods(r2r)); } if (!_options.Header && standardDump) { _dumper.DumpAllMethods(); } } _dumper.End(); }
internal void Write(PdbWriter writer) { foreach (var function in functions) function.Write(writer); }
public CodeModelRoundTripTests() { pdbReader = null; pdbWriter = null; host = new HostEnvironment(); }
internal void Convert(PEReader peReader, MetadataReader pdbReader, PdbWriter <TDocumentWriter> pdbWriter, PdbConversionOptions options) { if (!SymReaderHelpers.TryReadPdbId(peReader, out var pePdbId, out int peAge)) { throw new InvalidDataException(ConverterResources.SpecifiedPEFileHasNoAssociatedPdb); } if (!new BlobContentId(pdbReader.DebugMetadataHeader.Id).Equals(pePdbId)) { throw new InvalidDataException(ConverterResources.PdbNotMatchingDebugDirectory); } string vbDefaultNamespace = MetadataUtilities.GetVisualBasicDefaultNamespace(pdbReader); bool vbSemantics = vbDefaultNamespace != null; string vbDefaultNamespaceImportString = string.IsNullOrEmpty(vbDefaultNamespace) ? null : "*" + vbDefaultNamespace; var metadataReader = peReader.GetMetadataReader(); var metadataModel = new MetadataModel(metadataReader, vbSemantics); var documentWriters = new ArrayBuilder <TDocumentWriter>(pdbReader.Documents.Count); var documentNames = new ArrayBuilder <string>(pdbReader.Documents.Count); var symSequencePointBuilder = new SequencePointsBuilder(capacity: 64); var declaredExternAliases = new HashSet <string>(); var importStringsBuilder = new List <string>(); var importGroups = new List <int>(); var cdiBuilder = new BlobBuilder(); var dynamicLocals = new List <(string LocalName, byte[] Flags, int Count, int SlotIndex)>(); var tupleLocals = new List <(string LocalName, int SlotIndex, int ScopeStart, int ScopeEnd, ImmutableArray <string> Names)>(); var openScopeEndOffsets = new Stack <int>(); // state for calculating import string forwarding: var lastImportScopeHandle = default(ImportScopeHandle); var vbLastImportScopeNamespace = default(string); var lastImportScopeMethodDefHandle = default(MethodDefinitionHandle); var importStringsMap = new Dictionary <ImmutableArray <string>, MethodDefinitionHandle>(SequenceComparer <string> .Instance); var aliasedAssemblyRefs = GetAliasedAssemblyRefs(pdbReader); foreach (var documentHandle in pdbReader.Documents) { var document = pdbReader.GetDocument(documentHandle); var languageGuid = pdbReader.GetGuid(document.Language); var name = pdbReader.GetString(document.Name); documentNames.Add(name); documentWriters.Add(pdbWriter.DefineDocument( name: name, language: languageGuid, type: s_documentTypeText, vendor: GetLanguageVendorGuid(languageGuid), algorithmId: pdbReader.GetGuid(document.HashAlgorithm), checksum: pdbReader.GetBlobBytes(document.Hash))); } var localScopeEnumerator = pdbReader.LocalScopes.GetEnumerator(); LocalScope?currentLocalScope = NextLocalScope(); LocalScope?NextLocalScope() => localScopeEnumerator.MoveNext() ? pdbReader.GetLocalScope(localScopeEnumerator.Current) : default(LocalScope?); // Handle of the method that is gonna contain list of AssemblyRef aliases. // Other methods will forward to it. var methodDefHandleWithAssemblyRefAliases = default(MethodDefinitionHandle); foreach (var methodDebugInfoHandle in pdbReader.MethodDebugInformation) { var methodDebugInfo = pdbReader.GetMethodDebugInformation(methodDebugInfoHandle); var methodDefHandle = methodDebugInfoHandle.ToDefinitionHandle(); int methodToken = MetadataTokens.GetToken(methodDefHandle); var methodDef = metadataReader.GetMethodDefinition(methodDefHandle); #if DEBUG var declaringTypeDef = metadataReader.GetTypeDefinition(methodDef.GetDeclaringType()); var typeName = metadataReader.GetString(declaringTypeDef.Name); var methodName = metadataReader.GetString(methodDef.Name); #endif bool methodOpened = false; var methodBodyOpt = (methodDef.RelativeVirtualAddress != 0 && (methodDef.ImplAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Managed) ? peReader.GetMethodBody(methodDef.RelativeVirtualAddress) : null; var vbCurrentMethodNamespace = vbSemantics ? GetMethodNamespace(metadataReader, methodDef) : null; var moveNextHandle = metadataModel.FindStateMachineMoveNextMethod(methodDefHandle, vbSemantics); bool isKickOffMethod = !moveNextHandle.IsNil; var forwardImportScopesToMethodDef = default(MethodDefinitionHandle); Debug.Assert(dynamicLocals.Count == 0); Debug.Assert(tupleLocals.Count == 0); Debug.Assert(openScopeEndOffsets.Count == 0); void LazyOpenMethod() { if (!methodOpened) { #if DEBUG Debug.WriteLine($"Open Method '{typeName}::{methodName}' {methodToken:X8}"); #endif pdbWriter.OpenMethod(methodToken); methodOpened = true; } } void CloseOpenScopes(int currentScopeStartOffset) { // close all open scopes that end before this scope starts: while (openScopeEndOffsets.Count > 0 && currentScopeStartOffset >= openScopeEndOffsets.Peek()) { int scopeEnd = openScopeEndOffsets.Pop(); Debug.WriteLine($"Close Scope [.., {scopeEnd})"); // Note that the root scope end is not end-inclusive in VB: pdbWriter.CloseScope(AdjustEndScopeOffset(scopeEnd, isEndInclusive: vbSemantics && openScopeEndOffsets.Count > 0)); } } bool isFirstMethodScope = true; while (currentLocalScope.HasValue && currentLocalScope.Value.Method == methodDefHandle) { // kickoff methods don't have any scopes emitted to Windows PDBs if (methodBodyOpt == null) { ReportDiagnostic(PdbDiagnosticId.MethodAssociatedWithLocalScopeHasNoBody, MetadataTokens.GetToken(localScopeEnumerator.Current)); } else if (!isKickOffMethod) { LazyOpenMethod(); var localScope = currentLocalScope.Value; CloseOpenScopes(localScope.StartOffset); Debug.WriteLine($"Open Scope [{localScope.StartOffset}, {localScope.EndOffset})"); pdbWriter.OpenScope(localScope.StartOffset); openScopeEndOffsets.Push(localScope.EndOffset); if (isFirstMethodScope) { if (lastImportScopeHandle == localScope.ImportScope && vbLastImportScopeNamespace == vbCurrentMethodNamespace) { // forward to a method that has the same imports: forwardImportScopesToMethodDef = lastImportScopeMethodDefHandle; } else { Debug.Assert(importStringsBuilder.Count == 0); Debug.Assert(declaredExternAliases.Count == 0); Debug.Assert(importGroups.Count == 0); AddImportStrings(importStringsBuilder, importGroups, declaredExternAliases, pdbReader, metadataModel, localScope.ImportScope, aliasedAssemblyRefs, vbDefaultNamespaceImportString, vbCurrentMethodNamespace, vbSemantics); var importStrings = importStringsBuilder.ToImmutableArray(); importStringsBuilder.Clear(); if (importStringsMap.TryGetValue(importStrings, out forwardImportScopesToMethodDef)) { // forward to a method that has the same imports: lastImportScopeMethodDefHandle = forwardImportScopesToMethodDef; } else { // attach import strings to the current method: WriteImports(pdbWriter, importStrings); lastImportScopeMethodDefHandle = methodDefHandle; importStringsMap[importStrings] = methodDefHandle; } lastImportScopeHandle = localScope.ImportScope; vbLastImportScopeNamespace = vbCurrentMethodNamespace; } if (vbSemantics && !forwardImportScopesToMethodDef.IsNil) { pdbWriter.UsingNamespace("@" + MetadataTokens.GetToken(forwardImportScopesToMethodDef)); } // This is the method that's gonna have AssemblyRef aliases attached: if (methodDefHandleWithAssemblyRefAliases.IsNil) { foreach (var(assemblyRefHandle, alias) in aliasedAssemblyRefs) { var assemblyRef = metadataReader.GetAssemblyReference(assemblyRefHandle); pdbWriter.UsingNamespace("Z" + alias + " " + AssemblyDisplayNameBuilder.GetAssemblyDisplayName(metadataReader, assemblyRef)); } } } foreach (var localVariableHandle in localScope.GetLocalVariables()) { var variable = pdbReader.GetLocalVariable(localVariableHandle); string name = pdbReader.GetString(variable.Name); if (name.Length > MaxEntityNameLength) { ReportDiagnostic(PdbDiagnosticId.LocalConstantNameTooLong, MetadataTokens.GetToken(localVariableHandle)); continue; } if (methodBodyOpt.LocalSignature.IsNil) { ReportDiagnostic(PdbDiagnosticId.MethodContainingLocalVariablesHasNoLocalSignature, methodToken); continue; } // TODO: translate hoisted variable scopes to dummy VB hoisted state machine locals (https://github.com/dotnet/roslyn/issues/8473) pdbWriter.DefineLocalVariable(variable.Index, name, variable.Attributes, MetadataTokens.GetToken(methodBodyOpt.LocalSignature)); var dynamicFlags = MetadataUtilities.ReadDynamicCustomDebugInformation(pdbReader, localVariableHandle); if (TryGetDynamicLocal(name, variable.Index, dynamicFlags, out var dynamicLocal)) { dynamicLocals.Add(dynamicLocal); } var tupleElementNames = MetadataUtilities.ReadTupleCustomDebugInformation(pdbReader, localVariableHandle); if (!tupleElementNames.IsDefaultOrEmpty) { tupleLocals.Add((name, SlotIndex: variable.Index, ScopeStart: 0, ScopeEnd: 0, Names: tupleElementNames)); } } foreach (var localConstantHandle in localScope.GetLocalConstants()) { var constant = pdbReader.GetLocalConstant(localConstantHandle); string name = pdbReader.GetString(constant.Name); if (name.Length > MaxEntityNameLength) { ReportDiagnostic(PdbDiagnosticId.LocalConstantNameTooLong, MetadataTokens.GetToken(localConstantHandle)); continue; } var(value, signature) = PortableConstantSignature.GetConstantValueAndSignature(pdbReader, localConstantHandle, metadataReader.GetQualifiedTypeName); if (!metadataModel.TryGetStandaloneSignatureHandle(signature, out var constantSignatureHandle)) { // Signature will be unspecified. At least we store the name and the value. constantSignatureHandle = default(StandaloneSignatureHandle); } pdbWriter.DefineLocalConstant(name, value, MetadataTokens.GetToken(constantSignatureHandle)); var dynamicFlags = MetadataUtilities.ReadDynamicCustomDebugInformation(pdbReader, localConstantHandle); if (TryGetDynamicLocal(name, 0, dynamicFlags, out var dynamicLocal)) { dynamicLocals.Add(dynamicLocal); } var tupleElementNames = MetadataUtilities.ReadTupleCustomDebugInformation(pdbReader, localConstantHandle); if (!tupleElementNames.IsDefaultOrEmpty) { // Note that the end offset of tuple locals is always end-exclusive, regardless of whether the PDB uses VB semantics or not. tupleLocals.Add((name, SlotIndex: -1, ScopeStart: localScope.StartOffset, ScopeEnd: localScope.EndOffset, Names: tupleElementNames)); } } } currentLocalScope = NextLocalScope(); isFirstMethodScope = false; } bool hasAnyScopes = !isFirstMethodScope; CloseOpenScopes(int.MaxValue); if (openScopeEndOffsets.Count > 0) { ReportDiagnostic(PdbDiagnosticId.LocalScopeRangesNestingIsInvalid, methodToken); openScopeEndOffsets.Clear(); } if (!methodDebugInfo.SequencePointsBlob.IsNil) { LazyOpenMethod(); WriteSequencePoints(pdbWriter, documentWriters, symSequencePointBuilder, methodDebugInfo.GetSequencePoints(), methodToken); } // async method data: var asyncData = MetadataUtilities.ReadAsyncMethodData(pdbReader, methodDebugInfoHandle); if (!asyncData.IsNone) { LazyOpenMethod(); pdbWriter.SetAsyncInfo( moveNextMethodToken: methodToken, kickoffMethodToken: MetadataTokens.GetToken(asyncData.KickoffMethod), catchHandlerOffset: asyncData.CatchHandlerOffset, yieldOffsets: asyncData.YieldOffsets.ToArray(), resumeOffsets: asyncData.ResumeOffsets.ToArray()); } // custom debug information: var cdiEncoder = new CustomDebugInfoEncoder(cdiBuilder); if (isKickOffMethod) { cdiEncoder.AddStateMachineTypeName(GetIteratorTypeName(metadataReader, moveNextHandle)); } else { if (!vbSemantics && hasAnyScopes) { if (forwardImportScopesToMethodDef.IsNil) { // record the number of import strings in each scope: cdiEncoder.AddUsingGroups(importGroups); if (!methodDefHandleWithAssemblyRefAliases.IsNil) { // forward assembly ref aliases to the first method: cdiEncoder.AddForwardModuleInfo(methodDefHandleWithAssemblyRefAliases); } } else { // forward all imports to another method: cdiEncoder.AddForwardMethodInfo(forwardImportScopesToMethodDef); } } var hoistedLocalScopes = GetStateMachineHoistedLocalScopes(pdbReader, methodDefHandle); if (!hoistedLocalScopes.IsDefault) { cdiEncoder.AddStateMachineHoistedLocalScopes(hoistedLocalScopes); } if (dynamicLocals.Count > 0) { cdiEncoder.AddDynamicLocals(dynamicLocals); dynamicLocals.Clear(); } if (tupleLocals.Count > 0) { cdiEncoder.AddTupleElementNames(tupleLocals); tupleLocals.Clear(); } } importGroups.Clear(); // the following blobs map 1:1 CopyCustomDebugInfoRecord(ref cdiEncoder, pdbReader, methodDefHandle, PortableCustomDebugInfoKinds.EncLocalSlotMap, CustomDebugInfoKind.EditAndContinueLocalSlotMap); CopyCustomDebugInfoRecord(ref cdiEncoder, pdbReader, methodDefHandle, PortableCustomDebugInfoKinds.EncLambdaAndClosureMap, CustomDebugInfoKind.EditAndContinueLambdaMap); if (cdiEncoder.RecordCount > 0) { LazyOpenMethod(); pdbWriter.DefineCustomMetadata(cdiEncoder.ToArray()); } cdiBuilder.Clear(); if (methodOpened && aliasedAssemblyRefs.Length > 0 && !isKickOffMethod && methodDefHandleWithAssemblyRefAliases.IsNil) { methodDefHandleWithAssemblyRefAliases = methodDefHandle; } if (methodOpened) { Debug.WriteLine($"Close Method {methodToken:X8}"); pdbWriter.CloseMethod(); } } if (!pdbReader.DebugMetadataHeader.EntryPoint.IsNil) { pdbWriter.SetEntryPoint(MetadataTokens.GetToken(pdbReader.DebugMetadataHeader.EntryPoint)); } var sourceLinkHandle = pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition, PortableCustomDebugInfoKinds.SourceLink); if (!sourceLinkHandle.IsNil) { if ((options & PdbConversionOptions.SuppressSourceLinkConversion) == 0) { ConvertSourceServerData(pdbReader.GetStringUTF8(sourceLinkHandle), pdbWriter, documentNames); } else { pdbWriter.SetSourceLinkData(pdbReader.GetBlobBytes(sourceLinkHandle)); } } SymReaderHelpers.GetWindowsPdbSignature(pdbReader.DebugMetadataHeader.Id, out var guid, out var stamp, out var age); pdbWriter.UpdateSignature(guid, stamp, age); }
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); }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext [noStack]"); return; } bool noStack = args.Length == 2; using (var host = new PeReader.DefaultHost()) { //Read the Metadata Model from the PE file var 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; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } using (pdbReader) { //Construct a Code Model from the Metadata model via decompilation var options = DecompilerOptions.None; if (noStack) { options |= DecompilerOptions.Unstack; } var decompiledModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, options); ISourceLocationProvider sourceLocationProvider = pdbReader; //The decompiler preserves the Locations from the IOperation values, so the PdbReader still works. //Recompiling the CodeModel to IL might change the IL offsets, so a new provider is needed. ILocalScopeProvider localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); //Get a mutable copy of the Code Model. The ISourceLocationProvider is needed to provide copied source method bodies with the //ability to find out where to mark sequence points when compiling themselves back into IL. //(ISourceMethodBody does not know about the Source Model, so this information must be provided explicitly.) var copier = new CodeDeepCopier(host, sourceLocationProvider); var mutableModule = copier.Copy(decompiledModule); //Traverse the mutable copy. In a real application the traversal will collect information to be used during rewriting. var traverser = new CodeTraverser() { PreorderVisitor = new CodeVisitor() }; traverser.Traverse(mutableModule); //Rewrite the mutable Code Model. In a real application CodeRewriter would be a subclass that actually does something. //(This is why decompiled source method bodies must recompile themselves, rather than just use the IL from which they were decompiled.) var rewriter = new CodeRewriter(host); var rewrittenModule = rewriter.Rewrite(mutableModule); //Write out the Code Model by traversing it as the Metadata Model that it also is. using (var peStream = File.Create(rewrittenModule.Location + ".pe")) { if (pdbReader == null) { PeWriter.WritePeToStream(rewrittenModule, host, peStream); } else { using (var pdbWriter = new PdbWriter(rewrittenModule.Location + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenModule, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } } } }
public bool WriteSliceToFile(ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice, string directory, out string dll) { #if TRACE_PERFORMANCE var stopWatch = new Stopwatch(); stopWatch.Start(); #endif var newAssembly = Prune.PruneAssembly(host, slice); #if TRACE_PERFORMANCE Console.WriteLine("Time to prune the assembly: {0}", stopWatch.Elapsed); #endif var errors = ValidateAssembly(host, newAssembly); if (/*errors != null && */ 0 < errors.Count) { #if !DEBUG_SLICE dll = null; return(false); #endif } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = slice.ContainingAssembly.ResolvedAssembly.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile)) { pdbFile = Path.ChangeExtension(slice.ContainingAssembly.ResolvedAssembly.Location, "pdb"); } if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { ISourceLocationProvider sourceLocationProvider = pdbReader; ILocalScopeProvider localScopeProvider = pdbReader; Contract.Assume(sourceLocationProvider != null, "why??"); if (!MakeSureSliceHasAtLeastMethodSourceLocation(slice, sourceLocationProvider)) { dll = null; return(false); } dll = Path.Combine(directory, slice.Name + ".dll"); #if TRACE_PERFORMANCE stopWatch.Reset(); #endif using (var peStream = File.Create(dll)) { if (pdbReader == null) { PeWriter.WritePeToStream(newAssembly, host, peStream); } else { using (var pdbWriter = new PdbWriter(dll.Replace(".dll", ".pdb"), pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(newAssembly, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #if TRACE_PERFORMANCE Console.WriteLine("Time spent to write on the disk: {0}", stopWatch.Elapsed); #endif } #if !DEBUG_SLICE if (errors != null && 0 < errors.Count) { using (var tw = new StreamWriter(File.Create(Path.Combine(directory, slice.Name + ".errors.txt")))) { // something is performed asynchronously and may not be terminated here, that is wrong! lock (errors) { foreach (var err in errors) { tw.WriteLine(err.Location); foreach (var e in err.Errors) { tw.WriteLine("{0} {1} {2}", e.IsWarning ? "WARNING" : "ERROR ", e.Code, e.Message); } tw.WriteLine(); } } } return(false); } #endif // Can this be checked before writing it out? if (newAssembly.AssemblyReferences.Any(ar => ar.AssemblyIdentity.Equals(slice.ContainingAssembly.AssemblyIdentity))) { } return(true); }
static int Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: HelloContracts [path]fileName.Contracts.dll [-libpaths ...]* [-p [-i] | -inject]"); return(1); } #region Parse options var options = new Options(); options.Parse(args); if (options.HelpRequested) { options.PrintOptions(""); return(1); } if (options.HasErrors) { options.PrintErrorsAndExit(Console.Out); } #endregion var fileName = String.IsNullOrEmpty(options.assembly) ? options.GeneralArguments[0] : options.assembly; if (options.printContracts) { #region Collect and write contracts using (var host = new CodeContractAwareHostEnvironment(options.libpaths)) { IModule module = host.LoadUnitFrom(fileName) as IModule; if (module == null || module is Dummy) { Console.WriteLine("'{0}' is not a PE file containing a CLR module or assembly.", fileName); Environment.Exit(1); } var t = new Traverser(host, options.inherited); t.Traverse(module); } #endregion return(0); } else { using (var host = new CodeContractAwareHostEnvironment(options.libpaths, true, true)) { // Read the Metadata Model from the PE file var module = host.LoadUnitFrom(fileName) as IModule; if (module == null || module is Dummy) { Console.WriteLine(fileName + " is not a PE file containing a CLR module or assembly."); return(1); } // Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { ISourceLocationProvider sourceLocationProvider = pdbReader; // Construct a Code Model from the Metadata model via decompilation var mutableModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, DecompilerOptions.AnonymousDelegates | DecompilerOptions.Loops); ILocalScopeProvider localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); // Extract contracts (side effect: removes them from the method bodies) var contractProvider = Microsoft.Cci.MutableContracts.ContractHelper.ExtractContracts(host, mutableModule, pdbReader, localScopeProvider); // Inject non-null postconditions if (options.inject) { new NonNullInjector(host, contractProvider).Traverse(mutableModule); } // Put the contracts back in as method calls at the beginning of each method Microsoft.Cci.MutableContracts.ContractHelper.InjectContractCalls(host, mutableModule, contractProvider, sourceLocationProvider); // Write out the resulting module. Each method's corresponding IL is produced // lazily using CodeModelToILConverter via the delegate that the mutator stored in the method bodies. using (var peStream = File.Create(mutableModule.Location + ".pe")) { if (pdbReader == null) { PeWriter.WritePeToStream(mutableModule, host, peStream); } else { using (var pdbWriter = new PdbWriter(mutableModule.Location + ".pdb", sourceLocationProvider)) { PeWriter.WritePeToStream(mutableModule, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } } } return(0); } }
/// <summary> /// Outputs specified headers, sections, methods or runtime functions for one ReadyToRun image /// </summary> /// <param name="r2r">The structure containing the info of the ReadyToRun image</param> public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); bool standardDump = !(_options.EntryPoints || _options.CreatePDB || _options.CreatePerfmap); if (_options.Header && standardDump) { _dumper.WriteDivider("R2R Header"); _dumper.DumpHeader(true); } bool haveQuery = false; if (_options.Section != null) { haveQuery = true; QuerySection(r2r, _options.Section); } if (_options.RuntimeFunction != null) { haveQuery = true; QueryRuntimeFunction(r2r, _options.RuntimeFunction); } if (_options.Query != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Query", _options.Query, true); } if (_options.Keyword != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Keyword", _options.Keyword, false); } if (!haveQuery) { // Dump all sections and methods if no queries specified if (_options.EntryPoints) { _dumper.DumpEntryPoints(); } if (_options.CreatePDB) { string pdbPath = _options.PdbPath; if (String.IsNullOrEmpty(pdbPath)) { pdbPath = Path.GetDirectoryName(r2r.Filename); } var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None); pdbWriter.WritePDBData(r2r.Filename, ProduceDebugInfoMethods(r2r)); } if (_options.CreatePerfmap) { string perfmapPath = _options.PerfmapPath; if (string.IsNullOrEmpty(perfmapPath)) { perfmapPath = Path.ChangeExtension(r2r.Filename, ".r2rmap"); } // TODO: can't seem to find any place that surfaces the ABI. This is for debugging purposes, so may not be as relevant to be correct. TargetDetails details = new TargetDetails(r2r.TargetArchitecture, r2r.TargetOperatingSystem, TargetAbi.CoreRT); PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), details); } if (standardDump) { _dumper.DumpAllMethods(); _dumper.DumpFixupStats(); } } _dumper.End(); }
/// <summary> /// Outputs specified headers, sections, methods or runtime functions for one ReadyToRun image /// </summary> /// <param name="r2r">The structure containing the info of the ReadyToRun image</param> public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); bool standardDump = !(_options.EntryPoints || _options.CreatePDB || _options.CreatePerfmap); if (_options.Header && standardDump) { _dumper.WriteDivider("R2R Header"); _dumper.DumpHeader(true); } bool haveQuery = false; if (_options.Section != null) { haveQuery = true; QuerySection(r2r, _options.Section); } if (_options.RuntimeFunction != null) { haveQuery = true; QueryRuntimeFunction(r2r, _options.RuntimeFunction); } if (_options.Query != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Query", _options.Query, true); } if (_options.Keyword != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Keyword", _options.Keyword, false); } if (!haveQuery) { // Dump all sections and methods if no queries specified if (_options.EntryPoints) { _dumper.DumpEntryPoints(); } TargetArchitecture architecture = r2r.Machine switch { Machine.I386 => TargetArchitecture.X86, Machine.Amd64 => TargetArchitecture.X64, Machine.ArmThumb2 => TargetArchitecture.ARM, Machine.Arm64 => TargetArchitecture.ARM64, _ => throw new NotImplementedException(r2r.Machine.ToString()), }; TargetOS os = r2r.OperatingSystem switch { OperatingSystem.Windows => TargetOS.Windows, OperatingSystem.Linux => TargetOS.Linux, OperatingSystem.Apple => TargetOS.OSX, OperatingSystem.FreeBSD => TargetOS.FreeBSD, OperatingSystem.NetBSD => TargetOS.FreeBSD, _ => throw new NotImplementedException(r2r.OperatingSystem.ToString()), }; TargetDetails details = new TargetDetails(architecture, os, TargetAbi.CoreRT); if (_options.CreatePDB) { string pdbPath = _options.PdbPath; if (String.IsNullOrEmpty(pdbPath)) { pdbPath = Path.GetDirectoryName(r2r.Filename); } var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None, details); pdbWriter.WritePDBData(r2r.Filename, ProduceDebugInfoMethods(r2r)); } if (_options.CreatePerfmap) { string perfmapPath = _options.PerfmapPath; if (string.IsNullOrEmpty(perfmapPath)) { perfmapPath = Path.ChangeExtension(r2r.Filename, ".r2rmap"); } PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), details); } if (standardDump) { _dumper.DumpAllMethods(); _dumper.DumpFixupStats(); } } _dumper.End(); }
public static MemoryStream RewriteProgramIL(CeleriacArgs celeriacArgs, TypeManager typeManager) { if (String.IsNullOrWhiteSpace(celeriacArgs.AssemblyPath)) { throw new FileNotFoundException("Path to program to be profiled not provided"); } Stream resultStream; var host = typeManager.Host; IModule /*?*/ module = host.LoadUnitFrom(celeriacArgs.AssemblyPath) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new FileNotFoundException("Given path is not a PE file containing a CLR" + " assembly, or an error occurred when loading it.", celeriacArgs.AssemblyPath); } if (module.GetAllTypes().Any( type => type.Name.ToString().Equals(ILRewriter.ArgumentStoringClassName))) { throw new InvalidOperationException("Program has already been instrumented."); } string pdbFile = Path.ChangeExtension(module.Location, "pdb"); Assembly mutable = null; using (var pdbReader = LoadPdbReaderAndFile(celeriacArgs, typeManager, module, pdbFile)) { AssemblySummary comparabilityManager = GenerateComparability(celeriacArgs, typeManager, host, module, pdbReader, ref mutable); if (celeriacArgs.GenerateComparability && celeriacArgs.ComparabilityFile == null) { return(null); } ILRewriter mutator = new ILRewriter(host, pdbReader, celeriacArgs, typeManager, comparabilityManager); module = mutator.Visit(mutable, Path.Combine(FindVisitorDir(), VisitorDll)); if (celeriacArgs.EmitNullaryInfo || celeriacArgs.GenerateComparability) { return(null); } // Remove the old PDB file try { File.Delete(pdbFile); } catch (UnauthorizedAccessException) { // If they are running the debugger we might not be able to delete the file // Save the pdb elsewhere in this case. pdbFile = module.Location + ".pdb"; } if (celeriacArgs.SaveProgram != null) { resultStream = new FileStream(celeriacArgs.SaveProgram, FileMode.Create); } else { resultStream = new MemoryStream(); } #if __MonoCS__ // Reading / Writing DEBUG information on Mono is not supported by CCI PdbWriter pdbWriter = null; #else var pdbWriter = new PdbWriter(pdbFile, pdbReader); #endif // 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 (pdbWriter) { PeWriter.WritePeToStream(module, host, resultStream, pdbReader, null, pdbWriter); } } if (celeriacArgs.SaveProgram != null) { // We aren't going to run the program, so no need to return anything, // but close the file stream. resultStream.Close(); return(null); } else { return((MemoryStream)resultStream); // success } }
/// <summary> /// Write the pdb to a file. /// </summary> /// <param name="fileName">The file name to write the pdb into.</param> /// <param name="metadataProvider">The metadata provider for the managed metadata.</param> public void Write(string fileName, IMetadataProvider metadataProvider) { if (fileName == null) throw new ArgumentNullException("fileName"); if (metadataProvider == null) throw new ArgumentNullException("metadataProvider"); using (var writer = new PdbWriter(fileName, metadataProvider)) Write(writer); WriteHeader(fileName); }
internal int Run() { SecurityKeepOptions securityKeepOptions = options.onlySecurityTransparent ? SecurityKeepOptions.OnlyNonCritical : SecurityKeepOptions.All; if (options.doBreak) { System.Diagnostics.Debugger.Launch(); } string assemblyName = null; if (options.GeneralArguments.Count == 1) { assemblyName = options.GeneralArguments[0]; } if (assemblyName == null) { errorLogger("Must specify an input file."); return(1); } using (var host = new AsmMetaHostEnvironment(options.libPaths.ToArray(), options.searchGAC)) { foreach (var p in options.resolvedPaths) { host.AddResolvedPath(p); } IAssembly /*?*/ assembly = host.LoadUnitFrom(assemblyName) as IAssembly; if (assembly == null || assembly is Dummy) { errorLogger(assemblyName + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return(1); } var rewrittenAttribute = CreateTypeReference(host, assembly, "System.Diagnostics.Contracts.RuntimeContractsAttribute"); if (AttributeHelper.Contains(assembly.Attributes, rewrittenAttribute)) { errorLogger(assemblyName + " is already rewritten, cannot generate a reference assembly from it."); return(1); } if (options.backwardCompatibility) { // redundant because RemoveMethodBodies.ctor also does this when the flag is set options.whatToEmit = KeepOptions.ExtVis; options.emitAttributes = false; } PdbReader /*?*/ pdbReader = null; if (options.includeSourceTextInContract) { // No point getting the PDB file unless we want to use it for source text string pdbFile = Path.ChangeExtension(assembly.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { errorLogger("Could not load the PDB file for the assembly '" + assembly.Name.Value + "' . Source text will not be preserved in the reference assembly. Proceeding anyway."); } } using (pdbReader) { // We might be working on the assembly that defines the contract class and/or the type System.Void. // (Or any other platform type!) // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones. // This is OK, except if the assembly is being renamed. this.compilerGeneratedAttributeType = host.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute; this.contractClassType = host.PlatformType.SystemDiagnosticsContractsContract; this.systemAttributeType = host.PlatformType.SystemAttribute; this.systemBooleanType = host.PlatformType.SystemBoolean; this.systemStringType = host.PlatformType.SystemString; this.systemObjectType = host.PlatformType.SystemObject; this.systemVoidType = host.PlatformType.SystemVoid; //new FindPlatformTypes(this).Traverse(assembly); //update the above fields if any of those types are defined in mutable Assembly mutable = new MetadataDeepCopier(host).Copy(assembly); #region Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity if (options.rename) { if (options.output != null) { mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(options.output)); } else { mutable.Name = host.NameTable.GetNameFor(assembly.Name.Value + ".Contracts"); } mutable.ModuleName = mutable.Name; mutable.Kind = ModuleKind.DynamicallyLinkedLibrary; mutable = (Assembly)RenameAssembly.ReparentAssemblyIdentity(host, assembly.AssemblyIdentity, mutable.AssemblyIdentity, mutable); } #endregion Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity if (!options.renameOnly) { if (options.contracts) { if (options.rename) { // We might be working on the assembly that defines the contract class and/or the type System.Void. // (Or any other platform type!) // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones. // This is OK, except if the assembly is being renamed. var systemNamespace = GetFirstMatchingNamespace(host, mutable.UnitNamespaceRoot, "System"); if (systemNamespace != null) { var typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Attribute"); if (typeDefinition != null) { this.systemAttributeType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Boolean"); if (typeDefinition != null) { this.systemBooleanType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Object"); if (typeDefinition != null) { this.systemObjectType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "String"); if (typeDefinition != null) { this.systemStringType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Void"); if (typeDefinition != null) { this.systemVoidType = typeDefinition; } var systemRuntimeNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Runtime"); if (systemRuntimeNamespace != null) { var systemRuntimeCompilerServicesNamespace = GetFirstMatchingNamespace(host, systemRuntimeNamespace, "CompilerServices"); if (systemRuntimeCompilerServicesNamespace != null) { typeDefinition = GetFirstMatchingTypeDefinition(host, systemRuntimeCompilerServicesNamespace, "CompilerGeneratedAttribute"); if (typeDefinition != null) { this.compilerGeneratedAttributeType = typeDefinition; } } } var systemDiagnosticsNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Diagnostics"); if (systemDiagnosticsNamespace != null) { var systemDiagnosticsContractsNamespace = GetFirstMatchingNamespace(host, systemDiagnosticsNamespace, "Contracts"); if (systemDiagnosticsContractsNamespace != null) { typeDefinition = GetFirstMatchingTypeDefinition(host, systemDiagnosticsContractsNamespace, "Contract"); if (typeDefinition != null) { this.contractClassType = typeDefinition; } } } } } mutable = AsmMetaRewriter.RewriteModule(host, pdbReader, mutable, contractClassType, compilerGeneratedAttributeType, systemAttributeType, systemBooleanType, systemObjectType, systemStringType, systemVoidType ) as Assembly; } #region Delete things that are not to be kept if (options.backwardCompatibility || options.whatToEmit != KeepOptions.All || !options.emitAttributes || (options.attrs != null && 0 < options.attrs.Count)) { DeleteThings thinner = new DeleteThings(host, options.whatToEmit, securityKeepOptions, options.emitAttributes, options.attrs.ToArray(), options.backwardCompatibility); if (securityKeepOptions == SecurityKeepOptions.OnlyNonCritical && host.platformType.SystemSecuritySecurityCriticalAttribute.ResolvedType is Dummy) { errorLogger("You asked to remove security critical methods, but the version of mscorlib doesn't support the SecurityCriticalAttribute."); return(1); } thinner.RewriteChildren(mutable); #region Fix up dangling references to things that were deleted FixUpReferences patcher = new FixUpReferences(host, thinner.WhackedMethods, thinner.WhackedTypes); patcher.RewriteChildren(mutable); #endregion Fix up dangling references to things that were deleted } #endregion Delete things that are not to be kept #region Output is always a dll, so mark the assembly as that mutable.EntryPoint = Dummy.MethodReference; mutable.Kind = ModuleKind.DynamicallyLinkedLibrary; #endregion Output is always a dll, so mark the assembly as that } assembly = mutable; string outputPath; if (options.output != null) // user specified, they'd better make sure it doesn't conflict with anything { outputPath = options.output; } else if (options.rename) // A.dll ==> A.Contracts.dll (Always! Even if the input is an exe!) { outputPath = assembly.Name.Value + ".dll"; } else // A.dll ==> A.dll.meta { outputPath = assembly.Name.Value + Path.GetExtension(assemblyName) + ".meta"; } // NB: Do *not* pass a pdbWriter to WritePeToStream. No need to create a PDB file and if // it is provided, then it might find things (like constants in a scope) that don't get // visited and so don't have any type references modified as they should be. using (var outputFile = File.Create(outputPath)) { if (pdbReader != null && options.writePDB) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), pdbReader)) { // Need to not pass in a local scope provider until such time as we have one that will use the mutator // to remap things (like the type of a scope constant) from the original assembly to the mutated one. PeWriter.WritePeToStream(assembly, host, outputFile, pdbReader, null /*pdbReader*/, pdbWriter); } } else { PeWriter.WritePeToStream(assembly, host, outputFile); } } } } return(0); // success }
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 }
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); } } } } }