1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #ifndef __PE_HEADER_
19 #define __PE_HEADER_
20 
21 #include <endian.h>
22 #include <sys/types.h>
23 
24 //
25 // Directory Entries
26 //
27 static constexpr size_t IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
28 static constexpr size_t IMAGE_DIRECTORY_ENTRY_IMPORT = 1;
29 static constexpr size_t IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
30 static constexpr size_t IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3;
31 static constexpr size_t IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
32 static constexpr size_t IMAGE_DIRECTORY_ENTRY_BASERELOC = 5;
33 static constexpr size_t IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
34 static constexpr size_t IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7;
35 static constexpr size_t IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8;
36 static constexpr size_t IMAGE_DIRECTORY_ENTRY_TLS = 9;
37 static constexpr size_t IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10;
38 
39 static constexpr size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
40 static constexpr size_t IMAGE_SIZEOF_SHORT_NAME = 8;
41 
42 static constexpr uint32_t kPEHeader = 0x4550;
43 struct IMAGE_NT_HEADERS64;
44 
45 struct IMAGE_DOS_HEADER { // DOS .EXE header
46   u16 e_magic;            // Magic number
47   u16 e_cblp;             // Bytes on last page of file
48   u16 e_cp;               // Pages in file
49   u16 e_crlc;             // Relocations
50   u16 e_cparhdr;          // Size of header in paragraphs
51   u16 e_minalloc;         // Minimum extra paragraphs needed
52   u16 e_maxalloc;         // Maximum extra paragraphs needed
53   u16 e_ss;               // Initial (relative) SS value
54   u16 e_sp;               // Initial SP value
55   u16 e_csum;             // Checksum
56   u16 e_ip;               // Initial IP value
57   u16 e_cs;               // Initial (relative) CS value
58   u16 e_lfarlc;           // File address of relocation table
59   u16 e_ovno;             // Overlay number
60   u16 e_res[4];           // Reserved words
61   u16 e_oemid;            // OEM identifier (for e_oeminfo)
62   u16 e_oeminfo;          // OEM information; e_oemid specific
63   u16 e_res2[10];         // Reserved words
64   u32 e_lfanew;           // File address of new exe header
65 
CheckMagicIMAGE_DOS_HEADER66   constexpr bool CheckMagic() const { return LE32(e_magic) == 0x5A4D; }
GetPEHeaderIMAGE_DOS_HEADER67   IMAGE_NT_HEADERS64 *GetPEHeader() {
68     auto address = reinterpret_cast<char *>(this);
69     const auto pe_header =
70         reinterpret_cast<IMAGE_NT_HEADERS64 *>(address + e_lfanew);
71     return pe_header;
72   }
GetPEHeaderIMAGE_DOS_HEADER73   const IMAGE_NT_HEADERS64 *GetPEHeader() const {
74     auto address = reinterpret_cast<const char *>(this);
75     const auto pe_header =
76         reinterpret_cast<const IMAGE_NT_HEADERS64 *>(address + e_lfanew);
77     return pe_header;
78   }
79 } __attribute__((packed));
80 
81 enum class ArchitectureType : u16 {
82   Unknown = 0x00,
83   ALPHAAXPOld = 0x183,
84   ALPHAAXP = 0x184,
85   ALPHAAXP64Bit = 0x284,
86   AM33 = 0x1D3,
87   AMD64 = 0x8664,
88   ARM = 0x1C0,
89   ARM64 = 0xAA64,
90   ARMNT = 0x1C4,
91   CLRPureMSIL = 0xC0EE,
92   EBC = 0xEBC,
93   I386 = 0x14C,
94   I860 = 0x14D,
95   IA64 = 0x200,
96   LOONGARCH32 = 0x6232,
97   LOONGARCH64 = 0x6264,
98   M32R = 0x9041,
99   MIPS16 = 0x266,
100   MIPSFPU = 0x366,
101   MIPSFPU16 = 0x466,
102   MOTOROLA68000 = 0x268,
103   POWERPC = 0x1F0,
104   POWERPCFP = 0x1F1,
105   POWERPC64 = 0x1F2,
106   R3000 = 0x162,
107   R4000 = 0x166,
108   R10000 = 0x168,
109   RISCV32 = 0x5032,
110   RISCV64 = 0x5064,
111   RISCV128 = 0x5128,
112   SH3 = 0x1A2,
113   SH3DSP = 0x1A3,
114   SH4 = 0x1A6,
115   SH5 = 0x1A8,
116   THUMB = 0x1C2,
117   WCEMIPSV2 = 0x169
118 };
119 
120 struct IMAGE_FILE_HEADER {
121   u32 Signature;
122   ArchitectureType Machine;
123   u16 NumberOfSections;
124   u32 TimeDateStamp;
125   u32 PointerToSymbolTable;
126   u32 NumberOfSymbols;
127   u16 SizeOfOptionalHeader;
128   u16 Characteristics;
129 } __attribute__((packed));
130 
131 struct IMAGE_DATA_DIRECTORY {
132   u32 VirtualAddress;
133   u32 Size;
134 } __attribute__((packed));
135 
136 enum SubsystemType : u16 {
137   Unknown = 0x00,
138   Native = 0x01,
139   WindowsGUI = 0x02,
140   WindowsCUI = 0x03,
141   OS2CUI = 0x05,
142   POSIXCUI = 0x07,
143   Windows9xNative = 0x08,
144   WindowsCEGUI = 0x09,
145   EFIApplication = 0x0A,
146   EFIBootServiceDriver = 0x0B,
147   EFIRuntimeDriver = 0x0C,
148   EFIROM = 0x0D,
149   Xbox = 0x0E,
150   WindowsBootApplication = 0x10
151 };
152 
ToString(SubsystemType type)153 constexpr const char *ToString(SubsystemType type) {
154   switch (type) {
155   case Native:
156     return "Native";
157   case WindowsGUI:
158     return "WindowsGUI";
159   case WindowsCUI:
160     return "WindowsCUI";
161   case OS2CUI:
162     return "OS2CUI";
163   case POSIXCUI:
164     return "POSIXCUI";
165   case Windows9xNative:
166     return "Windows9xNative";
167   case WindowsCEGUI:
168     return "WindowsCEGUI";
169   case EFIApplication:
170     return "EFIApplication";
171   case EFIBootServiceDriver:
172     return "EFIBootServiceDriver";
173   case EFIRuntimeDriver:
174     return "EFIRuntimeDriver";
175   case EFIROM:
176     return "EFIROM";
177   case Xbox:
178     return "Xbox";
179   case WindowsBootApplication:
180     return "WindowsBootApplication";
181   default:
182     return "Unknown";
183   }
184 }
185 
186 struct IMAGE_OPTIONAL_HEADER64 {
187   u16 Magic;
188   u8 MajorLinkerVersion;
189   u8 MinorLinkerVersion;
190   u32 SizeOfCode;
191   u32 SizeOfInitializedData;
192   u32 SizeOfUninitializedData;
193   u32 AddressOfEntryPoint;
194   u32 BaseOfCode;
195   u64 ImageBase;
196   u32 SectionAlignment;
197   u32 FileAlignment;
198   u16 MajorOperatingSystemVersion;
199   u16 MinorOperatingSystemVersion;
200   u16 MajorImageVersion;
201   u16 MinorImageVersion;
202   u16 MajorSubsystemVersion;
203   u16 MinorSubsystemVersion;
204   u32 Win32VersionValue;
205   u32 SizeOfImage;
206   u32 SizeOfHeaders;
207   u32 CheckSum;
208   SubsystemType Subsystem;
209   u16 DllCharacteristics;
210   u64 SizeOfStackReserve;
211   u64 SizeOfStackCommit;
212   u64 SizeOfHeapReserve;
213   u64 SizeOfHeapCommit;
214   u32 LoaderFlags;
215   u32 NumberOfRvaAndSizes;
216   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
217 } __attribute__((packed));
218 
219 struct IMAGE_OPTIONAL_HEADER32 {
220   u16 Magic;
221   u8 MajorLinkerVersion;
222   u8 MinorLinkerVersion;
223   u32 SizeOfCode;
224   u32 SizeOfInitializedData;
225   u32 SizeOfUninitializedData;
226   u32 AddressOfEntryPoint;
227   u32 BaseOfCode;
228   u32 BaseOfData;
229   u32 ImageBase;
230   u32 SectionAlignment;
231   u32 FileAlignment;
232   u16 MajorOperatingSystemVersion;
233   u16 MinorOperatingSystemVersion;
234   u16 MajorImageVersion;
235   u16 MinorImageVersion;
236   u16 MajorSubsystemVersion;
237   u16 MinorSubsystemVersion;
238   u32 Win32VersionValue;
239   u32 SizeOfImage;
240   u32 SizeOfHeaders;
241   u32 CheckSum;
242   u16 Subsystem;
243   u16 DllCharacteristics;
244   u32 SizeOfStackReserve;
245   u32 SizeOfStackCommit;
246   u32 SizeOfHeapReserve;
247   u32 SizeOfHeapCommit;
248   u32 LoaderFlags;
249   u32 NumberOfRvaAndSizes;
250   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
251 } __attribute__((packed));
252 
253 struct IMAGE_SECTION_HEADER {
254   char Name[IMAGE_SIZEOF_SHORT_NAME];
255   union {
256     u32 PhysicalAddress;
257     u32 VirtualSize;
258   } Misc;
259   u32 VirtualAddress;
260   u32 SizeOfRawData;
261   u32 PointerToRawData;
262   u32 PointerToRelocations;
263   u32 PointerToLinenumbers;
264   u16 NumberOfRelocations;
265   u16 NumberOfLinenumbers;
266   u32 Characteristics;
267 } __attribute__((packed));
268 
269 struct IMAGE_NT_HEADERS64 {
270   IMAGE_FILE_HEADER FileHeader;
271   IMAGE_OPTIONAL_HEADER64 OptionalHeader;
272 } __attribute__((packed));
273 
274 struct EFI_IMAGE_BASE_RELOCATION {
275   uint32_t VirtualAddress;
276   uint32_t SizeOfBlock;
277 };
278 
279 static constexpr size_t EFI_IMAGE_REL_BASED_ABSOLUTE = 0;
280 static constexpr size_t EFI_IMAGE_REL_BASED_HIGH = 1;
281 static constexpr size_t EFI_IMAGE_REL_BASED_LOW = 2;
282 static constexpr size_t EFI_IMAGE_REL_BASED_HIGHLOW = 3;
283 static constexpr size_t EFI_IMAGE_REL_BASED_HIGHADJ = 4;
284 static constexpr size_t EFI_IMAGE_REL_BASED_MIPS_JMPADDR = 5;
285 static constexpr size_t EFI_IMAGE_REL_BASED_ARM_MOV32A = 5;
286 static constexpr size_t EFI_IMAGE_REL_BASED_ARM_MOV32T = 7;
287 static constexpr size_t EFI_IMAGE_REL_BASED_IA64_IMM64 = 9;
288 static constexpr size_t EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 = 9;
289 static constexpr size_t EFI_IMAGE_REL_BASED_DIR64 = 10;
290 
291 #endif
292