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 // See the LICENSE file in the project root for more information. 4 5 using System.Reflection.Internal; 6 7 namespace System.Reflection.PortableExecutable 8 { 9 public sealed class PEHeaderBuilder 10 { 11 // COFF: 12 public Machine Machine { get; } 13 public Characteristics ImageCharacteristics { get; } 14 15 // PE: 16 public byte MajorLinkerVersion { get; } 17 public byte MinorLinkerVersion { get; } 18 19 public ulong ImageBase { get; } 20 public int SectionAlignment { get; } 21 public int FileAlignment { get; } 22 23 public ushort MajorOperatingSystemVersion { get; } 24 public ushort MinorOperatingSystemVersion { get; } 25 26 public ushort MajorImageVersion { get; } 27 public ushort MinorImageVersion { get; } 28 29 public ushort MajorSubsystemVersion { get; } 30 public ushort MinorSubsystemVersion { get; } 31 32 public Subsystem Subsystem { get; } 33 public DllCharacteristics DllCharacteristics { get; } 34 35 public ulong SizeOfStackReserve { get; } 36 public ulong SizeOfStackCommit { get; } 37 public ulong SizeOfHeapReserve { get; } 38 public ulong SizeOfHeapCommit { get; } 39 40 /// <summary> 41 /// Creates PE header builder. 42 /// </summary> 43 /// <exception cref="ArgumentOutOfRangeException"> 44 /// <paramref name="fileAlignment"/> is not power of 2 between 512 and 64K, or 45 /// <paramref name="sectionAlignment"/> not power of 2 or it's less than <paramref name="fileAlignment"/>. 46 /// </exception> PEHeaderBuilder( Machine machine = 0, int sectionAlignment = 0x2000, int fileAlignment = 0x200, ulong imageBase = 0x00400000, byte majorLinkerVersion = 0x30, byte minorLinkerVersion = 0, ushort majorOperatingSystemVersion = 4, ushort minorOperatingSystemVersion = 0, ushort majorImageVersion = 0, ushort minorImageVersion = 0, ushort majorSubsystemVersion = 4, ushort minorSubsystemVersion = 0, Subsystem subsystem = Subsystem.WindowsCui, DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware, Characteristics imageCharacteristics = Characteristics.Dll, ulong sizeOfStackReserve = 0x00100000, ulong sizeOfStackCommit = 0x1000, ulong sizeOfHeapReserve = 0x00100000, ulong sizeOfHeapCommit = 0x1000)47 public PEHeaderBuilder( 48 Machine machine = 0, 49 int sectionAlignment = 0x2000, 50 int fileAlignment = 0x200, 51 ulong imageBase = 0x00400000, 52 byte majorLinkerVersion = 0x30, // (what is ref.emit using?) 53 byte minorLinkerVersion = 0, 54 ushort majorOperatingSystemVersion = 4, 55 ushort minorOperatingSystemVersion = 0, 56 ushort majorImageVersion = 0, 57 ushort minorImageVersion = 0, 58 ushort majorSubsystemVersion = 4, 59 ushort minorSubsystemVersion = 0, 60 Subsystem subsystem = Subsystem.WindowsCui, 61 DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible | DllCharacteristics.NoSeh | DllCharacteristics.TerminalServerAware, 62 Characteristics imageCharacteristics = Characteristics.Dll, 63 ulong sizeOfStackReserve = 0x00100000, 64 ulong sizeOfStackCommit = 0x1000, 65 ulong sizeOfHeapReserve = 0x00100000, 66 ulong sizeOfHeapCommit = 0x1000) 67 { 68 if (fileAlignment < 512 || fileAlignment > 64 * 1024 || BitArithmetic.CountBits(fileAlignment) != 1) 69 { 70 Throw.ArgumentOutOfRange(nameof(fileAlignment)); 71 } 72 73 if (sectionAlignment < fileAlignment || BitArithmetic.CountBits(sectionAlignment) != 1) 74 { 75 Throw.ArgumentOutOfRange(nameof(sectionAlignment)); 76 } 77 78 Machine = machine; 79 SectionAlignment = sectionAlignment; 80 FileAlignment = fileAlignment; 81 ImageBase = imageBase; 82 MajorLinkerVersion = majorLinkerVersion; 83 MinorLinkerVersion = minorLinkerVersion; 84 MajorOperatingSystemVersion = majorOperatingSystemVersion; 85 MinorOperatingSystemVersion = minorOperatingSystemVersion; 86 MajorImageVersion = majorImageVersion; 87 MinorImageVersion = minorImageVersion; 88 MajorSubsystemVersion = majorSubsystemVersion; 89 MinorSubsystemVersion = minorSubsystemVersion; 90 Subsystem = subsystem; 91 DllCharacteristics = dllCharacteristics; 92 ImageCharacteristics = imageCharacteristics; 93 SizeOfStackReserve = sizeOfStackReserve; 94 SizeOfStackCommit = sizeOfStackCommit; 95 SizeOfHeapReserve = sizeOfHeapReserve; 96 SizeOfHeapCommit = sizeOfHeapCommit; 97 } 98 CreateExecutableHeader()99 public static PEHeaderBuilder CreateExecutableHeader() 100 { 101 return new PEHeaderBuilder(imageCharacteristics : Characteristics.ExecutableImage); 102 } 103 CreateLibraryHeader()104 public static PEHeaderBuilder CreateLibraryHeader() 105 { 106 return new PEHeaderBuilder(imageCharacteristics: Characteristics.Dll); 107 } 108 109 internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64; 110 ComputeSizeOfPEHeaders(int sectionCount)111 internal int ComputeSizeOfPEHeaders(int sectionCount) => 112 PEBuilder.DosHeaderSize + 113 PEHeaders.PESignatureSize + 114 CoffHeader.Size + 115 PEHeader.Size(Is32Bit) + 116 SectionHeader.Size * sectionCount; 117 } 118 }