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