< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 332
Coverable lines: 332
Total lines: 554
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 68
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%220%
.ctor(...)100%110%
.ctor(...)0%440%
GetSections()0%220%
Serialize(...)0%220%
SerializeSections()0%220%
WritePESignature(...)100%110%
WriteCoffHeader(...)0%220%
WritePEHeader(...)0%10100%
WriteSectionHeaders(...)0%220%
WriteSectionHeader(...)0%660%
IndexOfSection(...)0%440%
SumRawDataSizes(...)0%440%
GetContentToSign()0%10100%
GetPrefixBlob(...)100%110%
GetSuffixBlob(...)100%110%
Sign(...)0%440%
CalculateChecksum(...)0%660%
AddToChecksum(...)0%880%
AggregateChecksum(...)100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers.Binary;
 5using System.Collections.Generic;
 6using System.Collections.Immutable;
 7using System.Diagnostics;
 8using System.Reflection.Internal;
 9using System.Reflection.Metadata;
 10
 11namespace System.Reflection.PortableExecutable
 12{
 13    public abstract class PEBuilder
 14    {
 015        public PEHeaderBuilder Header { get; }
 016        public Func<IEnumerable<Blob>, BlobContentId> IdProvider { get; }
 017        public bool IsDeterministic { get; }
 18
 19        private readonly Lazy<ImmutableArray<Section>> _lazySections;
 20        private Blob _lazyChecksum;
 21
 22        protected readonly struct Section
 23        {
 24            public readonly string Name;
 25            public readonly SectionCharacteristics Characteristics;
 26
 27            public Section(string name, SectionCharacteristics characteristics)
 028            {
 029                if (name is null)
 030                {
 031                    Throw.ArgumentNull(nameof(name));
 32                }
 33
 034                Name = name;
 035                Characteristics = characteristics;
 036            }
 37        }
 38
 39        private readonly struct SerializedSection
 40        {
 41            public readonly BlobBuilder Builder;
 42
 43            public readonly string Name;
 44            public readonly SectionCharacteristics Characteristics;
 45            public readonly int RelativeVirtualAddress;
 46            public readonly int SizeOfRawData;
 47            public readonly int PointerToRawData;
 48
 49            public SerializedSection(BlobBuilder builder, string name, SectionCharacteristics characteristics, int relat
 050            {
 051                Name = name;
 052                Characteristics = characteristics;
 053                Builder = builder;
 054                RelativeVirtualAddress = relativeVirtualAddress;
 055                SizeOfRawData = sizeOfRawData;
 056                PointerToRawData = pointerToRawData;
 057            }
 58
 059            public int VirtualSize => Builder.Count;
 60        }
 61
 062        protected PEBuilder(PEHeaderBuilder header, Func<IEnumerable<Blob>, BlobContentId>? deterministicIdProvider)
 063        {
 064            if (header is null)
 065            {
 066                Throw.ArgumentNull(nameof(header));
 67            }
 68
 069            IdProvider = deterministicIdProvider ?? BlobContentId.GetTimeBasedProvider();
 070            IsDeterministic = deterministicIdProvider != null;
 071            Header = header;
 072            _lazySections = new Lazy<ImmutableArray<Section>>(CreateSections);
 073        }
 74
 75        protected ImmutableArray<Section> GetSections()
 076        {
 077            var sections = _lazySections.Value;
 078            if (sections.IsDefault)
 079            {
 080                throw new InvalidOperationException(SR.Format(SR.MustNotReturnNull, nameof(CreateSections)));
 81            }
 82
 083            return sections;
 084        }
 85
 86        protected abstract ImmutableArray<Section> CreateSections();
 87
 88        protected abstract BlobBuilder SerializeSection(string name, SectionLocation location);
 89
 90        protected internal abstract PEDirectoriesBuilder GetDirectories();
 91
 92        public BlobContentId Serialize(BlobBuilder builder)
 093        {
 94            // Define and serialize sections in two steps.
 95            // We need to know about all sections before serializing them.
 096            var serializedSections = SerializeSections();
 97
 98            // The positions and sizes of directories are calculated during section serialization.
 099            var directories = GetDirectories();
 100
 101            Blob stampFixup;
 0102            WritePESignature(builder);
 0103            WriteCoffHeader(builder, serializedSections, out stampFixup);
 0104            WritePEHeader(builder, directories, serializedSections);
 0105            WriteSectionHeaders(builder, serializedSections);
 0106            builder.Align(Header.FileAlignment);
 107
 0108            foreach (var section in serializedSections)
 0109            {
 0110                builder.LinkSuffix(section.Builder);
 0111                builder.Align(Header.FileAlignment);
 0112            }
 113
 0114            var contentId = IdProvider(builder.GetBlobs());
 115
 116            // patch timestamp in COFF header:
 0117            var stampWriter = new BlobWriter(stampFixup);
 0118            stampWriter.WriteUInt32(contentId.Stamp);
 0119            Debug.Assert(stampWriter.RemainingBytes == 0);
 120
 0121            return contentId;
 0122        }
 123
 124        private ImmutableArray<SerializedSection> SerializeSections()
 0125        {
 0126            var sections = GetSections();
 0127            var result = ImmutableArray.CreateBuilder<SerializedSection>(sections.Length);
 0128            int sizeOfPeHeaders = Header.ComputeSizeOfPEHeaders(sections.Length);
 129
 0130            var nextRva = BitArithmetic.Align(sizeOfPeHeaders, Header.SectionAlignment);
 0131            var nextPointer = BitArithmetic.Align(sizeOfPeHeaders, Header.FileAlignment);
 132
 0133            foreach (var section in sections)
 0134            {
 0135                var builder = SerializeSection(section.Name, new SectionLocation(nextRva, nextPointer));
 136
 0137                var serialized = new SerializedSection(
 0138                    builder,
 0139                    section.Name,
 0140                    section.Characteristics,
 0141                    relativeVirtualAddress: nextRva,
 0142                    sizeOfRawData: BitArithmetic.Align(builder.Count, Header.FileAlignment),
 0143                    pointerToRawData: nextPointer);
 144
 0145                result.Add(serialized);
 146
 0147                nextRva = BitArithmetic.Align(serialized.RelativeVirtualAddress + serialized.VirtualSize, Header.Section
 0148                nextPointer = serialized.PointerToRawData + serialized.SizeOfRawData;
 0149            }
 150
 0151            return result.MoveToImmutable();
 0152        }
 153
 154        private static void WritePESignature(BlobBuilder builder)
 0155        {
 156            // MS-DOS stub (128 bytes)
 0157            builder.WriteBytes(DosHeader);
 158
 159            // PE Signature "PE\0\0"
 0160            builder.WriteUInt32(PEHeaders.PESignature);
 0161        }
 162
 163        internal static ReadOnlySpan<byte> DosHeader =>
 0164        [
 0165            0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
 0166            0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
 0167            0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0168            0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0169            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0170            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0171            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0172            0x00, 0x00, 0x00, 0x00,
 0173
 0174            0x80, 0x00, 0x00, 0x00, // NT Header offset (0x80 == DosHeader.Length)
 0175
 0176            0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,
 0177            0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
 0178            0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
 0179            0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
 0180            0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,
 0181            0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
 0182            0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,
 0183            0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 0184        ];
 185
 186        private void WriteCoffHeader(BlobBuilder builder, ImmutableArray<SerializedSection> sections, out Blob stampFixu
 0187        {
 188            // Machine
 0189            builder.WriteUInt16((ushort)(Header.Machine == 0 ? Machine.I386 : Header.Machine));
 190
 191            // NumberOfSections
 0192            builder.WriteUInt16((ushort)sections.Length);
 193
 194            // TimeDateStamp:
 0195            stampFixup = builder.ReserveBytes(sizeof(uint));
 196
 197            // PointerToSymbolTable (TODO: not supported):
 198            // The file pointer to the COFF symbol table, or zero if no COFF symbol table is present.
 199            // This value should be zero for a PE image.
 0200            builder.WriteUInt32(0);
 201
 202            // NumberOfSymbols (TODO: not supported):
 203            // The number of entries in the symbol table. This data can be used to locate the string table,
 204            // which immediately follows the symbol table. This value should be zero for a PE image.
 0205            builder.WriteUInt32(0);
 206
 207            // SizeOfOptionalHeader:
 208            // The size of the optional header, which is required for executable files but not for object files.
 209            // This value should be zero for an object file (TODO).
 0210            builder.WriteUInt16((ushort)PEHeader.Size(Header.Is32Bit));
 211
 212            // Characteristics
 0213            builder.WriteUInt16((ushort)Header.ImageCharacteristics);
 0214        }
 215
 216        private void WritePEHeader(BlobBuilder builder, PEDirectoriesBuilder directories, ImmutableArray<SerializedSecti
 0217        {
 0218            builder.WriteUInt16((ushort)(Header.Is32Bit ? PEMagic.PE32 : PEMagic.PE32Plus));
 0219            builder.WriteByte(Header.MajorLinkerVersion);
 0220            builder.WriteByte(Header.MinorLinkerVersion);
 221
 222            // SizeOfCode:
 0223            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsCode));
 224
 225            // SizeOfInitializedData:
 0226            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsInitializedData));
 227
 228            // SizeOfUninitializedData:
 0229            builder.WriteUInt32((uint)SumRawDataSizes(sections, SectionCharacteristics.ContainsUninitializedData));
 230
 231            // AddressOfEntryPoint:
 0232            builder.WriteUInt32((uint)directories.AddressOfEntryPoint);
 233
 234            // BaseOfCode:
 0235            int codeSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsCode);
 0236            builder.WriteUInt32((uint)(codeSectionIndex != -1 ? sections[codeSectionIndex].RelativeVirtualAddress : 0));
 237
 0238            if (Header.Is32Bit)
 0239            {
 240                // BaseOfData:
 0241                int dataSectionIndex = IndexOfSection(sections, SectionCharacteristics.ContainsInitializedData);
 0242                builder.WriteUInt32((uint)(dataSectionIndex != -1 ? sections[dataSectionIndex].RelativeVirtualAddress : 
 243
 0244                builder.WriteUInt32((uint)Header.ImageBase);
 0245            }
 246            else
 0247            {
 0248                builder.WriteUInt64(Header.ImageBase);
 0249            }
 250
 251            // NT additional fields:
 0252            builder.WriteUInt32((uint)Header.SectionAlignment);
 0253            builder.WriteUInt32((uint)Header.FileAlignment);
 0254            builder.WriteUInt16(Header.MajorOperatingSystemVersion);
 0255            builder.WriteUInt16(Header.MinorOperatingSystemVersion);
 0256            builder.WriteUInt16(Header.MajorImageVersion);
 0257            builder.WriteUInt16(Header.MinorImageVersion);
 0258            builder.WriteUInt16(Header.MajorSubsystemVersion);
 0259            builder.WriteUInt16(Header.MinorSubsystemVersion);
 260
 261            // Win32VersionValue (reserved, should be 0)
 0262            builder.WriteUInt32(0);
 263
 264            // SizeOfImage:
 0265            var lastSection = sections[sections.Length - 1];
 0266            builder.WriteUInt32((uint)BitArithmetic.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, 
 267
 268            // SizeOfHeaders:
 0269            builder.WriteUInt32((uint)BitArithmetic.Align(Header.ComputeSizeOfPEHeaders(sections.Length), Header.FileAli
 270
 271            // Checksum:
 272            // Shall be zero for strong name signing, already zeroed by ReserveBytes.
 0273            _lazyChecksum = builder.ReserveBytes(sizeof(uint));
 274
 0275            builder.WriteUInt16((ushort)Header.Subsystem);
 0276            builder.WriteUInt16((ushort)Header.DllCharacteristics);
 277
 0278            if (Header.Is32Bit)
 0279            {
 0280                builder.WriteUInt32((uint)Header.SizeOfStackReserve);
 0281                builder.WriteUInt32((uint)Header.SizeOfStackCommit);
 0282                builder.WriteUInt32((uint)Header.SizeOfHeapReserve);
 0283                builder.WriteUInt32((uint)Header.SizeOfHeapCommit);
 0284            }
 285            else
 0286            {
 0287                builder.WriteUInt64(Header.SizeOfStackReserve);
 0288                builder.WriteUInt64(Header.SizeOfStackCommit);
 0289                builder.WriteUInt64(Header.SizeOfHeapReserve);
 0290                builder.WriteUInt64(Header.SizeOfHeapCommit);
 0291            }
 292
 293            // LoaderFlags
 0294            builder.WriteUInt32(0);
 295
 296            // The number of data-directory entries in the remainder of the header.
 0297            builder.WriteUInt32(16);
 298
 299            // directory entries:
 0300            builder.WriteUInt32((uint)directories.ExportTable.RelativeVirtualAddress);
 0301            builder.WriteUInt32((uint)directories.ExportTable.Size);
 0302            builder.WriteUInt32((uint)directories.ImportTable.RelativeVirtualAddress);
 0303            builder.WriteUInt32((uint)directories.ImportTable.Size);
 0304            builder.WriteUInt32((uint)directories.ResourceTable.RelativeVirtualAddress);
 0305            builder.WriteUInt32((uint)directories.ResourceTable.Size);
 0306            builder.WriteUInt32((uint)directories.ExceptionTable.RelativeVirtualAddress);
 0307            builder.WriteUInt32((uint)directories.ExceptionTable.Size);
 308
 309            // Authenticode CertificateTable directory. Shall be zero before the PE is signed.
 0310            builder.WriteUInt32(0);
 0311            builder.WriteUInt32(0);
 312
 0313            builder.WriteUInt32((uint)directories.BaseRelocationTable.RelativeVirtualAddress);
 0314            builder.WriteUInt32((uint)directories.BaseRelocationTable.Size);
 0315            builder.WriteUInt32((uint)directories.DebugTable.RelativeVirtualAddress);
 0316            builder.WriteUInt32((uint)directories.DebugTable.Size);
 0317            builder.WriteUInt32((uint)directories.CopyrightTable.RelativeVirtualAddress);
 0318            builder.WriteUInt32((uint)directories.CopyrightTable.Size);
 0319            builder.WriteUInt32((uint)directories.GlobalPointerTable.RelativeVirtualAddress);
 0320            builder.WriteUInt32((uint)directories.GlobalPointerTable.Size);
 0321            builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.RelativeVirtualAddress);
 0322            builder.WriteUInt32((uint)directories.ThreadLocalStorageTable.Size);
 0323            builder.WriteUInt32((uint)directories.LoadConfigTable.RelativeVirtualAddress);
 0324            builder.WriteUInt32((uint)directories.LoadConfigTable.Size);
 0325            builder.WriteUInt32((uint)directories.BoundImportTable.RelativeVirtualAddress);
 0326            builder.WriteUInt32((uint)directories.BoundImportTable.Size);
 0327            builder.WriteUInt32((uint)directories.ImportAddressTable.RelativeVirtualAddress);
 0328            builder.WriteUInt32((uint)directories.ImportAddressTable.Size);
 0329            builder.WriteUInt32((uint)directories.DelayImportTable.RelativeVirtualAddress);
 0330            builder.WriteUInt32((uint)directories.DelayImportTable.Size);
 0331            builder.WriteUInt32((uint)directories.CorHeaderTable.RelativeVirtualAddress);
 0332            builder.WriteUInt32((uint)directories.CorHeaderTable.Size);
 333
 334            // Reserved, should be 0
 0335            builder.WriteUInt64(0);
 0336        }
 337
 338        private static void WriteSectionHeaders(BlobBuilder builder, ImmutableArray<SerializedSection> serializedSection
 0339        {
 0340            foreach (var serializedSection in serializedSections)
 0341            {
 0342                WriteSectionHeader(builder, serializedSection);
 0343            }
 0344        }
 345
 346        private static void WriteSectionHeader(BlobBuilder builder, SerializedSection serializedSection)
 0347        {
 0348            if (serializedSection.VirtualSize == 0)
 0349            {
 0350                return;
 351            }
 352
 0353            for (int j = 0, m = serializedSection.Name.Length; j < 8; j++)
 0354            {
 0355                if (j < m)
 0356                {
 0357                    builder.WriteByte((byte)serializedSection.Name[j]);
 0358                }
 359                else
 0360                {
 0361                    builder.WriteByte(0);
 0362                }
 0363            }
 364
 0365            builder.WriteUInt32((uint)serializedSection.VirtualSize);
 0366            builder.WriteUInt32((uint)serializedSection.RelativeVirtualAddress);
 0367            builder.WriteUInt32((uint)serializedSection.SizeOfRawData);
 0368            builder.WriteUInt32((uint)serializedSection.PointerToRawData);
 369
 370            // PointerToRelocations (TODO: not supported):
 0371            builder.WriteUInt32(0);
 372
 373            // PointerToLinenumbers (TODO: not supported):
 0374            builder.WriteUInt32(0);
 375
 376            // NumberOfRelocations (TODO: not supported):
 0377            builder.WriteUInt16(0);
 378
 379            // NumberOfLinenumbers (TODO: not supported):
 0380            builder.WriteUInt16(0);
 381
 0382            builder.WriteUInt32((uint)serializedSection.Characteristics);
 0383        }
 384
 385        private static int IndexOfSection(ImmutableArray<SerializedSection> sections, SectionCharacteristics characteris
 0386        {
 0387            for (int i = 0; i < sections.Length; i++)
 0388            {
 0389                if ((sections[i].Characteristics & characteristics) == characteristics)
 0390                {
 0391                    return i;
 392                }
 0393            }
 394
 0395            return -1;
 0396        }
 397
 398        private static int SumRawDataSizes(ImmutableArray<SerializedSection> sections, SectionCharacteristics characteri
 0399        {
 0400            int result = 0;
 0401            for (int i = 0; i < sections.Length; i++)
 0402            {
 0403                if ((sections[i].Characteristics & characteristics) == characteristics)
 0404                {
 0405                    result += sections[i].SizeOfRawData;
 0406                }
 0407            }
 408
 0409            return result;
 0410        }
 411
 412        // internal for testing
 413        internal static IEnumerable<Blob> GetContentToSign(BlobBuilder peImage, int peHeadersSize, int peHeaderAlignment
 0414        {
 415            // Signed content includes
 416            // - PE header without its alignment padding
 417            // - all sections including their alignment padding and excluding strong name signature blob
 418
 419            // PE specification:
 420            //   To calculate the PE image hash, Authenticode orders the sections that are specified in the section tabl
 421            //   by address range, then hashes the resulting sequence of bytes, passing over the exclusion ranges.
 422            //
 423            // Note that sections are by construction ordered by their address, so there is no need to reorder.
 424
 0425            int remainingHeaderToSign = peHeadersSize;
 0426            int remainingHeader = BitArithmetic.Align(peHeadersSize, peHeaderAlignment);
 0427            foreach (var blob in peImage.GetBlobs())
 0428            {
 0429                int blobStart = blob.Start;
 0430                int blobLength = blob.Length;
 0431                while (blobLength > 0)
 0432                {
 0433                    if (remainingHeader > 0)
 0434                    {
 435                        int length;
 436
 0437                        if (remainingHeaderToSign > 0)
 0438                        {
 0439                            length = Math.Min(remainingHeaderToSign, blobLength);
 0440                            yield return new Blob(blob.Buffer, blobStart, length);
 0441                            remainingHeaderToSign -= length;
 0442                        }
 443                        else
 0444                        {
 0445                            length = Math.Min(remainingHeader, blobLength);
 0446                        }
 447
 0448                        remainingHeader -= length;
 0449                        blobStart += length;
 0450                        blobLength -= length;
 0451                    }
 0452                    else if (blob.Buffer == strongNameSignatureFixup.Buffer)
 0453                    {
 0454                        yield return GetPrefixBlob(new Blob(blob.Buffer, blobStart, blobLength), strongNameSignatureFixu
 0455                        yield return GetSuffixBlob(new Blob(blob.Buffer, blobStart, blobLength), strongNameSignatureFixu
 0456                        break;
 457                    }
 458                    else
 0459                    {
 0460                        yield return new Blob(blob.Buffer, blobStart, blobLength);
 0461                        break;
 462                    }
 0463                }
 0464            }
 0465        }
 466
 467        // internal for testing
 0468        internal static Blob GetPrefixBlob(Blob container, Blob blob) => new Blob(container.Buffer, container.Start, blo
 0469        internal static Blob GetSuffixBlob(Blob container, Blob blob) => new Blob(container.Buffer, blob.Start + blob.Le
 470
 471        internal void Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func<IEnumerable<Blob>, byte[]> signature
 0472        {
 0473            Debug.Assert(peImage != null);
 0474            Debug.Assert(signatureProvider != null);
 475
 0476            int peHeadersSize = Header.ComputeSizeOfPEHeaders(GetSections().Length);
 0477            byte[] signature = signatureProvider(GetContentToSign(peImage, peHeadersSize, Header.FileAlignment, strongNa
 478
 479            // signature may be shorter (the rest of the reserved space is padding):
 0480            if (signature == null || signature.Length > strongNameSignatureFixup.Length)
 0481            {
 0482                throw new InvalidOperationException(SR.SignatureProviderReturnedInvalidSignature);
 483            }
 484
 0485            var writer = new BlobWriter(strongNameSignatureFixup);
 0486            writer.WriteBytes(signature);
 487
 488            // Calculate the checksum after the strong name signature has been written.
 0489            uint checksum = CalculateChecksum(peImage, _lazyChecksum);
 0490            new BlobWriter(_lazyChecksum).WriteUInt32(checksum);
 0491        }
 492
 493        // internal for testing
 494        internal static uint CalculateChecksum(BlobBuilder peImage, Blob checksumFixup)
 0495        {
 0496            uint checksum = 0;
 0497            int pendingByte = -1;
 498
 0499            foreach (Blob blob in peImage.GetBlobs())
 0500            {
 0501                if (blob.Buffer == checksumFixup.Buffer)
 0502                {
 503                    // The checksum field itself is excluded, so checksum the content before and
 504                    // after the fixup as two separate segments.
 0505                    AddToChecksum(GetPrefixBlob(blob, checksumFixup).GetBytes(), ref checksum, ref pendingByte);
 0506                    AddToChecksum(GetSuffixBlob(blob, checksumFixup).GetBytes(), ref checksum, ref pendingByte);
 0507                }
 508                else
 0509                {
 0510                    AddToChecksum(blob.GetBytes(), ref checksum, ref pendingByte);
 0511                }
 0512            }
 513
 0514            if (pendingByte >= 0)
 0515            {
 0516                checksum = AggregateChecksum(checksum, (ushort)pendingByte);
 0517            }
 518
 0519            return checksum + (uint)peImage.Count;
 0520        }
 521
 522        private static void AddToChecksum(ReadOnlySpan<byte> segment, ref uint checksum, ref int pendingByte)
 0523        {
 0524            if (segment.IsEmpty)
 0525            {
 0526                return;
 527            }
 528
 0529            if (pendingByte >= 0)
 0530            {
 531                // little-endian encoding:
 0532                checksum = AggregateChecksum(checksum, (ushort)(segment[0] << 8 | pendingByte));
 0533                segment = segment.Slice(1);
 0534            }
 535
 0536            while (segment.Length >= sizeof(ushort))
 0537            {
 538                // little-endian encoding:
 0539                checksum = AggregateChecksum(checksum, BinaryPrimitives.ReadUInt16LittleEndian(segment));
 0540                segment = segment.Slice(sizeof(ushort));
 0541            }
 542
 543            // Carry a trailing odd byte over to the next segment.
 0544            pendingByte = segment.IsEmpty ? -1 : segment[0];
 0545        }
 546
 547        private static uint AggregateChecksum(uint checksum, ushort value)
 0548        {
 0549            uint sum = checksum + value;
 0550            return (sum >> 16) + unchecked((ushort)sum);
 0551        }
 552    }
 553}
 554

Methods/Properties

Header()
IdProvider()
IsDeterministic()
.ctor(System.String,System.Reflection.PortableExecutable.SectionCharacteristics)
.ctor(System.Reflection.Metadata.BlobBuilder,System.String,System.Reflection.PortableExecutable.SectionCharacteristics,System.Int32,System.Int32,System.Int32)
VirtualSize()
.ctor(System.Reflection.PortableExecutable.PEHeaderBuilder,System.Func`2<System.Collections.Generic.IEnumerable`1<System.Reflection.Metadata.Blob>,System.Reflection.Metadata.BlobContentId>)
GetSections()
Serialize(System.Reflection.Metadata.BlobBuilder)
SerializeSections()
WritePESignature(System.Reflection.Metadata.BlobBuilder)
DosHeader()
WriteCoffHeader(System.Reflection.Metadata.BlobBuilder,System.Collections.Immutable.ImmutableArray`1<System.Reflection.PortableExecutable.PEBuilder/SerializedSection>,System.Reflection.Metadata.Blob&)
WritePEHeader(System.Reflection.Metadata.BlobBuilder,System.Reflection.PortableExecutable.PEDirectoriesBuilder,System.Collections.Immutable.ImmutableArray`1<System.Reflection.PortableExecutable.PEBuilder/SerializedSection>)
WriteSectionHeaders(System.Reflection.Metadata.BlobBuilder,System.Collections.Immutable.ImmutableArray`1<System.Reflection.PortableExecutable.PEBuilder/SerializedSection>)
WriteSectionHeader(System.Reflection.Metadata.BlobBuilder,System.Reflection.PortableExecutable.PEBuilder/SerializedSection)
IndexOfSection(System.Collections.Immutable.ImmutableArray`1<System.Reflection.PortableExecutable.PEBuilder/SerializedSection>,System.Reflection.PortableExecutable.SectionCharacteristics)
SumRawDataSizes(System.Collections.Immutable.ImmutableArray`1<System.Reflection.PortableExecutable.PEBuilder/SerializedSection>,System.Reflection.PortableExecutable.SectionCharacteristics)
GetContentToSign()
GetPrefixBlob(System.Reflection.Metadata.Blob,System.Reflection.Metadata.Blob)
GetSuffixBlob(System.Reflection.Metadata.Blob,System.Reflection.Metadata.Blob)
Sign(System.Reflection.Metadata.BlobBuilder,System.Reflection.Metadata.Blob,System.Func`2<System.Collections.Generic.IEnumerable`1<System.Reflection.Metadata.Blob>,System.Byte[]>)
CalculateChecksum(System.Reflection.Metadata.BlobBuilder,System.Reflection.Metadata.Blob)
AddToChecksum(System.ReadOnlySpan`1<System.Byte>,System.UInt32&,System.Int32&)
AggregateChecksum(System.UInt32,System.UInt16)