/// <summary>
        /// Updates the PE header and COR20 header fields that need updating. All sections are
        /// also updated, and the new ones are added.
        /// </summary>
        void UpdateHeaderFields(BinaryWriter writer)
        {
            long fileHeaderOffset     = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset;
            long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset;
            long sectionsOffset       = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset;
            long dataDirOffset        = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8;
            long cor20Offset          = destStreamBaseOffset + (long)module.MetaData.ImageCor20Header.StartOffset;

            uint fileAlignment    = peImage.ImageNTHeaders.OptionalHeader.FileAlignment;
            uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment;

            // Update PE file header
            var peOptions = Options.PEHeadersOptions;

            writer.BaseStream.Position = fileHeaderOffset;
            writer.Write((ushort)(peOptions.Machine ?? module.Machine));
            writer.Write((ushort)(origSections.Count + sections.Count));
            WriteUInt32(writer, peOptions.TimeDateStamp);
            writer.BaseStream.Position += 10;
            writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics()));

            // Update optional header
            var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), () => GetSectionSizeInfos());

            writer.BaseStream.Position = optionalHeaderOffset;
            bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32;

            if (is32BitOptionalHeader)
            {
                writer.BaseStream.Position += 2;
                WriteByte(writer, peOptions.MajorLinkerVersion);
                WriteByte(writer, peOptions.MinorLinkerVersion);
                writer.Write(sectionSizes.SizeOfCode);
                writer.Write(sectionSizes.SizeOfInitdData);
                writer.Write(sectionSizes.SizeOfUninitdData);
                writer.BaseStream.Position += 4;                        // EntryPoint
                writer.Write(sectionSizes.BaseOfCode);
                writer.Write(sectionSizes.BaseOfData);
                WriteUInt32(writer, peOptions.ImageBase);
                writer.BaseStream.Position += 8;                        // SectionAlignment, FileAlignment
                WriteUInt16(writer, peOptions.MajorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MinorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MajorImageVersion);
                WriteUInt16(writer, peOptions.MinorImageVersion);
                WriteUInt16(writer, peOptions.MajorSubsystemVersion);
                WriteUInt16(writer, peOptions.MinorSubsystemVersion);
                WriteUInt32(writer, peOptions.Win32VersionValue);
                writer.Write(sectionSizes.SizeOfImage);
                writer.Write(sectionSizes.SizeOfHeaders);
                checkSumOffset = writer.BaseStream.Position;
                writer.Write(0);                        // CheckSum
                WriteUInt16(writer, peOptions.Subsystem);
                WriteUInt16(writer, peOptions.DllCharacteristics);
                WriteUInt32(writer, peOptions.SizeOfStackReserve);
                WriteUInt32(writer, peOptions.SizeOfStackCommit);
                WriteUInt32(writer, peOptions.SizeOfHeapReserve);
                WriteUInt32(writer, peOptions.SizeOfHeapCommit);
                WriteUInt32(writer, peOptions.LoaderFlags);
                WriteUInt32(writer, peOptions.NumberOfRvaAndSizes);
            }
            else
            {
                writer.BaseStream.Position += 2;
                WriteByte(writer, peOptions.MajorLinkerVersion);
                WriteByte(writer, peOptions.MinorLinkerVersion);
                writer.Write(sectionSizes.SizeOfCode);
                writer.Write(sectionSizes.SizeOfInitdData);
                writer.Write(sectionSizes.SizeOfUninitdData);
                writer.BaseStream.Position += 4;                        // EntryPoint
                writer.Write(sectionSizes.BaseOfCode);
                WriteUInt64(writer, peOptions.ImageBase);
                writer.BaseStream.Position += 8;                        // SectionAlignment, FileAlignment
                WriteUInt16(writer, peOptions.MajorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MinorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MajorImageVersion);
                WriteUInt16(writer, peOptions.MinorImageVersion);
                WriteUInt16(writer, peOptions.MajorSubsystemVersion);
                WriteUInt16(writer, peOptions.MinorSubsystemVersion);
                WriteUInt32(writer, peOptions.Win32VersionValue);
                writer.Write(sectionSizes.SizeOfImage);
                writer.Write(sectionSizes.SizeOfHeaders);
                checkSumOffset = writer.BaseStream.Position;
                writer.Write(0);                        // CheckSum
                WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem());
                WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics);
                WriteUInt64(writer, peOptions.SizeOfStackReserve);
                WriteUInt64(writer, peOptions.SizeOfStackCommit);
                WriteUInt64(writer, peOptions.SizeOfHeapReserve);
                WriteUInt64(writer, peOptions.SizeOfHeapCommit);
                WriteUInt32(writer, peOptions.LoaderFlags);
                WriteUInt32(writer, peOptions.NumberOfRvaAndSizes);
            }

            // Update Win32 resources data directory, if we wrote a new one
            if (win32Resources != null)
            {
                writer.BaseStream.Position = dataDirOffset + 2 * 8;
                writer.WriteDataDirectory(win32Resources);
            }

            // Update old sections, and add new sections
            writer.BaseStream.Position = sectionsOffset;
            foreach (var section in origSections)
            {
                writer.BaseStream.Position += 0x14;
                writer.Write((uint)section.chunk.FileOffset);                   // PointerToRawData
                writer.BaseStream.Position += 0x10;
            }
            foreach (var section in sections)
            {
                section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA);
            }

            // Update .NET header
            writer.BaseStream.Position = cor20Offset + 4;
            WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion);
            WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion);
            writer.WriteDataDirectory(metaData);
            uint entryPoint;

            writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint)));
            writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint);
            writer.WriteDataDirectory(netResources);
            if (Options.StrongNameKey != null)
            {
                if (strongNameSignature != null)
                {
                    writer.WriteDataDirectory(strongNameSignature);
                }
                else if (strongNameSigOffset != null)
                {
                    // RVA is the same. Only need to update size.
                    writer.BaseStream.Position += 4;
                    writer.Write(Options.StrongNameKey.SignatureSize);
                }
            }

            UpdateVTableFixups(writer);
        }
        /// <summary>
        /// Updates the PE header and COR20 header fields that need updating. All sections are
        /// also updated, and the new ones are added.
        /// </summary>
        private void UpdateHeaderFields(BinaryWriter writer)
        {
            long fileHeaderOffset     = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset;
            long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset;
            long sectionsOffset       = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset;
            long dataDirOffset        = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8;
            long cor20Offset          = destStreamBaseOffset + (long)imageCor20Header.FileOffset;

            uint fileAlignment    = peImage.ImageNTHeaders.OptionalHeader.FileAlignment;
            uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment;

            // Update PE file header
            var peOptions = Options.PEHeadersOptions;

            writer.BaseStream.Position = fileHeaderOffset;
            writer.Write((ushort)(peOptions.Machine ?? module.Machine));
            writer.Write((ushort)(origSections.Count + sections.Count));
            WriteUInt32(writer, peOptions.TimeDateStamp);
            WriteUInt32(writer, peOptions.PointerToSymbolTable);
            WriteUInt32(writer, peOptions.NumberOfSymbols);
            writer.BaseStream.Position += 2;    // sizeof(SizeOfOptionalHeader)
            writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics()));

            // Update optional header
            var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), GetSectionSizeInfos);

            writer.BaseStream.Position = optionalHeaderOffset;
            bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32;

            if (is32BitOptionalHeader)
            {
                writer.BaseStream.Position += 2;
                WriteByte(writer, peOptions.MajorLinkerVersion);
                WriteByte(writer, peOptions.MinorLinkerVersion);
                writer.Write(sectionSizes.SizeOfCode);
                writer.Write(sectionSizes.SizeOfInitdData);
                writer.Write(sectionSizes.SizeOfUninitdData);
                writer.BaseStream.Position += 4;    // EntryPoint
                writer.Write(sectionSizes.BaseOfCode);
                writer.Write(sectionSizes.BaseOfData);
                WriteUInt32(writer, peOptions.ImageBase);
                writer.BaseStream.Position += 8;    // SectionAlignment, FileAlignment
                WriteUInt16(writer, peOptions.MajorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MinorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MajorImageVersion);
                WriteUInt16(writer, peOptions.MinorImageVersion);
                WriteUInt16(writer, peOptions.MajorSubsystemVersion);
                WriteUInt16(writer, peOptions.MinorSubsystemVersion);
                WriteUInt32(writer, peOptions.Win32VersionValue);
                writer.Write(sectionSizes.SizeOfImage);
                writer.Write(sectionSizes.SizeOfHeaders);
                checkSumOffset = writer.BaseStream.Position;
                writer.Write(0);    // CheckSum
                WriteUInt16(writer, peOptions.Subsystem);
                WriteUInt16(writer, peOptions.DllCharacteristics);
                WriteUInt32(writer, peOptions.SizeOfStackReserve);
                WriteUInt32(writer, peOptions.SizeOfStackCommit);
                WriteUInt32(writer, peOptions.SizeOfHeapReserve);
                WriteUInt32(writer, peOptions.SizeOfHeapCommit);
                WriteUInt32(writer, peOptions.LoaderFlags);
                WriteUInt32(writer, peOptions.NumberOfRvaAndSizes);
            }
            else
            {
                writer.BaseStream.Position += 2;
                WriteByte(writer, peOptions.MajorLinkerVersion);
                WriteByte(writer, peOptions.MinorLinkerVersion);
                writer.Write(sectionSizes.SizeOfCode);
                writer.Write(sectionSizes.SizeOfInitdData);
                writer.Write(sectionSizes.SizeOfUninitdData);
                writer.BaseStream.Position += 4;    // EntryPoint
                writer.Write(sectionSizes.BaseOfCode);
                WriteUInt64(writer, peOptions.ImageBase);
                writer.BaseStream.Position += 8;    // SectionAlignment, FileAlignment
                WriteUInt16(writer, peOptions.MajorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MinorOperatingSystemVersion);
                WriteUInt16(writer, peOptions.MajorImageVersion);
                WriteUInt16(writer, peOptions.MinorImageVersion);
                WriteUInt16(writer, peOptions.MajorSubsystemVersion);
                WriteUInt16(writer, peOptions.MinorSubsystemVersion);
                WriteUInt32(writer, peOptions.Win32VersionValue);
                writer.Write(sectionSizes.SizeOfImage);
                writer.Write(sectionSizes.SizeOfHeaders);
                checkSumOffset = writer.BaseStream.Position;
                writer.Write(0);    // CheckSum
                WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem());
                WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics);
                WriteUInt64(writer, peOptions.SizeOfStackReserve);
                WriteUInt64(writer, peOptions.SizeOfStackCommit);
                WriteUInt64(writer, peOptions.SizeOfHeapReserve);
                WriteUInt64(writer, peOptions.SizeOfHeapCommit);
                WriteUInt32(writer, peOptions.LoaderFlags);
                WriteUInt32(writer, peOptions.NumberOfRvaAndSizes);
            }

            // Update Win32 resources data directory, if we wrote a new one
            if (win32Resources != null)
            {
                writer.BaseStream.Position = dataDirOffset + 2 * 8;
                writer.WriteDataDirectory(win32Resources);
            }

            // Clear the security descriptor directory
            writer.BaseStream.Position = dataDirOffset + 4 * 8;
            writer.WriteDataDirectory(null);

            // Write a new debug directory
            writer.BaseStream.Position = dataDirOffset + 6 * 8;
            writer.WriteDataDirectory(debugDirectory, DebugDirectory.HEADER_SIZE);

            // Write a new Metadata data directory
            writer.BaseStream.Position = dataDirOffset + 14 * 8;
            writer.WriteDataDirectory(imageCor20Header);

            // Update old sections, and add new sections
            writer.BaseStream.Position = sectionsOffset;
            foreach (var section in origSections)
            {
                writer.BaseStream.Position += 0x14;
                writer.Write((uint)section.Chunk.FileOffset);   // PointerToRawData
                writer.BaseStream.Position += 0x10;
            }
            foreach (var section in sections)
            {
                section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA);
            }

            // Write the .NET header
            writer.BaseStream.Position = cor20Offset;
            writer.Write(0x48);     // cb
            WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion);
            WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion);
            writer.WriteDataDirectory(metaData);
            uint entryPoint;

            writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint)));
            writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint);
            writer.WriteDataDirectory(netResources);
            writer.WriteDataDirectory(strongNameSignature);
            WriteDataDirectory(writer, module.MetaData.ImageCor20Header.CodeManagerTable);
            WriteDataDirectory(writer, module.MetaData.ImageCor20Header.VTableFixups);
            WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ExportAddressTableJumps);
            WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ManagedNativeHeader);

            UpdateVTableFixups(writer);
        }