private static void WriteAligned(BlobBuilder source, BlobBuilder target) { int length = source.Count; target.LinkSuffix(source); target.WriteBytes(0, BitArithmeticUtilities.Align(length, 4) - length); }
public static int GetMetadataStreamHeaderSize(string streamName) { return (sizeof(int) + // offset sizeof(int) + // size BitArithmeticUtilities.Align(streamName.Length + 1, 4)); // zero-terminated name, padding }
private ImmutableArray <SerializedSection> SerializeSections() { var result = ImmutableArray.CreateBuilder <SerializedSection>(_sections.Count); int sizeOfPeHeaders = ComputeSizeOfPeHeaders(_sections.Count, Is32Bit); var nextRva = BitArithmeticUtilities.Align(sizeOfPeHeaders, SectionAlignment); var nextPointer = BitArithmeticUtilities.Align(sizeOfPeHeaders, FileAlignment); foreach (var section in _sections) { var builder = section.Builder(new PESectionLocation(nextRva, nextPointer)); var serialized = new SerializedSection( builder, section.Name, section.Characteristics, relativeVirtualAddress: nextRva, sizeOfRawData: BitArithmeticUtilities.Align(builder.Count, FileAlignment), pointerToRawData: nextPointer); result.Add(serialized); nextRva = BitArithmeticUtilities.Align(serialized.RelativeVirtualAddress + serialized.VirtualSize, SectionAlignment); nextPointer = serialized.PointerToRawData + serialized.SizeOfRawData; } return(result.MoveToImmutable()); }
internal int CalculateStandalonePdbStreamSize() { int result = PdbIdSize + // PDB ID sizeof(int) + // EntryPoint sizeof(long) + // ReferencedTypeSystemTables BitArithmeticUtilities.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 = BitArithmeticUtilities.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); }
private void WriteAlignedBlobHeap(BlobBuilder builder) { int alignment = BitArithmeticUtilities.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); }
private int ComputeOffsetToMetadata() { return(OffsetToILStream + BitArithmeticUtilities.Align(ILStreamSize, 4)); }
private void WritePEHeader(BlobBuilder builder, PEDirectoriesBuilder headers, ImmutableArray <SerializedSection> sections) { builder.WriteUInt16((ushort)(Is32Bit ? PEMagic.PE32 : PEMagic.PE32Plus)); builder.WriteByte(MajorLinkerVersion); builder.WriteByte(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)headers.AddressOfEntryPoint); // BaseOfCode: int codeSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsCode); builder.WriteUInt32((uint)(codeSectionIndex != -1 ? sections[codeSectionIndex].RelativeVirtualAddress : 0)); if (Is32Bit) { // BaseOfData: int dataSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsInitializedData); builder.WriteUInt32((uint)(dataSectionIndex != -1 ? sections[dataSectionIndex].RelativeVirtualAddress : 0)); builder.WriteUInt32((uint)ImageBase); } else { builder.WriteUInt64(ImageBase); } // NT additional fields: builder.WriteUInt32((uint)SectionAlignment); builder.WriteUInt32((uint)FileAlignment); builder.WriteUInt16(MajorOperatingSystemVersion); builder.WriteUInt16(MinorOperatingSystemVersion); builder.WriteUInt16(MajorImageVersion); builder.WriteUInt16(MinorImageVersion); builder.WriteUInt16(MajorSubsystemVersion); builder.WriteUInt16(MinorSubsystemVersion); // Win32VersionValue (reserved, should be 0) builder.WriteUInt32(0); // SizeOfImage: var lastSection = sections[sections.Length - 1]; builder.WriteUInt32((uint)BitArithmeticUtilities.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, SectionAlignment)); // SizeOfHeaders: builder.WriteUInt32((uint)BitArithmeticUtilities.Align(ComputeSizeOfPeHeaders(sections.Length, Is32Bit), FileAlignment)); // Checksum (TODO: not supported): builder.WriteUInt32(0); builder.WriteUInt16((ushort)Subsystem); builder.WriteUInt16((ushort)DllCharacteristics); if (Is32Bit) { builder.WriteUInt32((uint)SizeOfStackReserve); builder.WriteUInt32((uint)SizeOfStackCommit); builder.WriteUInt32((uint)SizeOfHeapReserve); builder.WriteUInt32((uint)SizeOfHeapCommit); } else { builder.WriteUInt64(SizeOfStackReserve); builder.WriteUInt64(SizeOfStackCommit); builder.WriteUInt64(SizeOfHeapReserve); builder.WriteUInt64(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)headers.ExportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ExportTable.Size); builder.WriteUInt32((uint)headers.ImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ImportTable.Size); builder.WriteUInt32((uint)headers.ResourceTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ResourceTable.Size); builder.WriteUInt32((uint)headers.ExceptionTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ExceptionTable.Size); builder.WriteUInt32((uint)headers.CertificateTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CertificateTable.Size); builder.WriteUInt32((uint)headers.BaseRelocationTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.BaseRelocationTable.Size); builder.WriteUInt32((uint)headers.DebugTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.DebugTable.Size); builder.WriteUInt32((uint)headers.CopyrightTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CopyrightTable.Size); builder.WriteUInt32((uint)headers.GlobalPointerTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.GlobalPointerTable.Size); builder.WriteUInt32((uint)headers.ThreadLocalStorageTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ThreadLocalStorageTable.Size); builder.WriteUInt32((uint)headers.LoadConfigTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.LoadConfigTable.Size); builder.WriteUInt32((uint)headers.BoundImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.BoundImportTable.Size); builder.WriteUInt32((uint)headers.ImportAddressTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.ImportAddressTable.Size); builder.WriteUInt32((uint)headers.DelayImportTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.DelayImportTable.Size); builder.WriteUInt32((uint)headers.CorHeaderTable.RelativeVirtualAddress); builder.WriteUInt32((uint)headers.CorHeaderTable.Size); // Reserved, should be 0 builder.WriteUInt64(0); }
public void Align(int alignment) { int offset = Offset; WriteBytes(0, BitArithmeticUtilities.Align(offset, alignment) - offset); }
public int GetAlignedHeapSize(HeapIndex index) { return(BitArithmeticUtilities.Align(HeapSizes[(int)index], StreamAlignment)); }
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 = BitArithmeticUtilities.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; }
/// <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, BitArithmeticUtilities.Align(position, alignment) - position); }