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