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(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { 424 uint32_t LoadCommandCount = this->getHeader().ncmds; 425 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 426 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 427 428 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 429 for (unsigned I = 0; ; ++I) { 430 if (Load.C.cmd == MachO::LC_SYMTAB) { 431 assert(!SymtabLoadCmd && "Multiple symbol tables"); 432 SymtabLoadCmd = Load.Ptr; 433 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 434 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 435 DysymtabLoadCmd = Load.Ptr; 436 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 437 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 438 DataInCodeLoadCmd = Load.Ptr; 439 } else if (Load.C.cmd == SegmentLoadType) { 440 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 441 for (unsigned J = 0; J < NumSections; ++J) { 442 const char *Sec = getSectionPtr(this, Load, J); 443 Sections.push_back(Sec); 444 } 445 } 446 447 if (I == LoadCommandCount - 1) 448 break; 449 else 450 Load = getNextLoadCommandInfo(Load); 451 } 452 } 453 454 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 455 unsigned SymbolTableEntrySize = is64Bit() ? 456 sizeof(MachO::nlist_64) : 457 sizeof(MachO::nlist); 458 Symb.p += SymbolTableEntrySize; 459 } 460 461 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 462 StringRef &Res) const { 463 StringRef StringTable = getStringTableData(); 464 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 465 const char *Start = &StringTable.data()[Entry.n_strx]; 466 Res = StringRef(Start); 467 return object_error::success; 468 } 469 470 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 471 uint64_t &Res) const { 472 if (is64Bit()) { 473 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 474 Res = Entry.n_value; 475 } else { 476 MachO::nlist Entry = getSymbolTableEntry(Symb); 477 Res = Entry.n_value; 478 } 479 return object_error::success; 480 } 481 482 error_code 483 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, 484 uint64_t &Res) const { 485 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 486 getSymbolAddress(Symb, Res); 487 if (Entry.n_sect) { 488 uint64_t Delta; 489 DataRefImpl SecRel; 490 SecRel.d.a = Entry.n_sect-1; 491 if (is64Bit()) { 492 MachO::section_64 Sec = getSection64(SecRel); 493 Delta = Sec.offset - Sec.addr; 494 } else { 495 MachO::section Sec = getSection(SecRel); 496 Delta = Sec.offset - Sec.addr; 497 } 498 499 Res += Delta; 500 } 501 502 return object_error::success; 503 } 504 505 error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 506 uint32_t &Result) const { 507 uint32_t flags = getSymbolFlags(DRI); 508 if (flags & SymbolRef::SF_Common) { 509 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 510 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 511 } else { 512 Result = 0; 513 } 514 return object_error::success; 515 } 516 517 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 518 uint64_t &Result) const { 519 uint64_t BeginOffset; 520 uint64_t EndOffset = 0; 521 uint8_t SectionIndex; 522 523 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 524 uint64_t Value; 525 getSymbolAddress(DRI, Value); 526 527 BeginOffset = Value; 528 529 SectionIndex = Entry.n_sect; 530 if (!SectionIndex) { 531 uint32_t flags = getSymbolFlags(DRI); 532 if (flags & SymbolRef::SF_Common) 533 Result = Value; 534 else 535 Result = UnknownAddressOrSize; 536 return object_error::success; 537 } 538 // Unfortunately symbols are unsorted so we need to touch all 539 // symbols from load command 540 for (const SymbolRef &Symbol : symbols()) { 541 DataRefImpl DRI = Symbol.getRawDataRefImpl(); 542 Entry = getSymbolTableEntryBase(this, DRI); 543 getSymbolAddress(DRI, Value); 544 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 545 if (!EndOffset || Value < EndOffset) 546 EndOffset = Value; 547 } 548 if (!EndOffset) { 549 uint64_t Size; 550 DataRefImpl Sec; 551 Sec.d.a = SectionIndex-1; 552 getSectionSize(Sec, Size); 553 getSectionAddress(Sec, EndOffset); 554 EndOffset += Size; 555 } 556 Result = EndOffset - BeginOffset; 557 return object_error::success; 558 } 559 560 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 561 SymbolRef::Type &Res) const { 562 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 563 uint8_t n_type = Entry.n_type; 564 565 Res = SymbolRef::ST_Other; 566 567 // If this is a STAB debugging symbol, we can do nothing more. 568 if (n_type & MachO::N_STAB) { 569 Res = SymbolRef::ST_Debug; 570 return object_error::success; 571 } 572 573 switch (n_type & MachO::N_TYPE) { 574 case MachO::N_UNDF : 575 Res = SymbolRef::ST_Unknown; 576 break; 577 case MachO::N_SECT : 578 Res = SymbolRef::ST_Function; 579 break; 580 } 581 return object_error::success; 582 } 583 584 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 585 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 586 587 uint8_t MachOType = Entry.n_type; 588 uint16_t MachOFlags = Entry.n_desc; 589 590 uint32_t Result = SymbolRef::SF_None; 591 592 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 593 Result |= SymbolRef::SF_Undefined; 594 595 if (MachOType & MachO::N_STAB) 596 Result |= SymbolRef::SF_FormatSpecific; 597 598 if (MachOType & MachO::N_EXT) { 599 Result |= SymbolRef::SF_Global; 600 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 601 uint64_t Value; 602 getSymbolAddress(DRI, Value); 603 if (Value) 604 Result |= SymbolRef::SF_Common; 605 } 606 } 607 608 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 609 Result |= SymbolRef::SF_Weak; 610 611 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 612 Result |= SymbolRef::SF_Absolute; 613 614 return Result; 615 } 616 617 error_code 618 MachOObjectFile::getSymbolSection(DataRefImpl Symb, 619 section_iterator &Res) const { 620 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 621 uint8_t index = Entry.n_sect; 622 623 if (index == 0) { 624 Res = section_end(); 625 } else { 626 DataRefImpl DRI; 627 DRI.d.a = index - 1; 628 Res = section_iterator(SectionRef(DRI, this)); 629 } 630 631 return object_error::success; 632 } 633 634 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, 635 uint64_t &Val) const { 636 // In MachO both relocatable and non-relocatable objects have addresses. 637 return getSymbolAddress(Symb, Val); 638 } 639 640 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 641 Sec.d.a++; 642 } 643 644 error_code 645 MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { 646 ArrayRef<char> Raw = getSectionRawName(Sec); 647 Result = parseSegmentOrSectionName(Raw.data()); 648 return object_error::success; 649 } 650 651 error_code 652 MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { 653 if (is64Bit()) { 654 MachO::section_64 Sect = getSection64(Sec); 655 Res = Sect.addr; 656 } else { 657 MachO::section Sect = getSection(Sec); 658 Res = Sect.addr; 659 } 660 return object_error::success; 661 } 662 663 error_code 664 MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { 665 if (is64Bit()) { 666 MachO::section_64 Sect = getSection64(Sec); 667 Res = Sect.size; 668 } else { 669 MachO::section Sect = getSection(Sec); 670 Res = Sect.size; 671 } 672 673 return object_error::success; 674 } 675 676 error_code 677 MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { 678 uint32_t Offset; 679 uint64_t Size; 680 681 if (is64Bit()) { 682 MachO::section_64 Sect = getSection64(Sec); 683 Offset = Sect.offset; 684 Size = Sect.size; 685 } else { 686 MachO::section Sect = getSection(Sec); 687 Offset = Sect.offset; 688 Size = Sect.size; 689 } 690 691 Res = this->getData().substr(Offset, Size); 692 return object_error::success; 693 } 694 695 error_code 696 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { 697 uint32_t Align; 698 if (is64Bit()) { 699 MachO::section_64 Sect = getSection64(Sec); 700 Align = Sect.align; 701 } else { 702 MachO::section Sect = getSection(Sec); 703 Align = Sect.align; 704 } 705 706 Res = uint64_t(1) << Align; 707 return object_error::success; 708 } 709 710 error_code 711 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { 712 uint32_t Flags = getSectionFlags(this, Sec); 713 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 714 return object_error::success; 715 } 716 717 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { 718 // FIXME: Unimplemented. 719 Result = false; 720 return object_error::success; 721 } 722 723 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { 724 // FIXME: Unimplemented. 725 Result = false; 726 return object_error::success; 727 } 728 729 error_code 730 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 731 bool &Result) const { 732 // FIXME: Unimplemented. 733 Result = true; 734 return object_error::success; 735 } 736 737 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 738 bool &Result) const { 739 // FIXME: Unimplemented. 740 Result = false; 741 return object_error::success; 742 } 743 744 error_code 745 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { 746 uint32_t Flags = getSectionFlags(this, Sec); 747 unsigned SectionType = Flags & MachO::SECTION_TYPE; 748 Res = SectionType == MachO::S_ZEROFILL || 749 SectionType == MachO::S_GB_ZEROFILL; 750 return object_error::success; 751 } 752 753 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 754 bool &Result) const { 755 // Consider using the code from isSectionText to look for __const sections. 756 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 757 // to use section attributes to distinguish code from data. 758 759 // FIXME: Unimplemented. 760 Result = false; 761 return object_error::success; 762 } 763 764 error_code 765 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 766 bool &Result) const { 767 SymbolRef::Type ST; 768 this->getSymbolType(Symb, ST); 769 if (ST == SymbolRef::ST_Unknown) { 770 Result = false; 771 return object_error::success; 772 } 773 774 uint64_t SectBegin, SectEnd; 775 getSectionAddress(Sec, SectBegin); 776 getSectionSize(Sec, SectEnd); 777 SectEnd += SectBegin; 778 779 uint64_t SymAddr; 780 getSymbolAddress(Symb, SymAddr); 781 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 782 783 return object_error::success; 784 } 785 786 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 787 uint32_t Offset; 788 if (is64Bit()) { 789 MachO::section_64 Sect = getSection64(Sec); 790 Offset = Sect.reloff; 791 } else { 792 MachO::section Sect = getSection(Sec); 793 Offset = Sect.reloff; 794 } 795 796 DataRefImpl Ret; 797 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 798 return relocation_iterator(RelocationRef(Ret, this)); 799 } 800 801 relocation_iterator 802 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 803 uint32_t Offset; 804 uint32_t Num; 805 if (is64Bit()) { 806 MachO::section_64 Sect = getSection64(Sec); 807 Offset = Sect.reloff; 808 Num = Sect.nreloc; 809 } else { 810 MachO::section Sect = getSection(Sec); 811 Offset = Sect.reloff; 812 Num = Sect.nreloc; 813 } 814 815 const MachO::any_relocation_info *P = 816 reinterpret_cast<const MachO::any_relocation_info *>(getPtr(this, Offset)); 817 818 DataRefImpl Ret; 819 Ret.p = reinterpret_cast<uintptr_t>(P + Num); 820 return relocation_iterator(RelocationRef(Ret, this)); 821 } 822 823 bool MachOObjectFile::section_rel_empty(DataRefImpl Sec) const { 824 if (is64Bit()) { 825 MachO::section_64 Sect = getSection64(Sec); 826 return Sect.nreloc == 0; 827 } else { 828 MachO::section Sect = getSection(Sec); 829 return Sect.nreloc == 0; 830 } 831 } 832 833 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 834 const MachO::any_relocation_info *P = 835 reinterpret_cast<const MachO::any_relocation_info *>(Rel.p); 836 Rel.p = reinterpret_cast<uintptr_t>(P + 1); 837 } 838 839 error_code 840 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { 841 report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); 842 } 843 844 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 845 uint64_t &Res) const { 846 MachO::any_relocation_info RE = getRelocation(Rel); 847 Res = getAnyRelocationAddress(RE); 848 return object_error::success; 849 } 850 851 symbol_iterator 852 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 853 MachO::any_relocation_info RE = getRelocation(Rel); 854 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 855 bool isExtern = getPlainRelocationExternal(RE); 856 if (!isExtern) 857 return symbol_end(); 858 859 MachO::symtab_command S = getSymtabLoadCommand(); 860 unsigned SymbolTableEntrySize = is64Bit() ? 861 sizeof(MachO::nlist_64) : 862 sizeof(MachO::nlist); 863 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 864 DataRefImpl Sym; 865 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 866 return symbol_iterator(SymbolRef(Sym, this)); 867 } 868 869 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 870 uint64_t &Res) const { 871 MachO::any_relocation_info RE = getRelocation(Rel); 872 Res = getAnyRelocationType(RE); 873 return object_error::success; 874 } 875 876 error_code 877 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 878 SmallVectorImpl<char> &Result) const { 879 StringRef res; 880 uint64_t RType; 881 getRelocationType(Rel, RType); 882 883 unsigned Arch = this->getArch(); 884 885 switch (Arch) { 886 case Triple::x86: { 887 static const char *const Table[] = { 888 "GENERIC_RELOC_VANILLA", 889 "GENERIC_RELOC_PAIR", 890 "GENERIC_RELOC_SECTDIFF", 891 "GENERIC_RELOC_PB_LA_PTR", 892 "GENERIC_RELOC_LOCAL_SECTDIFF", 893 "GENERIC_RELOC_TLV" }; 894 895 if (RType > 5) 896 res = "Unknown"; 897 else 898 res = Table[RType]; 899 break; 900 } 901 case Triple::x86_64: { 902 static const char *const Table[] = { 903 "X86_64_RELOC_UNSIGNED", 904 "X86_64_RELOC_SIGNED", 905 "X86_64_RELOC_BRANCH", 906 "X86_64_RELOC_GOT_LOAD", 907 "X86_64_RELOC_GOT", 908 "X86_64_RELOC_SUBTRACTOR", 909 "X86_64_RELOC_SIGNED_1", 910 "X86_64_RELOC_SIGNED_2", 911 "X86_64_RELOC_SIGNED_4", 912 "X86_64_RELOC_TLV" }; 913 914 if (RType > 9) 915 res = "Unknown"; 916 else 917 res = Table[RType]; 918 break; 919 } 920 case Triple::arm: { 921 static const char *const Table[] = { 922 "ARM_RELOC_VANILLA", 923 "ARM_RELOC_PAIR", 924 "ARM_RELOC_SECTDIFF", 925 "ARM_RELOC_LOCAL_SECTDIFF", 926 "ARM_RELOC_PB_LA_PTR", 927 "ARM_RELOC_BR24", 928 "ARM_THUMB_RELOC_BR22", 929 "ARM_THUMB_32BIT_BRANCH", 930 "ARM_RELOC_HALF", 931 "ARM_RELOC_HALF_SECTDIFF" }; 932 933 if (RType > 9) 934 res = "Unknown"; 935 else 936 res = Table[RType]; 937 break; 938 } 939 case Triple::arm64: 940 case Triple::aarch64: { 941 static const char *const Table[] = { 942 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 943 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 944 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 945 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 946 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 947 "ARM64_RELOC_ADDEND" 948 }; 949 950 if (RType >= array_lengthof(Table)) 951 res = "Unknown"; 952 else 953 res = Table[RType]; 954 break; 955 } 956 case Triple::ppc: { 957 static const char *const Table[] = { 958 "PPC_RELOC_VANILLA", 959 "PPC_RELOC_PAIR", 960 "PPC_RELOC_BR14", 961 "PPC_RELOC_BR24", 962 "PPC_RELOC_HI16", 963 "PPC_RELOC_LO16", 964 "PPC_RELOC_HA16", 965 "PPC_RELOC_LO14", 966 "PPC_RELOC_SECTDIFF", 967 "PPC_RELOC_PB_LA_PTR", 968 "PPC_RELOC_HI16_SECTDIFF", 969 "PPC_RELOC_LO16_SECTDIFF", 970 "PPC_RELOC_HA16_SECTDIFF", 971 "PPC_RELOC_JBSR", 972 "PPC_RELOC_LO14_SECTDIFF", 973 "PPC_RELOC_LOCAL_SECTDIFF" }; 974 975 if (RType > 15) 976 res = "Unknown"; 977 else 978 res = Table[RType]; 979 break; 980 } 981 case Triple::UnknownArch: 982 res = "Unknown"; 983 break; 984 } 985 Result.append(res.begin(), res.end()); 986 return object_error::success; 987 } 988 989 error_code 990 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 991 SmallVectorImpl<char> &Result) const { 992 MachO::any_relocation_info RE = getRelocation(Rel); 993 994 unsigned Arch = this->getArch(); 995 996 std::string fmtbuf; 997 raw_string_ostream fmt(fmtbuf); 998 unsigned Type = this->getAnyRelocationType(RE); 999 bool IsPCRel = this->getAnyRelocationPCRel(RE); 1000 1001 // Determine any addends that should be displayed with the relocation. 1002 // These require decoding the relocation type, which is triple-specific. 1003 1004 // X86_64 has entirely custom relocation types. 1005 if (Arch == Triple::x86_64) { 1006 bool isPCRel = getAnyRelocationPCRel(RE); 1007 1008 switch (Type) { 1009 case MachO::X86_64_RELOC_GOT_LOAD: 1010 case MachO::X86_64_RELOC_GOT: { 1011 printRelocationTargetName(this, RE, fmt); 1012 fmt << "@GOT"; 1013 if (isPCRel) fmt << "PCREL"; 1014 break; 1015 } 1016 case MachO::X86_64_RELOC_SUBTRACTOR: { 1017 DataRefImpl RelNext = Rel; 1018 RelNext.d.a++; 1019 MachO::any_relocation_info RENext = getRelocation(RelNext); 1020 1021 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 1022 // X86_64_RELOC_UNSIGNED. 1023 // NOTE: Scattered relocations don't exist on x86_64. 1024 unsigned RType = getAnyRelocationType(RENext); 1025 if (RType != MachO::X86_64_RELOC_UNSIGNED) 1026 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1027 "X86_64_RELOC_SUBTRACTOR."); 1028 1029 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 1030 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 1031 printRelocationTargetName(this, RENext, fmt); 1032 fmt << "-"; 1033 printRelocationTargetName(this, RE, fmt); 1034 break; 1035 } 1036 case MachO::X86_64_RELOC_TLV: 1037 printRelocationTargetName(this, RE, fmt); 1038 fmt << "@TLV"; 1039 if (isPCRel) fmt << "P"; 1040 break; 1041 case MachO::X86_64_RELOC_SIGNED_1: 1042 printRelocationTargetName(this, RE, fmt); 1043 fmt << "-1"; 1044 break; 1045 case MachO::X86_64_RELOC_SIGNED_2: 1046 printRelocationTargetName(this, RE, fmt); 1047 fmt << "-2"; 1048 break; 1049 case MachO::X86_64_RELOC_SIGNED_4: 1050 printRelocationTargetName(this, RE, fmt); 1051 fmt << "-4"; 1052 break; 1053 default: 1054 printRelocationTargetName(this, RE, fmt); 1055 break; 1056 } 1057 // X86 and ARM share some relocation types in common. 1058 } else if (Arch == Triple::x86 || Arch == Triple::arm || 1059 Arch == Triple::ppc) { 1060 // Generic relocation types... 1061 switch (Type) { 1062 case MachO::GENERIC_RELOC_PAIR: // prints no info 1063 return object_error::success; 1064 case MachO::GENERIC_RELOC_SECTDIFF: { 1065 DataRefImpl RelNext = Rel; 1066 RelNext.d.a++; 1067 MachO::any_relocation_info RENext = getRelocation(RelNext); 1068 1069 // X86 sect diff's must be followed by a relocation of type 1070 // GENERIC_RELOC_PAIR. 1071 unsigned RType = getAnyRelocationType(RENext); 1072 1073 if (RType != MachO::GENERIC_RELOC_PAIR) 1074 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1075 "GENERIC_RELOC_SECTDIFF."); 1076 1077 printRelocationTargetName(this, RE, fmt); 1078 fmt << "-"; 1079 printRelocationTargetName(this, RENext, fmt); 1080 break; 1081 } 1082 } 1083 1084 if (Arch == Triple::x86 || Arch == Triple::ppc) { 1085 switch (Type) { 1086 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 1087 DataRefImpl RelNext = Rel; 1088 RelNext.d.a++; 1089 MachO::any_relocation_info RENext = getRelocation(RelNext); 1090 1091 // X86 sect diff's must be followed by a relocation of type 1092 // GENERIC_RELOC_PAIR. 1093 unsigned RType = getAnyRelocationType(RENext); 1094 if (RType != MachO::GENERIC_RELOC_PAIR) 1095 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1096 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1097 1098 printRelocationTargetName(this, RE, fmt); 1099 fmt << "-"; 1100 printRelocationTargetName(this, RENext, fmt); 1101 break; 1102 } 1103 case MachO::GENERIC_RELOC_TLV: { 1104 printRelocationTargetName(this, RE, fmt); 1105 fmt << "@TLV"; 1106 if (IsPCRel) fmt << "P"; 1107 break; 1108 } 1109 default: 1110 printRelocationTargetName(this, RE, fmt); 1111 } 1112 } else { // ARM-specific relocations 1113 switch (Type) { 1114 case MachO::ARM_RELOC_HALF: 1115 case MachO::ARM_RELOC_HALF_SECTDIFF: { 1116 // Half relocations steal a bit from the length field to encode 1117 // whether this is an upper16 or a lower16 relocation. 1118 bool isUpper = getAnyRelocationLength(RE) >> 1; 1119 1120 if (isUpper) 1121 fmt << ":upper16:("; 1122 else 1123 fmt << ":lower16:("; 1124 printRelocationTargetName(this, RE, fmt); 1125 1126 DataRefImpl RelNext = Rel; 1127 RelNext.d.a++; 1128 MachO::any_relocation_info RENext = getRelocation(RelNext); 1129 1130 // ARM half relocs must be followed by a relocation of type 1131 // ARM_RELOC_PAIR. 1132 unsigned RType = getAnyRelocationType(RENext); 1133 if (RType != MachO::ARM_RELOC_PAIR) 1134 report_fatal_error("Expected ARM_RELOC_PAIR after " 1135 "ARM_RELOC_HALF"); 1136 1137 // NOTE: The half of the target virtual address is stashed in the 1138 // address field of the secondary relocation, but we can't reverse 1139 // engineer the constant offset from it without decoding the movw/movt 1140 // instruction to find the other half in its immediate field. 1141 1142 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1143 // symbol/section pointer of the follow-on relocation. 1144 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1145 fmt << "-"; 1146 printRelocationTargetName(this, RENext, fmt); 1147 } 1148 1149 fmt << ")"; 1150 break; 1151 } 1152 default: { 1153 printRelocationTargetName(this, RE, fmt); 1154 } 1155 } 1156 } 1157 } else 1158 printRelocationTargetName(this, RE, fmt); 1159 1160 fmt.flush(); 1161 Result.append(fmtbuf.begin(), fmtbuf.end()); 1162 return object_error::success; 1163 } 1164 1165 error_code 1166 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { 1167 unsigned Arch = getArch(); 1168 uint64_t Type; 1169 getRelocationType(Rel, Type); 1170 1171 Result = false; 1172 1173 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1174 // is always hidden. 1175 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 1176 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 1177 } else if (Arch == Triple::x86_64) { 1178 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1179 // an X86_64_RELOC_SUBTRACTOR. 1180 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1181 DataRefImpl RelPrev = Rel; 1182 RelPrev.d.a--; 1183 uint64_t PrevType; 1184 getRelocationType(RelPrev, PrevType); 1185 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1186 Result = true; 1187 } 1188 } 1189 1190 return object_error::success; 1191 } 1192 1193 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1194 LibraryRef &Res) const { 1195 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1196 } 1197 1198 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1199 StringRef &Res) const { 1200 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1201 } 1202 1203 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1204 DataRefImpl DRI; 1205 if (!SymtabLoadCmd) 1206 return basic_symbol_iterator(SymbolRef(DRI, this)); 1207 1208 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1209 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1210 return basic_symbol_iterator(SymbolRef(DRI, this)); 1211 } 1212 1213 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1214 DataRefImpl DRI; 1215 if (!SymtabLoadCmd) 1216 return basic_symbol_iterator(SymbolRef(DRI, this)); 1217 1218 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1219 unsigned SymbolTableEntrySize = is64Bit() ? 1220 sizeof(MachO::nlist_64) : 1221 sizeof(MachO::nlist); 1222 unsigned Offset = Symtab.symoff + 1223 Symtab.nsyms * SymbolTableEntrySize; 1224 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1225 return basic_symbol_iterator(SymbolRef(DRI, this)); 1226 } 1227 1228 section_iterator MachOObjectFile::section_begin() const { 1229 DataRefImpl DRI; 1230 return section_iterator(SectionRef(DRI, this)); 1231 } 1232 1233 section_iterator MachOObjectFile::section_end() const { 1234 DataRefImpl DRI; 1235 DRI.d.a = Sections.size(); 1236 return section_iterator(SectionRef(DRI, this)); 1237 } 1238 1239 library_iterator MachOObjectFile::needed_library_begin() const { 1240 // TODO: implement 1241 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1242 } 1243 1244 library_iterator MachOObjectFile::needed_library_end() const { 1245 // TODO: implement 1246 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1247 } 1248 1249 uint8_t MachOObjectFile::getBytesInAddress() const { 1250 return is64Bit() ? 8 : 4; 1251 } 1252 1253 StringRef MachOObjectFile::getFileFormatName() const { 1254 unsigned CPUType = getCPUType(this); 1255 if (!is64Bit()) { 1256 switch (CPUType) { 1257 case llvm::MachO::CPU_TYPE_I386: 1258 return "Mach-O 32-bit i386"; 1259 case llvm::MachO::CPU_TYPE_ARM: 1260 return "Mach-O arm"; 1261 case llvm::MachO::CPU_TYPE_POWERPC: 1262 return "Mach-O 32-bit ppc"; 1263 default: 1264 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1265 "64-bit object file when we're not 64-bit?"); 1266 return "Mach-O 32-bit unknown"; 1267 } 1268 } 1269 1270 // Make sure the cpu type has the correct mask. 1271 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1272 == llvm::MachO::CPU_ARCH_ABI64 && 1273 "32-bit object file when we're 64-bit?"); 1274 1275 switch (CPUType) { 1276 case llvm::MachO::CPU_TYPE_X86_64: 1277 return "Mach-O 64-bit x86-64"; 1278 case llvm::MachO::CPU_TYPE_ARM64: 1279 return "Mach-O arm64"; 1280 case llvm::MachO::CPU_TYPE_POWERPC64: 1281 return "Mach-O 64-bit ppc64"; 1282 default: 1283 return "Mach-O 64-bit unknown"; 1284 } 1285 } 1286 1287 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1288 switch (CPUType) { 1289 case llvm::MachO::CPU_TYPE_I386: 1290 return Triple::x86; 1291 case llvm::MachO::CPU_TYPE_X86_64: 1292 return Triple::x86_64; 1293 case llvm::MachO::CPU_TYPE_ARM: 1294 return Triple::arm; 1295 case llvm::MachO::CPU_TYPE_ARM64: 1296 return Triple::arm64; 1297 case llvm::MachO::CPU_TYPE_POWERPC: 1298 return Triple::ppc; 1299 case llvm::MachO::CPU_TYPE_POWERPC64: 1300 return Triple::ppc64; 1301 default: 1302 return Triple::UnknownArch; 1303 } 1304 } 1305 1306 unsigned MachOObjectFile::getArch() const { 1307 return getArch(getCPUType(this)); 1308 } 1309 1310 StringRef MachOObjectFile::getLoadName() const { 1311 // TODO: Implement 1312 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1313 } 1314 1315 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1316 DataRefImpl DRI; 1317 DRI.d.a = Index; 1318 return section_rel_begin(DRI); 1319 } 1320 1321 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1322 DataRefImpl DRI; 1323 DRI.d.a = Index; 1324 return section_rel_end(DRI); 1325 } 1326 1327 dice_iterator MachOObjectFile::begin_dices() const { 1328 DataRefImpl DRI; 1329 if (!DataInCodeLoadCmd) 1330 return dice_iterator(DiceRef(DRI, this)); 1331 1332 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1333 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1334 return dice_iterator(DiceRef(DRI, this)); 1335 } 1336 1337 dice_iterator MachOObjectFile::end_dices() const { 1338 DataRefImpl DRI; 1339 if (!DataInCodeLoadCmd) 1340 return dice_iterator(DiceRef(DRI, this)); 1341 1342 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1343 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1344 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1345 return dice_iterator(DiceRef(DRI, this)); 1346 } 1347 1348 StringRef 1349 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1350 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1351 return parseSegmentOrSectionName(Raw.data()); 1352 } 1353 1354 ArrayRef<char> 1355 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1356 const section_base *Base = 1357 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1358 return ArrayRef<char>(Base->sectname); 1359 } 1360 1361 ArrayRef<char> 1362 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1363 const section_base *Base = 1364 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1365 return ArrayRef<char>(Base->segname); 1366 } 1367 1368 bool 1369 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1370 const { 1371 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1372 return false; 1373 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1374 } 1375 1376 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1377 const MachO::any_relocation_info &RE) const { 1378 if (isLittleEndian()) 1379 return RE.r_word1 & 0xffffff; 1380 return RE.r_word1 >> 8; 1381 } 1382 1383 bool MachOObjectFile::getPlainRelocationExternal( 1384 const MachO::any_relocation_info &RE) const { 1385 if (isLittleEndian()) 1386 return (RE.r_word1 >> 27) & 1; 1387 return (RE.r_word1 >> 4) & 1; 1388 } 1389 1390 bool MachOObjectFile::getScatteredRelocationScattered( 1391 const MachO::any_relocation_info &RE) const { 1392 return RE.r_word0 >> 31; 1393 } 1394 1395 uint32_t MachOObjectFile::getScatteredRelocationValue( 1396 const MachO::any_relocation_info &RE) const { 1397 return RE.r_word1; 1398 } 1399 1400 unsigned MachOObjectFile::getAnyRelocationAddress( 1401 const MachO::any_relocation_info &RE) const { 1402 if (isRelocationScattered(RE)) 1403 return getScatteredRelocationAddress(RE); 1404 return getPlainRelocationAddress(RE); 1405 } 1406 1407 unsigned MachOObjectFile::getAnyRelocationPCRel( 1408 const MachO::any_relocation_info &RE) const { 1409 if (isRelocationScattered(RE)) 1410 return getScatteredRelocationPCRel(this, RE); 1411 return getPlainRelocationPCRel(this, RE); 1412 } 1413 1414 unsigned MachOObjectFile::getAnyRelocationLength( 1415 const MachO::any_relocation_info &RE) const { 1416 if (isRelocationScattered(RE)) 1417 return getScatteredRelocationLength(RE); 1418 return getPlainRelocationLength(this, RE); 1419 } 1420 1421 unsigned 1422 MachOObjectFile::getAnyRelocationType( 1423 const MachO::any_relocation_info &RE) const { 1424 if (isRelocationScattered(RE)) 1425 return getScatteredRelocationType(RE); 1426 return getPlainRelocationType(this, RE); 1427 } 1428 1429 SectionRef 1430 MachOObjectFile::getRelocationSection( 1431 const MachO::any_relocation_info &RE) const { 1432 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1433 return *section_end(); 1434 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1435 DataRefImpl DRI; 1436 DRI.d.a = SecNum; 1437 return SectionRef(DRI, this); 1438 } 1439 1440 MachOObjectFile::LoadCommandInfo 1441 MachOObjectFile::getFirstLoadCommandInfo() const { 1442 MachOObjectFile::LoadCommandInfo Load; 1443 1444 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1445 sizeof(MachO::mach_header); 1446 Load.Ptr = getPtr(this, HeaderSize); 1447 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1448 return Load; 1449 } 1450 1451 MachOObjectFile::LoadCommandInfo 1452 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1453 MachOObjectFile::LoadCommandInfo Next; 1454 Next.Ptr = L.Ptr + L.C.cmdsize; 1455 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1456 return Next; 1457 } 1458 1459 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1460 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1461 } 1462 1463 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1464 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1465 } 1466 1467 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1468 unsigned Index) const { 1469 const char *Sec = getSectionPtr(this, L, Index); 1470 return getStruct<MachO::section>(this, Sec); 1471 } 1472 1473 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1474 unsigned Index) const { 1475 const char *Sec = getSectionPtr(this, L, Index); 1476 return getStruct<MachO::section_64>(this, Sec); 1477 } 1478 1479 MachO::nlist 1480 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1481 const char *P = reinterpret_cast<const char *>(DRI.p); 1482 return getStruct<MachO::nlist>(this, P); 1483 } 1484 1485 MachO::nlist_64 1486 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1487 const char *P = reinterpret_cast<const char *>(DRI.p); 1488 return getStruct<MachO::nlist_64>(this, P); 1489 } 1490 1491 MachO::linkedit_data_command 1492 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1493 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1494 } 1495 1496 MachO::segment_command 1497 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1498 return getStruct<MachO::segment_command>(this, L.Ptr); 1499 } 1500 1501 MachO::segment_command_64 1502 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1503 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1504 } 1505 1506 MachO::linker_options_command 1507 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1508 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1509 } 1510 1511 MachO::version_min_command 1512 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1513 return getStruct<MachO::version_min_command>(this, L.Ptr); 1514 } 1515 1516 MachO::any_relocation_info 1517 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1518 const char *P = reinterpret_cast<const char *>(Rel.p); 1519 return getStruct<MachO::any_relocation_info>(this, P); 1520 } 1521 1522 MachO::data_in_code_entry 1523 MachOObjectFile::getDice(DataRefImpl Rel) const { 1524 const char *P = reinterpret_cast<const char *>(Rel.p); 1525 return getStruct<MachO::data_in_code_entry>(this, P); 1526 } 1527 1528 MachO::mach_header MachOObjectFile::getHeader() const { 1529 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1530 } 1531 1532 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1533 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1534 } 1535 1536 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1537 const MachO::dysymtab_command &DLC, 1538 unsigned Index) const { 1539 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1540 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1541 } 1542 1543 MachO::data_in_code_entry 1544 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1545 unsigned Index) const { 1546 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1547 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1548 } 1549 1550 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1551 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1552 } 1553 1554 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1555 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1556 } 1557 1558 MachO::linkedit_data_command 1559 MachOObjectFile::getDataInCodeLoadCommand() const { 1560 if (DataInCodeLoadCmd) 1561 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1562 1563 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1564 MachO::linkedit_data_command Cmd; 1565 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1566 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1567 Cmd.dataoff = 0; 1568 Cmd.datasize = 0; 1569 return Cmd; 1570 } 1571 1572 StringRef MachOObjectFile::getStringTableData() const { 1573 MachO::symtab_command S = getSymtabLoadCommand(); 1574 return getData().substr(S.stroff, S.strsize); 1575 } 1576 1577 bool MachOObjectFile::is64Bit() const { 1578 return getType() == getMachOType(false, true) || 1579 getType() == getMachOType(true, true); 1580 } 1581 1582 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1583 SmallVectorImpl<uint64_t> &Out) const { 1584 DataExtractor extractor(ObjectFile::getData(), true, 0); 1585 1586 uint32_t offset = Index; 1587 uint64_t data = 0; 1588 while (uint64_t delta = extractor.getULEB128(&offset)) { 1589 data += delta; 1590 Out.push_back(data); 1591 } 1592 } 1593 1594 ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer, 1595 bool BufferOwned) { 1596 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1597 error_code EC; 1598 std::unique_ptr<MachOObjectFile> Ret; 1599 if (Magic == "\xFE\xED\xFA\xCE") 1600 Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned)); 1601 else if (Magic == "\xCE\xFA\xED\xFE") 1602 Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned)); 1603 else if (Magic == "\xFE\xED\xFA\xCF") 1604 Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned)); 1605 else if (Magic == "\xCF\xFA\xED\xFE") 1606 Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned)); 1607 else { 1608 delete Buffer; 1609 return object_error::parse_failed; 1610 } 1611 1612 if (EC) 1613 return EC; 1614 return Ret.release(); 1615 } 1616 1617 } // end namespace object 1618 } // end namespace llvm 1619