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