1// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2// Copyright Antony Polukhin, 2015-2024.
3//
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt
6// or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8// For more information, see http://www.boost.org
9
10#include <boost/dll/detail/elf_info.hpp>
11#include <boost/dll/detail/pe_info.hpp>
12#include <boost/dll/detail/macho_info.hpp>
13#include <boost/core/lightweight_test.hpp>
14#include <boost/predef/os.h>
15
16#if BOOST_OS_WINDOWS
17# include <windows.h>
18#elif BOOST_OS_MACOS || BOOST_OS_IOS
19# include <mach-o/loader.h>
20# include <mach-o/nlist.h>
21#elif BOOST_OS_QNX
22// QNX's copy of <elf.h> and <link.h> reside in sys folder
23# include <sys/elf.h>
24#else
25 #include <elf.h>
26#endif
27
28namespace dd = boost::dll::detail;
29
30template <class T1, class T2>
31inline std::size_t get_offset(const T1& v1, const T2& v2) {
32 const unsigned char* p1 = reinterpret_cast<const unsigned char*>(&v1);
33 const unsigned char* p2 = reinterpret_cast<const unsigned char*>(&v2);
34
35 if (p1 < p2) {
36 return static_cast<std::size_t>(p2 - p1);
37 }
38
39 return static_cast<std::size_t>(p1 - p2);
40}
41
42#define CHECK_FIELD(Field) \
43 static_assert(sizeof(v1.Field) == sizeof(v2.Field), ""); \
44 BOOST_TEST(get_offset(v1, v1.Field) == get_offset(v2, v2.Field)) \
45 /**/
46
47
48// ELF structures
49template <class T1, class T2>
50void elf_header_checks(const T1& v1, const T2& v2) {
51 static_assert(sizeof(T1) == sizeof(T2), "");
52
53 CHECK_FIELD(e_ident);
54 CHECK_FIELD(e_type);
55 CHECK_FIELD(e_machine);
56 CHECK_FIELD(e_version);
57 CHECK_FIELD(e_entry);
58 CHECK_FIELD(e_phoff);
59 CHECK_FIELD(e_shoff);
60 CHECK_FIELD(e_flags);
61 CHECK_FIELD(e_ehsize);
62 CHECK_FIELD(e_phentsize);
63 CHECK_FIELD(e_phnum);
64 CHECK_FIELD(e_shentsize);
65 CHECK_FIELD(e_shnum);
66 CHECK_FIELD(e_shstrndx);
67}
68
69template <class T1, class T2>
70void elf_sheader_checks(const T1& v1, const T2& v2) {
71 static_assert(sizeof(T1) == sizeof(T2), "");
72
73 CHECK_FIELD(sh_name);
74 CHECK_FIELD(sh_type);
75 CHECK_FIELD(sh_flags);
76 CHECK_FIELD(sh_addr);
77 CHECK_FIELD(sh_offset);
78 CHECK_FIELD(sh_size);
79 CHECK_FIELD(sh_link);
80 CHECK_FIELD(sh_info);
81 CHECK_FIELD(sh_addralign);
82 CHECK_FIELD(sh_entsize);
83}
84
85template <class T1, class T2>
86void elf_sym_header_checks(const T1& v1, const T2& v2) {
87 static_assert(sizeof(T1) == sizeof(T2), "");
88
89 CHECK_FIELD(st_name);
90 CHECK_FIELD(st_value);
91 CHECK_FIELD(st_size);
92 CHECK_FIELD(st_info);
93 CHECK_FIELD(st_other);
94 CHECK_FIELD(st_shndx);
95}
96
97
98// PE structures
99template <class T>
100void generic_header_check(const T& v1, const dd::IMAGE_DOS_HEADER_& v2) {
101 static_assert(sizeof(v1) == sizeof(v2), "");
102
103 CHECK_FIELD(e_magic);
104 CHECK_FIELD(e_cblp);
105 CHECK_FIELD(e_cp);
106 CHECK_FIELD(e_crlc);
107 CHECK_FIELD(e_cparhdr);
108 CHECK_FIELD(e_minalloc);
109 CHECK_FIELD(e_maxalloc);
110 CHECK_FIELD(e_ss);
111 CHECK_FIELD(e_sp);
112 CHECK_FIELD(e_csum);
113 CHECK_FIELD(e_ip);
114 CHECK_FIELD(e_cs);
115 CHECK_FIELD(e_lfarlc);
116 CHECK_FIELD(e_ovno);
117 CHECK_FIELD(e_res);
118 CHECK_FIELD(e_oemid);
119 CHECK_FIELD(e_oeminfo);
120 CHECK_FIELD(e_res2);
121 CHECK_FIELD(e_lfanew);
122}
123
124template <class T>
125void generic_header_check(const T& v1, const dd::IMAGE_FILE_HEADER_& v2) {
126 static_assert(sizeof(v1) == sizeof(v2), "");
127
128 CHECK_FIELD(Machine);
129 CHECK_FIELD(NumberOfSections);
130 CHECK_FIELD(TimeDateStamp);
131 CHECK_FIELD(PointerToSymbolTable);
132 CHECK_FIELD(NumberOfSymbols);
133 CHECK_FIELD(SizeOfOptionalHeader);
134 CHECK_FIELD(Characteristics);
135}
136
137template <class T>
138void generic_header_check(const T& v1, const dd::IMAGE_DATA_DIRECTORY_& v2) {
139 static_assert(sizeof(v1) == sizeof(v2), "");
140
141 CHECK_FIELD(VirtualAddress);
142 CHECK_FIELD(Size);
143}
144
145template <class T>
146void generic_header_check(const T& v1, const dd::IMAGE_EXPORT_DIRECTORY_& v2) {
147 static_assert(sizeof(v1) == sizeof(v2), "");
148
149 CHECK_FIELD(Characteristics);
150 CHECK_FIELD(TimeDateStamp);
151 CHECK_FIELD(MajorVersion);
152 CHECK_FIELD(MinorVersion);
153 CHECK_FIELD(Name);
154 CHECK_FIELD(Base);
155 CHECK_FIELD(NumberOfFunctions);
156 CHECK_FIELD(NumberOfNames);
157 CHECK_FIELD(AddressOfFunctions);
158 CHECK_FIELD(AddressOfNames);
159 CHECK_FIELD(AddressOfNameOrdinals);
160}
161
162
163template <class T>
164void generic_header_check(const T& v1, const dd::IMAGE_SECTION_HEADER_& v2) {
165 static_assert(sizeof(v1) == sizeof(v2), "");
166
167 CHECK_FIELD(Name);
168 CHECK_FIELD(VirtualAddress);
169 CHECK_FIELD(SizeOfRawData);
170 CHECK_FIELD(PointerToRawData);
171 CHECK_FIELD(PointerToRelocations);
172 CHECK_FIELD(PointerToLinenumbers);
173 CHECK_FIELD(NumberOfRelocations);
174 CHECK_FIELD(NumberOfLinenumbers);
175 CHECK_FIELD(Characteristics);
176}
177
178template <class T, class AddrT>
179void generic_header_check(const T& v1, const dd::IMAGE_OPTIONAL_HEADER_template<AddrT>& v2) {
180 static_assert(sizeof(v1) == sizeof(v2), "");
181
182 CHECK_FIELD(Magic);
183 CHECK_FIELD(MajorLinkerVersion);
184 CHECK_FIELD(MinorLinkerVersion);
185 CHECK_FIELD(SizeOfCode);
186 CHECK_FIELD(SizeOfInitializedData);
187 CHECK_FIELD(SizeOfUninitializedData);
188 CHECK_FIELD(AddressOfEntryPoint);
189 CHECK_FIELD(ImageBase);
190 CHECK_FIELD(SectionAlignment);
191 CHECK_FIELD(FileAlignment);
192 CHECK_FIELD(MajorOperatingSystemVersion);
193 CHECK_FIELD(MinorOperatingSystemVersion);
194 CHECK_FIELD(MajorImageVersion);
195 CHECK_FIELD(MinorImageVersion);
196 CHECK_FIELD(MajorSubsystemVersion);
197 CHECK_FIELD(MinorSubsystemVersion);
198 CHECK_FIELD(Win32VersionValue);
199 CHECK_FIELD(SizeOfImage);
200 CHECK_FIELD(SizeOfHeaders);
201 CHECK_FIELD(CheckSum);
202 CHECK_FIELD(Subsystem);
203 CHECK_FIELD(DllCharacteristics);
204 CHECK_FIELD(SizeOfStackReserve);
205 CHECK_FIELD(SizeOfStackCommit);
206 CHECK_FIELD(SizeOfHeapReserve);
207 CHECK_FIELD(SizeOfHeapCommit);
208 CHECK_FIELD(LoaderFlags);
209 CHECK_FIELD(NumberOfRvaAndSizes);
210 CHECK_FIELD(DataDirectory);
211}
212
213template <class T, class AddrT>
214void generic_header_check(const T& v1, const dd::IMAGE_NT_HEADERS_template<AddrT>& v2) {
215 static_assert(sizeof(v1) == sizeof(v2), "");
216
217 CHECK_FIELD(Signature);
218 CHECK_FIELD(FileHeader);
219 CHECK_FIELD(OptionalHeader);
220}
221template <class T, class AddrT>
222void generic_header_check(const T& v1, const dd::mach_header_template<AddrT>& v2) {
223 static_assert(sizeof(v1) == sizeof(v2), "");
224
225 CHECK_FIELD(magic);
226 CHECK_FIELD(cputype);
227 CHECK_FIELD(cpusubtype);
228 CHECK_FIELD(filetype);
229 CHECK_FIELD(ncmds);
230 CHECK_FIELD(sizeofcmds);
231 //CHECK_FIELD(flags);
232}
233
234template <class T, class AddrT>
235void generic_header_check(const T& v1, const dd::segment_command_template<AddrT>& v2) {
236 static_assert(sizeof(v1) == sizeof(v2), "");
237
238 CHECK_FIELD(cmd);
239 CHECK_FIELD(cmdsize);
240 CHECK_FIELD(segname);
241 CHECK_FIELD(vmaddr);
242 CHECK_FIELD(vmsize);
243 CHECK_FIELD(fileoff);
244 CHECK_FIELD(filesize);
245 CHECK_FIELD(maxprot);
246 CHECK_FIELD(initprot);
247 CHECK_FIELD(nsects);
248 CHECK_FIELD(flags);
249}
250
251template <class T, class AddrT>
252void generic_header_check(const T& v1, const dd::section_template<AddrT>& v2) {
253 static_assert(sizeof(v1) == sizeof(v2), "");
254
255 CHECK_FIELD(sectname);
256 CHECK_FIELD(segname);
257 CHECK_FIELD(addr);
258 CHECK_FIELD(size);
259 CHECK_FIELD(offset);
260 CHECK_FIELD(align);
261 CHECK_FIELD(reloff);
262 CHECK_FIELD(nreloc);
263 CHECK_FIELD(flags);
264 //CHECK_FIELD(reserved vs reserveed1&reserved2);
265}
266
267template <class T>
268void generic_header_check(const T& v1, const dd::symtab_command_& v2) {
269 static_assert(sizeof(v1) == sizeof(v2), "");
270
271 CHECK_FIELD(cmd);
272 CHECK_FIELD(cmdsize);
273 CHECK_FIELD(symoff);
274 CHECK_FIELD(nsyms);
275 CHECK_FIELD(stroff);
276 CHECK_FIELD(strsize);
277}
278
279template <class T, class AddrT>
280void generic_header_check(const T& v1, const dd::nlist_template<AddrT>& v2) {
281 static_assert(sizeof(v1) == sizeof(v2), "");
282
283 //CHECK_FIELD(n_strx);
284 CHECK_FIELD(n_type);
285 CHECK_FIELD(n_sect);
286 CHECK_FIELD(n_desc);
287 CHECK_FIELD(n_value);
288}
289
290template <class T>
291void generic_header_check(const T& v1, const dd::load_command_& v2) {
292 static_assert(sizeof(v1) == sizeof(v2), "");
293
294 CHECK_FIELD(cmd);
295 CHECK_FIELD(cmdsize);
296}
297
298
299
300// Unit Tests
301int main(int /*argc*/, char* /*argv*/[]) {
302
303#if BOOST_OS_WINDOWS
304 generic_header_check(::IMAGE_DOS_HEADER(), dd::IMAGE_DOS_HEADER_());
305 generic_header_check(::IMAGE_FILE_HEADER(), dd::IMAGE_FILE_HEADER_());
306 generic_header_check(::IMAGE_DATA_DIRECTORY(), dd::IMAGE_DATA_DIRECTORY_());
307 generic_header_check(::IMAGE_EXPORT_DIRECTORY(), dd::IMAGE_EXPORT_DIRECTORY_());
308 generic_header_check(::IMAGE_SECTION_HEADER(), dd::IMAGE_SECTION_HEADER_());
309 generic_header_check(::IMAGE_OPTIONAL_HEADER32(), dd::IMAGE_OPTIONAL_HEADER32_());
310 generic_header_check(::IMAGE_OPTIONAL_HEADER64(), dd::IMAGE_OPTIONAL_HEADER64_());
311 generic_header_check(::IMAGE_NT_HEADERS32(), dd::IMAGE_NT_HEADERS32_());
312 generic_header_check(::IMAGE_NT_HEADERS64(), dd::IMAGE_NT_HEADERS64_());
313#elif BOOST_OS_MACOS || BOOST_OS_IOS
314 generic_header_check(::mach_header(), dd::mach_header_32_());
315 generic_header_check(::mach_header_64(), dd::mach_header_64_());
316
317 generic_header_check(::segment_command(), dd::segment_command_32_());
318 generic_header_check(::segment_command_64(), dd::segment_command_64_());
319
320 generic_header_check(::section(), dd::section_32_());
321 generic_header_check(::section_64(), dd::section_64_());
322
323 generic_header_check(::load_command(), dd::load_command_());
324 generic_header_check(::symtab_command(), dd::symtab_command_());
325
326 struct ::nlist nl32_var;
327 generic_header_check(nl32_var, dd::nlist_32_());
328 struct ::nlist_64 nl64_var;
329 generic_header_check(nl64_var, dd::nlist_64_());
330
331#else
332 elf_header_checks(v1: ::Elf32_Ehdr(), v2: dd::Elf32_Ehdr_());
333 elf_header_checks(v1: ::Elf64_Ehdr(), v2: dd::Elf64_Ehdr_());
334
335 elf_sheader_checks(v1: ::Elf32_Shdr(), v2: dd::Elf32_Shdr_());
336 elf_sheader_checks(v1: ::Elf64_Shdr(), v2: dd::Elf64_Shdr_());
337
338 elf_sym_header_checks(v1: ::Elf32_Sym(), v2: dd::Elf32_Sym_());
339 elf_sym_header_checks(v1: ::Elf64_Sym(), v2: dd::Elf64_Sym_());
340#endif
341
342 return boost::report_errors();
343}
344
345

source code of boost/libs/dll/test/structures_tests.cpp