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/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
41 // FIXME: Replace all uses of this function with getStructOrErr.
43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
87 static MachO::nlist_base
88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
93 static StringRef parseSegmentOrSectionName(const char *P) {
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
101 // Helper to advance a section or symbol iterator multiple increments at a time.
103 static void advance(T &it, size_t Val) {
108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile *O,
157 MachO::section_64 Sect = O->getSection64(Sec);
160 MachO::section Sect = O->getSection(Sec);
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
173 Load.C = CmdOrErr.get();
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
190 template <typename T>
191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
195 Header = HeaderOrErr.get();
197 EC = HeaderOrErr.getError();
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
235 parseHeader(this, Header64, EC);
237 parseHeader(this, Header, EC);
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
247 EC = LoadOrErr.getError();
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
256 EC = object_error::parse_failed;
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
292 EC = object_error::parse_failed;
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
314 EC = LoadOrErr.getError();
317 Load = LoadOrErr.get();
320 assert(LoadCommands.size() == LoadCommandCount);
323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
330 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
334 const char *Start = &StringTable.data()[Entry.n_strx];
335 if (Start < getData().begin() || Start >= getData().end())
337 "Symbol name entry points before beginning or past end of file.");
338 Res = StringRef(Start);
339 return std::error_code();
342 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
343 DataRefImpl DRI = Sec.getRawDataRefImpl();
344 uint32_t Flags = getSectionFlags(this, DRI);
345 return Flags & MachO::SECTION_TYPE;
348 // getIndirectName() returns the name of the alias'ed symbol who's string table
349 // index is in the n_value field.
350 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
351 StringRef &Res) const {
352 StringRef StringTable = getStringTableData();
355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
356 NValue = Entry.n_value;
357 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
358 return object_error::parse_failed;
360 MachO::nlist Entry = getSymbolTableEntry(Symb);
361 NValue = Entry.n_value;
362 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
363 return object_error::parse_failed;
365 if (NValue >= StringTable.size())
366 return object_error::parse_failed;
367 const char *Start = &StringTable.data()[NValue];
368 Res = StringRef(Start);
369 return std::error_code();
372 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
373 uint64_t &Res) const {
375 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
378 Res = UnknownAddressOrSize;
382 MachO::nlist Entry = getSymbolTableEntry(Symb);
383 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
385 Res = UnknownAddressOrSize;
389 return std::error_code();
392 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
393 uint32_t flags = getSymbolFlags(DRI);
394 if (flags & SymbolRef::SF_Common) {
395 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
396 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
401 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
403 getSymbolAddress(DRI, Value);
404 uint32_t flags = getSymbolFlags(DRI);
405 if (flags & SymbolRef::SF_Common)
407 return UnknownAddressOrSize;
410 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
411 SymbolRef::Type &Res) const {
412 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
413 uint8_t n_type = Entry.n_type;
415 Res = SymbolRef::ST_Other;
417 // If this is a STAB debugging symbol, we can do nothing more.
418 if (n_type & MachO::N_STAB) {
419 Res = SymbolRef::ST_Debug;
420 return std::error_code();
423 switch (n_type & MachO::N_TYPE) {
425 Res = SymbolRef::ST_Unknown;
428 Res = SymbolRef::ST_Function;
431 return std::error_code();
434 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
435 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
437 uint8_t MachOType = Entry.n_type;
438 uint16_t MachOFlags = Entry.n_desc;
440 uint32_t Result = SymbolRef::SF_None;
442 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
443 Result |= SymbolRef::SF_Undefined;
445 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
446 Result |= SymbolRef::SF_Indirect;
448 if (MachOType & MachO::N_STAB)
449 Result |= SymbolRef::SF_FormatSpecific;
451 if (MachOType & MachO::N_EXT) {
452 Result |= SymbolRef::SF_Global;
453 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
455 getSymbolAddress(DRI, Value);
456 if (Value && Value != UnknownAddressOrSize)
457 Result |= SymbolRef::SF_Common;
460 if (!(MachOType & MachO::N_PEXT))
461 Result |= SymbolRef::SF_Exported;
464 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
465 Result |= SymbolRef::SF_Weak;
467 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
468 Result |= SymbolRef::SF_Thumb;
470 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
471 Result |= SymbolRef::SF_Absolute;
476 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
477 section_iterator &Res) const {
478 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
479 uint8_t index = Entry.n_sect;
486 if (DRI.d.a >= Sections.size())
487 report_fatal_error("getSymbolSection: Invalid section index.");
488 Res = section_iterator(SectionRef(DRI, this));
491 return std::error_code();
494 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
498 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
499 StringRef &Result) const {
500 ArrayRef<char> Raw = getSectionRawName(Sec);
501 Result = parseSegmentOrSectionName(Raw.data());
502 return std::error_code();
505 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
507 return getSection64(Sec).addr;
508 return getSection(Sec).addr;
511 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
513 return getSection64(Sec).size;
514 return getSection(Sec).size;
517 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
518 StringRef &Res) const {
523 MachO::section_64 Sect = getSection64(Sec);
524 Offset = Sect.offset;
527 MachO::section Sect = getSection(Sec);
528 Offset = Sect.offset;
532 Res = this->getData().substr(Offset, Size);
533 return std::error_code();
536 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
539 MachO::section_64 Sect = getSection64(Sec);
542 MachO::section Sect = getSection(Sec);
546 return uint64_t(1) << Align;
549 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
550 uint32_t Flags = getSectionFlags(this, Sec);
551 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
554 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
555 uint32_t Flags = getSectionFlags(this, Sec);
556 unsigned SectionType = Flags & MachO::SECTION_TYPE;
557 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558 !(SectionType == MachO::S_ZEROFILL ||
559 SectionType == MachO::S_GB_ZEROFILL);
562 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
563 uint32_t Flags = getSectionFlags(this, Sec);
564 unsigned SectionType = Flags & MachO::SECTION_TYPE;
565 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
566 (SectionType == MachO::S_ZEROFILL ||
567 SectionType == MachO::S_GB_ZEROFILL);
570 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
571 // FIXME: Unimplemented.
575 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
576 DataRefImpl Symb) const {
578 this->getSymbolType(Symb, ST);
579 if (ST == SymbolRef::ST_Unknown)
582 uint64_t SectBegin = getSectionAddress(Sec);
583 uint64_t SectEnd = getSectionSize(Sec);
584 SectEnd += SectBegin;
587 getSymbolAddress(Symb, SymAddr);
588 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
591 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
595 return relocation_iterator(RelocationRef(Ret, this));
599 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
602 MachO::section_64 Sect = getSection64(Sec);
605 MachO::section Sect = getSection(Sec);
612 return relocation_iterator(RelocationRef(Ret, this));
615 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
619 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
620 uint64_t &Res) const {
622 getRelocationOffset(Rel, Offset);
626 uint64_t SecAddress = getSectionAddress(Sec);
627 Res = SecAddress + Offset;
628 return std::error_code();
631 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
632 uint64_t &Res) const {
633 assert(getHeader().filetype == MachO::MH_OBJECT &&
634 "Only implemented for MH_OBJECT");
635 MachO::any_relocation_info RE = getRelocation(Rel);
636 Res = getAnyRelocationAddress(RE);
637 return std::error_code();
641 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
642 MachO::any_relocation_info RE = getRelocation(Rel);
643 if (isRelocationScattered(RE))
646 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
647 bool isExtern = getPlainRelocationExternal(RE);
651 MachO::symtab_command S = getSymtabLoadCommand();
652 unsigned SymbolTableEntrySize = is64Bit() ?
653 sizeof(MachO::nlist_64) :
654 sizeof(MachO::nlist);
655 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
657 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
658 return symbol_iterator(SymbolRef(Sym, this));
662 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
663 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
666 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
667 uint64_t &Res) const {
668 MachO::any_relocation_info RE = getRelocation(Rel);
669 Res = getAnyRelocationType(RE);
670 return std::error_code();
674 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
675 SmallVectorImpl<char> &Result) const {
678 getRelocationType(Rel, RType);
680 unsigned Arch = this->getArch();
684 static const char *const Table[] = {
685 "GENERIC_RELOC_VANILLA",
686 "GENERIC_RELOC_PAIR",
687 "GENERIC_RELOC_SECTDIFF",
688 "GENERIC_RELOC_PB_LA_PTR",
689 "GENERIC_RELOC_LOCAL_SECTDIFF",
690 "GENERIC_RELOC_TLV" };
698 case Triple::x86_64: {
699 static const char *const Table[] = {
700 "X86_64_RELOC_UNSIGNED",
701 "X86_64_RELOC_SIGNED",
702 "X86_64_RELOC_BRANCH",
703 "X86_64_RELOC_GOT_LOAD",
705 "X86_64_RELOC_SUBTRACTOR",
706 "X86_64_RELOC_SIGNED_1",
707 "X86_64_RELOC_SIGNED_2",
708 "X86_64_RELOC_SIGNED_4",
709 "X86_64_RELOC_TLV" };
718 static const char *const Table[] = {
721 "ARM_RELOC_SECTDIFF",
722 "ARM_RELOC_LOCAL_SECTDIFF",
723 "ARM_RELOC_PB_LA_PTR",
725 "ARM_THUMB_RELOC_BR22",
726 "ARM_THUMB_32BIT_BRANCH",
728 "ARM_RELOC_HALF_SECTDIFF" };
736 case Triple::aarch64: {
737 static const char *const Table[] = {
738 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
739 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
740 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
741 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
742 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
746 if (RType >= array_lengthof(Table))
753 static const char *const Table[] = {
762 "PPC_RELOC_SECTDIFF",
763 "PPC_RELOC_PB_LA_PTR",
764 "PPC_RELOC_HI16_SECTDIFF",
765 "PPC_RELOC_LO16_SECTDIFF",
766 "PPC_RELOC_HA16_SECTDIFF",
768 "PPC_RELOC_LO14_SECTDIFF",
769 "PPC_RELOC_LOCAL_SECTDIFF" };
777 case Triple::UnknownArch:
781 Result.append(res.begin(), res.end());
782 return std::error_code();
785 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
786 bool &Result) const {
787 unsigned Arch = getArch();
789 getRelocationType(Rel, Type);
793 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
795 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
796 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
797 } else if (Arch == Triple::x86_64) {
798 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
799 // an X86_64_RELOC_SUBTRACTOR.
800 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
801 DataRefImpl RelPrev = Rel;
804 getRelocationType(RelPrev, PrevType);
805 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
810 return std::error_code();
813 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
814 MachO::any_relocation_info RE = getRelocation(Rel);
815 return getAnyRelocationLength(RE);
819 // guessLibraryShortName() is passed a name of a dynamic library and returns a
820 // guess on what the short name is. Then name is returned as a substring of the
821 // StringRef Name passed in. The name of the dynamic library is recognized as
822 // a framework if it has one of the two following forms:
823 // Foo.framework/Versions/A/Foo
825 // Where A and Foo can be any string. And may contain a trailing suffix
826 // starting with an underbar. If the Name is recognized as a framework then
827 // isFramework is set to true else it is set to false. If the Name has a
828 // suffix then Suffix is set to the substring in Name that contains the suffix
829 // else it is set to a NULL StringRef.
831 // The Name of the dynamic library is recognized as a library name if it has
832 // one of the two following forms:
835 // The library may have a suffix trailing the name Foo of the form:
836 // libFoo_profile.A.dylib
837 // libFoo_profile.dylib
839 // The Name of the dynamic library is also recognized as a library name if it
840 // has the following form:
843 // If the Name of the dynamic library is none of the forms above then a NULL
844 // StringRef is returned.
846 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
849 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
850 size_t a, b, c, d, Idx;
853 Suffix = StringRef();
855 // Pull off the last component and make Foo point to it
857 if (a == Name.npos || a == 0)
859 Foo = Name.slice(a+1, Name.npos);
861 // Look for a suffix starting with a '_'
862 Idx = Foo.rfind('_');
863 if (Idx != Foo.npos && Foo.size() >= 2) {
864 Suffix = Foo.slice(Idx, Foo.npos);
865 Foo = Foo.slice(0, Idx);
868 // First look for the form Foo.framework/Foo
869 b = Name.rfind('/', a);
874 F = Name.slice(Idx, Idx + Foo.size());
875 DotFramework = Name.slice(Idx + Foo.size(),
876 Idx + Foo.size() + sizeof(".framework/")-1);
877 if (F == Foo && DotFramework == ".framework/") {
882 // Next look for the form Foo.framework/Versions/A/Foo
885 c = Name.rfind('/', b);
886 if (c == Name.npos || c == 0)
888 V = Name.slice(c+1, Name.npos);
889 if (!V.startswith("Versions/"))
891 d = Name.rfind('/', c);
896 F = Name.slice(Idx, Idx + Foo.size());
897 DotFramework = Name.slice(Idx + Foo.size(),
898 Idx + Foo.size() + sizeof(".framework/")-1);
899 if (F == Foo && DotFramework == ".framework/") {
905 // pull off the suffix after the "." and make a point to it
907 if (a == Name.npos || a == 0)
909 Dylib = Name.slice(a, Name.npos);
910 if (Dylib != ".dylib")
913 // First pull off the version letter for the form Foo.A.dylib if any.
915 Dot = Name.slice(a-2, a-1);
920 b = Name.rfind('/', a);
925 // ignore any suffix after an underbar like Foo_profile.A.dylib
926 Idx = Name.find('_', b);
927 if (Idx != Name.npos && Idx != b) {
928 Lib = Name.slice(b, Idx);
929 Suffix = Name.slice(Idx, a);
932 Lib = Name.slice(b, a);
933 // There are incorrect library names of the form:
934 // libATS.A_profile.dylib so check for these.
935 if (Lib.size() >= 3) {
936 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
938 Lib = Lib.slice(0, Lib.size()-2);
943 Qtx = Name.slice(a, Name.npos);
946 b = Name.rfind('/', a);
948 Lib = Name.slice(0, a);
950 Lib = Name.slice(b+1, a);
951 // There are library names of the form: QT.A.qtx so check for these.
952 if (Lib.size() >= 3) {
953 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
955 Lib = Lib.slice(0, Lib.size()-2);
960 // getLibraryShortNameByIndex() is used to get the short name of the library
961 // for an undefined symbol in a linked Mach-O binary that was linked with the
962 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
963 // It is passed the index (0 - based) of the library as translated from
964 // GET_LIBRARY_ORDINAL (1 - based).
965 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
966 StringRef &Res) const {
967 if (Index >= Libraries.size())
968 return object_error::parse_failed;
970 // If the cache of LibrariesShortNames is not built up do that first for
971 // all the Libraries.
972 if (LibrariesShortNames.size() == 0) {
973 for (unsigned i = 0; i < Libraries.size(); i++) {
974 MachO::dylib_command D =
975 getStruct<MachO::dylib_command>(this, Libraries[i]);
976 if (D.dylib.name >= D.cmdsize)
977 return object_error::parse_failed;
978 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
979 StringRef Name = StringRef(P);
980 if (D.dylib.name+Name.size() >= D.cmdsize)
981 return object_error::parse_failed;
984 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
985 if (shortName.empty())
986 LibrariesShortNames.push_back(Name);
988 LibrariesShortNames.push_back(shortName);
992 Res = LibrariesShortNames[Index];
993 return std::error_code();
996 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
997 return getSymbolByIndex(0);
1000 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1003 return basic_symbol_iterator(SymbolRef(DRI, this));
1005 MachO::symtab_command Symtab = getSymtabLoadCommand();
1006 unsigned SymbolTableEntrySize = is64Bit() ?
1007 sizeof(MachO::nlist_64) :
1008 sizeof(MachO::nlist);
1009 unsigned Offset = Symtab.symoff +
1010 Symtab.nsyms * SymbolTableEntrySize;
1011 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1012 return basic_symbol_iterator(SymbolRef(DRI, this));
1015 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1018 return basic_symbol_iterator(SymbolRef(DRI, this));
1020 MachO::symtab_command Symtab = getSymtabLoadCommand();
1021 if (Index >= Symtab.nsyms)
1022 report_fatal_error("Requested symbol index is out of range.");
1023 unsigned SymbolTableEntrySize =
1024 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1025 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1026 DRI.p += Index * SymbolTableEntrySize;
1027 return basic_symbol_iterator(SymbolRef(DRI, this));
1030 section_iterator MachOObjectFile::section_begin() const {
1032 return section_iterator(SectionRef(DRI, this));
1035 section_iterator MachOObjectFile::section_end() const {
1037 DRI.d.a = Sections.size();
1038 return section_iterator(SectionRef(DRI, this));
1041 uint8_t MachOObjectFile::getBytesInAddress() const {
1042 return is64Bit() ? 8 : 4;
1045 StringRef MachOObjectFile::getFileFormatName() const {
1046 unsigned CPUType = getCPUType(this);
1049 case llvm::MachO::CPU_TYPE_I386:
1050 return "Mach-O 32-bit i386";
1051 case llvm::MachO::CPU_TYPE_ARM:
1052 return "Mach-O arm";
1053 case llvm::MachO::CPU_TYPE_POWERPC:
1054 return "Mach-O 32-bit ppc";
1056 return "Mach-O 32-bit unknown";
1061 case llvm::MachO::CPU_TYPE_X86_64:
1062 return "Mach-O 64-bit x86-64";
1063 case llvm::MachO::CPU_TYPE_ARM64:
1064 return "Mach-O arm64";
1065 case llvm::MachO::CPU_TYPE_POWERPC64:
1066 return "Mach-O 64-bit ppc64";
1068 return "Mach-O 64-bit unknown";
1072 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1074 case llvm::MachO::CPU_TYPE_I386:
1076 case llvm::MachO::CPU_TYPE_X86_64:
1077 return Triple::x86_64;
1078 case llvm::MachO::CPU_TYPE_ARM:
1080 case llvm::MachO::CPU_TYPE_ARM64:
1081 return Triple::aarch64;
1082 case llvm::MachO::CPU_TYPE_POWERPC:
1084 case llvm::MachO::CPU_TYPE_POWERPC64:
1085 return Triple::ppc64;
1087 return Triple::UnknownArch;
1091 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1092 const char **McpuDefault) {
1094 *McpuDefault = nullptr;
1097 case MachO::CPU_TYPE_I386:
1098 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1099 case MachO::CPU_SUBTYPE_I386_ALL:
1100 return Triple("i386-apple-darwin");
1104 case MachO::CPU_TYPE_X86_64:
1105 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1106 case MachO::CPU_SUBTYPE_X86_64_ALL:
1107 return Triple("x86_64-apple-darwin");
1108 case MachO::CPU_SUBTYPE_X86_64_H:
1109 return Triple("x86_64h-apple-darwin");
1113 case MachO::CPU_TYPE_ARM:
1114 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1115 case MachO::CPU_SUBTYPE_ARM_V4T:
1116 return Triple("armv4t-apple-darwin");
1117 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1118 return Triple("armv5e-apple-darwin");
1119 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1120 return Triple("xscale-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V6:
1122 return Triple("armv6-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V6M:
1125 *McpuDefault = "cortex-m0";
1126 return Triple("armv6m-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V7:
1128 return Triple("armv7-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V7EM:
1131 *McpuDefault = "cortex-m4";
1132 return Triple("armv7em-apple-darwin");
1133 case MachO::CPU_SUBTYPE_ARM_V7K:
1134 return Triple("armv7k-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V7M:
1137 *McpuDefault = "cortex-m3";
1138 return Triple("armv7m-apple-darwin");
1139 case MachO::CPU_SUBTYPE_ARM_V7S:
1140 return Triple("armv7s-apple-darwin");
1144 case MachO::CPU_TYPE_ARM64:
1145 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1146 case MachO::CPU_SUBTYPE_ARM64_ALL:
1147 return Triple("arm64-apple-darwin");
1151 case MachO::CPU_TYPE_POWERPC:
1152 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1153 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1154 return Triple("ppc-apple-darwin");
1158 case MachO::CPU_TYPE_POWERPC64:
1159 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1160 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1161 return Triple("ppc64-apple-darwin");
1170 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1171 const char **McpuDefault) {
1173 *McpuDefault = nullptr;
1176 case MachO::CPU_TYPE_ARM:
1177 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1178 case MachO::CPU_SUBTYPE_ARM_V4T:
1179 return Triple("thumbv4t-apple-darwin");
1180 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1181 return Triple("thumbv5e-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1183 return Triple("xscale-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V6:
1185 return Triple("thumbv6-apple-darwin");
1186 case MachO::CPU_SUBTYPE_ARM_V6M:
1188 *McpuDefault = "cortex-m0";
1189 return Triple("thumbv6m-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V7:
1191 return Triple("thumbv7-apple-darwin");
1192 case MachO::CPU_SUBTYPE_ARM_V7EM:
1194 *McpuDefault = "cortex-m4";
1195 return Triple("thumbv7em-apple-darwin");
1196 case MachO::CPU_SUBTYPE_ARM_V7K:
1197 return Triple("thumbv7k-apple-darwin");
1198 case MachO::CPU_SUBTYPE_ARM_V7M:
1200 *McpuDefault = "cortex-m3";
1201 return Triple("thumbv7m-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V7S:
1203 return Triple("thumbv7s-apple-darwin");
1212 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1213 const char **McpuDefault,
1214 Triple *ThumbTriple) {
1215 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1216 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1221 Triple MachOObjectFile::getHostArch() {
1222 return Triple(sys::getDefaultTargetTriple());
1225 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1226 return StringSwitch<bool>(ArchFlag)
1228 .Case("x86_64", true)
1229 .Case("x86_64h", true)
1230 .Case("armv4t", true)
1232 .Case("armv5e", true)
1233 .Case("armv6", true)
1234 .Case("armv6m", true)
1235 .Case("armv7", true)
1236 .Case("armv7em", true)
1237 .Case("armv7k", true)
1238 .Case("armv7m", true)
1239 .Case("armv7s", true)
1240 .Case("arm64", true)
1242 .Case("ppc64", true)
1246 unsigned MachOObjectFile::getArch() const {
1247 return getArch(getCPUType(this));
1250 Triple MachOObjectFile::getArch(const char **McpuDefault,
1251 Triple *ThumbTriple) const {
1252 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1253 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1256 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1259 return section_rel_begin(DRI);
1262 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1265 return section_rel_end(DRI);
1268 dice_iterator MachOObjectFile::begin_dices() const {
1270 if (!DataInCodeLoadCmd)
1271 return dice_iterator(DiceRef(DRI, this));
1273 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1274 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1275 return dice_iterator(DiceRef(DRI, this));
1278 dice_iterator MachOObjectFile::end_dices() const {
1280 if (!DataInCodeLoadCmd)
1281 return dice_iterator(DiceRef(DRI, this));
1283 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1284 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1285 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1286 return dice_iterator(DiceRef(DRI, this));
1289 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1290 : Trie(T), Malformed(false), Done(false) { }
1292 void ExportEntry::moveToFirst() {
1294 pushDownUntilBottom();
1297 void ExportEntry::moveToEnd() {
1302 bool ExportEntry::operator==(const ExportEntry &Other) const {
1303 // Common case, one at end, other iterating from begin.
1304 if (Done || Other.Done)
1305 return (Done == Other.Done);
1306 // Not equal if different stack sizes.
1307 if (Stack.size() != Other.Stack.size())
1309 // Not equal if different cumulative strings.
1310 if (!CumulativeString.equals(Other.CumulativeString))
1312 // Equal if all nodes in both stacks match.
1313 for (unsigned i=0; i < Stack.size(); ++i) {
1314 if (Stack[i].Start != Other.Stack[i].Start)
1320 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1322 uint64_t Result = decodeULEB128(Ptr, &Count);
1324 if (Ptr > Trie.end()) {
1331 StringRef ExportEntry::name() const {
1332 return CumulativeString;
1335 uint64_t ExportEntry::flags() const {
1336 return Stack.back().Flags;
1339 uint64_t ExportEntry::address() const {
1340 return Stack.back().Address;
1343 uint64_t ExportEntry::other() const {
1344 return Stack.back().Other;
1347 StringRef ExportEntry::otherName() const {
1348 const char* ImportName = Stack.back().ImportName;
1350 return StringRef(ImportName);
1354 uint32_t ExportEntry::nodeOffset() const {
1355 return Stack.back().Start - Trie.begin();
1358 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1359 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1360 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1361 ParentStringLength(0), IsExportNode(false) {
1364 void ExportEntry::pushNode(uint64_t offset) {
1365 const uint8_t *Ptr = Trie.begin() + offset;
1366 NodeState State(Ptr);
1367 uint64_t ExportInfoSize = readULEB128(State.Current);
1368 State.IsExportNode = (ExportInfoSize != 0);
1369 const uint8_t* Children = State.Current + ExportInfoSize;
1370 if (State.IsExportNode) {
1371 State.Flags = readULEB128(State.Current);
1372 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1374 State.Other = readULEB128(State.Current); // dylib ordinal
1375 State.ImportName = reinterpret_cast<const char*>(State.Current);
1377 State.Address = readULEB128(State.Current);
1378 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1379 State.Other = readULEB128(State.Current);
1382 State.ChildCount = *Children;
1383 State.Current = Children + 1;
1384 State.NextChildIndex = 0;
1385 State.ParentStringLength = CumulativeString.size();
1386 Stack.push_back(State);
1389 void ExportEntry::pushDownUntilBottom() {
1390 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1391 NodeState &Top = Stack.back();
1392 CumulativeString.resize(Top.ParentStringLength);
1393 for (;*Top.Current != 0; Top.Current++) {
1394 char C = *Top.Current;
1395 CumulativeString.push_back(C);
1398 uint64_t childNodeIndex = readULEB128(Top.Current);
1399 Top.NextChildIndex += 1;
1400 pushNode(childNodeIndex);
1402 if (!Stack.back().IsExportNode) {
1408 // We have a trie data structure and need a way to walk it that is compatible
1409 // with the C++ iterator model. The solution is a non-recursive depth first
1410 // traversal where the iterator contains a stack of parent nodes along with a
1411 // string that is the accumulation of all edge strings along the parent chain
1414 // There is one "export" node for each exported symbol. But because some
1415 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1416 // node may have child nodes too.
1418 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1419 // child until hitting a node with no children (which is an export node or
1420 // else the trie is malformed). On the way down, each node is pushed on the
1421 // stack ivar. If there is no more ways down, it pops up one and tries to go
1422 // down a sibling path until a childless node is reached.
1423 void ExportEntry::moveNext() {
1424 if (Stack.empty() || !Stack.back().IsExportNode) {
1431 while (!Stack.empty()) {
1432 NodeState &Top = Stack.back();
1433 if (Top.NextChildIndex < Top.ChildCount) {
1434 pushDownUntilBottom();
1435 // Now at the next export node.
1438 if (Top.IsExportNode) {
1439 // This node has no children but is itself an export node.
1440 CumulativeString.resize(Top.ParentStringLength);
1449 iterator_range<export_iterator>
1450 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1451 ExportEntry Start(Trie);
1452 if (Trie.size() == 0)
1455 Start.moveToFirst();
1457 ExportEntry Finish(Trie);
1460 return iterator_range<export_iterator>(export_iterator(Start),
1461 export_iterator(Finish));
1464 iterator_range<export_iterator> MachOObjectFile::exports() const {
1465 return exports(getDyldInfoExportsTrie());
1469 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1470 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1471 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1472 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1474 void MachORebaseEntry::moveToFirst() {
1475 Ptr = Opcodes.begin();
1479 void MachORebaseEntry::moveToEnd() {
1480 Ptr = Opcodes.end();
1481 RemainingLoopCount = 0;
1485 void MachORebaseEntry::moveNext() {
1486 // If in the middle of some loop, move to next rebasing in loop.
1487 SegmentOffset += AdvanceAmount;
1488 if (RemainingLoopCount) {
1489 --RemainingLoopCount;
1492 if (Ptr == Opcodes.end()) {
1497 while (More && !Malformed) {
1498 // Parse next opcode and set up next loop.
1499 uint8_t Byte = *Ptr++;
1500 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1501 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1503 case MachO::REBASE_OPCODE_DONE:
1507 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1509 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1510 RebaseType = ImmValue;
1513 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1514 << "RebaseType=" << (int) RebaseType << "\n");
1516 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1517 SegmentIndex = ImmValue;
1518 SegmentOffset = readULEB128();
1521 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1522 << "SegmentIndex=" << SegmentIndex << ", "
1523 << format("SegmentOffset=0x%06X", SegmentOffset)
1526 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1527 SegmentOffset += readULEB128();
1528 DEBUG_WITH_TYPE("mach-o-rebase",
1529 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1530 << format("SegmentOffset=0x%06X",
1531 SegmentOffset) << "\n");
1533 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1534 SegmentOffset += ImmValue * PointerSize;
1535 DEBUG_WITH_TYPE("mach-o-rebase",
1536 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1537 << format("SegmentOffset=0x%06X",
1538 SegmentOffset) << "\n");
1540 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1541 AdvanceAmount = PointerSize;
1542 RemainingLoopCount = ImmValue - 1;
1545 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1546 << format("SegmentOffset=0x%06X", SegmentOffset)
1547 << ", AdvanceAmount=" << AdvanceAmount
1548 << ", RemainingLoopCount=" << RemainingLoopCount
1551 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1552 AdvanceAmount = PointerSize;
1553 RemainingLoopCount = readULEB128() - 1;
1556 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1557 << format("SegmentOffset=0x%06X", SegmentOffset)
1558 << ", AdvanceAmount=" << AdvanceAmount
1559 << ", RemainingLoopCount=" << RemainingLoopCount
1562 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1563 AdvanceAmount = readULEB128() + PointerSize;
1564 RemainingLoopCount = 0;
1567 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1568 << format("SegmentOffset=0x%06X", SegmentOffset)
1569 << ", AdvanceAmount=" << AdvanceAmount
1570 << ", RemainingLoopCount=" << RemainingLoopCount
1573 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1574 RemainingLoopCount = readULEB128() - 1;
1575 AdvanceAmount = readULEB128() + PointerSize;
1578 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1579 << format("SegmentOffset=0x%06X", SegmentOffset)
1580 << ", AdvanceAmount=" << AdvanceAmount
1581 << ", RemainingLoopCount=" << RemainingLoopCount
1590 uint64_t MachORebaseEntry::readULEB128() {
1592 uint64_t Result = decodeULEB128(Ptr, &Count);
1594 if (Ptr > Opcodes.end()) {
1595 Ptr = Opcodes.end();
1601 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1603 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1605 StringRef MachORebaseEntry::typeName() const {
1606 switch (RebaseType) {
1607 case MachO::REBASE_TYPE_POINTER:
1609 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1610 return "text abs32";
1611 case MachO::REBASE_TYPE_TEXT_PCREL32:
1612 return "text rel32";
1617 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1618 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1619 return (Ptr == Other.Ptr) &&
1620 (RemainingLoopCount == Other.RemainingLoopCount) &&
1621 (Done == Other.Done);
1624 iterator_range<rebase_iterator>
1625 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1626 MachORebaseEntry Start(Opcodes, is64);
1627 Start.moveToFirst();
1629 MachORebaseEntry Finish(Opcodes, is64);
1632 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1633 rebase_iterator(Finish));
1636 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1637 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1641 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1643 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1644 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1645 BindType(0), PointerSize(is64Bit ? 8 : 4),
1646 TableKind(BK), Malformed(false), Done(false) {}
1648 void MachOBindEntry::moveToFirst() {
1649 Ptr = Opcodes.begin();
1653 void MachOBindEntry::moveToEnd() {
1654 Ptr = Opcodes.end();
1655 RemainingLoopCount = 0;
1659 void MachOBindEntry::moveNext() {
1660 // If in the middle of some loop, move to next binding in loop.
1661 SegmentOffset += AdvanceAmount;
1662 if (RemainingLoopCount) {
1663 --RemainingLoopCount;
1666 if (Ptr == Opcodes.end()) {
1671 while (More && !Malformed) {
1672 // Parse next opcode and set up next loop.
1673 uint8_t Byte = *Ptr++;
1674 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1675 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1676 int8_t SignExtended;
1677 const uint8_t *SymStart;
1679 case MachO::BIND_OPCODE_DONE:
1680 if (TableKind == Kind::Lazy) {
1681 // Lazying bindings have a DONE opcode between entries. Need to ignore
1682 // it to advance to next entry. But need not if this is last entry.
1683 bool NotLastEntry = false;
1684 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1686 NotLastEntry = true;
1695 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1697 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1701 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1702 << "Ordinal=" << Ordinal << "\n");
1704 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1705 Ordinal = readULEB128();
1708 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1709 << "Ordinal=" << Ordinal << "\n");
1711 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1713 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1714 Ordinal = SignExtended;
1719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1720 << "Ordinal=" << Ordinal << "\n");
1722 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1728 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1733 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1734 << "SymbolName=" << SymbolName << "\n");
1735 if (TableKind == Kind::Weak) {
1736 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1740 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1741 BindType = ImmValue;
1744 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1745 << "BindType=" << (int)BindType << "\n");
1747 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1748 Addend = readSLEB128();
1749 if (TableKind == Kind::Lazy)
1753 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1754 << "Addend=" << Addend << "\n");
1756 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1757 SegmentIndex = ImmValue;
1758 SegmentOffset = readULEB128();
1761 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1762 << "SegmentIndex=" << SegmentIndex << ", "
1763 << format("SegmentOffset=0x%06X", SegmentOffset)
1766 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1767 SegmentOffset += readULEB128();
1768 DEBUG_WITH_TYPE("mach-o-bind",
1769 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1770 << format("SegmentOffset=0x%06X",
1771 SegmentOffset) << "\n");
1773 case MachO::BIND_OPCODE_DO_BIND:
1774 AdvanceAmount = PointerSize;
1775 RemainingLoopCount = 0;
1776 DEBUG_WITH_TYPE("mach-o-bind",
1777 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1778 << format("SegmentOffset=0x%06X",
1779 SegmentOffset) << "\n");
1781 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1782 AdvanceAmount = readULEB128() + PointerSize;
1783 RemainingLoopCount = 0;
1784 if (TableKind == Kind::Lazy)
1788 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1789 << format("SegmentOffset=0x%06X", SegmentOffset)
1790 << ", AdvanceAmount=" << AdvanceAmount
1791 << ", RemainingLoopCount=" << RemainingLoopCount
1794 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1795 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1796 RemainingLoopCount = 0;
1797 if (TableKind == Kind::Lazy)
1799 DEBUG_WITH_TYPE("mach-o-bind",
1801 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1802 << format("SegmentOffset=0x%06X",
1803 SegmentOffset) << "\n");
1805 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1806 RemainingLoopCount = readULEB128() - 1;
1807 AdvanceAmount = readULEB128() + PointerSize;
1808 if (TableKind == Kind::Lazy)
1812 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1813 << format("SegmentOffset=0x%06X", SegmentOffset)
1814 << ", AdvanceAmount=" << AdvanceAmount
1815 << ", RemainingLoopCount=" << RemainingLoopCount
1824 uint64_t MachOBindEntry::readULEB128() {
1826 uint64_t Result = decodeULEB128(Ptr, &Count);
1828 if (Ptr > Opcodes.end()) {
1829 Ptr = Opcodes.end();
1835 int64_t MachOBindEntry::readSLEB128() {
1837 int64_t Result = decodeSLEB128(Ptr, &Count);
1839 if (Ptr > Opcodes.end()) {
1840 Ptr = Opcodes.end();
1847 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1849 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1851 StringRef MachOBindEntry::typeName() const {
1853 case MachO::BIND_TYPE_POINTER:
1855 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1856 return "text abs32";
1857 case MachO::BIND_TYPE_TEXT_PCREL32:
1858 return "text rel32";
1863 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1865 int64_t MachOBindEntry::addend() const { return Addend; }
1867 uint32_t MachOBindEntry::flags() const { return Flags; }
1869 int MachOBindEntry::ordinal() const { return Ordinal; }
1871 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1872 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1873 return (Ptr == Other.Ptr) &&
1874 (RemainingLoopCount == Other.RemainingLoopCount) &&
1875 (Done == Other.Done);
1878 iterator_range<bind_iterator>
1879 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1880 MachOBindEntry::Kind BKind) {
1881 MachOBindEntry Start(Opcodes, is64, BKind);
1882 Start.moveToFirst();
1884 MachOBindEntry Finish(Opcodes, is64, BKind);
1887 return iterator_range<bind_iterator>(bind_iterator(Start),
1888 bind_iterator(Finish));
1891 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1892 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1893 MachOBindEntry::Kind::Regular);
1896 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1897 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1898 MachOBindEntry::Kind::Lazy);
1901 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1902 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1903 MachOBindEntry::Kind::Weak);
1906 MachOObjectFile::load_command_iterator
1907 MachOObjectFile::begin_load_commands() const {
1908 return LoadCommands.begin();
1911 MachOObjectFile::load_command_iterator
1912 MachOObjectFile::end_load_commands() const {
1913 return LoadCommands.end();
1916 iterator_range<MachOObjectFile::load_command_iterator>
1917 MachOObjectFile::load_commands() const {
1918 return iterator_range<load_command_iterator>(begin_load_commands(),
1919 end_load_commands());
1923 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1924 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1925 return parseSegmentOrSectionName(Raw.data());
1929 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1930 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1931 const section_base *Base =
1932 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1933 return makeArrayRef(Base->sectname);
1937 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1938 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1939 const section_base *Base =
1940 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1941 return makeArrayRef(Base->segname);
1945 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1947 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1949 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1952 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1953 const MachO::any_relocation_info &RE) const {
1954 if (isLittleEndian())
1955 return RE.r_word1 & 0xffffff;
1956 return RE.r_word1 >> 8;
1959 bool MachOObjectFile::getPlainRelocationExternal(
1960 const MachO::any_relocation_info &RE) const {
1961 if (isLittleEndian())
1962 return (RE.r_word1 >> 27) & 1;
1963 return (RE.r_word1 >> 4) & 1;
1966 bool MachOObjectFile::getScatteredRelocationScattered(
1967 const MachO::any_relocation_info &RE) const {
1968 return RE.r_word0 >> 31;
1971 uint32_t MachOObjectFile::getScatteredRelocationValue(
1972 const MachO::any_relocation_info &RE) const {
1976 uint32_t MachOObjectFile::getScatteredRelocationType(
1977 const MachO::any_relocation_info &RE) const {
1978 return (RE.r_word0 >> 24) & 0xf;
1981 unsigned MachOObjectFile::getAnyRelocationAddress(
1982 const MachO::any_relocation_info &RE) const {
1983 if (isRelocationScattered(RE))
1984 return getScatteredRelocationAddress(RE);
1985 return getPlainRelocationAddress(RE);
1988 unsigned MachOObjectFile::getAnyRelocationPCRel(
1989 const MachO::any_relocation_info &RE) const {
1990 if (isRelocationScattered(RE))
1991 return getScatteredRelocationPCRel(this, RE);
1992 return getPlainRelocationPCRel(this, RE);
1995 unsigned MachOObjectFile::getAnyRelocationLength(
1996 const MachO::any_relocation_info &RE) const {
1997 if (isRelocationScattered(RE))
1998 return getScatteredRelocationLength(RE);
1999 return getPlainRelocationLength(this, RE);
2003 MachOObjectFile::getAnyRelocationType(
2004 const MachO::any_relocation_info &RE) const {
2005 if (isRelocationScattered(RE))
2006 return getScatteredRelocationType(RE);
2007 return getPlainRelocationType(this, RE);
2011 MachOObjectFile::getAnyRelocationSection(
2012 const MachO::any_relocation_info &RE) const {
2013 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2014 return *section_end();
2015 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2016 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2017 return *section_end();
2019 DRI.d.a = SecNum - 1;
2020 return SectionRef(DRI, this);
2023 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2024 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2025 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2028 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2029 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2030 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2033 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2034 unsigned Index) const {
2035 const char *Sec = getSectionPtr(this, L, Index);
2036 return getStruct<MachO::section>(this, Sec);
2039 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2040 unsigned Index) const {
2041 const char *Sec = getSectionPtr(this, L, Index);
2042 return getStruct<MachO::section_64>(this, Sec);
2046 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2047 const char *P = reinterpret_cast<const char *>(DRI.p);
2048 return getStruct<MachO::nlist>(this, P);
2052 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2053 const char *P = reinterpret_cast<const char *>(DRI.p);
2054 return getStruct<MachO::nlist_64>(this, P);
2057 MachO::linkedit_data_command
2058 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2059 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2062 MachO::segment_command
2063 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2064 return getStruct<MachO::segment_command>(this, L.Ptr);
2067 MachO::segment_command_64
2068 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2069 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2072 MachO::linker_option_command
2073 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2074 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2077 MachO::version_min_command
2078 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2079 return getStruct<MachO::version_min_command>(this, L.Ptr);
2082 MachO::dylib_command
2083 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2084 return getStruct<MachO::dylib_command>(this, L.Ptr);
2087 MachO::dyld_info_command
2088 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2092 MachO::dylinker_command
2093 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2098 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2099 return getStruct<MachO::uuid_command>(this, L.Ptr);
2102 MachO::rpath_command
2103 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2104 return getStruct<MachO::rpath_command>(this, L.Ptr);
2107 MachO::source_version_command
2108 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::source_version_command>(this, L.Ptr);
2112 MachO::entry_point_command
2113 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2117 MachO::encryption_info_command
2118 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2122 MachO::encryption_info_command_64
2123 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2127 MachO::sub_framework_command
2128 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2129 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2132 MachO::sub_umbrella_command
2133 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2134 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2137 MachO::sub_library_command
2138 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2139 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2142 MachO::sub_client_command
2143 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2144 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2147 MachO::routines_command
2148 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2149 return getStruct<MachO::routines_command>(this, L.Ptr);
2152 MachO::routines_command_64
2153 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2154 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2157 MachO::thread_command
2158 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2159 return getStruct<MachO::thread_command>(this, L.Ptr);
2162 MachO::any_relocation_info
2163 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2168 MachO::section_64 Sect = getSection64(Sec);
2169 Offset = Sect.reloff;
2171 MachO::section Sect = getSection(Sec);
2172 Offset = Sect.reloff;
2175 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2176 getPtr(this, Offset)) + Rel.d.b;
2177 return getStruct<MachO::any_relocation_info>(
2178 this, reinterpret_cast<const char *>(P));
2181 MachO::data_in_code_entry
2182 MachOObjectFile::getDice(DataRefImpl Rel) const {
2183 const char *P = reinterpret_cast<const char *>(Rel.p);
2184 return getStruct<MachO::data_in_code_entry>(this, P);
2187 const MachO::mach_header &MachOObjectFile::getHeader() const {
2191 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2196 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2197 const MachO::dysymtab_command &DLC,
2198 unsigned Index) const {
2199 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2200 return getStruct<uint32_t>(this, getPtr(this, Offset));
2203 MachO::data_in_code_entry
2204 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2205 unsigned Index) const {
2206 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2207 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2210 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2212 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2214 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2215 MachO::symtab_command Cmd;
2216 Cmd.cmd = MachO::LC_SYMTAB;
2217 Cmd.cmdsize = sizeof(MachO::symtab_command);
2225 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2226 if (DysymtabLoadCmd)
2227 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2229 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2230 MachO::dysymtab_command Cmd;
2231 Cmd.cmd = MachO::LC_DYSYMTAB;
2232 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2243 Cmd.extrefsymoff = 0;
2244 Cmd.nextrefsyms = 0;
2245 Cmd.indirectsymoff = 0;
2246 Cmd.nindirectsyms = 0;
2254 MachO::linkedit_data_command
2255 MachOObjectFile::getDataInCodeLoadCommand() const {
2256 if (DataInCodeLoadCmd)
2257 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2259 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2260 MachO::linkedit_data_command Cmd;
2261 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2262 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2268 MachO::linkedit_data_command
2269 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2270 if (LinkOptHintsLoadCmd)
2271 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2273 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2275 MachO::linkedit_data_command Cmd;
2276 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2277 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2283 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2284 if (!DyldInfoLoadCmd)
2285 return ArrayRef<uint8_t>();
2287 MachO::dyld_info_command DyldInfo
2288 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2289 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2290 getPtr(this, DyldInfo.rebase_off));
2291 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2294 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2295 if (!DyldInfoLoadCmd)
2296 return ArrayRef<uint8_t>();
2298 MachO::dyld_info_command DyldInfo
2299 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2300 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2301 getPtr(this, DyldInfo.bind_off));
2302 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2305 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2306 if (!DyldInfoLoadCmd)
2307 return ArrayRef<uint8_t>();
2309 MachO::dyld_info_command DyldInfo
2310 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2311 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2312 getPtr(this, DyldInfo.weak_bind_off));
2313 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2316 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2317 if (!DyldInfoLoadCmd)
2318 return ArrayRef<uint8_t>();
2320 MachO::dyld_info_command DyldInfo
2321 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2322 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2323 getPtr(this, DyldInfo.lazy_bind_off));
2324 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2327 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2328 if (!DyldInfoLoadCmd)
2329 return ArrayRef<uint8_t>();
2331 MachO::dyld_info_command DyldInfo
2332 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2333 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2334 getPtr(this, DyldInfo.export_off));
2335 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2338 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2340 return ArrayRef<uint8_t>();
2341 // Returning a pointer is fine as uuid doesn't need endian swapping.
2342 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2343 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2346 StringRef MachOObjectFile::getStringTableData() const {
2347 MachO::symtab_command S = getSymtabLoadCommand();
2348 return getData().substr(S.stroff, S.strsize);
2351 bool MachOObjectFile::is64Bit() const {
2352 return getType() == getMachOType(false, true) ||
2353 getType() == getMachOType(true, true);
2356 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2357 SmallVectorImpl<uint64_t> &Out) const {
2358 DataExtractor extractor(ObjectFile::getData(), true, 0);
2360 uint32_t offset = Index;
2362 while (uint64_t delta = extractor.getULEB128(&offset)) {
2364 Out.push_back(data);
2368 bool MachOObjectFile::isRelocatableObject() const {
2369 return getHeader().filetype == MachO::MH_OBJECT;
2372 ErrorOr<std::unique_ptr<MachOObjectFile>>
2373 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2374 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2376 std::unique_ptr<MachOObjectFile> Ret;
2377 if (Magic == "\xFE\xED\xFA\xCE")
2378 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2379 else if (Magic == "\xCE\xFA\xED\xFE")
2380 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2381 else if (Magic == "\xFE\xED\xFA\xCF")
2382 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2383 else if (Magic == "\xCF\xFA\xED\xFE")
2384 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2386 return object_error::parse_failed;
2390 return std::move(Ret);