Ejemplo n.º 1
0
        public void TestFunctionPointerSignatures()
        {
            var ilModule = _context.GetModuleForSimpleName("ILMetadataAssembly");

            Cts.MetadataType typeWithFunctionPointers = ilModule.GetType("SampleMetadata", "TypeWithFunctionPointers");

            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, ilModule });

            var typeWithFunctionPointersType = transformResult.GetTransformedTypeDefinition(typeWithFunctionPointers);
            var objectType = transformResult.GetTransformedTypeDefinition((Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Object));

            Assert.Equal(1, typeWithFunctionPointersType.Fields.Count);

            var theField = typeWithFunctionPointersType.Fields[0];

            Assert.IsType <TypeSpecification>(theField.Signature.Type);
            var theFieldSignature = (TypeSpecification)theField.Signature.Type;

            Assert.IsType <FunctionPointerSignature>(theFieldSignature.Signature);
            var theFieldPointerSignature = (FunctionPointerSignature)theFieldSignature.Signature;

            Assert.Equal(objectType, theFieldPointerSignature.Signature.ReturnType);
            Assert.Equal(1, theFieldPointerSignature.Signature.Parameters.Count);
            Assert.Equal(objectType, theFieldPointerSignature.Signature.Parameters[0]);
        }
Ejemplo n.º 2
0
        public void TestMultifileSanity()
        {
            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");
            var policy          = new MultifileMetadataPolicy(sampleMetadataModule);
            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, sampleMetadataModule });

            Assert.Equal(1, transformResult.Scopes.Count);

            var sampleScope = transformResult.Scopes.Single();

            Assert.Equal(sampleMetadataModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), sampleScope.GetAllTypes().Count());

            var objectType   = (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Object);
            var objectRecord = transformResult.GetTransformedTypeReference(objectType);

            Assert.Equal("Object", objectRecord.TypeName.Value);

            var stringType   = (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String);
            var stringRecord = transformResult.GetTransformedTypeReference(stringType);

            Assert.Equal("String", stringRecord.TypeName.Value);

            Assert.Same(objectRecord.ParentNamespaceOrType, stringRecord.ParentNamespaceOrType);
            Assert.IsType <NamespaceReference>(objectRecord.ParentNamespaceOrType);

            var parentNamespace = objectRecord.ParentNamespaceOrType as NamespaceReference;

            Assert.Equal("System", parentNamespace.Name.Value);

            Assert.Null(transformResult.GetTransformedTypeDefinition(objectType));
            Assert.Null(transformResult.GetTransformedTypeDefinition(stringType));
        }
Ejemplo n.º 3
0
        public void TestExplicitScopeAttributesForWinRTSingleFilePolicy()
        {
            // Test that custom attributes referring to blocked types don't show up in metadata

            var sampleMetadataModule       = _context.GetModuleForSimpleName("SampleMetadataAssembly");
            var sampleWinRTMetadataModule  = _context.GetModuleForSimpleName("SampleWinRTMetadataAssembly");
            var windowsWinRTMetadataModule = _context.GetModuleForSimpleName("WindowsWinRTMetadataAssembly");

            Cts.MetadataType controlType        = windowsWinRTMetadataModule.GetType("Windows", "Control");
            Cts.MetadataType derivedFromControl = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControl");
            Cts.MetadataType derivedFromControlInCustomScope = sampleWinRTMetadataModule.GetType("SampleMetadataWinRT", "DerivedFromControlAndInCustomScope");

            var policy = new SingleFileMetadataPolicy();

            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, sampleMetadataModule, sampleWinRTMetadataModule, windowsWinRTMetadataModule });

            var controlTypeMetadata        = transformResult.GetTransformedTypeDefinition(controlType);
            var derivedFromControlMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControl);
            var derivedFromControlInCustomScopeMetadata = transformResult.GetTransformedTypeDefinition(derivedFromControlInCustomScope);

            CheckTypeDefinitionForProperWinRTHome(controlTypeMetadata, "Windows");
            ScopeDefinition scopeDefOfDerivedFromControlType = GetScopeDefinitionOfType(derivedFromControlMetadata);

            Assert.Equal("SampleWinRTMetadataAssembly", scopeDefOfDerivedFromControlType.Name.Value);
            CheckTypeDefinitionForProperWinRTHome(derivedFromControlInCustomScopeMetadata, "SampleMetadataWinRT");
        }
