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