コード例 #1
0
        // internal for testing
        internal static IEnumerable <Blob> GetContentToSign(BlobBuilder peImage, int peHeadersSize, int peHeaderAlignment, Blob strongNameSignatureFixup)
        {
            // Signed content includes
            // - PE header without its alignment padding
            // - all sections including their alignment padding and excluding strong name signature blob

            // PE specification:
            //   To calculate the PE image hash, Authenticode orders the sections that are specified in the section table
            //   by address range, then hashes the resulting sequence of bytes, passing over the exclusion ranges.
            //
            // Note that sections are by construction ordered by their address, so there is no need to reorder.

            int remainingHeaderToSign = peHeadersSize;
            int remainingHeader       = BitArithmetic.Align(peHeadersSize, peHeaderAlignment);

            foreach (var blob in peImage.GetBlobs())
            {
                int blobStart  = blob.Start;
                int blobLength = blob.Length;
                while (blobLength > 0)
                {
                    if (remainingHeader > 0)
                    {
                        int length;

                        if (remainingHeaderToSign > 0)
                        {
                            length = Math.Min(remainingHeaderToSign, blobLength);
                            yield return(new Blob(blob.Buffer, blobStart, length));

                            remainingHeaderToSign -= length;
                        }
                        else
                        {
                            length = Math.Min(remainingHeader, blobLength);
                        }

                        remainingHeader -= length;
                        blobStart       += length;
                        blobLength      -= length;
                    }
                    else if (blob.Buffer == strongNameSignatureFixup.Buffer)
                    {
                        yield return(GetPrefixBlob(new Blob(blob.Buffer, blobStart, blobLength), strongNameSignatureFixup));

                        yield return(GetSuffixBlob(new Blob(blob.Buffer, blobStart, blobLength), strongNameSignatureFixup));

                        break;
                    }
                    else
                    {
                        yield return(new Blob(blob.Buffer, blobStart, blobLength));

                        break;
                    }
                }
            }
        }
コード例 #2
0
ファイル: ManagedTextSection.cs プロジェクト: z77ma/runtime
        public int CalculateOffsetToMappedFieldDataStream()
        {
            int result = CalculateOffsetToMappedFieldDataStreamUnaligned();

            if (MappedFieldDataSize != 0)
            {
                result = BitArithmetic.Align(result, MappedFieldDataAlignment);
            }
            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Returns aligned size of the specified heap.
        /// </summary>
        public int GetAlignedHeapSize(HeapIndex index)
        {
            int i = (int)index;

            if (i < 0 || i > HeapSizes.Length)
            {
                Throw.ArgumentOutOfRange(nameof(index));
            }

            return(BitArithmetic.Align(HeapSizes[i], StreamAlignment));
        }
コード例 #4
0
        internal int CalculateStandalonePdbStreamSize()
        {
            int result =
                PdbIdSize +                                                // PDB ID
                sizeof(int) +                                              // EntryPoint
                sizeof(long) +                                             // ReferencedTypeSystemTables
                BitArithmetic.CountBits(ExternalTablesMask) * sizeof(int); // External row counts

            Debug.Assert(result % StreamAlignment == 0);
            return(result);
        }
コード例 #5
0
        public int CalculateOffsetToMappedFieldDataStream()
        {
            int result = ComputeOffsetToImportTable();

            if (RequiresStartupStub)
            {
                result += SizeOfImportTable + SizeOfNameTable;
                result  = BitArithmetic.Align(result, Is32Bit ? 4 : 8); //optional padding to make startup stub's target address align on word or double word boundary
                result += SizeOfRuntimeStartupStub;
            }

            return(result);
        }
コード例 #6
0
        /// <summary>
        /// Creates PE header builder.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="fileAlignment"/> is not power of 2 between 512 and 64K, or
        /// <paramref name="sectionAlignment"/> not power of 2 or it's less than <paramref name="fileAlignment"/>.
        /// </exception>
        public PEHeaderBuilder(
            Machine machine                       = 0,
            int sectionAlignment                  = 0x2000,
            int fileAlignment                     = 0x200,
            ulong imageBase                       = 0x00400000,
            byte majorLinkerVersion               = 0x30, // (what is ref.emit using?)
            byte minorLinkerVersion               = 0,
            ushort majorOperatingSystemVersion    = 4,
            ushort minorOperatingSystemVersion    = 0,
            ushort majorImageVersion              = 0,
            ushort minorImageVersion              = 0,
            ushort majorSubsystemVersion          = 4,
            ushort minorSubsystemVersion          = 0,
            Subsystem subsystem                   = Subsystem.WindowsCui,
            DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware,
            Characteristics imageCharacteristics  = Characteristics.Dll,
            ulong sizeOfStackReserve              = 0x00100000,
            ulong sizeOfStackCommit               = 0x1000,
            ulong sizeOfHeapReserve               = 0x00100000,
            ulong sizeOfHeapCommit                = 0x1000)
        {
            if (fileAlignment < 512 || fileAlignment > 64 * 1024 || BitArithmetic.CountBits(fileAlignment) != 1)
            {
                Throw.ArgumentOutOfRange(nameof(fileAlignment));
            }

            if (sectionAlignment < fileAlignment || BitArithmetic.CountBits(sectionAlignment) != 1)
            {
                Throw.ArgumentOutOfRange(nameof(sectionAlignment));
            }

            Machine                     = machine;
            SectionAlignment            = sectionAlignment;
            FileAlignment               = fileAlignment;
            ImageBase                   = imageBase;
            MajorLinkerVersion          = majorLinkerVersion;
            MinorLinkerVersion          = minorLinkerVersion;
            MajorOperatingSystemVersion = majorOperatingSystemVersion;
            MinorOperatingSystemVersion = minorOperatingSystemVersion;
            MajorImageVersion           = majorImageVersion;
            MinorImageVersion           = minorImageVersion;
            MajorSubsystemVersion       = majorSubsystemVersion;
            MinorSubsystemVersion       = minorSubsystemVersion;
            Subsystem                   = subsystem;
            DllCharacteristics          = dllCharacteristics;
            ImageCharacteristics        = imageCharacteristics;
            SizeOfStackReserve          = sizeOfStackReserve;
            SizeOfStackCommit           = sizeOfStackCommit;
            SizeOfHeapReserve           = sizeOfHeapReserve;
            SizeOfHeapCommit            = sizeOfHeapCommit;
        }
コード例 #7
0
 private SectionHeader GetTextHeader(TextMap map)
 {
     return(new SectionHeader()
     {
         Name = ".text",
         VirtualSize = map.GetSize(),
         VirtualAddress = TEXT_SECTION_BASE,
         SizeOfRawData = BitArithmetic.Align(map.GetSize(), FILE_ALIGMENT),
         PointerToRawData = GetPEHeaderSize(),
         Characteristics = SectionCharacteristic.MEM_READ
                           | SectionCharacteristic.MEM_EXECUTE
                           | SectionCharacteristic.CNT_CODE
     });
 }
コード例 #8
0
        private SectionHeader GetRsrcHeader(Win32ResourceBuffer buffer)
        {
            uint rva = GetNextVirtualAddress(_text);

            return(new SectionHeader()
            {
                Name = ".rsrc",
                VirtualSize = (uint)buffer.Length,
                VirtualAddress = rva,
                SizeOfRawData = BitArithmetic.Align((uint)buffer.Length, FILE_ALIGMENT),
                PointerToRawData = _text.Header.PointerToRawData + _text.Header.SizeOfRawData,
                Characteristics = SectionCharacteristic.MEM_READ
                                  | SectionCharacteristic.CNT_INITIALIZED_DATA
            });
        }
コード例 #9
0
        private SectionHeader GetRelocHeader(RelocationBuffer buffer)
        {
            uint rva = GetNextVirtualAddress(_rsrc);

            return(new SectionHeader()
            {
                Name = ".reloc",
                VirtualSize = (uint)buffer.Length,
                VirtualAddress = rva,
                SizeOfRawData = BitArithmetic.Align((uint)buffer.Length, FILE_ALIGMENT),
                PointerToRawData = _rsrc.Header.PointerToRawData + _rsrc.Header.SizeOfRawData,
                Characteristics = SectionCharacteristic.MEM_READ
                                  | SectionCharacteristic.CNT_INITIALIZED_DATA
                                  | SectionCharacteristic.MEM_DISCARDABLE
            });
        }
コード例 #10
0
        private string ReadAlignedString(int length)
        {
            var read   = 0;
            var buffer = new char[length];

            while (read < length)
            {
                read++;
                var current = ReadByte();
                if (current == 0)
                {
                    break;
                }

                buffer[read - 1] = (char)current;
            }

            Advance(BitArithmetic.Align(read, 4) - read);
            return(new string(buffer, 0, read - 1));
        }
コード例 #11
0
        private void WriteAlignedBlobHeap(BlobBuilder builder)
        {
            int alignment = BitArithmetic.Align(_blobHeapSize, 4) - _blobHeapSize;

            var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize + alignment));

            // Perf consideration: With large heap the following loop may cause a lot of cache misses
            // since the order of entries in _blobs dictionary depends on the hash of the array values,
            // which is not correlated to the heap index. If we observe such issue we should order
            // the entries by heap position before running this loop.
            foreach (var entry in _blobs)
            {
                int heapOffset = MetadataTokens.GetHeapOffset(entry.Value);
                var blob       = entry.Key;

                writer.Offset = heapOffset;
                writer.WriteCompressedInteger(blob.Length);
                writer.WriteBytes(blob);
            }

            writer.Offset = _blobHeapSize;
            writer.WriteBytes(0, alignment);
        }
