internal static void SerializeMetadataHeader(BlobBuilder builder, string metadataVersion, MetadataSizes sizes) { int startOffset = builder.Count; // signature builder.WriteUInt32(0x424A5342); // major version builder.WriteUInt16(1); // minor version builder.WriteUInt16(1); // reserved builder.WriteUInt32(0); // Spec (section 24.2.1 Metadata Root): // Length ... Number of bytes allocated to hold version string (including null terminator), call this x. // Call the length of the string (including the terminator) m (we require m <= 255); // the length x is m rounded up to a multiple of four. builder.WriteInt32(sizes.MetadataVersionPaddedLength); int metadataVersionStart = builder.Count; builder.WriteUTF8(metadataVersion); builder.WriteByte(0); int metadataVersionEnd = builder.Count; for (int i = 0; i < sizes.MetadataVersionPaddedLength - (metadataVersionEnd - metadataVersionStart); i++) { builder.WriteByte(0); } // reserved builder.WriteUInt16(0); // number of streams builder.WriteUInt16((ushort)(5 + (sizes.IsEncDelta ? 1 : 0) + (sizes.IsStandaloneDebugMetadata ? 1 : 0))); // stream headers int offsetFromStartOfMetadata = sizes.MetadataHeaderSize; // emit the #Pdb stream first so that only a single page has to be read in order to find out PDB ID if (sizes.IsStandaloneDebugMetadata) { SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.StandalonePdbStreamSize, "#Pdb", builder); } // Spec: Some compilers store metadata in a #- stream, which holds an uncompressed, or non-optimized, representation of metadata tables; // this includes extra metadata -Ptr tables. Such PE files do not form part of ECMA-335 standard. // // Note: EnC delta is stored as uncompressed metadata stream. SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.MetadataTableStreamSize, (sizes.IsCompressed ? "#~" : "#-"), builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", builder); if (sizes.IsEncDelta) { SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", builder); } int endOffset = builder.Count; Debug.Assert(endOffset - startOffset == sizes.MetadataHeaderSize); }
private void SerializeMetadataHeader(BlobBuilder builder) { int startOffset = builder.Count; // signature builder.WriteUInt32(0x424A5342); // major version builder.WriteUInt16(1); // minor version builder.WriteUInt16(1); // reserved builder.WriteUInt32(0); // metadata version length builder.WriteUInt32(MetadataSizes.MetadataVersionPaddedLength); int n = Math.Min(MetadataSizes.MetadataVersionPaddedLength, _metadataVersion.Length); for (int i = 0; i < n; i++) { builder.WriteByte((byte)_metadataVersion[i]); } for (int i = n; i < MetadataSizes.MetadataVersionPaddedLength; i++) { builder.WriteByte(0); } // reserved builder.WriteUInt16(0); // number of streams builder.WriteUInt16((ushort)(5 + (_sizes.IsMinimalDelta ? 1 : 0) + (_sizes.IsStandaloneDebugMetadata ? 1 : 0))); // stream headers int offsetFromStartOfMetadata = _sizes.MetadataHeaderSize; // emit the #Pdb stream first so that only a single page has to be read in order to find out PDB ID if (_sizes.IsStandaloneDebugMetadata) { SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.StandalonePdbStreamSize, "#Pdb", builder); } // Spec: Some compilers store metadata in a #- stream, which holds an uncompressed, or non-optimized, representation of metadata tables; // this includes extra metadata -Ptr tables. Such PE files do not form part of ECMA-335 standard. // // Note: EnC delta is stored as uncompressed metadata stream. SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.MetadataTableStreamSize, (_sizes.IsMetadataTableStreamCompressed ? "#~" : "#-"), builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", builder); SerializeStreamHeader(ref offsetFromStartOfMetadata, _sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", builder); if (_sizes.IsMinimalDelta) { SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", builder); } int endOffset = builder.Count; Debug.Assert(endOffset - startOffset == _sizes.MetadataHeaderSize); }