--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public abstract class ApplyPreserveAttributeBase : BaseSubStep {
+
+ protected abstract string PreserveAttribute { get; }
+
+ public override SubStepTargets Targets {
+ get {
+ return SubStepTargets.Type
+ | SubStepTargets.Field
+ | SubStepTargets.Method
+ | SubStepTargets.Property
+ | SubStepTargets.Event;
+ }
+ }
+
+ public override bool IsActiveFor (AssemblyDefinition assembly)
+ {
+ return !Profile.IsSdkAssembly (assembly) && Annotations.GetAction (assembly) == AssemblyAction.Link;
+ }
+
+ public override void ProcessType (TypeDefinition type)
+ {
+ TryApplyPreserveAttribute (type);
+ }
+
+ public override void ProcessField (FieldDefinition field)
+ {
+ var attribute = GetPreserveAttribute (field);
+ if (attribute == null)
+ return;
+
+ Mark (field, attribute);
+ }
+
+ public override void ProcessMethod (MethodDefinition method)
+ {
+ MarkMethodIfPreserved (method);
+ }
+
+ public override void ProcessProperty (PropertyDefinition property)
+ {
+ var attribute = GetPreserveAttribute (property);
+ if (attribute == null)
+ return;
+
+ MarkMethod (property.GetMethod, attribute);
+ MarkMethod (property.SetMethod, attribute);
+ }
+
+ public override void ProcessEvent (EventDefinition @event)
+ {
+ var attribute = GetPreserveAttribute (@event);
+ if (attribute == null)
+ return;
+
+ MarkMethod (@event.AddMethod, attribute);
+ MarkMethod (@event.InvokeMethod, attribute);
+ MarkMethod (@event.RemoveMethod, attribute);
+ }
+
+ void MarkMethodIfPreserved (MethodDefinition method)
+ {
+ var attribute = GetPreserveAttribute (method);
+ if (attribute == null)
+ return;
+
+ MarkMethod (method, attribute);
+ }
+
+ void MarkMethod (MethodDefinition method, CustomAttribute preserve_attribute)
+ {
+ if (method == null)
+ return;
+
+ Mark (method, preserve_attribute);
+ Annotations.SetAction (method, MethodAction.Parse);
+ }
+
+ void Mark (IMetadataTokenProvider provider, CustomAttribute preserve_attribute)
+ {
+ if (IsConditionalAttribute (preserve_attribute)) {
+ PreserveConditional (provider);
+ return;
+ }
+
+ PreserveUnconditional (provider);
+ }
+
+ void PreserveConditional (IMetadataTokenProvider provider)
+ {
+ var method = provider as MethodDefinition;
+ if (method == null)
+ return;
+
+ Annotations.AddPreservedMethod (method.DeclaringType, method);
+ }
+
+ static bool IsConditionalAttribute (CustomAttribute attribute)
+ {
+ if (attribute == null)
+ return false;
+
+ foreach (var named_argument in attribute.Fields)
+ if (named_argument.Name == "Conditional")
+ return (bool) named_argument.Argument.Value;
+
+ return false;
+ }
+
+ void PreserveUnconditional (IMetadataTokenProvider provider)
+ {
+ Annotations.Mark (provider);
+
+ var member = provider as IMemberDefinition;
+ if (member == null || member.DeclaringType == null)
+ return;
+
+ Mark (member.DeclaringType, null);
+ }
+
+ void TryApplyPreserveAttribute (TypeDefinition type)
+ {
+ var attribute = GetPreserveAttribute (type);
+ if (attribute == null)
+ return;
+
+ Annotations.Mark (type);
+
+ foreach (var named_argument in attribute.Fields)
+ if (named_argument.Name == "AllMembers" && (bool) named_argument.Argument.Value)
+ Annotations.SetPreserve (type, TypePreserve.All);
+ }
+
+ CustomAttribute GetPreserveAttribute (ICustomAttributeProvider provider)
+ {
+ if (!provider.HasCustomAttributes)
+ return null;
+
+ var attributes = provider.CustomAttributes;
+
+ for (int i = 0; i < attributes.Count; i++) {
+ var attribute = attributes [i];
+
+ if (attribute.Constructor.DeclaringType.FullName != PreserveAttribute)
+ continue;
+
+ attributes.RemoveAt (i);
+ return attribute;
+ }
+
+ return null;
+ }
+ }
+}
--- /dev/null
+//
+// MethodBodyRocks.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// Copyright (c) 2008 - 2011 Jb Evain
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Mono.Tuner {
+
+ static class MethodBodyRocks {
+
+ public static IEnumerable<TypeDefinition> GetAllTypes (this ModuleDefinition self)
+ {
+ return self.Types.SelectMany (t => t.GetAllTypes ());
+ }
+
+ static IEnumerable<TypeDefinition> GetAllTypes (this TypeDefinition self)
+ {
+ yield return self;
+
+ if (!self.HasNestedTypes)
+ yield break;
+
+ foreach (var type in self.NestedTypes.SelectMany (t => t.GetAllTypes ()))
+ yield return type;
+ }
+
+ public static IEnumerable<MethodDefinition> GetMethods (this TypeDefinition self)
+ {
+ return self.Methods.Where (m => !m.IsConstructor);
+ }
+
+ public static IEnumerable<MethodDefinition> GetConstructors (this TypeDefinition self)
+ {
+ return self.Methods.Where (m => m.IsConstructor);
+ }
+
+ public static MethodDefinition GetTypeConstructor (this TypeDefinition self)
+ {
+ return self.GetConstructors ().FirstOrDefault (c => c.IsStatic);
+ }
+
+ public static void SimplifyMacros (this MethodBody self)
+ {
+ if (self == null)
+ throw new ArgumentNullException ("self");
+
+ foreach (var instruction in self.Instructions) {
+ if (instruction.OpCode.OpCodeType != OpCodeType.Macro)
+ continue;
+
+ switch (instruction.OpCode.Code) {
+ case Code.Ldarg_0:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (0));
+ break;
+ case Code.Ldarg_1:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (1));
+ break;
+ case Code.Ldarg_2:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (2));
+ break;
+ case Code.Ldarg_3:
+ ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (3));
+ break;
+ case Code.Ldloc_0:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [0]);
+ break;
+ case Code.Ldloc_1:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [1]);
+ break;
+ case Code.Ldloc_2:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [2]);
+ break;
+ case Code.Ldloc_3:
+ ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [3]);
+ break;
+ case Code.Stloc_0:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [0]);
+ break;
+ case Code.Stloc_1:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [1]);
+ break;
+ case Code.Stloc_2:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [2]);
+ break;
+ case Code.Stloc_3:
+ ExpandMacro (instruction, OpCodes.Stloc, self.Variables [3]);
+ break;
+ case Code.Ldarg_S:
+ instruction.OpCode = OpCodes.Ldarg;
+ break;
+ case Code.Ldarga_S:
+ instruction.OpCode = OpCodes.Ldarga;
+ break;
+ case Code.Starg_S:
+ instruction.OpCode = OpCodes.Starg;
+ break;
+ case Code.Ldloc_S:
+ instruction.OpCode = OpCodes.Ldloc;
+ break;
+ case Code.Ldloca_S:
+ instruction.OpCode = OpCodes.Ldloca;
+ break;
+ case Code.Stloc_S:
+ instruction.OpCode = OpCodes.Stloc;
+ break;
+ case Code.Ldc_I4_M1:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, -1);
+ break;
+ case Code.Ldc_I4_0:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 0);
+ break;
+ case Code.Ldc_I4_1:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 1);
+ break;
+ case Code.Ldc_I4_2:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 2);
+ break;
+ case Code.Ldc_I4_3:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 3);
+ break;
+ case Code.Ldc_I4_4:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 4);
+ break;
+ case Code.Ldc_I4_5:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 5);
+ break;
+ case Code.Ldc_I4_6:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 6);
+ break;
+ case Code.Ldc_I4_7:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 7);
+ break;
+ case Code.Ldc_I4_8:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, 8);
+ break;
+ case Code.Ldc_I4_S:
+ ExpandMacro (instruction, OpCodes.Ldc_I4, (int) (sbyte) instruction.Operand);
+ break;
+ case Code.Br_S:
+ instruction.OpCode = OpCodes.Br;
+ break;
+ case Code.Brfalse_S:
+ instruction.OpCode = OpCodes.Brfalse;
+ break;
+ case Code.Brtrue_S:
+ instruction.OpCode = OpCodes.Brtrue;
+ break;
+ case Code.Beq_S:
+ instruction.OpCode = OpCodes.Beq;
+ break;
+ case Code.Bge_S:
+ instruction.OpCode = OpCodes.Bge;
+ break;
+ case Code.Bgt_S:
+ instruction.OpCode = OpCodes.Bgt;
+ break;
+ case Code.Ble_S:
+ instruction.OpCode = OpCodes.Ble;
+ break;
+ case Code.Blt_S:
+ instruction.OpCode = OpCodes.Blt;
+ break;
+ case Code.Bne_Un_S:
+ instruction.OpCode = OpCodes.Bne_Un;
+ break;
+ case Code.Bge_Un_S:
+ instruction.OpCode = OpCodes.Bge_Un;
+ break;
+ case Code.Bgt_Un_S:
+ instruction.OpCode = OpCodes.Bgt_Un;
+ break;
+ case Code.Ble_Un_S:
+ instruction.OpCode = OpCodes.Ble_Un;
+ break;
+ case Code.Blt_Un_S:
+ instruction.OpCode = OpCodes.Blt_Un;
+ break;
+ case Code.Leave_S:
+ instruction.OpCode = OpCodes.Leave;
+ break;
+ }
+ }
+ }
+
+ static void ExpandMacro (Instruction instruction, OpCode opcode, object operand)
+ {
+ instruction.OpCode = opcode;
+ instruction.Operand = operand;
+ }
+
+ static void MakeMacro (Instruction instruction, OpCode opcode)
+ {
+ instruction.OpCode = opcode;
+ instruction.Operand = null;
+ }
+
+ public static void OptimizeMacros (this MethodBody self)
+ {
+ if (self == null)
+ throw new ArgumentNullException ("self");
+
+ var method = self.Method;
+
+ foreach (var instruction in self.Instructions) {
+ int index;
+ switch (instruction.OpCode.Code) {
+ case Code.Ldarg:
+ index = ((ParameterDefinition) instruction.Operand).Index;
+ if (index == -1 && instruction.Operand == self.ThisParameter)
+ index = 0;
+ else if (method.HasThis)
+ index++;
+
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldarg_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldarg_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldarg_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldarg_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldarg_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Ldloc:
+ index = ((VariableDefinition) instruction.Operand).Index;
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldloc_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldloc_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldloc_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldloc_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldloc_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Stloc:
+ index = ((VariableDefinition) instruction.Operand).Index;
+ switch (index) {
+ case 0:
+ MakeMacro (instruction, OpCodes.Stloc_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Stloc_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Stloc_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Stloc_3);
+ break;
+ default:
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Stloc_S, instruction.Operand);
+ break;
+ }
+ break;
+ case Code.Ldarga:
+ index = ((ParameterDefinition) instruction.Operand).Index;
+ if (index == -1 && instruction.Operand == self.ThisParameter)
+ index = 0;
+ else if (method.HasThis)
+ index++;
+ if (index < 256)
+ ExpandMacro (instruction, OpCodes.Ldarga_S, instruction.Operand);
+ break;
+ case Code.Ldloca:
+ if (((VariableDefinition) instruction.Operand).Index < 256)
+ ExpandMacro (instruction, OpCodes.Ldloca_S, instruction.Operand);
+ break;
+ case Code.Ldc_I4:
+ int i = (int) instruction.Operand;
+ switch (i) {
+ case -1:
+ MakeMacro (instruction, OpCodes.Ldc_I4_M1);
+ break;
+ case 0:
+ MakeMacro (instruction, OpCodes.Ldc_I4_0);
+ break;
+ case 1:
+ MakeMacro (instruction, OpCodes.Ldc_I4_1);
+ break;
+ case 2:
+ MakeMacro (instruction, OpCodes.Ldc_I4_2);
+ break;
+ case 3:
+ MakeMacro (instruction, OpCodes.Ldc_I4_3);
+ break;
+ case 4:
+ MakeMacro (instruction, OpCodes.Ldc_I4_4);
+ break;
+ case 5:
+ MakeMacro (instruction, OpCodes.Ldc_I4_5);
+ break;
+ case 6:
+ MakeMacro (instruction, OpCodes.Ldc_I4_6);
+ break;
+ case 7:
+ MakeMacro (instruction, OpCodes.Ldc_I4_7);
+ break;
+ case 8:
+ MakeMacro (instruction, OpCodes.Ldc_I4_8);
+ break;
+ default:
+ if (i >= -128 && i < 128)
+ ExpandMacro (instruction, OpCodes.Ldc_I4_S, (sbyte) i);
+ break;
+ }
+ break;
+ }
+ }
+
+ OptimizeBranches (self);
+ }
+
+ static void OptimizeBranches (MethodBody body)
+ {
+ ComputeOffsets (body);
+
+ foreach (var instruction in body.Instructions) {
+ if (instruction.OpCode.OperandType != OperandType.InlineBrTarget)
+ continue;
+
+ if (OptimizeBranch (instruction))
+ ComputeOffsets (body);
+ }
+ }
+
+ static bool OptimizeBranch (Instruction instruction)
+ {
+ var offset = ((Instruction) instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4);
+ if (!(offset >= -128 && offset <= 127))
+ return false;
+
+ switch (instruction.OpCode.Code) {
+ case Code.Br:
+ instruction.OpCode = OpCodes.Br_S;
+ break;
+ case Code.Brfalse:
+ instruction.OpCode = OpCodes.Brfalse_S;
+ break;
+ case Code.Brtrue:
+ instruction.OpCode = OpCodes.Brtrue_S;
+ break;
+ case Code.Beq:
+ instruction.OpCode = OpCodes.Beq_S;
+ break;
+ case Code.Bge:
+ instruction.OpCode = OpCodes.Bge_S;
+ break;
+ case Code.Bgt:
+ instruction.OpCode = OpCodes.Bgt_S;
+ break;
+ case Code.Ble:
+ instruction.OpCode = OpCodes.Ble_S;
+ break;
+ case Code.Blt:
+ instruction.OpCode = OpCodes.Blt_S;
+ break;
+ case Code.Bne_Un:
+ instruction.OpCode = OpCodes.Bne_Un_S;
+ break;
+ case Code.Bge_Un:
+ instruction.OpCode = OpCodes.Bge_Un_S;
+ break;
+ case Code.Bgt_Un:
+ instruction.OpCode = OpCodes.Bgt_Un_S;
+ break;
+ case Code.Ble_Un:
+ instruction.OpCode = OpCodes.Ble_Un_S;
+ break;
+ case Code.Blt_Un:
+ instruction.OpCode = OpCodes.Blt_Un_S;
+ break;
+ case Code.Leave:
+ instruction.OpCode = OpCodes.Leave_S;
+ break;
+ }
+
+ return true;
+ }
+
+ static void ComputeOffsets (MethodBody body)
+ {
+ var offset = 0;
+ foreach (var instruction in body.Instructions) {
+ instruction.Offset = offset;
+ offset += instruction.GetSize ();
+ }
+ }
+
+ public static ParameterDefinition GetParameter (this MethodBody self, int index)
+ {
+ var method = self.Method;
+
+ if (method.HasThis) {
+ if (index == 0)
+ return self.ThisParameter;
+
+ index--;
+ }
+
+ var parameters = method.Parameters;
+
+ if (index < 0 || index >= parameters.Count)
+ return null;
+
+ return parameters [index];
+ }
+
+ public static bool Implements (this TypeReference self, string interfaceName)
+ {
+ if (interfaceName == null)
+ throw new ArgumentNullException ("interfaceName");
+ if (self == null)
+ return false;
+
+ TypeDefinition type = self.Resolve ();
+ if (type == null)
+ return false; // not enough information available
+
+ // special case, check if we implement ourselves
+ if (type.IsInterface && (type.FullName == interfaceName))
+ return true;
+
+ return Implements (type, interfaceName, (interfaceName.IndexOf ('`') >= 0));
+ }
+
+ public static bool Implements (TypeDefinition type, string interfaceName, bool generic)
+ {
+ while (type != null) {
+ // does the type implements it itself
+ if (type.HasInterfaces) {
+ foreach (TypeReference iface in type.Interfaces) {
+ string fullname = (generic) ? iface.GetElementType ().FullName : iface.FullName;
+ if (fullname == interfaceName)
+ return true;
+ //if not, then maybe one of its parent interfaces does
+ if (Implements (iface.Resolve (), interfaceName, generic))
+ return true;
+ }
+ }
+
+ type = type.BaseType != null ? type.BaseType.Resolve () : null;
+ }
+ return false;
+ }
+
+ public static bool Inherits (this TypeReference self, string className)
+ {
+ if (className == null)
+ throw new ArgumentNullException ("className");
+ if (self == null)
+ return false;
+
+ TypeReference current = self.Resolve ();
+ while (current != null) {
+ string fullname = current.FullName;
+ if (fullname == className)
+ return true;
+ if (fullname == "System.Object")
+ return false;
+
+ TypeDefinition td = current.Resolve ();
+ if (td == null)
+ return false; // could not resolve type
+ current = td.BaseType;
+ }
+ return false;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Mono.Tuner {
+
+ public class CustomizeActions : BaseStep {
+
+ readonly bool link_sdk_only;
+ readonly HashSet<string> skipped_assemblies;
+
+ public CustomizeActions (bool link_sdk_only, IEnumerable<string> skipped_assemblies)
+ {
+ this.link_sdk_only = link_sdk_only;
+ this.skipped_assemblies = new HashSet<string> (skipped_assemblies);
+ }
+
+ protected override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ if (IsSkipped (assembly)) {
+ ProcessUserAssembly (assembly);
+ return;
+ }
+
+ if (!link_sdk_only) {
+ if (!Annotations.HasAction (assembly)) // stray assembly not picked up when resolving references
+ Annotations.SetAction (assembly, AssemblyAction.Link);
+
+ return;
+ }
+
+ if (Profile.IsSdkAssembly (assembly) || Profile.IsProductAssembly (assembly)) {
+ Annotations.SetAction (assembly, AssemblyAction.Link);
+ return;
+ }
+
+ ProcessUserAssembly (assembly);
+ }
+
+ bool IsSkipped (AssemblyDefinition assembly)
+ {
+ return skipped_assemblies.Contains (assembly.Name.Name);
+ }
+
+ void ProcessUserAssembly (AssemblyDefinition assembly)
+ {
+ ResolveFromAssemblyStep.ProcessLibrary (Context, assembly);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ [Flags]
+ public enum SubStepTargets {
+ None = 0,
+
+ Assembly = 1,
+ Type = 2,
+ Field = 4,
+ Method = 8,
+ Property = 16,
+ Event = 32,
+ }
+
+ public interface ISubStep {
+
+ SubStepTargets Targets { get; }
+
+ void Initialize (LinkContext context);
+ bool IsActiveFor (AssemblyDefinition assembly);
+
+ void ProcessAssembly (AssemblyDefinition assembly);
+ void ProcessType (TypeDefinition type);
+ void ProcessField (FieldDefinition field);
+ void ProcessMethod (MethodDefinition method);
+ void ProcessProperty (PropertyDefinition property);
+ void ProcessEvent (EventDefinition @event);
+ }
+
+ public abstract class BaseSubStep : ISubStep {
+
+ protected LinkContext context;
+
+ public AnnotationStore Annotations {
+ get { return context.Annotations; }
+ }
+
+ public abstract SubStepTargets Targets { get; }
+
+ void ISubStep.Initialize (LinkContext context)
+ {
+ this.context = context;
+ }
+
+ public virtual bool IsActiveFor (AssemblyDefinition assembly)
+ {
+ return true;
+ }
+
+ public virtual void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ }
+
+ public virtual void ProcessType (TypeDefinition type)
+ {
+ }
+
+ public virtual void ProcessField (FieldDefinition field)
+ {
+ }
+
+ public virtual void ProcessMethod (MethodDefinition method)
+ {
+ }
+
+ public virtual void ProcessProperty (PropertyDefinition property)
+ {
+ }
+
+ public virtual void ProcessEvent (EventDefinition @event)
+ {
+ }
+ }
+
+ public class SubStepDispatcher : IStep, IEnumerable<ISubStep> {
+
+ List<ISubStep> substeps = new List<ISubStep> ();
+
+ List<ISubStep> on_assemblies;
+ List<ISubStep> on_types;
+ List<ISubStep> on_fields;
+ List<ISubStep> on_methods;
+ List<ISubStep> on_properties;
+ List<ISubStep> on_events;
+
+ public void Add (ISubStep substep)
+ {
+ substeps.Add (substep);
+ }
+
+ public void Process (LinkContext context)
+ {
+ InitializeSubSteps (context);
+
+ BrowseAssemblies (context.GetAssemblies ());
+ }
+
+ static bool HasSubSteps (List<ISubStep> substeps)
+ {
+ return substeps != null && substeps.Count > 0;
+ }
+
+ void BrowseAssemblies (IEnumerable<AssemblyDefinition> assemblies)
+ {
+ foreach (var assembly in assemblies) {
+ CategorizeSubSteps (assembly);
+
+ if (HasSubSteps (on_assemblies))
+ DispatchAssembly (assembly);
+
+ if (!ShouldDispatchTypes ())
+ continue;
+
+ BrowseTypes (assembly.MainModule.Types);
+ }
+ }
+
+ bool ShouldDispatchTypes ()
+ {
+ return HasSubSteps (on_types)
+ || HasSubSteps (on_fields)
+ || HasSubSteps (on_methods)
+ || HasSubSteps (on_properties)
+ || HasSubSteps (on_events);
+ }
+
+ void BrowseTypes (ICollection types)
+ {
+ foreach (TypeDefinition type in types) {
+ DispatchType (type);
+
+ if (type.HasFields && HasSubSteps (on_fields))
+ BrowseFields (type.Fields);
+
+ if (type.HasMethods && HasSubSteps (on_methods))
+ BrowseMethods (type.Methods);
+
+ if (type.HasProperties && HasSubSteps (on_properties))
+ BrowseProperties (type.Properties);
+
+ if (type.HasEvents && HasSubSteps (on_events))
+ BrowseEvents (type.Events);
+
+ if (type.HasNestedTypes)
+ BrowseTypes (type.NestedTypes);
+ }
+ }
+
+ void BrowseFields (ICollection fields)
+ {
+ foreach (FieldDefinition field in fields)
+ DispatchField (field);
+ }
+
+ void BrowseMethods (ICollection methods)
+ {
+ foreach (MethodDefinition method in methods)
+ DispatchMethod (method);
+ }
+
+ void BrowseProperties (ICollection properties)
+ {
+ foreach (PropertyDefinition property in properties)
+ DispatchProperty (property);
+ }
+
+ void BrowseEvents (ICollection events)
+ {
+ foreach (EventDefinition @event in events)
+ DispatchEvent (@event);
+ }
+
+ void DispatchAssembly (AssemblyDefinition assembly)
+ {
+ foreach (var substep in on_assemblies)
+ substep.ProcessAssembly (assembly);
+ }
+
+ void DispatchType (TypeDefinition type)
+ {
+ foreach (var substep in on_types)
+ substep.ProcessType (type);
+ }
+
+ void DispatchField (FieldDefinition field)
+ {
+ foreach (var substep in on_fields)
+ substep.ProcessField (field);
+ }
+
+ void DispatchMethod (MethodDefinition method)
+ {
+ foreach (var substep in on_methods)
+ substep.ProcessMethod (method);
+ }
+
+ void DispatchProperty (PropertyDefinition property)
+ {
+ foreach (var substep in on_properties)
+ substep.ProcessProperty (property);
+ }
+
+ void DispatchEvent (EventDefinition @event)
+ {
+ foreach (var substep in on_events)
+ substep.ProcessEvent (@event);
+ }
+
+ void InitializeSubSteps (LinkContext context)
+ {
+ foreach (var substep in substeps)
+ substep.Initialize (context);
+ }
+
+ void CategorizeSubSteps (AssemblyDefinition assembly)
+ {
+ on_assemblies = null;
+ on_types = null;
+ on_fields = null;
+ on_methods = null;
+ on_properties = null;
+ on_events = null;
+
+ foreach (var substep in substeps)
+ CategorizeSubStep (substep, assembly);
+ }
+
+ void CategorizeSubStep (ISubStep substep, AssemblyDefinition assembly)
+ {
+ if (!substep.IsActiveFor (assembly))
+ return;
+
+ CategorizeTarget (substep, SubStepTargets.Assembly, ref on_assemblies);
+ CategorizeTarget (substep, SubStepTargets.Type, ref on_types);
+ CategorizeTarget (substep, SubStepTargets.Field, ref on_fields);
+ CategorizeTarget (substep, SubStepTargets.Method, ref on_methods);
+ CategorizeTarget (substep, SubStepTargets.Property, ref on_properties);
+ CategorizeTarget (substep, SubStepTargets.Event, ref on_events);
+ }
+
+ static void CategorizeTarget (ISubStep substep, SubStepTargets target, ref List<ISubStep> list)
+ {
+ if (!Targets (substep, target))
+ return;
+
+ if (list == null)
+ list = new List<ISubStep> ();
+
+ list.Add (substep);
+ }
+
+ static bool Targets (ISubStep substep, SubStepTargets target)
+ {
+ return (substep.Targets & target) == target;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+
+ public IEnumerator<ISubStep> GetEnumerator ()
+ {
+ return substeps.GetEnumerator ();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+using Mono.Cecil;
+
+using Mono.Linker;
+
+namespace Mono.Tuner {
+
+ static class Extensions {
+
+ public static bool TryGetLinkedAssembly (this LinkContext context, string name, out AssemblyDefinition assembly)
+ {
+ assembly = GetAssembly (context, name);
+ if (assembly == null)
+ return false;
+
+ return context.Annotations.GetAction (assembly) == AssemblyAction.Link;
+ }
+
+ public static AssemblyDefinition GetAssembly (this LinkContext context, string assembly_name)
+ {
+ foreach (var assembly in context.GetAssemblies ())
+ if (assembly.Name.Name == assembly_name)
+ return assembly;
+
+ return null;
+ }
+ }
+}
--- /dev/null
+using System;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class FixModuleFlags : BaseStep {
+
+ protected override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ if (Annotations.GetAction (assembly) != AssemblyAction.Link)
+ return;
+
+ assembly.MainModule.Attributes = ModuleAttributes.ILOnly;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Mono.Tuner {
+
+ public class PreserveCrypto : IStep {
+
+ AnnotationStore annotations;
+
+ public void Process (LinkContext context)
+ {
+ annotations = context.Annotations;
+
+ ProcessCorlib (context);
+ ProcessSystemCore (context);
+ }
+
+ void ProcessCorlib (LinkContext context)
+ {
+ AssemblyDefinition corlib;
+ if (!context.TryGetLinkedAssembly ("mscorlib", out corlib))
+ return;
+
+ AddPreserveInfo (corlib, "DES", "DESCryptoServiceProvider");
+ AddPreserveInfo (corlib, "DSA", "DSACryptoServiceProvider");
+ AddPreserveInfo (corlib, "RandomNumberGenerator", "RNGCryptoServiceProvider");
+ AddPreserveInfo (corlib, "SHA1", "SHA1CryptoServiceProvider");
+ AddPreserveInfo (corlib, "SHA1", "SHA1Managed");
+ AddPreserveInfo (corlib, "MD5", "MD5CryptoServiceProvider");
+ AddPreserveInfo (corlib, "RC2", "RC2CryptoServiceProvider");
+ AddPreserveInfo (corlib, "TripleDES", "TripleDESCryptoServiceProvider");
+
+ AddPreserveInfo (corlib, "Rijndael", "RijndaelManaged");
+ AddPreserveInfo (corlib, "RIPEMD160", "RIPEMD160Managed");
+ AddPreserveInfo (corlib, "SHA256", "SHA256Managed");
+ AddPreserveInfo (corlib, "SHA384", "SHA384Managed");
+ AddPreserveInfo (corlib, "SHA512", "SHA512Managed");
+
+ AddPreserveInfo (corlib, "HMAC", "HMACMD5");
+ AddPreserveInfo (corlib, "HMAC", "HMACRIPEMD160");
+ AddPreserveInfo (corlib, "HMAC", "HMACSHA1");
+ AddPreserveInfo (corlib, "HMAC", "HMACSHA256");
+ AddPreserveInfo (corlib, "HMAC", "HMACSHA384");
+ AddPreserveInfo (corlib, "HMAC", "HMACSHA512");
+
+ AddPreserveInfo (corlib, "HMACMD5", "MD5CryptoServiceProvider");
+ AddPreserveInfo (corlib, "HMACRIPEMD160", "RIPEMD160Managed");
+ AddPreserveInfo (corlib, "HMACSHA1", "SHA1CryptoServiceProvider");
+ AddPreserveInfo (corlib, "HMACSHA1", "SHA1Managed");
+ AddPreserveInfo (corlib, "HMACSHA256", "SHA256Managed");
+ AddPreserveInfo (corlib, "HMACSHA384", "SHA384Managed");
+ AddPreserveInfo (corlib, "HMACSHA512", "SHA512Managed");
+
+ TryAddPreserveInfo (corlib, "Aes", "AesManaged");
+ }
+
+ void ProcessSystemCore (LinkContext context)
+ {
+ AssemblyDefinition syscore;
+ if (!context.TryGetLinkedAssembly ("System.Core", out syscore))
+ return;
+
+ // AddPreserveInfo (syscore, "Aes", "AesCryptoServiceProvider");
+ TryAddPreserveInfo (syscore, "Aes", "AesManaged");
+ }
+
+ bool TryAddPreserveInfo (AssemblyDefinition assembly, string name, string type)
+ {
+ var marker = GetCryptoType (assembly, name);
+ if (marker == null)
+ return false;
+
+ var implementation = GetCryptoType (assembly, type);
+ if (implementation == null)
+ return false;
+
+ Preserve (marker, implementation);
+ return true;
+ }
+
+ void AddPreserveInfo (AssemblyDefinition assembly, string name, string type)
+ {
+ var marker = GetCryptoType (assembly, name);
+ if (marker == null)
+ throw new ArgumentException (name);
+
+ var implementation = GetCryptoType (assembly, type);
+ if (implementation == null)
+ throw new ArgumentException (type);
+
+ Preserve (marker, implementation);
+ }
+
+ void Preserve (TypeDefinition marker, TypeDefinition implementation)
+ {
+ foreach (var constructor in implementation.GetConstructors ())
+ annotations.AddPreservedMethod (marker, constructor);
+ }
+
+ TypeDefinition GetCryptoType (AssemblyDefinition assembly, string name)
+ {
+ return assembly.MainModule.GetType ("System.Security.Cryptography." + name);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.IO;
+using System.Xml.XPath;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class PreserveHttps : BaseStep {
+
+ static string [] types = new [] {
+ "System.Net.WebRequest",
+ "System.Net.WebClient",
+ "System.Net.Security.RemoteCertificateValidationCallback",
+ "System.Web.Services.Protocols.WebClientProtocol",
+ "System.Security.Cryptography.X509Certificates.X509Certificate",
+ "System.Web.Services.WebServiceBindingAttribute",
+ "System.Web.Services.Protocols.SoapHttpClientProtocol",
+ };
+
+ bool need_https;
+
+ protected override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ if (need_https)
+ return;
+
+ if (Profile.IsSdkAssembly (assembly))
+ return;
+
+ if (HasNeededReference (assembly.MainModule))
+ need_https = true;
+ }
+
+ static bool HasNeededReference (ModuleDefinition module)
+ {
+ foreach (var type in types)
+ if (module.HasTypeReference (type))
+ return true;
+
+ return false;
+ }
+
+ protected override void EndProcess ()
+ {
+ if (!need_https)
+ return;
+
+ var mono_security = Context.Resolve ("Mono.Security");
+ if (mono_security == null)
+ return;
+
+ if (Annotations.GetAction (mono_security) != AssemblyAction.Link)
+ return;
+
+ var xml_preserve = CreatePreserveStep ();
+ Context.Pipeline.AddStepAfter (typeof (PreserveHttps), xml_preserve);
+// Context.Pipeline.AddStepAfter (xml_preserve, new PreserveCrypto ());
+ }
+
+ static IStep CreatePreserveStep ()
+ {
+ return new ResolveFromXmlStep (
+ new XPathDocument (
+ new StringReader (descriptor)));
+ }
+
+ const string descriptor = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+<linker>
+ <assembly fullname=""mscorlib"">
+ <namespace fullname=""System.Security.Cryptography"" />
+ </assembly>
+ <assembly fullname=""System"">
+ <namespace fullname=""System.Security.Cryptography"" />
+ </assembly>
+ <assembly fullname=""Mono.Security"">
+ <type fullname=""Mono.Security.Protocol.Tls.HttpsClientStream"" />
+ <type fullname=""Mono.Security.Protocol.Tls.SslClientStream"">
+ <method name=""get_SelectedClientCertificate"" />
+ </type>
+ <type fullname=""Mono.Security.Protocol.Tls.SslStreamBase"">
+ <method name=""get_ServerCertificate"" />
+ </type>
+ </assembly>
+</linker>
+";
+ }
+}
--- /dev/null
+using System;
+
+using Mono.Linker;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class PreserveSoapHttpClients : BaseSubStep {
+
+ public override SubStepTargets Targets {
+ get { return SubStepTargets.Type; }
+ }
+
+ public override bool IsActiveFor (AssemblyDefinition assembly)
+ {
+ return Annotations.GetAction (assembly) == AssemblyAction.Link && !Profile.IsSdkAssembly (assembly);
+ }
+
+ public override void ProcessType (TypeDefinition type)
+ {
+ if (IsWebServiceClient (type))
+ PreserveClient (type);
+ }
+
+ void PreserveClient (TypeDefinition type)
+ {
+ if (!type.HasMethods)
+ return;
+
+ foreach (MethodDefinition method in type.Methods) {
+ string sync_method;
+ if (!TryExtractSyncMethod (method, out sync_method))
+ continue;
+
+ AddPreservedMethod (method, sync_method);
+ }
+ }
+
+ void AddPreservedMethod (MethodDefinition target, string methodName)
+ {
+ foreach (MethodDefinition method in target.DeclaringType.Methods)
+ if (method.Name == methodName)
+ Annotations.AddPreservedMethod (target, method);
+ }
+
+ static bool TryExtractSyncMethod (MethodDefinition method, out string sync_method)
+ {
+ if (TryExtractPrefixedMethodName ("Begin", method.Name, out sync_method))
+ return true;
+
+ if (TryExtractPrefixedMethodName ("End", method.Name, out sync_method))
+ return true;
+
+ if (TryExtractSuffixedMethodName ("Async", method.Name, out sync_method))
+ return true;
+
+ return false;
+ }
+
+ static bool TryExtractPrefixedMethodName (string prefix, string fullName, out string methodName)
+ {
+ methodName = null;
+
+ int pos = fullName.IndexOf (prefix);
+ if (pos == -1)
+ return false;
+
+ methodName = fullName.Substring (prefix.Length);
+ return true;
+ }
+
+ static bool TryExtractSuffixedMethodName (string suffix, string fullName, out string methodName)
+ {
+ methodName = null;
+
+ int pos = fullName.LastIndexOf (suffix);
+ if (pos == -1)
+ return false;
+
+ methodName = fullName.Substring (0, pos);
+ return true;
+ }
+
+ static bool IsWebServiceClient (TypeDefinition type)
+ {
+ return type.Inherits ("System.Web.Services.Protocols.SoapHttpClientProtocol");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+//
+// PrintTypeMap.cs
+//
+// Author:
+// Jb Evain (jbevain@novell.com)
+//
+// (C) 2009 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class PrintTypeMap : BaseStep {
+
+ protected override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ foreach (TypeDefinition type in assembly.MainModule.GetAllTypes ())
+ PrintMap (type);
+ }
+
+ void PrintMap (TypeDefinition type)
+ {
+ if (!type.HasMethods)
+ return;
+
+ Console.WriteLine ("Type {0} map", type);
+
+ foreach (MethodDefinition method in type.Methods) {
+ if (!method.IsVirtual)
+ continue;
+
+ Console.WriteLine (" Method {0} map", method);
+
+ IEnumerable<MethodDefinition> overrides = Annotations.GetOverrides (method);
+ foreach (var @override in overrides ?? new MethodDefinition [0])
+ Console.WriteLine (" HasOverride {0}", @override);
+
+ IEnumerable<MethodDefinition> bases = Annotations.GetBaseMethods (method);
+ foreach (var @base in bases ?? new MethodDefinition [0])
+ Console.WriteLine (" Base {0}", @base);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ abstract class Profile {
+
+ static Profile current;
+
+ static Profile Current {
+ get {
+ if (current != null)
+ return current;
+
+ current = CreateProfile ("MonoTouch");
+ if (current != null)
+ return current;
+
+ current = CreateProfile ("MonoDroid");
+ if (current != null)
+ return current;
+
+ current = CreateProfile ("MonoMac");
+ if (current != null)
+ return current;
+
+ throw new NotSupportedException ("No active profile");
+ }
+ }
+
+ static Profile CreateProfile (string name)
+ {
+ var type = Type.GetType (string.Format ("{0}.Tuner.{0}Profile", name));
+ if (type == null)
+ return null;
+
+ return (Profile) Activator.CreateInstance (type);
+ }
+
+ public static bool IsSdkAssembly (AssemblyDefinition assembly)
+ {
+ return Current.IsSdk (assembly);
+ }
+
+ public static bool IsProductAssembly (AssemblyDefinition assembly)
+ {
+ return Current.IsProduct (assembly);
+ }
+
+ protected abstract bool IsSdk (AssemblyDefinition assembly);
+ protected abstract bool IsProduct (AssemblyDefinition assembly);
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Tuner;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public abstract class RemoveAttributesBase : BaseSubStep {
+
+ public override SubStepTargets Targets {
+ get {
+ return SubStepTargets.Assembly
+ | SubStepTargets.Type
+ | SubStepTargets.Field
+ | SubStepTargets.Method
+ | SubStepTargets.Property
+ | SubStepTargets.Event;
+ }
+ }
+
+ public override bool IsActiveFor (AssemblyDefinition assembly)
+ {
+ return Annotations.GetAction (assembly) == AssemblyAction.Link;
+ }
+
+ public override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ ProcessAttributeProvider (assembly);
+ ProcessAttributeProvider (assembly.MainModule);
+ }
+
+ public override void ProcessType (TypeDefinition type)
+ {
+ ProcessAttributeProvider (type);
+
+ if (type.HasGenericParameters)
+ ProcessAttributeProviderCollection (type.GenericParameters);
+ }
+
+ void ProcessAttributeProviderCollection (IList list)
+ {
+ for (int i = 0; i < list.Count; i++)
+ ProcessAttributeProvider ((ICustomAttributeProvider) list [i]);
+ }
+
+ public override void ProcessField (FieldDefinition field)
+ {
+ ProcessAttributeProvider (field);
+ }
+
+ public override void ProcessMethod (MethodDefinition method)
+ {
+ ProcessMethodAttributeProvider (method);
+ }
+
+ void ProcessMethodAttributeProvider (MethodDefinition method)
+ {
+ ProcessAttributeProvider (method);
+ ProcessAttributeProvider (method.MethodReturnType);
+
+ if (method.HasParameters)
+ ProcessAttributeProviderCollection (method.Parameters);
+
+ if (method.HasGenericParameters)
+ ProcessAttributeProviderCollection (method.GenericParameters);
+ }
+
+ public override void ProcessProperty (PropertyDefinition property)
+ {
+ ProcessAttributeProvider (property);
+ }
+
+ public override void ProcessEvent (EventDefinition @event)
+ {
+ ProcessAttributeProvider (@event);
+ }
+
+ void ProcessAttributeProvider (ICustomAttributeProvider provider)
+ {
+ if (!provider.HasCustomAttributes)
+ return;
+
+ for (int i = 0; i < provider.CustomAttributes.Count; i++) {
+ if (!IsRemovedAttribute (provider.CustomAttributes [i]))
+ continue;
+
+ provider.CustomAttributes.RemoveAt (i--);
+ }
+ }
+
+ protected abstract bool IsRemovedAttribute (CustomAttribute attribute);
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class RemoveResources : IStep {
+
+ I18nAssemblies assemblies;
+
+ public RemoveResources (I18nAssemblies assemblies)
+ {
+ this.assemblies = assemblies;
+ }
+
+ public void Process (LinkContext context)
+ {
+ AssemblyDefinition assembly;
+ if (!context.TryGetLinkedAssembly ("mscorlib", out assembly))
+ return;
+
+ var resources = assembly.MainModule.Resources;
+
+ for (int i = 0; i < resources.Count; i++) {
+ var resource = resources [i] as EmbeddedResource;
+ if (resource == null)
+ continue;
+
+ switch (resource.Name) {
+ case "collation.core.bin":
+ case "collation.tailoring.bin":
+ continue;
+ default:
+ if (!resource.Name.Contains ("cjk"))
+ continue;
+ if (IncludeCJK ())
+ continue;
+
+ resources.RemoveAt (i--);
+ break;
+ }
+ }
+ }
+
+ bool IncludeCJK ()
+ {
+ return (assemblies & I18nAssemblies.CJK) != 0;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Linker;
+using Mono.Linker.Steps;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public class RemoveSecurity : BaseSubStep {
+
+ public override SubStepTargets Targets {
+ get {
+ return SubStepTargets.Assembly
+ | SubStepTargets.Type
+ | SubStepTargets.Method;
+ }
+ }
+
+ public override bool IsActiveFor (AssemblyDefinition assembly)
+ {
+ return Annotations.GetAction (assembly) == AssemblyAction.Link;
+ }
+
+ public override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ ProcessSecurityProvider (assembly);
+ }
+
+ public override void ProcessType (TypeDefinition type)
+ {
+ ProcessSecurityProvider (type);
+ }
+
+ public override void ProcessMethod (MethodDefinition method)
+ {
+ ProcessSecurityProvider (method);
+ }
+
+ static void ProcessSecurityProvider (ISecurityDeclarationProvider provider)
+ {
+ if (!provider.HasSecurityDeclarations)
+ return;
+
+ provider.SecurityDeclarations.Clear ();
+ }
+ }
+}