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