Imported Upstream version 6.12.0.86

Former-commit-id: 7a84ce7d08c42c458ac8e74b27186ca863315d79
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-07-10 08:44:59 +00:00
parent 92747312ea
commit 0b380204a4
812 changed files with 26901 additions and 9053 deletions

View File

@@ -1,18 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(MSBuildThisFileDirectory)../../eng/Versions.props" Condition=" '$(ArcadeBuild)' != 'true' " />
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net472</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<BaseOutputPath>bin/</BaseOutputPath>
<PackageOutputPath>$(BaseOutputPath)nupkgs</PackageOutputPath>
<IsPackable>true</IsPackable>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Description>MSBuild tasks for running the IL Linker</Description>
<Authors>$(AssemblyName)</Authors>
<!-- Don't include the build output. Instead, we want to include
the TargetFramework-specific publish output. -->
<IncludeBuildOutput>false</IncludeBuildOutput>
<!-- Suppress NuGet warning for package which sets IncludeBuildOutput=false, see https://github.com/NuGet/Home/issues/8583 -->
<NoWarn>$(NoWarn);NU5128</NoWarn>
<!-- We want to package the tasks package together with its
transitive dependencies and the linker, without marking them
as dependencies in the tasks package.
@@ -78,11 +75,8 @@
</Target>
<ItemGroup>
<ProjectReference Include="../linker/Mono.Linker.csproj"
PrivateAssets="All"
Condition=" '$(TargetFramework)' == 'netcoreapp2.0' " />
<ProjectReference Include="../../external/cecil/Mono.Cecil.csproj"
PrivateAssets="All" />
<ProjectReference Include="../linker/Mono.Linker.csproj" PrivateAssets="All" />
<ProjectReference Include="../../external/cecil/Mono.Cecil.csproj" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
@@ -90,16 +84,10 @@
<!-- We use private assets for the Microsoft.Build packages to
prevent them from being published with the tasks dll, because
these are already a part of the SDK. -->
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkVersion)"
PrivateAssets="All"
ExcludeAssets="Runtime" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCoreVersion)"
PrivateAssets="All"
ExcludeAssets="Runtime" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)"
Condition=" '$(TargetFramework)' == 'net472' "
PrivateAssets="All"
Publish="True" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkVersion)" PrivateAssets="All" ExcludeAssets="Runtime" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCoreVersion)" PrivateAssets="All" ExcludeAssets="Runtime" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" Condition=" '$(TargetFramework)' == 'net472' " PrivateAssets="All" Publish="True" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<_LinkTaskDirectoryRoot>$(MSBuildThisFileDirectory)../tools/</_LinkTaskDirectoryRoot>
<_LinkTaskTFM Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netcoreapp2.0</_LinkTaskTFM>
<_LinkTaskTFM Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netcoreapp3.0</_LinkTaskTFM>
<_LinkTaskTFM Condition=" '$(_LinkTaskTFM)' == '' ">net46</_LinkTaskTFM>
<_LinkTaskDirectory>$(_LinkTaskDirectoryRoot)$(_LinkTaskTFM)/</_LinkTaskDirectory>
<LinkTaskDllPath Condition=" '$(LinkTaskDllPath)' == '' ">$(_LinkTaskDirectory)ILLink.Tasks.dll</LinkTaskDllPath>

View File

@@ -111,7 +111,7 @@ namespace ILLink.Tasks
var taskDirectory = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);
// The linker always runs on .NET Core, even when using desktop MSBuild to host ILLink.Tasks.
_illinkPath = Path.Combine (Path.GetDirectoryName (taskDirectory), "netcoreapp2.0", "illink.dll");
_illinkPath = Path.Combine (Path.GetDirectoryName (taskDirectory), "netcoreapp3.0", "illink.dll");
return _illinkPath;
}
set => _illinkPath = value;

View File

@@ -13,7 +13,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<PropertyGroup>
<_ILLinkTasksDirectoryRoot Condition=" '$(_ILLinkTasksDirectoryRoot)' == '' ">$(MSBuildThisFileDirectory)../tools/</_ILLinkTasksDirectoryRoot>
<_ILLinkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netcoreapp2.0</_ILLinkTasksTFM>
<_ILLinkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core' ">netcoreapp3.0</_ILLinkTasksTFM>
<_ILLinkTasksTFM Condition=" '$(_ILLinkTasksTFM)' == '' ">net472</_ILLinkTasksTFM>
<_ILLinkTasksDirectory>$(_ILLinkTasksDirectoryRoot)$(_ILLinkTasksTFM)/</_ILLinkTasksDirectory>
<ILLinkTasksAssembly Condition=" '$(ILLinkTasksAssembly)' == '' ">$(_ILLinkTasksDirectory)ILLink.Tasks.dll</ILLinkTasksAssembly>

