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