Ejemplo n.º 4
0
        public void TestAllTypes()
        {
            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy, new[] { _systemModule });

            Assert.Equal(1, transformResult.Scopes.Count());

            Assert.Equal(
                _systemModule.GetAllTypes().Count(x => !policy.IsBlocked(x)),
                transformResult.Scopes.Single().GetAllTypes().Count());
        }
Ejemplo n.º 5
0
        protected override void ComputeMetadata(NodeFactory factory,
                                                out byte[] metadataBlob,
                                                out List <MetadataMapping <MetadataType> > typeMappings,
                                                out List <MetadataMapping <MethodDesc> > methodMappings,
                                                out List <MetadataMapping <FieldDesc> > fieldMappings,
                                                out List <MetadataMapping <MethodDesc> > stackTraceMapping)
        {
            var ms     = new MemoryStream();
            var writer = new MetadataWriter();

            // Run an empty transform pass. This doesn't matter. We just need an instance of the MetadataTransform.
            var transformed             = MetadataTransform.Run(new Policy(), Array.Empty <ModuleDesc>());
            MetadataTransform transform = transformed.Transform;

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                MethodDesc method = methodBody.Method;

                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                MetadataRecord record = CreateStackTraceRecord(transform, method);

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            writer.Write(ms);
            metadataBlob = ms.ToArray();

            typeMappings      = new List <MetadataMapping <MetadataType> >();
            methodMappings    = new List <MetadataMapping <MethodDesc> >();
            fieldMappings     = new List <MetadataMapping <FieldDesc> >();
            stackTraceMapping = new List <MetadataMapping <MethodDesc> >();

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }
        }
Ejemplo n.º 6
0
        private void EnsureMetadataGenerated()
        {
            if (_metadataBlob != null)
            {
                return;
            }

            var transformed = MetadataTransform.Run(new DummyMetadataPolicy(this), _modulesSeen);

            // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
            //       TypeReference records for _typeDefinitionsGenerated that don't have metadata.
            //       (To be used in MissingMetadataException messages)

            // Generate metadata blob
            var writer = new MetadataWriter();

            writer.ScopeDefinitions.AddRange(transformed.Scopes);
            var ms = new MemoryStream();

            writer.Write(ms);
            _metadataBlob = ms.ToArray();

            // Generate type definition mappings
            foreach (var definition in _typeDefinitionsGenerated)
            {
                MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);

                // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
                // if there is an EEType for it, we also need a mapping table entry for it.
                if (record == null)
                {
                    record = transformed.GetTransformedTypeReference(definition);
                }

                if (record != null)
                {
                    _typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record)));
                }
            }

            foreach (var method in _methodsGenerated)
            {
                MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());

                if (record != null)
                {
                    _methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record)));
                }
            }
        }
Ejemplo n.º 7
0
        public void TestMethodImplMetadata()
        {
            // Test that custom attributes referring to blocked types don't show up in metadata

            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");

            Cts.MetadataType iCloneable                      = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ICloneable");
            Cts.MetadataType implementsICloneable            = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ImplementsICloneable");
            Cts.MethodDesc   iCloneableDotClone              = iCloneable.GetMethod("Clone", null);
            Cts.MethodDesc   iCloneableImplementation        = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.Clone", null);
            Cts.MethodDesc   iCloneableDotGenericClone       = iCloneable.GetMethod("GenericClone", null);
            Cts.MethodDesc   iCloneableGenericImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.GenericClone", null);

            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, sampleMetadataModule });

            var iCloneableType           = transformResult.GetTransformedTypeDefinition(iCloneable);
            var implementsICloneableType = transformResult.GetTransformedTypeDefinition(implementsICloneable);

            Assert.Equal(2, implementsICloneableType.MethodImpls.Count);

            // non-generic MethodImpl
            Method          iCloneableDotCloneMethod       = transformResult.GetTransformedMethodDefinition(iCloneableDotClone);
            Method          iCloneableImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableImplementation);
            QualifiedMethod methodImplMethodDecl           = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodDeclaration;
            QualifiedMethod methodImplMethodBody           = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodBody;

            Assert.Equal(iCloneableDotCloneMethod, methodImplMethodDecl.Method);
            Assert.Equal(iCloneableType, methodImplMethodDecl.EnclosingType);

            Assert.Equal(iCloneableImplementationMethod, methodImplMethodBody.Method);
            Assert.Equal(implementsICloneableType, methodImplMethodBody.EnclosingType);

            // generic MethodImpl
            Method          iCloneableDotGenericCloneMethod       = transformResult.GetTransformedMethodDefinition(iCloneableDotGenericClone);
            Method          iCloneableGenericImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableGenericImplementation);
            QualifiedMethod methodImplGenericMethodDecl           = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodDeclaration;
            QualifiedMethod methodImplGenericMethodBody           = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodBody;

            Assert.Equal(iCloneableDotGenericCloneMethod, methodImplGenericMethodDecl.Method);
            Assert.Equal(iCloneableType, methodImplGenericMethodDecl.EnclosingType);

            Assert.Equal(iCloneableGenericImplementationMethod, methodImplGenericMethodBody.Method);
            Assert.Equal(implementsICloneableType, methodImplGenericMethodBody.EnclosingType);
        }
