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