View File

@@ -1,49 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{4F328B3E-39C1-4E48-8093-F24390C58A5E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>LinkerAnalyzer</RootNamespace>
<AssemblyName>illinkanalyzer</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
<PropertyGroup Condition="'$(MonoBuild)' == ''">
<DefineConstants>$(DefineConstants);FEATURE_ILLINK</DefineConstants>
<TargetFrameworks>netcoreapp3.0;net471</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
<PropertyGroup Condition="'$(MonoBuild)' != ''">
<TargetFrameworks>net471</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<ProjectReference Include="../../external/cecil/Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleDependencyGraph.cs" />
<Compile Include="Main.cs" />
<Compile Include="LinkerAnalyzerCore\DependencyGraph.cs" />
<Compile Include="LinkerAnalyzerCore\SpaceAnalyzer.cs" />
<Compile Include="common\Mono.Options\Options.cs">
<Link>Options.cs</Link>
</Compile>
<ItemGroup Condition="'$(MonoBuild)' == ''">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -46,11 +46,11 @@ namespace Mono.Linker.Steps {
continue;
try {
Context.LogMessage ("Processing resource linker descriptor: {0}", name);
Context.LogMessage ($"Processing resource linker descriptor: {name}");
AddToPipeline (GetResolveStep (name));
} catch (XmlException ex) {
/* This could happen if some broken XML file is included. */
Context.LogMessage ("Error processing {0}: {1}", name, ex);
Context.LogMessage ($"Error processing {name}: {ex}");
}
}
@@ -62,12 +62,12 @@ namespace Mono.Linker.Steps {
.Where (res => ShouldProcessAssemblyResource (GetAssemblyName (res.Name)))
.Cast<EmbeddedResource> ()) {
try {
Context.LogMessage ("Processing embedded resource linker descriptor: {0}", rsc.Name);
Context.LogMessage ($"Processing embedded resource linker descriptor: {rsc.Name}");
AddToPipeline (GetExternalResolveStep (rsc, asm));
} catch (XmlException ex) {
/* This could happen if some broken XML file is embedded. */
Context.LogMessage ("Error processing {0}: {1}", rsc.Name, ex);
Context.LogMessage ($"Error processing {rsc.Name}: {ex}");
}
}
}
@@ -127,14 +127,14 @@ namespace Mono.Linker.Steps {
protected static XPathDocument GetExternalDescriptor (EmbeddedResource resource)
{
using (var sr = new StreamReader (resource.GetResourceStream ())) {
return new XPathDocument (new StringReader (sr.ReadToEnd ()));
return new XPathDocument (sr);
}
}
static XPathDocument GetDescriptor (string descriptor)
{
using (StreamReader sr = new StreamReader (GetResource (descriptor))) {
return new XPathDocument (new StringReader (sr.ReadToEnd ()));
return new XPathDocument (sr);
}
}

View File

@@ -0,0 +1,310 @@
using System;
using System.IO;
using System.Linq;
using System.Globalization;
using System.Xml.XPath;
using Mono.Cecil;
namespace Mono.Linker.Steps
{
public class BodySubstituterStep : BaseStep
{
protected override void Process ()
{
var files = Context.Substitutions;
if (files == null)
return;
foreach (var file in files) {
try {
ReadSubstitutionFile (GetSubstitutions (file));
} catch (Exception ex) when (!(ex is XmlResolutionException)) {
throw new XmlResolutionException ($"Failed to process XML substitution '{file}'", ex);
}
}
}
static XPathDocument GetSubstitutions (string substitutionsFile)
{
using (FileStream fs = File.OpenRead (substitutionsFile)) {
return GetSubstitutions (fs);
}
}
static XPathDocument GetSubstitutions (Stream substitutions)
{
using (StreamReader sr = new StreamReader (substitutions)) {
return new XPathDocument (sr);
}
}
void ReadSubstitutionFile (XPathDocument document)
{
XPathNavigator nav = document.CreateNavigator ();
// Initial structure check
if (!nav.MoveToChild ("linker", ""))
return;
// TODO: Add handling for feature
ProcessAssemblies (nav.SelectChildren ("assembly", ""));
}
void ProcessAssemblies (XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
var name = GetAssemblyName (iterator.Current);
var cache = Context.Resolver.AssemblyCache;
if (!cache.TryGetValue (name.Name, out AssemblyDefinition assembly)) {
Context.LogMessage (MessageImportance.Low, $"Could not match assembly '{name.FullName}' for substitution");
continue;
}
ProcessAssembly (assembly, iterator);
}
}
void ProcessAssembly (AssemblyDefinition assembly, XPathNodeIterator iterator)
{
ProcessTypes (assembly, iterator.Current.SelectChildren ("type", ""));
}
void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
XPathNavigator nav = iterator.Current;
string fullname = GetAttribute (nav, "fullname");
TypeDefinition type = assembly.MainModule.GetType (fullname);
if (type == null) {
Context.LogMessage (MessageImportance.Low, $"Could not resolve type '{fullname}' for substitution");
continue;
}
ProcessType (type, nav);
}
}
void ProcessType (TypeDefinition type, XPathNavigator nav)
{
if (!nav.HasChildren)
return;
XPathNodeIterator methods = nav.SelectChildren ("method", "");
if (methods.Count > 0)
ProcessMethods (type, methods);
var fields = nav.SelectChildren ("field", "");
if (fields.Count > 0) {
while (fields.MoveNext ())
ProcessField (type, fields);
}
}
void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
{
while (iterator.MoveNext ())
ProcessMethod (type, iterator);
}
void ProcessMethod (TypeDefinition type, XPathNodeIterator iterator)
{
string signature = GetAttribute (iterator.Current, "signature");
if (string.IsNullOrEmpty (signature))
return;
MethodDefinition method = FindMethod (type, signature);
if (method == null) {
Context.LogMessage (MessageImportance.Normal, $"Could not find method '{signature}' for substitution");
return;
}
string action = GetAttribute (iterator.Current, "body");
switch (action) {
case "remove":
Annotations.SetAction (method, MethodAction.ConvertToThrow);
return;
case "stub":
string value = GetAttribute (iterator.Current, "value");
if (value != "") {
if (!TryConvertValue (value, method.ReturnType, out object res)) {
Context.LogMessage (MessageImportance.High, $"Invalid value for '{signature}' stub");
return;
}
Annotations.SetMethodStubValue (method, res);
}
Annotations.SetAction (method, MethodAction.ConvertToStub);
return;
default:
Context.LogMessage (MessageImportance.High, $"Unknown body modification '{action}' for '{signature}'");
return;
}
}
void ProcessField (TypeDefinition type, XPathNodeIterator iterator)
{
string name = GetAttribute (iterator.Current, "name");
if (string.IsNullOrEmpty (name))
return;
var field = type.Fields.FirstOrDefault (f => f.Name == name);
if (field == null) {
Context.LogMessage (MessageImportance.Normal, $"Could not find field '{name}' for substitution.");
return;
}
if (!field.IsStatic || field.IsLiteral) {
Context.LogMessage (MessageImportance.Normal, $"Substituted field '{name}' needs to be static field.");
return;
}
string value = GetAttribute (iterator.Current, "value");
if (string.IsNullOrEmpty (value)) {
Context.LogMessage (MessageImportance.High, $"Missing 'value' attribute for field '{field}'.");
return;
}
if (!TryConvertValue (value, field.FieldType, out object res)) {
Context.LogMessage (MessageImportance.High, $"Invalid value for '{field}': '{value}'.");
return;
}
Annotations.SetFieldValue (field, res);
string init = GetAttribute (iterator.Current, "initialize");
if (init?.ToLowerInvariant () == "true") {
Annotations.SetSubstitutedInit (field);
}
}
static bool TryConvertValue (string value, TypeReference target, out object result)
{
switch (target.MetadataType) {
case MetadataType.Boolean:
if (bool.TryParse (value, out bool bvalue)) {
result = bvalue ? 1 : 0;
return true;
}
goto case MetadataType.Int32;
case MetadataType.Byte:
if (!byte.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out byte byteresult))
break;
result = (int) byteresult;
return true;
case MetadataType.SByte:
if (!sbyte.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out sbyte sbyteresult))
break;
result = (int) sbyteresult;
return true;
case MetadataType.Int16:
if (!short.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out short shortresult))
break;
result = (int) shortresult;
return true;
case MetadataType.UInt16:
if (!ushort.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort ushortresult))
break;
result = (int) ushortresult;
return true;
case MetadataType.Int32:
if (!int.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult))
break;
result = iresult;
return true;
case MetadataType.UInt32:
if (!uint.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint uresult))
break;
result = (int)uresult;
return true;
case MetadataType.Double:
if (!double.TryParse (value, NumberStyles.Float, CultureInfo.InvariantCulture, out double dresult))
break;
result = dresult;
return true;
case MetadataType.Single:
if (!float.TryParse (value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fresult))
break;
result = fresult;
return true;
case MetadataType.Int64:
if (!long.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long lresult))
break;
result = lresult;
return true;
case MetadataType.UInt64:
if (!ulong.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong ulresult))
break;
result = (long)ulresult;
return true;
case MetadataType.Char:
if (!char.TryParse (value, out char chresult))
break;
result = (int) chresult;
return true;
case MetadataType.String:
if (value is string || value == null) {
result = value;
return true;
}
break;
}
result = null;
return false;
}
static MethodDefinition FindMethod (TypeDefinition type, string signature)
{
if (!type.HasMethods)
return null;
foreach (MethodDefinition meth in type.Methods)
if (signature == ResolveFromXmlStep.GetMethodSignature (meth, includeGenericParameters: true))
return meth;
return null;
}
static AssemblyNameReference GetAssemblyName (XPathNavigator nav)
{
return AssemblyNameReference.Parse (GetAttribute (nav, "fullname"));
}
static string GetAttribute (XPathNavigator nav, string attribute)
{
return nav.GetAttribute (attribute, "");
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -26,10 +27,65 @@ namespace Mono.Linker.Steps {
ProcessMethod (method);
}
if (type.HasFields && Annotations.HasSubstitutedInit (type)) {
AddFieldsInitializations (type);
}
foreach (var nested in type.NestedTypes)
ProcessType (nested);
}
void AddFieldsInitializations (TypeDefinition type)
{
Instruction ret;
ILProcessor processor;
var cctor = type.Methods.FirstOrDefault (MethodDefinitionExtensions.IsStaticConstructor);
if (cctor == null) {
type.Attributes |= TypeAttributes.BeforeFieldInit;
var method = new MethodDefinition (".cctor",
MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
assembly.MainModule.TypeSystem.Void);
type.Methods.Add (method);
processor = method.Body.GetILProcessor ();
ret = Instruction.Create (OpCodes.Ret);
processor.Append (ret);
} else {
ret = cctor.Body.Instructions.Last (l => l.OpCode.Code == Code.Ret);
var body = cctor.Body;
processor = cctor.Body.GetILProcessor ();
for (int i = 0; i < body.Instructions.Count; ++i) {
var instr = body.Instructions [i];
if (instr.OpCode.Code != Code.Stsfld)
continue;
var field = (FieldReference)instr.Operand;
if (!Annotations.HasSubstitutedInit (field.Resolve ()))
continue;
processor.Replace (instr, Instruction.Create (OpCodes.Pop));
}
}
foreach (var field in type.Fields) {
if (!Annotations.HasSubstitutedInit (field))
continue;
Context.Annotations.TryGetFieldUserValue (field, out object value);
var valueInstr = CreateConstantResultInstruction (field.FieldType, value);
if (valueInstr == null)
throw new NotImplementedException (field.FieldType.ToString ());
processor.InsertBefore (ret, valueInstr);
processor.InsertBefore (ret, Instruction.Create (OpCodes.Stsfld, field));
}
}
void ProcessMethod (MethodDefinition method)
{
switch (Annotations.GetAction (method)) {
@@ -39,9 +95,6 @@ namespace Mono.Linker.Steps {
case MethodAction.ConvertToThrow:
RewriteBodyToLinkedAway (method);
break;
case MethodAction.ConvertToFalse:
RewriteBodyToFalse (method);
break;
}
}
@@ -65,28 +118,28 @@ namespace Mono.Linker.Steps {
method.ClearDebugInformation();
}
protected virtual void RewriteBodyToFalse (MethodDefinition method)
{
if (!method.IsIL)
throw new NotImplementedException ();
method.Body = CreateReturnFalseBody (method);
method.ClearDebugInformation();
}
MethodBody CreateThrowLinkedAwayBody (MethodDefinition method)
{
var body = new MethodBody (method);
var il = body.GetILProcessor ();
MethodReference ctor;
// Makes the body verifiable
if (method.IsConstructor && !method.DeclaringType.IsValueType) {
ctor = assembly.MainModule.ImportReference (Context.MarkedKnownMembers.ObjectCtor);
il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Call, ctor);
}
// import the method into the current assembly
MethodReference ctor = Context.MarkedKnownMembers.NotSupportedExceptionCtorString;
ctor = Context.MarkedKnownMembers.NotSupportedExceptionCtorString;
ctor = assembly.MainModule.ImportReference (ctor);
il.Emit (OpCodes.Ldstr, "Linked away");
il.Emit (OpCodes.Newobj, ctor);
il.Emit (OpCodes.Throw);
return body;
}
@@ -98,8 +151,11 @@ namespace Mono.Linker.Steps {
throw new NotImplementedException ();
var il = body.GetILProcessor ();
if (method.IsInstanceConstructor ()) {
if (method.IsInstanceConstructor () && !method.DeclaringType.IsValueType) {
var base_ctor = method.DeclaringType.BaseType.GetDefaultInstanceConstructor();
if (base_ctor == null)
throw new NotSupportedException ($"Cannot replace constructor for '{method.DeclaringType}' when no base default constructor exists");
base_ctor = assembly.MainModule.ImportReference (base_ctor);
il.Emit (OpCodes.Ldarg_0);
@@ -109,27 +165,114 @@ namespace Mono.Linker.Steps {
switch (method.ReturnType.MetadataType) {
case MetadataType.Void:
break;
case MetadataType.Boolean:
il.Emit (OpCodes.Ldc_I4_0);
break;
default:
throw new NotImplementedException (method.ReturnType.FullName);
var instruction = CreateConstantResultInstruction (Context, method);
if (instruction != null) {
il.Append (instruction);
} else {
StubComplexBody (method, body, il);
}
break;
}
il.Emit (OpCodes.Ret);
return body;
}
MethodBody CreateReturnFalseBody (MethodDefinition method)
static void StubComplexBody (MethodDefinition method, MethodBody body, ILProcessor il)
{
if (method.ReturnType.MetadataType != MetadataType.Boolean)
throw new NotImplementedException ();
switch (method.ReturnType.MetadataType) {
case MetadataType.MVar:
case MetadataType.ValueType:
var vd = new VariableDefinition (method.ReturnType);
body.Variables.Add (vd);
body.InitLocals = true;
var body = new MethodBody (method);
var il = body.GetILProcessor ();
il.Emit (OpCodes.Ldc_I4_0);
il.Emit (OpCodes.Ret);
return body;
il.Emit (OpCodes.Ldloca_S, vd);
il.Emit (OpCodes.Initobj, method.ReturnType);
il.Emit (OpCodes.Ldloc_0);
return;
case MetadataType.Pointer:
case MetadataType.IntPtr:
case MetadataType.UIntPtr:
il.Emit (OpCodes.Ldc_I4_0);
il.Emit (OpCodes.Conv_I);
return;
}
throw new NotImplementedException (method.FullName);
}
public static Instruction CreateConstantResultInstruction (LinkContext context, MethodDefinition method)
{
context.Annotations.TryGetMethodStubValue (method, out object value);
return CreateConstantResultInstruction (method.ReturnType, value);
}
public static Instruction CreateConstantResultInstruction (TypeReference rtype, object value = null)
{
switch (rtype.MetadataType) {
case MetadataType.ValueType:
var definition = rtype.Resolve ();
if (definition?.IsEnum == true) {
rtype = definition.GetEnumUnderlyingType ();
}
break;
case MetadataType.GenericInstance:
rtype = rtype.Resolve ();
break;
}
switch (rtype.MetadataType) {
case MetadataType.Boolean:
if (value is int bintValue && bintValue == 1)
return Instruction.Create (OpCodes.Ldc_I4_1);
return Instruction.Create (OpCodes.Ldc_I4_0);
case MetadataType.String:
if (value is string svalue)
return Instruction.Create (OpCodes.Ldstr, svalue);
return Instruction.Create (OpCodes.Ldnull);
case MetadataType.Object:
case MetadataType.Array:
case MetadataType.Class:
Debug.Assert (value == null);
return Instruction.Create (OpCodes.Ldnull);
case MetadataType.Double:
if (value is double dvalue)
return Instruction.Create (OpCodes.Ldc_R8, dvalue);
return Instruction.Create (OpCodes.Ldc_R8, 0.0);
case MetadataType.Single:
if (value is float fvalue)
return Instruction.Create (OpCodes.Ldc_R4, fvalue);
return Instruction.Create (OpCodes.Ldc_R4, 0.0f);
case MetadataType.Char:
case MetadataType.Byte:
case MetadataType.SByte:
case MetadataType.Int16:
case MetadataType.UInt16:
case MetadataType.Int32:
case MetadataType.UInt32:
if (value is int intValue)
return Instruction.Create (OpCodes.Ldc_I4, intValue);
return Instruction.Create (OpCodes.Ldc_I4_0);
case MetadataType.UInt64:
case MetadataType.Int64:
return Instruction.Create (OpCodes.Ldc_I8, 0L);
}
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
55bd31187c808a0374d8d10665a723aa621c5bab

View File

@@ -259,7 +259,7 @@ namespace Mono.Linker.Steps
{
if (method.Name == "get_UseManagedCollation")
{
annotations.SetAction(method, MethodAction.ConvertToFalse);
annotations.SetAction(method, MethodAction.ConvertToStub);
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -63,8 +63,13 @@ namespace Mono.Linker.Steps
if (_assembly != null)
Context.Resolver.CacheAssembly (_assembly);
AssemblyDefinition assembly = _assembly ?? Context.Resolve (_file);
var ignoreUnresolved = Context.Resolver.IgnoreUnresolved;
if (_rootVisibility == RootVisibility.PublicAndFamily) {
Context.Resolver.IgnoreUnresolved = false;
}
AssemblyDefinition assembly = _assembly ?? Context.Resolve (_file);
Context.Resolver.IgnoreUnresolved = ignoreUnresolved;
if (_rootVisibility != RootVisibility.Any && HasInternalsVisibleTo (assembly)) {
_rootVisibility = RootVisibility.PublicAndFamilyAndAssembly;
}

View File

@@ -462,18 +462,23 @@ namespace Mono.Linker.Steps {
{
if (type.HasMethods)
foreach (MethodDefinition meth in type.Methods)
if (signature == GetMethodSignature (meth))
if (signature == GetMethodSignature (meth, false))
return meth;
return null;
}
static string GetMethodSignature (MethodDefinition meth)
public static string GetMethodSignature (MethodDefinition meth, bool includeGenericParameters)
{
StringBuilder sb = new StringBuilder ();
sb.Append (meth.ReturnType.FullName);
sb.Append (" ");
sb.Append (meth.Name);
if (includeGenericParameters && meth.HasGenericParameters) {
sb.Append ("`");
sb.Append (meth.GenericParameters.Count);
}
sb.Append ("(");
if (meth.HasParameters) {
for (int i = 0; i < meth.Parameters.Count; i++) {

View File

@@ -39,6 +39,10 @@ namespace Mono.Linker {
protected readonly Dictionary<AssemblyDefinition, AssemblyAction> assembly_actions = new Dictionary<AssemblyDefinition, AssemblyAction> ();
protected readonly Dictionary<MethodDefinition, MethodAction> method_actions = new Dictionary<MethodDefinition, MethodAction> ();
protected readonly Dictionary<MethodDefinition, object> method_stub_values = new Dictionary<MethodDefinition, object> ();
protected readonly Dictionary<FieldDefinition, object> field_values = new Dictionary<FieldDefinition, object> ();
protected readonly HashSet<FieldDefinition> field_init = new HashSet<FieldDefinition> ();
protected readonly HashSet<TypeDefinition> fieldType_init = new HashSet<TypeDefinition> ();
protected readonly HashSet<IMetadataTokenProvider> marked = new HashSet<IMetadataTokenProvider> ();
protected readonly HashSet<IMetadataTokenProvider> processed = new HashSet<IMetadataTokenProvider> ();
protected readonly Dictionary<TypeDefinition, TypePreserve> preserved_types = new Dictionary<TypeDefinition, TypePreserve> ();
@@ -71,14 +75,13 @@ namespace Mono.Linker {
[Obsolete ("Use Tracer in LinkContext directly")]
public void PrepareDependenciesDump ()
{
Tracer.Start ();
Tracer.AddRecorder (new XmlDependencyRecorder (context));
}
[Obsolete ("Use Tracer in LinkContext directly")]
public void PrepareDependenciesDump (string filename)
{
Tracer.DependenciesFileName = filename;
Tracer.Start ();
Tracer.AddRecorder (new XmlDependencyRecorder (context, filename));
}
public ICollection<AssemblyDefinition> GetAssemblies ()
@@ -119,6 +122,36 @@ namespace Mono.Linker {
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);
@@ -233,6 +266,16 @@ namespace Mono.Linker {
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<string> GetResourcesToRemove (AssemblyDefinition assembly)
{
HashSet<string> resources;

View File

@@ -60,22 +60,27 @@ namespace Mono.Linker
return true;
}
static readonly string[] corlibNames = new [] {
"mscorlib",
"System.Runtime",
"System.Private.CoreLib",
"netstandard"
};
public static TypeDefinition FindPredefinedType (string ns, string name, LinkContext context)
{
var cache = context.Resolver.AssemblyCache;
AssemblyDefinition corlib;
TypeDefinition type = null;
if (cache.TryGetValue ("mscorlib", out corlib)) {
type = corlib.MainModule.GetType (ns, name);
foreach (var corlibName in corlibNames) {
if (!cache.TryGetValue (corlibName, out AssemblyDefinition corlib))
continue;
TypeDefinition type = corlib.MainModule.GetType (ns, name);
// The assembly could be a facade with type forwarders, in which case we don't find the type in this assembly.
if (type != null)
return type;
}
if (cache.TryGetValue ("System.Private.CoreLib", out corlib))
return corlib.MainModule.GetType (ns, name);
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public interface IDependencyRecorder
{
/// <summary>
/// Reports a dependency detected by the linker.
/// </summary>
/// <param name="source">The source of the dependency (for example the caller method).</param>
/// <param name="target">The target of the dependency (for example the callee method).</param>
/// <param name="marked">true if the target is also marked by the MarkStep.</param>
/// <remarks>The source and target are typically Cecil metadata objects (MethodDefinition, TypeDefinition, ...)
/// but they can also be the linker steps or really any other object.</remarks>
void RecordDependency (object source, object target, bool marked);
}
}

View File

@@ -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
{
/// <summary>
/// Interface which is called every time the linker inspects a pattern of code involving reflection to determine a more complex
/// dependency.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public interface IReflectionPatternRecorder
{
/// <summary>
/// Called when the linker recognized a reflection access pattern (and thus was able to correctly apply marking to the accessed item).
/// </summary>
/// <param name="sourceMethod">The method which contains the reflection access pattern.</param>
/// <param name="reflectionMethod">The reflection method which is at the heart of the access pattern.</param>
/// <param name="accessedItem">The item accessed through reflection. This can be one of:
/// TypeDefinition, MethodDefinition, PropertyDefinition, FieldDefinition, EventDefinition.</param>
void RecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, IMemberDefinition accessedItem);
/// <summary>
/// Called when the linker detected a reflection access but was not able to recognize the entire pattern.
/// </summary>
/// <param name="sourceMethod">The method which contains the reflection access code.</param>
/// <param name="reflectionMethod">The reflection method which is at the heart of the access code.</param>
/// <param name="message">Humanly readable message describing what failed during the pattern recognition.</param>
/// <remarks>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.</remarks>
void UnrecognizedReflectionAccessPattern (MethodDefinition sourceMethod, MethodDefinition reflectionMethod, string message);
}
}

View File

@@ -6,6 +6,7 @@ namespace Mono.Linker
{
public MethodDefinition NotSupportedExceptionCtorString { get; set; }
public MethodDefinition DisablePrivateReflectionAttributeCtor { get; set; }
public MethodDefinition ObjectCtor { get; set; }
public static bool IsNotSupportedExceptionCtorString (MethodDefinition method)
{

Some files were not shown because too many files have changed in this diff Show More