Skip to content

Commit

Permalink
[mtouch] Use a custom symbol writer to ensure only pdb file names are…
Browse files Browse the repository at this point in the history
… written to assemblies.

We need our 32-bit and 64-bit assemblies to be identical so that we can avoid
duplicating the .dll in fat apps.

One difference used to be that the .dll contained the full path to the
corresponding .pdb ([1]), but we changed cecil to only write the filename
([2]). Unfortunately this change breaks something else, so it has to be
reverted ([3]).

This implements a different solution: we provide a custom symbol writer to
Cecil, which only writes the filename of the pdb in the .dll, not the full
path.

[1]: https://bugzilla.xamarin.com/show_bug.cgi?id=54578
[2]: jbevain/cecil#372
[3]: jbevain/cecil#554
  • Loading branch information
rolfbjarne committed Jan 28, 2019
1 parent 2b271cb commit 53874c8
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
6 changes: 5 additions & 1 deletion tools/common/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
85 changes: 85 additions & 0 deletions tools/linker/CustomSymbolWriter.cs
Original file line number Diff line number Diff line change
@@ -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 ();
}
}
3 changes: 3 additions & 0 deletions tools/mmp/mmp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,9 @@
<Compile Include="..\..\external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs">
<Link>external\PListObject.cs</Link>
</Compile>
<Compile Include="..\linker\CustomSymbolWriter.cs">
<Link>Xamarin.Linker\CustomSymbolWriter.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions tools/mtouch/Tuning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions tools/mtouch/mtouch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@
<Compile Include="..\..\external\mono\external\linker\linker\Linker\TypeNameParser.cs">
<Link>Linker\TypeNameParser.cs</Link>
</Compile>
<Compile Include="..\linker\CustomSymbolWriter.cs">
<Link>Xamarin.Linker\CustomSymbolWriter.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Core" />
Expand Down

0 comments on commit 53874c8

Please sign in to comment.