private static void WriteAligned(BlobBuilder source, BlobBuilder target)
        {
            int length = source.Count;

            target.LinkSuffix(source);
            target.WriteBytes(0, BitArithmeticUtilities.Align(length, 4) - length);
        }
Пример #2
0
 public static int GetMetadataStreamHeaderSize(string streamName)
 {
     return
         (sizeof(int) +                                            // offset
          sizeof(int) +                                            // size
          BitArithmeticUtilities.Align(streamName.Length + 1, 4)); // zero-terminated name, padding
 }
Пример #3
0
        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());
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #7
0
 private int ComputeOffsetToMetadata()
 {
     return(OffsetToILStream + BitArithmeticUtilities.Align(ILStreamSize, 4));
 }
Пример #8
0
        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);
        }
Пример #9
0
        public void Align(int alignment)
        {
            int offset = Offset;

            WriteBytes(0, BitArithmeticUtilities.Align(offset, alignment) - offset);
        }
Пример #10
0
 public int GetAlignedHeapSize(HeapIndex index)
 {
     return(BitArithmeticUtilities.Align(HeapSizes[(int)index], StreamAlignment));
 }
Пример #11
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 = 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;
        }
Пример #12
0
        /// <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);
        }