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