Example #1
0
        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
            }));
        }
Example #2
0
        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;
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
        }