1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/raw_ostream.h"
29 using namespace object;
39 static T getStruct(const MachOObjectFile *O, const char *P) {
41 memcpy(&Cmd, P, sizeof(T));
42 if (O->isLittleEndian() != sys::IsLittleEndianHost)
43 MachO::swapStruct(Cmd);
48 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
49 const MachOObjectFile::LoadCommandInfo &L) {
51 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
54 MachO::segment_command S = O->getSegmentLoadCommand(L);
59 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
61 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
63 bool Is64 = O->is64Bit();
64 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
65 sizeof(MachO::segment_command);
66 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
67 sizeof(MachO::section);
69 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
70 return reinterpret_cast<const char*>(SectionAddr);
73 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
74 return O->getData().substr(Offset, 1).data();
77 static MachO::nlist_base
78 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
79 const char *P = reinterpret_cast<const char *>(DRI.p);
80 return getStruct<MachO::nlist_base>(O, P);
83 static StringRef parseSegmentOrSectionName(const char *P) {
87 // Not null terminated, so this is a 16 char string.
88 return StringRef(P, 16);
91 // Helper to advance a section or symbol iterator multiple increments at a time.
93 static void advance(T &it, size_t Val) {
98 static unsigned getCPUType(const MachOObjectFile *O) {
99 return O->getHeader().cputype;
102 static void printRelocationTargetName(const MachOObjectFile *O,
103 const MachO::any_relocation_info &RE,
104 raw_string_ostream &fmt) {
105 bool IsScattered = O->isRelocationScattered(RE);
107 // Target of a scattered relocation is an address. In the interest of
108 // generating pretty output, scan through the symbol table looking for a
109 // symbol that aligns with that address. If we find one, print it.
110 // Otherwise, we just print the hex address of the target.
112 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
114 for (const SymbolRef &Symbol : O->symbols()) {
119 if ((ec = Symbol.getAddress(Addr)))
120 report_fatal_error(ec.message());
123 if ((ec = Symbol.getName(Name)))
124 report_fatal_error(ec.message());
129 // If we couldn't find a symbol that this relocation refers to, try
130 // to find a section beginning instead.
131 for (const SectionRef &Section : O->sections()) {
136 if ((ec = Section.getAddress(Addr)))
137 report_fatal_error(ec.message());
140 if ((ec = Section.getName(Name)))
141 report_fatal_error(ec.message());
146 fmt << format("0x%x", Val);
151 bool isExtern = O->getPlainRelocationExternal(RE);
152 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
155 symbol_iterator SI = O->symbol_begin();
159 section_iterator SI = O->section_begin();
160 // Adjust for the fact that sections are 1-indexed.
161 advance(SI, Val - 1);
169 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
174 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
175 return RE.r_word0 & 0xffffff;
178 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
179 const MachO::any_relocation_info &RE) {
180 if (O->isLittleEndian())
181 return (RE.r_word1 >> 24) & 1;
182 return (RE.r_word1 >> 7) & 1;
186 getScatteredRelocationPCRel(const MachOObjectFile *O,
187 const MachO::any_relocation_info &RE) {
188 return (RE.r_word0 >> 30) & 1;
191 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
192 const MachO::any_relocation_info &RE) {
193 if (O->isLittleEndian())
194 return (RE.r_word1 >> 25) & 3;
195 return (RE.r_word1 >> 5) & 3;
199 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 28) & 3;
203 static unsigned getPlainRelocationType(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return RE.r_word1 >> 28;
207 return RE.r_word1 & 0xf;
211 getScatteredRelocationType(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 24) & 0xf;
215 static uint32_t getSectionFlags(const MachOObjectFile *O,
218 MachO::section_64 Sect = O->getSection64(Sec);
221 MachO::section Sect = O->getSection(Sec);
225 MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
226 bool IsLittleEndian, bool Is64bits,
228 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
229 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
230 DataInCodeLoadCmd(nullptr) {
231 uint32_t LoadCommandCount = this->getHeader().ncmds;
232 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
233 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
235 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
236 for (unsigned I = 0; ; ++I) {
237 if (Load.C.cmd == MachO::LC_SYMTAB) {
238 assert(!SymtabLoadCmd && "Multiple symbol tables");
239 SymtabLoadCmd = Load.Ptr;
240 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
241 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
242 DysymtabLoadCmd = Load.Ptr;
243 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
244 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
245 DataInCodeLoadCmd = Load.Ptr;
246 } else if (Load.C.cmd == SegmentLoadType) {
247 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
248 for (unsigned J = 0; J < NumSections; ++J) {
249 const char *Sec = getSectionPtr(this, Load, J);
250 Sections.push_back(Sec);
252 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
253 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
254 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
255 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
256 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
257 Libraries.push_back(Load.Ptr);
260 if (I == LoadCommandCount - 1)
263 Load = getNextLoadCommandInfo(Load);
267 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
268 unsigned SymbolTableEntrySize = is64Bit() ?
269 sizeof(MachO::nlist_64) :
270 sizeof(MachO::nlist);
271 Symb.p += SymbolTableEntrySize;
274 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
275 StringRef &Res) const {
276 StringRef StringTable = getStringTableData();
277 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
278 const char *Start = &StringTable.data()[Entry.n_strx];
279 Res = StringRef(Start);
280 return object_error::success;
283 // getIndirectName() returns the name of the alias'ed symbol who's string table
284 // index is in the n_value field.
285 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
286 StringRef &Res) const {
287 StringRef StringTable = getStringTableData();
290 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
291 NValue = Entry.n_value;
292 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
293 return object_error::parse_failed;
295 MachO::nlist Entry = getSymbolTableEntry(Symb);
296 NValue = Entry.n_value;
297 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
298 return object_error::parse_failed;
300 if (NValue >= StringTable.size())
301 return object_error::parse_failed;
302 const char *Start = &StringTable.data()[NValue];
303 Res = StringRef(Start);
304 return object_error::success;
307 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
308 uint64_t &Res) const {
310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
311 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
313 Res = UnknownAddressOrSize;
317 MachO::nlist Entry = getSymbolTableEntry(Symb);
318 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
320 Res = UnknownAddressOrSize;
324 return object_error::success;
327 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
328 uint32_t &Result) const {
329 uint32_t flags = getSymbolFlags(DRI);
330 if (flags & SymbolRef::SF_Common) {
331 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
332 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
336 return object_error::success;
339 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
340 uint64_t &Result) const {
341 uint64_t BeginOffset;
342 uint64_t EndOffset = 0;
343 uint8_t SectionIndex;
345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
347 getSymbolAddress(DRI, Value);
348 if (Value == UnknownAddressOrSize) {
349 Result = UnknownAddressOrSize;
350 return object_error::success;
355 SectionIndex = Entry.n_sect;
357 uint32_t flags = getSymbolFlags(DRI);
358 if (flags & SymbolRef::SF_Common)
361 Result = UnknownAddressOrSize;
362 return object_error::success;
364 // Unfortunately symbols are unsorted so we need to touch all
365 // symbols from load command
366 for (const SymbolRef &Symbol : symbols()) {
367 DataRefImpl DRI = Symbol.getRawDataRefImpl();
368 Entry = getSymbolTableEntryBase(this, DRI);
369 getSymbolAddress(DRI, Value);
370 if (Value == UnknownAddressOrSize)
372 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
373 if (!EndOffset || Value < EndOffset)
379 Sec.d.a = SectionIndex-1;
380 getSectionSize(Sec, Size);
381 getSectionAddress(Sec, EndOffset);
384 Result = EndOffset - BeginOffset;
385 return object_error::success;
388 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
389 SymbolRef::Type &Res) const {
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
391 uint8_t n_type = Entry.n_type;
393 Res = SymbolRef::ST_Other;
395 // If this is a STAB debugging symbol, we can do nothing more.
396 if (n_type & MachO::N_STAB) {
397 Res = SymbolRef::ST_Debug;
398 return object_error::success;
401 switch (n_type & MachO::N_TYPE) {
403 Res = SymbolRef::ST_Unknown;
406 Res = SymbolRef::ST_Function;
409 return object_error::success;
412 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
415 uint8_t MachOType = Entry.n_type;
416 uint16_t MachOFlags = Entry.n_desc;
418 uint32_t Result = SymbolRef::SF_None;
420 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
421 Result |= SymbolRef::SF_Undefined;
423 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
424 Result |= SymbolRef::SF_Indirect;
426 if (MachOType & MachO::N_STAB)
427 Result |= SymbolRef::SF_FormatSpecific;
429 if (MachOType & MachO::N_EXT) {
430 Result |= SymbolRef::SF_Global;
431 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
433 getSymbolAddress(DRI, Value);
434 if (Value && Value != UnknownAddressOrSize)
435 Result |= SymbolRef::SF_Common;
439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
440 Result |= SymbolRef::SF_Weak;
442 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
443 Result |= SymbolRef::SF_Thumb;
445 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
446 Result |= SymbolRef::SF_Absolute;
451 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
452 section_iterator &Res) const {
453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
454 uint8_t index = Entry.n_sect;
461 Res = section_iterator(SectionRef(DRI, this));
464 return object_error::success;
467 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
471 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
472 StringRef &Result) const {
473 ArrayRef<char> Raw = getSectionRawName(Sec);
474 Result = parseSegmentOrSectionName(Raw.data());
475 return object_error::success;
478 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
479 uint64_t &Res) const {
481 MachO::section_64 Sect = getSection64(Sec);
484 MachO::section Sect = getSection(Sec);
487 return object_error::success;
490 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
491 uint64_t &Res) const {
493 MachO::section_64 Sect = getSection64(Sec);
496 MachO::section Sect = getSection(Sec);
500 return object_error::success;
503 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
504 StringRef &Res) const {
509 MachO::section_64 Sect = getSection64(Sec);
510 Offset = Sect.offset;
513 MachO::section Sect = getSection(Sec);
514 Offset = Sect.offset;
518 Res = this->getData().substr(Offset, Size);
519 return object_error::success;
522 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
523 uint64_t &Res) const {
526 MachO::section_64 Sect = getSection64(Sec);
529 MachO::section Sect = getSection(Sec);
533 Res = uint64_t(1) << Align;
534 return object_error::success;
537 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
539 uint32_t Flags = getSectionFlags(this, Sec);
540 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
541 return object_error::success;
544 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
545 bool &Result) const {
546 uint32_t Flags = getSectionFlags(this, Sec);
547 unsigned SectionType = Flags & MachO::SECTION_TYPE;
548 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
549 !(SectionType == MachO::S_ZEROFILL ||
550 SectionType == MachO::S_GB_ZEROFILL);
551 return object_error::success;
554 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
555 bool &Result) const {
556 uint32_t Flags = getSectionFlags(this, Sec);
557 unsigned SectionType = Flags & MachO::SECTION_TYPE;
558 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
559 (SectionType == MachO::S_ZEROFILL ||
560 SectionType == MachO::S_GB_ZEROFILL);
561 return object_error::success;
565 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
566 bool &Result) const {
567 // FIXME: Unimplemented.
569 return object_error::success;
572 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
573 bool &Result) const {
574 // FIXME: Unimplemented.
576 return object_error::success;
579 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
581 uint32_t Flags = getSectionFlags(this, Sec);
582 unsigned SectionType = Flags & MachO::SECTION_TYPE;
583 Res = SectionType == MachO::S_ZEROFILL ||
584 SectionType == MachO::S_GB_ZEROFILL;
585 return object_error::success;
588 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
589 bool &Result) const {
590 // Consider using the code from isSectionText to look for __const sections.
591 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
592 // to use section attributes to distinguish code from data.
594 // FIXME: Unimplemented.
596 return object_error::success;
599 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
601 bool &Result) const {
603 this->getSymbolType(Symb, ST);
604 if (ST == SymbolRef::ST_Unknown) {
606 return object_error::success;
609 uint64_t SectBegin, SectEnd;
610 getSectionAddress(Sec, SectBegin);
611 getSectionSize(Sec, SectEnd);
612 SectEnd += SectBegin;
615 getSymbolAddress(Symb, SymAddr);
616 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
618 return object_error::success;
621 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
625 return relocation_iterator(RelocationRef(Ret, this));
629 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
632 MachO::section_64 Sect = getSection64(Sec);
635 MachO::section Sect = getSection(Sec);
642 return relocation_iterator(RelocationRef(Ret, this));
645 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
649 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
650 uint64_t &Res) const {
652 getRelocationOffset(Rel, Offset);
657 getSectionAddress(Sec, SecAddress);
658 Res = SecAddress + Offset;
659 return object_error::success;
662 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
663 uint64_t &Res) const {
664 assert(getHeader().filetype == MachO::MH_OBJECT &&
665 "Only implemented for MH_OBJECT");
666 MachO::any_relocation_info RE = getRelocation(Rel);
667 Res = getAnyRelocationAddress(RE);
668 return object_error::success;
672 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
673 MachO::any_relocation_info RE = getRelocation(Rel);
674 if (isRelocationScattered(RE))
677 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
678 bool isExtern = getPlainRelocationExternal(RE);
682 MachO::symtab_command S = getSymtabLoadCommand();
683 unsigned SymbolTableEntrySize = is64Bit() ?
684 sizeof(MachO::nlist_64) :
685 sizeof(MachO::nlist);
686 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
688 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
689 return symbol_iterator(SymbolRef(Sym, this));
692 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
693 uint64_t &Res) const {
694 MachO::any_relocation_info RE = getRelocation(Rel);
695 Res = getAnyRelocationType(RE);
696 return object_error::success;
700 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
701 SmallVectorImpl<char> &Result) const {
704 getRelocationType(Rel, RType);
706 unsigned Arch = this->getArch();
710 static const char *const Table[] = {
711 "GENERIC_RELOC_VANILLA",
712 "GENERIC_RELOC_PAIR",
713 "GENERIC_RELOC_SECTDIFF",
714 "GENERIC_RELOC_PB_LA_PTR",
715 "GENERIC_RELOC_LOCAL_SECTDIFF",
716 "GENERIC_RELOC_TLV" };
724 case Triple::x86_64: {
725 static const char *const Table[] = {
726 "X86_64_RELOC_UNSIGNED",
727 "X86_64_RELOC_SIGNED",
728 "X86_64_RELOC_BRANCH",
729 "X86_64_RELOC_GOT_LOAD",
731 "X86_64_RELOC_SUBTRACTOR",
732 "X86_64_RELOC_SIGNED_1",
733 "X86_64_RELOC_SIGNED_2",
734 "X86_64_RELOC_SIGNED_4",
735 "X86_64_RELOC_TLV" };
744 static const char *const Table[] = {
747 "ARM_RELOC_SECTDIFF",
748 "ARM_RELOC_LOCAL_SECTDIFF",
749 "ARM_RELOC_PB_LA_PTR",
751 "ARM_THUMB_RELOC_BR22",
752 "ARM_THUMB_32BIT_BRANCH",
754 "ARM_RELOC_HALF_SECTDIFF" };
762 case Triple::aarch64: {
763 static const char *const Table[] = {
764 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
765 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
766 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
767 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
768 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
772 if (RType >= array_lengthof(Table))
779 static const char *const Table[] = {
788 "PPC_RELOC_SECTDIFF",
789 "PPC_RELOC_PB_LA_PTR",
790 "PPC_RELOC_HI16_SECTDIFF",
791 "PPC_RELOC_LO16_SECTDIFF",
792 "PPC_RELOC_HA16_SECTDIFF",
794 "PPC_RELOC_LO14_SECTDIFF",
795 "PPC_RELOC_LOCAL_SECTDIFF" };
803 case Triple::UnknownArch:
807 Result.append(res.begin(), res.end());
808 return object_error::success;
812 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
813 SmallVectorImpl<char> &Result) const {
814 MachO::any_relocation_info RE = getRelocation(Rel);
816 unsigned Arch = this->getArch();
819 raw_string_ostream fmt(fmtbuf);
820 unsigned Type = this->getAnyRelocationType(RE);
821 bool IsPCRel = this->getAnyRelocationPCRel(RE);
823 // Determine any addends that should be displayed with the relocation.
824 // These require decoding the relocation type, which is triple-specific.
826 // X86_64 has entirely custom relocation types.
827 if (Arch == Triple::x86_64) {
828 bool isPCRel = getAnyRelocationPCRel(RE);
831 case MachO::X86_64_RELOC_GOT_LOAD:
832 case MachO::X86_64_RELOC_GOT: {
833 printRelocationTargetName(this, RE, fmt);
835 if (isPCRel) fmt << "PCREL";
838 case MachO::X86_64_RELOC_SUBTRACTOR: {
839 DataRefImpl RelNext = Rel;
840 moveRelocationNext(RelNext);
841 MachO::any_relocation_info RENext = getRelocation(RelNext);
843 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
844 // X86_64_RELOC_UNSIGNED.
845 // NOTE: Scattered relocations don't exist on x86_64.
846 unsigned RType = getAnyRelocationType(RENext);
847 if (RType != MachO::X86_64_RELOC_UNSIGNED)
848 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
849 "X86_64_RELOC_SUBTRACTOR.");
851 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
852 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
853 printRelocationTargetName(this, RENext, fmt);
855 printRelocationTargetName(this, RE, fmt);
858 case MachO::X86_64_RELOC_TLV:
859 printRelocationTargetName(this, RE, fmt);
861 if (isPCRel) fmt << "P";
863 case MachO::X86_64_RELOC_SIGNED_1:
864 printRelocationTargetName(this, RE, fmt);
867 case MachO::X86_64_RELOC_SIGNED_2:
868 printRelocationTargetName(this, RE, fmt);
871 case MachO::X86_64_RELOC_SIGNED_4:
872 printRelocationTargetName(this, RE, fmt);
876 printRelocationTargetName(this, RE, fmt);
879 // X86 and ARM share some relocation types in common.
880 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
881 Arch == Triple::ppc) {
882 // Generic relocation types...
884 case MachO::GENERIC_RELOC_PAIR: // prints no info
885 return object_error::success;
886 case MachO::GENERIC_RELOC_SECTDIFF: {
887 DataRefImpl RelNext = Rel;
888 moveRelocationNext(RelNext);
889 MachO::any_relocation_info RENext = getRelocation(RelNext);
891 // X86 sect diff's must be followed by a relocation of type
892 // GENERIC_RELOC_PAIR.
893 unsigned RType = getAnyRelocationType(RENext);
895 if (RType != MachO::GENERIC_RELOC_PAIR)
896 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
897 "GENERIC_RELOC_SECTDIFF.");
899 printRelocationTargetName(this, RE, fmt);
901 printRelocationTargetName(this, RENext, fmt);
906 if (Arch == Triple::x86 || Arch == Triple::ppc) {
908 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
909 DataRefImpl RelNext = Rel;
910 moveRelocationNext(RelNext);
911 MachO::any_relocation_info RENext = getRelocation(RelNext);
913 // X86 sect diff's must be followed by a relocation of type
914 // GENERIC_RELOC_PAIR.
915 unsigned RType = getAnyRelocationType(RENext);
916 if (RType != MachO::GENERIC_RELOC_PAIR)
917 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
918 "GENERIC_RELOC_LOCAL_SECTDIFF.");
920 printRelocationTargetName(this, RE, fmt);
922 printRelocationTargetName(this, RENext, fmt);
925 case MachO::GENERIC_RELOC_TLV: {
926 printRelocationTargetName(this, RE, fmt);
928 if (IsPCRel) fmt << "P";
932 printRelocationTargetName(this, RE, fmt);
934 } else { // ARM-specific relocations
936 case MachO::ARM_RELOC_HALF:
937 case MachO::ARM_RELOC_HALF_SECTDIFF: {
938 // Half relocations steal a bit from the length field to encode
939 // whether this is an upper16 or a lower16 relocation.
940 bool isUpper = getAnyRelocationLength(RE) >> 1;
946 printRelocationTargetName(this, RE, fmt);
948 DataRefImpl RelNext = Rel;
949 moveRelocationNext(RelNext);
950 MachO::any_relocation_info RENext = getRelocation(RelNext);
952 // ARM half relocs must be followed by a relocation of type
954 unsigned RType = getAnyRelocationType(RENext);
955 if (RType != MachO::ARM_RELOC_PAIR)
956 report_fatal_error("Expected ARM_RELOC_PAIR after "
959 // NOTE: The half of the target virtual address is stashed in the
960 // address field of the secondary relocation, but we can't reverse
961 // engineer the constant offset from it without decoding the movw/movt
962 // instruction to find the other half in its immediate field.
964 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
965 // symbol/section pointer of the follow-on relocation.
966 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
968 printRelocationTargetName(this, RENext, fmt);
975 printRelocationTargetName(this, RE, fmt);
980 printRelocationTargetName(this, RE, fmt);
983 Result.append(fmtbuf.begin(), fmtbuf.end());
984 return object_error::success;
987 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
988 bool &Result) const {
989 unsigned Arch = getArch();
991 getRelocationType(Rel, Type);
995 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
997 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
998 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
999 } else if (Arch == Triple::x86_64) {
1000 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1001 // an X86_64_RELOC_SUBTRACTOR.
1002 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1003 DataRefImpl RelPrev = Rel;
1006 getRelocationType(RelPrev, PrevType);
1007 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1012 return object_error::success;
1016 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1017 // guess on what the short name is. Then name is returned as a substring of the
1018 // StringRef Name passed in. The name of the dynamic library is recognized as
1019 // a framework if it has one of the two following forms:
1020 // Foo.framework/Versions/A/Foo
1021 // Foo.framework/Foo
1022 // Where A and Foo can be any string. And may contain a trailing suffix
1023 // starting with an underbar. If the Name is recognized as a framework then
1024 // isFramework is set to true else it is set to false. If the Name has a
1025 // suffix then Suffix is set to the substring in Name that contains the suffix
1026 // else it is set to a NULL StringRef.
1028 // The Name of the dynamic library is recognized as a library name if it has
1029 // one of the two following forms:
1032 // The library may have a suffix trailing the name Foo of the form:
1033 // libFoo_profile.A.dylib
1034 // libFoo_profile.dylib
1036 // The Name of the dynamic library is also recognized as a library name if it
1037 // has the following form:
1040 // If the Name of the dynamic library is none of the forms above then a NULL
1041 // StringRef is returned.
1043 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1045 StringRef &Suffix) {
1046 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1047 size_t a, b, c, d, Idx;
1049 isFramework = false;
1050 Suffix = StringRef();
1052 // Pull off the last component and make Foo point to it
1053 a = Name.rfind('/');
1054 if (a == Name.npos || a == 0)
1056 Foo = Name.slice(a+1, Name.npos);
1058 // Look for a suffix starting with a '_'
1059 Idx = Foo.rfind('_');
1060 if (Idx != Foo.npos && Foo.size() >= 2) {
1061 Suffix = Foo.slice(Idx, Foo.npos);
1062 Foo = Foo.slice(0, Idx);
1065 // First look for the form Foo.framework/Foo
1066 b = Name.rfind('/', a);
1071 F = Name.slice(Idx, Idx + Foo.size());
1072 DotFramework = Name.slice(Idx + Foo.size(),
1073 Idx + Foo.size() + sizeof(".framework/")-1);
1074 if (F == Foo && DotFramework == ".framework/") {
1079 // Next look for the form Foo.framework/Versions/A/Foo
1082 c = Name.rfind('/', b);
1083 if (c == Name.npos || c == 0)
1085 V = Name.slice(c+1, Name.npos);
1086 if (!V.startswith("Versions/"))
1088 d = Name.rfind('/', c);
1093 F = Name.slice(Idx, Idx + Foo.size());
1094 DotFramework = Name.slice(Idx + Foo.size(),
1095 Idx + Foo.size() + sizeof(".framework/")-1);
1096 if (F == Foo && DotFramework == ".framework/") {
1102 // pull off the suffix after the "." and make a point to it
1103 a = Name.rfind('.');
1104 if (a == Name.npos || a == 0)
1106 Dylib = Name.slice(a, Name.npos);
1107 if (Dylib != ".dylib")
1110 // First pull off the version letter for the form Foo.A.dylib if any.
1112 Dot = Name.slice(a-2, a-1);
1117 b = Name.rfind('/', a);
1122 // ignore any suffix after an underbar like Foo_profile.A.dylib
1123 Idx = Name.find('_', b);
1124 if (Idx != Name.npos && Idx != b) {
1125 Lib = Name.slice(b, Idx);
1126 Suffix = Name.slice(Idx, a);
1129 Lib = Name.slice(b, a);
1130 // There are incorrect library names of the form:
1131 // libATS.A_profile.dylib so check for these.
1132 if (Lib.size() >= 3) {
1133 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1135 Lib = Lib.slice(0, Lib.size()-2);
1140 Qtx = Name.slice(a, Name.npos);
1143 b = Name.rfind('/', a);
1145 Lib = Name.slice(0, a);
1147 Lib = Name.slice(b+1, a);
1148 // There are library names of the form: QT.A.qtx so check for these.
1149 if (Lib.size() >= 3) {
1150 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1152 Lib = Lib.slice(0, Lib.size()-2);
1157 // getLibraryShortNameByIndex() is used to get the short name of the library
1158 // for an undefined symbol in a linked Mach-O binary that was linked with the
1159 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1160 // It is passed the index (0 - based) of the library as translated from
1161 // GET_LIBRARY_ORDINAL (1 - based).
1162 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1164 if (Index >= Libraries.size())
1165 return object_error::parse_failed;
1167 MachO::dylib_command D =
1168 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1169 if (D.dylib.name >= D.cmdsize)
1170 return object_error::parse_failed;
1172 // If the cache of LibrariesShortNames is not built up do that first for
1173 // all the Libraries.
1174 if (LibrariesShortNames.size() == 0) {
1175 for (unsigned i = 0; i < Libraries.size(); i++) {
1176 MachO::dylib_command D =
1177 getStruct<MachO::dylib_command>(this, Libraries[i]);
1178 if (D.dylib.name >= D.cmdsize) {
1179 LibrariesShortNames.push_back(StringRef());
1182 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1183 StringRef Name = StringRef(P);
1186 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1187 if (shortName == StringRef())
1188 LibrariesShortNames.push_back(Name);
1190 LibrariesShortNames.push_back(shortName);
1194 Res = LibrariesShortNames[Index];
1195 return object_error::success;
1198 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1199 return getSymbolByIndex(0);
1202 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1205 return basic_symbol_iterator(SymbolRef(DRI, this));
1207 MachO::symtab_command Symtab = getSymtabLoadCommand();
1208 unsigned SymbolTableEntrySize = is64Bit() ?
1209 sizeof(MachO::nlist_64) :
1210 sizeof(MachO::nlist);
1211 unsigned Offset = Symtab.symoff +
1212 Symtab.nsyms * SymbolTableEntrySize;
1213 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1214 return basic_symbol_iterator(SymbolRef(DRI, this));
1217 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1220 return basic_symbol_iterator(SymbolRef(DRI, this));
1222 MachO::symtab_command Symtab = getSymtabLoadCommand();
1223 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1224 unsigned SymbolTableEntrySize =
1225 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1226 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1227 DRI.p += Index * SymbolTableEntrySize;
1228 return basic_symbol_iterator(SymbolRef(DRI, this));
1231 section_iterator MachOObjectFile::section_begin() const {
1233 return section_iterator(SectionRef(DRI, this));
1236 section_iterator MachOObjectFile::section_end() const {
1238 DRI.d.a = Sections.size();
1239 return section_iterator(SectionRef(DRI, this));
1242 uint8_t MachOObjectFile::getBytesInAddress() const {
1243 return is64Bit() ? 8 : 4;
1246 StringRef MachOObjectFile::getFileFormatName() const {
1247 unsigned CPUType = getCPUType(this);
1250 case llvm::MachO::CPU_TYPE_I386:
1251 return "Mach-O 32-bit i386";
1252 case llvm::MachO::CPU_TYPE_ARM:
1253 return "Mach-O arm";
1254 case llvm::MachO::CPU_TYPE_POWERPC:
1255 return "Mach-O 32-bit ppc";
1257 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1258 "64-bit object file when we're not 64-bit?");
1259 return "Mach-O 32-bit unknown";
1263 // Make sure the cpu type has the correct mask.
1264 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1265 == llvm::MachO::CPU_ARCH_ABI64 &&
1266 "32-bit object file when we're 64-bit?");
1269 case llvm::MachO::CPU_TYPE_X86_64:
1270 return "Mach-O 64-bit x86-64";
1271 case llvm::MachO::CPU_TYPE_ARM64:
1272 return "Mach-O arm64";
1273 case llvm::MachO::CPU_TYPE_POWERPC64:
1274 return "Mach-O 64-bit ppc64";
1276 return "Mach-O 64-bit unknown";
1280 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1282 case llvm::MachO::CPU_TYPE_I386:
1284 case llvm::MachO::CPU_TYPE_X86_64:
1285 return Triple::x86_64;
1286 case llvm::MachO::CPU_TYPE_ARM:
1288 case llvm::MachO::CPU_TYPE_ARM64:
1289 return Triple::aarch64;
1290 case llvm::MachO::CPU_TYPE_POWERPC:
1292 case llvm::MachO::CPU_TYPE_POWERPC64:
1293 return Triple::ppc64;
1295 return Triple::UnknownArch;
1299 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1300 const char **McpuDefault) {
1302 *McpuDefault = nullptr;
1305 case MachO::CPU_TYPE_I386:
1306 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1307 case MachO::CPU_SUBTYPE_I386_ALL:
1308 return Triple("i386-apple-darwin");
1312 case MachO::CPU_TYPE_X86_64:
1313 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1314 case MachO::CPU_SUBTYPE_X86_64_ALL:
1315 return Triple("x86_64-apple-darwin");
1316 case MachO::CPU_SUBTYPE_X86_64_H:
1317 return Triple("x86_64h-apple-darwin");
1321 case MachO::CPU_TYPE_ARM:
1322 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1323 case MachO::CPU_SUBTYPE_ARM_V4T:
1324 return Triple("armv4t-apple-darwin");
1325 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1326 return Triple("armv5e-apple-darwin");
1327 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1328 return Triple("xscale-apple-darwin");
1329 case MachO::CPU_SUBTYPE_ARM_V6:
1330 return Triple("armv6-apple-darwin");
1331 case MachO::CPU_SUBTYPE_ARM_V6M:
1333 *McpuDefault = "cortex-m0";
1334 return Triple("armv6m-apple-darwin");
1335 case MachO::CPU_SUBTYPE_ARM_V7:
1336 return Triple("armv7-apple-darwin");
1337 case MachO::CPU_SUBTYPE_ARM_V7EM:
1339 *McpuDefault = "cortex-m4";
1340 return Triple("armv7em-apple-darwin");
1341 case MachO::CPU_SUBTYPE_ARM_V7K:
1342 return Triple("armv7k-apple-darwin");
1343 case MachO::CPU_SUBTYPE_ARM_V7M:
1345 *McpuDefault = "cortex-m3";
1346 return Triple("armv7m-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_V7S:
1348 return Triple("armv7s-apple-darwin");
1352 case MachO::CPU_TYPE_ARM64:
1353 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1354 case MachO::CPU_SUBTYPE_ARM64_ALL:
1355 return Triple("arm64-apple-darwin");
1359 case MachO::CPU_TYPE_POWERPC:
1360 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1361 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1362 return Triple("ppc-apple-darwin");
1366 case MachO::CPU_TYPE_POWERPC64:
1367 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1368 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1369 return Triple("ppc64-apple-darwin");
1378 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1379 const char **McpuDefault) {
1381 *McpuDefault = nullptr;
1384 case MachO::CPU_TYPE_ARM:
1385 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1386 case MachO::CPU_SUBTYPE_ARM_V4T:
1387 return Triple("thumbv4t-apple-darwin");
1388 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1389 return Triple("thumbv5e-apple-darwin");
1390 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1391 return Triple("xscale-apple-darwin");
1392 case MachO::CPU_SUBTYPE_ARM_V6:
1393 return Triple("thumbv6-apple-darwin");
1394 case MachO::CPU_SUBTYPE_ARM_V6M:
1396 *McpuDefault = "cortex-m0";
1397 return Triple("thumbv6m-apple-darwin");
1398 case MachO::CPU_SUBTYPE_ARM_V7:
1399 return Triple("thumbv7-apple-darwin");
1400 case MachO::CPU_SUBTYPE_ARM_V7EM:
1402 *McpuDefault = "cortex-m4";
1403 return Triple("thumbv7em-apple-darwin");
1404 case MachO::CPU_SUBTYPE_ARM_V7K:
1405 return Triple("thumbv7k-apple-darwin");
1406 case MachO::CPU_SUBTYPE_ARM_V7M:
1408 *McpuDefault = "cortex-m3";
1409 return Triple("thumbv7m-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_V7S:
1411 return Triple("thumbv7s-apple-darwin");
1420 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1421 const char **McpuDefault,
1422 Triple *ThumbTriple) {
1423 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1424 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1429 Triple MachOObjectFile::getHostArch() {
1430 return Triple(sys::getDefaultTargetTriple());
1433 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1434 return StringSwitch<bool>(ArchFlag)
1436 .Case("x86_64", true)
1437 .Case("x86_64h", true)
1438 .Case("armv4t", true)
1440 .Case("armv5e", true)
1441 .Case("armv6", true)
1442 .Case("armv6m", true)
1443 .Case("armv7em", true)
1444 .Case("armv7k", true)
1445 .Case("armv7m", true)
1446 .Case("armv7s", true)
1447 .Case("arm64", true)
1449 .Case("ppc64", true)
1453 unsigned MachOObjectFile::getArch() const {
1454 return getArch(getCPUType(this));
1457 Triple MachOObjectFile::getArch(const char **McpuDefault,
1458 Triple *ThumbTriple) const {
1461 MachO::mach_header_64 H_64;
1462 H_64 = getHeader64();
1463 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1464 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1467 MachO::mach_header H;
1469 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1470 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1476 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1479 return section_rel_begin(DRI);
1482 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1485 return section_rel_end(DRI);
1488 dice_iterator MachOObjectFile::begin_dices() const {
1490 if (!DataInCodeLoadCmd)
1491 return dice_iterator(DiceRef(DRI, this));
1493 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1494 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1495 return dice_iterator(DiceRef(DRI, this));
1498 dice_iterator MachOObjectFile::end_dices() const {
1500 if (!DataInCodeLoadCmd)
1501 return dice_iterator(DiceRef(DRI, this));
1503 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1504 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1505 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1506 return dice_iterator(DiceRef(DRI, this));
1510 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1511 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1512 return parseSegmentOrSectionName(Raw.data());
1516 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1517 const section_base *Base =
1518 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1519 return ArrayRef<char>(Base->sectname);
1523 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1524 const section_base *Base =
1525 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1526 return ArrayRef<char>(Base->segname);
1530 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1532 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1534 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1537 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1538 const MachO::any_relocation_info &RE) const {
1539 if (isLittleEndian())
1540 return RE.r_word1 & 0xffffff;
1541 return RE.r_word1 >> 8;
1544 bool MachOObjectFile::getPlainRelocationExternal(
1545 const MachO::any_relocation_info &RE) const {
1546 if (isLittleEndian())
1547 return (RE.r_word1 >> 27) & 1;
1548 return (RE.r_word1 >> 4) & 1;
1551 bool MachOObjectFile::getScatteredRelocationScattered(
1552 const MachO::any_relocation_info &RE) const {
1553 return RE.r_word0 >> 31;
1556 uint32_t MachOObjectFile::getScatteredRelocationValue(
1557 const MachO::any_relocation_info &RE) const {
1561 unsigned MachOObjectFile::getAnyRelocationAddress(
1562 const MachO::any_relocation_info &RE) const {
1563 if (isRelocationScattered(RE))
1564 return getScatteredRelocationAddress(RE);
1565 return getPlainRelocationAddress(RE);
1568 unsigned MachOObjectFile::getAnyRelocationPCRel(
1569 const MachO::any_relocation_info &RE) const {
1570 if (isRelocationScattered(RE))
1571 return getScatteredRelocationPCRel(this, RE);
1572 return getPlainRelocationPCRel(this, RE);
1575 unsigned MachOObjectFile::getAnyRelocationLength(
1576 const MachO::any_relocation_info &RE) const {
1577 if (isRelocationScattered(RE))
1578 return getScatteredRelocationLength(RE);
1579 return getPlainRelocationLength(this, RE);
1583 MachOObjectFile::getAnyRelocationType(
1584 const MachO::any_relocation_info &RE) const {
1585 if (isRelocationScattered(RE))
1586 return getScatteredRelocationType(RE);
1587 return getPlainRelocationType(this, RE);
1591 MachOObjectFile::getRelocationSection(
1592 const MachO::any_relocation_info &RE) const {
1593 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1594 return *section_end();
1595 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1598 return SectionRef(DRI, this);
1601 MachOObjectFile::LoadCommandInfo
1602 MachOObjectFile::getFirstLoadCommandInfo() const {
1603 MachOObjectFile::LoadCommandInfo Load;
1605 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1606 sizeof(MachO::mach_header);
1607 Load.Ptr = getPtr(this, HeaderSize);
1608 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1612 MachOObjectFile::LoadCommandInfo
1613 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1614 MachOObjectFile::LoadCommandInfo Next;
1615 Next.Ptr = L.Ptr + L.C.cmdsize;
1616 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1620 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1621 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1624 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1625 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1628 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1629 unsigned Index) const {
1630 const char *Sec = getSectionPtr(this, L, Index);
1631 return getStruct<MachO::section>(this, Sec);
1634 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1635 unsigned Index) const {
1636 const char *Sec = getSectionPtr(this, L, Index);
1637 return getStruct<MachO::section_64>(this, Sec);
1641 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1642 const char *P = reinterpret_cast<const char *>(DRI.p);
1643 return getStruct<MachO::nlist>(this, P);
1647 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1648 const char *P = reinterpret_cast<const char *>(DRI.p);
1649 return getStruct<MachO::nlist_64>(this, P);
1652 MachO::linkedit_data_command
1653 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1654 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1657 MachO::segment_command
1658 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1659 return getStruct<MachO::segment_command>(this, L.Ptr);
1662 MachO::segment_command_64
1663 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1664 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1667 MachO::linker_options_command
1668 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1669 return getStruct<MachO::linker_options_command>(this, L.Ptr);
1672 MachO::version_min_command
1673 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1674 return getStruct<MachO::version_min_command>(this, L.Ptr);
1677 MachO::dylib_command
1678 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1679 return getStruct<MachO::dylib_command>(this, L.Ptr);
1683 MachO::any_relocation_info
1684 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1689 MachO::section_64 Sect = getSection64(Sec);
1690 Offset = Sect.reloff;
1692 MachO::section Sect = getSection(Sec);
1693 Offset = Sect.reloff;
1696 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1697 getPtr(this, Offset)) + Rel.d.b;
1698 return getStruct<MachO::any_relocation_info>(
1699 this, reinterpret_cast<const char *>(P));
1702 MachO::data_in_code_entry
1703 MachOObjectFile::getDice(DataRefImpl Rel) const {
1704 const char *P = reinterpret_cast<const char *>(Rel.p);
1705 return getStruct<MachO::data_in_code_entry>(this, P);
1708 MachO::mach_header MachOObjectFile::getHeader() const {
1709 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1712 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1713 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1716 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1717 const MachO::dysymtab_command &DLC,
1718 unsigned Index) const {
1719 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1720 return getStruct<uint32_t>(this, getPtr(this, Offset));
1723 MachO::data_in_code_entry
1724 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1725 unsigned Index) const {
1726 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1727 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1730 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1731 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1734 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1735 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1738 MachO::linkedit_data_command
1739 MachOObjectFile::getDataInCodeLoadCommand() const {
1740 if (DataInCodeLoadCmd)
1741 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1743 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1744 MachO::linkedit_data_command Cmd;
1745 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1746 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1752 StringRef MachOObjectFile::getStringTableData() const {
1753 MachO::symtab_command S = getSymtabLoadCommand();
1754 return getData().substr(S.stroff, S.strsize);
1757 bool MachOObjectFile::is64Bit() const {
1758 return getType() == getMachOType(false, true) ||
1759 getType() == getMachOType(true, true);
1762 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1763 SmallVectorImpl<uint64_t> &Out) const {
1764 DataExtractor extractor(ObjectFile::getData(), true, 0);
1766 uint32_t offset = Index;
1768 while (uint64_t delta = extractor.getULEB128(&offset)) {
1770 Out.push_back(data);
1774 bool MachOObjectFile::isRelocatableObject() const {
1775 return getHeader().filetype == MachO::MH_OBJECT;
1778 ErrorOr<std::unique_ptr<MachOObjectFile>>
1779 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
1780 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1782 std::unique_ptr<MachOObjectFile> Ret;
1783 if (Magic == "\xFE\xED\xFA\xCE")
1784 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
1785 else if (Magic == "\xCE\xFA\xED\xFE")
1786 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
1787 else if (Magic == "\xFE\xED\xFA\xCF")
1788 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
1789 else if (Magic == "\xCF\xFA\xED\xFE")
1790 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
1792 return object_error::parse_failed;
1796 return std::move(Ret);