]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/pe-binary.h
build(deps): bump pkg/debian from `f550017` to `50b20e2`
[thirdparty/systemd.git] / src / shared / pe-binary.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include <sys/types.h>
5
6 #include "sparse-endian.h"
7
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 */
10
11 typedef struct _packed_ _IMAGE_DOS_HEADER {
12 le16_t e_magic;
13 le16_t e_cblp;
14 le16_t e_cp;
15 le16_t e_crlc;
16 le16_t e_cparhdr;
17 le16_t e_minalloc;
18 le16_t e_maxalloc;
19 le16_t e_ss;
20 le16_t e_sp;
21 le16_t e_csum;
22 le16_t e_ip;
23 le16_t e_cs;
24 le16_t e_lfarlc;
25 le16_t e_ovno;
26 le16_t e_res[4];
27 le16_t e_oemid;
28 le16_t e_oeminfo;
29 le16_t e_res2[10];
30 le32_t e_lfanew;
31 } IMAGE_DOS_HEADER;
32
33 typedef struct _packed_ _IMAGE_FILE_HEADER {
34 le16_t Machine;
35 le16_t NumberOfSections;
36 le32_t TimeDateStamp;
37 le32_t PointerToSymbolTable;
38 le32_t NumberOfSymbols;
39 le16_t SizeOfOptionalHeader;
40 le16_t Characteristics;
41 } IMAGE_FILE_HEADER;
42
43 typedef struct _packed_ _IMAGE_DATA_DIRECTORY {
44 le32_t VirtualAddress;
45 le32_t Size;
46 } IMAGE_DATA_DIRECTORY;
47
48 typedef struct _packed_ _IMAGE_OPTIONAL_HEADER {
49 /* Standard fields */
50 le16_t Magic;
51 uint8_t MajorLinkerVersion;
52 uint8_t MinorLinkerVersion;
53 le32_t SizeOfCode;
54 le32_t SizeOfInitializedData;
55 le32_t SizeOfUninitializedData;
56 le32_t AddressOfEntryPoint;
57 le32_t BaseOfCode;
58
59 /* Here the PE32 and PE32+ headers differ: PE32+ has one 64bit field, PE32+ has two 32bit fields */
60 union {
61 struct {
62 le32_t BaseOfData;
63 le32_t pe32_ImageBase;
64 };
65 le64_t pe32plus_ImageBase;
66 };
67
68 /* Additional fields */
69 le32_t SectionAlignment;
70 le32_t FileAlignment;
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;
78 le32_t SizeOfImage;
79 le32_t SizeOfHeaders;
80 le32_t CheckSum;
81 le16_t Subsystem;
82 le16_t DllCharacteristics;
83
84 /* Here similar: on PE32+ some fields are 64bit that are 32bit on PE32. */
85 union {
86 struct {
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[];
94 };
95 struct {
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[];
103 };
104 };
105 } IMAGE_OPTIONAL_HEADER;
106
107 typedef struct _packed_ PeHeader {
108 le32_t signature;
109 IMAGE_FILE_HEADER pe;
110 IMAGE_OPTIONAL_HEADER optional;
111 } PeHeader;
112
113 typedef struct _packed_ _IMAGE_SECTION_HEADER {
114 uint8_t Name[8];
115 le32_t VirtualSize;
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;
125
126 #define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
127
128 bool pe_header_is_64bit(const PeHeader *h);
129
130 #define PE_HEADER_OPTIONAL_FIELD(h, field) \
131 (pe_header_is_64bit(h) ? (h)->optional.pe32plus_##field : (h)->optional.pe32_##field)
132
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))
135
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);
138
139 int pe_load_headers(int fd, IMAGE_DOS_HEADER **ret_dos_header, PeHeader **ret_pe_header);
140
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);
143
144 bool pe_is_uki(const PeHeader *pe_header, const IMAGE_SECTION_HEADER *sections);