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