From 5fa598a5d5fdd0e769495717626db9f20852d3eb Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 10 May 2017 05:58:27 -0700 Subject: Add support for writing pure IL for R2R assemblies (#99) --- linker/Mono.Linker.Steps/OutputStep.cs | 54 +++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'linker') diff --git a/linker/Mono.Linker.Steps/OutputStep.cs b/linker/Mono.Linker.Steps/OutputStep.cs index 47e2c3853..842434efd 100644 --- a/linker/Mono.Linker.Steps/OutputStep.cs +++ b/linker/Mono.Linker.Steps/OutputStep.cs @@ -27,15 +27,47 @@ // using System; +using System.Collections.Generic; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; +using Mono.Cecil.PE; namespace Mono.Linker.Steps { public class OutputStep : BaseStep { + private static Dictionary architectureMap; + + private enum NativeOSOverride { + Apple = 0x4644, + FreeBSD = 0xadc4, + Linux = 0x7b79, + NetBSD = 0x1993, + Default = 0 + } + + static TargetArchitecture CalculateArchitecture (TargetArchitecture readyToRunArch) + { + if (architectureMap == null) { + architectureMap = new Dictionary (); + foreach (var os in Enum.GetValues (typeof (NativeOSOverride))) { + ushort osVal = (ushort) (NativeOSOverride) os; + foreach (var arch in Enum.GetValues (typeof (TargetArchitecture))) { + ushort archVal = (ushort) (TargetArchitecture)arch; + architectureMap.Add ((ushort) (archVal ^ osVal), (TargetArchitecture) arch); + } + } + } + + TargetArchitecture pureILArch; + if (architectureMap.TryGetValue ((ushort) readyToRunArch, out pureILArch)) { + return pureILArch; + } + throw new BadImageFormatException ("unrecognized module attributes"); + } + protected override void Process () { CheckOutputDirectory (); @@ -55,6 +87,26 @@ namespace Mono.Linker.Steps { OutputAssembly (assembly); } + static bool IsReadyToRun (ModuleDefinition module) + { + return (module.Attributes & ModuleAttributes.ILOnly) == 0 && + (module.Attributes & (ModuleAttributes) 0x04) != 0; + } + + void WriteAssembly (AssemblyDefinition assembly, string directory) + { + foreach (var module in assembly.Modules) { + // Write back pure IL even for R2R assemblies + if (IsReadyToRun (module)) { + module.Attributes |= ModuleAttributes.ILOnly; + module.Attributes ^= (ModuleAttributes) (uint) 0x04; + module.Architecture = CalculateArchitecture (module.Architecture); + } + } + + assembly.Write (GetAssemblyFileName (assembly, directory), SaveSymbols (assembly)); + } + void OutputAssembly (AssemblyDefinition assembly) { string directory = Context.OutputDirectory; @@ -65,7 +117,7 @@ namespace Mono.Linker.Steps { case AssemblyAction.Save: case AssemblyAction.Link: Context.Annotations.AddDependency (assembly); - assembly.Write (GetAssemblyFileName (assembly, directory), SaveSymbols (assembly)); + WriteAssembly (assembly, directory); break; case AssemblyAction.Copy: Context.Annotations.AddDependency (assembly); -- cgit v1.2.3