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