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 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
350 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
351 return Entry.n_value;
353 MachO::nlist Entry = getSymbolTableEntry(Sym);
354 return Entry.n_value;
357 // getIndirectName() returns the name of the alias'ed symbol who's string table
358 // index is in the n_value field.
359 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
360 StringRef &Res) const {
361 StringRef StringTable = getStringTableData();
362 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
363 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
364 return object_error::parse_failed;
365 uint64_t NValue = getNValue(Symb);
366 if (NValue >= StringTable.size())
367 return object_error::parse_failed;
368 const char *Start = &StringTable.data()[NValue];
369 Res = StringRef(Start);
370 return std::error_code();
373 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
374 uint64_t NValue = getNValue(Sym);
375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
377 return UnknownAddress;
381 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
382 uint64_t &Res) const {
383 Res = getSymbolValue(Sym);
384 return std::error_code();
387 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
388 uint32_t flags = getSymbolFlags(DRI);
389 if (flags & SymbolRef::SF_Common) {
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
391 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
396 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
398 getSymbolAddress(DRI, Value);
402 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
403 SymbolRef::Type &Res) const {
404 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
405 uint8_t n_type = Entry.n_type;
407 Res = SymbolRef::ST_Other;
409 // If this is a STAB debugging symbol, we can do nothing more.
410 if (n_type & MachO::N_STAB) {
411 Res = SymbolRef::ST_Debug;
412 return std::error_code();
415 switch (n_type & MachO::N_TYPE) {
417 Res = SymbolRef::ST_Unknown;
420 Res = SymbolRef::ST_Function;
423 return std::error_code();
426 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
427 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
429 uint8_t MachOType = Entry.n_type;
430 uint16_t MachOFlags = Entry.n_desc;
432 uint32_t Result = SymbolRef::SF_None;
434 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
435 Result |= SymbolRef::SF_Undefined;
437 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
438 Result |= SymbolRef::SF_Indirect;
440 if (MachOType & MachO::N_STAB)
441 Result |= SymbolRef::SF_FormatSpecific;
443 if (MachOType & MachO::N_EXT) {
444 Result |= SymbolRef::SF_Global;
445 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
447 getSymbolAddress(DRI, Value);
448 if (Value && Value != UnknownAddress)
449 Result |= SymbolRef::SF_Common;
452 if (!(MachOType & MachO::N_PEXT))
453 Result |= SymbolRef::SF_Exported;
456 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
457 Result |= SymbolRef::SF_Weak;
459 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
460 Result |= SymbolRef::SF_Thumb;
462 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
463 Result |= SymbolRef::SF_Absolute;
468 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
469 section_iterator &Res) const {
470 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
471 uint8_t index = Entry.n_sect;
478 if (DRI.d.a >= Sections.size())
479 report_fatal_error("getSymbolSection: Invalid section index.");
480 Res = section_iterator(SectionRef(DRI, this));
483 return std::error_code();
486 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
487 MachO::nlist_base Entry =
488 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
489 return Entry.n_sect - 1;
492 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
496 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
497 StringRef &Result) const {
498 ArrayRef<char> Raw = getSectionRawName(Sec);
499 Result = parseSegmentOrSectionName(Raw.data());
500 return std::error_code();
503 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
505 return getSection64(Sec).addr;
506 return getSection(Sec).addr;
509 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
511 return getSection64(Sec).size;
512 return getSection(Sec).size;
515 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
516 StringRef &Res) const {
521 MachO::section_64 Sect = getSection64(Sec);
522 Offset = Sect.offset;
525 MachO::section Sect = getSection(Sec);
526 Offset = Sect.offset;
530 Res = this->getData().substr(Offset, Size);
531 return std::error_code();
534 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
537 MachO::section_64 Sect = getSection64(Sec);
540 MachO::section Sect = getSection(Sec);
544 return uint64_t(1) << Align;
547 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
548 uint32_t Flags = getSectionFlags(this, Sec);
549 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
552 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
553 uint32_t Flags = getSectionFlags(this, Sec);
554 unsigned SectionType = Flags & MachO::SECTION_TYPE;
555 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
556 !(SectionType == MachO::S_ZEROFILL ||
557 SectionType == MachO::S_GB_ZEROFILL);
560 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
561 uint32_t Flags = getSectionFlags(this, Sec);
562 unsigned SectionType = Flags & MachO::SECTION_TYPE;
563 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
564 (SectionType == MachO::S_ZEROFILL ||
565 SectionType == MachO::S_GB_ZEROFILL);
568 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
569 return Sec.getRawDataRefImpl().d.a;
572 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
573 // FIXME: Unimplemented.
577 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
578 DataRefImpl Symb) const {
580 this->getSymbolType(Symb, ST);
581 if (ST == SymbolRef::ST_Unknown)
584 uint64_t SectBegin = getSectionAddress(Sec);
585 uint64_t SectEnd = getSectionSize(Sec);
586 SectEnd += SectBegin;
589 getSymbolAddress(Symb, SymAddr);
590 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
593 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
597 return relocation_iterator(RelocationRef(Ret, this));
601 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
604 MachO::section_64 Sect = getSection64(Sec);
607 MachO::section Sect = getSection(Sec);
614 return relocation_iterator(RelocationRef(Ret, this));
617 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
621 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
622 uint64_t &Res) const {
624 getRelocationOffset(Rel, Offset);
628 uint64_t SecAddress = getSectionAddress(Sec);
629 Res = SecAddress + Offset;
630 return std::error_code();
633 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
634 uint64_t &Res) const {
635 assert(getHeader().filetype == MachO::MH_OBJECT &&
636 "Only implemented for MH_OBJECT");
637 MachO::any_relocation_info RE = getRelocation(Rel);
638 Res = getAnyRelocationAddress(RE);
639 return std::error_code();
643 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
644 MachO::any_relocation_info RE = getRelocation(Rel);
645 if (isRelocationScattered(RE))
648 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
649 bool isExtern = getPlainRelocationExternal(RE);
653 MachO::symtab_command S = getSymtabLoadCommand();
654 unsigned SymbolTableEntrySize = is64Bit() ?
655 sizeof(MachO::nlist_64) :
656 sizeof(MachO::nlist);
657 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
659 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
660 return symbol_iterator(SymbolRef(Sym, this));
664 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
665 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
668 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
669 uint64_t &Res) const {
670 MachO::any_relocation_info RE = getRelocation(Rel);
671 Res = getAnyRelocationType(RE);
672 return std::error_code();
676 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
677 SmallVectorImpl<char> &Result) const {
680 getRelocationType(Rel, RType);
682 unsigned Arch = this->getArch();
686 static const char *const Table[] = {
687 "GENERIC_RELOC_VANILLA",
688 "GENERIC_RELOC_PAIR",
689 "GENERIC_RELOC_SECTDIFF",
690 "GENERIC_RELOC_PB_LA_PTR",
691 "GENERIC_RELOC_LOCAL_SECTDIFF",
692 "GENERIC_RELOC_TLV" };
700 case Triple::x86_64: {
701 static const char *const Table[] = {
702 "X86_64_RELOC_UNSIGNED",
703 "X86_64_RELOC_SIGNED",
704 "X86_64_RELOC_BRANCH",
705 "X86_64_RELOC_GOT_LOAD",
707 "X86_64_RELOC_SUBTRACTOR",
708 "X86_64_RELOC_SIGNED_1",
709 "X86_64_RELOC_SIGNED_2",
710 "X86_64_RELOC_SIGNED_4",
711 "X86_64_RELOC_TLV" };
720 static const char *const Table[] = {
723 "ARM_RELOC_SECTDIFF",
724 "ARM_RELOC_LOCAL_SECTDIFF",
725 "ARM_RELOC_PB_LA_PTR",
727 "ARM_THUMB_RELOC_BR22",
728 "ARM_THUMB_32BIT_BRANCH",
730 "ARM_RELOC_HALF_SECTDIFF" };
738 case Triple::aarch64: {
739 static const char *const Table[] = {
740 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
741 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
742 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
743 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
744 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
748 if (RType >= array_lengthof(Table))
755 static const char *const Table[] = {
764 "PPC_RELOC_SECTDIFF",
765 "PPC_RELOC_PB_LA_PTR",
766 "PPC_RELOC_HI16_SECTDIFF",
767 "PPC_RELOC_LO16_SECTDIFF",
768 "PPC_RELOC_HA16_SECTDIFF",
770 "PPC_RELOC_LO14_SECTDIFF",
771 "PPC_RELOC_LOCAL_SECTDIFF" };
779 case Triple::UnknownArch:
783 Result.append(res.begin(), res.end());
784 return std::error_code();
787 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
788 bool &Result) const {
789 unsigned Arch = getArch();
791 getRelocationType(Rel, Type);
795 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
797 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
798 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
799 } else if (Arch == Triple::x86_64) {
800 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
801 // an X86_64_RELOC_SUBTRACTOR.
802 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
803 DataRefImpl RelPrev = Rel;
806 getRelocationType(RelPrev, PrevType);
807 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
812 return std::error_code();
815 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
816 MachO::any_relocation_info RE = getRelocation(Rel);
817 return getAnyRelocationLength(RE);
821 // guessLibraryShortName() is passed a name of a dynamic library and returns a
822 // guess on what the short name is. Then name is returned as a substring of the
823 // StringRef Name passed in. The name of the dynamic library is recognized as
824 // a framework if it has one of the two following forms:
825 // Foo.framework/Versions/A/Foo
827 // Where A and Foo can be any string. And may contain a trailing suffix
828 // starting with an underbar. If the Name is recognized as a framework then
829 // isFramework is set to true else it is set to false. If the Name has a
830 // suffix then Suffix is set to the substring in Name that contains the suffix
831 // else it is set to a NULL StringRef.
833 // The Name of the dynamic library is recognized as a library name if it has
834 // one of the two following forms:
837 // The library may have a suffix trailing the name Foo of the form:
838 // libFoo_profile.A.dylib
839 // libFoo_profile.dylib
841 // The Name of the dynamic library is also recognized as a library name if it
842 // has the following form:
845 // If the Name of the dynamic library is none of the forms above then a NULL
846 // StringRef is returned.
848 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
851 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
852 size_t a, b, c, d, Idx;
855 Suffix = StringRef();
857 // Pull off the last component and make Foo point to it
859 if (a == Name.npos || a == 0)
861 Foo = Name.slice(a+1, Name.npos);
863 // Look for a suffix starting with a '_'
864 Idx = Foo.rfind('_');
865 if (Idx != Foo.npos && Foo.size() >= 2) {
866 Suffix = Foo.slice(Idx, Foo.npos);
867 Foo = Foo.slice(0, Idx);
870 // First look for the form Foo.framework/Foo
871 b = Name.rfind('/', a);
876 F = Name.slice(Idx, Idx + Foo.size());
877 DotFramework = Name.slice(Idx + Foo.size(),
878 Idx + Foo.size() + sizeof(".framework/")-1);
879 if (F == Foo && DotFramework == ".framework/") {
884 // Next look for the form Foo.framework/Versions/A/Foo
887 c = Name.rfind('/', b);
888 if (c == Name.npos || c == 0)
890 V = Name.slice(c+1, Name.npos);
891 if (!V.startswith("Versions/"))
893 d = Name.rfind('/', c);
898 F = Name.slice(Idx, Idx + Foo.size());
899 DotFramework = Name.slice(Idx + Foo.size(),
900 Idx + Foo.size() + sizeof(".framework/")-1);
901 if (F == Foo && DotFramework == ".framework/") {
907 // pull off the suffix after the "." and make a point to it
909 if (a == Name.npos || a == 0)
911 Dylib = Name.slice(a, Name.npos);
912 if (Dylib != ".dylib")
915 // First pull off the version letter for the form Foo.A.dylib if any.
917 Dot = Name.slice(a-2, a-1);
922 b = Name.rfind('/', a);
927 // ignore any suffix after an underbar like Foo_profile.A.dylib
928 Idx = Name.find('_', b);
929 if (Idx != Name.npos && Idx != b) {
930 Lib = Name.slice(b, Idx);
931 Suffix = Name.slice(Idx, a);
934 Lib = Name.slice(b, a);
935 // There are incorrect library names of the form:
936 // libATS.A_profile.dylib so check for these.
937 if (Lib.size() >= 3) {
938 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
940 Lib = Lib.slice(0, Lib.size()-2);
945 Qtx = Name.slice(a, Name.npos);
948 b = Name.rfind('/', a);
950 Lib = Name.slice(0, a);
952 Lib = Name.slice(b+1, a);
953 // There are library names of the form: QT.A.qtx so check for these.
954 if (Lib.size() >= 3) {
955 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
957 Lib = Lib.slice(0, Lib.size()-2);
962 // getLibraryShortNameByIndex() is used to get the short name of the library
963 // for an undefined symbol in a linked Mach-O binary that was linked with the
964 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
965 // It is passed the index (0 - based) of the library as translated from
966 // GET_LIBRARY_ORDINAL (1 - based).
967 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
968 StringRef &Res) const {
969 if (Index >= Libraries.size())
970 return object_error::parse_failed;
972 // If the cache of LibrariesShortNames is not built up do that first for
973 // all the Libraries.
974 if (LibrariesShortNames.size() == 0) {
975 for (unsigned i = 0; i < Libraries.size(); i++) {
976 MachO::dylib_command D =
977 getStruct<MachO::dylib_command>(this, Libraries[i]);
978 if (D.dylib.name >= D.cmdsize)
979 return object_error::parse_failed;
980 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
981 StringRef Name = StringRef(P);
982 if (D.dylib.name+Name.size() >= D.cmdsize)
983 return object_error::parse_failed;
986 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
987 if (shortName.empty())
988 LibrariesShortNames.push_back(Name);
990 LibrariesShortNames.push_back(shortName);
994 Res = LibrariesShortNames[Index];
995 return std::error_code();
998 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
999 return getSymbolByIndex(0);
1002 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1005 return basic_symbol_iterator(SymbolRef(DRI, this));
1007 MachO::symtab_command Symtab = getSymtabLoadCommand();
1008 unsigned SymbolTableEntrySize = is64Bit() ?
1009 sizeof(MachO::nlist_64) :
1010 sizeof(MachO::nlist);
1011 unsigned Offset = Symtab.symoff +
1012 Symtab.nsyms * SymbolTableEntrySize;
1013 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1014 return basic_symbol_iterator(SymbolRef(DRI, this));
1017 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1020 return basic_symbol_iterator(SymbolRef(DRI, this));
1022 MachO::symtab_command Symtab = getSymtabLoadCommand();
1023 if (Index >= Symtab.nsyms)
1024 report_fatal_error("Requested symbol index is out of range.");
1025 unsigned SymbolTableEntrySize =
1026 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1027 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1028 DRI.p += Index * SymbolTableEntrySize;
1029 return basic_symbol_iterator(SymbolRef(DRI, this));
1032 section_iterator MachOObjectFile::section_begin() const {
1034 return section_iterator(SectionRef(DRI, this));
1037 section_iterator MachOObjectFile::section_end() const {
1039 DRI.d.a = Sections.size();
1040 return section_iterator(SectionRef(DRI, this));
1043 uint8_t MachOObjectFile::getBytesInAddress() const {
1044 return is64Bit() ? 8 : 4;
1047 StringRef MachOObjectFile::getFileFormatName() const {
1048 unsigned CPUType = getCPUType(this);
1051 case llvm::MachO::CPU_TYPE_I386:
1052 return "Mach-O 32-bit i386";
1053 case llvm::MachO::CPU_TYPE_ARM:
1054 return "Mach-O arm";
1055 case llvm::MachO::CPU_TYPE_POWERPC:
1056 return "Mach-O 32-bit ppc";
1058 return "Mach-O 32-bit unknown";
1063 case llvm::MachO::CPU_TYPE_X86_64:
1064 return "Mach-O 64-bit x86-64";
1065 case llvm::MachO::CPU_TYPE_ARM64:
1066 return "Mach-O arm64";
1067 case llvm::MachO::CPU_TYPE_POWERPC64:
1068 return "Mach-O 64-bit ppc64";
1070 return "Mach-O 64-bit unknown";
1074 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1076 case llvm::MachO::CPU_TYPE_I386:
1078 case llvm::MachO::CPU_TYPE_X86_64:
1079 return Triple::x86_64;
1080 case llvm::MachO::CPU_TYPE_ARM:
1082 case llvm::MachO::CPU_TYPE_ARM64:
1083 return Triple::aarch64;
1084 case llvm::MachO::CPU_TYPE_POWERPC:
1086 case llvm::MachO::CPU_TYPE_POWERPC64:
1087 return Triple::ppc64;
1089 return Triple::UnknownArch;
1093 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1094 const char **McpuDefault) {
1096 *McpuDefault = nullptr;
1099 case MachO::CPU_TYPE_I386:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_I386_ALL:
1102 return Triple("i386-apple-darwin");
1106 case MachO::CPU_TYPE_X86_64:
1107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1108 case MachO::CPU_SUBTYPE_X86_64_ALL:
1109 return Triple("x86_64-apple-darwin");
1110 case MachO::CPU_SUBTYPE_X86_64_H:
1111 return Triple("x86_64h-apple-darwin");
1115 case MachO::CPU_TYPE_ARM:
1116 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1117 case MachO::CPU_SUBTYPE_ARM_V4T:
1118 return Triple("armv4t-apple-darwin");
1119 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1120 return Triple("armv5e-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1122 return Triple("xscale-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V6:
1124 return Triple("armv6-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V6M:
1127 *McpuDefault = "cortex-m0";
1128 return Triple("armv6m-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V7:
1130 return Triple("armv7-apple-darwin");
1131 case MachO::CPU_SUBTYPE_ARM_V7EM:
1133 *McpuDefault = "cortex-m4";
1134 return Triple("armv7em-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V7K:
1136 return Triple("armv7k-apple-darwin");
1137 case MachO::CPU_SUBTYPE_ARM_V7M:
1139 *McpuDefault = "cortex-m3";
1140 return Triple("armv7m-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_V7S:
1142 return Triple("armv7s-apple-darwin");
1146 case MachO::CPU_TYPE_ARM64:
1147 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1148 case MachO::CPU_SUBTYPE_ARM64_ALL:
1149 return Triple("arm64-apple-darwin");
1153 case MachO::CPU_TYPE_POWERPC:
1154 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1155 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1156 return Triple("ppc-apple-darwin");
1160 case MachO::CPU_TYPE_POWERPC64:
1161 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1162 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1163 return Triple("ppc64-apple-darwin");
1172 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1173 const char **McpuDefault) {
1175 *McpuDefault = nullptr;
1178 case MachO::CPU_TYPE_ARM:
1179 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1180 case MachO::CPU_SUBTYPE_ARM_V4T:
1181 return Triple("thumbv4t-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1183 return Triple("thumbv5e-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1185 return Triple("xscale-apple-darwin");
1186 case MachO::CPU_SUBTYPE_ARM_V6:
1187 return Triple("thumbv6-apple-darwin");
1188 case MachO::CPU_SUBTYPE_ARM_V6M:
1190 *McpuDefault = "cortex-m0";
1191 return Triple("thumbv6m-apple-darwin");
1192 case MachO::CPU_SUBTYPE_ARM_V7:
1193 return Triple("thumbv7-apple-darwin");
1194 case MachO::CPU_SUBTYPE_ARM_V7EM:
1196 *McpuDefault = "cortex-m4";
1197 return Triple("thumbv7em-apple-darwin");
1198 case MachO::CPU_SUBTYPE_ARM_V7K:
1199 return Triple("thumbv7k-apple-darwin");
1200 case MachO::CPU_SUBTYPE_ARM_V7M:
1202 *McpuDefault = "cortex-m3";
1203 return Triple("thumbv7m-apple-darwin");
1204 case MachO::CPU_SUBTYPE_ARM_V7S:
1205 return Triple("thumbv7s-apple-darwin");
1214 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1215 const char **McpuDefault,
1216 Triple *ThumbTriple) {
1217 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1218 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1223 Triple MachOObjectFile::getHostArch() {
1224 return Triple(sys::getDefaultTargetTriple());
1227 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1228 return StringSwitch<bool>(ArchFlag)
1230 .Case("x86_64", true)
1231 .Case("x86_64h", true)
1232 .Case("armv4t", true)
1234 .Case("armv5e", true)
1235 .Case("armv6", true)
1236 .Case("armv6m", true)
1237 .Case("armv7", true)
1238 .Case("armv7em", true)
1239 .Case("armv7k", true)
1240 .Case("armv7m", true)
1241 .Case("armv7s", true)
1242 .Case("arm64", true)
1244 .Case("ppc64", true)
1248 unsigned MachOObjectFile::getArch() const {
1249 return getArch(getCPUType(this));
1252 Triple MachOObjectFile::getArch(const char **McpuDefault,
1253 Triple *ThumbTriple) const {
1254 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1255 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1258 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1261 return section_rel_begin(DRI);
1264 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1267 return section_rel_end(DRI);
1270 dice_iterator MachOObjectFile::begin_dices() const {
1272 if (!DataInCodeLoadCmd)
1273 return dice_iterator(DiceRef(DRI, this));
1275 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1276 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1277 return dice_iterator(DiceRef(DRI, this));
1280 dice_iterator MachOObjectFile::end_dices() const {
1282 if (!DataInCodeLoadCmd)
1283 return dice_iterator(DiceRef(DRI, this));
1285 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1286 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1287 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1288 return dice_iterator(DiceRef(DRI, this));
1291 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1292 : Trie(T), Malformed(false), Done(false) { }
1294 void ExportEntry::moveToFirst() {
1296 pushDownUntilBottom();
1299 void ExportEntry::moveToEnd() {
1304 bool ExportEntry::operator==(const ExportEntry &Other) const {
1305 // Common case, one at end, other iterating from begin.
1306 if (Done || Other.Done)
1307 return (Done == Other.Done);
1308 // Not equal if different stack sizes.
1309 if (Stack.size() != Other.Stack.size())
1311 // Not equal if different cumulative strings.
1312 if (!CumulativeString.equals(Other.CumulativeString))
1314 // Equal if all nodes in both stacks match.
1315 for (unsigned i=0; i < Stack.size(); ++i) {
1316 if (Stack[i].Start != Other.Stack[i].Start)
1322 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1324 uint64_t Result = decodeULEB128(Ptr, &Count);
1326 if (Ptr > Trie.end()) {
1333 StringRef ExportEntry::name() const {
1334 return CumulativeString;
1337 uint64_t ExportEntry::flags() const {
1338 return Stack.back().Flags;
1341 uint64_t ExportEntry::address() const {
1342 return Stack.back().Address;
1345 uint64_t ExportEntry::other() const {
1346 return Stack.back().Other;
1349 StringRef ExportEntry::otherName() const {
1350 const char* ImportName = Stack.back().ImportName;
1352 return StringRef(ImportName);
1356 uint32_t ExportEntry::nodeOffset() const {
1357 return Stack.back().Start - Trie.begin();
1360 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1361 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1362 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1363 ParentStringLength(0), IsExportNode(false) {
1366 void ExportEntry::pushNode(uint64_t offset) {
1367 const uint8_t *Ptr = Trie.begin() + offset;
1368 NodeState State(Ptr);
1369 uint64_t ExportInfoSize = readULEB128(State.Current);
1370 State.IsExportNode = (ExportInfoSize != 0);
1371 const uint8_t* Children = State.Current + ExportInfoSize;
1372 if (State.IsExportNode) {
1373 State.Flags = readULEB128(State.Current);
1374 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1376 State.Other = readULEB128(State.Current); // dylib ordinal
1377 State.ImportName = reinterpret_cast<const char*>(State.Current);
1379 State.Address = readULEB128(State.Current);
1380 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1381 State.Other = readULEB128(State.Current);
1384 State.ChildCount = *Children;
1385 State.Current = Children + 1;
1386 State.NextChildIndex = 0;
1387 State.ParentStringLength = CumulativeString.size();
1388 Stack.push_back(State);
1391 void ExportEntry::pushDownUntilBottom() {
1392 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1393 NodeState &Top = Stack.back();
1394 CumulativeString.resize(Top.ParentStringLength);
1395 for (;*Top.Current != 0; Top.Current++) {
1396 char C = *Top.Current;
1397 CumulativeString.push_back(C);
1400 uint64_t childNodeIndex = readULEB128(Top.Current);
1401 Top.NextChildIndex += 1;
1402 pushNode(childNodeIndex);
1404 if (!Stack.back().IsExportNode) {
1410 // We have a trie data structure and need a way to walk it that is compatible
1411 // with the C++ iterator model. The solution is a non-recursive depth first
1412 // traversal where the iterator contains a stack of parent nodes along with a
1413 // string that is the accumulation of all edge strings along the parent chain
1416 // There is one "export" node for each exported symbol. But because some
1417 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1418 // node may have child nodes too.
1420 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1421 // child until hitting a node with no children (which is an export node or
1422 // else the trie is malformed). On the way down, each node is pushed on the
1423 // stack ivar. If there is no more ways down, it pops up one and tries to go
1424 // down a sibling path until a childless node is reached.
1425 void ExportEntry::moveNext() {
1426 if (Stack.empty() || !Stack.back().IsExportNode) {
1433 while (!Stack.empty()) {
1434 NodeState &Top = Stack.back();
1435 if (Top.NextChildIndex < Top.ChildCount) {
1436 pushDownUntilBottom();
1437 // Now at the next export node.
1440 if (Top.IsExportNode) {
1441 // This node has no children but is itself an export node.
1442 CumulativeString.resize(Top.ParentStringLength);
1451 iterator_range<export_iterator>
1452 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1453 ExportEntry Start(Trie);
1454 if (Trie.size() == 0)
1457 Start.moveToFirst();
1459 ExportEntry Finish(Trie);
1462 return iterator_range<export_iterator>(export_iterator(Start),
1463 export_iterator(Finish));
1466 iterator_range<export_iterator> MachOObjectFile::exports() const {
1467 return exports(getDyldInfoExportsTrie());
1471 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1472 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1473 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1474 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1476 void MachORebaseEntry::moveToFirst() {
1477 Ptr = Opcodes.begin();
1481 void MachORebaseEntry::moveToEnd() {
1482 Ptr = Opcodes.end();
1483 RemainingLoopCount = 0;
1487 void MachORebaseEntry::moveNext() {
1488 // If in the middle of some loop, move to next rebasing in loop.
1489 SegmentOffset += AdvanceAmount;
1490 if (RemainingLoopCount) {
1491 --RemainingLoopCount;
1494 if (Ptr == Opcodes.end()) {
1499 while (More && !Malformed) {
1500 // Parse next opcode and set up next loop.
1501 uint8_t Byte = *Ptr++;
1502 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1503 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1505 case MachO::REBASE_OPCODE_DONE:
1509 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1511 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1512 RebaseType = ImmValue;
1515 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1516 << "RebaseType=" << (int) RebaseType << "\n");
1518 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1519 SegmentIndex = ImmValue;
1520 SegmentOffset = readULEB128();
1523 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1524 << "SegmentIndex=" << SegmentIndex << ", "
1525 << format("SegmentOffset=0x%06X", SegmentOffset)
1528 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1529 SegmentOffset += readULEB128();
1530 DEBUG_WITH_TYPE("mach-o-rebase",
1531 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1532 << format("SegmentOffset=0x%06X",
1533 SegmentOffset) << "\n");
1535 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1536 SegmentOffset += ImmValue * PointerSize;
1537 DEBUG_WITH_TYPE("mach-o-rebase",
1538 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1539 << format("SegmentOffset=0x%06X",
1540 SegmentOffset) << "\n");
1542 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1543 AdvanceAmount = PointerSize;
1544 RemainingLoopCount = ImmValue - 1;
1547 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1548 << format("SegmentOffset=0x%06X", SegmentOffset)
1549 << ", AdvanceAmount=" << AdvanceAmount
1550 << ", RemainingLoopCount=" << RemainingLoopCount
1553 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1554 AdvanceAmount = PointerSize;
1555 RemainingLoopCount = readULEB128() - 1;
1558 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1559 << format("SegmentOffset=0x%06X", SegmentOffset)
1560 << ", AdvanceAmount=" << AdvanceAmount
1561 << ", RemainingLoopCount=" << RemainingLoopCount
1564 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1565 AdvanceAmount = readULEB128() + PointerSize;
1566 RemainingLoopCount = 0;
1569 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1570 << format("SegmentOffset=0x%06X", SegmentOffset)
1571 << ", AdvanceAmount=" << AdvanceAmount
1572 << ", RemainingLoopCount=" << RemainingLoopCount
1575 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1576 RemainingLoopCount = readULEB128() - 1;
1577 AdvanceAmount = readULEB128() + PointerSize;
1580 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1581 << format("SegmentOffset=0x%06X", SegmentOffset)
1582 << ", AdvanceAmount=" << AdvanceAmount
1583 << ", RemainingLoopCount=" << RemainingLoopCount
1592 uint64_t MachORebaseEntry::readULEB128() {
1594 uint64_t Result = decodeULEB128(Ptr, &Count);
1596 if (Ptr > Opcodes.end()) {
1597 Ptr = Opcodes.end();
1603 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1605 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1607 StringRef MachORebaseEntry::typeName() const {
1608 switch (RebaseType) {
1609 case MachO::REBASE_TYPE_POINTER:
1611 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1612 return "text abs32";
1613 case MachO::REBASE_TYPE_TEXT_PCREL32:
1614 return "text rel32";
1619 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1620 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1621 return (Ptr == Other.Ptr) &&
1622 (RemainingLoopCount == Other.RemainingLoopCount) &&
1623 (Done == Other.Done);
1626 iterator_range<rebase_iterator>
1627 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1628 MachORebaseEntry Start(Opcodes, is64);
1629 Start.moveToFirst();
1631 MachORebaseEntry Finish(Opcodes, is64);
1634 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1635 rebase_iterator(Finish));
1638 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1639 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1643 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1645 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1646 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1647 BindType(0), PointerSize(is64Bit ? 8 : 4),
1648 TableKind(BK), Malformed(false), Done(false) {}
1650 void MachOBindEntry::moveToFirst() {
1651 Ptr = Opcodes.begin();
1655 void MachOBindEntry::moveToEnd() {
1656 Ptr = Opcodes.end();
1657 RemainingLoopCount = 0;
1661 void MachOBindEntry::moveNext() {
1662 // If in the middle of some loop, move to next binding in loop.
1663 SegmentOffset += AdvanceAmount;
1664 if (RemainingLoopCount) {
1665 --RemainingLoopCount;
1668 if (Ptr == Opcodes.end()) {
1673 while (More && !Malformed) {
1674 // Parse next opcode and set up next loop.
1675 uint8_t Byte = *Ptr++;
1676 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1677 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1678 int8_t SignExtended;
1679 const uint8_t *SymStart;
1681 case MachO::BIND_OPCODE_DONE:
1682 if (TableKind == Kind::Lazy) {
1683 // Lazying bindings have a DONE opcode between entries. Need to ignore
1684 // it to advance to next entry. But need not if this is last entry.
1685 bool NotLastEntry = false;
1686 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1688 NotLastEntry = true;
1697 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1699 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1703 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1704 << "Ordinal=" << Ordinal << "\n");
1706 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1707 Ordinal = readULEB128();
1710 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1711 << "Ordinal=" << Ordinal << "\n");
1713 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1715 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1716 Ordinal = SignExtended;
1721 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1722 << "Ordinal=" << Ordinal << "\n");
1724 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1730 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1735 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1736 << "SymbolName=" << SymbolName << "\n");
1737 if (TableKind == Kind::Weak) {
1738 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1742 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1743 BindType = ImmValue;
1746 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1747 << "BindType=" << (int)BindType << "\n");
1749 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1750 Addend = readSLEB128();
1751 if (TableKind == Kind::Lazy)
1755 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1756 << "Addend=" << Addend << "\n");
1758 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1759 SegmentIndex = ImmValue;
1760 SegmentOffset = readULEB128();
1763 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1764 << "SegmentIndex=" << SegmentIndex << ", "
1765 << format("SegmentOffset=0x%06X", SegmentOffset)
1768 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1769 SegmentOffset += readULEB128();
1770 DEBUG_WITH_TYPE("mach-o-bind",
1771 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1772 << format("SegmentOffset=0x%06X",
1773 SegmentOffset) << "\n");
1775 case MachO::BIND_OPCODE_DO_BIND:
1776 AdvanceAmount = PointerSize;
1777 RemainingLoopCount = 0;
1778 DEBUG_WITH_TYPE("mach-o-bind",
1779 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1780 << format("SegmentOffset=0x%06X",
1781 SegmentOffset) << "\n");
1783 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1784 AdvanceAmount = readULEB128() + PointerSize;
1785 RemainingLoopCount = 0;
1786 if (TableKind == Kind::Lazy)
1790 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1791 << format("SegmentOffset=0x%06X", SegmentOffset)
1792 << ", AdvanceAmount=" << AdvanceAmount
1793 << ", RemainingLoopCount=" << RemainingLoopCount
1796 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1797 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1798 RemainingLoopCount = 0;
1799 if (TableKind == Kind::Lazy)
1801 DEBUG_WITH_TYPE("mach-o-bind",
1803 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1804 << format("SegmentOffset=0x%06X",
1805 SegmentOffset) << "\n");
1807 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1808 RemainingLoopCount = readULEB128() - 1;
1809 AdvanceAmount = readULEB128() + PointerSize;
1810 if (TableKind == Kind::Lazy)
1814 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1815 << format("SegmentOffset=0x%06X", SegmentOffset)
1816 << ", AdvanceAmount=" << AdvanceAmount
1817 << ", RemainingLoopCount=" << RemainingLoopCount
1826 uint64_t MachOBindEntry::readULEB128() {
1828 uint64_t Result = decodeULEB128(Ptr, &Count);
1830 if (Ptr > Opcodes.end()) {
1831 Ptr = Opcodes.end();
1837 int64_t MachOBindEntry::readSLEB128() {
1839 int64_t Result = decodeSLEB128(Ptr, &Count);
1841 if (Ptr > Opcodes.end()) {
1842 Ptr = Opcodes.end();
1849 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1851 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1853 StringRef MachOBindEntry::typeName() const {
1855 case MachO::BIND_TYPE_POINTER:
1857 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1858 return "text abs32";
1859 case MachO::BIND_TYPE_TEXT_PCREL32:
1860 return "text rel32";
1865 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1867 int64_t MachOBindEntry::addend() const { return Addend; }
1869 uint32_t MachOBindEntry::flags() const { return Flags; }
1871 int MachOBindEntry::ordinal() const { return Ordinal; }
1873 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1874 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1875 return (Ptr == Other.Ptr) &&
1876 (RemainingLoopCount == Other.RemainingLoopCount) &&
1877 (Done == Other.Done);
1880 iterator_range<bind_iterator>
1881 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1882 MachOBindEntry::Kind BKind) {
1883 MachOBindEntry Start(Opcodes, is64, BKind);
1884 Start.moveToFirst();
1886 MachOBindEntry Finish(Opcodes, is64, BKind);
1889 return iterator_range<bind_iterator>(bind_iterator(Start),
1890 bind_iterator(Finish));
1893 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1894 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1895 MachOBindEntry::Kind::Regular);
1898 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1899 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1900 MachOBindEntry::Kind::Lazy);
1903 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1904 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1905 MachOBindEntry::Kind::Weak);
1908 MachOObjectFile::load_command_iterator
1909 MachOObjectFile::begin_load_commands() const {
1910 return LoadCommands.begin();
1913 MachOObjectFile::load_command_iterator
1914 MachOObjectFile::end_load_commands() const {
1915 return LoadCommands.end();
1918 iterator_range<MachOObjectFile::load_command_iterator>
1919 MachOObjectFile::load_commands() const {
1920 return iterator_range<load_command_iterator>(begin_load_commands(),
1921 end_load_commands());
1925 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1926 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1927 return parseSegmentOrSectionName(Raw.data());
1931 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1932 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1933 const section_base *Base =
1934 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1935 return makeArrayRef(Base->sectname);
1939 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1940 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1941 const section_base *Base =
1942 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1943 return makeArrayRef(Base->segname);
1947 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1949 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1951 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1954 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1955 const MachO::any_relocation_info &RE) const {
1956 if (isLittleEndian())
1957 return RE.r_word1 & 0xffffff;
1958 return RE.r_word1 >> 8;
1961 bool MachOObjectFile::getPlainRelocationExternal(
1962 const MachO::any_relocation_info &RE) const {
1963 if (isLittleEndian())
1964 return (RE.r_word1 >> 27) & 1;
1965 return (RE.r_word1 >> 4) & 1;
1968 bool MachOObjectFile::getScatteredRelocationScattered(
1969 const MachO::any_relocation_info &RE) const {
1970 return RE.r_word0 >> 31;
1973 uint32_t MachOObjectFile::getScatteredRelocationValue(
1974 const MachO::any_relocation_info &RE) const {
1978 uint32_t MachOObjectFile::getScatteredRelocationType(
1979 const MachO::any_relocation_info &RE) const {
1980 return (RE.r_word0 >> 24) & 0xf;
1983 unsigned MachOObjectFile::getAnyRelocationAddress(
1984 const MachO::any_relocation_info &RE) const {
1985 if (isRelocationScattered(RE))
1986 return getScatteredRelocationAddress(RE);
1987 return getPlainRelocationAddress(RE);
1990 unsigned MachOObjectFile::getAnyRelocationPCRel(
1991 const MachO::any_relocation_info &RE) const {
1992 if (isRelocationScattered(RE))
1993 return getScatteredRelocationPCRel(this, RE);
1994 return getPlainRelocationPCRel(this, RE);
1997 unsigned MachOObjectFile::getAnyRelocationLength(
1998 const MachO::any_relocation_info &RE) const {
1999 if (isRelocationScattered(RE))
2000 return getScatteredRelocationLength(RE);
2001 return getPlainRelocationLength(this, RE);
2005 MachOObjectFile::getAnyRelocationType(
2006 const MachO::any_relocation_info &RE) const {
2007 if (isRelocationScattered(RE))
2008 return getScatteredRelocationType(RE);
2009 return getPlainRelocationType(this, RE);
2013 MachOObjectFile::getAnyRelocationSection(
2014 const MachO::any_relocation_info &RE) const {
2015 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2016 return *section_end();
2017 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2018 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2019 return *section_end();
2021 DRI.d.a = SecNum - 1;
2022 return SectionRef(DRI, this);
2025 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2026 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2027 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2030 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2031 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2032 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2035 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2036 unsigned Index) const {
2037 const char *Sec = getSectionPtr(this, L, Index);
2038 return getStruct<MachO::section>(this, Sec);
2041 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2042 unsigned Index) const {
2043 const char *Sec = getSectionPtr(this, L, Index);
2044 return getStruct<MachO::section_64>(this, Sec);
2048 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2049 const char *P = reinterpret_cast<const char *>(DRI.p);
2050 return getStruct<MachO::nlist>(this, P);
2054 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2055 const char *P = reinterpret_cast<const char *>(DRI.p);
2056 return getStruct<MachO::nlist_64>(this, P);
2059 MachO::linkedit_data_command
2060 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2061 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2064 MachO::segment_command
2065 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2066 return getStruct<MachO::segment_command>(this, L.Ptr);
2069 MachO::segment_command_64
2070 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2071 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2074 MachO::linker_option_command
2075 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2079 MachO::version_min_command
2080 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::version_min_command>(this, L.Ptr);
2084 MachO::dylib_command
2085 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::dylib_command>(this, L.Ptr);
2089 MachO::dyld_info_command
2090 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2094 MachO::dylinker_command
2095 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2096 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2100 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2101 return getStruct<MachO::uuid_command>(this, L.Ptr);
2104 MachO::rpath_command
2105 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::rpath_command>(this, L.Ptr);
2109 MachO::source_version_command
2110 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::source_version_command>(this, L.Ptr);
2114 MachO::entry_point_command
2115 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2116 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2119 MachO::encryption_info_command
2120 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2124 MachO::encryption_info_command_64
2125 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2129 MachO::sub_framework_command
2130 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2134 MachO::sub_umbrella_command
2135 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2139 MachO::sub_library_command
2140 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2144 MachO::sub_client_command
2145 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2149 MachO::routines_command
2150 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::routines_command>(this, L.Ptr);
2154 MachO::routines_command_64
2155 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2156 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2159 MachO::thread_command
2160 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2161 return getStruct<MachO::thread_command>(this, L.Ptr);
2164 MachO::any_relocation_info
2165 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2170 MachO::section_64 Sect = getSection64(Sec);
2171 Offset = Sect.reloff;
2173 MachO::section Sect = getSection(Sec);
2174 Offset = Sect.reloff;
2177 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2178 getPtr(this, Offset)) + Rel.d.b;
2179 return getStruct<MachO::any_relocation_info>(
2180 this, reinterpret_cast<const char *>(P));
2183 MachO::data_in_code_entry
2184 MachOObjectFile::getDice(DataRefImpl Rel) const {
2185 const char *P = reinterpret_cast<const char *>(Rel.p);
2186 return getStruct<MachO::data_in_code_entry>(this, P);
2189 const MachO::mach_header &MachOObjectFile::getHeader() const {
2193 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2198 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2199 const MachO::dysymtab_command &DLC,
2200 unsigned Index) const {
2201 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2202 return getStruct<uint32_t>(this, getPtr(this, Offset));
2205 MachO::data_in_code_entry
2206 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2207 unsigned Index) const {
2208 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2209 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2212 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2214 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2216 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2217 MachO::symtab_command Cmd;
2218 Cmd.cmd = MachO::LC_SYMTAB;
2219 Cmd.cmdsize = sizeof(MachO::symtab_command);
2227 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2228 if (DysymtabLoadCmd)
2229 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2231 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2232 MachO::dysymtab_command Cmd;
2233 Cmd.cmd = MachO::LC_DYSYMTAB;
2234 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2245 Cmd.extrefsymoff = 0;
2246 Cmd.nextrefsyms = 0;
2247 Cmd.indirectsymoff = 0;
2248 Cmd.nindirectsyms = 0;
2256 MachO::linkedit_data_command
2257 MachOObjectFile::getDataInCodeLoadCommand() const {
2258 if (DataInCodeLoadCmd)
2259 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2261 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2262 MachO::linkedit_data_command Cmd;
2263 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2264 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2270 MachO::linkedit_data_command
2271 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2272 if (LinkOptHintsLoadCmd)
2273 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2275 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2277 MachO::linkedit_data_command Cmd;
2278 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2279 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2285 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2286 if (!DyldInfoLoadCmd)
2287 return ArrayRef<uint8_t>();
2289 MachO::dyld_info_command DyldInfo
2290 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2291 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2292 getPtr(this, DyldInfo.rebase_off));
2293 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2296 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2297 if (!DyldInfoLoadCmd)
2298 return ArrayRef<uint8_t>();
2300 MachO::dyld_info_command DyldInfo
2301 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2302 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2303 getPtr(this, DyldInfo.bind_off));
2304 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2307 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2308 if (!DyldInfoLoadCmd)
2309 return ArrayRef<uint8_t>();
2311 MachO::dyld_info_command DyldInfo
2312 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2313 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2314 getPtr(this, DyldInfo.weak_bind_off));
2315 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2318 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2319 if (!DyldInfoLoadCmd)
2320 return ArrayRef<uint8_t>();
2322 MachO::dyld_info_command DyldInfo
2323 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2324 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2325 getPtr(this, DyldInfo.lazy_bind_off));
2326 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2329 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2330 if (!DyldInfoLoadCmd)
2331 return ArrayRef<uint8_t>();
2333 MachO::dyld_info_command DyldInfo
2334 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2335 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2336 getPtr(this, DyldInfo.export_off));
2337 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2340 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2342 return ArrayRef<uint8_t>();
2343 // Returning a pointer is fine as uuid doesn't need endian swapping.
2344 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2345 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2348 StringRef MachOObjectFile::getStringTableData() const {
2349 MachO::symtab_command S = getSymtabLoadCommand();
2350 return getData().substr(S.stroff, S.strsize);
2353 bool MachOObjectFile::is64Bit() const {
2354 return getType() == getMachOType(false, true) ||
2355 getType() == getMachOType(true, true);
2358 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2359 SmallVectorImpl<uint64_t> &Out) const {
2360 DataExtractor extractor(ObjectFile::getData(), true, 0);
2362 uint32_t offset = Index;
2364 while (uint64_t delta = extractor.getULEB128(&offset)) {
2366 Out.push_back(data);
2370 bool MachOObjectFile::isRelocatableObject() const {
2371 return getHeader().filetype == MachO::MH_OBJECT;
2374 ErrorOr<std::unique_ptr<MachOObjectFile>>
2375 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2376 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2378 std::unique_ptr<MachOObjectFile> Ret;
2379 if (Magic == "\xFE\xED\xFA\xCE")
2380 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2381 else if (Magic == "\xCE\xFA\xED\xFE")
2382 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2383 else if (Magic == "\xFE\xED\xFA\xCF")
2384 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2385 else if (Magic == "\xCF\xFA\xED\xFE")
2386 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2388 return object_error::parse_failed;
2392 return std::move(Ret);