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