Ejemplo n.º 8
0
        public void TestSampleMetadataGeneration()
        {
            var policy = new SingleFileMetadataPolicy();
            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");
            var transformResult      = MetadataTransform.Run(policy,
                                                             new[] { _systemModule, sampleMetadataModule });

            Assert.Equal(2, transformResult.Scopes.Count);

            var systemScope = transformResult.Scopes.Single(s => s.Name.Value == "PrimaryMetadataAssembly");
            var sampleScope = transformResult.Scopes.Single(s => s.Name.Value == "SampleMetadataAssembly");

            Assert.Equal(_systemModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), systemScope.GetAllTypes().Count());
            Assert.Equal(sampleMetadataModule.GetAllTypes().Count(t => !policy.IsBlocked(t)), sampleScope.GetAllTypes().Count());

            // TODO: check individual types
        }
Ejemplo n.º 9
0
        public void TestStandaloneSignatureGeneration()
        {
            var transformResult = MetadataTransform.Run(new SingleFileMetadataPolicy(), new[] { _systemModule });

            var stringRecord = transformResult.GetTransformedTypeDefinition(
                (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.String));
            var singleRecord = transformResult.GetTransformedTypeDefinition(
                (Cts.MetadataType)_context.GetWellKnownType(Cts.WellKnownType.Single));

            var sig = new Cts.MethodSignature(
                0, 0, _context.GetWellKnownType(Cts.WellKnownType.String),
                new[] { _context.GetWellKnownType(Cts.WellKnownType.Single) });

            var sigRecord = transformResult.Transform.HandleMethodSignature(sig);

            // Verify the signature is connected to the existing transformResult world
            Assert.Same(stringRecord, sigRecord.ReturnType);
            Assert.Equal(1, sigRecord.Parameters.Count);
            Assert.Same(singleRecord, sigRecord.Parameters[0]);
        }
Ejemplo n.º 10
0
        public void TestBlockedInterface()
        {
            // BlockedObject implements IBlockedInterface, which is a metadata blocked type and should not show
            // up in the BlockedObject interface list.

            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy, new[] { _systemModule });

            Cts.MetadataType iblockedinterface = _systemModule.GetType("System.Private.CompilerServices", "IBlockedInterface");
            Cts.MetadataType comObject         = _systemModule.GetType("System", "BlockedObject");
            Assert.Equal(1, comObject.ExplicitlyImplementedInterfaces.Length);
            Assert.Equal(iblockedinterface, comObject.ExplicitlyImplementedInterfaces[0]);

            Assert.Null(transformResult.GetTransformedTypeDefinition(iblockedinterface));
            Assert.Null(transformResult.GetTransformedTypeReference(iblockedinterface));

            TypeDefinition comObjectRecord = transformResult.GetTransformedTypeDefinition(comObject);

            Assert.NotNull(comObjectRecord);
            Assert.Equal(comObject.Name, comObjectRecord.Name.Value);
            Assert.Equal(0, comObjectRecord.Interfaces.Count);
        }
