public SerializedMetadata( MetadataSizes sizes, BlobBuilder stringHeap, ImmutableArray <int> stringMap) { Sizes = sizes; StringHeap = stringHeap; StringMap = stringMap; }
internal SerializedMetadata GetSerializedMetadata(ImmutableArray <int> externalRowCounts, int metadataVersionByteCount, bool isStandaloneDebugMetadata) { var stringHeapBuilder = new HeapBlobBuilder(_stringHeapCapacity); var stringMap = SerializeStringHeap(stringHeapBuilder, _strings, _stringHeapStartOffset); Debug.Assert(HeapIndex.UserString == 0); Debug.Assert((int)HeapIndex.String == 1); Debug.Assert((int)HeapIndex.Blob == 2); Debug.Assert((int)HeapIndex.Guid == 3); var heapSizes = ImmutableArray.Create( _userStringBuilder.Count, stringHeapBuilder.Count, _blobHeapSize, _guidBuilder.Count); var sizes = new MetadataSizes(GetRowCounts(), externalRowCounts, heapSizes, metadataVersionByteCount, isStandaloneDebugMetadata); return(new SerializedMetadata(sizes, stringHeapBuilder, stringMap)); }
private static void SerializeStreamHeader(ref int offsetFromStartOfMetadata, int alignedStreamSize, string streamName, BlobBuilder builder) { // 4 for the first uint (offset), 4 for the second uint (padded size), length of stream name + 1 for null terminator (then padded) int sizeOfStreamHeader = MetadataSizes.GetMetadataStreamHeaderSize(streamName); builder.WriteInt32(offsetFromStartOfMetadata); builder.WriteInt32(alignedStreamSize); foreach (char ch in streamName) { builder.WriteByte((byte)ch); } // After offset, size, and stream name, write 0-bytes until we reach our padded size. for (uint i = 8 + (uint)streamName.Length; i < sizeOfStreamHeader; i++) { builder.WriteByte(0); } offsetFromStartOfMetadata += alignedStreamSize; }
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); }