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