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/Format.h" 21 #include "llvm/Support/Host.h" 22 #include "llvm/Support/MemoryBuffer.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <cctype> 25 #include <cstring> 26 #include <limits> 27 28 using namespace llvm; 29 using namespace object; 30 31 namespace { 32 struct section_base { 33 char sectname[16]; 34 char segname[16]; 35 }; 36 } 37 38 template<typename T> 39 static T getStruct(const MachOObjectFile *O, const char *P) { 40 T Cmd; 41 memcpy(&Cmd, P, sizeof(T)); 42 if (O->isLittleEndian() != sys::IsLittleEndianHost) 43 MachO::swapStruct(Cmd); 44 return Cmd; 45 } 46 47 static uint32_t 48 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 49 const MachOObjectFile::LoadCommandInfo &L) { 50 if (O->is64Bit()) { 51 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 52 return S.nsects; 53 } 54 MachO::segment_command S = O->getSegmentLoadCommand(L); 55 return S.nsects; 56 } 57 58 static const char * 59 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 60 unsigned Sec) { 61 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 62 63 bool Is64 = O->is64Bit(); 64 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 65 sizeof(MachO::segment_command); 66 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 67 sizeof(MachO::section); 68 69 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 70 return reinterpret_cast<const char*>(SectionAddr); 71 } 72 73 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 74 return O->getData().substr(Offset, 1).data(); 75 } 76 77 static MachO::nlist_base 78 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 79 const char *P = reinterpret_cast<const char *>(DRI.p); 80 return getStruct<MachO::nlist_base>(O, P); 81 } 82 83 static StringRef parseSegmentOrSectionName(const char *P) { 84 if (P[15] == 0) 85 // Null terminated. 86 return P; 87 // Not null terminated, so this is a 16 char string. 88 return StringRef(P, 16); 89 } 90 91 // Helper to advance a section or symbol iterator multiple increments at a time. 92 template<class T> 93 static void advance(T &it, size_t Val) { 94 while (Val--) 95 ++it; 96 } 97 98 static unsigned getCPUType(const MachOObjectFile *O) { 99 return O->getHeader().cputype; 100 } 101 102 static void printRelocationTargetName(const MachOObjectFile *O, 103 const MachO::any_relocation_info &RE, 104 raw_string_ostream &fmt) { 105 bool IsScattered = O->isRelocationScattered(RE); 106 107 // Target of a scattered relocation is an address. In the interest of 108 // generating pretty output, scan through the symbol table looking for a 109 // symbol that aligns with that address. If we find one, print it. 110 // Otherwise, we just print the hex address of the target. 111 if (IsScattered) { 112 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 113 114 for (const SymbolRef &Symbol : O->symbols()) { 115 std::error_code ec; 116 uint64_t Addr; 117 StringRef Name; 118 119 if ((ec = Symbol.getAddress(Addr))) 120 report_fatal_error(ec.message()); 121 if (Addr != Val) 122 continue; 123 if ((ec = Symbol.getName(Name))) 124 report_fatal_error(ec.message()); 125 fmt << Name; 126 return; 127 } 128 129 // If we couldn't find a symbol that this relocation refers to, try 130 // to find a section beginning instead. 131 for (const SectionRef &Section : O->sections()) { 132 std::error_code ec; 133 uint64_t Addr; 134 StringRef Name; 135 136 if ((ec = Section.getAddress(Addr))) 137 report_fatal_error(ec.message()); 138 if (Addr != Val) 139 continue; 140 if ((ec = Section.getName(Name))) 141 report_fatal_error(ec.message()); 142 fmt << Name; 143 return; 144 } 145 146 fmt << format("0x%x", Val); 147 return; 148 } 149 150 StringRef S; 151 bool isExtern = O->getPlainRelocationExternal(RE); 152 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 153 154 if (isExtern) { 155 symbol_iterator SI = O->symbol_begin(); 156 advance(SI, Val); 157 SI->getName(S); 158 } else { 159 section_iterator SI = O->section_begin(); 160 // Adjust for the fact that sections are 1-indexed. 161 advance(SI, Val - 1); 162 SI->getName(S); 163 } 164 165 fmt << S; 166 } 167 168 static uint32_t 169 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 170 return RE.r_word0; 171 } 172 173 static unsigned 174 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 175 return RE.r_word0 & 0xffffff; 176 } 177 178 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 179 const MachO::any_relocation_info &RE) { 180 if (O->isLittleEndian()) 181 return (RE.r_word1 >> 24) & 1; 182 return (RE.r_word1 >> 7) & 1; 183 } 184 185 static bool 186 getScatteredRelocationPCRel(const MachOObjectFile *O, 187 const MachO::any_relocation_info &RE) { 188 return (RE.r_word0 >> 30) & 1; 189 } 190 191 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 192 const MachO::any_relocation_info &RE) { 193 if (O->isLittleEndian()) 194 return (RE.r_word1 >> 25) & 3; 195 return (RE.r_word1 >> 5) & 3; 196 } 197 198 static unsigned 199 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 200 return (RE.r_word0 >> 28) & 3; 201 } 202 203 static unsigned getPlainRelocationType(const MachOObjectFile *O, 204 const MachO::any_relocation_info &RE) { 205 if (O->isLittleEndian()) 206 return RE.r_word1 >> 28; 207 return RE.r_word1 & 0xf; 208 } 209 210 static unsigned 211 getScatteredRelocationType(const MachO::any_relocation_info &RE) { 212 return (RE.r_word0 >> 24) & 0xf; 213 } 214 215 static uint32_t getSectionFlags(const MachOObjectFile *O, 216 DataRefImpl Sec) { 217 if (O->is64Bit()) { 218 MachO::section_64 Sect = O->getSection64(Sec); 219 return Sect.flags; 220 } 221 MachO::section Sect = O->getSection(Sec); 222 return Sect.flags; 223 } 224 225 MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, 226 bool IsLittleEndian, bool Is64bits, 227 std::error_code &EC) 228 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), 229 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 230 DataInCodeLoadCmd(nullptr) { 231 uint32_t LoadCommandCount = this->getHeader().ncmds; 232 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 233 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 234 235 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 236 for (unsigned I = 0; ; ++I) { 237 if (Load.C.cmd == MachO::LC_SYMTAB) { 238 assert(!SymtabLoadCmd && "Multiple symbol tables"); 239 SymtabLoadCmd = Load.Ptr; 240 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 241 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 242 DysymtabLoadCmd = Load.Ptr; 243 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 244 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 245 DataInCodeLoadCmd = Load.Ptr; 246 } else if (Load.C.cmd == SegmentLoadType) { 247 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 248 for (unsigned J = 0; J < NumSections; ++J) { 249 const char *Sec = getSectionPtr(this, Load, J); 250 Sections.push_back(Sec); 251 } 252 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 253 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 254 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 255 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 256 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 257 Libraries.push_back(Load.Ptr); 258 } 259 260 if (I == LoadCommandCount - 1) 261 break; 262 else 263 Load = getNextLoadCommandInfo(Load); 264 } 265 } 266 267 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 268 unsigned SymbolTableEntrySize = is64Bit() ? 269 sizeof(MachO::nlist_64) : 270 sizeof(MachO::nlist); 271 Symb.p += SymbolTableEntrySize; 272 } 273 274 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 275 StringRef &Res) const { 276 StringRef StringTable = getStringTableData(); 277 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 278 const char *Start = &StringTable.data()[Entry.n_strx]; 279 Res = StringRef(Start); 280 return object_error::success; 281 } 282 283 // getIndirectName() returns the name of the alias'ed symbol who's string table 284 // index is in the n_value field. 285 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 286 StringRef &Res) const { 287 StringRef StringTable = getStringTableData(); 288 uint64_t NValue; 289 if (is64Bit()) { 290 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 291 NValue = Entry.n_value; 292 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 293 return object_error::parse_failed; 294 } else { 295 MachO::nlist Entry = getSymbolTableEntry(Symb); 296 NValue = Entry.n_value; 297 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 298 return object_error::parse_failed; 299 } 300 if (NValue >= StringTable.size()) 301 return object_error::parse_failed; 302 const char *Start = &StringTable.data()[NValue]; 303 Res = StringRef(Start); 304 return object_error::success; 305 } 306 307 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 308 uint64_t &Res) const { 309 if (is64Bit()) { 310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 311 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 312 Entry.n_value == 0) 313 Res = UnknownAddressOrSize; 314 else 315 Res = Entry.n_value; 316 } else { 317 MachO::nlist Entry = getSymbolTableEntry(Symb); 318 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 319 Entry.n_value == 0) 320 Res = UnknownAddressOrSize; 321 else 322 Res = Entry.n_value; 323 } 324 return object_error::success; 325 } 326 327 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 328 uint32_t &Result) const { 329 uint32_t flags = getSymbolFlags(DRI); 330 if (flags & SymbolRef::SF_Common) { 331 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 332 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 333 } else { 334 Result = 0; 335 } 336 return object_error::success; 337 } 338 339 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 340 uint64_t &Result) const { 341 uint64_t BeginOffset; 342 uint64_t EndOffset = 0; 343 uint8_t SectionIndex; 344 345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 346 uint64_t Value; 347 getSymbolAddress(DRI, Value); 348 if (Value == UnknownAddressOrSize) { 349 Result = UnknownAddressOrSize; 350 return object_error::success; 351 } 352 353 BeginOffset = Value; 354 355 SectionIndex = Entry.n_sect; 356 if (!SectionIndex) { 357 uint32_t flags = getSymbolFlags(DRI); 358 if (flags & SymbolRef::SF_Common) 359 Result = Value; 360 else 361 Result = UnknownAddressOrSize; 362 return object_error::success; 363 } 364 // Unfortunately symbols are unsorted so we need to touch all 365 // symbols from load command 366 for (const SymbolRef &Symbol : symbols()) { 367 DataRefImpl DRI = Symbol.getRawDataRefImpl(); 368 Entry = getSymbolTableEntryBase(this, DRI); 369 getSymbolAddress(DRI, Value); 370 if (Value == UnknownAddressOrSize) 371 continue; 372 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 373 if (!EndOffset || Value < EndOffset) 374 EndOffset = Value; 375 } 376 if (!EndOffset) { 377 uint64_t Size; 378 DataRefImpl Sec; 379 Sec.d.a = SectionIndex-1; 380 getSectionSize(Sec, Size); 381 getSectionAddress(Sec, EndOffset); 382 EndOffset += Size; 383 } 384 Result = EndOffset - BeginOffset; 385 return object_error::success; 386 } 387 388 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 389 SymbolRef::Type &Res) const { 390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 391 uint8_t n_type = Entry.n_type; 392 393 Res = SymbolRef::ST_Other; 394 395 // If this is a STAB debugging symbol, we can do nothing more. 396 if (n_type & MachO::N_STAB) { 397 Res = SymbolRef::ST_Debug; 398 return object_error::success; 399 } 400 401 switch (n_type & MachO::N_TYPE) { 402 case MachO::N_UNDF : 403 Res = SymbolRef::ST_Unknown; 404 break; 405 case MachO::N_SECT : 406 Res = SymbolRef::ST_Function; 407 break; 408 } 409 return object_error::success; 410 } 411 412 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 414 415 uint8_t MachOType = Entry.n_type; 416 uint16_t MachOFlags = Entry.n_desc; 417 418 uint32_t Result = SymbolRef::SF_None; 419 420 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 421 Result |= SymbolRef::SF_Undefined; 422 423 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 424 Result |= SymbolRef::SF_Indirect; 425 426 if (MachOType & MachO::N_STAB) 427 Result |= SymbolRef::SF_FormatSpecific; 428 429 if (MachOType & MachO::N_EXT) { 430 Result |= SymbolRef::SF_Global; 431 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 432 uint64_t Value; 433 getSymbolAddress(DRI, Value); 434 if (Value && Value != UnknownAddressOrSize) 435 Result |= SymbolRef::SF_Common; 436 } 437 } 438 439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 440 Result |= SymbolRef::SF_Weak; 441 442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 443 Result |= SymbolRef::SF_Absolute; 444 445 return Result; 446 } 447 448 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 449 section_iterator &Res) const { 450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 451 uint8_t index = Entry.n_sect; 452 453 if (index == 0) { 454 Res = section_end(); 455 } else { 456 DataRefImpl DRI; 457 DRI.d.a = index - 1; 458 Res = section_iterator(SectionRef(DRI, this)); 459 } 460 461 return object_error::success; 462 } 463 464 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 465 Sec.d.a++; 466 } 467 468 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 469 StringRef &Result) const { 470 ArrayRef<char> Raw = getSectionRawName(Sec); 471 Result = parseSegmentOrSectionName(Raw.data()); 472 return object_error::success; 473 } 474 475 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 476 uint64_t &Res) const { 477 if (is64Bit()) { 478 MachO::section_64 Sect = getSection64(Sec); 479 Res = Sect.addr; 480 } else { 481 MachO::section Sect = getSection(Sec); 482 Res = Sect.addr; 483 } 484 return object_error::success; 485 } 486 487 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 488 uint64_t &Res) const { 489 if (is64Bit()) { 490 MachO::section_64 Sect = getSection64(Sec); 491 Res = Sect.size; 492 } else { 493 MachO::section Sect = getSection(Sec); 494 Res = Sect.size; 495 } 496 497 return object_error::success; 498 } 499 500 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 501 StringRef &Res) const { 502 uint32_t Offset; 503 uint64_t Size; 504 505 if (is64Bit()) { 506 MachO::section_64 Sect = getSection64(Sec); 507 Offset = Sect.offset; 508 Size = Sect.size; 509 } else { 510 MachO::section Sect = getSection(Sec); 511 Offset = Sect.offset; 512 Size = Sect.size; 513 } 514 515 Res = this->getData().substr(Offset, Size); 516 return object_error::success; 517 } 518 519 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 520 uint64_t &Res) const { 521 uint32_t Align; 522 if (is64Bit()) { 523 MachO::section_64 Sect = getSection64(Sec); 524 Align = Sect.align; 525 } else { 526 MachO::section Sect = getSection(Sec); 527 Align = Sect.align; 528 } 529 530 Res = uint64_t(1) << Align; 531 return object_error::success; 532 } 533 534 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 535 bool &Res) const { 536 uint32_t Flags = getSectionFlags(this, Sec); 537 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 538 return object_error::success; 539 } 540 541 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 542 bool &Result) const { 543 uint32_t Flags = getSectionFlags(this, Sec); 544 unsigned SectionType = Flags & MachO::SECTION_TYPE; 545 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 546 !(SectionType == MachO::S_ZEROFILL || 547 SectionType == MachO::S_GB_ZEROFILL); 548 return object_error::success; 549 } 550 551 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 552 bool &Result) const { 553 uint32_t Flags = getSectionFlags(this, Sec); 554 unsigned SectionType = Flags & MachO::SECTION_TYPE; 555 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 556 (SectionType == MachO::S_ZEROFILL || 557 SectionType == MachO::S_GB_ZEROFILL); 558 return object_error::success; 559 } 560 561 std::error_code 562 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 563 bool &Result) const { 564 // FIXME: Unimplemented. 565 Result = true; 566 return object_error::success; 567 } 568 569 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 570 bool &Result) const { 571 // FIXME: Unimplemented. 572 Result = false; 573 return object_error::success; 574 } 575 576 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 577 bool &Res) const { 578 uint32_t Flags = getSectionFlags(this, Sec); 579 unsigned SectionType = Flags & MachO::SECTION_TYPE; 580 Res = SectionType == MachO::S_ZEROFILL || 581 SectionType == MachO::S_GB_ZEROFILL; 582 return object_error::success; 583 } 584 585 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 586 bool &Result) const { 587 // Consider using the code from isSectionText to look for __const sections. 588 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 589 // to use section attributes to distinguish code from data. 590 591 // FIXME: Unimplemented. 592 Result = false; 593 return object_error::success; 594 } 595 596 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 597 DataRefImpl Symb, 598 bool &Result) const { 599 SymbolRef::Type ST; 600 this->getSymbolType(Symb, ST); 601 if (ST == SymbolRef::ST_Unknown) { 602 Result = false; 603 return object_error::success; 604 } 605 606 uint64_t SectBegin, SectEnd; 607 getSectionAddress(Sec, SectBegin); 608 getSectionSize(Sec, SectEnd); 609 SectEnd += SectBegin; 610 611 uint64_t SymAddr; 612 getSymbolAddress(Symb, SymAddr); 613 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 614 615 return object_error::success; 616 } 617 618 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 619 DataRefImpl Ret; 620 Ret.d.a = Sec.d.a; 621 Ret.d.b = 0; 622 return relocation_iterator(RelocationRef(Ret, this)); 623 } 624 625 relocation_iterator 626 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 627 uint32_t Num; 628 if (is64Bit()) { 629 MachO::section_64 Sect = getSection64(Sec); 630 Num = Sect.nreloc; 631 } else { 632 MachO::section Sect = getSection(Sec); 633 Num = Sect.nreloc; 634 } 635 636 DataRefImpl Ret; 637 Ret.d.a = Sec.d.a; 638 Ret.d.b = Num; 639 return relocation_iterator(RelocationRef(Ret, this)); 640 } 641 642 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 643 ++Rel.d.b; 644 } 645 646 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 647 uint64_t &Res) const { 648 uint64_t Offset; 649 getRelocationOffset(Rel, Offset); 650 651 DataRefImpl Sec; 652 Sec.d.a = Rel.d.a; 653 uint64_t SecAddress; 654 getSectionAddress(Sec, SecAddress); 655 Res = SecAddress + Offset; 656 return object_error::success; 657 } 658 659 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 660 uint64_t &Res) const { 661 assert(getHeader().filetype == MachO::MH_OBJECT && 662 "Only implemented for MH_OBJECT"); 663 MachO::any_relocation_info RE = getRelocation(Rel); 664 Res = getAnyRelocationAddress(RE); 665 return object_error::success; 666 } 667 668 symbol_iterator 669 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 670 MachO::any_relocation_info RE = getRelocation(Rel); 671 if (isRelocationScattered(RE)) 672 return symbol_end(); 673 674 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 675 bool isExtern = getPlainRelocationExternal(RE); 676 if (!isExtern) 677 return symbol_end(); 678 679 MachO::symtab_command S = getSymtabLoadCommand(); 680 unsigned SymbolTableEntrySize = is64Bit() ? 681 sizeof(MachO::nlist_64) : 682 sizeof(MachO::nlist); 683 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 684 DataRefImpl Sym; 685 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 686 return symbol_iterator(SymbolRef(Sym, this)); 687 } 688 689 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 690 uint64_t &Res) const { 691 MachO::any_relocation_info RE = getRelocation(Rel); 692 Res = getAnyRelocationType(RE); 693 return object_error::success; 694 } 695 696 std::error_code 697 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 698 SmallVectorImpl<char> &Result) const { 699 StringRef res; 700 uint64_t RType; 701 getRelocationType(Rel, RType); 702 703 unsigned Arch = this->getArch(); 704 705 switch (Arch) { 706 case Triple::x86: { 707 static const char *const Table[] = { 708 "GENERIC_RELOC_VANILLA", 709 "GENERIC_RELOC_PAIR", 710 "GENERIC_RELOC_SECTDIFF", 711 "GENERIC_RELOC_PB_LA_PTR", 712 "GENERIC_RELOC_LOCAL_SECTDIFF", 713 "GENERIC_RELOC_TLV" }; 714 715 if (RType > 5) 716 res = "Unknown"; 717 else 718 res = Table[RType]; 719 break; 720 } 721 case Triple::x86_64: { 722 static const char *const Table[] = { 723 "X86_64_RELOC_UNSIGNED", 724 "X86_64_RELOC_SIGNED", 725 "X86_64_RELOC_BRANCH", 726 "X86_64_RELOC_GOT_LOAD", 727 "X86_64_RELOC_GOT", 728 "X86_64_RELOC_SUBTRACTOR", 729 "X86_64_RELOC_SIGNED_1", 730 "X86_64_RELOC_SIGNED_2", 731 "X86_64_RELOC_SIGNED_4", 732 "X86_64_RELOC_TLV" }; 733 734 if (RType > 9) 735 res = "Unknown"; 736 else 737 res = Table[RType]; 738 break; 739 } 740 case Triple::arm: { 741 static const char *const Table[] = { 742 "ARM_RELOC_VANILLA", 743 "ARM_RELOC_PAIR", 744 "ARM_RELOC_SECTDIFF", 745 "ARM_RELOC_LOCAL_SECTDIFF", 746 "ARM_RELOC_PB_LA_PTR", 747 "ARM_RELOC_BR24", 748 "ARM_THUMB_RELOC_BR22", 749 "ARM_THUMB_32BIT_BRANCH", 750 "ARM_RELOC_HALF", 751 "ARM_RELOC_HALF_SECTDIFF" }; 752 753 if (RType > 9) 754 res = "Unknown"; 755 else 756 res = Table[RType]; 757 break; 758 } 759 case Triple::aarch64: { 760 static const char *const Table[] = { 761 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 762 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 763 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 764 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 765 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 766 "ARM64_RELOC_ADDEND" 767 }; 768 769 if (RType >= array_lengthof(Table)) 770 res = "Unknown"; 771 else 772 res = Table[RType]; 773 break; 774 } 775 case Triple::ppc: { 776 static const char *const Table[] = { 777 "PPC_RELOC_VANILLA", 778 "PPC_RELOC_PAIR", 779 "PPC_RELOC_BR14", 780 "PPC_RELOC_BR24", 781 "PPC_RELOC_HI16", 782 "PPC_RELOC_LO16", 783 "PPC_RELOC_HA16", 784 "PPC_RELOC_LO14", 785 "PPC_RELOC_SECTDIFF", 786 "PPC_RELOC_PB_LA_PTR", 787 "PPC_RELOC_HI16_SECTDIFF", 788 "PPC_RELOC_LO16_SECTDIFF", 789 "PPC_RELOC_HA16_SECTDIFF", 790 "PPC_RELOC_JBSR", 791 "PPC_RELOC_LO14_SECTDIFF", 792 "PPC_RELOC_LOCAL_SECTDIFF" }; 793 794 if (RType > 15) 795 res = "Unknown"; 796 else 797 res = Table[RType]; 798 break; 799 } 800 case Triple::UnknownArch: 801 res = "Unknown"; 802 break; 803 } 804 Result.append(res.begin(), res.end()); 805 return object_error::success; 806 } 807 808 std::error_code 809 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 810 SmallVectorImpl<char> &Result) const { 811 MachO::any_relocation_info RE = getRelocation(Rel); 812 813 unsigned Arch = this->getArch(); 814 815 std::string fmtbuf; 816 raw_string_ostream fmt(fmtbuf); 817 unsigned Type = this->getAnyRelocationType(RE); 818 bool IsPCRel = this->getAnyRelocationPCRel(RE); 819 820 // Determine any addends that should be displayed with the relocation. 821 // These require decoding the relocation type, which is triple-specific. 822 823 // X86_64 has entirely custom relocation types. 824 if (Arch == Triple::x86_64) { 825 bool isPCRel = getAnyRelocationPCRel(RE); 826 827 switch (Type) { 828 case MachO::X86_64_RELOC_GOT_LOAD: 829 case MachO::X86_64_RELOC_GOT: { 830 printRelocationTargetName(this, RE, fmt); 831 fmt << "@GOT"; 832 if (isPCRel) fmt << "PCREL"; 833 break; 834 } 835 case MachO::X86_64_RELOC_SUBTRACTOR: { 836 DataRefImpl RelNext = Rel; 837 moveRelocationNext(RelNext); 838 MachO::any_relocation_info RENext = getRelocation(RelNext); 839 840 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 841 // X86_64_RELOC_UNSIGNED. 842 // NOTE: Scattered relocations don't exist on x86_64. 843 unsigned RType = getAnyRelocationType(RENext); 844 if (RType != MachO::X86_64_RELOC_UNSIGNED) 845 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 846 "X86_64_RELOC_SUBTRACTOR."); 847 848 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 849 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 850 printRelocationTargetName(this, RENext, fmt); 851 fmt << "-"; 852 printRelocationTargetName(this, RE, fmt); 853 break; 854 } 855 case MachO::X86_64_RELOC_TLV: 856 printRelocationTargetName(this, RE, fmt); 857 fmt << "@TLV"; 858 if (isPCRel) fmt << "P"; 859 break; 860 case MachO::X86_64_RELOC_SIGNED_1: 861 printRelocationTargetName(this, RE, fmt); 862 fmt << "-1"; 863 break; 864 case MachO::X86_64_RELOC_SIGNED_2: 865 printRelocationTargetName(this, RE, fmt); 866 fmt << "-2"; 867 break; 868 case MachO::X86_64_RELOC_SIGNED_4: 869 printRelocationTargetName(this, RE, fmt); 870 fmt << "-4"; 871 break; 872 default: 873 printRelocationTargetName(this, RE, fmt); 874 break; 875 } 876 // X86 and ARM share some relocation types in common. 877 } else if (Arch == Triple::x86 || Arch == Triple::arm || 878 Arch == Triple::ppc) { 879 // Generic relocation types... 880 switch (Type) { 881 case MachO::GENERIC_RELOC_PAIR: // prints no info 882 return object_error::success; 883 case MachO::GENERIC_RELOC_SECTDIFF: { 884 DataRefImpl RelNext = Rel; 885 moveRelocationNext(RelNext); 886 MachO::any_relocation_info RENext = getRelocation(RelNext); 887 888 // X86 sect diff's must be followed by a relocation of type 889 // GENERIC_RELOC_PAIR. 890 unsigned RType = getAnyRelocationType(RENext); 891 892 if (RType != MachO::GENERIC_RELOC_PAIR) 893 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 894 "GENERIC_RELOC_SECTDIFF."); 895 896 printRelocationTargetName(this, RE, fmt); 897 fmt << "-"; 898 printRelocationTargetName(this, RENext, fmt); 899 break; 900 } 901 } 902 903 if (Arch == Triple::x86 || Arch == Triple::ppc) { 904 switch (Type) { 905 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 906 DataRefImpl RelNext = Rel; 907 moveRelocationNext(RelNext); 908 MachO::any_relocation_info RENext = getRelocation(RelNext); 909 910 // X86 sect diff's must be followed by a relocation of type 911 // GENERIC_RELOC_PAIR. 912 unsigned RType = getAnyRelocationType(RENext); 913 if (RType != MachO::GENERIC_RELOC_PAIR) 914 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 915 "GENERIC_RELOC_LOCAL_SECTDIFF."); 916 917 printRelocationTargetName(this, RE, fmt); 918 fmt << "-"; 919 printRelocationTargetName(this, RENext, fmt); 920 break; 921 } 922 case MachO::GENERIC_RELOC_TLV: { 923 printRelocationTargetName(this, RE, fmt); 924 fmt << "@TLV"; 925 if (IsPCRel) fmt << "P"; 926 break; 927 } 928 default: 929 printRelocationTargetName(this, RE, fmt); 930 } 931 } else { // ARM-specific relocations 932 switch (Type) { 933 case MachO::ARM_RELOC_HALF: 934 case MachO::ARM_RELOC_HALF_SECTDIFF: { 935 // Half relocations steal a bit from the length field to encode 936 // whether this is an upper16 or a lower16 relocation. 937 bool isUpper = getAnyRelocationLength(RE) >> 1; 938 939 if (isUpper) 940 fmt << ":upper16:("; 941 else 942 fmt << ":lower16:("; 943 printRelocationTargetName(this, RE, fmt); 944 945 DataRefImpl RelNext = Rel; 946 moveRelocationNext(RelNext); 947 MachO::any_relocation_info RENext = getRelocation(RelNext); 948 949 // ARM half relocs must be followed by a relocation of type 950 // ARM_RELOC_PAIR. 951 unsigned RType = getAnyRelocationType(RENext); 952 if (RType != MachO::ARM_RELOC_PAIR) 953 report_fatal_error("Expected ARM_RELOC_PAIR after " 954 "ARM_RELOC_HALF"); 955 956 // NOTE: The half of the target virtual address is stashed in the 957 // address field of the secondary relocation, but we can't reverse 958 // engineer the constant offset from it without decoding the movw/movt 959 // instruction to find the other half in its immediate field. 960 961 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 962 // symbol/section pointer of the follow-on relocation. 963 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 964 fmt << "-"; 965 printRelocationTargetName(this, RENext, fmt); 966 } 967 968 fmt << ")"; 969 break; 970 } 971 default: { 972 printRelocationTargetName(this, RE, fmt); 973 } 974 } 975 } 976 } else 977 printRelocationTargetName(this, RE, fmt); 978 979 fmt.flush(); 980 Result.append(fmtbuf.begin(), fmtbuf.end()); 981 return object_error::success; 982 } 983 984 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 985 bool &Result) const { 986 unsigned Arch = getArch(); 987 uint64_t Type; 988 getRelocationType(Rel, Type); 989 990 Result = false; 991 992 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 993 // is always hidden. 994 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 995 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 996 } else if (Arch == Triple::x86_64) { 997 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 998 // an X86_64_RELOC_SUBTRACTOR. 999 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1000 DataRefImpl RelPrev = Rel; 1001 RelPrev.d.a--; 1002 uint64_t PrevType; 1003 getRelocationType(RelPrev, PrevType); 1004 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1005 Result = true; 1006 } 1007 } 1008 1009 return object_error::success; 1010 } 1011 1012 // 1013 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1014 // guess on what the short name is. Then name is returned as a substring of the 1015 // StringRef Name passed in. The name of the dynamic library is recognized as 1016 // a framework if it has one of the two following forms: 1017 // Foo.framework/Versions/A/Foo 1018 // Foo.framework/Foo 1019 // Where A and Foo can be any string. And may contain a trailing suffix 1020 // starting with an underbar. If the Name is recognized as a framework then 1021 // isFramework is set to true else it is set to false. If the Name has a 1022 // suffix then Suffix is set to the substring in Name that contains the suffix 1023 // else it is set to a NULL StringRef. 1024 // 1025 // The Name of the dynamic library is recognized as a library name if it has 1026 // one of the two following forms: 1027 // libFoo.A.dylib 1028 // libFoo.dylib 1029 // The library may have a suffix trailing the name Foo of the form: 1030 // libFoo_profile.A.dylib 1031 // libFoo_profile.dylib 1032 // 1033 // The Name of the dynamic library is also recognized as a library name if it 1034 // has the following form: 1035 // Foo.qtx 1036 // 1037 // If the Name of the dynamic library is none of the forms above then a NULL 1038 // StringRef is returned. 1039 // 1040 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1041 bool &isFramework, 1042 StringRef &Suffix) { 1043 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1044 size_t a, b, c, d, Idx; 1045 1046 isFramework = false; 1047 Suffix = StringRef(); 1048 1049 // Pull off the last component and make Foo point to it 1050 a = Name.rfind('/'); 1051 if (a == Name.npos || a == 0) 1052 goto guess_library; 1053 Foo = Name.slice(a+1, Name.npos); 1054 1055 // Look for a suffix starting with a '_' 1056 Idx = Foo.rfind('_'); 1057 if (Idx != Foo.npos && Foo.size() >= 2) { 1058 Suffix = Foo.slice(Idx, Foo.npos); 1059 Foo = Foo.slice(0, Idx); 1060 } 1061 1062 // First look for the form Foo.framework/Foo 1063 b = Name.rfind('/', a); 1064 if (b == Name.npos) 1065 Idx = 0; 1066 else 1067 Idx = b+1; 1068 F = Name.slice(Idx, Idx + Foo.size()); 1069 DotFramework = Name.slice(Idx + Foo.size(), 1070 Idx + Foo.size() + sizeof(".framework/")-1); 1071 if (F == Foo && DotFramework == ".framework/") { 1072 isFramework = true; 1073 return Foo; 1074 } 1075 1076 // Next look for the form Foo.framework/Versions/A/Foo 1077 if (b == Name.npos) 1078 goto guess_library; 1079 c = Name.rfind('/', b); 1080 if (c == Name.npos || c == 0) 1081 goto guess_library; 1082 V = Name.slice(c+1, Name.npos); 1083 if (!V.startswith("Versions/")) 1084 goto guess_library; 1085 d = Name.rfind('/', c); 1086 if (d == Name.npos) 1087 Idx = 0; 1088 else 1089 Idx = d+1; 1090 F = Name.slice(Idx, Idx + Foo.size()); 1091 DotFramework = Name.slice(Idx + Foo.size(), 1092 Idx + Foo.size() + sizeof(".framework/")-1); 1093 if (F == Foo && DotFramework == ".framework/") { 1094 isFramework = true; 1095 return Foo; 1096 } 1097 1098 guess_library: 1099 // pull off the suffix after the "." and make a point to it 1100 a = Name.rfind('.'); 1101 if (a == Name.npos || a == 0) 1102 return StringRef(); 1103 Dylib = Name.slice(a, Name.npos); 1104 if (Dylib != ".dylib") 1105 goto guess_qtx; 1106 1107 // First pull off the version letter for the form Foo.A.dylib if any. 1108 if (a >= 3) { 1109 Dot = Name.slice(a-2, a-1); 1110 if (Dot == ".") 1111 a = a - 2; 1112 } 1113 1114 b = Name.rfind('/', a); 1115 if (b == Name.npos) 1116 b = 0; 1117 else 1118 b = b+1; 1119 // ignore any suffix after an underbar like Foo_profile.A.dylib 1120 Idx = Name.find('_', b); 1121 if (Idx != Name.npos && Idx != b) { 1122 Lib = Name.slice(b, Idx); 1123 Suffix = Name.slice(Idx, a); 1124 } 1125 else 1126 Lib = Name.slice(b, a); 1127 // There are incorrect library names of the form: 1128 // libATS.A_profile.dylib so check for these. 1129 if (Lib.size() >= 3) { 1130 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1131 if (Dot == ".") 1132 Lib = Lib.slice(0, Lib.size()-2); 1133 } 1134 return Lib; 1135 1136 guess_qtx: 1137 Qtx = Name.slice(a, Name.npos); 1138 if (Qtx != ".qtx") 1139 return StringRef(); 1140 b = Name.rfind('/', a); 1141 if (b == Name.npos) 1142 Lib = Name.slice(0, a); 1143 else 1144 Lib = Name.slice(b+1, a); 1145 // There are library names of the form: QT.A.qtx so check for these. 1146 if (Lib.size() >= 3) { 1147 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1148 if (Dot == ".") 1149 Lib = Lib.slice(0, Lib.size()-2); 1150 } 1151 return Lib; 1152 } 1153 1154 // getLibraryShortNameByIndex() is used to get the short name of the library 1155 // for an undefined symbol in a linked Mach-O binary that was linked with the 1156 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1157 // It is passed the index (0 - based) of the library as translated from 1158 // GET_LIBRARY_ORDINAL (1 - based). 1159 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1160 StringRef &Res) { 1161 if (Index >= Libraries.size()) 1162 return object_error::parse_failed; 1163 1164 MachO::dylib_command D = 1165 getStruct<MachO::dylib_command>(this, Libraries[Index]); 1166 if (D.dylib.name >= D.cmdsize) 1167 return object_error::parse_failed; 1168 1169 // If the cache of LibrariesShortNames is not built up do that first for 1170 // all the Libraries. 1171 if (LibrariesShortNames.size() == 0) { 1172 for (unsigned i = 0; i < Libraries.size(); i++) { 1173 MachO::dylib_command D = 1174 getStruct<MachO::dylib_command>(this, Libraries[i]); 1175 if (D.dylib.name >= D.cmdsize) { 1176 LibrariesShortNames.push_back(StringRef()); 1177 continue; 1178 } 1179 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1180 StringRef Name = StringRef(P); 1181 StringRef Suffix; 1182 bool isFramework; 1183 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1184 if (shortName == StringRef()) 1185 LibrariesShortNames.push_back(Name); 1186 else 1187 LibrariesShortNames.push_back(shortName); 1188 } 1189 } 1190 1191 Res = LibrariesShortNames[Index]; 1192 return object_error::success; 1193 } 1194 1195 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1196 return getSymbolByIndex(0); 1197 } 1198 1199 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1200 DataRefImpl DRI; 1201 if (!SymtabLoadCmd) 1202 return basic_symbol_iterator(SymbolRef(DRI, this)); 1203 1204 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1205 unsigned SymbolTableEntrySize = is64Bit() ? 1206 sizeof(MachO::nlist_64) : 1207 sizeof(MachO::nlist); 1208 unsigned Offset = Symtab.symoff + 1209 Symtab.nsyms * SymbolTableEntrySize; 1210 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1211 return basic_symbol_iterator(SymbolRef(DRI, this)); 1212 } 1213 1214 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1215 DataRefImpl DRI; 1216 if (!SymtabLoadCmd) 1217 return basic_symbol_iterator(SymbolRef(DRI, this)); 1218 1219 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1220 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 1221 unsigned SymbolTableEntrySize = 1222 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1223 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1224 DRI.p += Index * SymbolTableEntrySize; 1225 return basic_symbol_iterator(SymbolRef(DRI, this)); 1226 } 1227 1228 section_iterator MachOObjectFile::section_begin() const { 1229 DataRefImpl DRI; 1230 return section_iterator(SectionRef(DRI, this)); 1231 } 1232 1233 section_iterator MachOObjectFile::section_end() const { 1234 DataRefImpl DRI; 1235 DRI.d.a = Sections.size(); 1236 return section_iterator(SectionRef(DRI, this)); 1237 } 1238 1239 uint8_t MachOObjectFile::getBytesInAddress() const { 1240 return is64Bit() ? 8 : 4; 1241 } 1242 1243 StringRef MachOObjectFile::getFileFormatName() const { 1244 unsigned CPUType = getCPUType(this); 1245 if (!is64Bit()) { 1246 switch (CPUType) { 1247 case llvm::MachO::CPU_TYPE_I386: 1248 return "Mach-O 32-bit i386"; 1249 case llvm::MachO::CPU_TYPE_ARM: 1250 return "Mach-O arm"; 1251 case llvm::MachO::CPU_TYPE_POWERPC: 1252 return "Mach-O 32-bit ppc"; 1253 default: 1254 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1255 "64-bit object file when we're not 64-bit?"); 1256 return "Mach-O 32-bit unknown"; 1257 } 1258 } 1259 1260 // Make sure the cpu type has the correct mask. 1261 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1262 == llvm::MachO::CPU_ARCH_ABI64 && 1263 "32-bit object file when we're 64-bit?"); 1264 1265 switch (CPUType) { 1266 case llvm::MachO::CPU_TYPE_X86_64: 1267 return "Mach-O 64-bit x86-64"; 1268 case llvm::MachO::CPU_TYPE_ARM64: 1269 return "Mach-O arm64"; 1270 case llvm::MachO::CPU_TYPE_POWERPC64: 1271 return "Mach-O 64-bit ppc64"; 1272 default: 1273 return "Mach-O 64-bit unknown"; 1274 } 1275 } 1276 1277 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1278 switch (CPUType) { 1279 case llvm::MachO::CPU_TYPE_I386: 1280 return Triple::x86; 1281 case llvm::MachO::CPU_TYPE_X86_64: 1282 return Triple::x86_64; 1283 case llvm::MachO::CPU_TYPE_ARM: 1284 return Triple::arm; 1285 case llvm::MachO::CPU_TYPE_ARM64: 1286 return Triple::aarch64; 1287 case llvm::MachO::CPU_TYPE_POWERPC: 1288 return Triple::ppc; 1289 case llvm::MachO::CPU_TYPE_POWERPC64: 1290 return Triple::ppc64; 1291 default: 1292 return Triple::UnknownArch; 1293 } 1294 } 1295 1296 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { 1297 switch (CPUType) { 1298 case MachO::CPU_TYPE_I386: 1299 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1300 case MachO::CPU_SUBTYPE_I386_ALL: 1301 return Triple("i386-apple-darwin"); 1302 default: 1303 return Triple(); 1304 } 1305 case MachO::CPU_TYPE_X86_64: 1306 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1307 case MachO::CPU_SUBTYPE_X86_64_ALL: 1308 return Triple("x86_64-apple-darwin"); 1309 case MachO::CPU_SUBTYPE_X86_64_H: 1310 return Triple("x86_64h-apple-darwin"); 1311 default: 1312 return Triple(); 1313 } 1314 case MachO::CPU_TYPE_ARM: 1315 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1316 case MachO::CPU_SUBTYPE_ARM_V4T: 1317 return Triple("armv4t-apple-darwin"); 1318 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1319 return Triple("armv5e-apple-darwin"); 1320 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1321 return Triple("xscale-apple-darwin"); 1322 case MachO::CPU_SUBTYPE_ARM_V6: 1323 return Triple("armv6-apple-darwin"); 1324 case MachO::CPU_SUBTYPE_ARM_V6M: 1325 return Triple("armv6m-apple-darwin"); 1326 case MachO::CPU_SUBTYPE_ARM_V7: 1327 return Triple("armv7-apple-darwin"); 1328 case MachO::CPU_SUBTYPE_ARM_V7EM: 1329 return Triple("armv7em-apple-darwin"); 1330 case MachO::CPU_SUBTYPE_ARM_V7K: 1331 return Triple("armv7k-apple-darwin"); 1332 case MachO::CPU_SUBTYPE_ARM_V7M: 1333 return Triple("armv7m-apple-darwin"); 1334 case MachO::CPU_SUBTYPE_ARM_V7S: 1335 return Triple("armv7s-apple-darwin"); 1336 default: 1337 return Triple(); 1338 } 1339 case MachO::CPU_TYPE_ARM64: 1340 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1341 case MachO::CPU_SUBTYPE_ARM64_ALL: 1342 return Triple("arm64-apple-darwin"); 1343 default: 1344 return Triple(); 1345 } 1346 case MachO::CPU_TYPE_POWERPC: 1347 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1348 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1349 return Triple("ppc-apple-darwin"); 1350 default: 1351 return Triple(); 1352 } 1353 case MachO::CPU_TYPE_POWERPC64: 1354 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1355 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1356 return Triple("ppc64-apple-darwin"); 1357 default: 1358 return Triple(); 1359 } 1360 default: 1361 return Triple(); 1362 } 1363 } 1364 1365 Triple MachOObjectFile::getHostArch() { 1366 return Triple(sys::getDefaultTargetTriple()); 1367 } 1368 1369 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1370 return StringSwitch<bool>(ArchFlag) 1371 .Case("i386", true) 1372 .Case("x86_64", true) 1373 .Case("x86_64h", true) 1374 .Case("armv4t", true) 1375 .Case("arm", true) 1376 .Case("armv5e", true) 1377 .Case("armv6", true) 1378 .Case("armv6m", true) 1379 .Case("armv7em", true) 1380 .Case("armv7k", true) 1381 .Case("armv7m", true) 1382 .Case("armv7s", true) 1383 .Case("arm64", true) 1384 .Case("ppc", true) 1385 .Case("ppc64", true) 1386 .Default(false); 1387 } 1388 1389 unsigned MachOObjectFile::getArch() const { 1390 return getArch(getCPUType(this)); 1391 } 1392 1393 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1394 DataRefImpl DRI; 1395 DRI.d.a = Index; 1396 return section_rel_begin(DRI); 1397 } 1398 1399 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1400 DataRefImpl DRI; 1401 DRI.d.a = Index; 1402 return section_rel_end(DRI); 1403 } 1404 1405 dice_iterator MachOObjectFile::begin_dices() const { 1406 DataRefImpl DRI; 1407 if (!DataInCodeLoadCmd) 1408 return dice_iterator(DiceRef(DRI, this)); 1409 1410 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1411 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1412 return dice_iterator(DiceRef(DRI, this)); 1413 } 1414 1415 dice_iterator MachOObjectFile::end_dices() const { 1416 DataRefImpl DRI; 1417 if (!DataInCodeLoadCmd) 1418 return dice_iterator(DiceRef(DRI, this)); 1419 1420 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1421 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1422 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1423 return dice_iterator(DiceRef(DRI, this)); 1424 } 1425 1426 StringRef 1427 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1428 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1429 return parseSegmentOrSectionName(Raw.data()); 1430 } 1431 1432 ArrayRef<char> 1433 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1434 const section_base *Base = 1435 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1436 return ArrayRef<char>(Base->sectname); 1437 } 1438 1439 ArrayRef<char> 1440 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1441 const section_base *Base = 1442 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1443 return ArrayRef<char>(Base->segname); 1444 } 1445 1446 bool 1447 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1448 const { 1449 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1450 return false; 1451 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1452 } 1453 1454 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1455 const MachO::any_relocation_info &RE) const { 1456 if (isLittleEndian()) 1457 return RE.r_word1 & 0xffffff; 1458 return RE.r_word1 >> 8; 1459 } 1460 1461 bool MachOObjectFile::getPlainRelocationExternal( 1462 const MachO::any_relocation_info &RE) const { 1463 if (isLittleEndian()) 1464 return (RE.r_word1 >> 27) & 1; 1465 return (RE.r_word1 >> 4) & 1; 1466 } 1467 1468 bool MachOObjectFile::getScatteredRelocationScattered( 1469 const MachO::any_relocation_info &RE) const { 1470 return RE.r_word0 >> 31; 1471 } 1472 1473 uint32_t MachOObjectFile::getScatteredRelocationValue( 1474 const MachO::any_relocation_info &RE) const { 1475 return RE.r_word1; 1476 } 1477 1478 unsigned MachOObjectFile::getAnyRelocationAddress( 1479 const MachO::any_relocation_info &RE) const { 1480 if (isRelocationScattered(RE)) 1481 return getScatteredRelocationAddress(RE); 1482 return getPlainRelocationAddress(RE); 1483 } 1484 1485 unsigned MachOObjectFile::getAnyRelocationPCRel( 1486 const MachO::any_relocation_info &RE) const { 1487 if (isRelocationScattered(RE)) 1488 return getScatteredRelocationPCRel(this, RE); 1489 return getPlainRelocationPCRel(this, RE); 1490 } 1491 1492 unsigned MachOObjectFile::getAnyRelocationLength( 1493 const MachO::any_relocation_info &RE) const { 1494 if (isRelocationScattered(RE)) 1495 return getScatteredRelocationLength(RE); 1496 return getPlainRelocationLength(this, RE); 1497 } 1498 1499 unsigned 1500 MachOObjectFile::getAnyRelocationType( 1501 const MachO::any_relocation_info &RE) const { 1502 if (isRelocationScattered(RE)) 1503 return getScatteredRelocationType(RE); 1504 return getPlainRelocationType(this, RE); 1505 } 1506 1507 SectionRef 1508 MachOObjectFile::getRelocationSection( 1509 const MachO::any_relocation_info &RE) const { 1510 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1511 return *section_end(); 1512 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1513 DataRefImpl DRI; 1514 DRI.d.a = SecNum; 1515 return SectionRef(DRI, this); 1516 } 1517 1518 MachOObjectFile::LoadCommandInfo 1519 MachOObjectFile::getFirstLoadCommandInfo() const { 1520 MachOObjectFile::LoadCommandInfo Load; 1521 1522 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1523 sizeof(MachO::mach_header); 1524 Load.Ptr = getPtr(this, HeaderSize); 1525 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1526 return Load; 1527 } 1528 1529 MachOObjectFile::LoadCommandInfo 1530 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1531 MachOObjectFile::LoadCommandInfo Next; 1532 Next.Ptr = L.Ptr + L.C.cmdsize; 1533 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1534 return Next; 1535 } 1536 1537 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1538 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1539 } 1540 1541 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1542 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1543 } 1544 1545 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1546 unsigned Index) const { 1547 const char *Sec = getSectionPtr(this, L, Index); 1548 return getStruct<MachO::section>(this, Sec); 1549 } 1550 1551 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1552 unsigned Index) const { 1553 const char *Sec = getSectionPtr(this, L, Index); 1554 return getStruct<MachO::section_64>(this, Sec); 1555 } 1556 1557 MachO::nlist 1558 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1559 const char *P = reinterpret_cast<const char *>(DRI.p); 1560 return getStruct<MachO::nlist>(this, P); 1561 } 1562 1563 MachO::nlist_64 1564 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1565 const char *P = reinterpret_cast<const char *>(DRI.p); 1566 return getStruct<MachO::nlist_64>(this, P); 1567 } 1568 1569 MachO::linkedit_data_command 1570 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1571 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1572 } 1573 1574 MachO::segment_command 1575 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1576 return getStruct<MachO::segment_command>(this, L.Ptr); 1577 } 1578 1579 MachO::segment_command_64 1580 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1581 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1582 } 1583 1584 MachO::linker_options_command 1585 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1586 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1587 } 1588 1589 MachO::version_min_command 1590 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1591 return getStruct<MachO::version_min_command>(this, L.Ptr); 1592 } 1593 1594 MachO::dylib_command 1595 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 1596 return getStruct<MachO::dylib_command>(this, L.Ptr); 1597 } 1598 1599 1600 MachO::any_relocation_info 1601 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1602 DataRefImpl Sec; 1603 Sec.d.a = Rel.d.a; 1604 uint32_t Offset; 1605 if (is64Bit()) { 1606 MachO::section_64 Sect = getSection64(Sec); 1607 Offset = Sect.reloff; 1608 } else { 1609 MachO::section Sect = getSection(Sec); 1610 Offset = Sect.reloff; 1611 } 1612 1613 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 1614 getPtr(this, Offset)) + Rel.d.b; 1615 return getStruct<MachO::any_relocation_info>( 1616 this, reinterpret_cast<const char *>(P)); 1617 } 1618 1619 MachO::data_in_code_entry 1620 MachOObjectFile::getDice(DataRefImpl Rel) const { 1621 const char *P = reinterpret_cast<const char *>(Rel.p); 1622 return getStruct<MachO::data_in_code_entry>(this, P); 1623 } 1624 1625 MachO::mach_header MachOObjectFile::getHeader() const { 1626 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1627 } 1628 1629 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1630 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1631 } 1632 1633 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1634 const MachO::dysymtab_command &DLC, 1635 unsigned Index) const { 1636 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1637 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1638 } 1639 1640 MachO::data_in_code_entry 1641 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1642 unsigned Index) const { 1643 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1644 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1645 } 1646 1647 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1648 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1649 } 1650 1651 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1652 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1653 } 1654 1655 MachO::linkedit_data_command 1656 MachOObjectFile::getDataInCodeLoadCommand() const { 1657 if (DataInCodeLoadCmd) 1658 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1659 1660 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1661 MachO::linkedit_data_command Cmd; 1662 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1663 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1664 Cmd.dataoff = 0; 1665 Cmd.datasize = 0; 1666 return Cmd; 1667 } 1668 1669 StringRef MachOObjectFile::getStringTableData() const { 1670 MachO::symtab_command S = getSymtabLoadCommand(); 1671 return getData().substr(S.stroff, S.strsize); 1672 } 1673 1674 bool MachOObjectFile::is64Bit() const { 1675 return getType() == getMachOType(false, true) || 1676 getType() == getMachOType(true, true); 1677 } 1678 1679 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1680 SmallVectorImpl<uint64_t> &Out) const { 1681 DataExtractor extractor(ObjectFile::getData(), true, 0); 1682 1683 uint32_t offset = Index; 1684 uint64_t data = 0; 1685 while (uint64_t delta = extractor.getULEB128(&offset)) { 1686 data += delta; 1687 Out.push_back(data); 1688 } 1689 } 1690 1691 ErrorOr<std::unique_ptr<MachOObjectFile>> 1692 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) { 1693 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1694 std::error_code EC; 1695 std::unique_ptr<MachOObjectFile> Ret; 1696 if (Magic == "\xFE\xED\xFA\xCE") 1697 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); 1698 else if (Magic == "\xCE\xFA\xED\xFE") 1699 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); 1700 else if (Magic == "\xFE\xED\xFA\xCF") 1701 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); 1702 else if (Magic == "\xCF\xFA\xED\xFE") 1703 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); 1704 else 1705 return object_error::parse_failed; 1706 1707 if (EC) 1708 return EC; 1709 return std::move(Ret); 1710 } 1711 1712