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