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