Ejemplo n.º 11
0
        public void TestNestedTypeReference()
        {
            // A type reference nested under a type that has a definition record. The transform is required
            // to create a type reference for the containing type because a type *definition* can't be a parent
            // to a type *reference*.

            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");

            Cts.MetadataType genericOutside = sampleMetadataModule.GetType("SampleMetadata", "GenericOutside`1");
            Cts.MetadataType inside         = genericOutside.GetNestedType("Inside");

            {
                MockPolicy policy = new MockPolicy(
                    type =>
                {
                    return(type == genericOutside);
                });

                var result = MetadataTransform.Run(policy, new[] { sampleMetadataModule });

                Assert.Equal(1, result.Scopes.Count);
                Assert.Equal(1, result.Scopes.Single().GetAllTypes().Count());

                var genericOutsideDefRecord = result.GetTransformedTypeDefinition(genericOutside);
                Assert.NotNull(genericOutsideDefRecord);

                Assert.Null(result.GetTransformedTypeReference(inside));

                var insideRecord = result.Transform.HandleType(inside);
                Assert.IsType <TypeReference>(insideRecord);

                var genericOutsideRefRecord = ((TypeReference)insideRecord).ParentNamespaceOrType as TypeReference;
                Assert.NotNull(genericOutsideRefRecord);
                Assert.Equal(genericOutside.Name, genericOutsideRefRecord.TypeName.Value);

                Assert.Same(genericOutsideDefRecord, result.GetTransformedTypeDefinition(genericOutside));
            }
        }
Ejemplo n.º 12
0
        public void TestBlockedAttributes()
        {
            // Test that custom attributes referring to blocked types don't show up in metadata

            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");

            Cts.MetadataType attributeHolder = sampleMetadataModule.GetType("BlockedMetadata", "AttributeHolder");

            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, sampleMetadataModule });

            int blockedCount = 0;
            int allowedCount = 0;

            foreach (var field in attributeHolder.GetFields())
            {
                var transformedRecord = transformResult.GetTransformedFieldDefinition(field);
                Assert.NotNull(transformedRecord);

                if (field.Name.StartsWith("Blocked"))
                {
                    blockedCount++;
                    Assert.Equal(0, transformedRecord.CustomAttributes.Count);
                }
                else
                {
                    allowedCount++;
                    Assert.StartsWith("Allowed", field.Name);
                    Assert.Equal(1, transformedRecord.CustomAttributes.Count);
                }
            }

            Assert.Equal(5, allowedCount);
            Assert.Equal(8, blockedCount);
        }
        protected override void ComputeMetadata(NodeFactory factory,
                                                out byte[] metadataBlob,
                                                out List <MetadataMapping <MetadataType> > typeMappings,
                                                out List <MetadataMapping <MethodDesc> > methodMappings,
                                                out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                var definition = type.GetTypeDefinition() as Internal.TypeSystem.Ecma.EcmaType;
                if (definition == null)
                {
                    continue;
                }
                if (factory.CompilationModuleGroup.ContainsType(definition))
                {
                    _typeDefinitionsToGenerate.Add(definition);
                    _modulesSeen.Add(definition.Module);
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                var typicalMethod = method.GetTypicalMethodDefinition() as Internal.TypeSystem.Ecma.EcmaMethod;
                if (typicalMethod != null)
                {
                    var owningType = (MetadataType)typicalMethod.OwningType;
                    if (factory.CompilationModuleGroup.ContainsType(owningType))
                    {
                        _typeDefinitionsToGenerate.Add(owningType);
                        _modulesSeen.Add(owningType.Module);
                        _methodDefinitionsToGenerate.Add(typicalMethod);
                    }
                }
            }

            var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this), _modulesSeen);

            // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
            //       TypeReference records for _typeDefinitionsGenerated that don't have metadata.
            //       (To be used in MissingMetadataException messages)

            // Generate metadata blob
            var writer = new MetadataWriter();

            writer.ScopeDefinitions.AddRange(transformed.Scopes);
            var ms = new MemoryStream();

            // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8.
            var noThrowUtf8Encoding = new UTF8Encoding(false, false);

            using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null)
            {
                writer.LogWriter = logWriter;
                writer.Write(ms);
            }

            metadataBlob = ms.ToArray();

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            // Generate type definition mappings
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);

                // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
                // if there is an EEType for it, we also need a mapping table entry for it.
                if (record == null)
                {
                    record = transformed.GetTransformedTypeReference(definition);
                }

                if (record != null)
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record)));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
                {
                    // Canonical methods are not interesting.
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());

                if (record != null)
                {
                    methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record)));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                if (eetypeGenerated.HasInstantiation)
                {
                    // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries

                    TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
                    {
                        continue;
                    }
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition());
                    if (record != null)
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record)));
                    }
                }
            }
        }
        private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory)
        {
            var transformed             = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>());
            MetadataTransform transform = transformed.Transform;

            // Generate metadata blob
            var writer = new MetadataWriter();

            // Only emit stack trace metadata for those methods which don't have reflection metadata
            HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>();

            foreach (var mappingEntry in GetMethodMapping(factory))
            {
                var method = mappingEntry.Entity;
                if (ShouldMethodBeInInvokeMap(method))
                {
                    methodInvokeMap.Add(method);
                }
            }

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode;
                if (methodNode != null && !methodNode.HasCompiledBody)
                {
                    continue;
                }

                MethodDesc method = methodBody.Method;

                if (methodInvokeMap.Contains(method))
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                MetadataRecord record = CreateStackTraceRecord(transform, method);

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            writer.Write(ms);

            _stackTraceBlob = ms.ToArray();

            var result = new List <MetadataMapping <MethodDesc> >();

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }

            return(result);
        }
