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