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