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