Пример #1
0
        public override void SetValue(StringToken tkn, string val)
        {
            MetadataStream strs = this.Stream;
            uint           idx  = tkn.Token.Index;
            uint           c    = 0;

            while (strs.Data[idx + c] != 0)
            {
                c++;
            }
            c++;

            byte[]         dat = Encoding.UTF8.GetBytes(val);
            MetadataWriter wtr = new MetadataWriter(strs);

            if (c == dat.Length + 1)
            {
                strs.Position = tkn.Token.Index;
                wtr.Write(dat);
            }
            else
            {
                ResizeChild(tkn, (uint)dat.Length + 1);
                strs.Position = tkn.Token.Index;
                wtr.Write(dat);
                wtr.Write((byte)0);
            }
        }
Пример #2
0
        public override void SetValue(USToken tkn, string val)
        {
            MetadataStream strs = this.Stream;

            strs.Position = tkn.Token.Index;
            MetadataReader rdr = new MetadataReader(strs);
            uint           len = rdr.ReadCompressedUInt();

            MetadataWriter wtr = new MetadataWriter(strs);

            byte[] b = Encoding.Unicode.GetBytes(val);
            if (len == b.Length)
            {
                strs.Position = tkn.Token.Index;
                wtr.WriteCompressedUInt(len);
                wtr.Write(b);
            }
            else
            {
                ResizeChild(tkn, (uint)b.Length);
                strs.Position = tkn.Token.Index;
                wtr.WriteCompressedInt(b.Length);
                wtr.Write(b);
            }
        }
Пример #3
0
        protected override void WriteImpl(MetadataWriter mw)
        {
            // PDB id
            PositionPdbId = mw.Position;
            WritePdbId(mw, guid, timestamp);
            // EntryPoint
            // LAMESPEC the spec says "The same value as stored in CLI header of the PE file.",
            // but the intent is clearly to allow a separate "user" entry point
            // (i.e. it should default to the entry point defined in the PE file, but SetUserEntryPoint should override it)
            mw.Write(entryPointToken);
            // ReferencedTypeSystemTables
            var bit   = 1L;
            var valid = 0L;

            foreach (var table in referencedTables)
            {
                if (table != null && table.RowCount != 0)
                {
                    valid |= bit;
                }
                bit <<= 1;
            }
            mw.Write(valid);
            // TypeSystemTableRows
            foreach (var table in referencedTables)
            {
                if (table != null && table.RowCount != 0)
                {
                    mw.Write(table.RowCount);
                }
            }
        }
Пример #4
0
 void WriteTableToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
 {
     if (lens[(int)(val as TableToken).Token.Type] > ushort.MaxValue)
     {
         wtr.Write((uint)(val as TableToken).Token.Value);
     }
     else
     {
         wtr.Write((ushort)(val as TableToken).Token.Value);
     }
 }
Пример #5
0
        void WriteBlobToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
        {
            BlobHeap bh = wtr.BaseStream.Root[MetadataStreamType.Blob].Heap as BlobHeap;

            if (bh.Stream.Length > ushort.MaxValue)
            {
                wtr.Write((uint)(val as BlobToken).Token.Value);
            }
            else
            {
                wtr.Write((ushort)(val as BlobToken).Token.Value);
            }
        }
Пример #6
0
        void WriteGUIDToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
        {
            GUIDHeap gh = wtr.BaseStream.Root[MetadataStreamType.GUID].Heap as GUIDHeap;

            if (gh.Stream.Length > ushort.MaxValue)
            {
                wtr.Write((uint)(val as GUIDToken).Token.Value);
            }
            else
            {
                wtr.Write((ushort)(val as GUIDToken).Token.Value);
            }
        }
Пример #7
0
        void WriteStringToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
        {
            StringsHeap sh = wtr.BaseStream.Root[MetadataStreamType.Strings].Heap as StringsHeap;

            if (sh.Stream.Length > ushort.MaxValue)
            {
                wtr.Write((uint)(val as StringToken).Token.Value);
            }
            else
            {
                wtr.Write((ushort)(val as StringToken).Token.Value);
            }
        }
Пример #8
0
        public void Save()
        {
            MetadataWriter wtr = new MetadataWriter(str);

            str.Position = 0;
            wtr.Write(res);
            wtr.Write(maVer);
            wtr.Write(miVer);
            wtr.Write((byte)f);
            wtr.Write(res2);
            wtr.Write((ulong)v);
            wtr.Write((ulong)s);
            FillLens();
            foreach (MetadataTable i in mt)
            {
                if (i != null)
                {
                    wtr.Write((uint)i.Rows.Count);
                }
            }
            TableRw rw = new TableRw();

            foreach (MetadataTable i in mt)
            {
                if (i != null)
                {
                    rw.Save(i, wtr, len);
                }
            }
        }
Пример #9
0
        public override StringToken NewChildCore(uint len)
        {
            StringToken ret = new StringToken(this);

            ret.Token = new MetadataToken(MetadataTokenType.Unknown, (uint)this.Stream.Data.Length);

            this.Stream.SetLength(this.Stream.Data.Length + len + 1);

            MetadataWriter wtr = new MetadataWriter(this.Stream);

            this.Stream.Position = ret.Token.Index;
            for (int i = 0; i < len; i++)
            {
                wtr.Write((byte)0xff);
            }
            wtr.Write((byte)0);
            return(ret);
        }
