1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Object/MachO.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/Support/DataExtractor.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/Host.h" 23 #include "llvm/Support/LEB128.h" 24 #include "llvm/Support/MachO.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include <cctype> 28 #include <cstring> 29 #include <limits> 30 31 using namespace llvm; 32 using namespace object; 33 34 namespace { 35 struct section_base { 36 char sectname[16]; 37 char segname[16]; 38 }; 39 } 40 41 // FIXME: Replace all uses of this function with getStructOrErr. 42 template <typename T> 43 static T getStruct(const MachOObjectFile *O, const char *P) { 44 // Don't read before the beginning or past the end of the file 45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 46 report_fatal_error("Malformed MachO file."); 47 48 T Cmd; 49 memcpy(&Cmd, P, sizeof(T)); 50 if (O->isLittleEndian() != sys::IsLittleEndianHost) 51 MachO::swapStruct(Cmd); 52 return Cmd; 53 } 54 55 template <typename T> 56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) { 57 // Don't read before the beginning or past the end of the file 58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 59 return object_error::parse_failed; 60 61 T Cmd; 62 memcpy(&Cmd, P, sizeof(T)); 63 if (O->isLittleEndian() != sys::IsLittleEndianHost) 64 MachO::swapStruct(Cmd); 65 return Cmd; 66 } 67 68 static const char * 69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 70 unsigned Sec) { 71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 72 73 bool Is64 = O->is64Bit(); 74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 75 sizeof(MachO::segment_command); 76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 77 sizeof(MachO::section); 78 79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 80 return reinterpret_cast<const char*>(SectionAddr); 81 } 82 83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 84 return O->getData().substr(Offset, 1).data(); 85 } 86 87 static MachO::nlist_base 88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 89 const char *P = reinterpret_cast<const char *>(DRI.p); 90 return getStruct<MachO::nlist_base>(O, P); 91 } 92 93 static StringRef parseSegmentOrSectionName(const char *P) { 94 if (P[15] == 0) 95 // Null terminated. 96 return P; 97 // Not null terminated, so this is a 16 char string. 98 return StringRef(P, 16); 99 } 100 101 // Helper to advance a section or symbol iterator multiple increments at a time. 102 template<class T> 103 static void advance(T &it, size_t Val) { 104 while (Val--) 105 ++it; 106 } 107 108 static unsigned getCPUType(const MachOObjectFile *O) { 109 return O->getHeader().cputype; 110 } 111 112 static uint32_t 113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 114 return RE.r_word0; 115 } 116 117 static unsigned 118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 119 return RE.r_word0 & 0xffffff; 120 } 121 122 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 123 const MachO::any_relocation_info &RE) { 124 if (O->isLittleEndian()) 125 return (RE.r_word1 >> 24) & 1; 126 return (RE.r_word1 >> 7) & 1; 127 } 128 129 static bool 130 getScatteredRelocationPCRel(const MachOObjectFile *O, 131 const MachO::any_relocation_info &RE) { 132 return (RE.r_word0 >> 30) & 1; 133 } 134 135 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 136 const MachO::any_relocation_info &RE) { 137 if (O->isLittleEndian()) 138 return (RE.r_word1 >> 25) & 3; 139 return (RE.r_word1 >> 5) & 3; 140 } 141 142 static unsigned 143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 144 return (RE.r_word0 >> 28) & 3; 145 } 146 147 static unsigned getPlainRelocationType(const MachOObjectFile *O, 148 const MachO::any_relocation_info &RE) { 149 if (O->isLittleEndian()) 150 return RE.r_word1 >> 28; 151 return RE.r_word1 & 0xf; 152 } 153 154 static uint32_t getSectionFlags(const MachOObjectFile *O, 155 DataRefImpl Sec) { 156 if (O->is64Bit()) { 157 MachO::section_64 Sect = O->getSection64(Sec); 158 return Sect.flags; 159 } 160 MachO::section Sect = O->getSection(Sec); 161 return Sect.flags; 162 } 163 164 static ErrorOr<MachOObjectFile::LoadCommandInfo> 165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) { 166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr); 167 if (!CmdOrErr) 168 return CmdOrErr.getError(); 169 if (CmdOrErr->cmdsize < 8) 170 return object_error::macho_small_load_command; 171 MachOObjectFile::LoadCommandInfo Load; 172 Load.Ptr = Ptr; 173 Load.C = CmdOrErr.get(); 174 return Load; 175 } 176 177 static ErrorOr<MachOObjectFile::LoadCommandInfo> 178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) { 179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 180 : sizeof(MachO::mach_header); 181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize)); 182 } 183 184 static ErrorOr<MachOObjectFile::LoadCommandInfo> 185 getNextLoadCommandInfo(const MachOObjectFile *Obj, 186 const MachOObjectFile::LoadCommandInfo &L) { 187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize); 188 } 189 190 template <typename T> 191 static void parseHeader(const MachOObjectFile *Obj, T &Header, 192 std::error_code &EC) { 193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)); 194 if (HeaderOrErr) 195 Header = HeaderOrErr.get(); 196 else 197 EC = HeaderOrErr.getError(); 198 } 199 200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all 201 // sections to \param Sections, and optionally sets 202 // \param IsPageZeroSegment to true. 203 template <typename SegmentCmd> 204 static std::error_code parseSegmentLoadCommand( 205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, 206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) { 207 const unsigned SegmentLoadSize = sizeof(SegmentCmd); 208 if (Load.C.cmdsize < SegmentLoadSize) 209 return object_error::macho_load_segment_too_small; 210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr); 211 if (!SegOrErr) 212 return SegOrErr.getError(); 213 SegmentCmd S = SegOrErr.get(); 214 const unsigned SectionSize = 215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section); 216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || 217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) 218 return object_error::macho_load_segment_too_many_sections; 219 for (unsigned J = 0; J < S.nsects; ++J) { 220 const char *Sec = getSectionPtr(Obj, Load, J); 221 Sections.push_back(Sec); 222 } 223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); 224 return std::error_code(); 225 } 226 227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 228 bool Is64bits, std::error_code &EC) 229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 233 HasPageZeroSegment(false) { 234 if (is64Bit()) 235 parseHeader(this, Header64, EC); 236 else 237 parseHeader(this, Header, EC); 238 if (EC) 239 return; 240 241 uint32_t LoadCommandCount = getHeader().ncmds; 242 if (LoadCommandCount == 0) 243 return; 244 245 auto LoadOrErr = getFirstLoadCommandInfo(this); 246 if (!LoadOrErr) { 247 EC = LoadOrErr.getError(); 248 return; 249 } 250 LoadCommandInfo Load = LoadOrErr.get(); 251 for (unsigned I = 0; I < LoadCommandCount; ++I) { 252 LoadCommands.push_back(Load); 253 if (Load.C.cmd == MachO::LC_SYMTAB) { 254 // Multiple symbol tables 255 if (SymtabLoadCmd) { 256 EC = object_error::parse_failed; 257 return; 258 } 259 SymtabLoadCmd = Load.Ptr; 260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 261 // Multiple dynamic symbol tables 262 if (DysymtabLoadCmd) { 263 EC = object_error::parse_failed; 264 return; 265 } 266 DysymtabLoadCmd = Load.Ptr; 267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 268 // Multiple data in code tables 269 if (DataInCodeLoadCmd) { 270 EC = object_error::parse_failed; 271 return; 272 } 273 DataInCodeLoadCmd = Load.Ptr; 274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 275 // Multiple linker optimization hint tables 276 if (LinkOptHintsLoadCmd) { 277 EC = object_error::parse_failed; 278 return; 279 } 280 LinkOptHintsLoadCmd = Load.Ptr; 281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO || 282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 283 // Multiple dyldinfo load commands 284 if (DyldInfoLoadCmd) { 285 EC = object_error::parse_failed; 286 return; 287 } 288 DyldInfoLoadCmd = Load.Ptr; 289 } else if (Load.C.cmd == MachO::LC_UUID) { 290 // Multiple UUID load commands 291 if (UuidLoadCmd) { 292 EC = object_error::parse_failed; 293 return; 294 } 295 UuidLoadCmd = Load.Ptr; 296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>( 298 this, Load, Sections, HasPageZeroSegment))) 299 return; 300 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>( 302 this, Load, Sections, HasPageZeroSegment))) 303 return; 304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 309 Libraries.push_back(Load.Ptr); 310 } 311 if (I < LoadCommandCount - 1) { 312 auto LoadOrErr = getNextLoadCommandInfo(this, Load); 313 if (!LoadOrErr) { 314 EC = LoadOrErr.getError(); 315 return; 316 } 317 Load = LoadOrErr.get(); 318 } 319 } 320 assert(LoadCommands.size() == LoadCommandCount); 321 } 322 323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 324 unsigned SymbolTableEntrySize = is64Bit() ? 325 sizeof(MachO::nlist_64) : 326 sizeof(MachO::nlist); 327 Symb.p += SymbolTableEntrySize; 328 } 329 330 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 331 StringRef &Res) const { 332 StringRef StringTable = getStringTableData(); 333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 334 const char *Start = &StringTable.data()[Entry.n_strx]; 335 if (Start < getData().begin() || Start >= getData().end()) 336 report_fatal_error( 337 "Symbol name entry points before beginning or past end of file."); 338 Res = StringRef(Start); 339 return std::error_code(); 340 } 341 342 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 343 DataRefImpl DRI = Sec.getRawDataRefImpl(); 344 uint32_t Flags = getSectionFlags(this, DRI); 345 return Flags & MachO::SECTION_TYPE; 346 } 347 348 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 349 if (is64Bit()) { 350 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 351 return Entry.n_value; 352 } 353 MachO::nlist Entry = getSymbolTableEntry(Sym); 354 return Entry.n_value; 355 } 356 357 // getIndirectName() returns the name of the alias'ed symbol who's string table 358 // index is in the n_value field. 359 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 360 StringRef &Res) const { 361 StringRef StringTable = getStringTableData(); 362 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 363 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 364 return object_error::parse_failed; 365 uint64_t NValue = getNValue(Symb); 366 if (NValue >= StringTable.size()) 367 return object_error::parse_failed; 368 const char *Start = &StringTable.data()[NValue]; 369 Res = StringRef(Start); 370 return std::error_code(); 371 } 372 373 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const { 374 uint64_t NValue = getNValue(Sym); 375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym); 376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) 377 return UnknownAddress; 378 return NValue; 379 } 380 381 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym, 382 uint64_t &Res) const { 383 Res = getSymbolValue(Sym); 384 return std::error_code(); 385 } 386 387 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 388 uint32_t flags = getSymbolFlags(DRI); 389 if (flags & SymbolRef::SF_Common) { 390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 391 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 392 } 393 return 0; 394 } 395 396 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 397 uint64_t Value; 398 getSymbolAddress(DRI, Value); 399 return Value; 400 } 401 402 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 403 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 404 uint8_t n_type = Entry.n_type; 405 406 // If this is a STAB debugging symbol, we can do nothing more. 407 if (n_type & MachO::N_STAB) 408 return SymbolRef::ST_Debug; 409 410 switch (n_type & MachO::N_TYPE) { 411 case MachO::N_UNDF : 412 return SymbolRef::ST_Unknown; 413 case MachO::N_SECT : 414 return SymbolRef::ST_Function; 415 } 416 return SymbolRef::ST_Other; 417 } 418 419 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 420 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 421 422 uint8_t MachOType = Entry.n_type; 423 uint16_t MachOFlags = Entry.n_desc; 424 425 uint32_t Result = SymbolRef::SF_None; 426 427 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 428 Result |= SymbolRef::SF_Undefined; 429 430 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 431 Result |= SymbolRef::SF_Indirect; 432 433 if (MachOType & MachO::N_STAB) 434 Result |= SymbolRef::SF_FormatSpecific; 435 436 if (MachOType & MachO::N_EXT) { 437 Result |= SymbolRef::SF_Global; 438 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 439 uint64_t Value; 440 getSymbolAddress(DRI, Value); 441 if (Value && Value != UnknownAddress) 442 Result |= SymbolRef::SF_Common; 443 } 444 445 if (!(MachOType & MachO::N_PEXT)) 446 Result |= SymbolRef::SF_Exported; 447 } 448 449 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 450 Result |= SymbolRef::SF_Weak; 451 452 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 453 Result |= SymbolRef::SF_Thumb; 454 455 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 456 Result |= SymbolRef::SF_Absolute; 457 458 return Result; 459 } 460 461 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 462 section_iterator &Res) const { 463 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 464 uint8_t index = Entry.n_sect; 465 466 if (index == 0) { 467 Res = section_end(); 468 } else { 469 DataRefImpl DRI; 470 DRI.d.a = index - 1; 471 if (DRI.d.a >= Sections.size()) 472 report_fatal_error("getSymbolSection: Invalid section index."); 473 Res = section_iterator(SectionRef(DRI, this)); 474 } 475 476 return std::error_code(); 477 } 478 479 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 480 MachO::nlist_base Entry = 481 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 482 return Entry.n_sect - 1; 483 } 484 485 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 486 Sec.d.a++; 487 } 488 489 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 490 StringRef &Result) const { 491 ArrayRef<char> Raw = getSectionRawName(Sec); 492 Result = parseSegmentOrSectionName(Raw.data()); 493 return std::error_code(); 494 } 495 496 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 497 if (is64Bit()) 498 return getSection64(Sec).addr; 499 return getSection(Sec).addr; 500 } 501 502 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 503 if (is64Bit()) 504 return getSection64(Sec).size; 505 return getSection(Sec).size; 506 } 507 508 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 509 StringRef &Res) const { 510 uint32_t Offset; 511 uint64_t Size; 512 513 if (is64Bit()) { 514 MachO::section_64 Sect = getSection64(Sec); 515 Offset = Sect.offset; 516 Size = Sect.size; 517 } else { 518 MachO::section Sect = getSection(Sec); 519 Offset = Sect.offset; 520 Size = Sect.size; 521 } 522 523 Res = this->getData().substr(Offset, Size); 524 return std::error_code(); 525 } 526 527 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 528 uint32_t Align; 529 if (is64Bit()) { 530 MachO::section_64 Sect = getSection64(Sec); 531 Align = Sect.align; 532 } else { 533 MachO::section Sect = getSection(Sec); 534 Align = Sect.align; 535 } 536 537 return uint64_t(1) << Align; 538 } 539 540 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 541 uint32_t Flags = getSectionFlags(this, Sec); 542 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 543 } 544 545 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 546 uint32_t Flags = getSectionFlags(this, Sec); 547 unsigned SectionType = Flags & MachO::SECTION_TYPE; 548 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 549 !(SectionType == MachO::S_ZEROFILL || 550 SectionType == MachO::S_GB_ZEROFILL); 551 } 552 553 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 554 uint32_t Flags = getSectionFlags(this, Sec); 555 unsigned SectionType = Flags & MachO::SECTION_TYPE; 556 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 557 (SectionType == MachO::S_ZEROFILL || 558 SectionType == MachO::S_GB_ZEROFILL); 559 } 560 561 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 562 return Sec.getRawDataRefImpl().d.a; 563 } 564 565 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 566 // FIXME: Unimplemented. 567 return false; 568 } 569 570 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 571 DataRefImpl Ret; 572 Ret.d.a = Sec.d.a; 573 Ret.d.b = 0; 574 return relocation_iterator(RelocationRef(Ret, this)); 575 } 576 577 relocation_iterator 578 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 579 uint32_t Num; 580 if (is64Bit()) { 581 MachO::section_64 Sect = getSection64(Sec); 582 Num = Sect.nreloc; 583 } else { 584 MachO::section Sect = getSection(Sec); 585 Num = Sect.nreloc; 586 } 587 588 DataRefImpl Ret; 589 Ret.d.a = Sec.d.a; 590 Ret.d.b = Num; 591 return relocation_iterator(RelocationRef(Ret, this)); 592 } 593 594 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 595 ++Rel.d.b; 596 } 597 598 ErrorOr<uint64_t> MachOObjectFile::getRelocationAddress(DataRefImpl Rel) const { 599 uint64_t Offset = getRelocationOffset(Rel); 600 601 DataRefImpl Sec; 602 Sec.d.a = Rel.d.a; 603 uint64_t SecAddress = getSectionAddress(Sec); 604 return SecAddress + Offset; 605 } 606 607 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 608 assert(getHeader().filetype == MachO::MH_OBJECT && 609 "Only implemented for MH_OBJECT"); 610 MachO::any_relocation_info RE = getRelocation(Rel); 611 return getAnyRelocationAddress(RE); 612 } 613 614 symbol_iterator 615 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 616 MachO::any_relocation_info RE = getRelocation(Rel); 617 if (isRelocationScattered(RE)) 618 return symbol_end(); 619 620 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 621 bool isExtern = getPlainRelocationExternal(RE); 622 if (!isExtern) 623 return symbol_end(); 624 625 MachO::symtab_command S = getSymtabLoadCommand(); 626 unsigned SymbolTableEntrySize = is64Bit() ? 627 sizeof(MachO::nlist_64) : 628 sizeof(MachO::nlist); 629 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 630 DataRefImpl Sym; 631 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 632 return symbol_iterator(SymbolRef(Sym, this)); 633 } 634 635 section_iterator 636 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 637 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 638 } 639 640 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 641 MachO::any_relocation_info RE = getRelocation(Rel); 642 return getAnyRelocationType(RE); 643 } 644 645 void MachOObjectFile::getRelocationTypeName( 646 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 647 StringRef res; 648 uint64_t RType = getRelocationType(Rel); 649 650 unsigned Arch = this->getArch(); 651 652 switch (Arch) { 653 case Triple::x86: { 654 static const char *const Table[] = { 655 "GENERIC_RELOC_VANILLA", 656 "GENERIC_RELOC_PAIR", 657 "GENERIC_RELOC_SECTDIFF", 658 "GENERIC_RELOC_PB_LA_PTR", 659 "GENERIC_RELOC_LOCAL_SECTDIFF", 660 "GENERIC_RELOC_TLV" }; 661 662 if (RType > 5) 663 res = "Unknown"; 664 else 665 res = Table[RType]; 666 break; 667 } 668 case Triple::x86_64: { 669 static const char *const Table[] = { 670 "X86_64_RELOC_UNSIGNED", 671 "X86_64_RELOC_SIGNED", 672 "X86_64_RELOC_BRANCH", 673 "X86_64_RELOC_GOT_LOAD", 674 "X86_64_RELOC_GOT", 675 "X86_64_RELOC_SUBTRACTOR", 676 "X86_64_RELOC_SIGNED_1", 677 "X86_64_RELOC_SIGNED_2", 678 "X86_64_RELOC_SIGNED_4", 679 "X86_64_RELOC_TLV" }; 680 681 if (RType > 9) 682 res = "Unknown"; 683 else 684 res = Table[RType]; 685 break; 686 } 687 case Triple::arm: { 688 static const char *const Table[] = { 689 "ARM_RELOC_VANILLA", 690 "ARM_RELOC_PAIR", 691 "ARM_RELOC_SECTDIFF", 692 "ARM_RELOC_LOCAL_SECTDIFF", 693 "ARM_RELOC_PB_LA_PTR", 694 "ARM_RELOC_BR24", 695 "ARM_THUMB_RELOC_BR22", 696 "ARM_THUMB_32BIT_BRANCH", 697 "ARM_RELOC_HALF", 698 "ARM_RELOC_HALF_SECTDIFF" }; 699 700 if (RType > 9) 701 res = "Unknown"; 702 else 703 res = Table[RType]; 704 break; 705 } 706 case Triple::aarch64: { 707 static const char *const Table[] = { 708 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 709 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 710 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 711 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 712 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 713 "ARM64_RELOC_ADDEND" 714 }; 715 716 if (RType >= array_lengthof(Table)) 717 res = "Unknown"; 718 else 719 res = Table[RType]; 720 break; 721 } 722 case Triple::ppc: { 723 static const char *const Table[] = { 724 "PPC_RELOC_VANILLA", 725 "PPC_RELOC_PAIR", 726 "PPC_RELOC_BR14", 727 "PPC_RELOC_BR24", 728 "PPC_RELOC_HI16", 729 "PPC_RELOC_LO16", 730 "PPC_RELOC_HA16", 731 "PPC_RELOC_LO14", 732 "PPC_RELOC_SECTDIFF", 733 "PPC_RELOC_PB_LA_PTR", 734 "PPC_RELOC_HI16_SECTDIFF", 735 "PPC_RELOC_LO16_SECTDIFF", 736 "PPC_RELOC_HA16_SECTDIFF", 737 "PPC_RELOC_JBSR", 738 "PPC_RELOC_LO14_SECTDIFF", 739 "PPC_RELOC_LOCAL_SECTDIFF" }; 740 741 if (RType > 15) 742 res = "Unknown"; 743 else 744 res = Table[RType]; 745 break; 746 } 747 case Triple::UnknownArch: 748 res = "Unknown"; 749 break; 750 } 751 Result.append(res.begin(), res.end()); 752 } 753 754 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 755 MachO::any_relocation_info RE = getRelocation(Rel); 756 return getAnyRelocationLength(RE); 757 } 758 759 // 760 // guessLibraryShortName() is passed a name of a dynamic library and returns a 761 // guess on what the short name is. Then name is returned as a substring of the 762 // StringRef Name passed in. The name of the dynamic library is recognized as 763 // a framework if it has one of the two following forms: 764 // Foo.framework/Versions/A/Foo 765 // Foo.framework/Foo 766 // Where A and Foo can be any string. And may contain a trailing suffix 767 // starting with an underbar. If the Name is recognized as a framework then 768 // isFramework is set to true else it is set to false. If the Name has a 769 // suffix then Suffix is set to the substring in Name that contains the suffix 770 // else it is set to a NULL StringRef. 771 // 772 // The Name of the dynamic library is recognized as a library name if it has 773 // one of the two following forms: 774 // libFoo.A.dylib 775 // libFoo.dylib 776 // The library may have a suffix trailing the name Foo of the form: 777 // libFoo_profile.A.dylib 778 // libFoo_profile.dylib 779 // 780 // The Name of the dynamic library is also recognized as a library name if it 781 // has the following form: 782 // Foo.qtx 783 // 784 // If the Name of the dynamic library is none of the forms above then a NULL 785 // StringRef is returned. 786 // 787 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 788 bool &isFramework, 789 StringRef &Suffix) { 790 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 791 size_t a, b, c, d, Idx; 792 793 isFramework = false; 794 Suffix = StringRef(); 795 796 // Pull off the last component and make Foo point to it 797 a = Name.rfind('/'); 798 if (a == Name.npos || a == 0) 799 goto guess_library; 800 Foo = Name.slice(a+1, Name.npos); 801 802 // Look for a suffix starting with a '_' 803 Idx = Foo.rfind('_'); 804 if (Idx != Foo.npos && Foo.size() >= 2) { 805 Suffix = Foo.slice(Idx, Foo.npos); 806 Foo = Foo.slice(0, Idx); 807 } 808 809 // First look for the form Foo.framework/Foo 810 b = Name.rfind('/', a); 811 if (b == Name.npos) 812 Idx = 0; 813 else 814 Idx = b+1; 815 F = Name.slice(Idx, Idx + Foo.size()); 816 DotFramework = Name.slice(Idx + Foo.size(), 817 Idx + Foo.size() + sizeof(".framework/")-1); 818 if (F == Foo && DotFramework == ".framework/") { 819 isFramework = true; 820 return Foo; 821 } 822 823 // Next look for the form Foo.framework/Versions/A/Foo 824 if (b == Name.npos) 825 goto guess_library; 826 c = Name.rfind('/', b); 827 if (c == Name.npos || c == 0) 828 goto guess_library; 829 V = Name.slice(c+1, Name.npos); 830 if (!V.startswith("Versions/")) 831 goto guess_library; 832 d = Name.rfind('/', c); 833 if (d == Name.npos) 834 Idx = 0; 835 else 836 Idx = d+1; 837 F = Name.slice(Idx, Idx + Foo.size()); 838 DotFramework = Name.slice(Idx + Foo.size(), 839 Idx + Foo.size() + sizeof(".framework/")-1); 840 if (F == Foo && DotFramework == ".framework/") { 841 isFramework = true; 842 return Foo; 843 } 844 845 guess_library: 846 // pull off the suffix after the "." and make a point to it 847 a = Name.rfind('.'); 848 if (a == Name.npos || a == 0) 849 return StringRef(); 850 Dylib = Name.slice(a, Name.npos); 851 if (Dylib != ".dylib") 852 goto guess_qtx; 853 854 // First pull off the version letter for the form Foo.A.dylib if any. 855 if (a >= 3) { 856 Dot = Name.slice(a-2, a-1); 857 if (Dot == ".") 858 a = a - 2; 859 } 860 861 b = Name.rfind('/', a); 862 if (b == Name.npos) 863 b = 0; 864 else 865 b = b+1; 866 // ignore any suffix after an underbar like Foo_profile.A.dylib 867 Idx = Name.find('_', b); 868 if (Idx != Name.npos && Idx != b) { 869 Lib = Name.slice(b, Idx); 870 Suffix = Name.slice(Idx, a); 871 } 872 else 873 Lib = Name.slice(b, a); 874 // There are incorrect library names of the form: 875 // libATS.A_profile.dylib so check for these. 876 if (Lib.size() >= 3) { 877 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 878 if (Dot == ".") 879 Lib = Lib.slice(0, Lib.size()-2); 880 } 881 return Lib; 882 883 guess_qtx: 884 Qtx = Name.slice(a, Name.npos); 885 if (Qtx != ".qtx") 886 return StringRef(); 887 b = Name.rfind('/', a); 888 if (b == Name.npos) 889 Lib = Name.slice(0, a); 890 else 891 Lib = Name.slice(b+1, a); 892 // There are library names of the form: QT.A.qtx so check for these. 893 if (Lib.size() >= 3) { 894 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 895 if (Dot == ".") 896 Lib = Lib.slice(0, Lib.size()-2); 897 } 898 return Lib; 899 } 900 901 // getLibraryShortNameByIndex() is used to get the short name of the library 902 // for an undefined symbol in a linked Mach-O binary that was linked with the 903 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 904 // It is passed the index (0 - based) of the library as translated from 905 // GET_LIBRARY_ORDINAL (1 - based). 906 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 907 StringRef &Res) const { 908 if (Index >= Libraries.size()) 909 return object_error::parse_failed; 910 911 // If the cache of LibrariesShortNames is not built up do that first for 912 // all the Libraries. 913 if (LibrariesShortNames.size() == 0) { 914 for (unsigned i = 0; i < Libraries.size(); i++) { 915 MachO::dylib_command D = 916 getStruct<MachO::dylib_command>(this, Libraries[i]); 917 if (D.dylib.name >= D.cmdsize) 918 return object_error::parse_failed; 919 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 920 StringRef Name = StringRef(P); 921 if (D.dylib.name+Name.size() >= D.cmdsize) 922 return object_error::parse_failed; 923 StringRef Suffix; 924 bool isFramework; 925 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 926 if (shortName.empty()) 927 LibrariesShortNames.push_back(Name); 928 else 929 LibrariesShortNames.push_back(shortName); 930 } 931 } 932 933 Res = LibrariesShortNames[Index]; 934 return std::error_code(); 935 } 936 937 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 938 return getSymbolByIndex(0); 939 } 940 941 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 942 DataRefImpl DRI; 943 if (!SymtabLoadCmd) 944 return basic_symbol_iterator(SymbolRef(DRI, this)); 945 946 MachO::symtab_command Symtab = getSymtabLoadCommand(); 947 unsigned SymbolTableEntrySize = is64Bit() ? 948 sizeof(MachO::nlist_64) : 949 sizeof(MachO::nlist); 950 unsigned Offset = Symtab.symoff + 951 Symtab.nsyms * SymbolTableEntrySize; 952 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 953 return basic_symbol_iterator(SymbolRef(DRI, this)); 954 } 955 956 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 957 DataRefImpl DRI; 958 if (!SymtabLoadCmd) 959 return basic_symbol_iterator(SymbolRef(DRI, this)); 960 961 MachO::symtab_command Symtab = getSymtabLoadCommand(); 962 if (Index >= Symtab.nsyms) 963 report_fatal_error("Requested symbol index is out of range."); 964 unsigned SymbolTableEntrySize = 965 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 966 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 967 DRI.p += Index * SymbolTableEntrySize; 968 return basic_symbol_iterator(SymbolRef(DRI, this)); 969 } 970 971 section_iterator MachOObjectFile::section_begin() const { 972 DataRefImpl DRI; 973 return section_iterator(SectionRef(DRI, this)); 974 } 975 976 section_iterator MachOObjectFile::section_end() const { 977 DataRefImpl DRI; 978 DRI.d.a = Sections.size(); 979 return section_iterator(SectionRef(DRI, this)); 980 } 981 982 uint8_t MachOObjectFile::getBytesInAddress() const { 983 return is64Bit() ? 8 : 4; 984 } 985 986 StringRef MachOObjectFile::getFileFormatName() const { 987 unsigned CPUType = getCPUType(this); 988 if (!is64Bit()) { 989 switch (CPUType) { 990 case llvm::MachO::CPU_TYPE_I386: 991 return "Mach-O 32-bit i386"; 992 case llvm::MachO::CPU_TYPE_ARM: 993 return "Mach-O arm"; 994 case llvm::MachO::CPU_TYPE_POWERPC: 995 return "Mach-O 32-bit ppc"; 996 default: 997 return "Mach-O 32-bit unknown"; 998 } 999 } 1000 1001 switch (CPUType) { 1002 case llvm::MachO::CPU_TYPE_X86_64: 1003 return "Mach-O 64-bit x86-64"; 1004 case llvm::MachO::CPU_TYPE_ARM64: 1005 return "Mach-O arm64"; 1006 case llvm::MachO::CPU_TYPE_POWERPC64: 1007 return "Mach-O 64-bit ppc64"; 1008 default: 1009 return "Mach-O 64-bit unknown"; 1010 } 1011 } 1012 1013 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1014 switch (CPUType) { 1015 case llvm::MachO::CPU_TYPE_I386: 1016 return Triple::x86; 1017 case llvm::MachO::CPU_TYPE_X86_64: 1018 return Triple::x86_64; 1019 case llvm::MachO::CPU_TYPE_ARM: 1020 return Triple::arm; 1021 case llvm::MachO::CPU_TYPE_ARM64: 1022 return Triple::aarch64; 1023 case llvm::MachO::CPU_TYPE_POWERPC: 1024 return Triple::ppc; 1025 case llvm::MachO::CPU_TYPE_POWERPC64: 1026 return Triple::ppc64; 1027 default: 1028 return Triple::UnknownArch; 1029 } 1030 } 1031 1032 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 1033 const char **McpuDefault) { 1034 if (McpuDefault) 1035 *McpuDefault = nullptr; 1036 1037 switch (CPUType) { 1038 case MachO::CPU_TYPE_I386: 1039 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1040 case MachO::CPU_SUBTYPE_I386_ALL: 1041 return Triple("i386-apple-darwin"); 1042 default: 1043 return Triple(); 1044 } 1045 case MachO::CPU_TYPE_X86_64: 1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1047 case MachO::CPU_SUBTYPE_X86_64_ALL: 1048 return Triple("x86_64-apple-darwin"); 1049 case MachO::CPU_SUBTYPE_X86_64_H: 1050 return Triple("x86_64h-apple-darwin"); 1051 default: 1052 return Triple(); 1053 } 1054 case MachO::CPU_TYPE_ARM: 1055 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1056 case MachO::CPU_SUBTYPE_ARM_V4T: 1057 return Triple("armv4t-apple-darwin"); 1058 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1059 return Triple("armv5e-apple-darwin"); 1060 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1061 return Triple("xscale-apple-darwin"); 1062 case MachO::CPU_SUBTYPE_ARM_V6: 1063 return Triple("armv6-apple-darwin"); 1064 case MachO::CPU_SUBTYPE_ARM_V6M: 1065 if (McpuDefault) 1066 *McpuDefault = "cortex-m0"; 1067 return Triple("armv6m-apple-darwin"); 1068 case MachO::CPU_SUBTYPE_ARM_V7: 1069 return Triple("armv7-apple-darwin"); 1070 case MachO::CPU_SUBTYPE_ARM_V7EM: 1071 if (McpuDefault) 1072 *McpuDefault = "cortex-m4"; 1073 return Triple("armv7em-apple-darwin"); 1074 case MachO::CPU_SUBTYPE_ARM_V7K: 1075 return Triple("armv7k-apple-darwin"); 1076 case MachO::CPU_SUBTYPE_ARM_V7M: 1077 if (McpuDefault) 1078 *McpuDefault = "cortex-m3"; 1079 return Triple("armv7m-apple-darwin"); 1080 case MachO::CPU_SUBTYPE_ARM_V7S: 1081 return Triple("armv7s-apple-darwin"); 1082 default: 1083 return Triple(); 1084 } 1085 case MachO::CPU_TYPE_ARM64: 1086 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1087 case MachO::CPU_SUBTYPE_ARM64_ALL: 1088 return Triple("arm64-apple-darwin"); 1089 default: 1090 return Triple(); 1091 } 1092 case MachO::CPU_TYPE_POWERPC: 1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1094 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1095 return Triple("ppc-apple-darwin"); 1096 default: 1097 return Triple(); 1098 } 1099 case MachO::CPU_TYPE_POWERPC64: 1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1101 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1102 return Triple("ppc64-apple-darwin"); 1103 default: 1104 return Triple(); 1105 } 1106 default: 1107 return Triple(); 1108 } 1109 } 1110 1111 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, 1112 const char **McpuDefault) { 1113 if (McpuDefault) 1114 *McpuDefault = nullptr; 1115 1116 switch (CPUType) { 1117 case MachO::CPU_TYPE_ARM: 1118 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1119 case MachO::CPU_SUBTYPE_ARM_V4T: 1120 return Triple("thumbv4t-apple-darwin"); 1121 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1122 return Triple("thumbv5e-apple-darwin"); 1123 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1124 return Triple("xscale-apple-darwin"); 1125 case MachO::CPU_SUBTYPE_ARM_V6: 1126 return Triple("thumbv6-apple-darwin"); 1127 case MachO::CPU_SUBTYPE_ARM_V6M: 1128 if (McpuDefault) 1129 *McpuDefault = "cortex-m0"; 1130 return Triple("thumbv6m-apple-darwin"); 1131 case MachO::CPU_SUBTYPE_ARM_V7: 1132 return Triple("thumbv7-apple-darwin"); 1133 case MachO::CPU_SUBTYPE_ARM_V7EM: 1134 if (McpuDefault) 1135 *McpuDefault = "cortex-m4"; 1136 return Triple("thumbv7em-apple-darwin"); 1137 case MachO::CPU_SUBTYPE_ARM_V7K: 1138 return Triple("thumbv7k-apple-darwin"); 1139 case MachO::CPU_SUBTYPE_ARM_V7M: 1140 if (McpuDefault) 1141 *McpuDefault = "cortex-m3"; 1142 return Triple("thumbv7m-apple-darwin"); 1143 case MachO::CPU_SUBTYPE_ARM_V7S: 1144 return Triple("thumbv7s-apple-darwin"); 1145 default: 1146 return Triple(); 1147 } 1148 default: 1149 return Triple(); 1150 } 1151 } 1152 1153 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 1154 const char **McpuDefault, 1155 Triple *ThumbTriple) { 1156 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); 1157 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, 1158 McpuDefault); 1159 return T; 1160 } 1161 1162 Triple MachOObjectFile::getHostArch() { 1163 return Triple(sys::getDefaultTargetTriple()); 1164 } 1165 1166 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1167 return StringSwitch<bool>(ArchFlag) 1168 .Case("i386", true) 1169 .Case("x86_64", true) 1170 .Case("x86_64h", true) 1171 .Case("armv4t", true) 1172 .Case("arm", true) 1173 .Case("armv5e", true) 1174 .Case("armv6", true) 1175 .Case("armv6m", true) 1176 .Case("armv7", true) 1177 .Case("armv7em", true) 1178 .Case("armv7k", true) 1179 .Case("armv7m", true) 1180 .Case("armv7s", true) 1181 .Case("arm64", true) 1182 .Case("ppc", true) 1183 .Case("ppc64", true) 1184 .Default(false); 1185 } 1186 1187 unsigned MachOObjectFile::getArch() const { 1188 return getArch(getCPUType(this)); 1189 } 1190 1191 Triple MachOObjectFile::getArch(const char **McpuDefault, 1192 Triple *ThumbTriple) const { 1193 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault); 1194 return getArch(Header.cputype, Header.cpusubtype, McpuDefault); 1195 } 1196 1197 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1198 DataRefImpl DRI; 1199 DRI.d.a = Index; 1200 return section_rel_begin(DRI); 1201 } 1202 1203 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1204 DataRefImpl DRI; 1205 DRI.d.a = Index; 1206 return section_rel_end(DRI); 1207 } 1208 1209 dice_iterator MachOObjectFile::begin_dices() const { 1210 DataRefImpl DRI; 1211 if (!DataInCodeLoadCmd) 1212 return dice_iterator(DiceRef(DRI, this)); 1213 1214 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1215 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1216 return dice_iterator(DiceRef(DRI, this)); 1217 } 1218 1219 dice_iterator MachOObjectFile::end_dices() const { 1220 DataRefImpl DRI; 1221 if (!DataInCodeLoadCmd) 1222 return dice_iterator(DiceRef(DRI, this)); 1223 1224 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1225 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1226 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1227 return dice_iterator(DiceRef(DRI, this)); 1228 } 1229 1230 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 1231 : Trie(T), Malformed(false), Done(false) { } 1232 1233 void ExportEntry::moveToFirst() { 1234 pushNode(0); 1235 pushDownUntilBottom(); 1236 } 1237 1238 void ExportEntry::moveToEnd() { 1239 Stack.clear(); 1240 Done = true; 1241 } 1242 1243 bool ExportEntry::operator==(const ExportEntry &Other) const { 1244 // Common case, one at end, other iterating from begin. 1245 if (Done || Other.Done) 1246 return (Done == Other.Done); 1247 // Not equal if different stack sizes. 1248 if (Stack.size() != Other.Stack.size()) 1249 return false; 1250 // Not equal if different cumulative strings. 1251 if (!CumulativeString.equals(Other.CumulativeString)) 1252 return false; 1253 // Equal if all nodes in both stacks match. 1254 for (unsigned i=0; i < Stack.size(); ++i) { 1255 if (Stack[i].Start != Other.Stack[i].Start) 1256 return false; 1257 } 1258 return true; 1259 } 1260 1261 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 1262 unsigned Count; 1263 uint64_t Result = decodeULEB128(Ptr, &Count); 1264 Ptr += Count; 1265 if (Ptr > Trie.end()) { 1266 Ptr = Trie.end(); 1267 Malformed = true; 1268 } 1269 return Result; 1270 } 1271 1272 StringRef ExportEntry::name() const { 1273 return CumulativeString; 1274 } 1275 1276 uint64_t ExportEntry::flags() const { 1277 return Stack.back().Flags; 1278 } 1279 1280 uint64_t ExportEntry::address() const { 1281 return Stack.back().Address; 1282 } 1283 1284 uint64_t ExportEntry::other() const { 1285 return Stack.back().Other; 1286 } 1287 1288 StringRef ExportEntry::otherName() const { 1289 const char* ImportName = Stack.back().ImportName; 1290 if (ImportName) 1291 return StringRef(ImportName); 1292 return StringRef(); 1293 } 1294 1295 uint32_t ExportEntry::nodeOffset() const { 1296 return Stack.back().Start - Trie.begin(); 1297 } 1298 1299 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 1300 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 1301 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 1302 ParentStringLength(0), IsExportNode(false) { 1303 } 1304 1305 void ExportEntry::pushNode(uint64_t offset) { 1306 const uint8_t *Ptr = Trie.begin() + offset; 1307 NodeState State(Ptr); 1308 uint64_t ExportInfoSize = readULEB128(State.Current); 1309 State.IsExportNode = (ExportInfoSize != 0); 1310 const uint8_t* Children = State.Current + ExportInfoSize; 1311 if (State.IsExportNode) { 1312 State.Flags = readULEB128(State.Current); 1313 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 1314 State.Address = 0; 1315 State.Other = readULEB128(State.Current); // dylib ordinal 1316 State.ImportName = reinterpret_cast<const char*>(State.Current); 1317 } else { 1318 State.Address = readULEB128(State.Current); 1319 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 1320 State.Other = readULEB128(State.Current); 1321 } 1322 } 1323 State.ChildCount = *Children; 1324 State.Current = Children + 1; 1325 State.NextChildIndex = 0; 1326 State.ParentStringLength = CumulativeString.size(); 1327 Stack.push_back(State); 1328 } 1329 1330 void ExportEntry::pushDownUntilBottom() { 1331 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 1332 NodeState &Top = Stack.back(); 1333 CumulativeString.resize(Top.ParentStringLength); 1334 for (;*Top.Current != 0; Top.Current++) { 1335 char C = *Top.Current; 1336 CumulativeString.push_back(C); 1337 } 1338 Top.Current += 1; 1339 uint64_t childNodeIndex = readULEB128(Top.Current); 1340 Top.NextChildIndex += 1; 1341 pushNode(childNodeIndex); 1342 } 1343 if (!Stack.back().IsExportNode) { 1344 Malformed = true; 1345 moveToEnd(); 1346 } 1347 } 1348 1349 // We have a trie data structure and need a way to walk it that is compatible 1350 // with the C++ iterator model. The solution is a non-recursive depth first 1351 // traversal where the iterator contains a stack of parent nodes along with a 1352 // string that is the accumulation of all edge strings along the parent chain 1353 // to this point. 1354 // 1355 // There is one "export" node for each exported symbol. But because some 1356 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 1357 // node may have child nodes too. 1358 // 1359 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 1360 // child until hitting a node with no children (which is an export node or 1361 // else the trie is malformed). On the way down, each node is pushed on the 1362 // stack ivar. If there is no more ways down, it pops up one and tries to go 1363 // down a sibling path until a childless node is reached. 1364 void ExportEntry::moveNext() { 1365 if (Stack.empty() || !Stack.back().IsExportNode) { 1366 Malformed = true; 1367 moveToEnd(); 1368 return; 1369 } 1370 1371 Stack.pop_back(); 1372 while (!Stack.empty()) { 1373 NodeState &Top = Stack.back(); 1374 if (Top.NextChildIndex < Top.ChildCount) { 1375 pushDownUntilBottom(); 1376 // Now at the next export node. 1377 return; 1378 } else { 1379 if (Top.IsExportNode) { 1380 // This node has no children but is itself an export node. 1381 CumulativeString.resize(Top.ParentStringLength); 1382 return; 1383 } 1384 Stack.pop_back(); 1385 } 1386 } 1387 Done = true; 1388 } 1389 1390 iterator_range<export_iterator> 1391 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 1392 ExportEntry Start(Trie); 1393 if (Trie.size() == 0) 1394 Start.moveToEnd(); 1395 else 1396 Start.moveToFirst(); 1397 1398 ExportEntry Finish(Trie); 1399 Finish.moveToEnd(); 1400 1401 return iterator_range<export_iterator>(export_iterator(Start), 1402 export_iterator(Finish)); 1403 } 1404 1405 iterator_range<export_iterator> MachOObjectFile::exports() const { 1406 return exports(getDyldInfoExportsTrie()); 1407 } 1408 1409 1410 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 1411 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 1412 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 1413 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 1414 1415 void MachORebaseEntry::moveToFirst() { 1416 Ptr = Opcodes.begin(); 1417 moveNext(); 1418 } 1419 1420 void MachORebaseEntry::moveToEnd() { 1421 Ptr = Opcodes.end(); 1422 RemainingLoopCount = 0; 1423 Done = true; 1424 } 1425 1426 void MachORebaseEntry::moveNext() { 1427 // If in the middle of some loop, move to next rebasing in loop. 1428 SegmentOffset += AdvanceAmount; 1429 if (RemainingLoopCount) { 1430 --RemainingLoopCount; 1431 return; 1432 } 1433 if (Ptr == Opcodes.end()) { 1434 Done = true; 1435 return; 1436 } 1437 bool More = true; 1438 while (More && !Malformed) { 1439 // Parse next opcode and set up next loop. 1440 uint8_t Byte = *Ptr++; 1441 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 1442 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 1443 switch (Opcode) { 1444 case MachO::REBASE_OPCODE_DONE: 1445 More = false; 1446 Done = true; 1447 moveToEnd(); 1448 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 1449 break; 1450 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 1451 RebaseType = ImmValue; 1452 DEBUG_WITH_TYPE( 1453 "mach-o-rebase", 1454 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 1455 << "RebaseType=" << (int) RebaseType << "\n"); 1456 break; 1457 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 1458 SegmentIndex = ImmValue; 1459 SegmentOffset = readULEB128(); 1460 DEBUG_WITH_TYPE( 1461 "mach-o-rebase", 1462 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 1463 << "SegmentIndex=" << SegmentIndex << ", " 1464 << format("SegmentOffset=0x%06X", SegmentOffset) 1465 << "\n"); 1466 break; 1467 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 1468 SegmentOffset += readULEB128(); 1469 DEBUG_WITH_TYPE("mach-o-rebase", 1470 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 1471 << format("SegmentOffset=0x%06X", 1472 SegmentOffset) << "\n"); 1473 break; 1474 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 1475 SegmentOffset += ImmValue * PointerSize; 1476 DEBUG_WITH_TYPE("mach-o-rebase", 1477 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 1478 << format("SegmentOffset=0x%06X", 1479 SegmentOffset) << "\n"); 1480 break; 1481 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 1482 AdvanceAmount = PointerSize; 1483 RemainingLoopCount = ImmValue - 1; 1484 DEBUG_WITH_TYPE( 1485 "mach-o-rebase", 1486 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 1487 << format("SegmentOffset=0x%06X", SegmentOffset) 1488 << ", AdvanceAmount=" << AdvanceAmount 1489 << ", RemainingLoopCount=" << RemainingLoopCount 1490 << "\n"); 1491 return; 1492 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 1493 AdvanceAmount = PointerSize; 1494 RemainingLoopCount = readULEB128() - 1; 1495 DEBUG_WITH_TYPE( 1496 "mach-o-rebase", 1497 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 1498 << format("SegmentOffset=0x%06X", SegmentOffset) 1499 << ", AdvanceAmount=" << AdvanceAmount 1500 << ", RemainingLoopCount=" << RemainingLoopCount 1501 << "\n"); 1502 return; 1503 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 1504 AdvanceAmount = readULEB128() + PointerSize; 1505 RemainingLoopCount = 0; 1506 DEBUG_WITH_TYPE( 1507 "mach-o-rebase", 1508 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 1509 << format("SegmentOffset=0x%06X", SegmentOffset) 1510 << ", AdvanceAmount=" << AdvanceAmount 1511 << ", RemainingLoopCount=" << RemainingLoopCount 1512 << "\n"); 1513 return; 1514 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 1515 RemainingLoopCount = readULEB128() - 1; 1516 AdvanceAmount = readULEB128() + PointerSize; 1517 DEBUG_WITH_TYPE( 1518 "mach-o-rebase", 1519 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 1520 << format("SegmentOffset=0x%06X", SegmentOffset) 1521 << ", AdvanceAmount=" << AdvanceAmount 1522 << ", RemainingLoopCount=" << RemainingLoopCount 1523 << "\n"); 1524 return; 1525 default: 1526 Malformed = true; 1527 } 1528 } 1529 } 1530 1531 uint64_t MachORebaseEntry::readULEB128() { 1532 unsigned Count; 1533 uint64_t Result = decodeULEB128(Ptr, &Count); 1534 Ptr += Count; 1535 if (Ptr > Opcodes.end()) { 1536 Ptr = Opcodes.end(); 1537 Malformed = true; 1538 } 1539 return Result; 1540 } 1541 1542 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 1543 1544 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 1545 1546 StringRef MachORebaseEntry::typeName() const { 1547 switch (RebaseType) { 1548 case MachO::REBASE_TYPE_POINTER: 1549 return "pointer"; 1550 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 1551 return "text abs32"; 1552 case MachO::REBASE_TYPE_TEXT_PCREL32: 1553 return "text rel32"; 1554 } 1555 return "unknown"; 1556 } 1557 1558 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 1559 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 1560 return (Ptr == Other.Ptr) && 1561 (RemainingLoopCount == Other.RemainingLoopCount) && 1562 (Done == Other.Done); 1563 } 1564 1565 iterator_range<rebase_iterator> 1566 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 1567 MachORebaseEntry Start(Opcodes, is64); 1568 Start.moveToFirst(); 1569 1570 MachORebaseEntry Finish(Opcodes, is64); 1571 Finish.moveToEnd(); 1572 1573 return iterator_range<rebase_iterator>(rebase_iterator(Start), 1574 rebase_iterator(Finish)); 1575 } 1576 1577 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 1578 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 1579 } 1580 1581 1582 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, 1583 Kind BK) 1584 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 1585 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 1586 BindType(0), PointerSize(is64Bit ? 8 : 4), 1587 TableKind(BK), Malformed(false), Done(false) {} 1588 1589 void MachOBindEntry::moveToFirst() { 1590 Ptr = Opcodes.begin(); 1591 moveNext(); 1592 } 1593 1594 void MachOBindEntry::moveToEnd() { 1595 Ptr = Opcodes.end(); 1596 RemainingLoopCount = 0; 1597 Done = true; 1598 } 1599 1600 void MachOBindEntry::moveNext() { 1601 // If in the middle of some loop, move to next binding in loop. 1602 SegmentOffset += AdvanceAmount; 1603 if (RemainingLoopCount) { 1604 --RemainingLoopCount; 1605 return; 1606 } 1607 if (Ptr == Opcodes.end()) { 1608 Done = true; 1609 return; 1610 } 1611 bool More = true; 1612 while (More && !Malformed) { 1613 // Parse next opcode and set up next loop. 1614 uint8_t Byte = *Ptr++; 1615 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 1616 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 1617 int8_t SignExtended; 1618 const uint8_t *SymStart; 1619 switch (Opcode) { 1620 case MachO::BIND_OPCODE_DONE: 1621 if (TableKind == Kind::Lazy) { 1622 // Lazying bindings have a DONE opcode between entries. Need to ignore 1623 // it to advance to next entry. But need not if this is last entry. 1624 bool NotLastEntry = false; 1625 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 1626 if (*P) { 1627 NotLastEntry = true; 1628 } 1629 } 1630 if (NotLastEntry) 1631 break; 1632 } 1633 More = false; 1634 Done = true; 1635 moveToEnd(); 1636 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 1637 break; 1638 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 1639 Ordinal = ImmValue; 1640 DEBUG_WITH_TYPE( 1641 "mach-o-bind", 1642 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 1643 << "Ordinal=" << Ordinal << "\n"); 1644 break; 1645 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 1646 Ordinal = readULEB128(); 1647 DEBUG_WITH_TYPE( 1648 "mach-o-bind", 1649 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 1650 << "Ordinal=" << Ordinal << "\n"); 1651 break; 1652 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 1653 if (ImmValue) { 1654 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 1655 Ordinal = SignExtended; 1656 } else 1657 Ordinal = 0; 1658 DEBUG_WITH_TYPE( 1659 "mach-o-bind", 1660 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 1661 << "Ordinal=" << Ordinal << "\n"); 1662 break; 1663 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 1664 Flags = ImmValue; 1665 SymStart = Ptr; 1666 while (*Ptr) { 1667 ++Ptr; 1668 } 1669 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 1670 Ptr-SymStart); 1671 ++Ptr; 1672 DEBUG_WITH_TYPE( 1673 "mach-o-bind", 1674 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 1675 << "SymbolName=" << SymbolName << "\n"); 1676 if (TableKind == Kind::Weak) { 1677 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 1678 return; 1679 } 1680 break; 1681 case MachO::BIND_OPCODE_SET_TYPE_IMM: 1682 BindType = ImmValue; 1683 DEBUG_WITH_TYPE( 1684 "mach-o-bind", 1685 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 1686 << "BindType=" << (int)BindType << "\n"); 1687 break; 1688 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 1689 Addend = readSLEB128(); 1690 if (TableKind == Kind::Lazy) 1691 Malformed = true; 1692 DEBUG_WITH_TYPE( 1693 "mach-o-bind", 1694 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 1695 << "Addend=" << Addend << "\n"); 1696 break; 1697 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 1698 SegmentIndex = ImmValue; 1699 SegmentOffset = readULEB128(); 1700 DEBUG_WITH_TYPE( 1701 "mach-o-bind", 1702 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 1703 << "SegmentIndex=" << SegmentIndex << ", " 1704 << format("SegmentOffset=0x%06X", SegmentOffset) 1705 << "\n"); 1706 break; 1707 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 1708 SegmentOffset += readULEB128(); 1709 DEBUG_WITH_TYPE("mach-o-bind", 1710 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 1711 << format("SegmentOffset=0x%06X", 1712 SegmentOffset) << "\n"); 1713 break; 1714 case MachO::BIND_OPCODE_DO_BIND: 1715 AdvanceAmount = PointerSize; 1716 RemainingLoopCount = 0; 1717 DEBUG_WITH_TYPE("mach-o-bind", 1718 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 1719 << format("SegmentOffset=0x%06X", 1720 SegmentOffset) << "\n"); 1721 return; 1722 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 1723 AdvanceAmount = readULEB128() + PointerSize; 1724 RemainingLoopCount = 0; 1725 if (TableKind == Kind::Lazy) 1726 Malformed = true; 1727 DEBUG_WITH_TYPE( 1728 "mach-o-bind", 1729 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 1730 << format("SegmentOffset=0x%06X", SegmentOffset) 1731 << ", AdvanceAmount=" << AdvanceAmount 1732 << ", RemainingLoopCount=" << RemainingLoopCount 1733 << "\n"); 1734 return; 1735 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 1736 AdvanceAmount = ImmValue * PointerSize + PointerSize; 1737 RemainingLoopCount = 0; 1738 if (TableKind == Kind::Lazy) 1739 Malformed = true; 1740 DEBUG_WITH_TYPE("mach-o-bind", 1741 llvm::dbgs() 1742 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 1743 << format("SegmentOffset=0x%06X", 1744 SegmentOffset) << "\n"); 1745 return; 1746 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 1747 RemainingLoopCount = readULEB128() - 1; 1748 AdvanceAmount = readULEB128() + PointerSize; 1749 if (TableKind == Kind::Lazy) 1750 Malformed = true; 1751 DEBUG_WITH_TYPE( 1752 "mach-o-bind", 1753 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 1754 << format("SegmentOffset=0x%06X", SegmentOffset) 1755 << ", AdvanceAmount=" << AdvanceAmount 1756 << ", RemainingLoopCount=" << RemainingLoopCount 1757 << "\n"); 1758 return; 1759 default: 1760 Malformed = true; 1761 } 1762 } 1763 } 1764 1765 uint64_t MachOBindEntry::readULEB128() { 1766 unsigned Count; 1767 uint64_t Result = decodeULEB128(Ptr, &Count); 1768 Ptr += Count; 1769 if (Ptr > Opcodes.end()) { 1770 Ptr = Opcodes.end(); 1771 Malformed = true; 1772 } 1773 return Result; 1774 } 1775 1776 int64_t MachOBindEntry::readSLEB128() { 1777 unsigned Count; 1778 int64_t Result = decodeSLEB128(Ptr, &Count); 1779 Ptr += Count; 1780 if (Ptr > Opcodes.end()) { 1781 Ptr = Opcodes.end(); 1782 Malformed = true; 1783 } 1784 return Result; 1785 } 1786 1787 1788 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 1789 1790 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 1791 1792 StringRef MachOBindEntry::typeName() const { 1793 switch (BindType) { 1794 case MachO::BIND_TYPE_POINTER: 1795 return "pointer"; 1796 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 1797 return "text abs32"; 1798 case MachO::BIND_TYPE_TEXT_PCREL32: 1799 return "text rel32"; 1800 } 1801 return "unknown"; 1802 } 1803 1804 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 1805 1806 int64_t MachOBindEntry::addend() const { return Addend; } 1807 1808 uint32_t MachOBindEntry::flags() const { return Flags; } 1809 1810 int MachOBindEntry::ordinal() const { return Ordinal; } 1811 1812 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 1813 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 1814 return (Ptr == Other.Ptr) && 1815 (RemainingLoopCount == Other.RemainingLoopCount) && 1816 (Done == Other.Done); 1817 } 1818 1819 iterator_range<bind_iterator> 1820 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 1821 MachOBindEntry::Kind BKind) { 1822 MachOBindEntry Start(Opcodes, is64, BKind); 1823 Start.moveToFirst(); 1824 1825 MachOBindEntry Finish(Opcodes, is64, BKind); 1826 Finish.moveToEnd(); 1827 1828 return iterator_range<bind_iterator>(bind_iterator(Start), 1829 bind_iterator(Finish)); 1830 } 1831 1832 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 1833 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 1834 MachOBindEntry::Kind::Regular); 1835 } 1836 1837 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 1838 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 1839 MachOBindEntry::Kind::Lazy); 1840 } 1841 1842 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 1843 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 1844 MachOBindEntry::Kind::Weak); 1845 } 1846 1847 MachOObjectFile::load_command_iterator 1848 MachOObjectFile::begin_load_commands() const { 1849 return LoadCommands.begin(); 1850 } 1851 1852 MachOObjectFile::load_command_iterator 1853 MachOObjectFile::end_load_commands() const { 1854 return LoadCommands.end(); 1855 } 1856 1857 iterator_range<MachOObjectFile::load_command_iterator> 1858 MachOObjectFile::load_commands() const { 1859 return iterator_range<load_command_iterator>(begin_load_commands(), 1860 end_load_commands()); 1861 } 1862 1863 StringRef 1864 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1865 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1866 return parseSegmentOrSectionName(Raw.data()); 1867 } 1868 1869 ArrayRef<char> 1870 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1871 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 1872 const section_base *Base = 1873 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1874 return makeArrayRef(Base->sectname); 1875 } 1876 1877 ArrayRef<char> 1878 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1879 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 1880 const section_base *Base = 1881 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1882 return makeArrayRef(Base->segname); 1883 } 1884 1885 bool 1886 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1887 const { 1888 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1889 return false; 1890 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1891 } 1892 1893 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1894 const MachO::any_relocation_info &RE) const { 1895 if (isLittleEndian()) 1896 return RE.r_word1 & 0xffffff; 1897 return RE.r_word1 >> 8; 1898 } 1899 1900 bool MachOObjectFile::getPlainRelocationExternal( 1901 const MachO::any_relocation_info &RE) const { 1902 if (isLittleEndian()) 1903 return (RE.r_word1 >> 27) & 1; 1904 return (RE.r_word1 >> 4) & 1; 1905 } 1906 1907 bool MachOObjectFile::getScatteredRelocationScattered( 1908 const MachO::any_relocation_info &RE) const { 1909 return RE.r_word0 >> 31; 1910 } 1911 1912 uint32_t MachOObjectFile::getScatteredRelocationValue( 1913 const MachO::any_relocation_info &RE) const { 1914 return RE.r_word1; 1915 } 1916 1917 uint32_t MachOObjectFile::getScatteredRelocationType( 1918 const MachO::any_relocation_info &RE) const { 1919 return (RE.r_word0 >> 24) & 0xf; 1920 } 1921 1922 unsigned MachOObjectFile::getAnyRelocationAddress( 1923 const MachO::any_relocation_info &RE) const { 1924 if (isRelocationScattered(RE)) 1925 return getScatteredRelocationAddress(RE); 1926 return getPlainRelocationAddress(RE); 1927 } 1928 1929 unsigned MachOObjectFile::getAnyRelocationPCRel( 1930 const MachO::any_relocation_info &RE) const { 1931 if (isRelocationScattered(RE)) 1932 return getScatteredRelocationPCRel(this, RE); 1933 return getPlainRelocationPCRel(this, RE); 1934 } 1935 1936 unsigned MachOObjectFile::getAnyRelocationLength( 1937 const MachO::any_relocation_info &RE) const { 1938 if (isRelocationScattered(RE)) 1939 return getScatteredRelocationLength(RE); 1940 return getPlainRelocationLength(this, RE); 1941 } 1942 1943 unsigned 1944 MachOObjectFile::getAnyRelocationType( 1945 const MachO::any_relocation_info &RE) const { 1946 if (isRelocationScattered(RE)) 1947 return getScatteredRelocationType(RE); 1948 return getPlainRelocationType(this, RE); 1949 } 1950 1951 SectionRef 1952 MachOObjectFile::getAnyRelocationSection( 1953 const MachO::any_relocation_info &RE) const { 1954 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1955 return *section_end(); 1956 unsigned SecNum = getPlainRelocationSymbolNum(RE); 1957 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 1958 return *section_end(); 1959 DataRefImpl DRI; 1960 DRI.d.a = SecNum - 1; 1961 return SectionRef(DRI, this); 1962 } 1963 1964 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1965 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 1966 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1967 } 1968 1969 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1970 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 1971 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1972 } 1973 1974 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1975 unsigned Index) const { 1976 const char *Sec = getSectionPtr(this, L, Index); 1977 return getStruct<MachO::section>(this, Sec); 1978 } 1979 1980 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1981 unsigned Index) const { 1982 const char *Sec = getSectionPtr(this, L, Index); 1983 return getStruct<MachO::section_64>(this, Sec); 1984 } 1985 1986 MachO::nlist 1987 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1988 const char *P = reinterpret_cast<const char *>(DRI.p); 1989 return getStruct<MachO::nlist>(this, P); 1990 } 1991 1992 MachO::nlist_64 1993 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1994 const char *P = reinterpret_cast<const char *>(DRI.p); 1995 return getStruct<MachO::nlist_64>(this, P); 1996 } 1997 1998 MachO::linkedit_data_command 1999 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 2000 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 2001 } 2002 2003 MachO::segment_command 2004 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 2005 return getStruct<MachO::segment_command>(this, L.Ptr); 2006 } 2007 2008 MachO::segment_command_64 2009 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 2010 return getStruct<MachO::segment_command_64>(this, L.Ptr); 2011 } 2012 2013 MachO::linker_option_command 2014 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 2015 return getStruct<MachO::linker_option_command>(this, L.Ptr); 2016 } 2017 2018 MachO::version_min_command 2019 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 2020 return getStruct<MachO::version_min_command>(this, L.Ptr); 2021 } 2022 2023 MachO::dylib_command 2024 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 2025 return getStruct<MachO::dylib_command>(this, L.Ptr); 2026 } 2027 2028 MachO::dyld_info_command 2029 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 2030 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 2031 } 2032 2033 MachO::dylinker_command 2034 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 2035 return getStruct<MachO::dylinker_command>(this, L.Ptr); 2036 } 2037 2038 MachO::uuid_command 2039 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 2040 return getStruct<MachO::uuid_command>(this, L.Ptr); 2041 } 2042 2043 MachO::rpath_command 2044 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 2045 return getStruct<MachO::rpath_command>(this, L.Ptr); 2046 } 2047 2048 MachO::source_version_command 2049 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 2050 return getStruct<MachO::source_version_command>(this, L.Ptr); 2051 } 2052 2053 MachO::entry_point_command 2054 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 2055 return getStruct<MachO::entry_point_command>(this, L.Ptr); 2056 } 2057 2058 MachO::encryption_info_command 2059 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 2060 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 2061 } 2062 2063 MachO::encryption_info_command_64 2064 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 2065 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 2066 } 2067 2068 MachO::sub_framework_command 2069 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 2070 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 2071 } 2072 2073 MachO::sub_umbrella_command 2074 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 2075 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 2076 } 2077 2078 MachO::sub_library_command 2079 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 2080 return getStruct<MachO::sub_library_command>(this, L.Ptr); 2081 } 2082 2083 MachO::sub_client_command 2084 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 2085 return getStruct<MachO::sub_client_command>(this, L.Ptr); 2086 } 2087 2088 MachO::routines_command 2089 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 2090 return getStruct<MachO::routines_command>(this, L.Ptr); 2091 } 2092 2093 MachO::routines_command_64 2094 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 2095 return getStruct<MachO::routines_command_64>(this, L.Ptr); 2096 } 2097 2098 MachO::thread_command 2099 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 2100 return getStruct<MachO::thread_command>(this, L.Ptr); 2101 } 2102 2103 MachO::any_relocation_info 2104 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 2105 DataRefImpl Sec; 2106 Sec.d.a = Rel.d.a; 2107 uint32_t Offset; 2108 if (is64Bit()) { 2109 MachO::section_64 Sect = getSection64(Sec); 2110 Offset = Sect.reloff; 2111 } else { 2112 MachO::section Sect = getSection(Sec); 2113 Offset = Sect.reloff; 2114 } 2115 2116 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 2117 getPtr(this, Offset)) + Rel.d.b; 2118 return getStruct<MachO::any_relocation_info>( 2119 this, reinterpret_cast<const char *>(P)); 2120 } 2121 2122 MachO::data_in_code_entry 2123 MachOObjectFile::getDice(DataRefImpl Rel) const { 2124 const char *P = reinterpret_cast<const char *>(Rel.p); 2125 return getStruct<MachO::data_in_code_entry>(this, P); 2126 } 2127 2128 const MachO::mach_header &MachOObjectFile::getHeader() const { 2129 return Header; 2130 } 2131 2132 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 2133 assert(is64Bit()); 2134 return Header64; 2135 } 2136 2137 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 2138 const MachO::dysymtab_command &DLC, 2139 unsigned Index) const { 2140 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 2141 return getStruct<uint32_t>(this, getPtr(this, Offset)); 2142 } 2143 2144 MachO::data_in_code_entry 2145 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 2146 unsigned Index) const { 2147 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 2148 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 2149 } 2150 2151 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 2152 if (SymtabLoadCmd) 2153 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 2154 2155 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 2156 MachO::symtab_command Cmd; 2157 Cmd.cmd = MachO::LC_SYMTAB; 2158 Cmd.cmdsize = sizeof(MachO::symtab_command); 2159 Cmd.symoff = 0; 2160 Cmd.nsyms = 0; 2161 Cmd.stroff = 0; 2162 Cmd.strsize = 0; 2163 return Cmd; 2164 } 2165 2166 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 2167 if (DysymtabLoadCmd) 2168 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 2169 2170 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 2171 MachO::dysymtab_command Cmd; 2172 Cmd.cmd = MachO::LC_DYSYMTAB; 2173 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 2174 Cmd.ilocalsym = 0; 2175 Cmd.nlocalsym = 0; 2176 Cmd.iextdefsym = 0; 2177 Cmd.nextdefsym = 0; 2178 Cmd.iundefsym = 0; 2179 Cmd.nundefsym = 0; 2180 Cmd.tocoff = 0; 2181 Cmd.ntoc = 0; 2182 Cmd.modtaboff = 0; 2183 Cmd.nmodtab = 0; 2184 Cmd.extrefsymoff = 0; 2185 Cmd.nextrefsyms = 0; 2186 Cmd.indirectsymoff = 0; 2187 Cmd.nindirectsyms = 0; 2188 Cmd.extreloff = 0; 2189 Cmd.nextrel = 0; 2190 Cmd.locreloff = 0; 2191 Cmd.nlocrel = 0; 2192 return Cmd; 2193 } 2194 2195 MachO::linkedit_data_command 2196 MachOObjectFile::getDataInCodeLoadCommand() const { 2197 if (DataInCodeLoadCmd) 2198 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 2199 2200 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 2201 MachO::linkedit_data_command Cmd; 2202 Cmd.cmd = MachO::LC_DATA_IN_CODE; 2203 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2204 Cmd.dataoff = 0; 2205 Cmd.datasize = 0; 2206 return Cmd; 2207 } 2208 2209 MachO::linkedit_data_command 2210 MachOObjectFile::getLinkOptHintsLoadCommand() const { 2211 if (LinkOptHintsLoadCmd) 2212 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 2213 2214 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 2215 // fields. 2216 MachO::linkedit_data_command Cmd; 2217 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 2218 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2219 Cmd.dataoff = 0; 2220 Cmd.datasize = 0; 2221 return Cmd; 2222 } 2223 2224 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 2225 if (!DyldInfoLoadCmd) 2226 return ArrayRef<uint8_t>(); 2227 2228 MachO::dyld_info_command DyldInfo 2229 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2230 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 2231 getPtr(this, DyldInfo.rebase_off)); 2232 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size); 2233 } 2234 2235 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 2236 if (!DyldInfoLoadCmd) 2237 return ArrayRef<uint8_t>(); 2238 2239 MachO::dyld_info_command DyldInfo 2240 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2241 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 2242 getPtr(this, DyldInfo.bind_off)); 2243 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size); 2244 } 2245 2246 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 2247 if (!DyldInfoLoadCmd) 2248 return ArrayRef<uint8_t>(); 2249 2250 MachO::dyld_info_command DyldInfo 2251 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2252 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 2253 getPtr(this, DyldInfo.weak_bind_off)); 2254 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size); 2255 } 2256 2257 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 2258 if (!DyldInfoLoadCmd) 2259 return ArrayRef<uint8_t>(); 2260 2261 MachO::dyld_info_command DyldInfo 2262 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2263 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 2264 getPtr(this, DyldInfo.lazy_bind_off)); 2265 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size); 2266 } 2267 2268 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 2269 if (!DyldInfoLoadCmd) 2270 return ArrayRef<uint8_t>(); 2271 2272 MachO::dyld_info_command DyldInfo 2273 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2274 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 2275 getPtr(this, DyldInfo.export_off)); 2276 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size); 2277 } 2278 2279 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 2280 if (!UuidLoadCmd) 2281 return ArrayRef<uint8_t>(); 2282 // Returning a pointer is fine as uuid doesn't need endian swapping. 2283 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 2284 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16); 2285 } 2286 2287 StringRef MachOObjectFile::getStringTableData() const { 2288 MachO::symtab_command S = getSymtabLoadCommand(); 2289 return getData().substr(S.stroff, S.strsize); 2290 } 2291 2292 bool MachOObjectFile::is64Bit() const { 2293 return getType() == getMachOType(false, true) || 2294 getType() == getMachOType(true, true); 2295 } 2296 2297 void MachOObjectFile::ReadULEB128s(uint64_t Index, 2298 SmallVectorImpl<uint64_t> &Out) const { 2299 DataExtractor extractor(ObjectFile::getData(), true, 0); 2300 2301 uint32_t offset = Index; 2302 uint64_t data = 0; 2303 while (uint64_t delta = extractor.getULEB128(&offset)) { 2304 data += delta; 2305 Out.push_back(data); 2306 } 2307 } 2308 2309 bool MachOObjectFile::isRelocatableObject() const { 2310 return getHeader().filetype == MachO::MH_OBJECT; 2311 } 2312 2313 ErrorOr<std::unique_ptr<MachOObjectFile>> 2314 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 2315 StringRef Magic = Buffer.getBuffer().slice(0, 4); 2316 std::error_code EC; 2317 std::unique_ptr<MachOObjectFile> Ret; 2318 if (Magic == "\xFE\xED\xFA\xCE") 2319 Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); 2320 else if (Magic == "\xCE\xFA\xED\xFE") 2321 Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); 2322 else if (Magic == "\xFE\xED\xFA\xCF") 2323 Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); 2324 else if (Magic == "\xCF\xFA\xED\xFE") 2325 Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); 2326 else 2327 return object_error::parse_failed; 2328 2329 if (EC) 2330 return EC; 2331 return std::move(Ret); 2332 } 2333 2334