コード例 #12
0
        public void ValidateTagToTokenConversion()
        {
            foreach (var tag in GetTags())
            {
                Assert.True((1 << tag.GetNumberOfBits()) <= tag.GetTagToTokenTypeArray().Length,
                            tag.Name + " has mismatch between NumberOfBits and TagToTokenTypeArray.Length");

                Assert.True(tag.GetTagMask() == (1 << tag.GetNumberOfBits()) - 1,
                            tag.Name + " has mismatch between NumberOfBits and TagMask");

                TableMask tablesNotUsed = tag.GetTablesReferenced();

                Assert.True(tablesNotUsed != 0,
                            tag.Name + " does not have anything in TablesReferenced.");

                int    badTagCount = 0;
                Random random      = new Random(42);

                for (uint i = 0, n = (uint)(1 << tag.GetNumberOfBits()); i < n; i++)
                {
                    uint rowId      = (uint)random.Next(((int)TokenTypeIds.RIDMask + 1));
                    uint codedIndex = i | (rowId << tag.GetNumberOfBits());

                    Handle handle;

                    try
                    {
                        handle = tag.ConvertToToken(codedIndex);
                    }
                    catch (BadImageFormatException)
                    {
                        badTagCount++;
                        continue;
                    }

                    Assert.True(handle.RowId == rowId,
                                tag.Name + " did not return correct row id.");

                    uint badRowId = (uint)random.Next((int)TokenTypeIds.RIDMask + 1, int.MaxValue);
                    Assert.Throws <BadImageFormatException>(() => tag.ConvertToToken(i | ~tag.GetTagMask()));
                    Assert.Throws <BadImageFormatException>(() => tag.ConvertToToken(i | ((TokenTypeIds.RIDMask + 1) << tag.GetNumberOfBits())));
                    Assert.Throws <BadImageFormatException>(() => tag.ConvertToToken(i | (badRowId << tag.GetNumberOfBits())));

                    Assert.True((uint)(handle.Kind) << 24 == tag.GetTagToTokenTypeArray()[i],
                                tag.Name + " did not return handle type matching its TagToTokenTypeArray or TagToTokenTypeByteVector");

                    TableMask handleTableMask = (TableMask)(1UL << (int)handle.Kind);

                    Assert.True(tag.GetTagValue(handleTableMask.ToString()) == i,
                                tag.Name + " does not have a constant for '" + handleTableMask.ToString() + "' with matching value: " + i);

                    Assert.True((tag.GetTablesReferenced() & handleTableMask) == handleTableMask,
                                tag.Name + " does not declare that it references '" + handleTableMask.ToString() + "' table.");

                    TableMask tablesNotUsedPreviously = tablesNotUsed;
                    tablesNotUsed &= ~handleTableMask;

                    Assert.True(handleTableMask == 0 || tablesNotUsedPreviously != tablesNotUsed,
                                tag.Name + " did not use any table for tag value: " + i);

                    uint?roundTripped = tag.ConvertToTag(handle);
                    Assert.True(roundTripped == null || roundTripped == codedIndex,
                                tag.Name + " did not round trip coded index -> handle -> coded index");
                }

                Assert.True(badTagCount == (1 << tag.GetNumberOfBits()) - BitArithmetic.CountBits((ulong)tag.GetTablesReferenced()),
                            tag.Name + " did not find the correct number of bad tags.");

                Assert.True(tablesNotUsed == 0,
                            tag.Name + " did not use all of TablesReferenced when passed all possible tag bits up to NumberOfBits.");
            }
        }
