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