Ejemplo n.º 15
0
        protected override void ComputeMetadata(NodeFactory factory,
                                                out byte[] metadataBlob,
                                                out List <MetadataMapping <MetadataType> > typeMappings,
                                                out List <MetadataMapping <MethodDesc> > methodMappings,
                                                out List <MetadataMapping <FieldDesc> > fieldMappings)
        {
            var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(this), _modulesSeen);

            // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
            //       TypeReference records for _typeDefinitionsGenerated that don't have metadata.
            //       (To be used in MissingMetadataException messages)

            // Generate metadata blob
            var writer = new MetadataWriter();

            writer.ScopeDefinitions.AddRange(transformed.Scopes);
            var ms = new MemoryStream();

            writer.Write(ms);
            metadataBlob = ms.ToArray();

            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            // Generate type definition mappings
            foreach (var definition in _typeDefinitionsGenerated)
            {
                MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);

                // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
                // if there is an EEType for it, we also need a mapping table entry for it.
                if (record == null)
                {
                    record = transformed.GetTransformedTypeReference(definition);
                }

                if (record != null)
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record)));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
                {
                    // Canonical methods are not interesting.
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());

                if (record != null)
                {
                    methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record)));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                if (eetypeGenerated.HasInstantiation)
                {
                    // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries

                    TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
                    {
                        continue;
                    }
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition());
                    if (record != null)
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record)));
                    }
                }
            }
        }
Ejemplo n.º 16
0
        protected void ComputeMetadata <TPolicy>(
            TPolicy policy,
            NodeFactory factory,
            out byte[] metadataBlob,
            out List <MetadataMapping <MetadataType> > typeMappings,
            out List <MetadataMapping <MethodDesc> > methodMappings,
            out List <MetadataMapping <FieldDesc> > fieldMappings,
            out List <MetadataMapping <MethodDesc> > stackTraceMapping) where TPolicy : struct, IMetadataPolicy
        {
            var transformed             = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata());
            MetadataTransform transform = transformed.Transform;

            // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
            //       TypeReference records for _typeDefinitionsGenerated that don't have metadata.
            //       (To be used in MissingMetadataException messages)

            // Generate metadata blob
            var writer = new MetadataWriter();

            writer.ScopeDefinitions.AddRange(transformed.Scopes);

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                MethodDesc method = methodBody.Method;

                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();

                // Methods that will end up in the reflection invoke table should not have an entry in stack trace table
                // We'll try looking them up in reflection data at runtime.
                if (transformed.GetTransformedMethodDefinition(typicalMethod) != null &&
                    ShouldMethodBeInInvokeMap(method) &&
                    (GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) != 0)
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                MetadataRecord record = transform.HandleQualifiedMethod(typicalMethod);

                // As a twist, instantiated generic methods appear as if instantiated over their formals.
                if (typicalMethod.HasInstantiation)
                {
                    var methodInst = new MethodInstantiation
                    {
                        Method = record,
                    };
                    methodInst.GenericTypeArguments.Capacity = typicalMethod.Instantiation.Length;
                    foreach (EcmaGenericParameter typeArgument in typicalMethod.Instantiation)
                    {
                        var genericParam = new TypeReference
                        {
                            TypeName = (ConstantStringValue)typeArgument.Name,
                        };
                        methodInst.GenericTypeArguments.Add(genericParam);
                    }
                    record = methodInst;
                }

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8.
            var noThrowUtf8Encoding = new UTF8Encoding(false, false);

            using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null)
            {
                writer.LogWriter = logWriter;
                writer.Write(ms);
            }

            metadataBlob = ms.ToArray();

            typeMappings      = new List <MetadataMapping <MetadataType> >();
            methodMappings    = new List <MetadataMapping <MethodDesc> >();
            fieldMappings     = new List <MetadataMapping <FieldDesc> >();
            stackTraceMapping = new List <MetadataMapping <MethodDesc> >();

            // Generate type definition mappings
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);

                // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
                // if there is an EEType for it, we also need a mapping table entry for it.
                if (record == null)
                {
                    record = transformed.GetTransformedTypeReference(definition);
                }

                if (record != null)
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record)));
                }
            }

            foreach (var method in GetCompiledMethods())
            {
                if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
                {
                    // Canonical methods are not interesting.
                    continue;
                }

                if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation))
                {
                    continue;
                }

                if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0)
                {
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());

                if (record != null)
                {
                    methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record)));
                }
            }

            foreach (var eetypeGenerated in GetTypesWithEETypes())
            {
                if (eetypeGenerated.IsGenericDefinition)
                {
                    continue;
                }

                if (eetypeGenerated.HasInstantiation)
                {
                    // Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries

                    TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
                    {
                        continue;
                    }
                }

                foreach (FieldDesc field in eetypeGenerated.GetFields())
                {
                    if (IsReflectionBlocked(field.OwningType.Instantiation))
                    {
                        continue;
                    }

                    Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition());
                    if (record != null)
                    {
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, writer.GetRecordHandle(record)));
                    }
                }
            }

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }
        }
