346 lines
10 KiB
C++
346 lines
10 KiB
C++
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
|
|
// Copyright 2015-2019 Antony Polukhin.
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt
|
|
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// For more information, see http://www.boost.org
|
|
|
|
#include <boost/dll/detail/elf_info.hpp>
|
|
#include <boost/dll/detail/pe_info.hpp>
|
|
#include <boost/dll/detail/macho_info.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/core/lightweight_test.hpp>
|
|
#include <boost/predef/os.h>
|
|
|
|
#if BOOST_OS_WINDOWS
|
|
# include <windows.h>
|
|
#elif BOOST_OS_MACOS || BOOST_OS_IOS
|
|
# include <mach-o/loader.h>
|
|
# include <mach-o/nlist.h>
|
|
#elif BOOST_OS_QNX
|
|
// QNX's copy of <elf.h> and <link.h> reside in sys folder
|
|
# include <sys/elf.h>
|
|
#else
|
|
#include <elf.h>
|
|
#endif
|
|
|
|
namespace dd = boost::dll::detail;
|
|
|
|
template <class T1, class T2>
|
|
inline std::size_t get_offset(const T1& v1, const T2& v2) {
|
|
const unsigned char* p1 = reinterpret_cast<const unsigned char*>(&v1);
|
|
const unsigned char* p2 = reinterpret_cast<const unsigned char*>(&v2);
|
|
|
|
if (p1 < p2) {
|
|
return static_cast<std::size_t>(p2 - p1);
|
|
}
|
|
|
|
return static_cast<std::size_t>(p1 - p2);
|
|
}
|
|
|
|
#define CHECK_FIELD(Field) \
|
|
BOOST_STATIC_ASSERT(sizeof(v1.Field) == sizeof(v2.Field)); \
|
|
BOOST_TEST(get_offset(v1, v1.Field) == get_offset(v2, v2.Field)) \
|
|
/**/
|
|
|
|
|
|
// ELF structures
|
|
template <class T1, class T2>
|
|
void elf_header_checks(const T1& v1, const T2& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2));
|
|
|
|
CHECK_FIELD(e_ident);
|
|
CHECK_FIELD(e_type);
|
|
CHECK_FIELD(e_machine);
|
|
CHECK_FIELD(e_version);
|
|
CHECK_FIELD(e_entry);
|
|
CHECK_FIELD(e_phoff);
|
|
CHECK_FIELD(e_shoff);
|
|
CHECK_FIELD(e_flags);
|
|
CHECK_FIELD(e_ehsize);
|
|
CHECK_FIELD(e_phentsize);
|
|
CHECK_FIELD(e_phnum);
|
|
CHECK_FIELD(e_shentsize);
|
|
CHECK_FIELD(e_shnum);
|
|
CHECK_FIELD(e_shstrndx);
|
|
}
|
|
|
|
template <class T1, class T2>
|
|
void elf_sheader_checks(const T1& v1, const T2& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2));
|
|
|
|
CHECK_FIELD(sh_name);
|
|
CHECK_FIELD(sh_type);
|
|
CHECK_FIELD(sh_flags);
|
|
CHECK_FIELD(sh_addr);
|
|
CHECK_FIELD(sh_offset);
|
|
CHECK_FIELD(sh_size);
|
|
CHECK_FIELD(sh_link);
|
|
CHECK_FIELD(sh_info);
|
|
CHECK_FIELD(sh_addralign);
|
|
CHECK_FIELD(sh_entsize);
|
|
}
|
|
|
|
template <class T1, class T2>
|
|
void elf_sym_header_checks(const T1& v1, const T2& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(T1) == sizeof(T2));
|
|
|
|
CHECK_FIELD(st_name);
|
|
CHECK_FIELD(st_value);
|
|
CHECK_FIELD(st_size);
|
|
CHECK_FIELD(st_info);
|
|
CHECK_FIELD(st_other);
|
|
CHECK_FIELD(st_shndx);
|
|
}
|
|
|
|
|
|
// PE structures
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_DOS_HEADER_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(e_magic);
|
|
CHECK_FIELD(e_cblp);
|
|
CHECK_FIELD(e_cp);
|
|
CHECK_FIELD(e_crlc);
|
|
CHECK_FIELD(e_cparhdr);
|
|
CHECK_FIELD(e_minalloc);
|
|
CHECK_FIELD(e_maxalloc);
|
|
CHECK_FIELD(e_ss);
|
|
CHECK_FIELD(e_sp);
|
|
CHECK_FIELD(e_csum);
|
|
CHECK_FIELD(e_ip);
|
|
CHECK_FIELD(e_cs);
|
|
CHECK_FIELD(e_lfarlc);
|
|
CHECK_FIELD(e_ovno);
|
|
CHECK_FIELD(e_res);
|
|
CHECK_FIELD(e_oemid);
|
|
CHECK_FIELD(e_oeminfo);
|
|
CHECK_FIELD(e_res2);
|
|
CHECK_FIELD(e_lfanew);
|
|
}
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_FILE_HEADER_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(Machine);
|
|
CHECK_FIELD(NumberOfSections);
|
|
CHECK_FIELD(TimeDateStamp);
|
|
CHECK_FIELD(PointerToSymbolTable);
|
|
CHECK_FIELD(NumberOfSymbols);
|
|
CHECK_FIELD(SizeOfOptionalHeader);
|
|
CHECK_FIELD(Characteristics);
|
|
}
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_DATA_DIRECTORY_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(VirtualAddress);
|
|
CHECK_FIELD(Size);
|
|
}
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_EXPORT_DIRECTORY_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(Characteristics);
|
|
CHECK_FIELD(TimeDateStamp);
|
|
CHECK_FIELD(MajorVersion);
|
|
CHECK_FIELD(MinorVersion);
|
|
CHECK_FIELD(Name);
|
|
CHECK_FIELD(Base);
|
|
CHECK_FIELD(NumberOfFunctions);
|
|
CHECK_FIELD(NumberOfNames);
|
|
CHECK_FIELD(AddressOfFunctions);
|
|
CHECK_FIELD(AddressOfNames);
|
|
CHECK_FIELD(AddressOfNameOrdinals);
|
|
}
|
|
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_SECTION_HEADER_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(Name);
|
|
CHECK_FIELD(VirtualAddress);
|
|
CHECK_FIELD(SizeOfRawData);
|
|
CHECK_FIELD(PointerToRawData);
|
|
CHECK_FIELD(PointerToRelocations);
|
|
CHECK_FIELD(PointerToLinenumbers);
|
|
CHECK_FIELD(NumberOfRelocations);
|
|
CHECK_FIELD(NumberOfLinenumbers);
|
|
CHECK_FIELD(Characteristics);
|
|
}
|
|
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_OPTIONAL_HEADER_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(Magic);
|
|
CHECK_FIELD(MajorLinkerVersion);
|
|
CHECK_FIELD(MinorLinkerVersion);
|
|
CHECK_FIELD(SizeOfCode);
|
|
CHECK_FIELD(SizeOfInitializedData);
|
|
CHECK_FIELD(SizeOfUninitializedData);
|
|
CHECK_FIELD(AddressOfEntryPoint);
|
|
CHECK_FIELD(ImageBase);
|
|
CHECK_FIELD(SectionAlignment);
|
|
CHECK_FIELD(FileAlignment);
|
|
CHECK_FIELD(MajorOperatingSystemVersion);
|
|
CHECK_FIELD(MinorOperatingSystemVersion);
|
|
CHECK_FIELD(MajorImageVersion);
|
|
CHECK_FIELD(MinorImageVersion);
|
|
CHECK_FIELD(MajorSubsystemVersion);
|
|
CHECK_FIELD(MinorSubsystemVersion);
|
|
CHECK_FIELD(Win32VersionValue);
|
|
CHECK_FIELD(SizeOfImage);
|
|
CHECK_FIELD(SizeOfHeaders);
|
|
CHECK_FIELD(CheckSum);
|
|
CHECK_FIELD(Subsystem);
|
|
CHECK_FIELD(DllCharacteristics);
|
|
CHECK_FIELD(SizeOfStackReserve);
|
|
CHECK_FIELD(SizeOfStackCommit);
|
|
CHECK_FIELD(SizeOfHeapReserve);
|
|
CHECK_FIELD(SizeOfHeapCommit);
|
|
CHECK_FIELD(LoaderFlags);
|
|
CHECK_FIELD(NumberOfRvaAndSizes);
|
|
CHECK_FIELD(DataDirectory);
|
|
}
|
|
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::IMAGE_NT_HEADERS_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(Signature);
|
|
CHECK_FIELD(FileHeader);
|
|
CHECK_FIELD(OptionalHeader);
|
|
}
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::mach_header_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(magic);
|
|
CHECK_FIELD(cputype);
|
|
CHECK_FIELD(cpusubtype);
|
|
CHECK_FIELD(filetype);
|
|
CHECK_FIELD(ncmds);
|
|
CHECK_FIELD(sizeofcmds);
|
|
//CHECK_FIELD(flags);
|
|
}
|
|
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::segment_command_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(cmd);
|
|
CHECK_FIELD(cmdsize);
|
|
CHECK_FIELD(segname);
|
|
CHECK_FIELD(vmaddr);
|
|
CHECK_FIELD(vmsize);
|
|
CHECK_FIELD(fileoff);
|
|
CHECK_FIELD(filesize);
|
|
CHECK_FIELD(maxprot);
|
|
CHECK_FIELD(initprot);
|
|
CHECK_FIELD(nsects);
|
|
CHECK_FIELD(flags);
|
|
}
|
|
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::section_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(sectname);
|
|
CHECK_FIELD(segname);
|
|
CHECK_FIELD(addr);
|
|
CHECK_FIELD(size);
|
|
CHECK_FIELD(offset);
|
|
CHECK_FIELD(align);
|
|
CHECK_FIELD(reloff);
|
|
CHECK_FIELD(nreloc);
|
|
CHECK_FIELD(flags);
|
|
//CHECK_FIELD(reserved vs reserveed1&reserved2);
|
|
}
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::symtab_command_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(cmd);
|
|
CHECK_FIELD(cmdsize);
|
|
CHECK_FIELD(symoff);
|
|
CHECK_FIELD(nsyms);
|
|
CHECK_FIELD(stroff);
|
|
CHECK_FIELD(strsize);
|
|
}
|
|
|
|
template <class T, class AddrT>
|
|
void generic_header_check(const T& v1, const dd::nlist_template<AddrT>& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
//CHECK_FIELD(n_strx);
|
|
CHECK_FIELD(n_type);
|
|
CHECK_FIELD(n_sect);
|
|
CHECK_FIELD(n_desc);
|
|
CHECK_FIELD(n_value);
|
|
}
|
|
|
|
template <class T>
|
|
void generic_header_check(const T& v1, const dd::load_command_& v2) {
|
|
BOOST_STATIC_ASSERT(sizeof(v1) == sizeof(v2));
|
|
|
|
CHECK_FIELD(cmd);
|
|
CHECK_FIELD(cmdsize);
|
|
}
|
|
|
|
|
|
|
|
// Unit Tests
|
|
int main(int /*argc*/, char* /*argv*/[]) {
|
|
|
|
#if BOOST_OS_WINDOWS
|
|
generic_header_check(::IMAGE_DOS_HEADER(), dd::IMAGE_DOS_HEADER_());
|
|
generic_header_check(::IMAGE_FILE_HEADER(), dd::IMAGE_FILE_HEADER_());
|
|
generic_header_check(::IMAGE_DATA_DIRECTORY(), dd::IMAGE_DATA_DIRECTORY_());
|
|
generic_header_check(::IMAGE_EXPORT_DIRECTORY(), dd::IMAGE_EXPORT_DIRECTORY_());
|
|
generic_header_check(::IMAGE_SECTION_HEADER(), dd::IMAGE_SECTION_HEADER_());
|
|
generic_header_check(::IMAGE_OPTIONAL_HEADER32(), dd::IMAGE_OPTIONAL_HEADER32_());
|
|
generic_header_check(::IMAGE_OPTIONAL_HEADER64(), dd::IMAGE_OPTIONAL_HEADER64_());
|
|
generic_header_check(::IMAGE_NT_HEADERS32(), dd::IMAGE_NT_HEADERS32_());
|
|
generic_header_check(::IMAGE_NT_HEADERS64(), dd::IMAGE_NT_HEADERS64_());
|
|
#elif BOOST_OS_MACOS || BOOST_OS_IOS
|
|
generic_header_check(::mach_header(), dd::mach_header_32_());
|
|
generic_header_check(::mach_header_64(), dd::mach_header_64_());
|
|
|
|
generic_header_check(::segment_command(), dd::segment_command_32_());
|
|
generic_header_check(::segment_command_64(), dd::segment_command_64_());
|
|
|
|
generic_header_check(::section(), dd::section_32_());
|
|
generic_header_check(::section_64(), dd::section_64_());
|
|
|
|
generic_header_check(::load_command(), dd::load_command_());
|
|
generic_header_check(::symtab_command(), dd::symtab_command_());
|
|
|
|
struct ::nlist nl32_var;
|
|
generic_header_check(nl32_var, dd::nlist_32_());
|
|
struct ::nlist_64 nl64_var;
|
|
generic_header_check(nl64_var, dd::nlist_64_());
|
|
|
|
#else
|
|
elf_header_checks(::Elf32_Ehdr(), dd::Elf32_Ehdr_());
|
|
elf_header_checks(::Elf64_Ehdr(), dd::Elf64_Ehdr_());
|
|
|
|
elf_sheader_checks(::Elf32_Shdr(), dd::Elf32_Shdr_());
|
|
elf_sheader_checks(::Elf64_Shdr(), dd::Elf64_Shdr_());
|
|
|
|
elf_sym_header_checks(::Elf32_Sym(), dd::Elf32_Sym_());
|
|
elf_sym_header_checks(::Elf64_Sym(), dd::Elf64_Sym_());
|
|
#endif
|
|
|
|
return boost::report_errors();
|
|
}
|
|
|