structures_tests.cpp 10 KB

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