123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- #ifndef BOOST_DLL_DETAIL_MACHO_INFO_HPP
- #define BOOST_DLL_DETAIL_MACHO_INFO_HPP
- #include <boost/dll/config.hpp>
- #ifdef BOOST_HAS_PRAGMA_ONCE
- # pragma once
- #endif
- #include <algorithm>
- #include <fstream>
- #include <string> // for std::getline
- #include <vector>
- #include <boost/cstdint.hpp>
- namespace boost { namespace dll { namespace detail {
- typedef int integer_t;
- typedef int vm_prot_t;
- typedef integer_t cpu_type_t;
- typedef integer_t cpu_subtype_t;
- template <class AddressOffsetT>
- struct mach_header_template {
- boost::uint32_t magic;
- cpu_type_t cputype;
- cpu_subtype_t cpusubtype;
- boost::uint32_t filetype;
- boost::uint32_t ncmds;
- boost::uint32_t sizeofcmds;
- boost::uint32_t flags[sizeof(AddressOffsetT) / sizeof(uint32_t)];
- };
- typedef mach_header_template<boost::uint32_t> mach_header_32_;
- typedef mach_header_template<boost::uint64_t> mach_header_64_;
- struct load_command_ {
- boost::uint32_t cmd;
- boost::uint32_t cmdsize;
- };
- struct load_command_types {
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_ = 0x1);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMTAB_ = 0x2);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMSEG_ = 0x3);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_THREAD_ = 0x4);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UNIXTHREAD_ = 0x5);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOADFVMLIB_ = 0x6);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDFVMLIB_ = 0x7);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDENT_ = 0x8);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_FVMFILE_ = 0x9);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREPAGE_ = 0xa);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYSYMTAB_ = 0xb);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLIB_ = 0xc);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLIB_ = 0xd);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLINKER_ = 0xe);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLINKER_ = 0xf);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBOUND_DYLIB_ = 0x10);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_ = 0x11);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_FRAMEWORK_ = 0x12);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_UMBRELLA_ = 0x13);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_CLIENT_ = 0x14);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_LIBRARY_ = 0x15);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_TWOLEVEL_HINTS_ = 0x16);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBIND_CKSUM_ = 0x17);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REQ_DYLD_ = 0x80000000);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_WEAK_DYLIB_ = (0x18 | LC_REQ_DYLD_));
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_64_ = 0x19);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_64_ = 0x1a);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UUID_ = 0x1b);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_RPATH_ = (0x1c | LC_REQ_DYLD_));
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_CODE_SIGNATURE_ = 0x1d);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_SPLIT_INFO_= 0x1e);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REEXPORT_DYLIB_ = (0x1f | LC_REQ_DYLD_));
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LAZY_LOAD_DYLIB_ = 0x20);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ENCRYPTION_INFO_ = 0x21);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ = 0x22);
- BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ONLY_ = (0x22|LC_REQ_DYLD_));
- };
- template <class AddressOffsetT>
- struct segment_command_template {
- boost::uint32_t cmd;
- boost::uint32_t cmdsize;
- char segname[16];
- AddressOffsetT vmaddr;
- AddressOffsetT vmsize;
- AddressOffsetT fileoff;
- AddressOffsetT filesize;
- vm_prot_t maxprot;
- vm_prot_t initprot;
- boost::uint32_t nsects;
- boost::uint32_t flags;
- };
- typedef segment_command_template<boost::uint32_t> segment_command_32_;
- typedef segment_command_template<boost::uint64_t> segment_command_64_;
- template <class AddressOffsetT>
- struct section_template {
- char sectname[16];
- char segname[16];
- AddressOffsetT addr;
- AddressOffsetT size;
- boost::uint32_t offset;
- boost::uint32_t align;
- boost::uint32_t reloff;
- boost::uint32_t nreloc;
- boost::uint32_t flags;
- boost::uint32_t reserved[1 + sizeof(AddressOffsetT) / sizeof(uint32_t)];
- };
- typedef section_template<boost::uint32_t> section_32_;
- typedef section_template<boost::uint64_t> section_64_;
- struct symtab_command_ {
- boost::uint32_t cmd;
- boost::uint32_t cmdsize;
- boost::uint32_t symoff;
- boost::uint32_t nsyms;
- boost::uint32_t stroff;
- boost::uint32_t strsize;
- };
- template <class AddressOffsetT>
- struct nlist_template {
- boost::uint32_t n_strx;
- boost::uint8_t n_type;
- boost::uint8_t n_sect;
- boost::uint16_t n_desc;
- AddressOffsetT n_value;
- };
- typedef nlist_template<boost::uint32_t> nlist_32_;
- typedef nlist_template<boost::uint64_t> nlist_64_;
- template <class AddressOffsetT>
- class macho_info {
- typedef boost::dll::detail::mach_header_template<AddressOffsetT> header_t;
- typedef boost::dll::detail::load_command_ load_command_t;
- typedef boost::dll::detail::segment_command_template<AddressOffsetT> segment_t;
- typedef boost::dll::detail::section_template<AddressOffsetT> section_t;
- typedef boost::dll::detail::symtab_command_ symbol_header_t;
- typedef boost::dll::detail::nlist_template<AddressOffsetT> nlist_t;
- BOOST_STATIC_CONSTANT(boost::uint32_t, SEGMENT_CMD_NUMBER = (sizeof(AddressOffsetT) > 4 ? load_command_types::LC_SEGMENT_64_ : load_command_types::LC_SEGMENT_));
- public:
- static bool parsing_supported(std::ifstream& fs) {
- static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf);
- uint32_t magic;
- fs.seekg(0);
- fs.read(reinterpret_cast<char*>(&magic), sizeof(magic));
- return (magic_bytes == magic);
- }
- private:
- template <class T>
- static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) {
- fs.read(reinterpret_cast<char*>(&value), size);
- }
- template <class F>
- static void command_finder(std::ifstream& fs, uint32_t cmd_num, F callback_f) {
- const header_t h = header(fs);
- load_command_t command;
- fs.seekg(sizeof(header_t));
- for (std::size_t i = 0; i < h.ncmds; ++i) {
- const std::ifstream::pos_type pos = fs.tellg();
- read_raw(fs, command);
- if (command.cmd != cmd_num) {
- fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
- continue;
- }
- fs.seekg(pos);
- callback_f(fs);
- fs.seekg(pos + static_cast<std::ifstream::pos_type>(command.cmdsize));
- }
- }
- struct section_names_gather {
- std::vector<std::string>& ret;
- void operator()(std::ifstream& fs) const {
- segment_t segment;
- read_raw(fs, segment);
- section_t section;
- ret.reserve(ret.size() + segment.nsects);
- for (std::size_t j = 0; j < segment.nsects; ++j) {
- read_raw(fs, section);
-
-
- section.segname[0] = '\0';
- ret.push_back(section.sectname);
- if (ret.back().empty()) {
- ret.pop_back();
- }
- }
- }
- };
- struct symbol_names_gather {
- std::vector<std::string>& ret;
- std::size_t section_index;
- void operator()(std::ifstream& fs) const {
- symbol_header_t symbh;
- read_raw(fs, symbh);
- ret.reserve(ret.size() + symbh.nsyms);
- nlist_t symbol;
- std::string symbol_name;
- for (std::size_t j = 0; j < symbh.nsyms; ++j) {
- fs.seekg(symbh.symoff + j * sizeof(nlist_t));
- read_raw(fs, symbol);
- if (!symbol.n_strx) {
- continue;
- }
- if ((symbol.n_type & 0x0e) != 0xe || !symbol.n_sect) {
- continue;
- }
- if (section_index && section_index != symbol.n_sect) {
- continue;
- }
- fs.seekg(symbh.stroff + symbol.n_strx);
- std::getline(fs, symbol_name, '\0');
- if (symbol_name.empty()) {
- continue;
- }
- if (symbol_name[0] == '_') {
-
- ret.push_back(symbol_name.c_str() + 1);
- } else {
- ret.push_back(symbol_name);
- }
- }
- }
- };
- public:
- static std::vector<std::string> sections(std::ifstream& fs) {
- std::vector<std::string> ret;
- section_names_gather f = { ret };
- command_finder(fs, SEGMENT_CMD_NUMBER, f);
- return ret;
- }
- private:
- static header_t header(std::ifstream& fs) {
- header_t h;
- fs.seekg(0);
- read_raw(fs, h);
- return h;
- }
- public:
- static std::vector<std::string> symbols(std::ifstream& fs) {
- std::vector<std::string> ret;
- symbol_names_gather f = { ret, 0 };
- command_finder(fs, load_command_types::LC_SYMTAB_, f);
- return ret;
- }
- static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) {
-
- std::vector<std::string> ret = sections(fs);
- std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name);
- if (it == ret.end()) {
-
- ret.clear();
- return ret;
- }
-
- symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) };
- ret.clear();
- command_finder(fs, load_command_types::LC_SYMTAB_, f);
- return ret;
- }
- };
- typedef macho_info<boost::uint32_t> macho_info32;
- typedef macho_info<boost::uint64_t> macho_info64;
- }}}
- #endif
|