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