1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 2 * 3 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23*/ 24#ifndef __MACH_O_FILE_ABSTRACTION__ 25#define __MACH_O_FILE_ABSTRACTION__ 26 27#include <mach-o/loader.h> 28#include <mach-o/nlist.h> 29#include <mach-o/reloc.h> 30#include <mach/machine.h> 31 32// suport older versions of mach-o/loader.h 33#ifndef LC_UUID 34#define LC_UUID 0x1b 35struct uuid_command { 36 uint32_t cmd; /* LC_UUID */ 37 uint32_t cmdsize; /* sizeof(struct uuid_command) */ 38 uint8_t uuid[16]; /* the 128-bit uuid */ 39}; 40#endif 41 42#ifndef S_16BYTE_LITERALS 43 #define S_16BYTE_LITERALS 0xE 44#endif 45 46#ifndef CPU_SUBTYPE_ARM_V5TEJ 47 #define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) 48#endif 49#ifndef CPU_SUBTYPE_ARM_XSCALE 50 #define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) 51#endif 52#ifndef CPU_SUBTYPE_ARM_V7 53 #define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) 54#endif 55#ifndef CPU_SUBTYPE_ARM_V7F 56 #define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) 57#endif 58#ifndef CPU_SUBTYPE_ARM_V7K 59 #define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) 60#endif 61#ifndef CPU_SUBTYPE_ARM_V7S 62 #define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) 63#endif 64#ifndef CPU_SUBTYPE_ARM64_ALL 65 #define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0) 66#endif 67#ifndef CPU_TYPE_ARM64 68 #define CPU_TYPE_ARM64 ((cpu_type_t) (CPU_TYPE_ARM | CPU_ARCH_ABI64)) 69#endif 70 71#define ARM64_RELOC_UNSIGNED 0 // for pointers 72 73 74#ifndef LC_LOAD_UPWARD_DYLIB 75 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ 76#endif 77 78#ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 79 #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 80#endif 81#ifndef EXPORT_SYMBOL_FLAGS_REEXPORT 82 #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 83#endif 84 85#ifndef LC_FUNCTION_STARTS 86 #define LC_FUNCTION_STARTS 0x26 87#endif 88 89#ifndef LC_DATA_IN_CODE 90 #define LC_DATA_IN_CODE 0x29 91#endif 92 93#ifndef LC_DYLIB_CODE_SIGN_DRS 94 #define LC_DYLIB_CODE_SIGN_DRS 0x2B 95#endif 96 97#ifndef CPU_SUBTYPE_X86_64_H 98 #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8) 99#endif 100 101 102#include "FileAbstraction.hpp" 103#include "Architectures.hpp" 104 105// utility to pair together a cpu-type and cpu-sub-type 106struct ArchPair 107{ 108 uint32_t arch; 109 uint32_t subtype; 110 111 ArchPair(uint32_t cputype, uint32_t cpusubtype) : arch(cputype), subtype(cpusubtype) {} 112 113 bool operator<(const ArchPair& other) const { 114 if ( this->arch != other.arch ) 115 return (this->arch < other.arch); 116 return (this->subtype < other.subtype); 117 } 118}; 119 120 121// 122// This abstraction layer makes every mach-o file look like a 64-bit mach-o file with native endianness 123// 124 125// 126// mach-o load command 127// 128template <typename P> 129class macho_load_command { 130public: 131 uint32_t cmd() const INLINE { return E::get32(command.cmd); } 132 void set_cmd(uint32_t value) INLINE { E::set32(command.cmd, value); } 133 134 uint32_t cmdsize() const INLINE { return E::get32(command.cmdsize); } 135 void set_cmdsize(uint32_t value) INLINE { E::set32(command.cmdsize, value); } 136 137 typedef typename P::E E; 138private: 139 load_command command; 140}; 141 142 143// 144// mach-o segment load command 145// 146template <typename P> struct macho_segment_content {}; 147template <> struct macho_segment_content<Pointer32<BigEndian> > { segment_command fields; enum { CMD = LC_SEGMENT }; }; 148template <> struct macho_segment_content<Pointer64<BigEndian> > { segment_command_64 fields; enum { CMD = LC_SEGMENT_64 }; }; 149template <> struct macho_segment_content<Pointer32<LittleEndian> > { segment_command fields; enum { CMD = LC_SEGMENT }; }; 150template <> struct macho_segment_content<Pointer64<LittleEndian> > { segment_command_64 fields; enum { CMD = LC_SEGMENT_64 }; }; 151 152template <typename P> 153class macho_segment_command { 154public: 155 uint32_t cmd() const INLINE { return E::get32(segment.fields.cmd); } 156 void set_cmd(uint32_t value) INLINE { E::set32(segment.fields.cmd, value); } 157 158 uint32_t cmdsize() const INLINE { return E::get32(segment.fields.cmdsize); } 159 void set_cmdsize(uint32_t value) INLINE { E::set32(segment.fields.cmdsize, value); } 160 161 const char* segname() const INLINE { return segment.fields.segname; } 162 void set_segname(const char* value) INLINE { strncpy(segment.fields.segname, value, 16); } 163 164 uint64_t vmaddr() const INLINE { return P::getP(segment.fields.vmaddr); } 165 void set_vmaddr(uint64_t value) INLINE { P::setP(segment.fields.vmaddr, value); } 166 167 uint64_t vmsize() const INLINE { return P::getP(segment.fields.vmsize); } 168 void set_vmsize(uint64_t value) INLINE { P::setP(segment.fields.vmsize, value); } 169 170 uint64_t fileoff() const INLINE { return P::getP(segment.fields.fileoff); } 171 void set_fileoff(uint64_t value) INLINE { P::setP(segment.fields.fileoff, value); } 172 173 uint64_t filesize() const INLINE { return P::getP(segment.fields.filesize); } 174 void set_filesize(uint64_t value) INLINE { P::setP(segment.fields.filesize, value); } 175 176 uint32_t maxprot() const INLINE { return E::get32(segment.fields.maxprot); } 177 void set_maxprot(uint32_t value) INLINE { E::set32((uint32_t&)segment.fields.maxprot, value); } 178 179 uint32_t initprot() const INLINE { return E::get32(segment.fields.initprot); } 180 void set_initprot(uint32_t value) INLINE { E::set32((uint32_t&)segment.fields.initprot, value); } 181 182 uint32_t nsects() const INLINE { return E::get32(segment.fields.nsects); } 183 void set_nsects(uint32_t value) INLINE { E::set32(segment.fields.nsects, value); } 184 185 uint32_t flags() const INLINE { return E::get32(segment.fields.flags); } 186 void set_flags(uint32_t value) INLINE { E::set32(segment.fields.flags, value); } 187 188 enum { 189 CMD = macho_segment_content<P>::CMD 190 }; 191 192 typedef typename P::E E; 193private: 194 macho_segment_content<P> segment; 195}; 196 197 198// 199// mach-o section 200// 201template <typename P> struct macho_section_content {}; 202template <> struct macho_section_content<Pointer32<BigEndian> > { section fields; }; 203template <> struct macho_section_content<Pointer64<BigEndian> > { section_64 fields; }; 204template <> struct macho_section_content<Pointer32<LittleEndian> > { section fields; }; 205template <> struct macho_section_content<Pointer64<LittleEndian> > { section_64 fields; }; 206 207template <typename P> 208class macho_section { 209public: 210 const char* sectname() const INLINE { return section.fields.sectname; } 211 void set_sectname(const char* value) INLINE { strncpy(section.fields.sectname, value, 16); } 212 213 const char* segname() const INLINE { return section.fields.segname; } 214 void set_segname(const char* value) INLINE { strncpy(section.fields.segname, value, 16); } 215 216 uint64_t addr() const INLINE { return P::getP(section.fields.addr); } 217 void set_addr(uint64_t value) INLINE { P::setP(section.fields.addr, value); } 218 219 uint64_t size() const INLINE { return P::getP(section.fields.size); } 220 void set_size(uint64_t value) INLINE { P::setP(section.fields.size, value); } 221 222 uint32_t offset() const INLINE { return E::get32(section.fields.offset); } 223 void set_offset(uint32_t value) INLINE { E::set32(section.fields.offset, value); } 224 225 uint32_t align() const INLINE { return E::get32(section.fields.align); } 226 void set_align(uint32_t value) INLINE { E::set32(section.fields.align, value); } 227 228 uint32_t reloff() const INLINE { return E::get32(section.fields.reloff); } 229 void set_reloff(uint32_t value) INLINE { E::set32(section.fields.reloff, value); } 230 231 uint32_t nreloc() const INLINE { return E::get32(section.fields.nreloc); } 232 void set_nreloc(uint32_t value) INLINE { E::set32(section.fields.nreloc, value); } 233 234 uint32_t flags() const INLINE { return E::get32(section.fields.flags); } 235 void set_flags(uint32_t value) INLINE { E::set32(section.fields.flags, value); } 236 237 uint32_t reserved1() const INLINE { return E::get32(section.fields.reserved1); } 238 void set_reserved1(uint32_t value) INLINE { E::set32(section.fields.reserved1, value); } 239 240 uint32_t reserved2() const INLINE { return E::get32(section.fields.reserved2); } 241 void set_reserved2(uint32_t value) INLINE { E::set32(section.fields.reserved2, value); } 242 243 typedef typename P::E E; 244private: 245 macho_section_content<P> section; 246}; 247 248 249// 250// mach-o dylib load command 251// 252template <typename P> 253class macho_dylib_command { 254public: 255 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 256 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 257 258 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 259 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 260 261 uint32_t name_offset() const INLINE { return E::get32(fields.dylib.name.offset); } 262 void set_name_offset(uint32_t value) INLINE { E::set32(fields.dylib.name.offset, value); } 263 264 uint32_t timestamp() const INLINE { return E::get32(fields.dylib.timestamp); } 265 void set_timestamp(uint32_t value) INLINE { E::set32(fields.dylib.timestamp, value); } 266 267 uint32_t current_version() const INLINE { return E::get32(fields.dylib.current_version); } 268 void set_current_version(uint32_t value) INLINE { E::set32(fields.dylib.current_version, value); } 269 270 uint32_t compatibility_version() const INLINE { return E::get32(fields.dylib.compatibility_version); } 271 void set_compatibility_version(uint32_t value) INLINE { E::set32(fields.dylib.compatibility_version, value); } 272 273 const char* name() const INLINE { return (const char*)&fields + name_offset(); } 274 void set_name_offset() INLINE { set_name_offset(sizeof(fields)); } 275 276 typedef typename P::E E; 277private: 278 dylib_command fields; 279}; 280 281 282// 283// mach-o dylinker load command 284// 285template <typename P> 286class macho_dylinker_command { 287public: 288 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 289 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 290 291 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 292 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 293 294 uint32_t name_offset() const INLINE { return E::get32(fields.name.offset); } 295 void set_name_offset(uint32_t value) INLINE { E::set32(fields.name.offset, value); } 296 297 const char* name() const INLINE { return (const char*)&fields + name_offset(); } 298 void set_name_offset() INLINE { set_name_offset(sizeof(fields)); } 299 300 typedef typename P::E E; 301private: 302 dylinker_command fields; 303}; 304 305 306// 307// mach-o sub_framework load command 308// 309template <typename P> 310class macho_sub_framework_command { 311public: 312 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 313 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 314 315 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 316 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 317 318 uint32_t umbrella_offset() const INLINE { return E::get32(fields.umbrella.offset); } 319 void set_umbrella_offset(uint32_t value) INLINE { E::set32(fields.umbrella.offset, value); } 320 321 const char* umbrella() const INLINE { return (const char*)&fields + umbrella_offset(); } 322 void set_umbrella_offset() INLINE { set_umbrella_offset(sizeof(fields)); } 323 324 typedef typename P::E E; 325private: 326 sub_framework_command fields; 327}; 328 329 330// 331// mach-o sub_client load command 332// 333template <typename P> 334class macho_sub_client_command { 335public: 336 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 337 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 338 339 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 340 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 341 342 uint32_t client_offset() const INLINE { return E::get32(fields.client.offset); } 343 void set_client_offset(uint32_t value) INLINE { E::set32(fields.client.offset, value); } 344 345 const char* client() const INLINE { return (const char*)&fields + client_offset(); } 346 void set_client_offset() INLINE { set_client_offset(sizeof(fields)); } 347 348 typedef typename P::E E; 349private: 350 sub_client_command fields; 351}; 352 353 354// 355// mach-o sub_umbrella load command 356// 357template <typename P> 358class macho_sub_umbrella_command { 359public: 360 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 361 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 362 363 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 364 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 365 366 uint32_t sub_umbrella_offset() const INLINE { return E::get32(fields.sub_umbrella.offset); } 367 void set_sub_umbrella_offset(uint32_t value) INLINE { E::set32(fields.sub_umbrella.offset, value); } 368 369 const char* sub_umbrella() const INLINE { return (const char*)&fields + sub_umbrella_offset(); } 370 void set_sub_umbrella_offset() INLINE { set_sub_umbrella_offset(sizeof(fields)); } 371 372 typedef typename P::E E; 373private: 374 sub_umbrella_command fields; 375}; 376 377 378// 379// mach-o sub_library load command 380// 381template <typename P> 382class macho_sub_library_command { 383public: 384 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 385 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 386 387 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 388 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 389 390 uint32_t sub_library_offset() const INLINE { return E::get32(fields.sub_library.offset); } 391 void set_sub_library_offset(uint32_t value) INLINE { E::set32(fields.sub_library.offset, value); } 392 393 const char* sub_library() const INLINE { return (const char*)&fields + sub_library_offset(); } 394 void set_sub_library_offset() INLINE { set_sub_library_offset(sizeof(fields)); } 395 396 typedef typename P::E E; 397private: 398 sub_library_command fields; 399}; 400 401 402// 403// mach-o uuid load command 404// 405template <typename P> 406class macho_uuid_command { 407public: 408 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 409 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 410 411 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 412 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 413 414 const uint8_t* uuid() const INLINE { return fields.uuid; } 415 void set_uuid(uint8_t value[16]) INLINE { memcpy(&fields.uuid, value, 16); } 416 417 typedef typename P::E E; 418private: 419 uuid_command fields; 420}; 421 422 423// 424// mach-o routines load command 425// 426template <typename P> struct macho_routines_content {}; 427template <> struct macho_routines_content<Pointer32<BigEndian> > { routines_command fields; enum { CMD = LC_ROUTINES }; }; 428template <> struct macho_routines_content<Pointer64<BigEndian> > { routines_command_64 fields; enum { CMD = LC_ROUTINES_64 }; }; 429template <> struct macho_routines_content<Pointer32<LittleEndian> > { routines_command fields; enum { CMD = LC_ROUTINES }; }; 430template <> struct macho_routines_content<Pointer64<LittleEndian> > { routines_command_64 fields; enum { CMD = LC_ROUTINES_64 }; }; 431 432template <typename P> 433class macho_routines_command { 434public: 435 uint32_t cmd() const INLINE { return E::get32(routines.fields.cmd); } 436 void set_cmd(uint32_t value) INLINE { E::set32(routines.fields.cmd, value); } 437 438 uint32_t cmdsize() const INLINE { return E::get32(routines.fields.cmdsize); } 439 void set_cmdsize(uint32_t value) INLINE { E::set32(routines.fields.cmdsize, value); } 440 441 uint64_t init_address() const INLINE { return P::getP(routines.fields.init_address); } 442 void set_init_address(uint64_t value) INLINE { P::setP(routines.fields.init_address, value); } 443 444 uint64_t init_module() const INLINE { return P::getP(routines.fields.init_module); } 445 void set_init_module(uint64_t value) INLINE { P::setP(routines.fields.init_module, value); } 446 447 uint64_t reserved1() const INLINE { return P::getP(routines.fields.reserved1); } 448 void set_reserved1(uint64_t value) INLINE { P::setP(routines.fields.reserved1, value); } 449 450 uint64_t reserved2() const INLINE { return P::getP(routines.fields.reserved2); } 451 void set_reserved2(uint64_t value) INLINE { P::setP(routines.fields.reserved2, value); } 452 453 uint64_t reserved3() const INLINE { return P::getP(routines.fields.reserved3); } 454 void set_reserved3(uint64_t value) INLINE { P::setP(routines.fields.reserved3, value); } 455 456 uint64_t reserved4() const INLINE { return P::getP(routines.fields.reserved4); } 457 void set_reserved4(uint64_t value) INLINE { P::setP(routines.fields.reserved4, value); } 458 459 uint64_t reserved5() const INLINE { return P::getP(routines.fields.reserved5); } 460 void set_reserved5(uint64_t value) INLINE { P::setP(routines.fields.reserved5, value); } 461 462 uint64_t reserved6() const INLINE { return P::getP(routines.fields.reserved6); } 463 void set_reserved6(uint64_t value) INLINE { P::setP(routines.fields.reserved6, value); } 464 465 typedef typename P::E E; 466 enum { 467 CMD = macho_routines_content<P>::CMD 468 }; 469private: 470 macho_routines_content<P> routines; 471}; 472 473 474// 475// mach-o symbol table load command 476// 477template <typename P> 478class macho_symtab_command { 479public: 480 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 481 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 482 483 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 484 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 485 486 uint32_t symoff() const INLINE { return E::get32(fields.symoff); } 487 void set_symoff(uint32_t value) INLINE { E::set32(fields.symoff, value); } 488 489 uint32_t nsyms() const INLINE { return E::get32(fields.nsyms); } 490 void set_nsyms(uint32_t value) INLINE { E::set32(fields.nsyms, value); } 491 492 uint32_t stroff() const INLINE { return E::get32(fields.stroff); } 493 void set_stroff(uint32_t value) INLINE { E::set32(fields.stroff, value); } 494 495 uint32_t strsize() const INLINE { return E::get32(fields.strsize); } 496 void set_strsize(uint32_t value) INLINE { E::set32(fields.strsize, value); } 497 498 499 typedef typename P::E E; 500private: 501 symtab_command fields; 502}; 503 504 505// 506// mach-o dynamic symbol table load command 507// 508template <typename P> 509class macho_dysymtab_command { 510public: 511 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 512 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 513 514 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 515 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 516 517 uint32_t ilocalsym() const INLINE { return E::get32(fields.ilocalsym); } 518 void set_ilocalsym(uint32_t value) INLINE { E::set32(fields.ilocalsym, value); } 519 520 uint32_t nlocalsym() const INLINE { return E::get32(fields.nlocalsym); } 521 void set_nlocalsym(uint32_t value) INLINE { E::set32(fields.nlocalsym, value); } 522 523 uint32_t iextdefsym() const INLINE { return E::get32(fields.iextdefsym); } 524 void set_iextdefsym(uint32_t value) INLINE { E::set32(fields.iextdefsym, value); } 525 526 uint32_t nextdefsym() const INLINE { return E::get32(fields.nextdefsym); } 527 void set_nextdefsym(uint32_t value) INLINE { E::set32(fields.nextdefsym, value); } 528 529 uint32_t iundefsym() const INLINE { return E::get32(fields.iundefsym); } 530 void set_iundefsym(uint32_t value) INLINE { E::set32(fields.iundefsym, value); } 531 532 uint32_t nundefsym() const INLINE { return E::get32(fields.nundefsym); } 533 void set_nundefsym(uint32_t value) INLINE { E::set32(fields.nundefsym, value); } 534 535 uint32_t tocoff() const INLINE { return E::get32(fields.tocoff); } 536 void set_tocoff(uint32_t value) INLINE { E::set32(fields.tocoff, value); } 537 538 uint32_t ntoc() const INLINE { return E::get32(fields.ntoc); } 539 void set_ntoc(uint32_t value) INLINE { E::set32(fields.ntoc, value); } 540 541 uint32_t modtaboff() const INLINE { return E::get32(fields.modtaboff); } 542 void set_modtaboff(uint32_t value) INLINE { E::set32(fields.modtaboff, value); } 543 544 uint32_t nmodtab() const INLINE { return E::get32(fields.nmodtab); } 545 void set_nmodtab(uint32_t value) INLINE { E::set32(fields.nmodtab, value); } 546 547 uint32_t extrefsymoff() const INLINE { return E::get32(fields.extrefsymoff); } 548 void set_extrefsymoff(uint32_t value) INLINE { E::set32(fields.extrefsymoff, value); } 549 550 uint32_t nextrefsyms() const INLINE { return E::get32(fields.nextrefsyms); } 551 void set_nextrefsyms(uint32_t value) INLINE { E::set32(fields.nextrefsyms, value); } 552 553 uint32_t indirectsymoff() const INLINE { return E::get32(fields.indirectsymoff); } 554 void set_indirectsymoff(uint32_t value) INLINE { E::set32(fields.indirectsymoff, value); } 555 556 uint32_t nindirectsyms() const INLINE { return E::get32(fields.nindirectsyms); } 557 void set_nindirectsyms(uint32_t value) INLINE { E::set32(fields.nindirectsyms, value); } 558 559 uint32_t extreloff() const INLINE { return E::get32(fields.extreloff); } 560 void set_extreloff(uint32_t value) INLINE { E::set32(fields.extreloff, value); } 561 562 uint32_t nextrel() const INLINE { return E::get32(fields.nextrel); } 563 void set_nextrel(uint32_t value) INLINE { E::set32(fields.nextrel, value); } 564 565 uint32_t locreloff() const INLINE { return E::get32(fields.locreloff); } 566 void set_locreloff(uint32_t value) INLINE { E::set32(fields.locreloff, value); } 567 568 uint32_t nlocrel() const INLINE { return E::get32(fields.nlocrel); } 569 void set_nlocrel(uint32_t value) INLINE { E::set32(fields.nlocrel, value); } 570 571 typedef typename P::E E; 572private: 573 dysymtab_command fields; 574}; 575 576 577// 578// mach-o two-level hints load command 579// 580template <typename P> 581class macho_twolevel_hints_command { 582public: 583 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 584 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 585 586 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 587 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 588 589 uint32_t offset() const INLINE { return E::get32(fields.offset); } 590 void set_offset(uint32_t value) INLINE { E::set32(fields.offset, value); } 591 592 uint32_t nhints() const INLINE { return E::get32(fields.nhints); } 593 void set_nhints(uint32_t value) INLINE { E::set32(fields.nhints, value); } 594 595 typedef typename P::E E; 596private: 597 twolevel_hints_command fields; 598}; 599 600 601// 602// mach-o threads load command 603// 604template <typename P> 605class macho_thread_command { 606public: 607 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 608 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 609 610 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 611 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 612 613 uint32_t flavor() const INLINE { return E::get32(fields_flavor); } 614 void set_flavor(uint32_t value) INLINE { E::set32(fields_flavor, value); } 615 616 uint32_t count() const INLINE { return E::get32(fields_count); } 617 void set_count(uint32_t value) INLINE { E::set32(fields_count, value); } 618 619 uint64_t thread_register(uint32_t index) const INLINE { return P::getP(thread_registers[index]); } 620 void set_thread_register(uint32_t index, uint64_t value) INLINE { P::setP(thread_registers[index], value); } 621 622 typedef typename P::E E; 623 typedef typename P::uint_t pint_t; 624private: 625 struct thread_command fields; 626 uint32_t fields_flavor; 627 uint32_t fields_count; 628 pint_t thread_registers[1]; 629}; 630 631 632// 633// mach-o misc data 634// 635template <typename P> 636class macho_linkedit_data_command { 637public: 638 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 639 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 640 641 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 642 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 643 644 uint32_t dataoff() const INLINE { return E::get32(fields.dataoff); } 645 void set_dataoff(uint32_t value) INLINE { E::set32(fields.dataoff, value); } 646 647 uint32_t datasize() const INLINE { return E::get32(fields.datasize); } 648 void set_datasize(uint32_t value)INLINE { E::set32(fields.datasize, value); } 649 650 651 typedef typename P::E E; 652private: 653 linkedit_data_command fields; 654}; 655 656 657// 658// mach-o symbol table entry 659// 660template <typename P> struct macho_nlist_content {}; 661template <> struct macho_nlist_content<Pointer32<BigEndian> > { struct nlist fields; }; 662template <> struct macho_nlist_content<Pointer64<BigEndian> > { struct nlist_64 fields; }; 663template <> struct macho_nlist_content<Pointer32<LittleEndian> > { struct nlist fields; }; 664template <> struct macho_nlist_content<Pointer64<LittleEndian> > { struct nlist_64 fields; }; 665 666template <typename P> 667class macho_nlist { 668public: 669 uint32_t n_strx() const INLINE { return E::get32(entry.fields.n_un.n_strx); } 670 void set_n_strx(uint32_t value) INLINE { E::set32((uint32_t&)entry.fields.n_un.n_strx, value); } 671 672 uint8_t n_type() const INLINE { return entry.fields.n_type; } 673 void set_n_type(uint8_t value) INLINE { entry.fields.n_type = value; } 674 675 uint8_t n_sect() const INLINE { return entry.fields.n_sect; } 676 void set_n_sect(uint8_t value) INLINE { entry.fields.n_sect = value; } 677 678 uint16_t n_desc() const INLINE { return E::get16(entry.fields.n_desc); } 679 void set_n_desc(uint16_t value) INLINE { E::set16((uint16_t&)entry.fields.n_desc, value); } 680 681 uint64_t n_value() const INLINE { return P::getP(entry.fields.n_value); } 682 void set_n_value(uint64_t value) INLINE { P::setP(entry.fields.n_value, value); } 683 684 typedef typename P::E E; 685private: 686 macho_nlist_content<P> entry; 687}; 688 689 690 691// 692// mach-o relocation info 693// 694template <typename P> 695class macho_relocation_info { 696public: 697 uint32_t r_address() const INLINE { return E::get32(address); } 698 void set_r_address(uint32_t value) INLINE { E::set32(address, value); } 699 700 uint32_t r_symbolnum() const INLINE { return E::getBits(other, 0, 24); } 701 void set_r_symbolnum(uint32_t value) INLINE { E::setBits(other, value, 0, 24); } 702 703 bool r_pcrel() const INLINE { return E::getBits(other, 24, 1); } 704 void set_r_pcrel(bool value) INLINE { E::setBits(other, value, 24, 1); } 705 706 uint8_t r_length() const INLINE { return E::getBits(other, 25, 2); } 707 void set_r_length(uint8_t value) INLINE { E::setBits(other, value, 25, 2); } 708 709 bool r_extern() const INLINE { return E::getBits(other, 27, 1); } 710 void set_r_extern(bool value) INLINE { E::setBits(other, value, 27, 1); } 711 712 uint8_t r_type() const INLINE { return E::getBits(other, 28, 4); } 713 void set_r_type(uint8_t value) INLINE { E::setBits(other, value, 28, 4); } 714 715 void set_r_length() INLINE { set_r_length((sizeof(typename P::uint_t)==8) ? 3 : 2); } 716 717 typedef typename P::E E; 718private: 719 uint32_t address; 720 uint32_t other; 721}; 722 723 724// 725// mach-o scattered relocation info 726// The bit fields are always in big-endian order (see mach-o/reloc.h) 727// 728template <typename P> 729class macho_scattered_relocation_info { 730public: 731 bool r_scattered() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 0, 1); } 732 void set_r_scattered(bool x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 0, 1); E::set32(other, temp); } 733 734 bool r_pcrel() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 1, 1); } 735 void set_r_pcrel(bool x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 1, 1); E::set32(other, temp); } 736 737 uint8_t r_length() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 2, 2); } 738 void set_r_length(uint8_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 2, 2); E::set32(other, temp); } 739 740 uint8_t r_type() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 4, 4); } 741 void set_r_type(uint8_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 4, 4); E::set32(other, temp); } 742 743 uint32_t r_address() const INLINE { return BigEndian::getBitsRaw(E::get32(other), 8, 24); } 744 void set_r_address(uint32_t x) INLINE { uint32_t temp = E::get32(other); BigEndian::setBitsRaw(temp, x, 8, 24); E::set32(other, temp); } 745 746 uint32_t r_value() const INLINE { return E::get32(value); } 747 void set_r_value(uint32_t x) INLINE { E::set32(value, x); } 748 749 uint32_t r_other() const INLINE { return other; } 750 751 typedef typename P::E E; 752private: 753 uint32_t other; 754 uint32_t value; 755}; 756 757 758// 759// mach-o file header 760// 761template <typename P> struct macho_header_content {}; 762template <> struct macho_header_content<Pointer32<BigEndian> > { mach_header fields; }; 763template <> struct macho_header_content<Pointer64<BigEndian> > { mach_header_64 fields; }; 764template <> struct macho_header_content<Pointer32<LittleEndian> > { mach_header fields; }; 765template <> struct macho_header_content<Pointer64<LittleEndian> > { mach_header_64 fields; }; 766 767template <typename P> 768class macho_header { 769public: 770 uint32_t magic() const INLINE { return E::get32(header.fields.magic); } 771 void set_magic(uint32_t value) INLINE { E::set32(header.fields.magic, value); } 772 773 uint32_t cputype() const INLINE { return E::get32(header.fields.cputype); } 774 void set_cputype(uint32_t value) INLINE { E::set32((uint32_t&)header.fields.cputype, value); } 775 776 uint32_t cpusubtype() const INLINE { return E::get32(header.fields.cpusubtype); } 777 void set_cpusubtype(uint32_t value) INLINE { E::set32((uint32_t&)header.fields.cpusubtype, value); } 778 779 uint32_t filetype() const INLINE { return E::get32(header.fields.filetype); } 780 void set_filetype(uint32_t value) INLINE { E::set32(header.fields.filetype, value); } 781 782 uint32_t ncmds() const INLINE { return E::get32(header.fields.ncmds); } 783 void set_ncmds(uint32_t value) INLINE { E::set32(header.fields.ncmds, value); } 784 785 uint32_t sizeofcmds() const INLINE { return E::get32(header.fields.sizeofcmds); } 786 void set_sizeofcmds(uint32_t value) INLINE { E::set32(header.fields.sizeofcmds, value); } 787 788 uint32_t flags() const INLINE { return E::get32(header.fields.flags); } 789 void set_flags(uint32_t value) INLINE { E::set32(header.fields.flags, value); } 790 791 uint32_t reserved() const INLINE { return E::get32(header.fields.reserved); } 792 void set_reserved(uint32_t value) INLINE { E::set32(header.fields.reserved, value); } 793 794 const macho_segment_command<P>* getSegment(const char *segname) const 795 { 796 const macho_load_command<P>* cmds = (macho_load_command<P>*)((uint8_t*)this + sizeof(macho_header<P>)); 797 uint32_t cmd_count = this->ncmds(); 798 const macho_load_command<P>* cmd = cmds; 799 for (uint32_t i = 0; i < cmd_count; ++i) { 800 if ( cmd->cmd() == macho_segment_command<P>::CMD ) { 801 const macho_segment_command<P>* segcmd = (macho_segment_command<P>*)cmd; 802 if (0 == strncmp(segname, segcmd->segname(), 16)) { 803 return segcmd; 804 } 805 } 806 cmd = (macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize()); 807 } 808 return NULL; 809 } 810 811 const macho_section<P>* getSection(const char *segname, const char *sectname) const 812 { 813 const macho_segment_command<P>* segcmd = getSegment(segname); 814 if (!segcmd) return NULL; 815 816 const macho_section<P>* sectcmd = (macho_section<P>*)(segcmd+1); 817 uint32_t section_count = segcmd->nsects(); 818 for (uint32_t j = 0; j < section_count; ++j) { 819 if (0 == ::strncmp(sectcmd[j].sectname(), sectname, 16)) { 820 return sectcmd+j; 821 } 822 } 823 824 return NULL; 825 } 826 827 const macho_load_command<P>* getLoadCommand(int query) const 828 { 829 const macho_load_command<P>* cmds = (macho_load_command<P>*)((uint8_t*)this + sizeof(macho_header<P>)); 830 uint32_t cmd_count = this->ncmds(); 831 const macho_load_command<P>* cmd = cmds; 832 for (uint32_t i = 0; i < cmd_count; ++i) { 833 if ( cmd->cmd() == query ) { 834 return cmd; 835 } 836 cmd = (macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize()); 837 } 838 return NULL; 839 } 840 841 typedef typename P::E E; 842private: 843 macho_header_content<P> header; 844}; 845 846 847 848// 849// compressed dyld info load command 850// 851template <typename P> 852class macho_dyld_info_command { 853public: 854 uint32_t cmd() const INLINE { return E::get32(fields.cmd); } 855 void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } 856 857 uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } 858 void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } 859 860 uint32_t rebase_off() const INLINE { return E::get32(fields.rebase_off); } 861 void set_rebase_off(uint32_t value) INLINE { E::set32(fields.rebase_off, value); } 862 863 uint32_t rebase_size() const INLINE { return E::get32(fields.rebase_size); } 864 void set_rebase_size(uint32_t value) INLINE { E::set32(fields.rebase_size, value); } 865 866 uint32_t bind_off() const INLINE { return E::get32(fields.bind_off); } 867 void set_bind_off(uint32_t value) INLINE { E::set32(fields.bind_off, value); } 868 869 uint32_t bind_size() const INLINE { return E::get32(fields.bind_size); } 870 void set_bind_size(uint32_t value) INLINE { E::set32(fields.bind_size, value); } 871 872 uint32_t weak_bind_off() const INLINE { return E::get32(fields.weak_bind_off); } 873 void set_weak_bind_off(uint32_t value) INLINE { E::set32(fields.weak_bind_off, value); } 874 875 uint32_t weak_bind_size() const INLINE { return E::get32(fields.weak_bind_size); } 876 void set_weak_bind_size(uint32_t value) INLINE { E::set32(fields.weak_bind_size, value); } 877 878 uint32_t lazy_bind_off() const INLINE { return E::get32(fields.lazy_bind_off); } 879 void set_lazy_bind_off(uint32_t value) INLINE { E::set32(fields.lazy_bind_off, value); } 880 881 uint32_t lazy_bind_size() const INLINE { return E::get32(fields.lazy_bind_size); } 882 void set_lazy_bind_size(uint32_t value) INLINE { E::set32(fields.lazy_bind_size, value); } 883 884 uint32_t export_off() const INLINE { return E::get32(fields.export_off); } 885 void set_export_off(uint32_t value) INLINE { E::set32(fields.export_off, value); } 886 887 uint32_t export_size() const INLINE { return E::get32(fields.export_size); } 888 void set_export_size(uint32_t value) INLINE { E::set32(fields.export_size, value); } 889 890 891 typedef typename P::E E; 892private: 893 dyld_info_command fields; 894}; 895 896#ifndef NO_ULEB 897inline uint64_t read_uleb128(const uint8_t*& p, const uint8_t* end) { 898 uint64_t result = 0; 899 int bit = 0; 900 do { 901 if (p == end) 902 throw "malformed uleb128 extends beyond trie"; 903 904 uint64_t slice = *p & 0x7f; 905 906 if (bit >= 64 || slice << bit >> bit != slice) 907 throw "uleb128 too big for 64-bits"; 908 else { 909 result |= (slice << bit); 910 bit += 7; 911 } 912 } 913 while (*p++ & 0x80); 914 return result; 915} 916 917 918static int64_t read_sleb128(const uint8_t*& p, const uint8_t* end) 919{ 920 int64_t result = 0; 921 int bit = 0; 922 uint8_t byte; 923 do { 924 if (p == end) 925 throw "malformed sleb128"; 926 byte = *p++; 927 result |= ((byte & 0x7f) << bit); 928 bit += 7; 929 } while (byte & 0x80); 930 // sign extend negative numbers 931 if ( (byte & 0x40) != 0 ) 932 result |= (-1LL) << bit; 933 return result; 934} 935 936#endif 937 938 939#endif // __MACH_O_FILE_ABSTRACTION__ 940 941 942