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 std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1013 LibraryRef &Res) const { 1014 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1015 } 1016 1017 std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1018 StringRef &Res) const { 1019 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1020 } 1021 1022 // 1023 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1024 // guess on what the short name is. Then name is returned as a substring of the 1025 // StringRef Name passed in. The name of the dynamic library is recognized as 1026 // a framework if it has one of the two following forms: 1027 // Foo.framework/Versions/A/Foo 1028 // Foo.framework/Foo 1029 // Where A and Foo can be any string. And may contain a trailing suffix 1030 // starting with an underbar. If the Name is recognized as a framework then 1031 // isFramework is set to true else it is set to false. If the Name has a 1032 // suffix then Suffix is set to the substring in Name that contains the suffix 1033 // else it is set to a NULL StringRef. 1034 // 1035 // The Name of the dynamic library is recognized as a library name if it has 1036 // one of the two following forms: 1037 // libFoo.A.dylib 1038 // libFoo.dylib 1039 // The library may have a suffix trailing the name Foo of the form: 1040 // libFoo_profile.A.dylib 1041 // libFoo_profile.dylib 1042 // 1043 // The Name of the dynamic library is also recognized as a library name if it 1044 // has the following form: 1045 // Foo.qtx 1046 // 1047 // If the Name of the dynamic library is none of the forms above then a NULL 1048 // StringRef is returned. 1049 // 1050 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1051 bool &isFramework, 1052 StringRef &Suffix) { 1053 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1054 size_t a, b, c, d, Idx; 1055 1056 isFramework = false; 1057 Suffix = StringRef(); 1058 1059 // Pull off the last component and make Foo point to it 1060 a = Name.rfind('/'); 1061 if (a == Name.npos || a == 0) 1062 goto guess_library; 1063 Foo = Name.slice(a+1, Name.npos); 1064 1065 // Look for a suffix starting with a '_' 1066 Idx = Foo.rfind('_'); 1067 if (Idx != Foo.npos && Foo.size() >= 2) { 1068 Suffix = Foo.slice(Idx, Foo.npos); 1069 Foo = Foo.slice(0, Idx); 1070 } 1071 1072 // First look for the form Foo.framework/Foo 1073 b = Name.rfind('/', a); 1074 if (b == Name.npos) 1075 Idx = 0; 1076 else 1077 Idx = b+1; 1078 F = Name.slice(Idx, Idx + Foo.size()); 1079 DotFramework = Name.slice(Idx + Foo.size(), 1080 Idx + Foo.size() + sizeof(".framework/")-1); 1081 if (F == Foo && DotFramework == ".framework/") { 1082 isFramework = true; 1083 return Foo; 1084 } 1085 1086 // Next look for the form Foo.framework/Versions/A/Foo 1087 if (b == Name.npos) 1088 goto guess_library; 1089 c = Name.rfind('/', b); 1090 if (c == Name.npos || c == 0) 1091 goto guess_library; 1092 V = Name.slice(c+1, Name.npos); 1093 if (!V.startswith("Versions/")) 1094 goto guess_library; 1095 d = Name.rfind('/', c); 1096 if (d == Name.npos) 1097 Idx = 0; 1098 else 1099 Idx = d+1; 1100 F = Name.slice(Idx, Idx + Foo.size()); 1101 DotFramework = Name.slice(Idx + Foo.size(), 1102 Idx + Foo.size() + sizeof(".framework/")-1); 1103 if (F == Foo && DotFramework == ".framework/") { 1104 isFramework = true; 1105 return Foo; 1106 } 1107 1108 guess_library: 1109 // pull off the suffix after the "." and make a point to it 1110 a = Name.rfind('.'); 1111 if (a == Name.npos || a == 0) 1112 return StringRef(); 1113 Dylib = Name.slice(a, Name.npos); 1114 if (Dylib != ".dylib") 1115 goto guess_qtx; 1116 1117 // First pull off the version letter for the form Foo.A.dylib if any. 1118 if (a >= 3) { 1119 Dot = Name.slice(a-2, a-1); 1120 if (Dot == ".") 1121 a = a - 2; 1122 } 1123 1124 b = Name.rfind('/', a); 1125 if (b == Name.npos) 1126 b = 0; 1127 else 1128 b = b+1; 1129 // ignore any suffix after an underbar like Foo_profile.A.dylib 1130 Idx = Name.find('_', b); 1131 if (Idx != Name.npos && Idx != b) { 1132 Lib = Name.slice(b, Idx); 1133 Suffix = Name.slice(Idx, a); 1134 } 1135 else 1136 Lib = Name.slice(b, a); 1137 // There are incorrect library names of the form: 1138 // libATS.A_profile.dylib so check for these. 1139 if (Lib.size() >= 3) { 1140 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1141 if (Dot == ".") 1142 Lib = Lib.slice(0, Lib.size()-2); 1143 } 1144 return Lib; 1145 1146 guess_qtx: 1147 Qtx = Name.slice(a, Name.npos); 1148 if (Qtx != ".qtx") 1149 return StringRef(); 1150 b = Name.rfind('/', a); 1151 if (b == Name.npos) 1152 Lib = Name.slice(0, a); 1153 else 1154 Lib = Name.slice(b+1, a); 1155 // There are library names of the form: QT.A.qtx so check for these. 1156 if (Lib.size() >= 3) { 1157 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1158 if (Dot == ".") 1159 Lib = Lib.slice(0, Lib.size()-2); 1160 } 1161 return Lib; 1162 } 1163 1164 // getLibraryShortNameByIndex() is used to get the short name of the library 1165 // for an undefined symbol in a linked Mach-O binary that was linked with the 1166 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1167 // It is passed the index (0 - based) of the library as translated from 1168 // GET_LIBRARY_ORDINAL (1 - based). 1169 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1170 StringRef &Res) { 1171 if (Index >= Libraries.size()) 1172 return object_error::parse_failed; 1173 1174 MachO::dylib_command D = 1175 getStruct<MachO::dylib_command>(this, Libraries[Index]); 1176 if (D.dylib.name >= D.cmdsize) 1177 return object_error::parse_failed; 1178 1179 // If the cache of LibrariesShortNames is not built up do that first for 1180 // all the Libraries. 1181 if (LibrariesShortNames.size() == 0) { 1182 for (unsigned i = 0; i < Libraries.size(); i++) { 1183 MachO::dylib_command D = 1184 getStruct<MachO::dylib_command>(this, Libraries[i]); 1185 if (D.dylib.name >= D.cmdsize) { 1186 LibrariesShortNames.push_back(StringRef()); 1187 continue; 1188 } 1189 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1190 StringRef Name = StringRef(P); 1191 StringRef Suffix; 1192 bool isFramework; 1193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1194 if (shortName == StringRef()) 1195 LibrariesShortNames.push_back(Name); 1196 else 1197 LibrariesShortNames.push_back(shortName); 1198 } 1199 } 1200 1201 Res = LibrariesShortNames[Index]; 1202 return object_error::success; 1203 } 1204 1205 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1206 return getSymbolByIndex(0); 1207 } 1208 1209 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1210 DataRefImpl DRI; 1211 if (!SymtabLoadCmd) 1212 return basic_symbol_iterator(SymbolRef(DRI, this)); 1213 1214 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1215 unsigned SymbolTableEntrySize = is64Bit() ? 1216 sizeof(MachO::nlist_64) : 1217 sizeof(MachO::nlist); 1218 unsigned Offset = Symtab.symoff + 1219 Symtab.nsyms * SymbolTableEntrySize; 1220 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1221 return basic_symbol_iterator(SymbolRef(DRI, this)); 1222 } 1223 1224 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1225 DataRefImpl DRI; 1226 if (!SymtabLoadCmd) 1227 return basic_symbol_iterator(SymbolRef(DRI, this)); 1228 1229 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1230 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 1231 unsigned SymbolTableEntrySize = 1232 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1233 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1234 DRI.p += Index * SymbolTableEntrySize; 1235 return basic_symbol_iterator(SymbolRef(DRI, this)); 1236 } 1237 1238 section_iterator MachOObjectFile::section_begin() const { 1239 DataRefImpl DRI; 1240 return section_iterator(SectionRef(DRI, this)); 1241 } 1242 1243 section_iterator MachOObjectFile::section_end() const { 1244 DataRefImpl DRI; 1245 DRI.d.a = Sections.size(); 1246 return section_iterator(SectionRef(DRI, this)); 1247 } 1248 1249 library_iterator MachOObjectFile::needed_library_begin() const { 1250 // TODO: implement 1251 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1252 } 1253 1254 library_iterator MachOObjectFile::needed_library_end() const { 1255 // TODO: implement 1256 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1257 } 1258 1259 uint8_t MachOObjectFile::getBytesInAddress() const { 1260 return is64Bit() ? 8 : 4; 1261 } 1262 1263 StringRef MachOObjectFile::getFileFormatName() const { 1264 unsigned CPUType = getCPUType(this); 1265 if (!is64Bit()) { 1266 switch (CPUType) { 1267 case llvm::MachO::CPU_TYPE_I386: 1268 return "Mach-O 32-bit i386"; 1269 case llvm::MachO::CPU_TYPE_ARM: 1270 return "Mach-O arm"; 1271 case llvm::MachO::CPU_TYPE_POWERPC: 1272 return "Mach-O 32-bit ppc"; 1273 default: 1274 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1275 "64-bit object file when we're not 64-bit?"); 1276 return "Mach-O 32-bit unknown"; 1277 } 1278 } 1279 1280 // Make sure the cpu type has the correct mask. 1281 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1282 == llvm::MachO::CPU_ARCH_ABI64 && 1283 "32-bit object file when we're 64-bit?"); 1284 1285 switch (CPUType) { 1286 case llvm::MachO::CPU_TYPE_X86_64: 1287 return "Mach-O 64-bit x86-64"; 1288 case llvm::MachO::CPU_TYPE_ARM64: 1289 return "Mach-O arm64"; 1290 case llvm::MachO::CPU_TYPE_POWERPC64: 1291 return "Mach-O 64-bit ppc64"; 1292 default: 1293 return "Mach-O 64-bit unknown"; 1294 } 1295 } 1296 1297 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1298 switch (CPUType) { 1299 case llvm::MachO::CPU_TYPE_I386: 1300 return Triple::x86; 1301 case llvm::MachO::CPU_TYPE_X86_64: 1302 return Triple::x86_64; 1303 case llvm::MachO::CPU_TYPE_ARM: 1304 return Triple::arm; 1305 case llvm::MachO::CPU_TYPE_ARM64: 1306 return Triple::aarch64; 1307 case llvm::MachO::CPU_TYPE_POWERPC: 1308 return Triple::ppc; 1309 case llvm::MachO::CPU_TYPE_POWERPC64: 1310 return Triple::ppc64; 1311 default: 1312 return Triple::UnknownArch; 1313 } 1314 } 1315 1316 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { 1317 switch (CPUType) { 1318 case MachO::CPU_TYPE_I386: 1319 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1320 case MachO::CPU_SUBTYPE_I386_ALL: 1321 return Triple("i386-apple-darwin"); 1322 default: 1323 return Triple(); 1324 } 1325 case MachO::CPU_TYPE_X86_64: 1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1327 case MachO::CPU_SUBTYPE_X86_64_ALL: 1328 return Triple("x86_64-apple-darwin"); 1329 case MachO::CPU_SUBTYPE_X86_64_H: 1330 return Triple("x86_64h-apple-darwin"); 1331 default: 1332 return Triple(); 1333 } 1334 case MachO::CPU_TYPE_ARM: 1335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1336 case MachO::CPU_SUBTYPE_ARM_V4T: 1337 return Triple("armv4t-apple-darwin"); 1338 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1339 return Triple("armv5e-apple-darwin"); 1340 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1341 return Triple("xscale-apple-darwin"); 1342 case MachO::CPU_SUBTYPE_ARM_V6: 1343 return Triple("armv6-apple-darwin"); 1344 case MachO::CPU_SUBTYPE_ARM_V6M: 1345 return Triple("armv6m-apple-darwin"); 1346 case MachO::CPU_SUBTYPE_ARM_V7: 1347 return Triple("armv7-apple-darwin"); 1348 case MachO::CPU_SUBTYPE_ARM_V7EM: 1349 return Triple("armv7em-apple-darwin"); 1350 case MachO::CPU_SUBTYPE_ARM_V7K: 1351 return Triple("armv7k-apple-darwin"); 1352 case MachO::CPU_SUBTYPE_ARM_V7M: 1353 return Triple("armv7m-apple-darwin"); 1354 case MachO::CPU_SUBTYPE_ARM_V7S: 1355 return Triple("armv7s-apple-darwin"); 1356 default: 1357 return Triple(); 1358 } 1359 case MachO::CPU_TYPE_ARM64: 1360 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1361 case MachO::CPU_SUBTYPE_ARM64_ALL: 1362 return Triple("arm64-apple-darwin"); 1363 default: 1364 return Triple(); 1365 } 1366 case MachO::CPU_TYPE_POWERPC: 1367 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1368 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1369 return Triple("ppc-apple-darwin"); 1370 default: 1371 return Triple(); 1372 } 1373 case MachO::CPU_TYPE_POWERPC64: 1374 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1375 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1376 return Triple("ppc64-apple-darwin"); 1377 default: 1378 return Triple(); 1379 } 1380 default: 1381 return Triple(); 1382 } 1383 } 1384 1385 Triple MachOObjectFile::getHostArch() { 1386 return Triple(sys::getDefaultTargetTriple()); 1387 } 1388 1389 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1390 return StringSwitch<bool>(ArchFlag) 1391 .Case("i386", true) 1392 .Case("x86_64", true) 1393 .Case("x86_64h", true) 1394 .Case("armv4t", true) 1395 .Case("arm", true) 1396 .Case("armv5e", true) 1397 .Case("armv6", true) 1398 .Case("armv6m", true) 1399 .Case("armv7em", true) 1400 .Case("armv7k", true) 1401 .Case("armv7m", true) 1402 .Case("armv7s", true) 1403 .Case("arm64", true) 1404 .Case("ppc", true) 1405 .Case("ppc64", true) 1406 .Default(false); 1407 } 1408 1409 unsigned MachOObjectFile::getArch() const { 1410 return getArch(getCPUType(this)); 1411 } 1412 1413 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1414 DataRefImpl DRI; 1415 DRI.d.a = Index; 1416 return section_rel_begin(DRI); 1417 } 1418 1419 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1420 DataRefImpl DRI; 1421 DRI.d.a = Index; 1422 return section_rel_end(DRI); 1423 } 1424 1425 dice_iterator MachOObjectFile::begin_dices() const { 1426 DataRefImpl DRI; 1427 if (!DataInCodeLoadCmd) 1428 return dice_iterator(DiceRef(DRI, this)); 1429 1430 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1431 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1432 return dice_iterator(DiceRef(DRI, this)); 1433 } 1434 1435 dice_iterator MachOObjectFile::end_dices() const { 1436 DataRefImpl DRI; 1437 if (!DataInCodeLoadCmd) 1438 return dice_iterator(DiceRef(DRI, this)); 1439 1440 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1441 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1442 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1443 return dice_iterator(DiceRef(DRI, this)); 1444 } 1445 1446 StringRef 1447 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1448 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1449 return parseSegmentOrSectionName(Raw.data()); 1450 } 1451 1452 ArrayRef<char> 1453 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1454 const section_base *Base = 1455 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1456 return ArrayRef<char>(Base->sectname); 1457 } 1458 1459 ArrayRef<char> 1460 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1461 const section_base *Base = 1462 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1463 return ArrayRef<char>(Base->segname); 1464 } 1465 1466 bool 1467 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1468 const { 1469 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1470 return false; 1471 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1472 } 1473 1474 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1475 const MachO::any_relocation_info &RE) const { 1476 if (isLittleEndian()) 1477 return RE.r_word1 & 0xffffff; 1478 return RE.r_word1 >> 8; 1479 } 1480 1481 bool MachOObjectFile::getPlainRelocationExternal( 1482 const MachO::any_relocation_info &RE) const { 1483 if (isLittleEndian()) 1484 return (RE.r_word1 >> 27) & 1; 1485 return (RE.r_word1 >> 4) & 1; 1486 } 1487 1488 bool MachOObjectFile::getScatteredRelocationScattered( 1489 const MachO::any_relocation_info &RE) const { 1490 return RE.r_word0 >> 31; 1491 } 1492 1493 uint32_t MachOObjectFile::getScatteredRelocationValue( 1494 const MachO::any_relocation_info &RE) const { 1495 return RE.r_word1; 1496 } 1497 1498 unsigned MachOObjectFile::getAnyRelocationAddress( 1499 const MachO::any_relocation_info &RE) const { 1500 if (isRelocationScattered(RE)) 1501 return getScatteredRelocationAddress(RE); 1502 return getPlainRelocationAddress(RE); 1503 } 1504 1505 unsigned MachOObjectFile::getAnyRelocationPCRel( 1506 const MachO::any_relocation_info &RE) const { 1507 if (isRelocationScattered(RE)) 1508 return getScatteredRelocationPCRel(this, RE); 1509 return getPlainRelocationPCRel(this, RE); 1510 } 1511 1512 unsigned MachOObjectFile::getAnyRelocationLength( 1513 const MachO::any_relocation_info &RE) const { 1514 if (isRelocationScattered(RE)) 1515 return getScatteredRelocationLength(RE); 1516 return getPlainRelocationLength(this, RE); 1517 } 1518 1519 unsigned 1520 MachOObjectFile::getAnyRelocationType( 1521 const MachO::any_relocation_info &RE) const { 1522 if (isRelocationScattered(RE)) 1523 return getScatteredRelocationType(RE); 1524 return getPlainRelocationType(this, RE); 1525 } 1526 1527 SectionRef 1528 MachOObjectFile::getRelocationSection( 1529 const MachO::any_relocation_info &RE) const { 1530 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1531 return *section_end(); 1532 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1533 DataRefImpl DRI; 1534 DRI.d.a = SecNum; 1535 return SectionRef(DRI, this); 1536 } 1537 1538 MachOObjectFile::LoadCommandInfo 1539 MachOObjectFile::getFirstLoadCommandInfo() const { 1540 MachOObjectFile::LoadCommandInfo Load; 1541 1542 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1543 sizeof(MachO::mach_header); 1544 Load.Ptr = getPtr(this, HeaderSize); 1545 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1546 return Load; 1547 } 1548 1549 MachOObjectFile::LoadCommandInfo 1550 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1551 MachOObjectFile::LoadCommandInfo Next; 1552 Next.Ptr = L.Ptr + L.C.cmdsize; 1553 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1554 return Next; 1555 } 1556 1557 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1558 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1559 } 1560 1561 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1562 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1563 } 1564 1565 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1566 unsigned Index) const { 1567 const char *Sec = getSectionPtr(this, L, Index); 1568 return getStruct<MachO::section>(this, Sec); 1569 } 1570 1571 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1572 unsigned Index) const { 1573 const char *Sec = getSectionPtr(this, L, Index); 1574 return getStruct<MachO::section_64>(this, Sec); 1575 } 1576 1577 MachO::nlist 1578 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1579 const char *P = reinterpret_cast<const char *>(DRI.p); 1580 return getStruct<MachO::nlist>(this, P); 1581 } 1582 1583 MachO::nlist_64 1584 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1585 const char *P = reinterpret_cast<const char *>(DRI.p); 1586 return getStruct<MachO::nlist_64>(this, P); 1587 } 1588 1589 MachO::linkedit_data_command 1590 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1591 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1592 } 1593 1594 MachO::segment_command 1595 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1596 return getStruct<MachO::segment_command>(this, L.Ptr); 1597 } 1598 1599 MachO::segment_command_64 1600 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1601 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1602 } 1603 1604 MachO::linker_options_command 1605 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1606 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1607 } 1608 1609 MachO::version_min_command 1610 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1611 return getStruct<MachO::version_min_command>(this, L.Ptr); 1612 } 1613 1614 MachO::dylib_command 1615 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 1616 return getStruct<MachO::dylib_command>(this, L.Ptr); 1617 } 1618 1619 1620 MachO::any_relocation_info 1621 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1622 DataRefImpl Sec; 1623 Sec.d.a = Rel.d.a; 1624 uint32_t Offset; 1625 if (is64Bit()) { 1626 MachO::section_64 Sect = getSection64(Sec); 1627 Offset = Sect.reloff; 1628 } else { 1629 MachO::section Sect = getSection(Sec); 1630 Offset = Sect.reloff; 1631 } 1632 1633 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 1634 getPtr(this, Offset)) + Rel.d.b; 1635 return getStruct<MachO::any_relocation_info>( 1636 this, reinterpret_cast<const char *>(P)); 1637 } 1638 1639 MachO::data_in_code_entry 1640 MachOObjectFile::getDice(DataRefImpl Rel) const { 1641 const char *P = reinterpret_cast<const char *>(Rel.p); 1642 return getStruct<MachO::data_in_code_entry>(this, P); 1643 } 1644 1645 MachO::mach_header MachOObjectFile::getHeader() const { 1646 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1647 } 1648 1649 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1650 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1651 } 1652 1653 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1654 const MachO::dysymtab_command &DLC, 1655 unsigned Index) const { 1656 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1657 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1658 } 1659 1660 MachO::data_in_code_entry 1661 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1662 unsigned Index) const { 1663 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1664 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1665 } 1666 1667 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1668 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1669 } 1670 1671 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1672 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1673 } 1674 1675 MachO::linkedit_data_command 1676 MachOObjectFile::getDataInCodeLoadCommand() const { 1677 if (DataInCodeLoadCmd) 1678 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1679 1680 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1681 MachO::linkedit_data_command Cmd; 1682 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1683 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1684 Cmd.dataoff = 0; 1685 Cmd.datasize = 0; 1686 return Cmd; 1687 } 1688 1689 StringRef MachOObjectFile::getStringTableData() const { 1690 MachO::symtab_command S = getSymtabLoadCommand(); 1691 return getData().substr(S.stroff, S.strsize); 1692 } 1693 1694 bool MachOObjectFile::is64Bit() const { 1695 return getType() == getMachOType(false, true) || 1696 getType() == getMachOType(true, true); 1697 } 1698 1699 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1700 SmallVectorImpl<uint64_t> &Out) const { 1701 DataExtractor extractor(ObjectFile::getData(), true, 0); 1702 1703 uint32_t offset = Index; 1704 uint64_t data = 0; 1705 while (uint64_t delta = extractor.getULEB128(&offset)) { 1706 data += delta; 1707 Out.push_back(data); 1708 } 1709 } 1710 1711 ErrorOr<std::unique_ptr<MachOObjectFile>> 1712 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) { 1713 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1714 std::error_code EC; 1715 std::unique_ptr<MachOObjectFile> Ret; 1716 if (Magic == "\xFE\xED\xFA\xCE") 1717 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); 1718 else if (Magic == "\xCE\xFA\xED\xFE") 1719 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); 1720 else if (Magic == "\xFE\xED\xFA\xCF") 1721 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); 1722 else if (Magic == "\xCF\xFA\xED\xFE") 1723 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); 1724 else 1725 return object_error::parse_failed; 1726 1727 if (EC) 1728 return EC; 1729 return std::move(Ret); 1730 } 1731 1732