diff --git a/tools/common/Application.cs b/tools/common/Application.cs index d0e3dc207d73..12a607130df4 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -154,7 +154,11 @@ public static void SaveAssembly (AssemblyDefinition assembly, string destination main.ReadSymbols (provider.GetSymbolReader (main, main.FileName)); } - var wp = new WriterParameters () { WriteSymbols = symbols }; + var wp = new WriterParameters () { + WriteSymbols = symbols, + SymbolWriterProvider = symbols ? new CustomSymbolWriterProvider () : null, + }; + // re-write symbols, if available, so the new tokens will match assembly.Write (destination, wp); diff --git a/tools/linker/CustomSymbolWriter.cs b/tools/linker/CustomSymbolWriter.cs new file mode 100644 index 000000000000..bc26835f1080 --- /dev/null +++ b/tools/linker/CustomSymbolWriter.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using System.Text; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Xamarin.Linker +{ + public sealed class CustomSymbolWriterProvider : ISymbolWriterProvider + { + readonly DefaultSymbolWriterProvider default_symbol_writer_provider = new DefaultSymbolWriterProvider (); + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string filename) + => new CustomSymbolWriter (default_symbol_writer_provider.GetSymbolWriter (module, filename)); + + public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) + => new CustomSymbolWriter (default_symbol_writer_provider.GetSymbolWriter (module, symbolStream)); + } + + // This is symbol writer wraps another symbol writer, and changes one thing: + // it writes the filename part of the pdb (as opposed to the full path), in the debug header of the dll. + // References: + // https://bugzilla.xamarin.com/show_bug.cgi?id=54578 (Assemblies are duplicated in fat apps when built with .pdb, because pdb paths are different) + // https://github.com/jbevain/cecil/issues/372 (first attempt at a fix: make cecil write the filename only) + // https://github.com/jbevain/cecil/pull/554 (first fix attempt broke something else, so it had to be reverted) + public sealed class CustomSymbolWriter : ISymbolWriter + { + readonly ISymbolWriter _symbolWriter; + + public CustomSymbolWriter (ISymbolWriter symbolWriter) + { + _symbolWriter = symbolWriter; + } + + public ImageDebugHeader GetDebugHeader () + { + var header = _symbolWriter.GetDebugHeader (); + if (!header.HasEntries) + return header; + + for (int i = 0; i < header.Entries.Length; i++) { + header.Entries [i] = ProcessEntry (header.Entries [i]); + } + + return header; + } + + static ImageDebugHeaderEntry ProcessEntry (ImageDebugHeaderEntry entry) + { + if (entry.Directory.Type != ImageDebugType.CodeView) + return entry; + + var reader = new BinaryReader (new MemoryStream (entry.Data)); + var newDataStream = new MemoryStream (); + var writer = new BinaryWriter (newDataStream); + + var sig = reader.ReadUInt32 (); + if (sig != 0x53445352) + return entry; + + writer.Write (sig); // RSDS + writer.Write (reader.ReadBytes (16)); // MVID + writer.Write (reader.ReadUInt32 ()); // Age + + var fullPath = Encoding.UTF8.GetString (reader.ReadBytes (entry.Data.Length - 1 - 24)); // length - ending \0 - RSDS+MVID+AGE + + writer.Write (Encoding.UTF8.GetBytes (Path.GetFileName (fullPath))); + writer.Write ((byte) 0); + + var newData = newDataStream.ToArray (); + + var directory = entry.Directory; + directory.SizeOfData = newData.Length; + + return new ImageDebugHeaderEntry (directory, newData); + } + + public ISymbolReaderProvider GetReaderProvider () => _symbolWriter.GetReaderProvider (); + + public void Write (MethodDebugInformation info) => _symbolWriter.Write (info); + + public void Dispose () => _symbolWriter.Dispose (); + } +} diff --git a/tools/mmp/mmp.csproj b/tools/mmp/mmp.csproj index 30a89bf1ccbd..f0513395af44 100644 --- a/tools/mmp/mmp.csproj +++ b/tools/mmp/mmp.csproj @@ -379,6 +379,9 @@ external\PListObject.cs + + Xamarin.Linker\CustomSymbolWriter.cs + diff --git a/tools/mtouch/Tuning.cs b/tools/mtouch/Tuning.cs index 19be96cd08f2..278f85b3c42d 100644 --- a/tools/mtouch/Tuning.cs +++ b/tools/mtouch/Tuning.cs @@ -135,6 +135,7 @@ static MonoTouchLinkContext CreateLinkContext (LinkerOptions options, Pipeline p context.StaticRegistrar = options.Target.StaticRegistrar; context.Target = options.Target; context.ExcludedFeatures = new [] { "remoting", "com", "sre" }; + context.SymbolWriterProvider = new CustomSymbolWriterProvider (); options.LinkContext = context; return context; diff --git a/tools/mtouch/mtouch.csproj b/tools/mtouch/mtouch.csproj index 12f8a5f809a6..9d17d6b41680 100644 --- a/tools/mtouch/mtouch.csproj +++ b/tools/mtouch/mtouch.csproj @@ -383,6 +383,9 @@ Linker\TypeNameParser.cs + + Xamarin.Linker\CustomSymbolWriter.cs +