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