コード例 #13
0
ファイル: PEBuilder.cs プロジェクト: mikem8361/runtime
        private void WritePEHeader(BlobBuilder builder, PEDirectoriesBuilder directories, ImmutableArray <SerializedSection> sections)
        {
            builder.WriteUInt16((ushort)(Header.Is32Bit ? PEMagic.PE32 : PEMagic.PE32Plus));
            builder.WriteByte(Header.MajorLinkerVersion);
            builder.WriteByte(Header.MinorLinkerVersion);

            // SizeOfCode:
            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsCode));

            // SizeOfInitializedData:
            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsInitializedData));

            // SizeOfUninitializedData:
            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsUninitializedData));

            // AddressOfEntryPoint:
            builder.WriteUInt32((uint)directories.AddressOfEntryPoint);

            // BaseOfCode:
            int codeSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsCode);

            builder.WriteUInt32((uint)(codeSectionIndex != -1 ? sections[codeSectionIndex].RelativeVirtualAddress : 0));

            if (Header.Is32Bit)
            {
                // BaseOfData:
                int dataSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsInitializedData);
                builder.WriteUInt32((uint)(dataSectionIndex != -1 ? sections[dataSectionIndex].RelativeVirtualAddress : 0));

                builder.WriteUInt32((uint)Header.ImageBase);
            }
            else
            {
                builder.WriteUInt64(Header.ImageBase);
            }

            // NT additional fields:
            builder.WriteUInt32((uint)Header.SectionAlignment);
            builder.WriteUInt32((uint)Header.FileAlignment);
            builder.WriteUInt16(Header.MajorOperatingSystemVersion);
            builder.WriteUInt16(Header.MinorOperatingSystemVersion);
            builder.WriteUInt16(Header.MajorImageVersion);
            builder.WriteUInt16(Header.MinorImageVersion);
            builder.WriteUInt16(Header.MajorSubsystemVersion);
            builder.WriteUInt16(Header.MinorSubsystemVersion);

            // Win32VersionValue (reserved, should be 0)
            builder.WriteUInt32(0);

            // SizeOfImage:
            var lastSection = sections[sections.Length - 1];

            builder.WriteUInt32((uint)BitArithmetic.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, Header.SectionAlignment));

            // SizeOfHeaders:
            builder.WriteUInt32((uint)BitArithmetic.Align(Header.ComputeSizeOfPEHeaders(sections.Length), Header.FileAlignment));

            // Checksum:
            // Shall be zero for strong name signing.
            _lazyChecksum = builder.ReserveBytes(sizeof(uint));
            new BlobWriter(_lazyChecksum).WriteUInt32(0);

            builder.WriteUInt16((ushort)Header.Subsystem);
            builder.WriteUInt16((ushort)Header.DllCharacteristics);

            if (Header.Is32Bit)
            {
                builder.WriteUInt32((uint)Header.SizeOfStackReserve);
                builder.WriteUInt32((uint)Header.SizeOfStackCommit);
                builder.WriteUInt32((uint)Header.SizeOfHeapReserve);
                builder.WriteUInt32((uint)Header.SizeOfHeapCommit);
            }
            else
            {
                builder.WriteUInt64(Header.SizeOfStackReserve);
                builder.WriteUInt64(Header.SizeOfStackCommit);
                builder.WriteUInt64(Header.SizeOfHeapReserve);
                builder.WriteUInt64(Header.SizeOfHeapCommit);
            }

            // LoaderFlags
            builder.WriteUInt32(0);

            // The number of data-directory entries in the remainder of the header.
            builder.WriteUInt32(16);

            // directory entries:
            builder.WriteUInt32((uint)directories.ExportTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ExportTable.Size);
            builder.WriteUInt32((uint)directories.ImportTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ImportTable.Size);
            builder.WriteUInt32((uint)directories.ResourceTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ResourceTable.Size);
            builder.WriteUInt32((uint)directories.ExceptionTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ExceptionTable.Size);

            // Authenticode CertificateTable directory. Shall be zero before the PE is signed.
            builder.WriteUInt32(0);
            builder.WriteUInt32(0);

            builder.WriteUInt32((uint)directories.BaseRelocationTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.BaseRelocationTable.Size);
            builder.WriteUInt32((uint)directories.DebugTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.DebugTable.Size);
            builder.WriteUInt32((uint)directories.CopyrightTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.CopyrightTable.Size);
            builder.WriteUInt32((uint)directories.GlobalPointerTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.GlobalPointerTable.Size);
            builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.Size);
            builder.WriteUInt32((uint)directories.LoadConfigTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.LoadConfigTable.Size);
            builder.WriteUInt32((uint)directories.BoundImportTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.BoundImportTable.Size);
            builder.WriteUInt32((uint)directories.ImportAddressTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.ImportAddressTable.Size);
            builder.WriteUInt32((uint)directories.DelayImportTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.DelayImportTable.Size);
            builder.WriteUInt32((uint)directories.CorHeaderTable.RelativeVirtualAddress);
            builder.WriteUInt32((uint)directories.CorHeaderTable.Size);

            // Reserved, should be 0
            builder.WriteUInt64(0);
        }
