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