Imported Upstream version 5.2.0.175

Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-06-07 13:16:24 +00:00
parent 4bdbaf4a88
commit 966bba02bb
8776 changed files with 346420 additions and 149650 deletions

View File

@@ -77,7 +77,7 @@ namespace Mono.Linker.Steps {
void LoadAssembly (AssemblyNameReference name)
{
AssemblyDefinition assembly = Context.Resolve (name);
ResolveFromAssemblyStep.ProcessLibrary (Context, assembly);
ResolveFromAssemblyStep.ProcessLibrary (Context, assembly, ResolveFromAssemblyStep.RootVisibility.Any);
}
AssemblyNameReference GetAssemblyName (I18nAssemblies assembly)

View File

@@ -26,6 +26,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using Mono.Cecil;
@@ -48,8 +49,13 @@ namespace Mono.Linker.Steps {
_references.Add (assembly.Name, assembly);
foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences)
ProcessReferences (Context.Resolve (reference));
foreach (AssemblyDefinition referenceDefinition in Context.ResolveReferences (assembly)) {
try {
ProcessReferences (referenceDefinition);
} catch (Exception ex) {
throw new LoadException (string.Format ("Error while processing references of '{0}'", assembly.FullName), ex);
}
}
}
}
}

View File

@@ -30,6 +30,7 @@
using System;
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -122,15 +123,30 @@ namespace Mono.Linker.Steps {
continue;
foreach (var exported in assembly.MainModule.ExportedTypes) {
if (!exported.IsForwarder)
bool isForwarder = exported.IsForwarder;
var declaringType = exported.DeclaringType;
while (!isForwarder && (declaringType != null)) {
isForwarder = declaringType.IsForwarder;
declaringType = declaringType.DeclaringType;
}
if (!isForwarder)
continue;
var type = exported.Resolve ();
TypeDefinition type = null;
try {
type = exported.Resolve ();
}
catch (AssemblyResolutionException) {
continue;
}
if (!Annotations.IsMarked (type))
continue;
Annotations.Mark (exported);
Annotations.Mark (assembly.MainModule);
if (_context.KeepTypeForwarderOnlyAssemblies) {
Annotations.Mark (assembly.MainModule);
}
}
}
}
}
void ProcessQueue ()
@@ -138,8 +154,13 @@ namespace Mono.Linker.Steps {
while (!QueueIsEmpty ()) {
MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
Annotations.Push (method);
ProcessMethod (method);
Annotations.Pop ();
try {
ProcessMethod (method);
} catch (Exception e) {
throw new MarkException (string.Format ("Error processing method: '{0}' in assembly: '{1}'", method.FullName, method.Module.Name), e);
} finally {
Annotations.Pop ();
}
}
}
@@ -211,20 +232,24 @@ namespace Mono.Linker.Steps {
protected virtual void MarkCustomAttribute (CustomAttribute ca)
{
Annotations.Push (ca);
MarkMethod (ca.Constructor);
try {
MarkMethod (ca.Constructor);
MarkCustomAttributeArguments (ca);
MarkCustomAttributeArguments (ca);
TypeReference constructor_type = ca.Constructor.DeclaringType;
TypeDefinition type = constructor_type.Resolve ();
if (type == null) {
TypeReference constructor_type = ca.Constructor.DeclaringType;
TypeDefinition type = constructor_type.Resolve ();
if (type == null) {
HandleUnresolvedType (constructor_type);
return;
}
MarkCustomAttributeProperties (ca, type);
MarkCustomAttributeFields (ca, type);
} finally {
Annotations.Pop ();
throw new ResolutionException (constructor_type);
}
MarkCustomAttributeProperties (ca, type);
MarkCustomAttributeFields (ca, type);
Annotations.Pop ();
}
protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider)
@@ -341,6 +366,19 @@ namespace Mono.Linker.Steps {
return null;
}
MethodDefinition GetMethodWithNoParameters (TypeDefinition type, string methodname)
{
while (type != null) {
MethodDefinition method = type.Methods.FirstOrDefault (m => m.Name == methodname && !m.HasParameters);
if (method != null)
return method;
type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
}
return null;
}
void MarkCustomAttributeArguments (CustomAttribute ca)
{
if (!ca.HasConstructorArguments)
@@ -388,7 +426,7 @@ namespace Mono.Linker.Steps {
// e.g. System.String[] -> System.String
var ts = (type as TypeSpecification);
if (ts != null) {
MarkWithResolvedScope (ts.GetElementType ());
MarkWithResolvedScope (ts.ElementType);
return;
}
@@ -504,8 +542,10 @@ namespace Mono.Linker.Steps {
TypeDefinition type = ResolveTypeDefinition (reference);
if (type == null)
throw new ResolutionException (reference);
if (type == null) {
HandleUnresolvedType (reference);
return null;
}
if (CheckProcessed (type))
return null;
@@ -525,6 +565,10 @@ namespace Mono.Linker.Steps {
if (IsSerializable (type))
MarkSerializable (type);
if (IsEventSource (type)) {
MarkEventSource (type);
}
MarkTypeSpecialCustomAttributes (type);
MarkGenericParameterProvider (type);
@@ -570,6 +614,15 @@ namespace Mono.Linker.Steps {
case "System.Xml.Serialization.XmlSchemaProviderAttribute":
MarkXmlSchemaProvider (type, attribute);
break;
case "System.Diagnostics.DebuggerDisplayAttribute":
MarkTypeWithDebuggerDisplayAttribute (type, attribute);
break;
case "System.Diagnostics.DebuggerTypeProxyAttribute":
MarkTypeWithDebuggerTypeProxyAttribute (type, attribute);
break;
case "System.Diagnostics.Tracing.EventDataAttribute":
MarkTypeWithEventDataAttribute (type, attribute);
break;
}
}
}
@@ -588,6 +641,11 @@ namespace Mono.Linker.Steps {
}
}
void MarkTypeWithEventDataAttribute (TypeDefinition type, CustomAttribute attribute)
{
MarkMethodsIf (type.Methods, IsPublicInstancePropertyMethod);
}
void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
{
string method_name;
@@ -597,6 +655,73 @@ namespace Mono.Linker.Steps {
MarkNamedMethod (type, method_name);
}
void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute attribute)
{
if (_context.KeepMembersForDebuggerAttributes) {
string displayString = (string) attribute.ConstructorArguments[0].Value;
Regex regex = new Regex ("{[^{}]+}", RegexOptions.Compiled);
foreach (Match match in regex.Matches (displayString)) {
// Remove '{' and '}'
string realMatch = match.Value.Substring (1, match.Value.Length - 2);
// Remove ",nq" suffix if present
// (it asks the expression evaluator to remove the quotes when displaying the final value)
if (Regex.IsMatch(realMatch, @".+,\s*nq")) {
realMatch = realMatch.Substring (0, realMatch.LastIndexOf (','));
}
if (realMatch.EndsWith ("()")) {
string methodName = realMatch.Substring (0, realMatch.Length - 2);
MethodDefinition method = GetMethodWithNoParameters (type, methodName);
if (method != null) {
MarkMethod (method);
continue;
}
} else {
FieldDefinition field = GetField (type, realMatch);
if (field != null) {
MarkField (field);
continue;
}
PropertyDefinition property = GetProperty (type, realMatch);
if (property != null) {
if (property.GetMethod != null) {
MarkMethod (property.GetMethod);
}
if (property.SetMethod != null) {
MarkMethod (property.SetMethod);
}
continue;
}
}
while (type != null) {
MarkMethods (type);
MarkFields (type, includeStatic: true);
type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
}
return;
}
}
}
void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute)
{
if (_context.KeepMembersForDebuggerAttributes) {
TypeReference proxyTypeReference = (TypeReference) attribute.ConstructorArguments [0].Value;
MarkType (proxyTypeReference);
TypeDefinition proxyType = ResolveTypeDefinition (proxyTypeReference);
MarkMethods (proxyType);
MarkFields (proxyType, includeStatic: true);
}
}
static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
{
argument = null;
@@ -784,6 +909,33 @@ namespace Mono.Linker.Steps {
return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
}
bool IsEventSource (TypeDefinition td)
{
TypeReference type = td;
do {
if (type.FullName == "System.Diagnostics.Tracing.EventSource") {
return true;
}
TypeDefinition typeDef = type.Resolve ();
if (typeDef == null) {
HandleUnresolvedType (type);
return false;
}
type = typeDef.BaseType;
} while (type != null);
return false;
}
void MarkEventSource (TypeDefinition td)
{
foreach (var nestedType in td.NestedTypes) {
if (nestedType.Name == "Keywords" || nestedType.Name == "Tasks" || nestedType.Name == "Opcodes") {
MarkStaticFields (nestedType);
}
}
}
protected TypeDefinition ResolveTypeDefinition (TypeReference type)
{
TypeDefinition td = type as TypeDefinition;
@@ -915,6 +1067,17 @@ namespace Mono.Linker.Steps {
}
}
protected void MarkStaticFields(TypeDefinition type)
{
if (!type.HasFields)
return;
foreach (FieldDefinition field in type.Fields) {
if (field.IsStatic)
MarkField (field);
}
}
protected virtual void MarkMethods (TypeDefinition type)
{
if (type.HasMethods)
@@ -943,17 +1106,19 @@ namespace Mono.Linker.Steps {
MethodDefinition method = ResolveMethodDefinition (reference);
if (method == null) {
try {
if (method == null) {
HandleUnresolvedMethod (reference);
return null;
}
if (Annotations.GetAction (method) == MethodAction.Nothing)
Annotations.SetAction (method, MethodAction.Parse);
EnqueueMethod (method);
} finally {
Annotations.Pop ();
throw new ResolutionException (reference);
}
if (Annotations.GetAction (method) == MethodAction.Nothing)
Annotations.SetAction (method, MethodAction.Parse);
EnqueueMethod (method);
Annotations.Pop ();
Annotations.AddDependency (method);
return method;
@@ -1029,6 +1194,10 @@ namespace Mono.Linker.Steps {
MarkCustomAttributes (method.MethodReturnType);
MarkMarshalSpec (method.MethodReturnType);
if (method.IsPInvokeImpl || method.IsInternalCall) {
ProcessInteropMethod (method);
}
if (ShouldParseMethodBody (method))
MarkMethodBody (method.Body);
@@ -1060,6 +1229,34 @@ namespace Mono.Linker.Steps {
}
}
void ProcessInteropMethod(MethodDefinition method)
{
TypeDefinition returnTypeDefinition = ResolveTypeDefinition (method.ReturnType);
const bool includeStaticFields = false;
if (returnTypeDefinition != null) {
MarkDefaultConstructor (returnTypeDefinition);
MarkFields (returnTypeDefinition, includeStaticFields);
}
if (method.HasThis) {
MarkFields (method.DeclaringType, includeStaticFields);
}
foreach (ParameterDefinition pd in method.Parameters) {
TypeReference paramTypeReference = pd.ParameterType;
if (paramTypeReference is TypeSpecification) {
paramTypeReference = (paramTypeReference as TypeSpecification).ElementType;
}
TypeDefinition paramTypeDefinition = ResolveTypeDefinition (paramTypeReference);
if (paramTypeDefinition != null) {
MarkFields (paramTypeDefinition, includeStaticFields);
if (pd.ParameterType.IsByReference) {
MarkDefaultConstructor (paramTypeDefinition);
}
}
}
}
bool ShouldParseMethodBody (MethodDefinition method)
{
if (!method.HasBody)
@@ -1076,6 +1273,11 @@ namespace Mono.Linker.Steps {
(md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
}
static internal bool IsPublicInstancePropertyMethod (MethodDefinition md)
{
return md.IsPublic && !md.IsStatic && IsPropertyMethod (md);
}
static bool IsEventMethod (MethodDefinition md)
{
return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
@@ -1162,5 +1364,15 @@ namespace Mono.Linker.Steps {
break;
}
}
protected virtual void HandleUnresolvedType (TypeReference reference)
{
throw new ResolutionException (reference);
}
protected virtual void HandleUnresolvedMethod (MethodReference reference)
{
throw new ResolutionException (reference);
}
}
}

View File

@@ -78,6 +78,7 @@ namespace Mono.Linker.Steps {
if (File.Exists (target)) {
File.Delete (target);
File.Delete (target + ".mdb");
File.Delete (Path.ChangeExtension (target, "pdb"));
File.Delete (GetConfigFile (target));
}
break;
@@ -144,15 +145,18 @@ namespace Mono.Linker.Steps {
if (!symbols)
return;
source += ".mdb";
if (!File.Exists (source))
return;
File.Copy (source, target + ".mdb", true);
var mdb = source + ".mdb";
if (File.Exists (mdb))
File.Copy (mdb, target + ".mdb", true);
var pdb = Path.ChangeExtension (source, "pdb");
if (File.Exists (pdb))
File.Copy (pdb, Path.ChangeExtension (target, "pdb"), true);
}
static string GetAssemblyFileName (AssemblyDefinition assembly, string directory)
{
string file = assembly.Name.Name + (assembly.MainModule.Kind == ModuleKind.Dll ? ".dll" : ".exe");
string file = GetOriginalAssemblyFileInfo (assembly).Name;
return Path.Combine (directory, file);
}
}

View File

@@ -26,6 +26,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using Mono.Cecil;
@@ -35,10 +36,20 @@ namespace Mono.Linker.Steps {
AssemblyDefinition _assembly;
string _file;
RootVisibility _rootVisibility;
public ResolveFromAssemblyStep (string assembly)
public enum RootVisibility
{
Any = 0,
PublicAndFamily = 1,
PublicAndFamilyAndAssembly = 2
}
public ResolveFromAssemblyStep (string assembly, RootVisibility rootVisibility = RootVisibility.Any)
{
_file = assembly;
_rootVisibility = rootVisibility;
}
public ResolveFromAssemblyStep (AssemblyDefinition assembly)
@@ -53,9 +64,13 @@ namespace Mono.Linker.Steps {
AssemblyDefinition assembly = _assembly ?? Context.Resolve (_file);
if (_rootVisibility != RootVisibility.Any && HasInternalsVisibleTo (assembly)) {
_rootVisibility = RootVisibility.PublicAndFamilyAndAssembly;
}
switch (assembly.MainModule.Kind) {
case ModuleKind.Dll:
ProcessLibrary (Context, assembly);
ProcessLibrary (Context, assembly, _rootVisibility);
break;
default:
ProcessExecutable (assembly);
@@ -75,31 +90,78 @@ namespace Mono.Linker.Steps {
context.SafeReadSymbols (assembly);
}
public static void ProcessLibrary (LinkContext context, AssemblyDefinition assembly)
public static void ProcessLibrary (LinkContext context, AssemblyDefinition assembly, RootVisibility rootVisibility = RootVisibility.Any)
{
SetAction (context, assembly, AssemblyAction.Copy);
var action = rootVisibility == RootVisibility.Any ? AssemblyAction.Copy : AssemblyAction.Link;
SetAction (context, assembly, action);
context.Annotations.Push (assembly);
foreach (TypeDefinition type in assembly.MainModule.Types)
MarkType (context, type);
MarkType (context, type, rootVisibility);
if (assembly.MainModule.HasExportedTypes) {
foreach (var exported in assembly.MainModule.ExportedTypes) {
bool isForwarder = exported.IsForwarder;
var declaringType = exported.DeclaringType;
while (!isForwarder && (declaringType != null)) {
isForwarder = declaringType.IsForwarder;
declaringType = declaringType.DeclaringType;
}
if (!isForwarder)
continue;
TypeDefinition resolvedExportedType = null;
try {
resolvedExportedType = exported.Resolve ();
}
catch (AssemblyResolutionException) {
continue;
}
context.Resolve (resolvedExportedType.Scope);
MarkType (context, resolvedExportedType, rootVisibility);
context.Annotations.Mark (exported);
if (context.KeepTypeForwarderOnlyAssemblies) {
context.Annotations.Mark (assembly.MainModule);
}
}
}
context.Annotations.Pop ();
}
static void MarkType (LinkContext context, TypeDefinition type)
static void MarkType (LinkContext context, TypeDefinition type, RootVisibility rootVisibility)
{
bool markType;
switch (rootVisibility) {
default:
markType = true;
break;
case RootVisibility.PublicAndFamilyAndAssembly:
markType = !type.IsNestedPrivate;
break;
case RootVisibility.PublicAndFamily:
markType = type.IsPublic || type.IsNestedPublic || type.IsNestedFamily || type.IsNestedFamilyOrAssembly;
break;
}
if (!markType) {
return;
}
context.Annotations.Mark (type);
context.Annotations.Push (type);
if (type.HasFields)
MarkFields (context, type.Fields);
MarkFields (context, type.Fields, rootVisibility);
if (type.HasMethods)
MarkMethods (context, type.Methods);
MarkMethods (context, type.Methods, rootVisibility);
if (type.HasNestedTypes)
foreach (var nested in type.NestedTypes)
MarkType (context, nested);
MarkType (context, nested, rootVisibility);
context.Annotations.Pop ();
}
@@ -111,27 +173,73 @@ namespace Mono.Linker.Steps {
Annotations.Push (assembly);
Annotations.Mark (assembly.EntryPoint.DeclaringType);
MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse);
MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse, RootVisibility.Any);
Annotations.Pop ();
}
static void MarkFields (LinkContext context, ICollection fields)
static void MarkFields (LinkContext context, ICollection fields, RootVisibility rootVisibility)
{
foreach (FieldDefinition field in fields)
context.Annotations.Mark (field);
foreach (FieldDefinition field in fields) {
bool markField;
switch (rootVisibility) {
default:
markField = true;
break;
case RootVisibility.PublicAndFamily:
markField = field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly;
break;
case RootVisibility.PublicAndFamilyAndAssembly:
markField = field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly || field.IsAssembly || field.IsFamilyAndAssembly;
break;
}
if (markField) {
context.Annotations.Mark (field);
}
}
}
static void MarkMethods (LinkContext context, ICollection methods)
static void MarkMethods (LinkContext context, ICollection methods, RootVisibility rootVisibility)
{
foreach (MethodDefinition method in methods)
MarkMethod (context, method, MethodAction.ForceParse);
MarkMethod (context, method, MethodAction.ForceParse, rootVisibility);
}
static void MarkMethod (LinkContext context, MethodDefinition method, MethodAction action)
static void MarkMethod (LinkContext context, MethodDefinition method, MethodAction action, RootVisibility rootVisibility)
{
context.Annotations.Mark (method);
context.Annotations.SetAction (method, action);
bool markMethod;
switch (rootVisibility) {
default:
markMethod = true;
break;
case RootVisibility.PublicAndFamily:
markMethod = method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly;
break;
case RootVisibility.PublicAndFamilyAndAssembly:
markMethod = method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly || method.IsAssembly || method.IsFamilyAndAssembly;
break;
}
if (markMethod) {
context.Annotations.Mark (method);
context.Annotations.SetAction (method, action);
}
}
static bool HasInternalsVisibleTo (AssemblyDefinition assembly)
{
foreach (CustomAttribute attribute in assembly.CustomAttributes) {
if (attribute.Constructor.DeclaringType.FullName ==
"System.Runtime.CompilerServices.InternalsVisibleToAttribute")
return true;
}
return false;
}
}
}

View File

@@ -129,14 +129,14 @@ namespace Mono.Linker.Steps {
if (type == null) {
if (assembly.MainModule.HasExportedTypes) {
foreach (var exported in assembly.MainModule.ExportedTypes) {
if (fullname == exported.FullName) {
if (fullname == exported.FullName) {
Annotations.Mark (exported);
Annotations.Mark (assembly.MainModule);
var resolvedExternal = exported.Resolve ();
if (resolvedExternal != null) {
type = resolvedExternal;
break;
}
Annotations.Mark (assembly.MainModule);
var resolvedExternal = exported.Resolve ();
if (resolvedExternal != null) {
type = resolvedExternal;
break;
}
}
}
}
@@ -173,12 +173,17 @@ namespace Mono.Linker.Steps {
void MatchExportedType (ExportedType exportedType, ModuleDefinition module, Regex regex, XPathNavigator nav)
{
if (regex.Match (exportedType.FullName).Success) {
if (regex.Match (exportedType.FullName).Success) {
Annotations.Mark (exportedType);
Annotations.Mark (module);
var type = exportedType.Resolve ();
if (type != null) {
ProcessType (type, nav);
Annotations.Mark (module);
TypeDefinition type = null;
try {
type = exportedType.Resolve ();
}
catch (AssemblyResolutionException) {
}
if (type != null) {
ProcessType (type, nav);
}
}
}
@@ -399,8 +404,7 @@ namespace Mono.Linker.Steps {
static void ProcessReferences (AssemblyDefinition assembly, LinkContext context)
{
foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences)
context.Resolve (name);
context.ResolveReferences (assembly);
}
static bool IsRequired (XPathNavigator nav)

View File

@@ -34,7 +34,7 @@ namespace Mono.Linker.Steps {
ArrayList _unResolved;
internal ResolveStep ()
protected ResolveStep ()
{
_unResolved = new ArrayList ();
}

View File

@@ -29,8 +29,10 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Collections.Generic;
using Mono.Cecil.Cil;
namespace Mono.Linker.Steps {
@@ -38,30 +40,37 @@ namespace Mono.Linker.Steps {
AssemblyDefinition [] assemblies;
HashSet<AssemblyDefinition> resolvedTypeReferences;
readonly bool sweepSymbols;
public SweepStep (bool sweepSymbols = true)
{
this.sweepSymbols = sweepSymbols;
}
protected override void Process ()
{
assemblies = Context.GetAssemblies ();
assemblies = Context.Annotations.GetAssemblies ().ToArray ();
foreach (var assembly in assemblies) {
SweepAssembly (assembly);
if (Annotations.GetAction (assembly) == AssemblyAction.Copy) {
// Copy assemblies can still contain Type references with
// type forwarders from Delete assemblies
// thus try to resolve all the type references and see
// if some changed the scope. if yes change the action to Save
if (ResolveAllTypeReferences (assembly))
Annotations.SetAction (assembly, AssemblyAction.Save);
if ((Annotations.GetAction (assembly) == AssemblyAction.Copy) &&
!Context.KeepTypeForwarderOnlyAssemblies) {
// Copy assemblies can still contain Type references with
// type forwarders from Delete assemblies
// thus try to resolve all the type references and see
// if some changed the scope. if yes change the action to Save
if (ResolveAllTypeReferences (assembly))
Annotations.SetAction (assembly, AssemblyAction.Save);
}
AssemblyAction currentAction = Annotations.GetAction(assembly);
if ((currentAction == AssemblyAction.Link) || (currentAction == AssemblyAction.Save)) {
// if we save (only or by linking) then unmarked exports (e.g. forwarders) must be cleaned
// or they can point to nothing which will break later (e.g. when re-loading for stripping IL)
// reference: https://bugzilla.xamarin.com/show_bug.cgi?id=36577
if (assembly.MainModule.HasExportedTypes)
SweepCollection(assembly.MainModule.ExportedTypes);
}
AssemblyAction currentAction = Annotations.GetAction(assembly);
if ((currentAction == AssemblyAction.Link) || (currentAction == AssemblyAction.Save)) {
// if we save (only or by linking) then unmarked exports (e.g. forwarders) must be cleaned
// or they can point to nothing which will break later (e.g. when re-loading for stripping IL)
// reference: https://bugzilla.xamarin.com/show_bug.cgi?id=36577
if (assembly.MainModule.HasExportedTypes)
SweepCollection(assembly.MainModule.ExportedTypes);
}
}
}
@@ -119,7 +128,13 @@ namespace Mono.Linker.Steps {
var references = assembly.MainModule.AssemblyReferences;
for (int i = 0; i < references.Count; i++) {
var reference = references [i];
var r = Context.Resolver.Resolve (reference);
AssemblyDefinition r = null;
try {
r = Context.Resolver.Resolve (reference);
}
catch (AssemblyResolutionException) {
continue;
}
if (!AreSameReference (r.Name, target.Name))
continue;
@@ -131,12 +146,16 @@ namespace Mono.Linker.Steps {
// Copy means even if "unlinked" we still want that assembly to be saved back
// to disk (OutputStep) without the (removed) reference
Annotations.SetAction (assembly, AssemblyAction.Save);
ResolveAllTypeReferences (assembly);
if (!Context.KeepTypeForwarderOnlyAssemblies) {
ResolveAllTypeReferences (assembly);
}
break;
case AssemblyAction.Save:
case AssemblyAction.Link:
ResolveAllTypeReferences (assembly);
if (!Context.KeepTypeForwarderOnlyAssemblies) {
ResolveAllTypeReferences (assembly);
}
break;
}
return;
@@ -175,6 +194,7 @@ namespace Mono.Linker.Steps {
if ((td != null) && Annotations.IsMarked (td)) {
scope = assembly.MainModule.ImportReference (td).Scope;
hash.Add (td, scope);
et.Scope = scope;
}
}
}
@@ -190,19 +210,19 @@ namespace Mono.Linker.Steps {
return changes;
}
void SweepType (TypeDefinition type)
protected virtual void SweepType (TypeDefinition type)
{
if (type.HasFields)
SweepCollection (type.Fields);
if (type.HasMethods)
SweepCollection (type.Methods);
SweepMethods (type.Methods);
if (type.HasNestedTypes)
SweepNestedTypes (type);
}
void SweepNestedTypes (TypeDefinition type)
protected void SweepNestedTypes (TypeDefinition type)
{
for (int i = 0; i < type.NestedTypes.Count; i++) {
var nested = type.NestedTypes [i];
@@ -214,7 +234,59 @@ namespace Mono.Linker.Steps {
}
}
void SweepCollection (IList list)
void SweepMethods (Collection<MethodDefinition> methods)
{
SweepCollection (methods);
if (sweepSymbols)
SweepDebugInfo (methods);
}
void SweepDebugInfo (Collection<MethodDefinition> methods)
{
List<ScopeDebugInformation> sweptScopes = null;
foreach (var m in methods) {
if (m.DebugInformation == null)
continue;
var scope = m.DebugInformation.Scope;
if (scope == null)
continue;
if (sweptScopes == null) {
sweptScopes = new List<ScopeDebugInformation> ();
} else if (sweptScopes.Contains (scope)) {
continue;
}
sweptScopes.Add (scope);
if (scope.HasConstants) {
var constants = scope.Constants;
for (int i = 0; i < constants.Count; ++i) {
if (!Annotations.IsMarked (constants [i].ConstantType))
constants.RemoveAt (i--);
}
}
var import = scope.Import;
while (import != null) {
if (import.HasTargets) {
var targets = import.Targets;
for (int i = 0; i < targets.Count; ++i) {
var ttype = targets [i].Type;
if (ttype != null && !Annotations.IsMarked (ttype))
targets.RemoveAt (i--);
// TODO: Clear also AssemblyReference and Namespace when not marked
}
}
import = import.Parent;
}
}
}
protected void SweepCollection (IList list)
{
for (int i = 0; i < list.Count; i++)
if (!Annotations.IsMarked ((IMetadataTokenProvider) list [i]))

View File

@@ -1,5 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<!--
TODO: Remove this workaround once supported.
The configuration isn't correctly set when the linker is
restored as a P2P reference due to a nuget bug
(https://github.com/NuGet/Home/issues/4873). As a workaround, we
check NuGetRestoreTargets, which is set by the .NET Core restore
targets.
-->
<PropertyGroup>
<NetCoreBuild Condition=" $(Configuration.StartsWith('netcore')) Or '$(NuGetRestoreTargets)' != '' ">true</NetCoreBuild>
<NetCoreBuild Condition=" '$(NetCoreBuild)' == '' ">false</NetCoreBuild>
</PropertyGroup>
<Import Project="NetCore.props" Condition=" $(NetCoreBuild) " />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -9,7 +23,8 @@
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Mono.Linker</RootNamespace>
<AssemblyName>monolinker</AssemblyName>
<AssemblyName Condition=" ! $(NetCoreBuild) ">monolinker</AssemblyName>
<AssemblyName Condition=" $(NetCoreBuild) ">illink</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -29,7 +44,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" Condition=" ! $(NetCoreBuild) " />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
@@ -37,7 +52,7 @@
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<ItemGroup Condition=" ! $(Configuration.StartsWith('netcore')) ">
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
@@ -63,15 +78,18 @@
<Compile Include="Mono.Linker\AssemblyAction.cs" />
<Compile Include="Mono.Linker\AssemblyInfo.cs" />
<Compile Include="Mono.Linker\AssemblyResolver.cs" />
<Compile Include="Mono.Linker\DirectoryAssemblyResolver.cs" />
<Compile Include="Mono.Linker\Driver.cs" />
<Compile Include="Mono.Linker\LinkContext.cs" />
<Compile Include="Mono.Linker\LoadException.cs" />
<Compile Include="Mono.Linker\MarkException.cs" />
<Compile Include="Mono.Linker\MethodAction.cs" />
<Compile Include="Mono.Linker\Pipeline.cs" />
<Compile Include="Mono.Linker\TypePreserve.cs" />
<Compile Include="Mono.Linker\XApiReader.cs" />
<Compile Include="Mono.Linker.Steps\TypeMapStep.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(DoNotEmbedDescriptors)' == '' ">
<ItemGroup Condition=" '$(DoNotEmbedDescriptors)' == '' AND ! $(NetCoreBuild) ">
<EmbeddedResource Include="Descriptors\mscorlib.xml">
<LogicalName>mscorlib.xml</LogicalName>
</EmbeddedResource>
@@ -91,14 +109,26 @@
<LogicalName>System.Core.xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Makefile" />
<None Include="README" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<SetConfiguration Condition=" '$(Configuration)' == 'netcore_Debug' ">Configuration=netstandard_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'netcore_Release' ">Configuration=netstandard_Release</SetConfiguration>
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
</ItemGroup>
</Project>
<ItemGroup Condition=" $(NetCoreBuild) ">
<ProjectReference Include="..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<SetConfiguration Condition=" '$(Configuration)' == 'netcore_Debug' ">Configuration=netstandard_Debug</SetConfiguration>
<SetConfiguration Condition=" '$(Configuration)' == 'netcore_Release' ">Configuration=netstandard_Release</SetConfiguration>
<Project>{63E6915C-7EA4-4D76-AB28-0D7191EEA626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -78,6 +78,11 @@ namespace Mono.Linker {
writer.WriteEndAttribute ();
}
public ICollection<AssemblyDefinition> GetAssemblies ()
{
return assembly_actions.Keys;
}
public AssemblyAction GetAction (AssemblyDefinition assembly)
{
AssemblyAction action;
@@ -139,7 +144,32 @@ namespace Mono.Linker {
public void SetPreserve (TypeDefinition type, TypePreserve preserve)
{
preserved_types [type] = 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)
@@ -316,9 +346,6 @@ namespace Mono.Linker {
writer.WriteEndElement ();
writer.WriteEndDocument ();
writer.Flush ();
writer.Close ();
zipStream.Close ();
writer.Dispose ();
zipStream.Dispose ();
writer = null;

View File

@@ -28,12 +28,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
namespace Mono.Linker {
#if NET_CORE
public class AssemblyResolver : DirectoryAssemblyResolver {
#else
public class AssemblyResolver : BaseAssemblyResolver {
#endif
IDictionary _assemblies;
@@ -42,7 +47,7 @@ namespace Mono.Linker {
}
public AssemblyResolver ()
: this (new Hashtable ())
: this (new Dictionary<string, AssemblyDefinition> (StringComparer.OrdinalIgnoreCase))
{
}
@@ -56,7 +61,7 @@ namespace Mono.Linker {
AssemblyDefinition asm = (AssemblyDefinition) _assemblies [name.Name];
if (asm == null) {
asm = base.Resolve (name, parameters);
_assemblies [name.Name] = asm;
_assemblies [asm.Name.Name] = asm;
}
return asm;

View File

@@ -0,0 +1,92 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
using Mono.Collections.Generic;
using Mono.Cecil;
#if NET_CORE
namespace Mono.Linker {
public abstract class DirectoryAssemblyResolver : IAssemblyResolver {
readonly Collection<string> directories;
public void AddSearchDirectory (string directory)
{
directories.Add (directory);
}
public void RemoveSearchDirectory (string directory)
{
directories.Remove (directory);
}
public string [] GetSearchDirectories ()
{
return this.directories.ToArray ();
}
protected DirectoryAssemblyResolver ()
{
directories = new Collection<string> (2) { "." };
}
AssemblyDefinition GetAssembly (string file, ReaderParameters parameters)
{
if (parameters.AssemblyResolver == null)
parameters.AssemblyResolver = this;
return ModuleDefinition.ReadModule (file, parameters).Assembly;
}
public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
{
return Resolve (name, new ReaderParameters ());
}
public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
{
if (name == null)
throw new ArgumentNullException ("name");
if (parameters == null)
parameters = new ReaderParameters ();
var assembly = SearchDirectory (name, directories, parameters);
if (assembly != null)
return assembly;
throw new AssemblyResolutionException (name);
}
AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable<string> directories, ReaderParameters parameters)
{
var extensions = new [] { ".dll", ".exe" };
foreach (var directory in directories) {
foreach (var extension in extensions) {
string file = Path.Combine (directory, name.Name + extension);
if (!File.Exists (file))
continue;
try {
return GetAssembly (file, parameters);
} catch (System.BadImageFormatException) {
continue;
}
}
}
return null;
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
protected virtual void Dispose (bool disposing)
{
}
}
}
#endif

View File

@@ -38,7 +38,11 @@ namespace Mono.Linker {
public class Driver {
#if NET_CORE
static readonly string _linker = "IL Linker";
#else
static readonly string _linker = "Mono CIL Linker";
#endif
public static int Main (string [] args)
{
@@ -124,14 +128,21 @@ namespace Mono.Linker {
case 's':
custom_steps.Add (GetParam ());
break;
case 't':
context.KeepTypeForwarderOnlyAssemblies = true;
break;
case 'x':
foreach (string file in GetFiles (GetParam ()))
p.PrependStep (new ResolveFromXmlStep (new XPathDocument (file)));
resolver = true;
break;
case 'r':
case 'a':
var rootVisibility = (token[1] == 'r')
? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily
: ResolveFromAssemblyStep.RootVisibility.Any;
foreach (string file in GetFiles (GetParam ()))
p.PrependStep (new ResolveFromAssemblyStep (file));
p.PrependStep (new ResolveFromAssemblyStep (file, rootVisibility));
resolver = true;
break;
case 'i':
@@ -152,6 +163,9 @@ namespace Mono.Linker {
if (!bool.Parse (GetParam ()))
p.RemoveStep (typeof (RegenerateGuidStep));
break;
case 'v':
context.KeepMembersForDebuggerAttributes = bool.Parse (GetParam ());
break;
default:
Usage ("Unknown option: `" + token [1] + "'");
break;
@@ -169,7 +183,7 @@ namespace Mono.Linker {
p.Process (context);
}
static void AddCustomStep (Pipeline pipeline, string arg)
protected static void AddCustomStep (Pipeline pipeline, string arg)
{
int pos = arg.IndexOf (":");
if (pos == -1) {
@@ -230,7 +244,7 @@ namespace Mono.Linker {
return (string []) lines.ToArray (typeof (string));
}
static I18nAssemblies ParseI18n (string str)
protected static I18nAssemblies ParseI18n (string str)
{
I18nAssemblies assemblies = I18nAssemblies.None;
string [] parts = str.Split (',');
@@ -266,7 +280,11 @@ namespace Mono.Linker {
Console.WriteLine (_linker);
if (msg != null)
Console.WriteLine ("Error: " + msg);
#if NET_CORE
Console.WriteLine ("illink [options] -x|-a|-i file");
#else
Console.WriteLine ("monolinker [options] -x|-a|-i file");
#endif
Console.WriteLine (" --about About the {0}", _linker);
Console.WriteLine (" --version Print the version number of the {0}", _linker);
@@ -274,14 +292,17 @@ namespace Mono.Linker {
Console.WriteLine (" -c Action on the core assemblies, skip, copy or link, default to skip");
Console.WriteLine (" -p Action per assembly");
Console.WriteLine (" -s Add a new step to the pipeline.");
Console.WriteLine (" -t Keep assemblies in which only type forwarders are referenced.");
Console.WriteLine (" -d Add a directory where the linker will look for assemblies");
Console.WriteLine (" -b Generate debug symbols for each linked module (true or false)");
Console.WriteLine (" -g Generate a new unique guid for each linked module (true or false)");
Console.WriteLine (" -v Keep memebers needed by debugger attributes (true or false)");
Console.WriteLine (" -l List of i18n assemblies to copy to the output directory");
Console.WriteLine (" separated with a comma: none,all,cjk,mideast,other,rare,west");
Console.WriteLine (" default is all");
Console.WriteLine (" -x Link from an XML descriptor");
Console.WriteLine (" -a Link from a list of assemblies");
Console.WriteLine (" -r Link from a list of assemblies using roots visible outside of the assembly");
Console.WriteLine (" -i Link from an mono-api-info descriptor");
Console.WriteLine ("");

View File

@@ -28,8 +28,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -43,6 +43,8 @@ namespace Mono.Linker {
string _outputDirectory;
Hashtable _parameters;
bool _linkSymbols;
bool _keepTypeForwarderOnlyAssemblies;
bool _keepMembersForDebuggerAttributes;
AssemblyResolver _resolver;
@@ -75,6 +77,18 @@ namespace Mono.Linker {
set { _linkSymbols = value; }
}
public bool KeepTypeForwarderOnlyAssemblies
{
get { return _keepTypeForwarderOnlyAssemblies; }
set { _keepTypeForwarderOnlyAssemblies = value; }
}
public bool KeepMembersForDebuggerAttributes
{
get { return _keepMembersForDebuggerAttributes; }
set { _keepMembersForDebuggerAttributes = value; }
}
public IDictionary Actions {
get { return _actions; }
}
@@ -83,6 +97,10 @@ namespace Mono.Linker {
get { return _resolver; }
}
public ReaderParameters ReaderParameters {
get { return _readerParameters; }
}
public ISymbolReaderProvider SymbolReaderProvider {
get { return _symbolReaderProvider; }
set { _symbolReaderProvider = value; }
@@ -101,15 +119,21 @@ namespace Mono.Linker {
}
public LinkContext (Pipeline pipeline, AssemblyResolver resolver)
: this(pipeline, resolver, new ReaderParameters
{
AssemblyResolver = resolver
})
{
}
public LinkContext (Pipeline pipeline, AssemblyResolver resolver, ReaderParameters readerParameters)
{
_pipeline = pipeline;
_resolver = resolver;
_actions = new Hashtable ();
_parameters = new Hashtable ();
_annotations = new AnnotationStore ();
_readerParameters = new ReaderParameters {
AssemblyResolver = _resolver,
};
_readerParameters = readerParameters;
}
public TypeDefinition GetType (string fullName)
@@ -161,12 +185,12 @@ namespace Mono.Linker {
}
}
bool SeenFirstTime (AssemblyDefinition assembly)
protected bool SeenFirstTime (AssemblyDefinition assembly)
{
return !_annotations.HasAction (assembly);
}
public void SafeReadSymbols (AssemblyDefinition assembly)
public virtual void SafeReadSymbols (AssemblyDefinition assembly)
{
if (!_linkSymbols)
return;
@@ -187,6 +211,19 @@ namespace Mono.Linker {
} catch {}
}
public virtual ICollection<AssemblyDefinition> ResolveReferences (AssemblyDefinition assembly)
{
List<AssemblyDefinition> references = new List<AssemblyDefinition> ();
foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) {
try {
references.Add (Resolve (reference));
}
catch (AssemblyResolutionException) {
}
}
return references;
}
static AssemblyNameReference GetReference (IMetadataScope scope)
{
AssemblyNameReference reference;
@@ -199,7 +236,7 @@ namespace Mono.Linker {
return reference;
}
void SetAction (AssemblyDefinition assembly)
protected void SetAction (AssemblyDefinition assembly)
{
AssemblyAction action = AssemblyAction.Link;

View File

@@ -0,0 +1,17 @@
using System;
namespace Mono.Linker
{
public class LoadException : Exception
{
public LoadException (string message)
: base (message)
{
}
public LoadException (string message, Exception innerException)
: base (message, innerException)
{
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
namespace Mono.Linker
{
public class MarkException : Exception
{
public MarkException (string message)
: base (message)
{
}
public MarkException (string message, Exception innerException)
: base (message, innerException)
{
}
}
}

View File

@@ -65,6 +65,16 @@ namespace Mono.Linker {
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);

13
external/linker/linker/NetCore.props vendored Normal file
View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<RuntimeFrameworkVersion>2.0.0-beta-001509-00</RuntimeFrameworkVersion>
<DefineConstants>$(DefineConstants);NET_CORE</DefineConstants>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AssemblyName>illink</AssemblyName>
<OutputType>exe</OutputType>
</PropertyGroup>
</Project>