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(MemoryBufferRef Object, bool IsLittleEndian, 226 bool Is64bits, std::error_code &EC) 227 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), 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 (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 442 Result |= SymbolRef::SF_Thumb; 443 444 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 445 Result |= SymbolRef::SF_Absolute; 446 447 return Result; 448 } 449 450 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 451 section_iterator &Res) const { 452 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 453 uint8_t index = Entry.n_sect; 454 455 if (index == 0) { 456 Res = section_end(); 457 } else { 458 DataRefImpl DRI; 459 DRI.d.a = index - 1; 460 Res = section_iterator(SectionRef(DRI, this)); 461 } 462 463 return object_error::success; 464 } 465 466 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 467 Sec.d.a++; 468 } 469 470 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 471 StringRef &Result) const { 472 ArrayRef<char> Raw = getSectionRawName(Sec); 473 Result = parseSegmentOrSectionName(Raw.data()); 474 return object_error::success; 475 } 476 477 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 478 uint64_t &Res) const { 479 if (is64Bit()) { 480 MachO::section_64 Sect = getSection64(Sec); 481 Res = Sect.addr; 482 } else { 483 MachO::section Sect = getSection(Sec); 484 Res = Sect.addr; 485 } 486 return object_error::success; 487 } 488 489 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 490 uint64_t &Res) const { 491 if (is64Bit()) { 492 MachO::section_64 Sect = getSection64(Sec); 493 Res = Sect.size; 494 } else { 495 MachO::section Sect = getSection(Sec); 496 Res = Sect.size; 497 } 498 499 return object_error::success; 500 } 501 502 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 503 StringRef &Res) const { 504 uint32_t Offset; 505 uint64_t Size; 506 507 if (is64Bit()) { 508 MachO::section_64 Sect = getSection64(Sec); 509 Offset = Sect.offset; 510 Size = Sect.size; 511 } else { 512 MachO::section Sect = getSection(Sec); 513 Offset = Sect.offset; 514 Size = Sect.size; 515 } 516 517 Res = this->getData().substr(Offset, Size); 518 return object_error::success; 519 } 520 521 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 522 uint64_t &Res) const { 523 uint32_t Align; 524 if (is64Bit()) { 525 MachO::section_64 Sect = getSection64(Sec); 526 Align = Sect.align; 527 } else { 528 MachO::section Sect = getSection(Sec); 529 Align = Sect.align; 530 } 531 532 Res = uint64_t(1) << Align; 533 return object_error::success; 534 } 535 536 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 537 bool &Res) const { 538 uint32_t Flags = getSectionFlags(this, Sec); 539 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 540 return object_error::success; 541 } 542 543 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 544 bool &Result) const { 545 uint32_t Flags = getSectionFlags(this, Sec); 546 unsigned SectionType = Flags & MachO::SECTION_TYPE; 547 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 548 !(SectionType == MachO::S_ZEROFILL || 549 SectionType == MachO::S_GB_ZEROFILL); 550 return object_error::success; 551 } 552 553 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 554 bool &Result) const { 555 uint32_t Flags = getSectionFlags(this, Sec); 556 unsigned SectionType = Flags & MachO::SECTION_TYPE; 557 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 558 (SectionType == MachO::S_ZEROFILL || 559 SectionType == MachO::S_GB_ZEROFILL); 560 return object_error::success; 561 } 562 563 std::error_code 564 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 565 bool &Result) const { 566 // FIXME: Unimplemented. 567 Result = true; 568 return object_error::success; 569 } 570 571 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 572 bool &Result) const { 573 // FIXME: Unimplemented. 574 Result = false; 575 return object_error::success; 576 } 577 578 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 579 bool &Res) const { 580 uint32_t Flags = getSectionFlags(this, Sec); 581 unsigned SectionType = Flags & MachO::SECTION_TYPE; 582 Res = SectionType == MachO::S_ZEROFILL || 583 SectionType == MachO::S_GB_ZEROFILL; 584 return object_error::success; 585 } 586 587 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 588 bool &Result) const { 589 // Consider using the code from isSectionText to look for __const sections. 590 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 591 // to use section attributes to distinguish code from data. 592 593 // FIXME: Unimplemented. 594 Result = false; 595 return object_error::success; 596 } 597 598 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 599 DataRefImpl Symb, 600 bool &Result) const { 601 SymbolRef::Type ST; 602 this->getSymbolType(Symb, ST); 603 if (ST == SymbolRef::ST_Unknown) { 604 Result = false; 605 return object_error::success; 606 } 607 608 uint64_t SectBegin, SectEnd; 609 getSectionAddress(Sec, SectBegin); 610 getSectionSize(Sec, SectEnd); 611 SectEnd += SectBegin; 612 613 uint64_t SymAddr; 614 getSymbolAddress(Symb, SymAddr); 615 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 616 617 return object_error::success; 618 } 619 620 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 621 DataRefImpl Ret; 622 Ret.d.a = Sec.d.a; 623 Ret.d.b = 0; 624 return relocation_iterator(RelocationRef(Ret, this)); 625 } 626 627 relocation_iterator 628 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 629 uint32_t Num; 630 if (is64Bit()) { 631 MachO::section_64 Sect = getSection64(Sec); 632 Num = Sect.nreloc; 633 } else { 634 MachO::section Sect = getSection(Sec); 635 Num = Sect.nreloc; 636 } 637 638 DataRefImpl Ret; 639 Ret.d.a = Sec.d.a; 640 Ret.d.b = Num; 641 return relocation_iterator(RelocationRef(Ret, this)); 642 } 643 644 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 645 ++Rel.d.b; 646 } 647 648 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 649 uint64_t &Res) const { 650 uint64_t Offset; 651 getRelocationOffset(Rel, Offset); 652 653 DataRefImpl Sec; 654 Sec.d.a = Rel.d.a; 655 uint64_t SecAddress; 656 getSectionAddress(Sec, SecAddress); 657 Res = SecAddress + Offset; 658 return object_error::success; 659 } 660 661 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 662 uint64_t &Res) const { 663 assert(getHeader().filetype == MachO::MH_OBJECT && 664 "Only implemented for MH_OBJECT"); 665 MachO::any_relocation_info RE = getRelocation(Rel); 666 Res = getAnyRelocationAddress(RE); 667 return object_error::success; 668 } 669 670 symbol_iterator 671 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 672 MachO::any_relocation_info RE = getRelocation(Rel); 673 if (isRelocationScattered(RE)) 674 return symbol_end(); 675 676 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 677 bool isExtern = getPlainRelocationExternal(RE); 678 if (!isExtern) 679 return symbol_end(); 680 681 MachO::symtab_command S = getSymtabLoadCommand(); 682 unsigned SymbolTableEntrySize = is64Bit() ? 683 sizeof(MachO::nlist_64) : 684 sizeof(MachO::nlist); 685 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 686 DataRefImpl Sym; 687 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 688 return symbol_iterator(SymbolRef(Sym, this)); 689 } 690 691 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 692 uint64_t &Res) const { 693 MachO::any_relocation_info RE = getRelocation(Rel); 694 Res = getAnyRelocationType(RE); 695 return object_error::success; 696 } 697 698 std::error_code 699 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 700 SmallVectorImpl<char> &Result) const { 701 StringRef res; 702 uint64_t RType; 703 getRelocationType(Rel, RType); 704 705 unsigned Arch = this->getArch(); 706 707 switch (Arch) { 708 case Triple::x86: { 709 static const char *const Table[] = { 710 "GENERIC_RELOC_VANILLA", 711 "GENERIC_RELOC_PAIR", 712 "GENERIC_RELOC_SECTDIFF", 713 "GENERIC_RELOC_PB_LA_PTR", 714 "GENERIC_RELOC_LOCAL_SECTDIFF", 715 "GENERIC_RELOC_TLV" }; 716 717 if (RType > 5) 718 res = "Unknown"; 719 else 720 res = Table[RType]; 721 break; 722 } 723 case Triple::x86_64: { 724 static const char *const Table[] = { 725 "X86_64_RELOC_UNSIGNED", 726 "X86_64_RELOC_SIGNED", 727 "X86_64_RELOC_BRANCH", 728 "X86_64_RELOC_GOT_LOAD", 729 "X86_64_RELOC_GOT", 730 "X86_64_RELOC_SUBTRACTOR", 731 "X86_64_RELOC_SIGNED_1", 732 "X86_64_RELOC_SIGNED_2", 733 "X86_64_RELOC_SIGNED_4", 734 "X86_64_RELOC_TLV" }; 735 736 if (RType > 9) 737 res = "Unknown"; 738 else 739 res = Table[RType]; 740 break; 741 } 742 case Triple::arm: { 743 static const char *const Table[] = { 744 "ARM_RELOC_VANILLA", 745 "ARM_RELOC_PAIR", 746 "ARM_RELOC_SECTDIFF", 747 "ARM_RELOC_LOCAL_SECTDIFF", 748 "ARM_RELOC_PB_LA_PTR", 749 "ARM_RELOC_BR24", 750 "ARM_THUMB_RELOC_BR22", 751 "ARM_THUMB_32BIT_BRANCH", 752 "ARM_RELOC_HALF", 753 "ARM_RELOC_HALF_SECTDIFF" }; 754 755 if (RType > 9) 756 res = "Unknown"; 757 else 758 res = Table[RType]; 759 break; 760 } 761 case Triple::aarch64: { 762 static const char *const Table[] = { 763 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 764 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 765 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 766 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 767 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 768 "ARM64_RELOC_ADDEND" 769 }; 770 771 if (RType >= array_lengthof(Table)) 772 res = "Unknown"; 773 else 774 res = Table[RType]; 775 break; 776 } 777 case Triple::ppc: { 778 static const char *const Table[] = { 779 "PPC_RELOC_VANILLA", 780 "PPC_RELOC_PAIR", 781 "PPC_RELOC_BR14", 782 "PPC_RELOC_BR24", 783 "PPC_RELOC_HI16", 784 "PPC_RELOC_LO16", 785 "PPC_RELOC_HA16", 786 "PPC_RELOC_LO14", 787 "PPC_RELOC_SECTDIFF", 788 "PPC_RELOC_PB_LA_PTR", 789 "PPC_RELOC_HI16_SECTDIFF", 790 "PPC_RELOC_LO16_SECTDIFF", 791 "PPC_RELOC_HA16_SECTDIFF", 792 "PPC_RELOC_JBSR", 793 "PPC_RELOC_LO14_SECTDIFF", 794 "PPC_RELOC_LOCAL_SECTDIFF" }; 795 796 if (RType > 15) 797 res = "Unknown"; 798 else 799 res = Table[RType]; 800 break; 801 } 802 case Triple::UnknownArch: 803 res = "Unknown"; 804 break; 805 } 806 Result.append(res.begin(), res.end()); 807 return object_error::success; 808 } 809 810 std::error_code 811 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 812 SmallVectorImpl<char> &Result) const { 813 MachO::any_relocation_info RE = getRelocation(Rel); 814 815 unsigned Arch = this->getArch(); 816 817 std::string fmtbuf; 818 raw_string_ostream fmt(fmtbuf); 819 unsigned Type = this->getAnyRelocationType(RE); 820 bool IsPCRel = this->getAnyRelocationPCRel(RE); 821 822 // Determine any addends that should be displayed with the relocation. 823 // These require decoding the relocation type, which is triple-specific. 824 825 // X86_64 has entirely custom relocation types. 826 if (Arch == Triple::x86_64) { 827 bool isPCRel = getAnyRelocationPCRel(RE); 828 829 switch (Type) { 830 case MachO::X86_64_RELOC_GOT_LOAD: 831 case MachO::X86_64_RELOC_GOT: { 832 printRelocationTargetName(this, RE, fmt); 833 fmt << "@GOT"; 834 if (isPCRel) fmt << "PCREL"; 835 break; 836 } 837 case MachO::X86_64_RELOC_SUBTRACTOR: { 838 DataRefImpl RelNext = Rel; 839 moveRelocationNext(RelNext); 840 MachO::any_relocation_info RENext = getRelocation(RelNext); 841 842 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 843 // X86_64_RELOC_UNSIGNED. 844 // NOTE: Scattered relocations don't exist on x86_64. 845 unsigned RType = getAnyRelocationType(RENext); 846 if (RType != MachO::X86_64_RELOC_UNSIGNED) 847 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 848 "X86_64_RELOC_SUBTRACTOR."); 849 850 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 851 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 852 printRelocationTargetName(this, RENext, fmt); 853 fmt << "-"; 854 printRelocationTargetName(this, RE, fmt); 855 break; 856 } 857 case MachO::X86_64_RELOC_TLV: 858 printRelocationTargetName(this, RE, fmt); 859 fmt << "@TLV"; 860 if (isPCRel) fmt << "P"; 861 break; 862 case MachO::X86_64_RELOC_SIGNED_1: 863 printRelocationTargetName(this, RE, fmt); 864 fmt << "-1"; 865 break; 866 case MachO::X86_64_RELOC_SIGNED_2: 867 printRelocationTargetName(this, RE, fmt); 868 fmt << "-2"; 869 break; 870 case MachO::X86_64_RELOC_SIGNED_4: 871 printRelocationTargetName(this, RE, fmt); 872 fmt << "-4"; 873 break; 874 default: 875 printRelocationTargetName(this, RE, fmt); 876 break; 877 } 878 // X86 and ARM share some relocation types in common. 879 } else if (Arch == Triple::x86 || Arch == Triple::arm || 880 Arch == Triple::ppc) { 881 // Generic relocation types... 882 switch (Type) { 883 case MachO::GENERIC_RELOC_PAIR: // prints no info 884 return object_error::success; 885 case MachO::GENERIC_RELOC_SECTDIFF: { 886 DataRefImpl RelNext = Rel; 887 moveRelocationNext(RelNext); 888 MachO::any_relocation_info RENext = getRelocation(RelNext); 889 890 // X86 sect diff's must be followed by a relocation of type 891 // GENERIC_RELOC_PAIR. 892 unsigned RType = getAnyRelocationType(RENext); 893 894 if (RType != MachO::GENERIC_RELOC_PAIR) 895 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 896 "GENERIC_RELOC_SECTDIFF."); 897 898 printRelocationTargetName(this, RE, fmt); 899 fmt << "-"; 900 printRelocationTargetName(this, RENext, fmt); 901 break; 902 } 903 } 904 905 if (Arch == Triple::x86 || Arch == Triple::ppc) { 906 switch (Type) { 907 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 908 DataRefImpl RelNext = Rel; 909 moveRelocationNext(RelNext); 910 MachO::any_relocation_info RENext = getRelocation(RelNext); 911 912 // X86 sect diff's must be followed by a relocation of type 913 // GENERIC_RELOC_PAIR. 914 unsigned RType = getAnyRelocationType(RENext); 915 if (RType != MachO::GENERIC_RELOC_PAIR) 916 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 917 "GENERIC_RELOC_LOCAL_SECTDIFF."); 918 919 printRelocationTargetName(this, RE, fmt); 920 fmt << "-"; 921 printRelocationTargetName(this, RENext, fmt); 922 break; 923 } 924 case MachO::GENERIC_RELOC_TLV: { 925 printRelocationTargetName(this, RE, fmt); 926 fmt << "@TLV"; 927 if (IsPCRel) fmt << "P"; 928 break; 929 } 930 default: 931 printRelocationTargetName(this, RE, fmt); 932 } 933 } else { // ARM-specific relocations 934 switch (Type) { 935 case MachO::ARM_RELOC_HALF: 936 case MachO::ARM_RELOC_HALF_SECTDIFF: { 937 // Half relocations steal a bit from the length field to encode 938 // whether this is an upper16 or a lower16 relocation. 939 bool isUpper = getAnyRelocationLength(RE) >> 1; 940 941 if (isUpper) 942 fmt << ":upper16:("; 943 else 944 fmt << ":lower16:("; 945 printRelocationTargetName(this, RE, fmt); 946 947 DataRefImpl RelNext = Rel; 948 moveRelocationNext(RelNext); 949 MachO::any_relocation_info RENext = getRelocation(RelNext); 950 951 // ARM half relocs must be followed by a relocation of type 952 // ARM_RELOC_PAIR. 953 unsigned RType = getAnyRelocationType(RENext); 954 if (RType != MachO::ARM_RELOC_PAIR) 955 report_fatal_error("Expected ARM_RELOC_PAIR after " 956 "ARM_RELOC_HALF"); 957 958 // NOTE: The half of the target virtual address is stashed in the 959 // address field of the secondary relocation, but we can't reverse 960 // engineer the constant offset from it without decoding the movw/movt 961 // instruction to find the other half in its immediate field. 962 963 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 964 // symbol/section pointer of the follow-on relocation. 965 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 966 fmt << "-"; 967 printRelocationTargetName(this, RENext, fmt); 968 } 969 970 fmt << ")"; 971 break; 972 } 973 default: { 974 printRelocationTargetName(this, RE, fmt); 975 } 976 } 977 } 978 } else 979 printRelocationTargetName(this, RE, fmt); 980 981 fmt.flush(); 982 Result.append(fmtbuf.begin(), fmtbuf.end()); 983 return object_error::success; 984 } 985 986 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 987 bool &Result) const { 988 unsigned Arch = getArch(); 989 uint64_t Type; 990 getRelocationType(Rel, Type); 991 992 Result = false; 993 994 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 995 // is always hidden. 996 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 997 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 998 } else if (Arch == Triple::x86_64) { 999 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1000 // an X86_64_RELOC_SUBTRACTOR. 1001 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1002 DataRefImpl RelPrev = Rel; 1003 RelPrev.d.a--; 1004 uint64_t PrevType; 1005 getRelocationType(RelPrev, PrevType); 1006 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1007 Result = true; 1008 } 1009 } 1010 1011 return object_error::success; 1012 } 1013 1014 // 1015 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1016 // guess on what the short name is. Then name is returned as a substring of the 1017 // StringRef Name passed in. The name of the dynamic library is recognized as 1018 // a framework if it has one of the two following forms: 1019 // Foo.framework/Versions/A/Foo 1020 // Foo.framework/Foo 1021 // Where A and Foo can be any string. And may contain a trailing suffix 1022 // starting with an underbar. If the Name is recognized as a framework then 1023 // isFramework is set to true else it is set to false. If the Name has a 1024 // suffix then Suffix is set to the substring in Name that contains the suffix 1025 // else it is set to a NULL StringRef. 1026 // 1027 // The Name of the dynamic library is recognized as a library name if it has 1028 // one of the two following forms: 1029 // libFoo.A.dylib 1030 // libFoo.dylib 1031 // The library may have a suffix trailing the name Foo of the form: 1032 // libFoo_profile.A.dylib 1033 // libFoo_profile.dylib 1034 // 1035 // The Name of the dynamic library is also recognized as a library name if it 1036 // has the following form: 1037 // Foo.qtx 1038 // 1039 // If the Name of the dynamic library is none of the forms above then a NULL 1040 // StringRef is returned. 1041 // 1042 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1043 bool &isFramework, 1044 StringRef &Suffix) { 1045 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1046 size_t a, b, c, d, Idx; 1047 1048 isFramework = false; 1049 Suffix = StringRef(); 1050 1051 // Pull off the last component and make Foo point to it 1052 a = Name.rfind('/'); 1053 if (a == Name.npos || a == 0) 1054 goto guess_library; 1055 Foo = Name.slice(a+1, Name.npos); 1056 1057 // Look for a suffix starting with a '_' 1058 Idx = Foo.rfind('_'); 1059 if (Idx != Foo.npos && Foo.size() >= 2) { 1060 Suffix = Foo.slice(Idx, Foo.npos); 1061 Foo = Foo.slice(0, Idx); 1062 } 1063 1064 // First look for the form Foo.framework/Foo 1065 b = Name.rfind('/', a); 1066 if (b == Name.npos) 1067 Idx = 0; 1068 else 1069 Idx = b+1; 1070 F = Name.slice(Idx, Idx + Foo.size()); 1071 DotFramework = Name.slice(Idx + Foo.size(), 1072 Idx + Foo.size() + sizeof(".framework/")-1); 1073 if (F == Foo && DotFramework == ".framework/") { 1074 isFramework = true; 1075 return Foo; 1076 } 1077 1078 // Next look for the form Foo.framework/Versions/A/Foo 1079 if (b == Name.npos) 1080 goto guess_library; 1081 c = Name.rfind('/', b); 1082 if (c == Name.npos || c == 0) 1083 goto guess_library; 1084 V = Name.slice(c+1, Name.npos); 1085 if (!V.startswith("Versions/")) 1086 goto guess_library; 1087 d = Name.rfind('/', c); 1088 if (d == Name.npos) 1089 Idx = 0; 1090 else 1091 Idx = d+1; 1092 F = Name.slice(Idx, Idx + Foo.size()); 1093 DotFramework = Name.slice(Idx + Foo.size(), 1094 Idx + Foo.size() + sizeof(".framework/")-1); 1095 if (F == Foo && DotFramework == ".framework/") { 1096 isFramework = true; 1097 return Foo; 1098 } 1099 1100 guess_library: 1101 // pull off the suffix after the "." and make a point to it 1102 a = Name.rfind('.'); 1103 if (a == Name.npos || a == 0) 1104 return StringRef(); 1105 Dylib = Name.slice(a, Name.npos); 1106 if (Dylib != ".dylib") 1107 goto guess_qtx; 1108 1109 // First pull off the version letter for the form Foo.A.dylib if any. 1110 if (a >= 3) { 1111 Dot = Name.slice(a-2, a-1); 1112 if (Dot == ".") 1113 a = a - 2; 1114 } 1115 1116 b = Name.rfind('/', a); 1117 if (b == Name.npos) 1118 b = 0; 1119 else 1120 b = b+1; 1121 // ignore any suffix after an underbar like Foo_profile.A.dylib 1122 Idx = Name.find('_', b); 1123 if (Idx != Name.npos && Idx != b) { 1124 Lib = Name.slice(b, Idx); 1125 Suffix = Name.slice(Idx, a); 1126 } 1127 else 1128 Lib = Name.slice(b, a); 1129 // There are incorrect library names of the form: 1130 // libATS.A_profile.dylib so check for these. 1131 if (Lib.size() >= 3) { 1132 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1133 if (Dot == ".") 1134 Lib = Lib.slice(0, Lib.size()-2); 1135 } 1136 return Lib; 1137 1138 guess_qtx: 1139 Qtx = Name.slice(a, Name.npos); 1140 if (Qtx != ".qtx") 1141 return StringRef(); 1142 b = Name.rfind('/', a); 1143 if (b == Name.npos) 1144 Lib = Name.slice(0, a); 1145 else 1146 Lib = Name.slice(b+1, a); 1147 // There are library names of the form: QT.A.qtx so check for these. 1148 if (Lib.size() >= 3) { 1149 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1150 if (Dot == ".") 1151 Lib = Lib.slice(0, Lib.size()-2); 1152 } 1153 return Lib; 1154 } 1155 1156 // getLibraryShortNameByIndex() is used to get the short name of the library 1157 // for an undefined symbol in a linked Mach-O binary that was linked with the 1158 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1159 // It is passed the index (0 - based) of the library as translated from 1160 // GET_LIBRARY_ORDINAL (1 - based). 1161 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1162 StringRef &Res) { 1163 if (Index >= Libraries.size()) 1164 return object_error::parse_failed; 1165 1166 MachO::dylib_command D = 1167 getStruct<MachO::dylib_command>(this, Libraries[Index]); 1168 if (D.dylib.name >= D.cmdsize) 1169 return object_error::parse_failed; 1170 1171 // If the cache of LibrariesShortNames is not built up do that first for 1172 // all the Libraries. 1173 if (LibrariesShortNames.size() == 0) { 1174 for (unsigned i = 0; i < Libraries.size(); i++) { 1175 MachO::dylib_command D = 1176 getStruct<MachO::dylib_command>(this, Libraries[i]); 1177 if (D.dylib.name >= D.cmdsize) { 1178 LibrariesShortNames.push_back(StringRef()); 1179 continue; 1180 } 1181 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1182 StringRef Name = StringRef(P); 1183 StringRef Suffix; 1184 bool isFramework; 1185 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1186 if (shortName == StringRef()) 1187 LibrariesShortNames.push_back(Name); 1188 else 1189 LibrariesShortNames.push_back(shortName); 1190 } 1191 } 1192 1193 Res = LibrariesShortNames[Index]; 1194 return object_error::success; 1195 } 1196 1197 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1198 return getSymbolByIndex(0); 1199 } 1200 1201 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1202 DataRefImpl DRI; 1203 if (!SymtabLoadCmd) 1204 return basic_symbol_iterator(SymbolRef(DRI, this)); 1205 1206 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1207 unsigned SymbolTableEntrySize = is64Bit() ? 1208 sizeof(MachO::nlist_64) : 1209 sizeof(MachO::nlist); 1210 unsigned Offset = Symtab.symoff + 1211 Symtab.nsyms * SymbolTableEntrySize; 1212 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1213 return basic_symbol_iterator(SymbolRef(DRI, this)); 1214 } 1215 1216 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1217 DataRefImpl DRI; 1218 if (!SymtabLoadCmd) 1219 return basic_symbol_iterator(SymbolRef(DRI, this)); 1220 1221 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1222 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 1223 unsigned SymbolTableEntrySize = 1224 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1225 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1226 DRI.p += Index * SymbolTableEntrySize; 1227 return basic_symbol_iterator(SymbolRef(DRI, this)); 1228 } 1229 1230 section_iterator MachOObjectFile::section_begin() const { 1231 DataRefImpl DRI; 1232 return section_iterator(SectionRef(DRI, this)); 1233 } 1234 1235 section_iterator MachOObjectFile::section_end() const { 1236 DataRefImpl DRI; 1237 DRI.d.a = Sections.size(); 1238 return section_iterator(SectionRef(DRI, this)); 1239 } 1240 1241 uint8_t MachOObjectFile::getBytesInAddress() const { 1242 return is64Bit() ? 8 : 4; 1243 } 1244 1245 StringRef MachOObjectFile::getFileFormatName() const { 1246 unsigned CPUType = getCPUType(this); 1247 if (!is64Bit()) { 1248 switch (CPUType) { 1249 case llvm::MachO::CPU_TYPE_I386: 1250 return "Mach-O 32-bit i386"; 1251 case llvm::MachO::CPU_TYPE_ARM: 1252 return "Mach-O arm"; 1253 case llvm::MachO::CPU_TYPE_POWERPC: 1254 return "Mach-O 32-bit ppc"; 1255 default: 1256 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1257 "64-bit object file when we're not 64-bit?"); 1258 return "Mach-O 32-bit unknown"; 1259 } 1260 } 1261 1262 // Make sure the cpu type has the correct mask. 1263 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1264 == llvm::MachO::CPU_ARCH_ABI64 && 1265 "32-bit object file when we're 64-bit?"); 1266 1267 switch (CPUType) { 1268 case llvm::MachO::CPU_TYPE_X86_64: 1269 return "Mach-O 64-bit x86-64"; 1270 case llvm::MachO::CPU_TYPE_ARM64: 1271 return "Mach-O arm64"; 1272 case llvm::MachO::CPU_TYPE_POWERPC64: 1273 return "Mach-O 64-bit ppc64"; 1274 default: 1275 return "Mach-O 64-bit unknown"; 1276 } 1277 } 1278 1279 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1280 switch (CPUType) { 1281 case llvm::MachO::CPU_TYPE_I386: 1282 return Triple::x86; 1283 case llvm::MachO::CPU_TYPE_X86_64: 1284 return Triple::x86_64; 1285 case llvm::MachO::CPU_TYPE_ARM: 1286 return Triple::arm; 1287 case llvm::MachO::CPU_TYPE_ARM64: 1288 return Triple::aarch64; 1289 case llvm::MachO::CPU_TYPE_POWERPC: 1290 return Triple::ppc; 1291 case llvm::MachO::CPU_TYPE_POWERPC64: 1292 return Triple::ppc64; 1293 default: 1294 return Triple::UnknownArch; 1295 } 1296 } 1297 1298 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 1299 const char **McpuDefault) { 1300 if (McpuDefault) 1301 *McpuDefault = nullptr; 1302 1303 switch (CPUType) { 1304 case MachO::CPU_TYPE_I386: 1305 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1306 case MachO::CPU_SUBTYPE_I386_ALL: 1307 return Triple("i386-apple-darwin"); 1308 default: 1309 return Triple(); 1310 } 1311 case MachO::CPU_TYPE_X86_64: 1312 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1313 case MachO::CPU_SUBTYPE_X86_64_ALL: 1314 return Triple("x86_64-apple-darwin"); 1315 case MachO::CPU_SUBTYPE_X86_64_H: 1316 return Triple("x86_64h-apple-darwin"); 1317 default: 1318 return Triple(); 1319 } 1320 case MachO::CPU_TYPE_ARM: 1321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1322 case MachO::CPU_SUBTYPE_ARM_V4T: 1323 return Triple("armv4t-apple-darwin"); 1324 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1325 return Triple("armv5e-apple-darwin"); 1326 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1327 return Triple("xscale-apple-darwin"); 1328 case MachO::CPU_SUBTYPE_ARM_V6: 1329 return Triple("armv6-apple-darwin"); 1330 case MachO::CPU_SUBTYPE_ARM_V6M: 1331 if (McpuDefault) 1332 *McpuDefault = "cortex-m0"; 1333 return Triple("armv6m-apple-darwin"); 1334 case MachO::CPU_SUBTYPE_ARM_V7: 1335 return Triple("armv7-apple-darwin"); 1336 case MachO::CPU_SUBTYPE_ARM_V7EM: 1337 if (McpuDefault) 1338 *McpuDefault = "cortex-m4"; 1339 return Triple("armv7em-apple-darwin"); 1340 case MachO::CPU_SUBTYPE_ARM_V7K: 1341 return Triple("armv7k-apple-darwin"); 1342 case MachO::CPU_SUBTYPE_ARM_V7M: 1343 if (McpuDefault) 1344 *McpuDefault = "cortex-m3"; 1345 return Triple("armv7m-apple-darwin"); 1346 case MachO::CPU_SUBTYPE_ARM_V7S: 1347 return Triple("armv7s-apple-darwin"); 1348 default: 1349 return Triple(); 1350 } 1351 case MachO::CPU_TYPE_ARM64: 1352 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1353 case MachO::CPU_SUBTYPE_ARM64_ALL: 1354 return Triple("arm64-apple-darwin"); 1355 default: 1356 return Triple(); 1357 } 1358 case MachO::CPU_TYPE_POWERPC: 1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1360 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1361 return Triple("ppc-apple-darwin"); 1362 default: 1363 return Triple(); 1364 } 1365 case MachO::CPU_TYPE_POWERPC64: 1366 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1367 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1368 return Triple("ppc64-apple-darwin"); 1369 default: 1370 return Triple(); 1371 } 1372 default: 1373 return Triple(); 1374 } 1375 } 1376 1377 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, 1378 const char **McpuDefault) { 1379 if (McpuDefault) 1380 *McpuDefault = nullptr; 1381 1382 switch (CPUType) { 1383 case MachO::CPU_TYPE_ARM: 1384 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1385 case MachO::CPU_SUBTYPE_ARM_V4T: 1386 return Triple("thumbv4t-apple-darwin"); 1387 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1388 return Triple("thumbv5e-apple-darwin"); 1389 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1390 return Triple("xscale-apple-darwin"); 1391 case MachO::CPU_SUBTYPE_ARM_V6: 1392 return Triple("thumbv6-apple-darwin"); 1393 case MachO::CPU_SUBTYPE_ARM_V6M: 1394 if (McpuDefault) 1395 *McpuDefault = "cortex-m0"; 1396 return Triple("thumbv6m-apple-darwin"); 1397 case MachO::CPU_SUBTYPE_ARM_V7: 1398 return Triple("thumbv7-apple-darwin"); 1399 case MachO::CPU_SUBTYPE_ARM_V7EM: 1400 if (McpuDefault) 1401 *McpuDefault = "cortex-m4"; 1402 return Triple("thumbv7em-apple-darwin"); 1403 case MachO::CPU_SUBTYPE_ARM_V7K: 1404 return Triple("thumbv7k-apple-darwin"); 1405 case MachO::CPU_SUBTYPE_ARM_V7M: 1406 if (McpuDefault) 1407 *McpuDefault = "cortex-m3"; 1408 return Triple("thumbv7m-apple-darwin"); 1409 case MachO::CPU_SUBTYPE_ARM_V7S: 1410 return Triple("thumbv7s-apple-darwin"); 1411 default: 1412 return Triple(); 1413 } 1414 default: 1415 return Triple(); 1416 } 1417 } 1418 1419 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 1420 const char **McpuDefault, 1421 Triple *ThumbTriple) { 1422 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); 1423 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, 1424 McpuDefault); 1425 return T; 1426 } 1427 1428 Triple MachOObjectFile::getHostArch() { 1429 return Triple(sys::getDefaultTargetTriple()); 1430 } 1431 1432 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1433 return StringSwitch<bool>(ArchFlag) 1434 .Case("i386", true) 1435 .Case("x86_64", true) 1436 .Case("x86_64h", true) 1437 .Case("armv4t", true) 1438 .Case("arm", true) 1439 .Case("armv5e", true) 1440 .Case("armv6", true) 1441 .Case("armv6m", true) 1442 .Case("armv7em", true) 1443 .Case("armv7k", true) 1444 .Case("armv7m", true) 1445 .Case("armv7s", true) 1446 .Case("arm64", true) 1447 .Case("ppc", true) 1448 .Case("ppc64", true) 1449 .Default(false); 1450 } 1451 1452 unsigned MachOObjectFile::getArch() const { 1453 return getArch(getCPUType(this)); 1454 } 1455 1456 Triple MachOObjectFile::getArch(const char **McpuDefault, 1457 Triple *ThumbTriple) const { 1458 Triple T; 1459 if (is64Bit()) { 1460 MachO::mach_header_64 H_64; 1461 H_64 = getHeader64(); 1462 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault); 1463 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype, 1464 McpuDefault); 1465 } else { 1466 MachO::mach_header H; 1467 H = getHeader(); 1468 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault); 1469 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype, 1470 McpuDefault); 1471 } 1472 return T; 1473 } 1474 1475 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1476 DataRefImpl DRI; 1477 DRI.d.a = Index; 1478 return section_rel_begin(DRI); 1479 } 1480 1481 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1482 DataRefImpl DRI; 1483 DRI.d.a = Index; 1484 return section_rel_end(DRI); 1485 } 1486 1487 dice_iterator MachOObjectFile::begin_dices() const { 1488 DataRefImpl DRI; 1489 if (!DataInCodeLoadCmd) 1490 return dice_iterator(DiceRef(DRI, this)); 1491 1492 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1493 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1494 return dice_iterator(DiceRef(DRI, this)); 1495 } 1496 1497 dice_iterator MachOObjectFile::end_dices() const { 1498 DataRefImpl DRI; 1499 if (!DataInCodeLoadCmd) 1500 return dice_iterator(DiceRef(DRI, this)); 1501 1502 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1503 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1504 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1505 return dice_iterator(DiceRef(DRI, this)); 1506 } 1507 1508 StringRef 1509 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1510 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1511 return parseSegmentOrSectionName(Raw.data()); 1512 } 1513 1514 ArrayRef<char> 1515 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1516 const section_base *Base = 1517 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1518 return ArrayRef<char>(Base->sectname); 1519 } 1520 1521 ArrayRef<char> 1522 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1523 const section_base *Base = 1524 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1525 return ArrayRef<char>(Base->segname); 1526 } 1527 1528 bool 1529 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1530 const { 1531 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1532 return false; 1533 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1534 } 1535 1536 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1537 const MachO::any_relocation_info &RE) const { 1538 if (isLittleEndian()) 1539 return RE.r_word1 & 0xffffff; 1540 return RE.r_word1 >> 8; 1541 } 1542 1543 bool MachOObjectFile::getPlainRelocationExternal( 1544 const MachO::any_relocation_info &RE) const { 1545 if (isLittleEndian()) 1546 return (RE.r_word1 >> 27) & 1; 1547 return (RE.r_word1 >> 4) & 1; 1548 } 1549 1550 bool MachOObjectFile::getScatteredRelocationScattered( 1551 const MachO::any_relocation_info &RE) const { 1552 return RE.r_word0 >> 31; 1553 } 1554 1555 uint32_t MachOObjectFile::getScatteredRelocationValue( 1556 const MachO::any_relocation_info &RE) const { 1557 return RE.r_word1; 1558 } 1559 1560 unsigned MachOObjectFile::getAnyRelocationAddress( 1561 const MachO::any_relocation_info &RE) const { 1562 if (isRelocationScattered(RE)) 1563 return getScatteredRelocationAddress(RE); 1564 return getPlainRelocationAddress(RE); 1565 } 1566 1567 unsigned MachOObjectFile::getAnyRelocationPCRel( 1568 const MachO::any_relocation_info &RE) const { 1569 if (isRelocationScattered(RE)) 1570 return getScatteredRelocationPCRel(this, RE); 1571 return getPlainRelocationPCRel(this, RE); 1572 } 1573 1574 unsigned MachOObjectFile::getAnyRelocationLength( 1575 const MachO::any_relocation_info &RE) const { 1576 if (isRelocationScattered(RE)) 1577 return getScatteredRelocationLength(RE); 1578 return getPlainRelocationLength(this, RE); 1579 } 1580 1581 unsigned 1582 MachOObjectFile::getAnyRelocationType( 1583 const MachO::any_relocation_info &RE) const { 1584 if (isRelocationScattered(RE)) 1585 return getScatteredRelocationType(RE); 1586 return getPlainRelocationType(this, RE); 1587 } 1588 1589 SectionRef 1590 MachOObjectFile::getRelocationSection( 1591 const MachO::any_relocation_info &RE) const { 1592 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1593 return *section_end(); 1594 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1595 DataRefImpl DRI; 1596 DRI.d.a = SecNum; 1597 return SectionRef(DRI, this); 1598 } 1599 1600 MachOObjectFile::LoadCommandInfo 1601 MachOObjectFile::getFirstLoadCommandInfo() const { 1602 MachOObjectFile::LoadCommandInfo Load; 1603 1604 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1605 sizeof(MachO::mach_header); 1606 Load.Ptr = getPtr(this, HeaderSize); 1607 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1608 return Load; 1609 } 1610 1611 MachOObjectFile::LoadCommandInfo 1612 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1613 MachOObjectFile::LoadCommandInfo Next; 1614 Next.Ptr = L.Ptr + L.C.cmdsize; 1615 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1616 return Next; 1617 } 1618 1619 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1620 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1621 } 1622 1623 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1624 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1625 } 1626 1627 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1628 unsigned Index) const { 1629 const char *Sec = getSectionPtr(this, L, Index); 1630 return getStruct<MachO::section>(this, Sec); 1631 } 1632 1633 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1634 unsigned Index) const { 1635 const char *Sec = getSectionPtr(this, L, Index); 1636 return getStruct<MachO::section_64>(this, Sec); 1637 } 1638 1639 MachO::nlist 1640 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1641 const char *P = reinterpret_cast<const char *>(DRI.p); 1642 return getStruct<MachO::nlist>(this, P); 1643 } 1644 1645 MachO::nlist_64 1646 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1647 const char *P = reinterpret_cast<const char *>(DRI.p); 1648 return getStruct<MachO::nlist_64>(this, P); 1649 } 1650 1651 MachO::linkedit_data_command 1652 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1653 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1654 } 1655 1656 MachO::segment_command 1657 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1658 return getStruct<MachO::segment_command>(this, L.Ptr); 1659 } 1660 1661 MachO::segment_command_64 1662 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1663 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1664 } 1665 1666 MachO::linker_options_command 1667 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1668 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1669 } 1670 1671 MachO::version_min_command 1672 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1673 return getStruct<MachO::version_min_command>(this, L.Ptr); 1674 } 1675 1676 MachO::dylib_command 1677 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 1678 return getStruct<MachO::dylib_command>(this, L.Ptr); 1679 } 1680 1681 1682 MachO::any_relocation_info 1683 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1684 DataRefImpl Sec; 1685 Sec.d.a = Rel.d.a; 1686 uint32_t Offset; 1687 if (is64Bit()) { 1688 MachO::section_64 Sect = getSection64(Sec); 1689 Offset = Sect.reloff; 1690 } else { 1691 MachO::section Sect = getSection(Sec); 1692 Offset = Sect.reloff; 1693 } 1694 1695 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 1696 getPtr(this, Offset)) + Rel.d.b; 1697 return getStruct<MachO::any_relocation_info>( 1698 this, reinterpret_cast<const char *>(P)); 1699 } 1700 1701 MachO::data_in_code_entry 1702 MachOObjectFile::getDice(DataRefImpl Rel) const { 1703 const char *P = reinterpret_cast<const char *>(Rel.p); 1704 return getStruct<MachO::data_in_code_entry>(this, P); 1705 } 1706 1707 MachO::mach_header MachOObjectFile::getHeader() const { 1708 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1709 } 1710 1711 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1712 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1713 } 1714 1715 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1716 const MachO::dysymtab_command &DLC, 1717 unsigned Index) const { 1718 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1719 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1720 } 1721 1722 MachO::data_in_code_entry 1723 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1724 unsigned Index) const { 1725 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1726 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1727 } 1728 1729 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1730 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1731 } 1732 1733 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1734 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1735 } 1736 1737 MachO::linkedit_data_command 1738 MachOObjectFile::getDataInCodeLoadCommand() const { 1739 if (DataInCodeLoadCmd) 1740 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1741 1742 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1743 MachO::linkedit_data_command Cmd; 1744 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1745 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1746 Cmd.dataoff = 0; 1747 Cmd.datasize = 0; 1748 return Cmd; 1749 } 1750 1751 StringRef MachOObjectFile::getStringTableData() const { 1752 MachO::symtab_command S = getSymtabLoadCommand(); 1753 return getData().substr(S.stroff, S.strsize); 1754 } 1755 1756 bool MachOObjectFile::is64Bit() const { 1757 return getType() == getMachOType(false, true) || 1758 getType() == getMachOType(true, true); 1759 } 1760 1761 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1762 SmallVectorImpl<uint64_t> &Out) const { 1763 DataExtractor extractor(ObjectFile::getData(), true, 0); 1764 1765 uint32_t offset = Index; 1766 uint64_t data = 0; 1767 while (uint64_t delta = extractor.getULEB128(&offset)) { 1768 data += delta; 1769 Out.push_back(data); 1770 } 1771 } 1772 1773 bool MachOObjectFile::isRelocatableObject() const { 1774 return getHeader().filetype == MachO::MH_OBJECT; 1775 } 1776 1777 ErrorOr<std::unique_ptr<MachOObjectFile>> 1778 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 1779 StringRef Magic = Buffer.getBuffer().slice(0, 4); 1780 std::error_code EC; 1781 std::unique_ptr<MachOObjectFile> Ret; 1782 if (Magic == "\xFE\xED\xFA\xCE") 1783 Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); 1784 else if (Magic == "\xCE\xFA\xED\xFE") 1785 Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); 1786 else if (Magic == "\xFE\xED\xFA\xCF") 1787 Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); 1788 else if (Magic == "\xCF\xFA\xED\xFE") 1789 Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); 1790 else 1791 return object_error::parse_failed; 1792 1793 if (EC) 1794 return EC; 1795 return std::move(Ret); 1796 } 1797 1798