1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "sparse-endian.h"
8 /* When naming things we try to stay close to the official Windows APIs as per:
9 * → https://learn.microsoft.com/en-us/windows/win32/debug/pe-format */
11 typedef struct _packed_ _IMAGE_DOS_HEADER
{
33 typedef struct _packed_ _IMAGE_FILE_HEADER
{
35 le16_t NumberOfSections
;
37 le32_t PointerToSymbolTable
;
38 le32_t NumberOfSymbols
;
39 le16_t SizeOfOptionalHeader
;
40 le16_t Characteristics
;
43 typedef struct _packed_ _IMAGE_DATA_DIRECTORY
{
44 le32_t VirtualAddress
;
46 } IMAGE_DATA_DIRECTORY
;
48 typedef struct _packed_ _IMAGE_OPTIONAL_HEADER
{
51 uint8_t MajorLinkerVersion
;
52 uint8_t MinorLinkerVersion
;
54 le32_t SizeOfInitializedData
;
55 le32_t SizeOfUninitializedData
;
56 le32_t AddressOfEntryPoint
;
59 /* Here the PE32 and PE32+ headers differ: PE32+ has one 64bit field, PE32+ has two 32bit fields */
63 le32_t pe32_ImageBase
;
65 le64_t pe32plus_ImageBase
;
68 /* Additional fields */
69 le32_t SectionAlignment
;
71 le16_t MajorOperatingSystemVersion
;
72 le16_t MinorOperatingSystemVersion
;
73 le16_t MajorImageVersion
;
74 le16_t MinorImageVersion
;
75 le16_t MajorSubsystemVersion
;
76 le16_t MinorSubsystemVersion
;
77 le32_t Win32VersionValue
;
82 le16_t DllCharacteristics
;
84 /* Here similar: on PE32+ some fields are 64bit that are 32bit on PE32. */
87 le32_t pe32_SizeOfStackReserve
;
88 le32_t pe32_SizeOfStackCommit
;
89 le32_t pe32_SizeOfHeapReserve
;
90 le32_t pe32_SizeOfHeapCommit
;
91 le32_t pe32_LoaderFlags
;
92 le32_t pe32_NumberOfRvaAndSizes
;
93 IMAGE_DATA_DIRECTORY pe32_DataDirectory
[];
96 le64_t pe32plus_SizeOfStackReserve
;
97 le64_t pe32plus_SizeOfStackCommit
;
98 le64_t pe32plus_SizeOfHeapReserve
;
99 le64_t pe32plus_SizeOfHeapCommit
;
100 le32_t pe32plus_LoaderFlags
;
101 le32_t pe32plus_NumberOfRvaAndSizes
;
102 IMAGE_DATA_DIRECTORY pe32plus_DataDirectory
[];
105 } IMAGE_OPTIONAL_HEADER
;
107 typedef struct _packed_ PeHeader
{
109 IMAGE_FILE_HEADER pe
;
110 IMAGE_OPTIONAL_HEADER optional
;
113 typedef struct _packed_ _IMAGE_SECTION_HEADER
{
116 le32_t VirtualAddress
;
117 le32_t SizeOfRawData
;
118 le32_t PointerToRawData
;
119 le32_t PointerToRelocations
;
120 le32_t PointerToLinenumbers
;
121 le16_t NumberOfRelocations
;
122 le16_t NumberOfLinenumbers
;
123 le32_t Characteristics
;
124 } IMAGE_SECTION_HEADER
;
126 #define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
128 bool pe_header_is_64bit(const PeHeader
*h
);
130 #define PE_HEADER_OPTIONAL_FIELD(h, field) \
131 (pe_header_is_64bit(h) ? (h)->optional.pe32plus_##field : (h)->optional.pe32_##field)
133 #define PE_HEADER_OPTIONAL_FIELD_OFFSET(h, field) \
134 (pe_header_is_64bit(h) ? offsetof(PeHeader, optional.pe32plus_##field) : offsetof(PeHeader, optional.pe32_##field))
136 const IMAGE_DATA_DIRECTORY
*pe_header_get_data_directory(const PeHeader
*h
, size_t i
);
137 const IMAGE_SECTION_HEADER
*pe_header_find_section(const PeHeader
*pe_header
, const IMAGE_SECTION_HEADER
*sections
, const char *name
);
139 int pe_load_headers(int fd
, IMAGE_DOS_HEADER
**ret_dos_header
, PeHeader
**ret_pe_header
);
141 int pe_load_sections(int fd
, const IMAGE_DOS_HEADER
*dos_header
, const PeHeader
*pe_header
, IMAGE_SECTION_HEADER
**ret_sections
);
142 int pe_read_section_data(int fd
, const PeHeader
*pe_header
, const IMAGE_SECTION_HEADER
*sections
, const char *name
, size_t max_size
, void **ret
, size_t *ret_size
);
144 bool pe_is_uki(const PeHeader
*pe_header
, const IMAGE_SECTION_HEADER
*sections
);