You've already forked linux-packaging-mono
Imported Upstream version 5.20.0.180
Former-commit-id: ff953ca879339fe1e1211f7220f563e1342e66cb
This commit is contained in:
parent
0e2d47d1c8
commit
0510252385
92
external/linker/README.md
vendored
92
external/linker/README.md
vendored
@@ -21,3 +21,95 @@ TODO
|
||||
## Build & Test Status
|
||||
|
||||
[](https://jenkins.mono-project.com/job/test-linker-mainline/)
|
||||
|
||||
## Link xml file examples
|
||||
|
||||
A link xml file can be used to explicitly preserve assemblies, types, and members. Below is a sample file containing examples of various usages.
|
||||
|
||||
```xml
|
||||
<linker>
|
||||
<!--
|
||||
Preserve types and members in an assembly
|
||||
-->
|
||||
<assembly fullname="Assembly1">
|
||||
<!--Preserve an entire type-->
|
||||
<type fullname="Assembly1.A" preserve="all"/>
|
||||
<!--No "preserve" attribute and no members specified means preserve all members-->
|
||||
<type fullname="Assembly1.B"/>
|
||||
<!--Preserve all fields on a type-->
|
||||
<type fullname="Assembly1.C" preserve="fields"/>
|
||||
<!--Preserve all fields on a type-->
|
||||
<type fullname="Assembly1.D" preserve="methods"/>
|
||||
<!--Preserve the type only-->
|
||||
<type fullname="Assembly1.E" preserve="nothing"/>
|
||||
<!--Preserving only specific members of a type-->
|
||||
<type fullname="Assembly1.F">
|
||||
<!--
|
||||
Fields
|
||||
-->
|
||||
<field signature="System.Int32 field1" />
|
||||
<!--Preserve a field by name rather than signature-->
|
||||
<field name="field2" />
|
||||
<!--
|
||||
Methods
|
||||
-->
|
||||
<method signature="System.Void Method1()" />
|
||||
<!--Preserve a method with parameters-->
|
||||
<method signature="System.Void Method2(System.Int32,System.String)" />
|
||||
<!--Preserve a method by name rather than signature-->
|
||||
<method name="Method3" />
|
||||
<!--
|
||||
Properties
|
||||
-->
|
||||
<!--Preserve a property, it's backing field (if present), getter, and setter methods-->
|
||||
<property signature="System.Int32 Property1" />
|
||||
<property signature="System.Int32 Property2" accessors="all" />
|
||||
<!--Preserve a property, it's backing field (if present), and getter method-->
|
||||
<property signature="System.Int32 Property3" accessors="get" />
|
||||
<!--Preserve a property, it's backing field (if present), and setter method-->
|
||||
<property signature="System.Int32 Property4" accessors="set" />
|
||||
<!--Preserve a property by name rather than signature-->
|
||||
<property name="Property5" />
|
||||
<!--
|
||||
Events
|
||||
-->
|
||||
<!--Preserve an event, it's backing field (if present), add, and remove methods-->
|
||||
<event signature="System.EventHandler Event1" />
|
||||
<!--Preserve an event by name rather than signature-->
|
||||
<event name="Event2" />
|
||||
</type>
|
||||
<!--Examples with generics-->
|
||||
<type fullname="Assembly1.G`1">
|
||||
<!--Preserve a field with generics in the signature-->
|
||||
<field signature="System.Collections.Generic.List`1<System.Int32> field1" />
|
||||
<field signature="System.Collections.Generic.List`1<T> field2" />
|
||||
<!--Preserve a method with generics in the signature-->
|
||||
<method signature="System.Void Method1(System.Collections.Generic.List`1<System.Int32>)" />
|
||||
<!--Preserve an event with generics in the signature-->
|
||||
<event signature="System.EventHandler`1<System.EventArgs> Event1" />
|
||||
</type>
|
||||
<!--Preserve a nested type-->
|
||||
<type fullname="Assembly1.H/Nested" preserve="all"/>
|
||||
<!--Preserve all fields of a type if the type is used. If the type is not used it will be removed-->
|
||||
<type fullname="Assembly1.I" preserve="fields" required="0"/>
|
||||
<!--Preserve all methods of a type if the type is used. If the type is not used it will be removed-->
|
||||
<type fullname="Assembly1.J" preserve="methods" required="0"/>
|
||||
<!--Preserve all types in a namespace-->
|
||||
<type fullname="Assembly1.SomeNamespace*" />
|
||||
<!--Preserve all types with a common prefix in their name-->
|
||||
<type fullname="Prefix*" />
|
||||
</assembly>
|
||||
<!--
|
||||
Preserve an entire assembly
|
||||
-->
|
||||
<assembly fullname="Assembly2" preserve="all"/>
|
||||
<!--No "preserve" attribute and no types specified means preserve all-->
|
||||
<assembly fullname="Assembly3"/>
|
||||
<!--
|
||||
Fully qualified assembly name
|
||||
-->
|
||||
<assembly fullname="Assembly4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
|
||||
<type fullname="Assembly4.Foo" preserve="all"/>
|
||||
</assembly>
|
||||
</linker>
|
||||
```
|
||||
|
||||
@@ -34,21 +34,19 @@ using Mono.Cecil;
|
||||
namespace Mono.Linker.Steps {
|
||||
|
||||
public class LoadReferencesStep : BaseStep {
|
||||
|
||||
readonly Dictionary<AssemblyNameDefinition, AssemblyDefinition> _references = new Dictionary<AssemblyNameDefinition, AssemblyDefinition> ();
|
||||
|
||||
readonly HashSet<AssemblyNameDefinition> references = new HashSet<AssemblyNameDefinition> ();
|
||||
|
||||
protected override void ProcessAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
ProcessReferences (assembly);
|
||||
}
|
||||
|
||||
void ProcessReferences (AssemblyDefinition assembly)
|
||||
protected void ProcessReferences (AssemblyDefinition assembly)
|
||||
{
|
||||
if (_references.ContainsKey (assembly.Name))
|
||||
if (!references.Add (assembly.Name))
|
||||
return;
|
||||
|
||||
_references.Add (assembly.Name, assembly);
|
||||
|
||||
Context.RegisterAssembly (assembly);
|
||||
|
||||
foreach (AssemblyDefinition referenceDefinition in Context.ResolveReferences (assembly)) {
|
||||
|
||||
203
external/linker/linker/Linker.Steps/MarkStep.cs
vendored
203
external/linker/linker/Linker.Steps/MarkStep.cs
vendored
@@ -253,8 +253,8 @@ namespace Mono.Linker.Steps {
|
||||
Tracer.Push (provider);
|
||||
try {
|
||||
foreach (CustomAttribute ca in provider.CustomAttributes) {
|
||||
if (IsUserDependencyMarker (ca.AttributeType)) {
|
||||
MarkUserDependency (provider as MethodReference, ca);
|
||||
if (IsUserDependencyMarker (ca.AttributeType) && provider is MemberReference mr) {
|
||||
MarkUserDependency (mr, ca);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -274,14 +274,13 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
protected virtual bool IsUserDependencyMarker (TypeReference type)
|
||||
{
|
||||
return type.Name == "PreserveDependencyAttribute" &&
|
||||
type.Namespace == "System.Runtime.CompilerServices";
|
||||
return PreserveDependencyLookupStep.IsPreserveDependencyAttribute (type);
|
||||
}
|
||||
|
||||
protected virtual void MarkUserDependency (MethodReference context, CustomAttribute ca)
|
||||
protected virtual void MarkUserDependency (MemberReference context, CustomAttribute ca)
|
||||
{
|
||||
var args = ca.ConstructorArguments;
|
||||
if (args.Count == 2 && args[1].Value is string condition) {
|
||||
if (ca.HasProperties && ca.Properties [0].Name == "Condition") {
|
||||
var condition = ca.Properties [0].Argument.Value as string;
|
||||
switch (condition) {
|
||||
case "":
|
||||
case null:
|
||||
@@ -297,57 +296,51 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
if (args.Count >= 1 && args[0].Value is string dependency) {
|
||||
string member = null;
|
||||
string type = null;
|
||||
string[] signature = null;
|
||||
TypeDefinition td = null;
|
||||
|
||||
var sign_start = dependency.IndexOf ('(');
|
||||
var sign_end = dependency.LastIndexOf (')');
|
||||
if (sign_start > 0 && sign_end > sign_start) {
|
||||
var parameters = dependency.Substring (sign_start + 1, sign_end - sign_start - 1).Replace (" ", "");
|
||||
signature = string.IsNullOrEmpty (parameters) ? Array.Empty<string> () : parameters.Split (',');
|
||||
var idx = dependency.LastIndexOf ('.', sign_start);
|
||||
if (idx > 0) {
|
||||
member = dependency.Substring (idx + 1, sign_start - idx - 1).TrimEnd ();
|
||||
type = dependency.Substring (0, idx);
|
||||
} else {
|
||||
member = dependency.Substring (0, sign_start - 1);
|
||||
td = context.DeclaringType.Resolve ();
|
||||
}
|
||||
} else if (sign_start < 0) {
|
||||
var idx = dependency.LastIndexOf ('.');
|
||||
if (idx > 0) {
|
||||
member = dependency.Substring (idx + 1);
|
||||
type = dependency.Substring (0, idx);
|
||||
} else {
|
||||
member = dependency;
|
||||
td = context.DeclaringType.Resolve ();
|
||||
}
|
||||
AssemblyDefinition assembly;
|
||||
var args = ca.ConstructorArguments;
|
||||
if (args.Count >= 3 && args [2].Value is string assemblyName) {
|
||||
if (!_context.Resolver.AssemblyCache.TryGetValue (assemblyName, out assembly)) {
|
||||
_context.Logger.LogMessage (MessageImportance.Low, $"Could not resolve '{assemblyName}' assembly dependency");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
assembly = null;
|
||||
}
|
||||
|
||||
TypeDefinition td = null;
|
||||
if (args.Count >= 2 && args [1].Value is string typeName) {
|
||||
td = FindType (assembly ?? context.Module.Assembly, typeName);
|
||||
|
||||
if (td == null) {
|
||||
if (type == null) {
|
||||
_context.Logger.LogMessage (MessageImportance.Low, $"Could not resolve '{dependency}' dependency");
|
||||
return;
|
||||
}
|
||||
|
||||
td = FindType (context.Module.Assembly, type);
|
||||
if (td == null) {
|
||||
_context.Logger.LogMessage (MessageImportance.Low, $"Could not find '{dependency}' dependency");
|
||||
return;
|
||||
}
|
||||
_context.Logger.LogMessage (MessageImportance.Low, $"Could not resolve '{typeName}' type dependency");
|
||||
return;
|
||||
}
|
||||
|
||||
if (MarkDependencyMethod (td, member, signature))
|
||||
return;
|
||||
|
||||
if (MarkDependencyField (td, member))
|
||||
return;
|
||||
|
||||
_context.Logger.LogMessage (MessageImportance.High, $"Could not resolve dependency member '{member}' declared in type '{dependency}'");
|
||||
} else {
|
||||
td = context.DeclaringType.Resolve ();
|
||||
}
|
||||
|
||||
string member = null;
|
||||
string[] signature = null;
|
||||
if (args.Count >= 1 && args [0].Value is string memberSignature) {
|
||||
memberSignature = memberSignature.Replace (" ", "");
|
||||
var sign_start = memberSignature.IndexOf ('(');
|
||||
var sign_end = memberSignature.LastIndexOf (')');
|
||||
if (sign_start > 0 && sign_end > sign_start) {
|
||||
var parameters = memberSignature.Substring (sign_start + 1, sign_end - sign_start - 1);
|
||||
signature = string.IsNullOrEmpty (parameters) ? Array.Empty<string> () : parameters.Split (',');
|
||||
member = memberSignature.Substring (0, sign_start);
|
||||
} else {
|
||||
member = memberSignature;
|
||||
}
|
||||
}
|
||||
|
||||
if (MarkDependencyMethod (td, member, signature))
|
||||
return;
|
||||
|
||||
if (MarkDependencyField (td, member))
|
||||
return;
|
||||
|
||||
_context.Logger.LogMessage (MessageImportance.High, $"Could not resolve dependency member '{member}' declared in type '{td.FullName}'");
|
||||
}
|
||||
|
||||
static TypeDefinition FindType (AssemblyDefinition assembly, string fullName)
|
||||
@@ -460,6 +453,9 @@ namespace Mono.Linker.Steps {
|
||||
case "System.ThreadStaticAttribute":
|
||||
case "System.ContextStaticAttribute":
|
||||
return true;
|
||||
case "System.Runtime.InteropServices.InterfaceTypeAttribute":
|
||||
case "System.Runtime.InteropServices.GuidAttribute":
|
||||
return !_context.IsFeatureExcluded ("com");
|
||||
}
|
||||
|
||||
if (!Annotations.IsMarked (attr_type.Resolve ()))
|
||||
@@ -480,7 +476,7 @@ namespace Mono.Linker.Steps {
|
||||
// then surely nothing is using this attribute and there is no need to mark it
|
||||
if (!Annotations.IsMarked (resolvedConstructor.Module) && !Annotations.IsMarked (ca.AttributeType))
|
||||
return false;
|
||||
|
||||
|
||||
if (ca.Constructor.DeclaringType.Namespace == "System.Diagnostics") {
|
||||
string attributeName = ca.Constructor.DeclaringType.Name;
|
||||
if (attributeName == "DebuggerDisplayAttribute" || attributeName == "DebuggerTypeProxyAttribute") {
|
||||
@@ -815,6 +811,7 @@ namespace Mono.Linker.Steps {
|
||||
MarkType (field.FieldType);
|
||||
MarkCustomAttributes (field);
|
||||
MarkMarshalSpec (field);
|
||||
DoAdditionalFieldProcessing (field);
|
||||
|
||||
Annotations.Mark (field);
|
||||
}
|
||||
@@ -930,8 +927,23 @@ namespace Mono.Linker.Steps {
|
||||
{
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things when marking a method
|
||||
protected virtual void DoAdditionalTypeProcessing (TypeDefinition method)
|
||||
// Allow subclassers to mark additional things
|
||||
protected virtual void DoAdditionalTypeProcessing (TypeDefinition type)
|
||||
{
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things
|
||||
protected virtual void DoAdditionalFieldProcessing (FieldDefinition field)
|
||||
{
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things
|
||||
protected virtual void DoAdditionalPropertyProcessing (PropertyDefinition property)
|
||||
{
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things
|
||||
protected virtual void DoAdditionalEventProcessing (EventDefinition evt)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1744,6 +1756,7 @@ namespace Mono.Linker.Steps {
|
||||
protected void MarkProperty (PropertyDefinition prop)
|
||||
{
|
||||
MarkCustomAttributes (prop);
|
||||
DoAdditionalPropertyProcessing (prop);
|
||||
}
|
||||
|
||||
protected virtual void MarkEvent (EventDefinition evt)
|
||||
@@ -1752,6 +1765,7 @@ namespace Mono.Linker.Steps {
|
||||
MarkMethodIfNotNull (evt.AddMethod);
|
||||
MarkMethodIfNotNull (evt.InvokeMethod);
|
||||
MarkMethodIfNotNull (evt.RemoveMethod);
|
||||
DoAdditionalEventProcessing (evt);
|
||||
}
|
||||
|
||||
void MarkMethodIfNotNull (MethodReference method)
|
||||
@@ -1856,7 +1870,6 @@ namespace Mono.Linker.Steps {
|
||||
if (!CheckReflectionMethod (instruction, reflectionMethod))
|
||||
continue;
|
||||
|
||||
_context.Tracer.Push ($"Reflection-{instruction.Operand as MethodReference}");
|
||||
var nameOfThingUsedViaReflection = OperandOfNearestInstructionBefore<string> (i, OpCodes.Ldstr, instructions);
|
||||
var bindingFlags = (BindingFlags) OperandOfNearestInstructionBefore<sbyte> (i, OpCodes.Ldc_I4_S, instructions);
|
||||
|
||||
@@ -1868,7 +1881,6 @@ namespace Mono.Linker.Steps {
|
||||
if (typeDefinition != null)
|
||||
markMethod (instructions, nameOfThingUsedViaReflection, typeDefinition, bindingFlags);
|
||||
}
|
||||
_context.Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1880,32 +1892,44 @@ namespace Mono.Linker.Steps {
|
||||
if (!CheckReflectionMethod (instruction, "GetType"))
|
||||
continue;
|
||||
|
||||
_context.Tracer.Push ($"Reflection-{instruction.Operand as MethodReference}");
|
||||
var typeAssemblyQualifiedName = OperandOfNearestInstructionBefore<string> (i, OpCodes.Ldstr, instructions);
|
||||
|
||||
if (!TypeNameParser.TryParseTypeAssemblyQualifiedName (typeAssemblyQualifiedName, out string typeName, out string assemblyName))
|
||||
continue;
|
||||
|
||||
TypeDefinition foundType = null;
|
||||
foreach (var assemblyDefinition in _context.GetAssemblies ()) {
|
||||
if (assemblyName != null && assemblyDefinition.Name.Name != assemblyName)
|
||||
continue;
|
||||
|
||||
var type = assemblyDefinition.MainModule.GetType (typeName);
|
||||
if (type != null)
|
||||
{
|
||||
MarkType(type);
|
||||
foundType = assemblyDefinition.MainModule.GetType (typeName);
|
||||
if (foundType != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
_context.Tracer.Pop ();
|
||||
|
||||
if (foundType == null)
|
||||
continue;
|
||||
|
||||
_context.Tracer.Push ($"Reflection-{foundType}");
|
||||
try {
|
||||
MarkType (foundType);
|
||||
} finally {
|
||||
_context.Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MarkConstructorsUsedViaReflection (Collection<Instruction> instructions, string unused, TypeDefinition declaringType, BindingFlags bindingFlags)
|
||||
{
|
||||
foreach (var method in declaringType.Methods) {
|
||||
if ((bindingFlags == BindingFlags.Default || bindingFlags.IsSet(BindingFlags.Public) == method.IsPublic) && method.Name == ".ctor")
|
||||
MarkMethod (method);
|
||||
if ((bindingFlags == BindingFlags.Default || bindingFlags.IsSet(BindingFlags.Public) == method.IsPublic) && method.Name == ".ctor") {
|
||||
Tracer.Push ($"Reflection-{method}");
|
||||
try {
|
||||
MarkMethod (method);
|
||||
} finally {
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1916,8 +1940,14 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
foreach (var method in declaringType.Methods) {
|
||||
if ((bindingFlags == BindingFlags.Default || bindingFlags.IsSet(BindingFlags.Public) == method.IsPublic && bindingFlags.IsSet(BindingFlags.Static) == method.IsStatic)
|
||||
&& method.Name == name)
|
||||
MarkMethod (method);
|
||||
&& method.Name == name) {
|
||||
Tracer.Push ($"Reflection-{method}");
|
||||
try {
|
||||
MarkMethod (method);
|
||||
} finally {
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1928,11 +1958,16 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
foreach (var property in declaringType.Properties) {
|
||||
if (property.Name == name) {
|
||||
// It is not easy to reliably detect in the IL code whether the getter or setter (or both) are used.
|
||||
// Be conservative and mark everything for the property.
|
||||
MarkProperty (property);
|
||||
MarkMethodIfNotNull (property.GetMethod);
|
||||
MarkMethodIfNotNull (property.SetMethod);
|
||||
Tracer.Push ($"Reflection-{property}");
|
||||
try {
|
||||
// It is not easy to reliably detect in the IL code whether the getter or setter (or both) are used.
|
||||
// Be conservative and mark everything for the property.
|
||||
MarkProperty (property);
|
||||
MarkMethodIfNotNull (property.GetMethod);
|
||||
MarkMethodIfNotNull (property.SetMethod);
|
||||
} finally {
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1943,8 +1978,14 @@ namespace Mono.Linker.Steps {
|
||||
return;
|
||||
|
||||
foreach (var field in declaringType.Fields) {
|
||||
if (field.Name == name)
|
||||
MarkField (field);
|
||||
if (field.Name == name) {
|
||||
Tracer.Push ($"Reflection-{field}");
|
||||
try {
|
||||
MarkField (field);
|
||||
} finally {
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1954,8 +1995,14 @@ namespace Mono.Linker.Steps {
|
||||
return;
|
||||
|
||||
foreach (var eventInfo in declaringType.Events) {
|
||||
if (eventInfo.Name == name)
|
||||
MarkEvent (eventInfo);
|
||||
if (eventInfo.Name == name) {
|
||||
Tracer.Push ($"Reflection-{eventInfo}");
|
||||
try {
|
||||
MarkEvent (eventInfo);
|
||||
} finally {
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
86
external/linker/linker/Linker.Steps/PreserveDependencyLookupStep.cs
vendored
Normal file
86
external/linker/linker/Linker.Steps/PreserveDependencyLookupStep.cs
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// PreserveDependencyLookupStep.cs
|
||||
//
|
||||
// Author:
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2018 Microsoft Corporation
|
||||
//
|
||||
// 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 Mono.Cecil;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Mono.Linker.Steps {
|
||||
public class PreserveDependencyLookupStep : LoadReferencesStep {
|
||||
protected override void ProcessAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
var module = assembly.MainModule;
|
||||
|
||||
foreach (var type in module.Types) {
|
||||
if (type.HasMethods) {
|
||||
foreach (var method in type.GetMethods ()) {
|
||||
var md = method.Resolve ();
|
||||
if (md?.HasCustomAttributes != true)
|
||||
continue;
|
||||
|
||||
ProcessPreserveDependencyAttribute (md.CustomAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
if (type.HasFields) {
|
||||
foreach (var field in type.Fields) {
|
||||
var md = field.Resolve ();
|
||||
if (md?.HasCustomAttributes != true)
|
||||
continue;
|
||||
|
||||
ProcessPreserveDependencyAttribute (md.CustomAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPreserveDependencyAttribute (TypeReference tr)
|
||||
{
|
||||
return tr.Name == "PreserveDependencyAttribute" && tr.Namespace == "System.Runtime.CompilerServices";
|
||||
}
|
||||
|
||||
void ProcessPreserveDependencyAttribute (Collection<CustomAttribute> attributes)
|
||||
{
|
||||
foreach (var ca in attributes) {
|
||||
if (!IsPreserveDependencyAttribute (ca.AttributeType))
|
||||
continue;
|
||||
|
||||
if (ca.ConstructorArguments.Count != 3)
|
||||
continue;
|
||||
|
||||
var assemblyName = ca.ConstructorArguments [2].Value as string;
|
||||
if (assemblyName == null)
|
||||
continue;
|
||||
|
||||
var newDependency = Context.Resolve (new AssemblyNameReference (assemblyName, new Version ()));
|
||||
if (newDependency != null)
|
||||
ProcessReferences (newDependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
external/linker/linker/Linker.Steps/SweepStep.cs
vendored
57
external/linker/linker/Linker.Steps/SweepStep.cs
vendored
@@ -50,7 +50,7 @@ namespace Mono.Linker.Steps {
|
||||
{
|
||||
assemblies = Context.Annotations.GetAssemblies ().ToArray ();
|
||||
foreach (var assembly in assemblies) {
|
||||
SweepAssembly (assembly);
|
||||
ProcessAssemblyAction (assembly);
|
||||
if ((Annotations.GetAction (assembly) == AssemblyAction.Copy) &&
|
||||
!Context.KeepTypeForwarderOnlyAssemblies) {
|
||||
// Copy assemblies can still contain Type references with
|
||||
@@ -73,36 +73,41 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SweepAssembly (AssemblyDefinition assembly)
|
||||
protected void ProcessAssemblyAction (AssemblyDefinition assembly)
|
||||
{
|
||||
switch (Annotations.GetAction (assembly)) {
|
||||
case AssemblyAction.Link:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
case AssemblyAction.Link:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case AssemblyAction.AddBypassNGenUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
} else {
|
||||
Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen);
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case AssemblyAction.AddBypassNGenUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
} else {
|
||||
Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen);
|
||||
}
|
||||
return;
|
||||
case AssemblyAction.CopyUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
} else {
|
||||
Annotations.SetAction (assembly, AssemblyAction.Copy);
|
||||
}
|
||||
return;
|
||||
|
||||
case AssemblyAction.CopyUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
} else {
|
||||
Annotations.SetAction (assembly, AssemblyAction.Copy);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
SweepAssembly (assembly);
|
||||
}
|
||||
|
||||
protected virtual void SweepAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
var types = new List<TypeDefinition> ();
|
||||
|
||||
foreach (TypeDefinition type in assembly.MainModule.Types) {
|
||||
@@ -134,7 +139,7 @@ namespace Mono.Linker.Steps {
|
||||
return Annotations.IsMarked (assembly.MainModule);
|
||||
}
|
||||
|
||||
void RemoveAssembly (AssemblyDefinition assembly)
|
||||
protected virtual void RemoveAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
Annotations.SetAction (assembly, AssemblyAction.Delete);
|
||||
|
||||
@@ -394,6 +399,8 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
foreach (var parameter in method.Parameters)
|
||||
SweepCustomAttributes (parameter);
|
||||
|
||||
SweepCustomAttributes (method.MethodReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
external/linker/linker/Linker/Driver.cs
vendored
1
external/linker/linker/Linker/Driver.cs
vendored
@@ -434,6 +434,7 @@ namespace Mono.Linker {
|
||||
Pipeline p = new Pipeline ();
|
||||
p.AppendStep (new LoadReferencesStep ());
|
||||
p.AppendStep (new BlacklistStep ());
|
||||
p.AppendStep (new PreserveDependencyLookupStep ());
|
||||
p.AppendStep (new TypeMapStep ());
|
||||
p.AppendStep (new MarkStep ());
|
||||
p.AppendStep (new SweepStep ());
|
||||
|
||||
11
external/linker/linker/Linker/Pipeline.cs
vendored
11
external/linker/linker/Linker/Pipeline.cs
vendored
@@ -123,12 +123,17 @@ namespace Mono.Linker {
|
||||
{
|
||||
while (_steps.Count > 0) {
|
||||
IStep step = _steps [0];
|
||||
context.Tracer.Push (step);
|
||||
step.Process (context);
|
||||
context.Tracer.Pop ();
|
||||
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 ()
|
||||
{
|
||||
|
||||
1
external/linker/linker/Mono.Linker.csproj
vendored
1
external/linker/linker/Mono.Linker.csproj
vendored
@@ -99,6 +99,7 @@
|
||||
<Compile Include="Linker\ILogger.cs" />
|
||||
<Compile Include="Linker\ConsoleLogger.cs" />
|
||||
<Compile Include="Linker\Tracer.cs" />
|
||||
<Compile Include="Linker.Steps\PreserveDependencyLookupStep.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
|
||||
Reference in New Issue
Block a user