コード例 #14
0
 public void Align(int alignment)
 {
     int offset = Offset;
     WriteBytes(0, BitArithmetic.Align(offset, alignment) - offset);
 }
コード例 #15
0
 public void Add(TextSegment segment, uint size, uint align)
 {
     Add(segment, BitArithmetic.Align(size, align));
 }
コード例 #16
0
 private uint GetNextVirtualAddress(ISection section)
 {
     return(section.Header.VirtualAddress +
            BitArithmetic.Align(section.Header.VirtualSize, SECTION_ALIGMENT));
 }
コード例 #17
0
        internal MetadataSizes(
            ImmutableArray <int> rowCounts,
            ImmutableArray <int> externalRowCounts,
            ImmutableArray <int> heapSizes,
            bool isMinimalDelta,
            bool isStandaloneDebugMetadata)
        {
            Debug.Assert(rowCounts.Length == MetadataTokens.TableCount);
            Debug.Assert(externalRowCounts.Length == MetadataTokens.TableCount);
            Debug.Assert(heapSizes.Length == MetadataTokens.HeapCount);

            RowCounts         = rowCounts;
            ExternalRowCounts = externalRowCounts;
            HeapSizes         = heapSizes;
            IsMinimalDelta    = isMinimalDelta;

            BlobReferenceIsSmall   = !isMinimalDelta && heapSizes[(int)HeapIndex.Blob] <= ushort.MaxValue;
            StringReferenceIsSmall = !isMinimalDelta && heapSizes[(int)HeapIndex.String] <= ushort.MaxValue;
            GuidReferenceIsSmall   = !isMinimalDelta && heapSizes[(int)HeapIndex.Guid] <= ushort.MaxValue;

            PresentTablesMask  = ComputeNonEmptyTableMask(rowCounts);
            ExternalTablesMask = ComputeNonEmptyTableMask(externalRowCounts);

            // table can either be present or external, it can't be both:
            Debug.Assert((PresentTablesMask & ExternalTablesMask) == 0);

            CustomAttributeTypeCodedIndexIsSmall = IsReferenceSmall(3, TableIndex.MethodDef, TableIndex.MemberRef);
            DeclSecurityCodedIndexIsSmall        = IsReferenceSmall(2, TableIndex.MethodDef, TableIndex.TypeDef);
            EventDefReferenceIsSmall             = IsReferenceSmall(0, TableIndex.Event);
            FieldDefReferenceIsSmall             = IsReferenceSmall(0, TableIndex.Field);
            GenericParamReferenceIsSmall         = IsReferenceSmall(0, TableIndex.GenericParam);
            HasConstantCodedIndexIsSmall         = IsReferenceSmall(2, TableIndex.Field, TableIndex.Param, TableIndex.Property);

            HasCustomAttributeCodedIndexIsSmall = IsReferenceSmall(5,
                                                                   TableIndex.MethodDef,
                                                                   TableIndex.Field,
                                                                   TableIndex.TypeRef,
                                                                   TableIndex.TypeDef,
                                                                   TableIndex.Param,
                                                                   TableIndex.InterfaceImpl,
                                                                   TableIndex.MemberRef,
                                                                   TableIndex.Module,
                                                                   TableIndex.DeclSecurity,
                                                                   TableIndex.Property,
                                                                   TableIndex.Event,
                                                                   TableIndex.StandAloneSig,
                                                                   TableIndex.ModuleRef,
                                                                   TableIndex.TypeSpec,
                                                                   TableIndex.Assembly,
                                                                   TableIndex.AssemblyRef,
                                                                   TableIndex.File,
                                                                   TableIndex.ExportedType,
                                                                   TableIndex.ManifestResource,
                                                                   TableIndex.GenericParam,
                                                                   TableIndex.GenericParamConstraint,
                                                                   TableIndex.MethodSpec);

            HasFieldMarshalCodedIndexIsSmall = IsReferenceSmall(1, TableIndex.Field, TableIndex.Param);
            HasSemanticsCodedIndexIsSmall    = IsReferenceSmall(1, TableIndex.Event, TableIndex.Property);
            ImplementationCodedIndexIsSmall  = IsReferenceSmall(2, TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType);
            MemberForwardedCodedIndexIsSmall = IsReferenceSmall(1, TableIndex.Field, TableIndex.MethodDef);
            MemberRefParentCodedIndexIsSmall = IsReferenceSmall(3, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.MethodDef, TableIndex.TypeSpec);
            MethodDefReferenceIsSmall        = IsReferenceSmall(0, TableIndex.MethodDef);
            MethodDefOrRefCodedIndexIsSmall  = IsReferenceSmall(1, TableIndex.MethodDef, TableIndex.MemberRef);
            ModuleRefReferenceIsSmall        = IsReferenceSmall(0, TableIndex.ModuleRef);
            ParameterReferenceIsSmall        = IsReferenceSmall(0, TableIndex.Param);
            PropertyDefReferenceIsSmall      = IsReferenceSmall(0, TableIndex.Property);
            ResolutionScopeCodedIndexIsSmall = IsReferenceSmall(2, TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef);
            TypeDefReferenceIsSmall          = IsReferenceSmall(0, TableIndex.TypeDef);
            TypeDefOrRefCodedIndexIsSmall    = IsReferenceSmall(2, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec);
            TypeOrMethodDefCodedIndexIsSmall = IsReferenceSmall(1, TableIndex.TypeDef, TableIndex.MethodDef);

            DocumentReferenceIsSmall      = IsReferenceSmall(0, TableIndex.Document);
            LocalVariableReferenceIsSmall = IsReferenceSmall(0, TableIndex.LocalVariable);
            LocalConstantReferenceIsSmall = IsReferenceSmall(0, TableIndex.LocalConstant);
            ImportScopeReferenceIsSmall   = IsReferenceSmall(0, TableIndex.ImportScope);

            HasCustomDebugInformationCodedIndexIsSmall = IsReferenceSmall(5,
                                                                          TableIndex.MethodDef,
                                                                          TableIndex.Field,
                                                                          TableIndex.TypeRef,
                                                                          TableIndex.TypeDef,
                                                                          TableIndex.Param,
                                                                          TableIndex.InterfaceImpl,
                                                                          TableIndex.MemberRef,
                                                                          TableIndex.Module,
                                                                          TableIndex.DeclSecurity,
                                                                          TableIndex.Property,
                                                                          TableIndex.Event,
                                                                          TableIndex.StandAloneSig,
                                                                          TableIndex.ModuleRef,
                                                                          TableIndex.TypeSpec,
                                                                          TableIndex.Assembly,
                                                                          TableIndex.AssemblyRef,
                                                                          TableIndex.File,
                                                                          TableIndex.ExportedType,
                                                                          TableIndex.ManifestResource,
                                                                          TableIndex.GenericParam,
                                                                          TableIndex.GenericParamConstraint,
                                                                          TableIndex.MethodSpec,
                                                                          TableIndex.Document,
                                                                          TableIndex.LocalScope,
                                                                          TableIndex.LocalVariable,
                                                                          TableIndex.LocalConstant,
                                                                          TableIndex.ImportScope);

            int size = CalculateTableStreamHeaderSize();

            const byte small = 2;
            const byte large = 4;

            byte blobReferenceSize   = BlobReferenceIsSmall ? small : large;
            byte stringReferenceSize = StringReferenceIsSmall ? small : large;
            byte guidReferenceSize   = GuidReferenceIsSmall ? small : large;
            byte customAttributeTypeCodedIndexSize = CustomAttributeTypeCodedIndexIsSmall ? small : large;
            byte declSecurityCodedIndexSize        = DeclSecurityCodedIndexIsSmall ? small : large;
            byte eventDefReferenceSize             = EventDefReferenceIsSmall ? small : large;
            byte fieldDefReferenceSize             = FieldDefReferenceIsSmall ? small : large;
            byte genericParamReferenceSize         = GenericParamReferenceIsSmall ? small : large;
            byte hasConstantCodedIndexSize         = HasConstantCodedIndexIsSmall ? small : large;
            byte hasCustomAttributeCodedIndexSize  = HasCustomAttributeCodedIndexIsSmall ? small : large;
            byte hasFieldMarshalCodedIndexSize     = HasFieldMarshalCodedIndexIsSmall ? small : large;
            byte hasSemanticsCodedIndexSize        = HasSemanticsCodedIndexIsSmall ? small : large;
            byte implementationCodedIndexSize      = ImplementationCodedIndexIsSmall ? small : large;
            byte memberForwardedCodedIndexSize     = MemberForwardedCodedIndexIsSmall ? small : large;
            byte memberRefParentCodedIndexSize     = MemberRefParentCodedIndexIsSmall ? small : large;
            byte methodDefReferenceSize            = MethodDefReferenceIsSmall ? small : large;
            byte methodDefOrRefCodedIndexSize      = MethodDefOrRefCodedIndexIsSmall ? small : large;
            byte moduleRefReferenceSize            = ModuleRefReferenceIsSmall ? small : large;
            byte parameterReferenceSize            = ParameterReferenceIsSmall ? small : large;
            byte propertyDefReferenceSize          = PropertyDefReferenceIsSmall ? small : large;
            byte resolutionScopeCodedIndexSize     = ResolutionScopeCodedIndexIsSmall ? small : large;
            byte typeDefReferenceSize                    = TypeDefReferenceIsSmall ? small : large;
            byte typeDefOrRefCodedIndexSize              = TypeDefOrRefCodedIndexIsSmall ? small : large;
            byte typeOrMethodDefCodedIndexSize           = TypeOrMethodDefCodedIndexIsSmall ? small : large;
            byte documentReferenceSize                   = DocumentReferenceIsSmall ? small : large;
            byte localVariableReferenceSize              = LocalVariableReferenceIsSmall ? small : large;
            byte localConstantReferenceSize              = LocalConstantReferenceIsSmall ? small : large;
            byte importScopeReferenceSize                = ImportScopeReferenceIsSmall ? small : large;
            byte hasCustomDebugInformationCodedIndexSize = HasCustomDebugInformationCodedIndexIsSmall ? small : large;

            size += GetTableSize(TableIndex.Module, 2 + 3 * guidReferenceSize + stringReferenceSize);
            size += GetTableSize(TableIndex.TypeRef, resolutionScopeCodedIndexSize + stringReferenceSize + stringReferenceSize);
            size += GetTableSize(TableIndex.TypeDef, 4 + stringReferenceSize + stringReferenceSize + typeDefOrRefCodedIndexSize + fieldDefReferenceSize + methodDefReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.FieldPtr] == 0);
            size += GetTableSize(TableIndex.Field, 2 + stringReferenceSize + blobReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.MethodPtr] == 0);
            size += GetTableSize(TableIndex.MethodDef, 8 + stringReferenceSize + blobReferenceSize + parameterReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.ParamPtr] == 0);
            size += GetTableSize(TableIndex.Param, 4 + stringReferenceSize);
            size += GetTableSize(TableIndex.InterfaceImpl, typeDefReferenceSize + typeDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.MemberRef, memberRefParentCodedIndexSize + stringReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.Constant, 2 + hasConstantCodedIndexSize + blobReferenceSize);
            size += GetTableSize(TableIndex.CustomAttribute, hasCustomAttributeCodedIndexSize + customAttributeTypeCodedIndexSize + blobReferenceSize);
            size += GetTableSize(TableIndex.FieldMarshal, hasFieldMarshalCodedIndexSize + blobReferenceSize);
            size += GetTableSize(TableIndex.DeclSecurity, 2 + declSecurityCodedIndexSize + blobReferenceSize);
            size += GetTableSize(TableIndex.ClassLayout, 6 + typeDefReferenceSize);
            size += GetTableSize(TableIndex.FieldLayout, 4 + fieldDefReferenceSize);
            size += GetTableSize(TableIndex.StandAloneSig, blobReferenceSize);
            size += GetTableSize(TableIndex.EventMap, typeDefReferenceSize + eventDefReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.EventPtr] == 0);
            size += GetTableSize(TableIndex.Event, 2 + stringReferenceSize + typeDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.PropertyMap, typeDefReferenceSize + propertyDefReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.PropertyPtr] == 0);
            size += GetTableSize(TableIndex.Property, 2 + stringReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.MethodSemantics, 2 + methodDefReferenceSize + hasSemanticsCodedIndexSize);
            size += GetTableSize(TableIndex.MethodImpl, typeDefReferenceSize + methodDefOrRefCodedIndexSize + methodDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.ModuleRef, stringReferenceSize);
            size += GetTableSize(TableIndex.TypeSpec, blobReferenceSize);
            size += GetTableSize(TableIndex.ImplMap, 2 + memberForwardedCodedIndexSize + stringReferenceSize + moduleRefReferenceSize);
            size += GetTableSize(TableIndex.FieldRva, 4 + fieldDefReferenceSize);
            size += GetTableSize(TableIndex.EncLog, 8);
            size += GetTableSize(TableIndex.EncMap, 4);
            size += GetTableSize(TableIndex.Assembly, 16 + blobReferenceSize + stringReferenceSize + stringReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyProcessor] == 0);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyOS] == 0);
            size += GetTableSize(TableIndex.AssemblyRef, 12 + blobReferenceSize + stringReferenceSize + stringReferenceSize + blobReferenceSize);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyRefProcessor] == 0);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyRefOS] == 0);
            size += GetTableSize(TableIndex.File, 4 + stringReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.ExportedType, 8 + stringReferenceSize + stringReferenceSize + implementationCodedIndexSize);
            size += GetTableSize(TableIndex.ManifestResource, 8 + stringReferenceSize + implementationCodedIndexSize);
            size += GetTableSize(TableIndex.NestedClass, typeDefReferenceSize + typeDefReferenceSize);
            size += GetTableSize(TableIndex.GenericParam, 4 + typeOrMethodDefCodedIndexSize + stringReferenceSize);
            size += GetTableSize(TableIndex.MethodSpec, methodDefOrRefCodedIndexSize + blobReferenceSize);
            size += GetTableSize(TableIndex.GenericParamConstraint, genericParamReferenceSize + typeDefOrRefCodedIndexSize);

            size += GetTableSize(TableIndex.Document, blobReferenceSize + guidReferenceSize + blobReferenceSize + guidReferenceSize);
            size += GetTableSize(TableIndex.MethodDebugInformation, documentReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.LocalScope, methodDefReferenceSize + importScopeReferenceSize + localVariableReferenceSize + localConstantReferenceSize + 4 + 4);
            size += GetTableSize(TableIndex.LocalVariable, 2 + 2 + stringReferenceSize);
            size += GetTableSize(TableIndex.LocalConstant, stringReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.ImportScope, importScopeReferenceSize + blobReferenceSize);
            size += GetTableSize(TableIndex.StateMachineMethod, methodDefReferenceSize + methodDefReferenceSize);
            size += GetTableSize(TableIndex.CustomDebugInformation, hasCustomDebugInformationCodedIndexSize + guidReferenceSize + blobReferenceSize);

            // +1 for terminating 0 byte
            size = BitArithmetic.Align(size + 1, StreamAlignment);

            MetadataTableStreamSize = size;

            size += GetAlignedHeapSize(HeapIndex.String);
            size += GetAlignedHeapSize(HeapIndex.UserString);
            size += GetAlignedHeapSize(HeapIndex.Guid);
            size += GetAlignedHeapSize(HeapIndex.Blob);

            StandalonePdbStreamSize = isStandaloneDebugMetadata ? CalculateStandalonePdbStreamSize() : 0;
            size += StandalonePdbStreamSize;

            MetadataStreamStorageSize = size;
        }
