예제 #1
0
        public ManagedPEBuilder(
            PEHeaderBuilder header,
            MetadataRootBuilder metadataRootBuilder,
            BlobBuilder ilStream,
            BlobBuilder mappedFieldData                 = null,
            BlobBuilder managedResources                = null,
            ResourceSectionBuilder nativeResources      = null,
            DebugDirectoryBuilder debugDirectoryBuilder = null,
            int strongNameSignatureSize                 = DefaultStrongNameSignatureSize,
            MethodDefinitionHandle entryPoint           = default(MethodDefinitionHandle),
            CorFlags flags = CorFlags.ILOnly,
            Func <IEnumerable <Blob>, BlobContentId> deterministicIdProvider = null)
            : base(header, deterministicIdProvider)
        {
            if (header == null)
            {
                Throw.ArgumentNull(nameof(header));
            }

            if (metadataRootBuilder == null)
            {
                Throw.ArgumentNull(nameof(metadataRootBuilder));
            }

            if (ilStream == null)
            {
                Throw.ArgumentNull(nameof(ilStream));
            }

            if (strongNameSignatureSize < 0)
            {
                Throw.ArgumentOutOfRange(nameof(strongNameSignatureSize));
            }

            _metadataRootBuilder      = metadataRootBuilder;
            _ilStream                 = ilStream;
            _mappedFieldDataOpt       = mappedFieldData;
            _managedResourcesOpt      = managedResources;
            _nativeResourcesOpt       = nativeResources;
            _strongNameSignatureSize  = strongNameSignatureSize;
            _entryPointOpt            = entryPoint;
            _debugDirectoryBuilderOpt = debugDirectoryBuilder ?? CreateDefaultDebugDirectoryBuilder();
            _corFlags                 = flags;

            _peDirectoriesBuilder = new PEDirectoriesBuilder();
        }
예제 #2
0
        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);
        }