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