コード例 #18
0
 public int GetAlignedHeapSize(HeapIndex index)
 {
     return(BitArithmetic.Align(HeapSizes[(int)index], StreamAlignment));
 }
コード例 #19
0
 // Helper methods
 internal int GetNumberOfTablesPresent()
 {
     return(BitArithmetic.CountBits((ulong)this.ValidTables));
 }
コード例 #20
0
 private int ComputeOffsetToMetadata()
 {
     return(OffsetToILStream + BitArithmetic.Align(ILStreamSize, 4));
 }
コード例 #21
0
ファイル: BlobBuilder.cs プロジェクト: Fredo-Q/dotnet-corefx
        /// <exception cref="InvalidOperationException">Builder is not writable, it has been linked with another one.</exception>
        public void Align(int alignment)
        {
            int position = Count;

            WriteBytes(0, BitArithmetic.Align(position, alignment) - position);
        }
コード例 #22
0
        public MetadataSizes(
            ImmutableArray <int> rowCounts,
            ImmutableArray <int> externalRowCounts,
            ImmutableArray <int> heapSizes,
            bool isMinimalDelta,
            bool isStandaloneDebugMetadata)
        {
            Debug.Assert(rowCounts.Length == MetadataTokens.TableCount);
            Debug.Assert(externalRowCounts.Length == MetadataTokens.TableCount);
            Debug.Assert(heapSizes.Length == MetadataTokens.HeapCount);

            const byte large = 4;
            const byte small = 2;

            this.RowCounts         = rowCounts;
            this.ExternalRowCounts = externalRowCounts;
            this.HeapSizes         = heapSizes;
            this.IsMinimalDelta    = isMinimalDelta;

            this.BlobIndexSize   = (isMinimalDelta || heapSizes[(int)HeapIndex.Blob] > ushort.MaxValue) ? large : small;
            this.StringIndexSize = (isMinimalDelta || heapSizes[(int)HeapIndex.String] > ushort.MaxValue) ? large : small;
            this.GuidIndexSize   = (isMinimalDelta || heapSizes[(int)HeapIndex.Guid] > ushort.MaxValue) ? large : small;

            this.PresentTablesMask  = ComputeNonEmptyTableMask(rowCounts);
            this.ExternalTablesMask = ComputeNonEmptyTableMask(externalRowCounts);

            // table can either be present or external, it can't be both:
            Debug.Assert((PresentTablesMask & ExternalTablesMask) == 0);

            this.CustomAttributeTypeCodedIndexSize = this.GetReferenceByteSize(3, TableIndex.MethodDef, TableIndex.MemberRef);
            this.DeclSecurityCodedIndexSize        = this.GetReferenceByteSize(2, TableIndex.MethodDef, TableIndex.TypeDef);
            this.EventDefIndexSize         = this.GetReferenceByteSize(0, TableIndex.Event);
            this.FieldDefIndexSize         = this.GetReferenceByteSize(0, TableIndex.Field);
            this.GenericParamIndexSize     = this.GetReferenceByteSize(0, TableIndex.GenericParam);
            this.HasConstantCodedIndexSize = this.GetReferenceByteSize(2, TableIndex.Field, TableIndex.Param, TableIndex.Property);

            this.HasCustomAttributeCodedIndexSize = this.GetReferenceByteSize(5,
                                                                              TableIndex.MethodDef,
                                                                              TableIndex.Field,
                                                                              TableIndex.TypeRef,
                                                                              TableIndex.TypeDef,
                                                                              TableIndex.Param,
                                                                              TableIndex.InterfaceImpl,
                                                                              TableIndex.MemberRef,
                                                                              TableIndex.Module,
                                                                              TableIndex.DeclSecurity,
                                                                              TableIndex.Property,
                                                                              TableIndex.Event,
                                                                              TableIndex.StandAloneSig,
                                                                              TableIndex.ModuleRef,
                                                                              TableIndex.TypeSpec,
                                                                              TableIndex.Assembly,
                                                                              TableIndex.AssemblyRef,
                                                                              TableIndex.File,
                                                                              TableIndex.ExportedType,
                                                                              TableIndex.ManifestResource,
                                                                              TableIndex.GenericParam,
                                                                              TableIndex.GenericParamConstraint,
                                                                              TableIndex.MethodSpec);

            this.HasFieldMarshalCodedIndexSize = this.GetReferenceByteSize(1, TableIndex.Field, TableIndex.Param);
            this.HasSemanticsCodedIndexSize    = this.GetReferenceByteSize(1, TableIndex.Event, TableIndex.Property);
            this.ImplementationCodedIndexSize  = this.GetReferenceByteSize(2, TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType);
            this.MemberForwardedCodedIndexSize = this.GetReferenceByteSize(1, TableIndex.Field, TableIndex.MethodDef);
            this.MemberRefParentCodedIndexSize = this.GetReferenceByteSize(3, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.MethodDef, TableIndex.TypeSpec);
            this.MethodDefIndexSize            = this.GetReferenceByteSize(0, TableIndex.MethodDef);
            this.MethodDefOrRefCodedIndexSize  = this.GetReferenceByteSize(1, TableIndex.MethodDef, TableIndex.MemberRef);
            this.ModuleRefIndexSize            = this.GetReferenceByteSize(0, TableIndex.ModuleRef);
            this.ParameterIndexSize            = this.GetReferenceByteSize(0, TableIndex.Param);
            this.PropertyDefIndexSize          = this.GetReferenceByteSize(0, TableIndex.Property);
            this.ResolutionScopeCodedIndexSize = this.GetReferenceByteSize(2, TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef);
            this.TypeDefIndexSize              = this.GetReferenceByteSize(0, TableIndex.TypeDef);
            this.TypeDefOrRefCodedIndexSize    = this.GetReferenceByteSize(2, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec);
            this.TypeOrMethodDefCodedIndexSize = this.GetReferenceByteSize(1, TableIndex.TypeDef, TableIndex.MethodDef);

            this.DocumentIndexSize      = this.GetReferenceByteSize(0, TableIndex.Document);
            this.LocalVariableIndexSize = this.GetReferenceByteSize(0, TableIndex.LocalVariable);
            this.LocalConstantIndexSize = this.GetReferenceByteSize(0, TableIndex.LocalConstant);
            this.ImportScopeIndexSize   = this.GetReferenceByteSize(0, TableIndex.ImportScope);

            this.HasCustomDebugInformationSize = this.GetReferenceByteSize(5,
                                                                           TableIndex.MethodDef,
                                                                           TableIndex.Field,
                                                                           TableIndex.TypeRef,
                                                                           TableIndex.TypeDef,
                                                                           TableIndex.Param,
                                                                           TableIndex.InterfaceImpl,
                                                                           TableIndex.MemberRef,
                                                                           TableIndex.Module,
                                                                           TableIndex.DeclSecurity,
                                                                           TableIndex.Property,
                                                                           TableIndex.Event,
                                                                           TableIndex.StandAloneSig,
                                                                           TableIndex.ModuleRef,
                                                                           TableIndex.TypeSpec,
                                                                           TableIndex.Assembly,
                                                                           TableIndex.AssemblyRef,
                                                                           TableIndex.File,
                                                                           TableIndex.ExportedType,
                                                                           TableIndex.ManifestResource,
                                                                           TableIndex.GenericParam,
                                                                           TableIndex.GenericParamConstraint,
                                                                           TableIndex.MethodSpec,
                                                                           TableIndex.Document,
                                                                           TableIndex.LocalScope,
                                                                           TableIndex.LocalVariable,
                                                                           TableIndex.LocalConstant,
                                                                           TableIndex.ImportScope);

            int size = this.CalculateTableStreamHeaderSize();

            size += GetTableSize(TableIndex.Module, 2 + 3 * this.GuidIndexSize + this.StringIndexSize);
            size += GetTableSize(TableIndex.TypeRef, this.ResolutionScopeCodedIndexSize + this.StringIndexSize + this.StringIndexSize);
            size += GetTableSize(TableIndex.TypeDef, 4 + this.StringIndexSize + this.StringIndexSize + this.TypeDefOrRefCodedIndexSize + this.FieldDefIndexSize + this.MethodDefIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.FieldPtr] == 0);
            size += GetTableSize(TableIndex.Field, 2 + this.StringIndexSize + this.BlobIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.MethodPtr] == 0);
            size += GetTableSize(TableIndex.MethodDef, 8 + this.StringIndexSize + this.BlobIndexSize + this.ParameterIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.ParamPtr] == 0);
            size += GetTableSize(TableIndex.Param, 4 + this.StringIndexSize);
            size += GetTableSize(TableIndex.InterfaceImpl, this.TypeDefIndexSize + this.TypeDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.MemberRef, this.MemberRefParentCodedIndexSize + this.StringIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.Constant, 2 + this.HasConstantCodedIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.CustomAttribute, this.HasCustomAttributeCodedIndexSize + this.CustomAttributeTypeCodedIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.FieldMarshal, this.HasFieldMarshalCodedIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.DeclSecurity, 2 + this.DeclSecurityCodedIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.ClassLayout, 6 + this.TypeDefIndexSize);
            size += GetTableSize(TableIndex.FieldLayout, 4 + this.FieldDefIndexSize);
            size += GetTableSize(TableIndex.StandAloneSig, this.BlobIndexSize);
            size += GetTableSize(TableIndex.EventMap, this.TypeDefIndexSize + this.EventDefIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.EventPtr] == 0);
            size += GetTableSize(TableIndex.Event, 2 + this.StringIndexSize + this.TypeDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.PropertyMap, this.TypeDefIndexSize + this.PropertyDefIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.PropertyPtr] == 0);
            size += GetTableSize(TableIndex.Property, 2 + this.StringIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.MethodSemantics, 2 + this.MethodDefIndexSize + this.HasSemanticsCodedIndexSize);
            size += GetTableSize(TableIndex.MethodImpl, 0 + this.TypeDefIndexSize + this.MethodDefOrRefCodedIndexSize + this.MethodDefOrRefCodedIndexSize);
            size += GetTableSize(TableIndex.ModuleRef, 0 + this.StringIndexSize);
            size += GetTableSize(TableIndex.TypeSpec, 0 + this.BlobIndexSize);
            size += GetTableSize(TableIndex.ImplMap, 2 + this.MemberForwardedCodedIndexSize + this.StringIndexSize + this.ModuleRefIndexSize);
            size += GetTableSize(TableIndex.FieldRva, 4 + this.FieldDefIndexSize);
            size += GetTableSize(TableIndex.EncLog, 8);
            size += GetTableSize(TableIndex.EncMap, 4);
            size += GetTableSize(TableIndex.Assembly, 16 + this.BlobIndexSize + this.StringIndexSize + this.StringIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyProcessor] == 0);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyOS] == 0);
            size += GetTableSize(TableIndex.AssemblyRef, 12 + this.BlobIndexSize + this.StringIndexSize + this.StringIndexSize + this.BlobIndexSize);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyRefProcessor] == 0);
            Debug.Assert(rowCounts[(int)TableIndex.AssemblyRefOS] == 0);
            size += GetTableSize(TableIndex.File, 4 + this.StringIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.ExportedType, 8 + this.StringIndexSize + this.StringIndexSize + this.ImplementationCodedIndexSize);
            size += GetTableSize(TableIndex.ManifestResource, 8 + this.StringIndexSize + this.ImplementationCodedIndexSize);
            size += GetTableSize(TableIndex.NestedClass, this.TypeDefIndexSize + this.TypeDefIndexSize);
            size += GetTableSize(TableIndex.GenericParam, 4 + this.TypeOrMethodDefCodedIndexSize + this.StringIndexSize);
            size += GetTableSize(TableIndex.MethodSpec, this.MethodDefOrRefCodedIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.GenericParamConstraint, this.GenericParamIndexSize + this.TypeDefOrRefCodedIndexSize);

            size += GetTableSize(TableIndex.Document, this.BlobIndexSize + this.GuidIndexSize + this.BlobIndexSize + this.GuidIndexSize);
            size += GetTableSize(TableIndex.MethodDebugInformation, this.DocumentIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.LocalScope, this.MethodDefIndexSize + this.ImportScopeIndexSize + this.LocalVariableIndexSize + this.LocalConstantIndexSize + 4 + 4);
            size += GetTableSize(TableIndex.LocalVariable, 2 + 2 + this.StringIndexSize);
            size += GetTableSize(TableIndex.LocalConstant, this.StringIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.ImportScope, this.ImportScopeIndexSize + this.BlobIndexSize);
            size += GetTableSize(TableIndex.StateMachineMethod, this.MethodDefIndexSize + this.MethodDefIndexSize);
            size += GetTableSize(TableIndex.CustomDebugInformation, this.HasCustomDebugInformationSize + this.GuidIndexSize + this.BlobIndexSize);

            // +1 for terminating 0 byte
            size = BitArithmetic.Align(size + 1, StreamAlignment);

            this.MetadataTableStreamSize = size;

            size += GetAlignedHeapSize(HeapIndex.String);
            size += GetAlignedHeapSize(HeapIndex.UserString);
            size += GetAlignedHeapSize(HeapIndex.Guid);
            size += GetAlignedHeapSize(HeapIndex.Blob);

            this.StandalonePdbStreamSize = isStandaloneDebugMetadata ? CalculateStandalonePdbStreamSize() : 0;
            size += this.StandalonePdbStreamSize;

            this.MetadataStreamStorageSize = size;
        }