Ejemplo n.º 17
0
        private List <MetadataMapping <MethodDesc> > GenerateStackTraceMetadata(NodeFactory factory)
        {
            var transformed             = MetadataTransform.Run(new NoDefinitionMetadataPolicy(), Array.Empty <ModuleDesc>());
            MetadataTransform transform = transformed.Transform;

            // Generate metadata blob
            var writer = new MetadataWriter();

            // Only emit stack trace metadata for those methods which don't have reflection metadata
            HashSet <MethodDesc> methodInvokeMap = new HashSet <MethodDesc>();

            foreach (var mappingEntry in GetMethodMapping(factory))
            {
                var method = mappingEntry.Entity;
                if (ShouldMethodBeInInvokeMap(method))
                {
                    methodInvokeMap.Add(method);
                }
            }

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                NonExternMethodSymbolNode methodNode = methodBody as NonExternMethodSymbolNode;
                if (methodNode != null && !methodNode.HasCompiledBody)
                {
                    continue;
                }

                MethodDesc method = methodBody.Method;

                if (methodInvokeMap.Contains(method))
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                // In the metadata, we only represent the generic definition
                MethodDesc     methodToGenerateMetadataFor = method.GetTypicalMethodDefinition();
                MetadataRecord record = transform.HandleQualifiedMethod(methodToGenerateMetadataFor);

                // As a twist, instantiated generic methods appear as if instantiated over their formals.
                if (methodToGenerateMetadataFor.HasInstantiation)
                {
                    var methodInst = new MethodInstantiation
                    {
                        Method = record,
                    };
                    methodInst.GenericTypeArguments.Capacity = methodToGenerateMetadataFor.Instantiation.Length;
                    foreach (EcmaGenericParameter typeArgument in methodToGenerateMetadataFor.Instantiation)
                    {
                        var genericParam = new TypeReference
                        {
                            TypeName = (ConstantStringValue)typeArgument.Name,
                        };
                        methodInst.GenericTypeArguments.Add(genericParam);
                    }
                    record = methodInst;
                }

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            writer.Write(ms);

            _stackTraceBlob = ms.ToArray();

            var result = new List <MetadataMapping <MethodDesc> >();

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                result.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }

            return(result);
        }
