// 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; } } } }
public int CalculateOffsetToMappedFieldDataStream() { int result = CalculateOffsetToMappedFieldDataStreamUnaligned(); if (MappedFieldDataSize != 0) { result = BitArithmetic.Align(result, MappedFieldDataAlignment); } return(result); }
/// <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)); }
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); }
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); }
/// <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; }
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 }); }
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 }); }
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 }); }
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)); }
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); }
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."); } }
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); }
public void Align(int alignment) { int offset = Offset; WriteBytes(0, BitArithmetic.Align(offset, alignment) - offset); }
public void Add(TextSegment segment, uint size, uint align) { Add(segment, BitArithmetic.Align(size, align)); }
private uint GetNextVirtualAddress(ISection section) { return(section.Header.VirtualAddress + BitArithmetic.Align(section.Header.VirtualSize, SECTION_ALIGMENT)); }
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; }
public int GetAlignedHeapSize(HeapIndex index) { return(BitArithmetic.Align(HeapSizes[(int)index], StreamAlignment)); }
// Helper methods internal int GetNumberOfTablesPresent() { return(BitArithmetic.CountBits((ulong)this.ValidTables)); }
private int ComputeOffsetToMetadata() { return(OffsetToILStream + BitArithmetic.Align(ILStreamSize, 4)); }
/// <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); }
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; }