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