• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
2 // Copyright 2015-2020 Antony Polukhin.
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>
get_offset(const T1 & v1,const T2 & v2)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>
elf_header_checks(const T1 & v1,const T2 & v2)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>
elf_sheader_checks(const T1 & v1,const T2 & v2)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>
elf_sym_header_checks(const T1 & v1,const T2 & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_DOS_HEADER_ & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_FILE_HEADER_ & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_DATA_DIRECTORY_ & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_EXPORT_DIRECTORY_ & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_SECTION_HEADER_ & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_OPTIONAL_HEADER_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::IMAGE_NT_HEADERS_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::mach_header_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::segment_command_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::section_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::symtab_command_ & v2)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>
generic_header_check(const T & v1,const dd::nlist_template<AddrT> & v2)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>
generic_header_check(const T & v1,const dd::load_command_ & v2)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
main(int,char * [])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 
346