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 }