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