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