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