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