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