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