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