diff --git a/Configuration.props b/Configuration.props
index 46fbf558151..5c4a2f321fe 100644
--- a/Configuration.props
+++ b/Configuration.props
@@ -113,7 +113,6 @@
$(MonoRequiredMinimumVersion)
False
True
- $(MSBuildThisFileDirectory)external\mono\sdks\out\android-sources\external\linker\src
$(MSBuildThisFileDirectory)external\opentk
\usr
$(HostHomebrewPrefix)\opt\mingw-zlib\usr
@@ -165,7 +164,6 @@
$([System.IO.Path]::GetFullPath ('$(AndroidSdkDirectory)'))
$([System.IO.Path]::GetFullPath ('$(JavaInteropSourceDirectory)'))
$([System.IO.Path]::GetFullPath ('$(MonoSourceDirectory)'))
- $([System.IO.Path]::GetFullPath ('$(LinkerSourceDirectory)'))
$([System.IO.Path]::GetFullPath ('$(SqliteSourceDirectory)'))
$([System.IO.Path]::GetFullPath ('$(OpenTKSourceDirectory)'))
diff --git a/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj b/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
index aa8694c7a3c..bee005cab0c 100644
--- a/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
+++ b/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
@@ -13,32 +13,26 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/Microsoft.Android.Sdk.ILLink/SetupStep.cs b/src/Microsoft.Android.Sdk.ILLink/SetupStep.cs
index c8f56b575be..53ee2f3017f 100644
--- a/src/Microsoft.Android.Sdk.ILLink/SetupStep.cs
+++ b/src/Microsoft.Android.Sdk.ILLink/SetupStep.cs
@@ -5,7 +5,6 @@
using Mono.Cecil;
using Mono.Linker;
using Mono.Linker.Steps;
-using Mono.Tuner;
using MonoDroid.Tuner;
namespace Microsoft.Android.Sdk.ILLink
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs
new file mode 100644
index 00000000000..39210adc9ee
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs
@@ -0,0 +1,83 @@
+//
+// BaseStep.cs
+//
+// Author:
+// Jb Evain (jbevain@novell.com)
+//
+// (C) 2007 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 Mono.Cecil;
+
+namespace Mono.Linker.Steps {
+
+ public abstract class BaseStep : IStep {
+
+ private LinkContext _context;
+
+ public LinkContext Context {
+ get { return _context; }
+ }
+
+ public AnnotationStore Annotations {
+ get { return _context.Annotations; }
+ }
+
+ public Tracer Tracer {
+ get { return _context.Tracer; }
+ }
+
+ public MarkingHelpers MarkingHelpers => _context.MarkingHelpers;
+
+ public void Process (LinkContext context)
+ {
+ _context = context;
+
+ if (!ConditionToProcess ())
+ return;
+
+ Process ();
+
+ foreach (AssemblyDefinition assembly in context.GetAssemblies ())
+ ProcessAssembly (assembly);
+
+ EndProcess ();
+ }
+
+ protected virtual bool ConditionToProcess ()
+ {
+ return true;
+ }
+
+ protected virtual void Process ()
+ {
+ }
+
+ protected virtual void EndProcess ()
+ {
+ }
+
+ protected virtual void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/IStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/IStep.cs
new file mode 100644
index 00000000000..c01ef1e6b3f
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/IStep.cs
@@ -0,0 +1,34 @@
+//
+// IStep.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// (C) 2006 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.
+//
+
+namespace Mono.Linker.Steps {
+
+ public interface IStep {
+ void Process (LinkContext context);
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Annotations.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Annotations.cs
new file mode 100644
index 00000000000..95bc5eb5b15
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Annotations.cs
@@ -0,0 +1,452 @@
+//
+// Annotations.cs
+//
+// Author:
+// Jb Evain (jbevain@novell.com)
+//
+// (C) 2007 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.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Mono.Linker {
+
+ public partial class AnnotationStore {
+
+ protected readonly LinkContext context;
+
+ protected readonly Dictionary assembly_actions = new Dictionary ();
+ protected readonly Dictionary method_actions = new Dictionary ();
+ protected readonly Dictionary method_stub_values = new Dictionary ();
+ protected readonly Dictionary field_values = new Dictionary ();
+ protected readonly HashSet field_init = new HashSet ();
+ protected readonly HashSet fieldType_init = new HashSet ();
+ protected readonly HashSet marked = new HashSet ();
+ protected readonly HashSet processed = new HashSet ();
+ protected readonly Dictionary preserved_types = new Dictionary ();
+ protected readonly Dictionary> preserved_methods = new Dictionary> ();
+ protected readonly HashSet public_api = new HashSet ();
+ protected readonly Dictionary> override_methods = new Dictionary> ();
+ protected readonly Dictionary> base_methods = new Dictionary> ();
+ protected readonly Dictionary symbol_readers = new Dictionary ();
+ protected readonly Dictionary> class_type_base_hierarchy = new Dictionary> ();
+ protected readonly Dictionary> derived_interfaces = new Dictionary>();
+
+ protected readonly Dictionary> custom_annotations = new Dictionary> ();
+ protected readonly Dictionary> resources_to_remove = new Dictionary> ();
+ protected readonly HashSet marked_attributes = new HashSet ();
+ readonly HashSet marked_types_with_cctor = new HashSet ();
+ protected readonly HashSet marked_instantiated = new HashSet ();
+ protected readonly HashSet indirectly_called = new HashSet();
+
+
+ public AnnotationStore (LinkContext context) => this.context = context;
+
+ public bool ProcessSatelliteAssemblies { get; set; }
+
+ protected Tracer Tracer {
+ get {
+ return context.Tracer;
+ }
+ }
+
+ public ICollection GetAssemblies ()
+ {
+ return assembly_actions.Keys;
+ }
+
+ public AssemblyAction GetAction (AssemblyDefinition assembly)
+ {
+ AssemblyAction action;
+ if (assembly_actions.TryGetValue (assembly, out action))
+ return action;
+
+ throw new InvalidOperationException($"No action for the assembly {assembly.Name} defined");
+ }
+
+ public MethodAction GetAction (MethodDefinition method)
+ {
+ MethodAction action;
+ if (method_actions.TryGetValue (method, out action))
+ return action;
+
+ return MethodAction.Nothing;
+ }
+
+ public void SetAction (AssemblyDefinition assembly, AssemblyAction action)
+ {
+ assembly_actions [assembly] = action;
+ }
+
+ public bool HasAction (AssemblyDefinition assembly)
+ {
+ return assembly_actions.ContainsKey (assembly);
+ }
+
+ public void SetAction (MethodDefinition method, MethodAction action)
+ {
+ method_actions [method] = action;
+ }
+
+ public void SetMethodStubValue (MethodDefinition method, object value)
+ {
+ method_stub_values [method] = value;
+ }
+
+ public void SetFieldValue (FieldDefinition field, object value)
+ {
+ field_values [field] = value;
+ }
+
+ public void SetSubstitutedInit (FieldDefinition field)
+ {
+ field_init.Add (field);
+ }
+
+ public bool HasSubstitutedInit (FieldDefinition field)
+ {
+ return field_init.Contains (field);
+ }
+
+ public void SetSubstitutedInit (TypeDefinition type)
+ {
+ fieldType_init.Add (type);
+ }
+
+ public bool HasSubstitutedInit (TypeDefinition type)
+ {
+ return fieldType_init.Contains (type);
+ }
+
+ public void Mark (IMetadataTokenProvider provider)
+ {
+ marked.Add (provider);
+ Tracer.AddDependency (provider, true);
+ }
+
+ public void Mark (CustomAttribute attribute)
+ {
+ marked_attributes.Add (attribute);
+ }
+
+ public void MarkAndPush (IMetadataTokenProvider provider)
+ {
+ Mark (provider);
+ Tracer.Push (provider, false);
+ }
+
+ public bool IsMarked (IMetadataTokenProvider provider)
+ {
+ return marked.Contains (provider);
+ }
+
+ public bool IsMarked (CustomAttribute attribute)
+ {
+ return marked_attributes.Contains (attribute);
+ }
+
+ public void MarkIndirectlyCalledMethod (MethodDefinition method)
+ {
+ if (!context.AddReflectionAnnotations)
+ return;
+
+ indirectly_called.Add (method);
+ }
+
+ public bool HasMarkedAnyIndirectlyCalledMethods ()
+ {
+ return indirectly_called.Count != 0;
+ }
+
+ public bool IsIndirectlyCalled (MethodDefinition method)
+ {
+ return indirectly_called.Contains (method);
+ }
+
+ public void MarkInstantiated (TypeDefinition type)
+ {
+ marked_instantiated.Add (type);
+ }
+
+ public bool IsInstantiated (TypeDefinition type)
+ {
+ return marked_instantiated.Contains (type);
+ }
+
+ public void Processed (IMetadataTokenProvider provider)
+ {
+ processed.Add (provider);
+ }
+
+ public bool IsProcessed (IMetadataTokenProvider provider)
+ {
+ return processed.Contains (provider);
+ }
+
+ public bool IsPreserved (TypeDefinition type)
+ {
+ return preserved_types.ContainsKey (type);
+ }
+
+ public void SetPreserve (TypeDefinition type, TypePreserve preserve)
+ {
+ TypePreserve existing;
+ if (preserved_types.TryGetValue (type, out existing))
+ preserved_types [type] = ChoosePreserveActionWhichPreservesTheMost (existing, preserve);
+ else
+ preserved_types.Add (type, preserve);
+ }
+
+ public static TypePreserve ChoosePreserveActionWhichPreservesTheMost (TypePreserve leftPreserveAction, TypePreserve rightPreserveAction)
+ {
+ if (leftPreserveAction == rightPreserveAction)
+ return leftPreserveAction;
+
+ if (leftPreserveAction == TypePreserve.All || rightPreserveAction == TypePreserve.All)
+ return TypePreserve.All;
+
+ if (leftPreserveAction == TypePreserve.Nothing)
+ return rightPreserveAction;
+
+ if (rightPreserveAction == TypePreserve.Nothing)
+ return leftPreserveAction;
+
+ if ((leftPreserveAction == TypePreserve.Methods && rightPreserveAction == TypePreserve.Fields) ||
+ (leftPreserveAction == TypePreserve.Fields && rightPreserveAction == TypePreserve.Methods))
+ return TypePreserve.All;
+
+ return rightPreserveAction;
+ }
+
+ public TypePreserve GetPreserve (TypeDefinition type)
+ {
+ TypePreserve preserve;
+ if (preserved_types.TryGetValue (type, out preserve))
+ return preserve;
+
+ throw new NotSupportedException ($"No type preserve information for `{type}`");
+ }
+
+ public bool TryGetPreserve (TypeDefinition type, out TypePreserve preserve)
+ {
+ return preserved_types.TryGetValue (type, out preserve);
+ }
+
+ public bool TryGetMethodStubValue (MethodDefinition method, out object value)
+ {
+ return method_stub_values.TryGetValue (method, out value);
+ }
+
+ public bool TryGetFieldUserValue (FieldDefinition field, out object value)
+ {
+ return field_values.TryGetValue (field, out value);
+ }
+
+ public HashSet GetResourcesToRemove (AssemblyDefinition assembly)
+ {
+ HashSet resources;
+ if (resources_to_remove.TryGetValue (assembly, out resources))
+ return resources;
+
+ return null;
+ }
+
+ public void AddResourceToRemove (AssemblyDefinition assembly, string name)
+ {
+ HashSet resources;
+ if (!resources_to_remove.TryGetValue (assembly, out resources)) {
+ resources = resources_to_remove [assembly] = new HashSet ();
+ }
+
+ resources.Add (name);
+ }
+
+ public void SetPublic (IMetadataTokenProvider provider)
+ {
+ public_api.Add (provider);
+ }
+
+ public bool IsPublic (IMetadataTokenProvider provider)
+ {
+ return public_api.Contains (provider);
+ }
+
+ public void AddOverride (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null)
+ {
+ var methods = GetOverrides (@base);
+ if (methods == null) {
+ methods = new List ();
+ override_methods [@base] = methods;
+ }
+
+ methods.Add (new OverrideInformation (@base, @override, matchingInterfaceImplementation));
+ }
+
+ public List GetOverrides (MethodDefinition method)
+ {
+ List overrides;
+ if (override_methods.TryGetValue (method, out overrides))
+ return overrides;
+
+ return null;
+ }
+
+ public void AddBaseMethod (MethodDefinition method, MethodDefinition @base)
+ {
+ var methods = GetBaseMethods (method);
+ if (methods == null) {
+ methods = new List ();
+ base_methods [method] = methods;
+ }
+
+ methods.Add (@base);
+ }
+
+ public List GetBaseMethods (MethodDefinition method)
+ {
+ List bases;
+ if (base_methods.TryGetValue (method, out bases))
+ return bases;
+
+ return null;
+ }
+
+ public List GetPreservedMethods (TypeDefinition type)
+ {
+ return GetPreservedMethods (type as IMemberDefinition);
+ }
+
+ public void AddPreservedMethod (TypeDefinition type, MethodDefinition method)
+ {
+ AddPreservedMethod (type as IMemberDefinition, method);
+ }
+
+ public List GetPreservedMethods (MethodDefinition method)
+ {
+ return GetPreservedMethods (method as IMemberDefinition);
+ }
+
+ public void AddPreservedMethod (MethodDefinition key, MethodDefinition method)
+ {
+ AddPreservedMethod (key as IMemberDefinition, method);
+ }
+
+ List GetPreservedMethods (IMemberDefinition definition)
+ {
+ List preserved;
+ if (preserved_methods.TryGetValue (definition, out preserved))
+ return preserved;
+
+ return null;
+ }
+
+ void AddPreservedMethod (IMemberDefinition definition, MethodDefinition method)
+ {
+ var methods = GetPreservedMethods (definition);
+ if (methods == null) {
+ methods = new List ();
+ preserved_methods [definition] = methods;
+ }
+
+ methods.Add (method);
+ }
+
+ public void AddSymbolReader (AssemblyDefinition assembly, ISymbolReader symbolReader)
+ {
+ symbol_readers [assembly] = symbolReader;
+ }
+
+ public void CloseSymbolReader (AssemblyDefinition assembly)
+ {
+ ISymbolReader symbolReader;
+ if (!symbol_readers.TryGetValue (assembly, out symbolReader))
+ return;
+
+ symbol_readers.Remove (assembly);
+ symbolReader.Dispose ();
+ }
+
+ public Dictionary GetCustomAnnotations (object key)
+ {
+ Dictionary slots;
+ if (custom_annotations.TryGetValue (key, out slots))
+ return slots;
+
+ slots = new Dictionary ();
+ custom_annotations.Add (key, slots);
+ return slots;
+ }
+
+ public bool HasPreservedStaticCtor (TypeDefinition type)
+ {
+ return marked_types_with_cctor.Contains (type);
+ }
+
+ public bool SetPreservedStaticCtor (TypeDefinition type)
+ {
+ return marked_types_with_cctor.Add (type);
+ }
+
+ public void SetClassHierarchy (TypeDefinition type, List bases)
+ {
+ class_type_base_hierarchy [type] = bases;
+ }
+
+ public List GetClassHierarchy (TypeDefinition type)
+ {
+ if (class_type_base_hierarchy.TryGetValue (type, out List bases))
+ return bases;
+
+ return null;
+ }
+
+ public void AddDerivedInterfaceForInterface (TypeDefinition @base, TypeDefinition derived)
+ {
+ if (!@base.IsInterface)
+ throw new ArgumentException ($"{nameof (@base)} must be an interface");
+
+ if (!derived.IsInterface)
+ throw new ArgumentException ($"{nameof (derived)} must be an interface");
+
+ List derivedInterfaces;
+ if (!derived_interfaces.TryGetValue (@base, out derivedInterfaces))
+ derived_interfaces [@base] = derivedInterfaces = new List ();
+
+ derivedInterfaces.Add(derived);
+ }
+
+ public List GetDerivedInterfacesForInterface (TypeDefinition @interface)
+ {
+ if (!@interface.IsInterface)
+ throw new ArgumentException ($"{nameof (@interface)} must be an interface");
+
+ List derivedInterfaces;
+ if (derived_interfaces.TryGetValue (@interface, out derivedInterfaces))
+ return derivedInterfaces;
+
+ return null;
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyAction.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyAction.cs
new file mode 100644
index 00000000000..341339cd159
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyAction.cs
@@ -0,0 +1,55 @@
+//
+// AssemblyAction.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// (C) 2006 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.
+//
+
+namespace Mono.Linker {
+
+ public enum AssemblyAction {
+ // Ignore the assembly
+ Skip,
+ // Copy the existing files, assembly and symbols, into the output destination. E.g. .dll and .mdb
+ // The linker still analyzes the assemblies (to know what they require) but does not modify them.
+ Copy,
+ // Copy the existing files, assembly and symbols, into the output destination if and only if
+ // anything from the assembly is used.
+ // The linker still analyzes the assemblies (to know what they require) but does not modify them.
+ CopyUsed,
+ // Link the assembly
+ Link,
+ // Remove the assembly from the output
+ Delete,
+ // Save the assembly/symbols in memory without linking it.
+ // E.g. useful to remove unneeded assembly references (as done in SweepStep),
+ // resolving [TypeForwardedTo] attributes (like PCL) to their final location
+ Save,
+ // Keep all types, methods, and fields but add System.Runtime.BypassNGenAttribute to unmarked methods.
+ AddBypassNGen,
+ // Keep all types, methods, and fields in marked assemblies but add System.Runtime.BypassNGenAttribute to unmarked methods.
+ // Delete unmarked assemblies.
+ AddBypassNGenUsed
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyResolver.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyResolver.cs
new file mode 100644
index 00000000000..143a7559f1b
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/AssemblyResolver.cs
@@ -0,0 +1,157 @@
+//
+// AssemblyResolver.cs
+//
+// Author:
+// Jb Evain (jbevain@novell.com)
+//
+// (C) 2007 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.Generic;
+using System.IO;
+using Mono.Cecil;
+using Mono.Collections.Generic;
+
+namespace Mono.Linker {
+
+#if FEATURE_ILLINK
+ public class AssemblyResolver : DirectoryAssemblyResolver {
+#else
+ public class AssemblyResolver : BaseAssemblyResolver {
+#endif
+
+ readonly Dictionary _assemblies;
+ HashSet _unresolvedAssemblies;
+ bool _ignoreUnresolved;
+ LinkContext _context;
+ readonly Collection _references;
+
+
+ public IDictionary AssemblyCache {
+ get { return _assemblies; }
+ }
+
+ public AssemblyResolver ()
+ : this (new Dictionary (StringComparer.OrdinalIgnoreCase))
+ {
+ }
+
+ public AssemblyResolver (Dictionary assembly_cache)
+ {
+ _assemblies = assembly_cache;
+ _references = new Collection () { };
+ }
+
+ public bool IgnoreUnresolved {
+ get { return _ignoreUnresolved; }
+ set { _ignoreUnresolved = value; }
+ }
+
+ public LinkContext Context {
+ get { return _context; }
+ set { _context = value; }
+ }
+
+#if !FEATURE_ILLINK
+ // The base class's definition of GetAssembly is visible when using DirectoryAssemblyResolver.
+ AssemblyDefinition GetAssembly (string file, ReaderParameters parameters)
+ {
+ if (parameters.AssemblyResolver == null)
+ parameters.AssemblyResolver = this;
+
+ return ModuleDefinition.ReadModule (file, parameters).Assembly;
+ }
+#endif
+
+ AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection references, ReaderParameters parameters)
+ {
+ var fileName = name.Name + ".dll";
+ foreach (var reference in references) {
+ if (Path.GetFileName (reference) != fileName)
+ continue;
+ try {
+ return GetAssembly (reference, parameters);
+ } catch (BadImageFormatException) {
+ continue;
+ }
+ }
+
+ return null;
+ }
+
+ public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
+ {
+ // Validate arguments, similarly to how the base class does it.
+ if (name == null)
+ throw new ArgumentNullException ("name");
+ if (parameters == null)
+ throw new ArgumentNullException ("parameters");
+
+ AssemblyDefinition asm = null;
+ if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) {
+ try {
+ // Any full path explicit reference takes precedence over other look up logic
+ asm = ResolveFromReferences (name, _references, parameters);
+
+ // Fall back to the base class resolution logic
+ if (asm == null)
+ asm = base.Resolve (name, parameters);
+
+ _assemblies [name.Name] = asm;
+ } catch (AssemblyResolutionException) {
+ if (!_ignoreUnresolved)
+ throw;
+ _context.LogMessage ($"warning: Ignoring unresolved assembly '{name.Name}'.");
+ if (_unresolvedAssemblies == null)
+ _unresolvedAssemblies = new HashSet ();
+ _unresolvedAssemblies.Add (name.Name);
+ }
+ }
+
+ return asm;
+ }
+
+ public virtual AssemblyDefinition CacheAssembly (AssemblyDefinition assembly)
+ {
+ _assemblies [assembly.Name.Name] = assembly;
+ base.AddSearchDirectory (Path.GetDirectoryName (assembly.MainModule.FileName));
+ return assembly;
+ }
+
+ public void AddReferenceAssembly (string referencePath)
+ {
+ _references.Add (referencePath);
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ foreach (var asm in _assemblies.Values) {
+ asm.Dispose ();
+ }
+
+ _assemblies.Clear ();
+ if (_unresolvedAssemblies != null)
+ _unresolvedAssemblies.Clear ();
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ConsoleLogger.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ConsoleLogger.cs
new file mode 100644
index 00000000000..f7059f2b89f
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ConsoleLogger.cs
@@ -0,0 +1,11 @@
+using System;
+namespace Mono.Linker
+{
+ public class ConsoleLogger : ILogger
+ {
+ public void LogMessage (MessageImportance importance, string message, params object[] values)
+ {
+ Console.WriteLine (message, values);
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IDependencyRecorder.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IDependencyRecorder.cs
new file mode 100644
index 00000000000..de4e4616e94
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IDependencyRecorder.cs
@@ -0,0 +1,44 @@
+//
+// IDependencyRecorder.cs
+//
+// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com)
+//
+// 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.
+//
+
+namespace Mono.Linker
+{
+ ///
+ /// Abstraction exposed by the linker (mostly MarkStep, but not only) - it will call this interface
+ /// every time it finds a dependency between two parts of the dependency graph.
+ ///
+ public interface IDependencyRecorder
+ {
+ ///
+ /// Reports a dependency detected by the linker.
+ ///
+ /// The source of the dependency (for example the caller method).
+ /// The target of the dependency (for example the callee method).
+ /// true if the target is also marked by the MarkStep.
+ /// The source and target are typically Cecil metadata objects (MethodDefinition, TypeDefinition, ...)
+ /// but they can also be the linker steps or really any other object.
+ void RecordDependency (object source, object target, bool marked);
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ILogger.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ILogger.cs
new file mode 100644
index 00000000000..d4f610fbb53
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/ILogger.cs
@@ -0,0 +1,15 @@
+using System;
+namespace Mono.Linker
+{
+ public enum MessageImportance
+ {
+ High,
+ Low,
+ Normal,
+ }
+
+ public interface ILogger
+ {
+ void LogMessage (MessageImportance importance, string message, params object[] values);
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IReflectionPatternRecorder.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IReflectionPatternRecorder.cs
new file mode 100644
index 00000000000..b3aae2b2ea7
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/IReflectionPatternRecorder.cs
@@ -0,0 +1,62 @@
+//
+// IReflectionPatternRecorder.cs
+//
+// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com)
+//
+// 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 Mono.Cecil;
+
+namespace Mono.Linker
+{
+ ///
+ /// Interface which is called every time the linker inspects a pattern of code involving reflection to determine a more complex
+ /// dependency.
+ ///
+ ///
+ /// The rules are such that if a given callsite of a "reflectionMethod" gets examined
+ /// linker will always report it one way or another:
+ /// - it will either call RecognizedReflectionAccessPattern method when it can figure out exactly the dependency.
+ /// - or it will call UnrecognizedReflectionAccessPattern with an optional message describing why it could not recognize
+ /// the pattern.
+ ///
+ public interface IReflectionPatternRecorder
+ {
+ ///
+ /// Called when the linker recognized a reflection access pattern (and thus was able to correctly apply marking to the accessed item).
+ ///
+ /// The method which contains the reflection access pattern.
+ /// The reflection method which is at the heart of the access pattern.
+ /// The item accessed through reflection. This can be one of:
+ /// TypeDefinition, MethodDefinition, PropertyDefinition, FieldDefinition, EventDefinition.
+ void RecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, IMemberDefinition accessedItem);
+
+ ///
+ /// Called when the linker detected a reflection access but was not able to recognize the entire pattern.
+ ///
+ /// The method which contains the reflection access code.
+ /// The reflection method which is at the heart of the access code.
+ /// Humanly readable message describing what failed during the pattern recognition.
+ /// This effectively means that there's a potential hole in the linker marking - some items which are accessed only through
+ /// reflection may not be marked correctly and thus may fail at runtime.
+ void UnrecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, string message);
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/KnownMembers.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/KnownMembers.cs
new file mode 100644
index 00000000000..02dcf6469ad
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/KnownMembers.cs
@@ -0,0 +1,31 @@
+using Mono.Cecil;
+
+namespace Mono.Linker
+{
+ public class KnownMembers
+ {
+ public MethodDefinition NotSupportedExceptionCtorString { get; set; }
+ public MethodDefinition DisablePrivateReflectionAttributeCtor { get; set; }
+ public MethodDefinition ObjectCtor { get; set; }
+
+ public static bool IsNotSupportedExceptionCtorString (MethodDefinition method)
+ {
+ if (!method.IsConstructor || method.IsStatic || !method.HasParameters)
+ return false;
+
+ if (method.Parameters.Count != 1 || method.Parameters [0].ParameterType.MetadataType != MetadataType.String)
+ return false;
+
+ return true;
+ }
+
+ public static bool IsSatelliteAssemblyMarker (MethodDefinition method)
+ {
+ if (!method.IsConstructor || method.IsStatic)
+ return false;
+
+ var declaringType = method.DeclaringType;
+ return declaringType.Name == "ResourceManager" && declaringType.Namespace == "System.Resources";
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LinkContext.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LinkContext.cs
new file mode 100644
index 00000000000..b05afc29cb7
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LinkContext.cs
@@ -0,0 +1,447 @@
+//
+// LinkContext.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// (C) 2006 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.IO;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace Mono.Linker {
+
+ public class UnintializedContextFactory {
+ virtual public AnnotationStore CreateAnnotationStore (LinkContext context) => new AnnotationStore (context);
+ virtual public MarkingHelpers CreateMarkingHelpers (LinkContext context) => new MarkingHelpers (context);
+ virtual public Tracer CreateTracer (LinkContext context) => new Tracer (context);
+ }
+
+ public class LinkContext : IDisposable {
+
+ Pipeline _pipeline;
+ AssemblyAction _coreAction;
+ AssemblyAction _userAction;
+ Dictionary _actions;
+ string _outputDirectory;
+ readonly Dictionary _parameters;
+ bool _linkSymbols;
+ bool _keepTypeForwarderOnlyAssemblies;
+ bool _keepMembersForDebugger;
+ bool _ignoreUnresolved;
+
+ AssemblyResolver _resolver;
+
+ ReaderParameters _readerParameters;
+ ISymbolReaderProvider _symbolReaderProvider;
+ ISymbolWriterProvider _symbolWriterProvider;
+
+ AnnotationStore _annotations;
+
+ public Pipeline Pipeline {
+ get { return _pipeline; }
+ }
+
+ public AnnotationStore Annotations {
+ get { return _annotations; }
+ }
+
+ public bool DeterministicOutput { get; set; }
+
+ public string OutputDirectory {
+ get { return _outputDirectory; }
+ set { _outputDirectory = value; }
+ }
+
+ public AssemblyAction CoreAction {
+ get { return _coreAction; }
+ set { _coreAction = value; }
+ }
+
+ public AssemblyAction UserAction {
+ get { return _userAction; }
+ set { _userAction = value; }
+ }
+
+ public bool LinkSymbols {
+ get { return _linkSymbols; }
+ set { _linkSymbols = value; }
+ }
+
+ public bool KeepTypeForwarderOnlyAssemblies
+ {
+ get { return _keepTypeForwarderOnlyAssemblies; }
+ set { _keepTypeForwarderOnlyAssemblies = value; }
+ }
+
+ public bool KeepMembersForDebugger
+ {
+ get { return _keepMembersForDebugger; }
+ set { _keepMembersForDebugger = value; }
+ }
+
+ public bool IgnoreUnresolved
+ {
+ get { return _ignoreUnresolved; }
+ set { _ignoreUnresolved = value; }
+ }
+
+ public bool EnableReducedTracing { get; set; }
+
+ public bool KeepUsedAttributeTypesOnly { get; set; }
+
+ public bool KeepDependencyAttributes { get; set; }
+
+ public bool StripResources { get; set; }
+
+ public List Substitutions { get; private set; }
+
+ public System.Collections.IDictionary Actions {
+ get { return _actions; }
+ }
+
+ public AssemblyResolver Resolver {
+ get { return _resolver; }
+ }
+
+ public ReaderParameters ReaderParameters {
+ get { return _readerParameters; }
+ }
+
+ public ISymbolReaderProvider SymbolReaderProvider {
+ get { return _symbolReaderProvider; }
+ set { _symbolReaderProvider = value; }
+ }
+
+ public ISymbolWriterProvider SymbolWriterProvider {
+ get { return _symbolWriterProvider; }
+ set { _symbolWriterProvider = value; }
+ }
+
+ public bool LogMessages { get; set; }
+
+ public ILogger Logger { private get; set; } = new ConsoleLogger ();
+
+ public MarkingHelpers MarkingHelpers { get; private set; }
+
+ public KnownMembers MarkedKnownMembers { get; private set; }
+
+ public Tracer Tracer { get; private set; }
+
+ public IReflectionPatternRecorder ReflectionPatternRecorder { get; set; }
+
+ public string [] ExcludedFeatures { get; set; }
+
+ public CodeOptimizations DisabledOptimizations { get; set; }
+
+ public bool AddReflectionAnnotations { get; set; }
+
+ public string AssemblyListFile { get; set; }
+
+ public LinkContext (Pipeline pipeline)
+ : this (pipeline, new AssemblyResolver ())
+ {
+ }
+
+ public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
+ : this(pipeline, resolver, new ReaderParameters
+ {
+ AssemblyResolver = resolver
+ }, new UnintializedContextFactory ())
+ {
+ }
+
+ public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParameters readerParameters, UnintializedContextFactory factory)
+ {
+ _pipeline = pipeline;
+ _resolver = resolver;
+ _resolver.Context = this;
+ _actions = new Dictionary ();
+ _parameters = new Dictionary ();
+ _readerParameters = readerParameters;
+
+ SymbolReaderProvider = new DefaultSymbolReaderProvider (false);
+
+ if (factory == null)
+ throw new ArgumentNullException (nameof (factory));
+
+ _annotations = factory.CreateAnnotationStore (this);
+ MarkingHelpers = factory.CreateMarkingHelpers (this);
+ Tracer = factory.CreateTracer (this);
+ ReflectionPatternRecorder = new LoggingReflectionPatternRecorder (this);
+ MarkedKnownMembers = new KnownMembers ();
+ StripResources = true;
+
+ // See https://github.com/mono/linker/issues/612
+ DisabledOptimizations |= CodeOptimizations.UnreachableBodies;
+ DisabledOptimizations |= CodeOptimizations.ClearInitLocals;
+ DisabledOptimizations |= CodeOptimizations.IPConstantPropagation;
+ }
+
+ public void AddSubstitutionFile (string file)
+ {
+ if (Substitutions == null) {
+ Substitutions = new List ();
+ Substitutions.Add (file);
+ return;
+ }
+
+ if (Substitutions.Contains (file))
+ return;
+
+ Substitutions.Add (file);
+ }
+
+ public AssemblyDefinition Resolve (string name)
+ {
+ if (File.Exists (name)) {
+ try {
+ AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly (name, _readerParameters);
+ return _resolver.CacheAssembly (assembly);
+ } catch (Exception e) {
+ throw new AssemblyResolutionException (new AssemblyNameReference (name, new Version ()), e);
+ }
+ }
+
+ return Resolve (new AssemblyNameReference (name, new Version ()));
+ }
+
+ public AssemblyDefinition Resolve (IMetadataScope scope)
+ {
+ AssemblyNameReference reference = GetReference (scope);
+ try {
+ AssemblyDefinition assembly = _resolver.Resolve (reference, _readerParameters);
+
+ if (assembly != null)
+ RegisterAssembly (assembly);
+
+ return assembly;
+ }
+ catch (Exception e) {
+ throw new AssemblyResolutionException (reference, e);
+ }
+ }
+
+ public void RegisterAssembly (AssemblyDefinition assembly)
+ {
+ if (SeenFirstTime (assembly)) {
+ SafeReadSymbols (assembly);
+ SetDefaultAction (assembly);
+ }
+ }
+
+ protected bool SeenFirstTime (AssemblyDefinition assembly)
+ {
+ return !_annotations.HasAction (assembly);
+ }
+
+ public virtual void SafeReadSymbols (AssemblyDefinition assembly)
+ {
+ if (assembly.MainModule.HasSymbols)
+ return;
+
+ if (_symbolReaderProvider == null)
+ throw new ArgumentNullException (nameof (_symbolReaderProvider));
+
+ try {
+ var symbolReader = _symbolReaderProvider.GetSymbolReader (
+ assembly.MainModule,
+ assembly.MainModule.FileName);
+
+ if (symbolReader == null)
+ return;
+
+ try {
+ assembly.MainModule.ReadSymbols (symbolReader);
+ } catch {
+ symbolReader.Dispose ();
+ return;
+ }
+
+ // Add symbol reader to annotations only if we have successfully read it
+ _annotations.AddSymbolReader (assembly, symbolReader);
+ } catch { }
+ }
+
+ public virtual ICollection ResolveReferences (AssemblyDefinition assembly)
+ {
+ List references = new List ();
+ if (assembly == null)
+ return references;
+ foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) {
+ AssemblyDefinition definition = Resolve (reference);
+ if (definition != null)
+ references.Add (definition);
+ }
+ return references;
+ }
+
+ static AssemblyNameReference GetReference (IMetadataScope scope)
+ {
+ AssemblyNameReference reference;
+ if (scope is ModuleDefinition) {
+ AssemblyDefinition asm = ((ModuleDefinition) scope).Assembly;
+ reference = asm.Name;
+ } else
+ reference = (AssemblyNameReference) scope;
+
+ return reference;
+ }
+
+ public void SetAction (AssemblyDefinition assembly, AssemblyAction defaultAction)
+ {
+ RegisterAssembly (assembly);
+
+ if (!_actions.TryGetValue (assembly.Name.Name, out AssemblyAction action))
+ action = defaultAction;
+
+ Annotations.SetAction (assembly, action);
+ }
+
+ protected void SetDefaultAction (AssemblyDefinition assembly)
+ {
+ AssemblyAction action;
+
+ AssemblyNameDefinition name = assembly.Name;
+
+ if (_actions.TryGetValue (name.Name, out action)) {
+ } else if (IsCore (name)) {
+ action = _coreAction;
+ } else {
+ action = _userAction;
+ }
+
+ _annotations.SetAction (assembly, action);
+ }
+
+ public static bool IsCore (AssemblyNameReference name)
+ {
+ switch (name.Name) {
+ case "mscorlib":
+ case "Accessibility":
+ case "Mono.Security":
+ // WPF
+ case "PresentationFramework":
+ case "PresentationCore":
+ case "WindowsBase":
+ case "UIAutomationProvider":
+ case "UIAutomationTypes":
+ case "PresentationUI":
+ case "ReachFramework":
+ case "netstandard":
+ return true;
+ default:
+ return name.Name.StartsWith ("System")
+ || name.Name.StartsWith ("Microsoft");
+ }
+ }
+
+ public virtual AssemblyDefinition [] GetAssemblies ()
+ {
+ var cache = _resolver.AssemblyCache;
+ AssemblyDefinition [] asms = new AssemblyDefinition [cache.Count];
+ cache.Values.CopyTo (asms, 0);
+ return asms;
+ }
+
+ public void SetParameter (string key, string value)
+ {
+ _parameters [key] = value;
+ }
+
+ public bool HasParameter (string key)
+ {
+ return _parameters.ContainsKey (key);
+ }
+
+ public string GetParameter (string key)
+ {
+ string val = null;
+ _parameters.TryGetValue (key, out val);
+ return val;
+ }
+
+ public void Dispose ()
+ {
+ _resolver.Dispose ();
+ }
+
+ public bool IsFeatureExcluded (string featureName)
+ {
+ return ExcludedFeatures != null && Array.IndexOf (ExcludedFeatures, featureName) >= 0;
+ }
+
+ public bool IsOptimizationEnabled (CodeOptimizations optimization)
+ {
+ return (DisabledOptimizations & optimization) == 0;
+ }
+
+ public void LogMessage (string message)
+ {
+ LogMessage (MessageImportance.Normal, message);
+ }
+
+ public void LogMessage (MessageImportance importance, string message)
+ {
+ if (LogMessages && Logger != null)
+ Logger.LogMessage (importance, "{0}", message);
+ }
+ }
+
+ [Flags]
+ public enum CodeOptimizations
+ {
+ BeforeFieldInit = 1 << 0,
+
+ ///
+ /// Option to disable removal of overrides of virtual methods when a type is never instantiated
+ ///
+ /// Being able to disable this optimization is helpful when trying to troubleshoot problems caused by types created via reflection or from native
+ /// that do not get an instance constructor marked.
+ ///
+ OverrideRemoval = 1 << 1,
+
+ ///
+ /// Option to disable delaying marking of instance methods until an instance of that type could exist
+ ///
+ UnreachableBodies = 1 << 2,
+
+ ///
+ /// Option to clear the initlocals flag on methods
+ ///
+ ClearInitLocals = 1 << 3,
+
+ ///
+ /// Option to remove .interfaceimpl for interface types that are not used
+ ///
+ UnusedInterfaces = 1 << 4,
+
+ ///
+ /// Option to do interprocedural constant propagation on return values
+ ///
+ IPConstantPropagation = 1 << 5
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LoggingReflectionPatternRecorder.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LoggingReflectionPatternRecorder.cs
new file mode 100644
index 00000000000..f9c0d89e938
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/LoggingReflectionPatternRecorder.cs
@@ -0,0 +1,49 @@
+//
+// LoggingReflectionPatternRecorder.cs
+//
+// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com)
+//
+// 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 Mono.Cecil;
+
+namespace Mono.Linker
+{
+ class LoggingReflectionPatternRecorder : IReflectionPatternRecorder
+ {
+ private readonly LinkContext _context;
+
+ public LoggingReflectionPatternRecorder (LinkContext context)
+ {
+ _context = context;
+ }
+
+ public void RecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, IMemberDefinition accessedItem)
+ {
+ // Do nothing - there's no logging for successfully recognized patterns
+ }
+
+ public void UnrecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, string message)
+ {
+ _context.LogMessage (MessageImportance.Low, message);
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MarkingHelpers.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MarkingHelpers.cs
new file mode 100644
index 00000000000..b477a5ce389
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MarkingHelpers.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Cecil;
+
+namespace Mono.Linker {
+ public class MarkingHelpers {
+ protected readonly LinkContext _context;
+
+ public MarkingHelpers (LinkContext context)
+ {
+ _context = context;
+ }
+
+ public void MarkExportedType (ExportedType type, ModuleDefinition module)
+ {
+ _context.Annotations.Mark (type);
+ if (_context.KeepTypeForwarderOnlyAssemblies)
+ _context.Annotations.Mark (module);
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MethodAction.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MethodAction.cs
new file mode 100644
index 00000000000..a3550e78396
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/MethodAction.cs
@@ -0,0 +1,38 @@
+//
+// MethodAction.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// (C) 2006 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.
+//
+
+namespace Mono.Linker {
+
+ public enum MethodAction {
+ Nothing,
+ Parse,
+ ForceParse,
+ ConvertToStub,
+ ConvertToThrow,
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/OverrideInformation.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/OverrideInformation.cs
new file mode 100644
index 00000000000..f73d8bc1c63
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/OverrideInformation.cs
@@ -0,0 +1,43 @@
+using System.Diagnostics;
+using Mono.Cecil;
+
+namespace Mono.Linker {
+ [DebuggerDisplay ("{Override}")]
+ public class OverrideInformation {
+ public readonly MethodDefinition Base;
+ public readonly MethodDefinition Override;
+ public readonly InterfaceImplementation MatchingInterfaceImplementation;
+
+ public OverrideInformation (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null)
+ {
+ Base = @base;
+ Override = @override;
+ MatchingInterfaceImplementation = matchingInterfaceImplementation;
+ }
+
+ public bool IsOverrideOfInterfaceMember
+ {
+ get
+ {
+ if (MatchingInterfaceImplementation != null)
+ return true;
+
+ return Base.DeclaringType.IsInterface;
+ }
+ }
+
+ public TypeDefinition InterfaceType
+ {
+ get
+ {
+ if (!IsOverrideOfInterfaceMember)
+ return null;
+
+ if (MatchingInterfaceImplementation != null)
+ return MatchingInterfaceImplementation.InterfaceType.Resolve ();
+
+ return Base.DeclaringType;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Pipeline.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Pipeline.cs
new file mode 100644
index 00000000000..a28de3ba1b2
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Pipeline.cs
@@ -0,0 +1,152 @@
+//
+// Pipeline.cs
+//
+// Author:
+// Jb Evain (jbevain@gmail.com)
+//
+// (C) 2006 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 Mono.Linker.Steps;
+
+namespace Mono.Linker {
+
+ public class Pipeline {
+
+ readonly List _steps;
+
+ public Pipeline ()
+ {
+ _steps = new List();
+ }
+
+ public void PrependStep (IStep step)
+ {
+ _steps.Insert (0, step);
+ }
+
+ public void AppendStep (IStep step)
+ {
+ _steps.Add (step);
+ }
+
+ public void AddStepBefore (Type target, IStep step)
+ {
+ for (int i = 0; i < _steps.Count; i++) {
+ if (target.IsInstanceOfType (_steps [i])) {
+ _steps.Insert (i, step);
+ return;
+ }
+ }
+ string msg = String.Format ("Step {0} could not be inserted before (not found) {1}", step, target);
+ throw new InvalidOperationException (msg);
+ }
+
+ public void AddStepBefore (IStep target, IStep step)
+ {
+ for (int i = 0; i < _steps.Count; i++) {
+ if (_steps [i] == target) {
+ _steps.Insert (i, step);
+ return;
+ }
+ }
+ }
+
+ public void ReplaceStep (Type target, IStep step)
+ {
+ AddStepBefore (target, step);
+ RemoveStep (target);
+ }
+
+ public void AddStepAfter (Type target, IStep step)
+ {
+ for (int i = 0; i < _steps.Count; i++) {
+ if (target.IsInstanceOfType (_steps [i])) {
+ if (i == _steps.Count - 1)
+ _steps.Add (step);
+ else
+ _steps.Insert (i + 1, step);
+ return;
+ }
+ }
+ string msg = String.Format ("Step {0} could not be inserted after (not found) {1}", step, target);
+ throw new InvalidOperationException (msg);
+ }
+
+ public void AddStepAfter (IStep target, IStep step)
+ {
+ for (int i = 0; i < _steps.Count; i++) {
+ if (_steps [i] == target) {
+ if (i == _steps.Count - 1)
+ _steps.Add (step);
+ else
+ _steps.Insert (i + 1, step);
+ return;
+ }
+ }
+ }
+
+ public void RemoveStep (Type target)
+ {
+ for (int i = 0; i < _steps.Count; i++) {
+ if (_steps [i].GetType () != target)
+ continue;
+
+ _steps.RemoveAt (i);
+ break;
+ }
+ }
+
+ public void Process (LinkContext context)
+ {
+ while (_steps.Count > 0) {
+ IStep step = _steps [0];
+ ProcessStep (context, step);
+ _steps.Remove (step);
+ }
+ }
+
+ protected virtual void ProcessStep (LinkContext context, IStep step)
+ {
+ context.Tracer.Push (step);
+ step.Process (context);
+ context.Tracer.Pop ();
+ }
+
+ public IStep [] GetSteps ()
+ {
+ return _steps.ToArray ();
+ }
+
+ public bool ContainsStep (Type type)
+ {
+ foreach (IStep step in _steps)
+ if (step.GetType () == type)
+ return true;
+
+ return false;
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Tracer.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Tracer.cs
new file mode 100644
index 00000000000..1a6b7109fe9
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/Tracer.cs
@@ -0,0 +1,115 @@
+//
+// Tracer.cs
+//
+// Author:
+// Radek Doulik
+//
+// Copyright (C) 2017 Microsoft Corporation (http://www.microsoft.com)
+//
+// 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;
+
+namespace Mono.Linker
+{
+ public class Tracer
+ {
+ protected readonly LinkContext context;
+
+ Stack dependency_stack;
+ List recorders;
+
+ public Tracer (LinkContext context)
+ {
+ this.context = context;
+ dependency_stack = new Stack ();
+ }
+
+ public void Finish ()
+ {
+ dependency_stack = null;
+ if (recorders != null) {
+ foreach (var recorder in recorders) {
+ if (recorder is IDisposable disposableRecorder)
+ disposableRecorder.Dispose ();
+ }
+ }
+
+ recorders = null;
+ }
+
+ public void AddRecorder (IDependencyRecorder recorder)
+ {
+ if (recorders == null) {
+ recorders = new List ();
+ }
+
+ recorders.Add (recorder);
+ }
+
+ public void Push (object o, bool addDependency = true)
+ {
+ if (!IsRecordingEnabled ())
+ return;
+
+ if (addDependency && dependency_stack.Count > 0)
+ AddDependency (o);
+
+ dependency_stack.Push (o);
+ }
+
+ public void Pop ()
+ {
+ if (!IsRecordingEnabled ())
+ return;
+
+ dependency_stack.Pop ();
+ }
+
+ bool IsRecordingEnabled ()
+ {
+ return recorders != null;
+ }
+
+ public void AddDirectDependency (object b, object e)
+ {
+ ReportDependency (b, e, false);
+ }
+
+ public void AddDependency (object o, bool marked = false)
+ {
+ if (!IsRecordingEnabled ())
+ return;
+
+ ReportDependency (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o, marked);
+ }
+
+ private void ReportDependency (object source, object target, bool marked)
+ {
+ if (IsRecordingEnabled ()) {
+ foreach (IDependencyRecorder recorder in recorders) {
+ recorder.RecordDependency (source, target, marked);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/TypePreserve.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/TypePreserve.cs
new file mode 100644
index 00000000000..bc743c65a18
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker/TypePreserve.cs
@@ -0,0 +1,38 @@
+//
+// TypePreserve.cs
+//
+// Author:
+// Jb Evain (jb@nurv.fr)
+//
+// (C) 2007 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.
+//
+
+namespace Mono.Linker {
+
+ public enum TypePreserve
+ {
+ Nothing, // This is actually Declaration
+ All,
+ Fields,
+ Methods
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/CecilRocks.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/CecilRocks.cs
new file mode 100644
index 00000000000..69958598dda
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/CecilRocks.cs
@@ -0,0 +1,519 @@
+//
+// 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 {
+
+ public static class MethodBodyRocks {
+
+ public static IEnumerable GetAllTypes (this ModuleDefinition self)
+ {
+ return self.Types.SelectMany (t => t.GetAllTypes ());
+ }
+
+ static IEnumerable 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 GetMethods (this TypeDefinition self)
+ {
+ return self.Methods.Where (m => !m.IsConstructor);
+ }
+
+ public static IEnumerable 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 (var iface in type.Interfaces) {
+ string fullname = (generic) ? iface.InterfaceType.GetElementType ().FullName : iface.InterfaceType.FullName;
+ if (fullname == interfaceName)
+ return true;
+ //if not, then maybe one of its parent interfaces does
+ if (Implements (iface.InterfaceType.Resolve (), interfaceName, generic))
+ return true;
+ }
+ }
+
+ type = type.BaseType != null ? type.BaseType.Resolve () : null;
+ }
+ return false;
+ }
+
+ public static bool Inherits (this TypeReference self, string @namespace, string name)
+ {
+ if (@namespace == null)
+ throw new ArgumentNullException ("namespace");
+ if (name == null)
+ throw new ArgumentNullException ("name");
+ if (self == null)
+ return false;
+
+ TypeReference current = self.Resolve ();
+ while (current != null) {
+ if (current.Is (@namespace, name))
+ return true;
+ if (current.Is ("System", "Object"))
+ return false;
+
+ TypeDefinition td = current.Resolve ();
+ if (td == null)
+ return false; // could not resolve type
+ current = td.BaseType;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Microsoft.Android.Sdk.ILLink/Mono.Tuner/Extensions.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Extensions.cs
similarity index 92%
rename from src/Microsoft.Android.Sdk.ILLink/Mono.Tuner/Extensions.cs
rename to src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Extensions.cs
index f6af83d8b95..3e3b312133b 100644
--- a/src/Microsoft.Android.Sdk.ILLink/Mono.Tuner/Extensions.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Extensions.cs
@@ -5,11 +5,10 @@
using Mono.Linker;
-namespace Mono.Tuner
-{
+namespace Mono.Tuner {
+
+ public static partial class Extensions {
- public static partial class Extensions
- {
public static bool TryGetLinkedAssembly (this LinkContext context, string name, out AssemblyDefinition assembly)
{
assembly = GetAssembly (context, name);
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Profile.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Profile.cs
new file mode 100644
index 00000000000..54cfffa64f1
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Mono.Tuner/Profile.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+
+using Mono.Cecil;
+
+namespace Mono.Tuner {
+
+ public abstract class Profile {
+
+ static Profile current;
+
+ public 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");
+ }
+ set {
+ current = value;
+ }
+ }
+
+ 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 IsSdkAssembly (string assemblyName)
+ {
+ return Current.IsSdk (assemblyName);
+ }
+
+ public static bool IsProductAssembly (AssemblyDefinition assembly)
+ {
+ return Current.IsProduct (assembly);
+ }
+
+ public static bool IsProductAssembly (string assemblyName)
+ {
+ return Current.IsProduct (assemblyName);
+ }
+
+ protected virtual bool IsSdk (AssemblyDefinition assembly)
+ {
+ return IsSdk (assembly.Name.Name);
+ }
+
+ protected virtual bool IsProduct (AssemblyDefinition assembly)
+ {
+ return IsProduct (assembly.Name.Name);
+ }
+
+ protected abstract bool IsSdk (string assemblyName);
+ protected abstract bool IsProduct (string assemblyName);
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocumentElement.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocumentElement.cs
index 6b685a996c9..cf51a75094f 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocumentElement.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocumentElement.cs
@@ -8,7 +8,6 @@
using Monodroid;
using MonoDroid.Tuner;
-using MonoDroid.Utils;
using Java.Interop.Tools.Cecil;
using Java.Interop.Tools.TypeNameMappings;
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
index c94ad582680..92132281396 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
@@ -51,195 +51,40 @@
-
- Linker\Mono.Tuner\AdjustVisibility.cs
-
-
- Linker\Mono.Tuner\CecilRocks.cs
-
-
- Linker\Mono.Tuner\CheckVisibility.cs
-
-
- Linker\Linker\Annotations.cs
-
-
- Linker\Linker\AssemblyAction.cs
-
-
- Linker\Linker\AssemblyResolver.cs
-
-
- Linker\Linker\AssemblyUtilities.cs
-
-
- Linker\Linker\I18nAssemblies.cs
-
-
- Linker\Linker\Inflater.cs
-
-
- Linker\Linker\IXApiVisitor.cs
-
-
- Linker\Linker\LinkContext.cs
-
-
- Linker\Linker\MethodAction.cs
-
-
- Linker\Linker\MethodReferenceExtensions.cs
-
-
- Linker\Linker\OutputException.cs
-
-
- Linker\Linker\OverrideInformation.cs
-
-
- Linker\Linker\Pipeline.cs
-
-
- Linker\Linker\TypeNameParser.cs
-
-
- Linker\Linker\TypePreserve.cs
-
-
- Linker\Linker\TypeReferenceExtensions.cs
-
-
- Linker\Linker\XApiReader.cs
-
-
- Linker\Linker.Steps\BlacklistStep.cs
-
-
- Linker\Linker.Steps\BaseStep.cs
-
-
- Linker\Linker.Steps\CleanStep.cs
-
-
- Linker\Linker.Steps\IStep.cs
-
-
- Linker\Linker.Steps\LoadI18nAssemblies.cs
-
-
- Linker\Linker.Steps\LoadReferencesStep.cs
-
-
- Linker\Linker.Steps\OutputStep.cs
-
-
- Linker\Linker.Steps\RegenerateGuidStep.cs
-
-
- Linker\Linker.Steps\ResolveFromAssemblyStep.cs
-
-
- Linker\Linker.Steps\ResolveFromXApiStep.cs
-
-
- Linker\Linker.Steps\ResolveFromXmlStep.cs
-
-
- Linker\Linker.Steps\ResolveStep.cs
-
-
- Linker\Linker.Steps\TypeMapStep.cs
-
-
- Linker\Linker.Steps\SweepStep.cs
-
-
- Linker\Linker.Steps\MarkStep.cs
-
-
- Linker\Linker.Steps\PreserveDependencyLookupStep.cs
-
-
- Linker\Linker.Steps\BodySubstituterStep.cs
-
-
- Linker\Linker\IDependencyRecorder.cs
-
-
- Linker\Linker\IReflectionPatternRecorder.cs
-
-
- Linker\Linker\LoggingReflectionPatternRecorder.cs
-
-
- Linker\Linker\XmlDependencyRecorder.cs
-
-
- Linker\Linker\LoadException.cs
-
-
- Linker\Linker\MarkException.cs
-
-
- Linker\Linker\ConsoleLogger.cs
-
-
- Linker\Linker\ILogger.cs
-
-
- Linker\Linker\Tracer.cs
-
-
- Linker\Linker\MarkingHelpers.cs
-
-
- Linker\Linker\KnownMembers.cs
-
-
- Linker\Linker\MethodDefinitionExtensions.cs
-
-
- Linker\Linker\MethodBodyScanner.cs
-
-
- Linker\Linker\TypeDefinitionExtensions.cs
-
-
- Linker\Linker\BCL.cs
-
-
- Linker\Mono.Tuner\ApplyPreserveAttributeBase.cs
-
-
- Linker\Mono.Tuner\Dispatcher.cs
-
-
- Linker\Mono.Tuner\CustomizeActions.cs
-
-
- Linker\Mono.Tuner\Extensions.cs
-
-
- Linker\Mono.Tuner\FixModuleFlags.cs
-
-
- Linker\Mono.Tuner\PreserveCrypto.cs
-
-
- Linker\Mono.Tuner\PreserveSoapHttpClients.cs
-
-
- Linker\Mono.Tuner\Profile.cs
-
-
- Linker\Mono.Tuner\RemoveAttributesBase.cs
-
-
- Linker\Mono.Tuner\RemoveResources.cs
-
-
- Linker\Mono.Tuner\RemoveSecurity.cs
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Mono.Android\IntentFilterAttribute.cs
@@ -258,21 +103,6 @@
Utilities\StringRocks.cs
-
- Linker\Mono.Tuner\FilterAttributes.cs
-
-
- Linker\Mono.Tuner\InjectSecurityAttributes.cs
-
-
- Linker\Mono.Tuner\PrintStatus.cs
-
-
- Linker\Mono.Tuner\RemoveSerialization.cs
-
-
- Linker\Mono.Tuner\TunerAnnotations.cs
-
Mono.Android\UsesLibraryAttribute.cs