Ejemplo n.º 18
0
        protected void ComputeMetadata <TPolicy>(
            TPolicy policy,
            NodeFactory factory,
            out byte[] metadataBlob,
            out List <MetadataMapping <MetadataType> > typeMappings,
            out List <MetadataMapping <MethodDesc> > methodMappings,
            out List <MetadataMapping <FieldDesc> > fieldMappings,
            out List <MetadataMapping <MethodDesc> > stackTraceMapping) where TPolicy : struct, IMetadataPolicy
        {
            var transformed             = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata());
            MetadataTransform transform = transformed.Transform;

            // TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
            //       TypeReference records for _typeDefinitionsGenerated that don't have metadata.
            //       (To be used in MissingMetadataException messages)

            // Generate metadata blob
            var writer = new MetadataWriter();

            writer.ScopeDefinitions.AddRange(transformed.Scopes);

            // Generate entries in the blob for methods that will be necessary for stack trace purposes.
            var stackTraceRecords = new List <KeyValuePair <MethodDesc, MetadataRecord> >();

            foreach (var methodBody in GetCompiledMethodBodies())
            {
                MethodDesc method = methodBody.Method;

                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();

                // Methods that will end up in the reflection invoke table should not have an entry in stack trace table
                // We'll try looking them up in reflection data at runtime.
                if (transformed.GetTransformedMethodDefinition(typicalMethod) != null &&
                    ShouldMethodBeInInvokeMap(method) &&
                    (GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) != 0)
                {
                    continue;
                }

                if (!_stackTraceEmissionPolicy.ShouldIncludeMethod(method))
                {
                    continue;
                }

                MetadataRecord record = CreateStackTraceRecord(transform, method);

                stackTraceRecords.Add(new KeyValuePair <MethodDesc, MetadataRecord>(
                                          method,
                                          record));

                writer.AdditionalRootRecords.Add(record);
            }

            var ms = new MemoryStream();

            // .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8.
            var noThrowUtf8Encoding = new UTF8Encoding(false, false);

            using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null)
            {
                writer.LogWriter = logWriter;
                writer.Write(ms);
            }

            metadataBlob = ms.ToArray();

            typeMappings      = new List <MetadataMapping <MetadataType> >();
            methodMappings    = new List <MetadataMapping <MethodDesc> >();
            fieldMappings     = new List <MetadataMapping <FieldDesc> >();
            stackTraceMapping = new List <MetadataMapping <MethodDesc> >();

            // Generate type definition mappings
            foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
            {
                MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
                if (definition == null)
                {
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);

                // Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
                // if there is an EEType for it, we also need a mapping table entry for it.
                if (record == null)
                {
                    record = transformed.GetTransformedTypeReference(definition);
                }

                if (record != null)
                {
                    typeMappings.Add(new MetadataMapping <MetadataType>(definition, writer.GetRecordHandle(record)));
                }
            }

            HashSet <MethodDesc> canonicalGenericMethods = new HashSet <MethodDesc>();

            foreach (var method in GetCompiledMethods())
            {
                if ((method.HasInstantiation && method.IsCanonicalMethod(CanonicalFormKind.Specific)) ||
                    (!method.HasInstantiation && method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method))
                {
                    // Methods that are not in their canonical form are not interesting with the exception
                    // of generic methods: their dictionaries convey their identity.
                    continue;
                }

                if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation))
                {
                    continue;
                }

                if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0)
                {
                    continue;
                }

                // If we already added a canonically equivalent generic method, skip this one.
                if (method.HasInstantiation && !canonicalGenericMethods.Add(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))
                {
                    continue;
                }

                MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());

                if (record != null)
                {
                    methodMappings.Add(new MetadataMapping <MethodDesc>(method, writer.GetRecordHandle(record)));
                }
            }

            HashSet <FieldDesc> canonicalFields = new HashSet <FieldDesc>();

            foreach (var field in GetFieldsWithRuntimeMapping())
            {
                FieldDesc fieldToAdd = field;
                if (!field.IsStatic)
                {
                    TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific);
                    if (canonOwningType != field.OwningType)
                    {
                        FieldDesc canonField = _typeSystemContext.GetFieldForInstantiatedType(field.GetTypicalFieldDefinition(), (InstantiatedType)canonOwningType);

                        // If we already added a canonically equivalent field, skip this one.
                        if (!canonicalFields.Add(canonField))
                        {
                            continue;
                        }

                        fieldToAdd = canonField;
                    }
                }

                Field record = transformed.GetTransformedFieldDefinition(fieldToAdd.GetTypicalFieldDefinition());
                if (record != null)
                {
                    fieldMappings.Add(new MetadataMapping <FieldDesc>(fieldToAdd, writer.GetRecordHandle(record)));
                }
            }

            // Generate stack trace metadata mapping
            foreach (var stackTraceRecord in stackTraceRecords)
            {
                stackTraceMapping.Add(new MetadataMapping <MethodDesc>(stackTraceRecord.Key, writer.GetRecordHandle(stackTraceRecord.Value)));
            }
        }