Files
@ e0ea6762c78c
Branch filter:
Location: libtransport.git/include/boost/dll/detail/macho_info.hpp
e0ea6762c78c
14.0 KiB
text/x-c++hdr
Rename SlackInstallation to SlackSession. Allow SlackUser to move SlackSession from SlackUserManager once the SlackUser is created.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
// Copyright 2015 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)
#ifndef BOOST_DLL_DETAIL_MACHO_INFO_HPP
#define BOOST_DLL_DETAIL_MACHO_INFO_HPP
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <boost/filesystem/fstream.hpp>
#include <boost/dll/detail/x_info_interface.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)]; // Flags and reserved
};
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; /* type of command */
boost::uint32_t cmdsize;
};
struct load_command_types {
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_ = 0x1); /* segment of this file to be mapped */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMTAB_ = 0x2); /* link-edit stab symbol table info */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SYMSEG_ = 0x3); /* link-edit gdb symbol table info (obsolete) */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_THREAD_ = 0x4); /* thread */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UNIXTHREAD_ = 0x5); /* unix thread (includes a stack) */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOADFVMLIB_ = 0x6); /* load a specified fixed VM shared library */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDFVMLIB_ = 0x7); /* fixed VM shared library identification */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_IDENT_ = 0x8); /* object identification info (obsolete) */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_FVMFILE_ = 0x9); /* fixed VM file inclusion (internal use) */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREPAGE_ = 0xa); /* prepage command (internal use) */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYSYMTAB_ = 0xb); /* dynamic link-edit symbol table info */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLIB_ = 0xc); /* load a dynamically linked shared library */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLIB_ = 0xd); /* dynamically linked shared lib ident */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_DYLINKER_ = 0xe); /* load a dynamic linker */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ID_DYLINKER_ = 0xf); /* dynamic linker identification */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBOUND_DYLIB_ = 0x10); /* modules prebound for a dynamically linked shared library */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_ = 0x11); /* image routines */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_FRAMEWORK_ = 0x12); /* sub framework */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_UMBRELLA_ = 0x13); /* sub umbrella */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_CLIENT_ = 0x14); /* sub client */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SUB_LIBRARY_ = 0x15); /* sub library */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_TWOLEVEL_HINTS_ = 0x16); /* two-level namespace lookup hints */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_PREBIND_CKSUM_ = 0x17); /* prebind checksum */
/*
* After MacOS X 10.1 when a new load command is added that is required to be
* understood by the dynamic linker for the image to execute properly the
* LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
* linker sees such a load command it it does not understand will issue a
* "unknown load command required for execution" error and refuse to use the
* image. Other load commands without this bit that are not understood will
* simply be ignored.
*/
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REQ_DYLD_ = 0x80000000);
/*
* load a dynamically linked shared library that is allowed to be missing
* (all symbols are weak imported).
*/
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LOAD_WEAK_DYLIB_ = (0x18 | LC_REQ_DYLD_));
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_64_ = 0x19); /* 64-bit segment of this file to be mapped */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ROUTINES_64_ = 0x1a); /* 64-bit image routines */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_UUID_ = 0x1b); /* the uuid */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_RPATH_ = (0x1c | LC_REQ_DYLD_)); /* runpath additions */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_CODE_SIGNATURE_ = 0x1d); /* local of code signature */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_SEGMENT_SPLIT_INFO_= 0x1e); /* local of info to split segments */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_REEXPORT_DYLIB_ = (0x1f | LC_REQ_DYLD_)); /* load and re-export dylib */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_LAZY_LOAD_DYLIB_ = 0x20); /* delay load of dylib until first use */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_ENCRYPTION_INFO_ = 0x21); /* encrypted segment information */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ = 0x22); /* compressed dyld information */
BOOST_STATIC_CONSTANT(boost::uint32_t, LC_DYLD_INFO_ONLY_ = (0x22|LC_REQ_DYLD_)); /* compressed dyld information only */
};
template <class AddressOffsetT>
struct segment_command_template {
boost::uint32_t cmd; /* LC_SEGMENT_ */
boost::uint32_t cmdsize; /* includes sizeof section structs */
char segname[16]; /* segment name */
AddressOffsetT vmaddr; /* memory address of this segment */
AddressOffsetT vmsize; /* memory size of this segment */
AddressOffsetT fileoff; /* file offset of this segment */
AddressOffsetT filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
boost::uint32_t nsects; /* number of sections in segment */
boost::uint32_t flags; /* 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]; /* name of this section */
char segname[16]; /* segment this section goes in */
AddressOffsetT addr; /* memory address of this section */
AddressOffsetT size; /* size in bytes of this section */
boost::uint32_t offset; /* file offset of this section */
boost::uint32_t align; /* section alignment (power of 2) */
boost::uint32_t reloff; /* file offset of relocation entries */
boost::uint32_t nreloc; /* number of relocation entries */
boost::uint32_t flags; /* flags (section type and attributes)*/
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; /* LC_SYMTAB_ */
boost::uint32_t cmdsize; /* sizeof(struct symtab_command) */
boost::uint32_t symoff; /* symbol table offset */
boost::uint32_t nsyms; /* number of symbol table entries */
boost::uint32_t stroff; /* string table offset */
boost::uint32_t strsize; /* string table size in bytes */
};
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: public x_info_interface {
boost::filesystem::ifstream& f_;
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(boost::filesystem::ifstream& f) {
static const uint32_t magic_bytes = (sizeof(AddressOffsetT) <= sizeof(uint32_t) ? 0xfeedface : 0xfeedfacf);
uint32_t magic;
f.seekg(0);
f.read(reinterpret_cast<char*>(&magic), sizeof(magic));
return (magic_bytes == magic);
}
explicit macho_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
: f_(f)
{}
private:
template <class T>
inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
f_.read(reinterpret_cast<char*>(&value), size);
}
template <class F>
void command_finder(uint32_t cmd_num, F callback_f) {
const header_t h = header();
load_command_t command;
f_.seekg(sizeof(header_t));
for (std::size_t i = 0; i < h.ncmds; ++i) {
const boost::filesystem::ifstream::pos_type pos = f_.tellg();
read_raw(command);
if (command.cmd != cmd_num) {
f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
continue;
}
f_.seekg(pos);
callback_f(*this);
f_.seekg(pos + static_cast<boost::filesystem::ifstream::pos_type>(command.cmdsize));
}
}
struct section_names_gather {
std::vector<std::string>& ret;
void operator()(const macho_info& f) const {
segment_t segment;
f.read_raw(segment);
section_t section;
ret.reserve(ret.size() + segment.nsects);
for (std::size_t j = 0; j < segment.nsects; ++j) {
f.read_raw(section);
// `segname` goes right after the `sectname`.
// Forcing `sectname` to end on '\0'
section.segname[0] = '\0';
ret.push_back(section.sectname);
if (ret.back().empty()) {
ret.pop_back(); // Do not show empty names
}
}
}
};
struct symbol_names_gather {
std::vector<std::string>& ret;
std::size_t section_index;
void operator()(const macho_info& f) const {
symbol_header_t symbh;
f.read_raw(symbh);
ret.reserve(ret.size() + symbh.nsyms);
nlist_t symbol;
std::string symbol_name;
for (std::size_t j = 0; j < symbh.nsyms; ++j) {
f.f_.seekg(symbh.symoff + j * sizeof(nlist_t));
f.read_raw(symbol);
if (!symbol.n_strx) {
continue; // Symbol has no name
}
if ((symbol.n_type & 0x0e) != 0xe || !symbol.n_sect) {
continue; // Symbol has no section
}
if (section_index && section_index != symbol.n_sect) {
continue; // Not in the required section
}
f.f_.seekg(symbh.stroff + symbol.n_strx);
getline(f.f_, symbol_name, '\0');
if (symbol_name.empty()) {
continue;
}
if (symbol_name[0] == '_') {
// Linker adds additional '_' symbol. Could not find official docs for that case.
ret.push_back(symbol_name.c_str() + 1);
} else {
ret.push_back(symbol_name);
}
}
}
};
public:
std::vector<std::string> sections() {
std::vector<std::string> ret;
section_names_gather f = { ret };
command_finder(SEGMENT_CMD_NUMBER, f);
return ret;
}
private:
inline header_t header() {
header_t h;
f_.seekg(0);
read_raw(h);
return h;
}
public:
std::vector<std::string> symbols() {
std::vector<std::string> ret;
symbol_names_gather f = { ret, 0 };
command_finder(load_command_types::LC_SYMTAB_, f);
return ret;
}
std::vector<std::string> symbols(const char* section_name) {
// Not very optimal solution
std::vector<std::string> ret = sections();
std::vector<std::string>::iterator it = std::find(ret.begin(), ret.end(), section_name);
if (it == ret.end()) {
// No section with such name
ret.clear();
return ret;
}
// section indexes start from 1
symbol_names_gather f = { ret, static_cast<std::size_t>(1 + (it - ret.begin())) };
ret.clear();
command_finder(load_command_types::LC_SYMTAB_, f);
return ret;
}
};
typedef macho_info<boost::uint32_t> macho_info32;
typedef macho_info<boost::uint64_t> macho_info64;
}}} // namespace boost::dll::detail
#endif // BOOST_DLL_DETAIL_MACHO_INFO_HPP
|