static ModuleDefinition RoundtripModule(ModuleDefinition module, RoundtripType roundtripType) { if (roundtripType == RoundtripType.None) { return(module); } var file = Path.Combine(Path.GetTempPath(), "TestILProcessor.dll"); if (File.Exists(file)) { File.Delete(file); } ISymbolWriterProvider symbolWriterProvider; switch (roundtripType) { case RoundtripType.Pdb when Platform.HasNativePdbSupport: symbolWriterProvider = new PdbWriterProvider(); break; case RoundtripType.PortablePdb: default: symbolWriterProvider = new PortablePdbWriterProvider(); break; } module.Write(file, new WriterParameters { SymbolWriterProvider = symbolWriterProvider, }); module.Dispose(); ISymbolReaderProvider symbolReaderProvider; switch (roundtripType) { case RoundtripType.Pdb when Platform.HasNativePdbSupport: symbolReaderProvider = new PdbReaderProvider(); break; case RoundtripType.PortablePdb: default: symbolReaderProvider = new PortablePdbReaderProvider(); break; } return(ModuleDefinition.ReadModule(file, new ReaderParameters { SymbolReaderProvider = symbolReaderProvider, InMemory = true })); }
private static void ApplySymbolProviders(Options options, ReaderParameters readerParameters, WriterParameters writerParameters) { if (!options.DebugSymbols) { readerParameters.ReadSymbols = false; readerParameters.SymbolReaderProvider = null; writerParameters.WriteSymbols = false; writerParameters.SymbolWriterProvider = null; return; } var source = options.Source.FullName; var pdbPath = Path.ChangeExtension(source, ".pdb"); var pdbExists = File.Exists(pdbPath); readerParameters.ReadSymbols = true; readerParameters.SymbolReaderProvider = pdbExists ? (ISymbolReaderProvider) new Mono.Cecil.Pdb.PdbReaderProvider() : new EmbeddedPortablePdbReaderProvider(); ISymbolWriterProvider writer = null; switch (options.DebugType) { case null: writer = new Mono.Cecil.Pdb.PdbWriterProvider(); break; case DebugType.Portable: writer = new PortablePdbWriterProvider(); break; case DebugType.Embedded: writer = new EmbeddedPortablePdbWriterProvider(); break; } writerParameters.SymbolWriterProvider = writer; writerParameters.WriteSymbols = writer != null; }
private Stream GetSymbolInformation(out ISymbolReaderProvider symbolReaderProvider, out ISymbolWriterProvider symbolWriterProvider) { if (string.Equals("none", DebugType, StringComparison.OrdinalIgnoreCase)) { Logger.Info("No symbols"); symbolReaderProvider = null; symbolWriterProvider = null; return(null); } if (string.Equals("embedded", DebugType, StringComparison.OrdinalIgnoreCase)) { Logger.Info("Using embedded symbols"); symbolReaderProvider = new EmbeddedPortablePdbReaderProvider(); symbolWriterProvider = new EmbeddedPortablePdbWriterProvider(); return(null); } string pdbPath = FindPdbPath(); string mdbPath = FindMdbPath(); if (pdbPath != null && mdbPath != null) { if (File.GetLastWriteTimeUtc(pdbPath) >= File.GetLastWriteTimeUtc(mdbPath)) { mdbPath = null; Logger.Debug("Found mdb and pdb debug symbols. Selected pdb (newer).", DebugLogLevel.Verbose); } else { pdbPath = null; Logger.Debug("Found mdb and pdb debug symbols. Selected mdb (newer).", DebugLogLevel.Verbose); } } if (pdbPath != null) { if (IsPortablePdb(pdbPath)) { Logger.Info($"Using portable symbol file {pdbPath}"); symbolReaderProvider = new PortablePdbReaderProvider(); symbolWriterProvider = new PortablePdbWriterProvider(); } else { Logger.Info($"Using symbol file {pdbPath}"); symbolReaderProvider = new PdbReaderProvider(); symbolWriterProvider = new PdbWriterProvider(); } string tempPath = pdbPath + ".tmp"; File.Copy(pdbPath, tempPath, true); return(new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); } else if (mdbPath != null) { Logger.Info($"Using symbol file {mdbPath}"); symbolReaderProvider = new MdbReaderProvider(); symbolWriterProvider = new MdbWriterProvider(); string tempPath = mdbPath + ".tmp"; File.Copy(mdbPath, tempPath, true); return(new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); } symbolReaderProvider = null; symbolWriterProvider = null; return(null); string FindPdbPath() { // because UWP use a wacky convention for symbols string path = Path.ChangeExtension(AssemblyFile, "compile.pdb"); if (File.Exists(path)) { Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose); return(path); } path = Path.ChangeExtension(AssemblyFile, "pdb"); if (File.Exists(path)) { Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose); return(path); } return(null); } bool IsPortablePdb(string symbolsPath) { using (var fileStream = File.OpenRead(symbolsPath)) using (var reader = new BinaryReader(fileStream)) { return(reader.ReadBytes(4).SequenceEqual(new byte[] { 0x42, 0x4a, 0x53, 0x42 })); } } string FindMdbPath() { string path = AssemblyFile + ".mdb"; if (File.Exists(path)) { Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose); return(path); } return(null); } }
public CecilMigrationResult Migrate(string source, string destination) { if (string.IsNullOrWhiteSpace(source)) { throw new ArgumentException($"Invalid source assembly path specified: '{source}'.", nameof(source)); } if (string.IsNullOrWhiteSpace(destination)) { throw new ArgumentException($"Invalid destination assembly path specified: '{destination}'.", nameof(destination)); } if (!File.Exists(source)) { throw new FileNotFoundException($"Source assembly does not exist: '{source}'.", source); } var pdbPath = Path.ChangeExtension(source, "pdb"); var destPdbPath = Path.ChangeExtension(destination, "pdb"); var tempDllPath = Path.ChangeExtension(destination, "temp.dll"); var tempPdbPath = Path.ChangeExtension(destination, "temp.pdb"); var hasPdb = File.Exists(pdbPath); var result = CecilMigrationResult.Skipped; using (var resolver = new DefaultAssemblyResolver()) { resolver.AddSearchDirectory(Path.GetDirectoryName(source)); var readerParams = new ReaderParameters { ReadSymbols = hasPdb, AssemblyResolver = resolver, }; var requiresSave = false; using (var assembly = AssemblyDefinition.ReadAssembly(source, readerParams)) { LogVerboseMessage($"Processing assembly '{source}'..."); if (!hasPdb) { LogVerboseMessage($" No debug symbols found for the assembly."); } result = MigrateAssembly(assembly); requiresSave = result.HasFlag(CecilMigrationResult.ContainedSupport) || result.HasFlag(CecilMigrationResult.ContainedJni) || result.HasFlag(CecilMigrationResult.ContainedJavaArtifacts); var dir = Path.GetDirectoryName(destination); if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (requiresSave) { Stream symbolStream = null; ISymbolWriterProvider symbolWriter = null; if (hasPdb) { symbolStream = File.Create(tempPdbPath); symbolWriter = new PortablePdbWriterProvider(); } try { assembly.Write(tempDllPath, new WriterParameters { WriteSymbols = hasPdb, SymbolStream = symbolStream, SymbolWriterProvider = symbolWriter }); } finally { symbolStream?.Dispose(); } LogMessage($"Migrated assembly to '{destination}'."); } else { LogVerboseMessage($"Skipped assembly '{source}' due to lack of support types."); if (!source.Equals(destination, StringComparison.OrdinalIgnoreCase)) { LogVerboseMessage($"Copying source assembly '{source}' to '{destination}'."); File.Copy(source, destination, true); if (hasPdb) { File.Copy(pdbPath, destPdbPath, true); } } } } if (requiresSave) { if (File.Exists(tempDllPath)) { File.Copy(tempDllPath, destination, true); File.Delete(tempDllPath); } if (File.Exists(tempPdbPath)) { File.Copy(tempPdbPath, destPdbPath, true); File.Delete(tempPdbPath); } } } return(result); }