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