diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-06-29 13:07:18 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-29 13:07:18 +0300 |
commit | 25e1613eb2ae283990292472fa67d30ecd8f80b9 (patch) | |
tree | 7726916c03828e7a277066e029e89118bb134c64 /src/ILCompiler.Compiler | |
parent | f290974f13dd7b7857de30feece752607949dcb1 (diff) | |
parent | 602a88cec072f16fbf0628a534ac218496c8e710 (diff) |
Merge pull request #6032 from dotnet/master
Merge master to nmirror
Diffstat (limited to 'src/ILCompiler.Compiler')
14 files changed, 170 insertions, 13 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs index 64b2b33ad..a484a4f9b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs @@ -27,13 +27,14 @@ namespace ILCompiler public AnalysisBasedMetadataManager( CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, + ManifestResourceBlockingPolicy resourceBlockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy, IEnumerable<ModuleDesc> modulesWithMetadata, IEnumerable<ReflectableEntity<TypeDesc>> reflectableTypes, IEnumerable<ReflectableEntity<MethodDesc>> reflectableMethods, IEnumerable<ReflectableEntity<FieldDesc>> reflectableFields) - : base(typeSystemContext, blockingPolicy, logFile, stackTracePolicy) + : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy) { _modulesWithMetadata = new List<ModuleDesc>(modulesWithMetadata); diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs index 4feb7a582..9b822d89b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs @@ -505,7 +505,7 @@ namespace ILCompiler UniversalCanonGVMDepthHeuristic_NonCanonDepth = 2; UniversalCanonGVMDepthHeuristic_CanonDepth = 1; - // Unlike the GVM heuristics which are intended to kick in aggresively + // Unlike the GVM heuristics which are intended to kick in aggressively // this heuristic exists to make it so that a fair amount of generic // expansion is allowed. Numbers are chosen to allow a fairly large // amount of generic expansion before trimming. diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs index cc9dd6a2c..683343ffe 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs @@ -98,6 +98,11 @@ namespace ILCompiler.DependencyAnalysis } string resourceName = module.MetadataReader.GetString(resource.Name); + + // Check if emitting the manifest resource is blocked by policy. + if (factory.MetadataManager.IsManifestResourceBlocked(module, resourceName)) + continue; + string assemblyName = module.GetName().FullName; BlobReader reader = resourceDirectory.GetReader((int)resource.Offset, resourceDirectory.Length - (int)resource.Offset); int length = (int)reader.ReadUInt32(); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs index 490fcf309..f9226fe98 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs @@ -67,7 +67,7 @@ namespace ILCompiler } else { - return new PrecomputedMetadataManager(compilationModuleGroup, context, FindMetadataDescribingModuleInInputSet(inputModules), inputModules, inputMetadataOnlyAssemblies, ReadBytesFromFile(metadataFile), new UtcStackTraceEmissionPolicy()); + return new PrecomputedMetadataManager(compilationModuleGroup, context, FindMetadataDescribingModuleInInputSet(inputModules), inputModules, inputMetadataOnlyAssemblies, ReadBytesFromFile(metadataFile), new UtcStackTraceEmissionPolicy(), new NoManifestResourceBlockingPolicy()); } } diff --git a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs index 2ae053669..5217ec935 100644 --- a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs @@ -17,7 +17,7 @@ namespace ILCompiler public override bool SupportsReflection => false; public EmptyMetadataManager(CompilerTypeSystemContext typeSystemContext) - : base(typeSystemContext, new FullyBlockedMetadataPolicy()) + : base(typeSystemContext, new FullyBlockedMetadataPolicy(), new FullyBlockedManifestResourcePolicy()) { } @@ -108,5 +108,13 @@ namespace ILCompiler return true; } } + + private sealed class FullyBlockedManifestResourcePolicy : ManifestResourceBlockingPolicy + { + public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName) + { + return true; + } + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs new file mode 100644 index 000000000..dd53aa024 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + +namespace ILCompiler +{ + /// <summary> + /// A resource blocking policy that blocks RESX resources in framework assemblies. + /// This is useful for size-conscious scenarios where the conveniece of having + /// proper exception messages in framework-throw exceptions is not important. + /// </summary> + public sealed class FrameworkStringResourceBlockingPolicy : ManifestResourceBlockingPolicy + { + public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName) + { + // The embedded RESX files all have names that end with .resources, so use that as the initial filter. + if (!resourceName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) + return false; + + // Assuming multimodule and non-ecma assemblies are unsupported + EcmaModule ecmaModule = (EcmaModule)module; + + // If this is not a framework assembly, no resources are blocked + if (!IsFrameworkAssembly(ecmaModule)) + return false; + + MetadataReader reader = ecmaModule.MetadataReader; + + // We have a resource in the framework assembly. Now check if this is a RESX + foreach (ManifestResourceHandle resourceHandle in reader.ManifestResources) + { + ManifestResource resource = reader.GetManifestResource(resourceHandle); + if (reader.StringComparer.Equals(resource.Name, resourceName) && + resource.Implementation.IsNil) + { + PEMemoryBlock resourceDirectory = + ecmaModule.PEReader.GetSectionData(ecmaModule.PEReader.PEHeaders.CorHeader.ResourcesDirectory.RelativeVirtualAddress); + BlobReader blob = resourceDirectory.GetReader((int)resource.Offset, resourceDirectory.Length - (int)resource.Offset); + int length = (int)blob.ReadUInt32(); + if (length > 4) + { + // Check for magic bytes that correspond to RESX + if (blob.ReadUInt32() == 0xBEEFCACE) + return true; + } + } + } + + return false; + } + + /// <summary> + /// Gets a value indicating whether '<paramref name="module"/>' is a framework assembly. + /// </summary> + private static bool IsFrameworkAssembly(EcmaModule module) + { + MetadataReader reader = module.MetadataReader; + + // We look for [assembly:AssemblyMetadata(".NETFrameworkAssembly", "")] + + foreach (CustomAttributeHandle attributeHandle in reader.GetAssemblyDefinition().GetCustomAttributes()) + { + if (!reader.GetAttributeNamespaceAndName(attributeHandle, out StringHandle namespaceHandle, out StringHandle nameHandle)) + continue; + + if (!reader.StringComparer.Equals(namespaceHandle, "System.Reflection") || + !reader.StringComparer.Equals(nameHandle, "AssemblyMetadataAttribute")) + continue; + + var attributeTypeProvider = new CustomAttributeTypeProvider(module); + CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle); + CustomAttributeValue<TypeDesc> decodedAttribute = attribute.DecodeValue(attributeTypeProvider); + + if (decodedAttribute.FixedArguments.Length != 2) + continue; + + if (decodedAttribute.FixedArguments[0].Value is string s && s == ".NETFrameworkAssembly") + return true; + } + + return false; + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs index c4216775c..03879ed0b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs @@ -27,8 +27,8 @@ namespace ILCompiler protected readonly StackTraceEmissionPolicy _stackTraceEmissionPolicy; private readonly ModuleDesc _generatedAssembly; - public GeneratingMetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy) - : base(typeSystemContext, blockingPolicy) + public GeneratingMetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, ManifestResourceBlockingPolicy resourceBlockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy) + : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy) { _metadataLogFile = logFile; _stackTraceEmissionPolicy = stackTracePolicy; diff --git a/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs new file mode 100644 index 000000000..9f61db5bd --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.TypeSystem; + +namespace ILCompiler +{ + /// <summary> + /// Represents a manifest resource blocking policy. The policy dictates whether manifest resources should + /// be generated into the executable. + /// </summary> + public abstract class ManifestResourceBlockingPolicy + { + /// <summary> + /// Returns true if manifest resource with name '<paramref name="resourceName"/>' in module '<paramref name="module"/>' + /// is reflection blocked. + /// </summary> + public abstract bool IsManifestResourceBlocked(ModuleDesc module, string resourceName); + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs index 301c64572..de1994958 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs @@ -42,6 +42,7 @@ namespace ILCompiler protected readonly CompilerTypeSystemContext _typeSystemContext; protected readonly MetadataBlockingPolicy _blockingPolicy; + protected readonly ManifestResourceBlockingPolicy _resourceBlockingPolicy; private List<NonGCStaticsNode> _cctorContextsGenerated = new List<NonGCStaticsNode>(); private HashSet<TypeDesc> _typesWithEETypesGenerated = new HashSet<TypeDesc>(); @@ -55,10 +56,11 @@ namespace ILCompiler internal DynamicInvokeTemplateDataNode DynamicInvokeTemplateData { get; private set; } public virtual bool SupportsReflection => true; - public MetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy) + public MetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, ManifestResourceBlockingPolicy resourceBlockingPolicy) { _typeSystemContext = typeSystemContext; _blockingPolicy = blockingPolicy; + _resourceBlockingPolicy = resourceBlockingPolicy; } public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph) @@ -657,6 +659,11 @@ namespace ILCompiler return _blockingPolicy.IsBlocked(typicalMethodDefinition); } + public bool IsManifestResourceBlocked(ModuleDesc module, string resourceName) + { + return _resourceBlockingPolicy.IsManifestResourceBlocked(module, resourceName); + } + public bool CanGenerateMetadata(MetadataType type) { return (GetMetadataCategory(type) & MetadataCategory.Description) != 0; diff --git a/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs new file mode 100644 index 000000000..fd58d0e5b --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.TypeSystem; + +namespace ILCompiler +{ + /// <summary> + /// A blocking policy that doesn't block any manifest resources. + /// </summary> + public sealed class NoManifestResourceBlockingPolicy : ManifestResourceBlockingPolicy + { + public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName) + { + return false; + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/NoBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs index cca09285f..af0c073b9 100644 --- a/src/ILCompiler.Compiler/src/Compiler/NoBlockingPolicy.cs +++ b/src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs @@ -10,7 +10,7 @@ namespace ILCompiler /// <summary> /// Represents a metadata blocking policy that doesn't block any metadata. /// </summary> - public sealed class NoBlockingPolicy : MetadataBlockingPolicy + public sealed class NoMetadataBlockingPolicy : MetadataBlockingPolicy { public override bool IsBlocked(MetadataType type) => !(type is EcmaType); diff --git a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs index 0e333d323..ccb87ce2a 100644 --- a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs @@ -62,8 +62,9 @@ namespace ILCompiler IEnumerable<ModuleDesc> compilationModules, IEnumerable<ModuleDesc> inputMetadataOnlyAssemblies, byte[] metadataBlob, - StackTraceEmissionPolicy stackTraceEmissionPolicy) - : base(typeSystemContext, new AttributeSpecifiedBlockingPolicy()) + StackTraceEmissionPolicy stackTraceEmissionPolicy, + ManifestResourceBlockingPolicy resourceBlockingPolicy) + : base(typeSystemContext, new AttributeSpecifiedBlockingPolicy(), resourceBlockingPolicy) { _compilationModuleGroup = group; _metadataDescribingModule = metadataDescribingModule; diff --git a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs index a9f638d7b..3d13aa547 100644 --- a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs @@ -34,9 +34,10 @@ namespace ILCompiler CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, + ManifestResourceBlockingPolicy resourceBlockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy) - : base(typeSystemContext, blockingPolicy, logFile, stackTracePolicy) + : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy) { // We use this to mark places that would behave differently if we tracked exact fields used. _hasPreciseFieldUsageInformation = false; @@ -354,7 +355,7 @@ namespace ILCompiler } return new AnalysisBasedMetadataManager( - _typeSystemContext, _blockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, + _typeSystemContext, _blockingPolicy, _resourceBlockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _modulesWithMetadata, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(), reflectableFields.ToEnumerable()); } diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index 72c5d416f..7b86399ea 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -131,9 +131,12 @@ <Compile Include="Compiler\EmptyInteropStubManager.cs" /> <Compile Include="Compiler\DependencyAnalysis\SortableDependencyNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ImportedNodeProvider.cs" /> + <Compile Include="Compiler\FrameworkStringResourceBlockingPolicy.cs" /> <Compile Include="Compiler\GeneratingMetadataManager.cs" /> <Compile Include="Compiler\InternalCompilerErrorException.cs" /> - <Compile Include="Compiler\NoBlockingPolicy.cs" /> + <Compile Include="Compiler\ManifestResourceBlockingPolicy.cs" /> + <Compile Include="Compiler\NoManifestResourceBlockingPolicy.cs" /> + <Compile Include="Compiler\NoMetadataBlockingPolicy.cs" /> <Compile Include="Compiler\PreInitFieldInfo.cs" /> <Compile Include="Compiler\DependencyAnalysis\FrozenArrayNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\GCStaticsPreInitDataNode.cs" /> |