Пример #10
0
 internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList)
 {
     if (rva != -1)
     {
         mw.Write(rva + baseRVA);
     }
     else
     {
         mw.Write(0);
     }
     mw.Write((short)implFlags);
     mw.Write((short)attributes);
     mw.WriteStringIndex(nameIndex);
     mw.WriteBlobIndex(signature);
     mw.WriteParam(paramList);
     if (parameters != null)
     {
         paramList += parameters.Count;
     }
 }
Пример #11
0
 internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList)
 {
     mw.Write((int)attribs);
     mw.WriteStringIndex(typeName);
     mw.WriteStringIndex(typeNameSpace);
     mw.WriteTypeDefOrRef(extends);
     mw.WriteField(fieldList);
     mw.WriteMethodDef(methodList);
     methodList += methods.Count;
     fieldList  += fields.Count;
 }
Пример #12
0
        public override void SetValue(GUIDToken tkn, Guid val)
        {
            if (tkn.Token.Index == 0)
            {
                return;
            }
            MetadataStream strs = this.Stream;
            MetadataWriter wtr  = new MetadataWriter(strs);

            strs.Position = (tkn.Token.Index - 1) * 16;
            wtr.Write(val.ToByteArray());
        }
Пример #13
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)));
            }
        }
Пример #14
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)));
                }
            }
        }
Пример #15
0
        public override void SetValue(BlobToken tkn, byte[] val)
        {
            MetadataStream strs = this.Stream;

            strs.Position = tkn.Token.Index;
            MetadataReader rdr = new MetadataReader(strs);
            uint           len = rdr.ReadCompressedUInt();

            MetadataWriter wtr = new MetadataWriter(strs);

            if (len == val.Length)
            {
                strs.Position = tkn.Token.Index;
                wtr.WriteCompressedUInt(len);
                wtr.Write(val);
            }
            else
            {
                ResizeChild(tkn, (uint)val.Length);
                strs.Position = tkn.Token.Index;
                wtr.WriteCompressedInt(val.Length);
                wtr.Write(val);
            }
        }
Пример #16
0
 internal void WriteFieldRecords(MetadataWriter mw)
 {
     mw.Write((short)attribs);
     mw.WriteStringIndex(nameIndex);
     mw.WriteBlobIndex(signature);
 }
        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);
        }
Пример #19
0
 internal static void WritePdbId(MetadataWriter mw, Guid guid, uint timestamp)
 {
     mw.Write(guid.ToByteArray());
     mw.Write(timestamp);
 }
Пример #20
0
 internal void WriteParamRecord(MetadataWriter mw)
 {
     mw.Write(flags);
     mw.Write(sequence);
     mw.WriteStringIndex(nameIndex);
 }
Пример #21
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)));
            }
        }
Пример #22
0
        internal void WriteMetadata(MetadataWriter mw)
        {
            mw.Write(0x424A5342);                               // Signature ("BSJB")
            mw.Write((ushort)1);                                // MajorVersion
            mw.Write((ushort)1);                                // MinorVersion
            mw.Write(0);                                        // Reserved
            byte[] version = StringToPaddedUTF8(asm.ImageRuntimeVersion);
            mw.Write(version.Length);                           // Length
            mw.Write(version);
            mw.Write((ushort)0);                                // Flags
            // #Blob is the only optional heap
            if (Blobs.IsEmpty)
            {
                mw.Write((ushort)4);                            // Streams
            }
            else
            {
                mw.Write((ushort)5);                            // Streams
            }

            int offset = GetHeaderLength();

            // Streams
            mw.Write(offset);                                   // Offset
            mw.Write(Tables.Length);                            // Size
            mw.Write(StringToPaddedUTF8("#~"));
            offset += Tables.Length;

            mw.Write(offset);                                   // Offset
            mw.Write(Strings.Length);                           // Size
            mw.Write(StringToPaddedUTF8("#Strings"));
            offset += Strings.Length;

            mw.Write(offset);                           // Offset
            mw.Write(UserStrings.Length);               // Size
            mw.Write(StringToPaddedUTF8("#US"));
            offset += UserStrings.Length;

            mw.Write(offset);                                   // Offset
            mw.Write(Guids.Length);                             // Size
            mw.Write(StringToPaddedUTF8("#GUID"));
            offset += Guids.Length;

            if (!Blobs.IsEmpty)
            {
                mw.Write(offset);                                       // Offset
                mw.Write(Blobs.Length);                                 // Size
                mw.Write(StringToPaddedUTF8("#Blob"));
            }

            Tables.Write(mw);
            Strings.Write(mw);
            UserStrings.Write(mw);
            Guids.Write(mw);
            if (!Blobs.IsEmpty)
            {
                Blobs.Write(mw);
            }
        }
Пример #23
0
 void WriteRva(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
 {
     wtr.Write(((Rva)val).Value);
 }
Пример #24
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);
        }
Пример #25
0
 void WriteUInt32(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
 {
     wtr.Write((uint)val);
 }
Пример #26
0
 void WriteByte(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
 {
     wtr.Write((byte)val);
 }
Пример #27
0
 void WriteUInt16Flag(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
 {
     wtr.Write((ushort)val);
 }
Пример #28
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)));
                    }
                }
            }
        }
Пример #29
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)));
            }
        }