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