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 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
403 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
404 uint8_t n_type = Entry.n_type;
406 // If this is a STAB debugging symbol, we can do nothing more.
407 if (n_type & MachO::N_STAB)
408 return SymbolRef::ST_Debug;
410 switch (n_type & MachO::N_TYPE) {
412 return SymbolRef::ST_Unknown;
414 return SymbolRef::ST_Function;
416 return SymbolRef::ST_Other;
419 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
420 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
422 uint8_t MachOType = Entry.n_type;
423 uint16_t MachOFlags = Entry.n_desc;
425 uint32_t Result = SymbolRef::SF_None;
427 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
428 Result |= SymbolRef::SF_Undefined;
430 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
431 Result |= SymbolRef::SF_Indirect;
433 if (MachOType & MachO::N_STAB)
434 Result |= SymbolRef::SF_FormatSpecific;
436 if (MachOType & MachO::N_EXT) {
437 Result |= SymbolRef::SF_Global;
438 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
440 getSymbolAddress(DRI, Value);
441 if (Value && Value != UnknownAddress)
442 Result |= SymbolRef::SF_Common;
445 if (!(MachOType & MachO::N_PEXT))
446 Result |= SymbolRef::SF_Exported;
449 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
450 Result |= SymbolRef::SF_Weak;
452 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
453 Result |= SymbolRef::SF_Thumb;
455 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
456 Result |= SymbolRef::SF_Absolute;
461 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
462 section_iterator &Res) const {
463 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
464 uint8_t index = Entry.n_sect;
471 if (DRI.d.a >= Sections.size())
472 report_fatal_error("getSymbolSection: Invalid section index.");
473 Res = section_iterator(SectionRef(DRI, this));
476 return std::error_code();
479 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
480 MachO::nlist_base Entry =
481 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
482 return Entry.n_sect - 1;
485 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
489 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
490 StringRef &Result) const {
491 ArrayRef<char> Raw = getSectionRawName(Sec);
492 Result = parseSegmentOrSectionName(Raw.data());
493 return std::error_code();
496 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
498 return getSection64(Sec).addr;
499 return getSection(Sec).addr;
502 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
504 return getSection64(Sec).size;
505 return getSection(Sec).size;
508 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
509 StringRef &Res) const {
514 MachO::section_64 Sect = getSection64(Sec);
515 Offset = Sect.offset;
518 MachO::section Sect = getSection(Sec);
519 Offset = Sect.offset;
523 Res = this->getData().substr(Offset, Size);
524 return std::error_code();
527 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
530 MachO::section_64 Sect = getSection64(Sec);
533 MachO::section Sect = getSection(Sec);
537 return uint64_t(1) << Align;
540 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
545 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
546 uint32_t Flags = getSectionFlags(this, Sec);
547 unsigned SectionType = Flags & MachO::SECTION_TYPE;
548 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
549 !(SectionType == MachO::S_ZEROFILL ||
550 SectionType == MachO::S_GB_ZEROFILL);
553 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
554 uint32_t Flags = getSectionFlags(this, Sec);
555 unsigned SectionType = Flags & MachO::SECTION_TYPE;
556 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
557 (SectionType == MachO::S_ZEROFILL ||
558 SectionType == MachO::S_GB_ZEROFILL);
561 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
562 return Sec.getRawDataRefImpl().d.a;
565 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
566 // FIXME: Unimplemented.
570 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
571 DataRefImpl Symb) const {
572 SymbolRef::Type ST = getSymbolType(Symb);
573 if (ST == SymbolRef::ST_Unknown)
576 uint64_t SectBegin = getSectionAddress(Sec);
577 uint64_t SectEnd = getSectionSize(Sec);
578 SectEnd += SectBegin;
581 getSymbolAddress(Symb, SymAddr);
582 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
585 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
589 return relocation_iterator(RelocationRef(Ret, this));
593 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
596 MachO::section_64 Sect = getSection64(Sec);
599 MachO::section Sect = getSection(Sec);
606 return relocation_iterator(RelocationRef(Ret, this));
609 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
613 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
614 uint64_t &Res) const {
616 getRelocationOffset(Rel, Offset);
620 uint64_t SecAddress = getSectionAddress(Sec);
621 Res = SecAddress + Offset;
622 return std::error_code();
625 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
626 uint64_t &Res) const {
627 assert(getHeader().filetype == MachO::MH_OBJECT &&
628 "Only implemented for MH_OBJECT");
629 MachO::any_relocation_info RE = getRelocation(Rel);
630 Res = getAnyRelocationAddress(RE);
631 return std::error_code();
635 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
636 MachO::any_relocation_info RE = getRelocation(Rel);
637 if (isRelocationScattered(RE))
640 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
641 bool isExtern = getPlainRelocationExternal(RE);
645 MachO::symtab_command S = getSymtabLoadCommand();
646 unsigned SymbolTableEntrySize = is64Bit() ?
647 sizeof(MachO::nlist_64) :
648 sizeof(MachO::nlist);
649 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
651 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
652 return symbol_iterator(SymbolRef(Sym, this));
656 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
657 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
660 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
661 uint64_t &Res) const {
662 MachO::any_relocation_info RE = getRelocation(Rel);
663 Res = getAnyRelocationType(RE);
664 return std::error_code();
668 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
669 SmallVectorImpl<char> &Result) const {
672 getRelocationType(Rel, RType);
674 unsigned Arch = this->getArch();
678 static const char *const Table[] = {
679 "GENERIC_RELOC_VANILLA",
680 "GENERIC_RELOC_PAIR",
681 "GENERIC_RELOC_SECTDIFF",
682 "GENERIC_RELOC_PB_LA_PTR",
683 "GENERIC_RELOC_LOCAL_SECTDIFF",
684 "GENERIC_RELOC_TLV" };
692 case Triple::x86_64: {
693 static const char *const Table[] = {
694 "X86_64_RELOC_UNSIGNED",
695 "X86_64_RELOC_SIGNED",
696 "X86_64_RELOC_BRANCH",
697 "X86_64_RELOC_GOT_LOAD",
699 "X86_64_RELOC_SUBTRACTOR",
700 "X86_64_RELOC_SIGNED_1",
701 "X86_64_RELOC_SIGNED_2",
702 "X86_64_RELOC_SIGNED_4",
703 "X86_64_RELOC_TLV" };
712 static const char *const Table[] = {
715 "ARM_RELOC_SECTDIFF",
716 "ARM_RELOC_LOCAL_SECTDIFF",
717 "ARM_RELOC_PB_LA_PTR",
719 "ARM_THUMB_RELOC_BR22",
720 "ARM_THUMB_32BIT_BRANCH",
722 "ARM_RELOC_HALF_SECTDIFF" };
730 case Triple::aarch64: {
731 static const char *const Table[] = {
732 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
733 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
734 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
735 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
736 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
740 if (RType >= array_lengthof(Table))
747 static const char *const Table[] = {
756 "PPC_RELOC_SECTDIFF",
757 "PPC_RELOC_PB_LA_PTR",
758 "PPC_RELOC_HI16_SECTDIFF",
759 "PPC_RELOC_LO16_SECTDIFF",
760 "PPC_RELOC_HA16_SECTDIFF",
762 "PPC_RELOC_LO14_SECTDIFF",
763 "PPC_RELOC_LOCAL_SECTDIFF" };
771 case Triple::UnknownArch:
775 Result.append(res.begin(), res.end());
776 return std::error_code();
779 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
780 bool &Result) const {
781 unsigned Arch = getArch();
783 getRelocationType(Rel, Type);
787 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
789 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
790 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
791 } else if (Arch == Triple::x86_64) {
792 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
793 // an X86_64_RELOC_SUBTRACTOR.
794 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
795 DataRefImpl RelPrev = Rel;
798 getRelocationType(RelPrev, PrevType);
799 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
804 return std::error_code();
807 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
808 MachO::any_relocation_info RE = getRelocation(Rel);
809 return getAnyRelocationLength(RE);
813 // guessLibraryShortName() is passed a name of a dynamic library and returns a
814 // guess on what the short name is. Then name is returned as a substring of the
815 // StringRef Name passed in. The name of the dynamic library is recognized as
816 // a framework if it has one of the two following forms:
817 // Foo.framework/Versions/A/Foo
819 // Where A and Foo can be any string. And may contain a trailing suffix
820 // starting with an underbar. If the Name is recognized as a framework then
821 // isFramework is set to true else it is set to false. If the Name has a
822 // suffix then Suffix is set to the substring in Name that contains the suffix
823 // else it is set to a NULL StringRef.
825 // The Name of the dynamic library is recognized as a library name if it has
826 // one of the two following forms:
829 // The library may have a suffix trailing the name Foo of the form:
830 // libFoo_profile.A.dylib
831 // libFoo_profile.dylib
833 // The Name of the dynamic library is also recognized as a library name if it
834 // has the following form:
837 // If the Name of the dynamic library is none of the forms above then a NULL
838 // StringRef is returned.
840 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
843 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
844 size_t a, b, c, d, Idx;
847 Suffix = StringRef();
849 // Pull off the last component and make Foo point to it
851 if (a == Name.npos || a == 0)
853 Foo = Name.slice(a+1, Name.npos);
855 // Look for a suffix starting with a '_'
856 Idx = Foo.rfind('_');
857 if (Idx != Foo.npos && Foo.size() >= 2) {
858 Suffix = Foo.slice(Idx, Foo.npos);
859 Foo = Foo.slice(0, Idx);
862 // First look for the form Foo.framework/Foo
863 b = Name.rfind('/', a);
868 F = Name.slice(Idx, Idx + Foo.size());
869 DotFramework = Name.slice(Idx + Foo.size(),
870 Idx + Foo.size() + sizeof(".framework/")-1);
871 if (F == Foo && DotFramework == ".framework/") {
876 // Next look for the form Foo.framework/Versions/A/Foo
879 c = Name.rfind('/', b);
880 if (c == Name.npos || c == 0)
882 V = Name.slice(c+1, Name.npos);
883 if (!V.startswith("Versions/"))
885 d = Name.rfind('/', c);
890 F = Name.slice(Idx, Idx + Foo.size());
891 DotFramework = Name.slice(Idx + Foo.size(),
892 Idx + Foo.size() + sizeof(".framework/")-1);
893 if (F == Foo && DotFramework == ".framework/") {
899 // pull off the suffix after the "." and make a point to it
901 if (a == Name.npos || a == 0)
903 Dylib = Name.slice(a, Name.npos);
904 if (Dylib != ".dylib")
907 // First pull off the version letter for the form Foo.A.dylib if any.
909 Dot = Name.slice(a-2, a-1);
914 b = Name.rfind('/', a);
919 // ignore any suffix after an underbar like Foo_profile.A.dylib
920 Idx = Name.find('_', b);
921 if (Idx != Name.npos && Idx != b) {
922 Lib = Name.slice(b, Idx);
923 Suffix = Name.slice(Idx, a);
926 Lib = Name.slice(b, a);
927 // There are incorrect library names of the form:
928 // libATS.A_profile.dylib so check for these.
929 if (Lib.size() >= 3) {
930 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
932 Lib = Lib.slice(0, Lib.size()-2);
937 Qtx = Name.slice(a, Name.npos);
940 b = Name.rfind('/', a);
942 Lib = Name.slice(0, a);
944 Lib = Name.slice(b+1, a);
945 // There are library names of the form: QT.A.qtx so check for these.
946 if (Lib.size() >= 3) {
947 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
949 Lib = Lib.slice(0, Lib.size()-2);
954 // getLibraryShortNameByIndex() is used to get the short name of the library
955 // for an undefined symbol in a linked Mach-O binary that was linked with the
956 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
957 // It is passed the index (0 - based) of the library as translated from
958 // GET_LIBRARY_ORDINAL (1 - based).
959 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
960 StringRef &Res) const {
961 if (Index >= Libraries.size())
962 return object_error::parse_failed;
964 // If the cache of LibrariesShortNames is not built up do that first for
965 // all the Libraries.
966 if (LibrariesShortNames.size() == 0) {
967 for (unsigned i = 0; i < Libraries.size(); i++) {
968 MachO::dylib_command D =
969 getStruct<MachO::dylib_command>(this, Libraries[i]);
970 if (D.dylib.name >= D.cmdsize)
971 return object_error::parse_failed;
972 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
973 StringRef Name = StringRef(P);
974 if (D.dylib.name+Name.size() >= D.cmdsize)
975 return object_error::parse_failed;
978 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
979 if (shortName.empty())
980 LibrariesShortNames.push_back(Name);
982 LibrariesShortNames.push_back(shortName);
986 Res = LibrariesShortNames[Index];
987 return std::error_code();
990 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
991 return getSymbolByIndex(0);
994 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
997 return basic_symbol_iterator(SymbolRef(DRI, this));
999 MachO::symtab_command Symtab = getSymtabLoadCommand();
1000 unsigned SymbolTableEntrySize = is64Bit() ?
1001 sizeof(MachO::nlist_64) :
1002 sizeof(MachO::nlist);
1003 unsigned Offset = Symtab.symoff +
1004 Symtab.nsyms * SymbolTableEntrySize;
1005 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1006 return basic_symbol_iterator(SymbolRef(DRI, this));
1009 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1012 return basic_symbol_iterator(SymbolRef(DRI, this));
1014 MachO::symtab_command Symtab = getSymtabLoadCommand();
1015 if (Index >= Symtab.nsyms)
1016 report_fatal_error("Requested symbol index is out of range.");
1017 unsigned SymbolTableEntrySize =
1018 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1019 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1020 DRI.p += Index * SymbolTableEntrySize;
1021 return basic_symbol_iterator(SymbolRef(DRI, this));
1024 section_iterator MachOObjectFile::section_begin() const {
1026 return section_iterator(SectionRef(DRI, this));
1029 section_iterator MachOObjectFile::section_end() const {
1031 DRI.d.a = Sections.size();
1032 return section_iterator(SectionRef(DRI, this));
1035 uint8_t MachOObjectFile::getBytesInAddress() const {
1036 return is64Bit() ? 8 : 4;
1039 StringRef MachOObjectFile::getFileFormatName() const {
1040 unsigned CPUType = getCPUType(this);
1043 case llvm::MachO::CPU_TYPE_I386:
1044 return "Mach-O 32-bit i386";
1045 case llvm::MachO::CPU_TYPE_ARM:
1046 return "Mach-O arm";
1047 case llvm::MachO::CPU_TYPE_POWERPC:
1048 return "Mach-O 32-bit ppc";
1050 return "Mach-O 32-bit unknown";
1055 case llvm::MachO::CPU_TYPE_X86_64:
1056 return "Mach-O 64-bit x86-64";
1057 case llvm::MachO::CPU_TYPE_ARM64:
1058 return "Mach-O arm64";
1059 case llvm::MachO::CPU_TYPE_POWERPC64:
1060 return "Mach-O 64-bit ppc64";
1062 return "Mach-O 64-bit unknown";
1066 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1068 case llvm::MachO::CPU_TYPE_I386:
1070 case llvm::MachO::CPU_TYPE_X86_64:
1071 return Triple::x86_64;
1072 case llvm::MachO::CPU_TYPE_ARM:
1074 case llvm::MachO::CPU_TYPE_ARM64:
1075 return Triple::aarch64;
1076 case llvm::MachO::CPU_TYPE_POWERPC:
1078 case llvm::MachO::CPU_TYPE_POWERPC64:
1079 return Triple::ppc64;
1081 return Triple::UnknownArch;
1085 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1086 const char **McpuDefault) {
1088 *McpuDefault = nullptr;
1091 case MachO::CPU_TYPE_I386:
1092 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1093 case MachO::CPU_SUBTYPE_I386_ALL:
1094 return Triple("i386-apple-darwin");
1098 case MachO::CPU_TYPE_X86_64:
1099 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1100 case MachO::CPU_SUBTYPE_X86_64_ALL:
1101 return Triple("x86_64-apple-darwin");
1102 case MachO::CPU_SUBTYPE_X86_64_H:
1103 return Triple("x86_64h-apple-darwin");
1107 case MachO::CPU_TYPE_ARM:
1108 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1109 case MachO::CPU_SUBTYPE_ARM_V4T:
1110 return Triple("armv4t-apple-darwin");
1111 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1112 return Triple("armv5e-apple-darwin");
1113 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1114 return Triple("xscale-apple-darwin");
1115 case MachO::CPU_SUBTYPE_ARM_V6:
1116 return Triple("armv6-apple-darwin");
1117 case MachO::CPU_SUBTYPE_ARM_V6M:
1119 *McpuDefault = "cortex-m0";
1120 return Triple("armv6m-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V7:
1122 return Triple("armv7-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V7EM:
1125 *McpuDefault = "cortex-m4";
1126 return Triple("armv7em-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V7K:
1128 return Triple("armv7k-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V7M:
1131 *McpuDefault = "cortex-m3";
1132 return Triple("armv7m-apple-darwin");
1133 case MachO::CPU_SUBTYPE_ARM_V7S:
1134 return Triple("armv7s-apple-darwin");
1138 case MachO::CPU_TYPE_ARM64:
1139 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1140 case MachO::CPU_SUBTYPE_ARM64_ALL:
1141 return Triple("arm64-apple-darwin");
1145 case MachO::CPU_TYPE_POWERPC:
1146 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1147 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1148 return Triple("ppc-apple-darwin");
1152 case MachO::CPU_TYPE_POWERPC64:
1153 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1154 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1155 return Triple("ppc64-apple-darwin");
1164 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1165 const char **McpuDefault) {
1167 *McpuDefault = nullptr;
1170 case MachO::CPU_TYPE_ARM:
1171 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1172 case MachO::CPU_SUBTYPE_ARM_V4T:
1173 return Triple("thumbv4t-apple-darwin");
1174 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1175 return Triple("thumbv5e-apple-darwin");
1176 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1177 return Triple("xscale-apple-darwin");
1178 case MachO::CPU_SUBTYPE_ARM_V6:
1179 return Triple("thumbv6-apple-darwin");
1180 case MachO::CPU_SUBTYPE_ARM_V6M:
1182 *McpuDefault = "cortex-m0";
1183 return Triple("thumbv6m-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V7:
1185 return Triple("thumbv7-apple-darwin");
1186 case MachO::CPU_SUBTYPE_ARM_V7EM:
1188 *McpuDefault = "cortex-m4";
1189 return Triple("thumbv7em-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V7K:
1191 return Triple("thumbv7k-apple-darwin");
1192 case MachO::CPU_SUBTYPE_ARM_V7M:
1194 *McpuDefault = "cortex-m3";
1195 return Triple("thumbv7m-apple-darwin");
1196 case MachO::CPU_SUBTYPE_ARM_V7S:
1197 return Triple("thumbv7s-apple-darwin");
1206 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1207 const char **McpuDefault,
1208 Triple *ThumbTriple) {
1209 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1210 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1215 Triple MachOObjectFile::getHostArch() {
1216 return Triple(sys::getDefaultTargetTriple());
1219 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1220 return StringSwitch<bool>(ArchFlag)
1222 .Case("x86_64", true)
1223 .Case("x86_64h", true)
1224 .Case("armv4t", true)
1226 .Case("armv5e", true)
1227 .Case("armv6", true)
1228 .Case("armv6m", true)
1229 .Case("armv7", true)
1230 .Case("armv7em", true)
1231 .Case("armv7k", true)
1232 .Case("armv7m", true)
1233 .Case("armv7s", true)
1234 .Case("arm64", true)
1236 .Case("ppc64", true)
1240 unsigned MachOObjectFile::getArch() const {
1241 return getArch(getCPUType(this));
1244 Triple MachOObjectFile::getArch(const char **McpuDefault,
1245 Triple *ThumbTriple) const {
1246 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1247 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1250 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1253 return section_rel_begin(DRI);
1256 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1259 return section_rel_end(DRI);
1262 dice_iterator MachOObjectFile::begin_dices() const {
1264 if (!DataInCodeLoadCmd)
1265 return dice_iterator(DiceRef(DRI, this));
1267 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1268 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1269 return dice_iterator(DiceRef(DRI, this));
1272 dice_iterator MachOObjectFile::end_dices() const {
1274 if (!DataInCodeLoadCmd)
1275 return dice_iterator(DiceRef(DRI, this));
1277 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1278 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1279 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1280 return dice_iterator(DiceRef(DRI, this));
1283 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1284 : Trie(T), Malformed(false), Done(false) { }
1286 void ExportEntry::moveToFirst() {
1288 pushDownUntilBottom();
1291 void ExportEntry::moveToEnd() {
1296 bool ExportEntry::operator==(const ExportEntry &Other) const {
1297 // Common case, one at end, other iterating from begin.
1298 if (Done || Other.Done)
1299 return (Done == Other.Done);
1300 // Not equal if different stack sizes.
1301 if (Stack.size() != Other.Stack.size())
1303 // Not equal if different cumulative strings.
1304 if (!CumulativeString.equals(Other.CumulativeString))
1306 // Equal if all nodes in both stacks match.
1307 for (unsigned i=0; i < Stack.size(); ++i) {
1308 if (Stack[i].Start != Other.Stack[i].Start)
1314 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1316 uint64_t Result = decodeULEB128(Ptr, &Count);
1318 if (Ptr > Trie.end()) {
1325 StringRef ExportEntry::name() const {
1326 return CumulativeString;
1329 uint64_t ExportEntry::flags() const {
1330 return Stack.back().Flags;
1333 uint64_t ExportEntry::address() const {
1334 return Stack.back().Address;
1337 uint64_t ExportEntry::other() const {
1338 return Stack.back().Other;
1341 StringRef ExportEntry::otherName() const {
1342 const char* ImportName = Stack.back().ImportName;
1344 return StringRef(ImportName);
1348 uint32_t ExportEntry::nodeOffset() const {
1349 return Stack.back().Start - Trie.begin();
1352 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1353 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1354 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1355 ParentStringLength(0), IsExportNode(false) {
1358 void ExportEntry::pushNode(uint64_t offset) {
1359 const uint8_t *Ptr = Trie.begin() + offset;
1360 NodeState State(Ptr);
1361 uint64_t ExportInfoSize = readULEB128(State.Current);
1362 State.IsExportNode = (ExportInfoSize != 0);
1363 const uint8_t* Children = State.Current + ExportInfoSize;
1364 if (State.IsExportNode) {
1365 State.Flags = readULEB128(State.Current);
1366 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1368 State.Other = readULEB128(State.Current); // dylib ordinal
1369 State.ImportName = reinterpret_cast<const char*>(State.Current);
1371 State.Address = readULEB128(State.Current);
1372 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1373 State.Other = readULEB128(State.Current);
1376 State.ChildCount = *Children;
1377 State.Current = Children + 1;
1378 State.NextChildIndex = 0;
1379 State.ParentStringLength = CumulativeString.size();
1380 Stack.push_back(State);
1383 void ExportEntry::pushDownUntilBottom() {
1384 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1385 NodeState &Top = Stack.back();
1386 CumulativeString.resize(Top.ParentStringLength);
1387 for (;*Top.Current != 0; Top.Current++) {
1388 char C = *Top.Current;
1389 CumulativeString.push_back(C);
1392 uint64_t childNodeIndex = readULEB128(Top.Current);
1393 Top.NextChildIndex += 1;
1394 pushNode(childNodeIndex);
1396 if (!Stack.back().IsExportNode) {
1402 // We have a trie data structure and need a way to walk it that is compatible
1403 // with the C++ iterator model. The solution is a non-recursive depth first
1404 // traversal where the iterator contains a stack of parent nodes along with a
1405 // string that is the accumulation of all edge strings along the parent chain
1408 // There is one "export" node for each exported symbol. But because some
1409 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1410 // node may have child nodes too.
1412 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1413 // child until hitting a node with no children (which is an export node or
1414 // else the trie is malformed). On the way down, each node is pushed on the
1415 // stack ivar. If there is no more ways down, it pops up one and tries to go
1416 // down a sibling path until a childless node is reached.
1417 void ExportEntry::moveNext() {
1418 if (Stack.empty() || !Stack.back().IsExportNode) {
1425 while (!Stack.empty()) {
1426 NodeState &Top = Stack.back();
1427 if (Top.NextChildIndex < Top.ChildCount) {
1428 pushDownUntilBottom();
1429 // Now at the next export node.
1432 if (Top.IsExportNode) {
1433 // This node has no children but is itself an export node.
1434 CumulativeString.resize(Top.ParentStringLength);
1443 iterator_range<export_iterator>
1444 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1445 ExportEntry Start(Trie);
1446 if (Trie.size() == 0)
1449 Start.moveToFirst();
1451 ExportEntry Finish(Trie);
1454 return iterator_range<export_iterator>(export_iterator(Start),
1455 export_iterator(Finish));
1458 iterator_range<export_iterator> MachOObjectFile::exports() const {
1459 return exports(getDyldInfoExportsTrie());
1463 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1464 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1465 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1466 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1468 void MachORebaseEntry::moveToFirst() {
1469 Ptr = Opcodes.begin();
1473 void MachORebaseEntry::moveToEnd() {
1474 Ptr = Opcodes.end();
1475 RemainingLoopCount = 0;
1479 void MachORebaseEntry::moveNext() {
1480 // If in the middle of some loop, move to next rebasing in loop.
1481 SegmentOffset += AdvanceAmount;
1482 if (RemainingLoopCount) {
1483 --RemainingLoopCount;
1486 if (Ptr == Opcodes.end()) {
1491 while (More && !Malformed) {
1492 // Parse next opcode and set up next loop.
1493 uint8_t Byte = *Ptr++;
1494 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1495 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1497 case MachO::REBASE_OPCODE_DONE:
1501 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1503 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1504 RebaseType = ImmValue;
1507 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1508 << "RebaseType=" << (int) RebaseType << "\n");
1510 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1511 SegmentIndex = ImmValue;
1512 SegmentOffset = readULEB128();
1515 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1516 << "SegmentIndex=" << SegmentIndex << ", "
1517 << format("SegmentOffset=0x%06X", SegmentOffset)
1520 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1521 SegmentOffset += readULEB128();
1522 DEBUG_WITH_TYPE("mach-o-rebase",
1523 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1524 << format("SegmentOffset=0x%06X",
1525 SegmentOffset) << "\n");
1527 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1528 SegmentOffset += ImmValue * PointerSize;
1529 DEBUG_WITH_TYPE("mach-o-rebase",
1530 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1531 << format("SegmentOffset=0x%06X",
1532 SegmentOffset) << "\n");
1534 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1535 AdvanceAmount = PointerSize;
1536 RemainingLoopCount = ImmValue - 1;
1539 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1540 << format("SegmentOffset=0x%06X", SegmentOffset)
1541 << ", AdvanceAmount=" << AdvanceAmount
1542 << ", RemainingLoopCount=" << RemainingLoopCount
1545 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1546 AdvanceAmount = PointerSize;
1547 RemainingLoopCount = readULEB128() - 1;
1550 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1551 << format("SegmentOffset=0x%06X", SegmentOffset)
1552 << ", AdvanceAmount=" << AdvanceAmount
1553 << ", RemainingLoopCount=" << RemainingLoopCount
1556 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1557 AdvanceAmount = readULEB128() + PointerSize;
1558 RemainingLoopCount = 0;
1561 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1562 << format("SegmentOffset=0x%06X", SegmentOffset)
1563 << ", AdvanceAmount=" << AdvanceAmount
1564 << ", RemainingLoopCount=" << RemainingLoopCount
1567 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1568 RemainingLoopCount = readULEB128() - 1;
1569 AdvanceAmount = readULEB128() + PointerSize;
1572 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1573 << format("SegmentOffset=0x%06X", SegmentOffset)
1574 << ", AdvanceAmount=" << AdvanceAmount
1575 << ", RemainingLoopCount=" << RemainingLoopCount
1584 uint64_t MachORebaseEntry::readULEB128() {
1586 uint64_t Result = decodeULEB128(Ptr, &Count);
1588 if (Ptr > Opcodes.end()) {
1589 Ptr = Opcodes.end();
1595 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1597 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1599 StringRef MachORebaseEntry::typeName() const {
1600 switch (RebaseType) {
1601 case MachO::REBASE_TYPE_POINTER:
1603 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1604 return "text abs32";
1605 case MachO::REBASE_TYPE_TEXT_PCREL32:
1606 return "text rel32";
1611 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1612 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1613 return (Ptr == Other.Ptr) &&
1614 (RemainingLoopCount == Other.RemainingLoopCount) &&
1615 (Done == Other.Done);
1618 iterator_range<rebase_iterator>
1619 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1620 MachORebaseEntry Start(Opcodes, is64);
1621 Start.moveToFirst();
1623 MachORebaseEntry Finish(Opcodes, is64);
1626 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1627 rebase_iterator(Finish));
1630 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1631 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1635 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1637 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1638 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1639 BindType(0), PointerSize(is64Bit ? 8 : 4),
1640 TableKind(BK), Malformed(false), Done(false) {}
1642 void MachOBindEntry::moveToFirst() {
1643 Ptr = Opcodes.begin();
1647 void MachOBindEntry::moveToEnd() {
1648 Ptr = Opcodes.end();
1649 RemainingLoopCount = 0;
1653 void MachOBindEntry::moveNext() {
1654 // If in the middle of some loop, move to next binding in loop.
1655 SegmentOffset += AdvanceAmount;
1656 if (RemainingLoopCount) {
1657 --RemainingLoopCount;
1660 if (Ptr == Opcodes.end()) {
1665 while (More && !Malformed) {
1666 // Parse next opcode and set up next loop.
1667 uint8_t Byte = *Ptr++;
1668 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1669 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1670 int8_t SignExtended;
1671 const uint8_t *SymStart;
1673 case MachO::BIND_OPCODE_DONE:
1674 if (TableKind == Kind::Lazy) {
1675 // Lazying bindings have a DONE opcode between entries. Need to ignore
1676 // it to advance to next entry. But need not if this is last entry.
1677 bool NotLastEntry = false;
1678 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1680 NotLastEntry = true;
1689 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1691 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1695 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1696 << "Ordinal=" << Ordinal << "\n");
1698 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1699 Ordinal = readULEB128();
1702 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1703 << "Ordinal=" << Ordinal << "\n");
1705 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1707 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1708 Ordinal = SignExtended;
1713 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1714 << "Ordinal=" << Ordinal << "\n");
1716 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1722 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1727 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1728 << "SymbolName=" << SymbolName << "\n");
1729 if (TableKind == Kind::Weak) {
1730 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1734 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1735 BindType = ImmValue;
1738 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1739 << "BindType=" << (int)BindType << "\n");
1741 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1742 Addend = readSLEB128();
1743 if (TableKind == Kind::Lazy)
1747 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1748 << "Addend=" << Addend << "\n");
1750 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1751 SegmentIndex = ImmValue;
1752 SegmentOffset = readULEB128();
1755 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1756 << "SegmentIndex=" << SegmentIndex << ", "
1757 << format("SegmentOffset=0x%06X", SegmentOffset)
1760 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1761 SegmentOffset += readULEB128();
1762 DEBUG_WITH_TYPE("mach-o-bind",
1763 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1764 << format("SegmentOffset=0x%06X",
1765 SegmentOffset) << "\n");
1767 case MachO::BIND_OPCODE_DO_BIND:
1768 AdvanceAmount = PointerSize;
1769 RemainingLoopCount = 0;
1770 DEBUG_WITH_TYPE("mach-o-bind",
1771 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1772 << format("SegmentOffset=0x%06X",
1773 SegmentOffset) << "\n");
1775 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1776 AdvanceAmount = readULEB128() + PointerSize;
1777 RemainingLoopCount = 0;
1778 if (TableKind == Kind::Lazy)
1782 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1783 << format("SegmentOffset=0x%06X", SegmentOffset)
1784 << ", AdvanceAmount=" << AdvanceAmount
1785 << ", RemainingLoopCount=" << RemainingLoopCount
1788 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1789 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1790 RemainingLoopCount = 0;
1791 if (TableKind == Kind::Lazy)
1793 DEBUG_WITH_TYPE("mach-o-bind",
1795 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1796 << format("SegmentOffset=0x%06X",
1797 SegmentOffset) << "\n");
1799 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1800 RemainingLoopCount = readULEB128() - 1;
1801 AdvanceAmount = readULEB128() + PointerSize;
1802 if (TableKind == Kind::Lazy)
1806 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1807 << format("SegmentOffset=0x%06X", SegmentOffset)
1808 << ", AdvanceAmount=" << AdvanceAmount
1809 << ", RemainingLoopCount=" << RemainingLoopCount
1818 uint64_t MachOBindEntry::readULEB128() {
1820 uint64_t Result = decodeULEB128(Ptr, &Count);
1822 if (Ptr > Opcodes.end()) {
1823 Ptr = Opcodes.end();
1829 int64_t MachOBindEntry::readSLEB128() {
1831 int64_t Result = decodeSLEB128(Ptr, &Count);
1833 if (Ptr > Opcodes.end()) {
1834 Ptr = Opcodes.end();
1841 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1843 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1845 StringRef MachOBindEntry::typeName() const {
1847 case MachO::BIND_TYPE_POINTER:
1849 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1850 return "text abs32";
1851 case MachO::BIND_TYPE_TEXT_PCREL32:
1852 return "text rel32";
1857 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1859 int64_t MachOBindEntry::addend() const { return Addend; }
1861 uint32_t MachOBindEntry::flags() const { return Flags; }
1863 int MachOBindEntry::ordinal() const { return Ordinal; }
1865 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1866 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1867 return (Ptr == Other.Ptr) &&
1868 (RemainingLoopCount == Other.RemainingLoopCount) &&
1869 (Done == Other.Done);
1872 iterator_range<bind_iterator>
1873 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1874 MachOBindEntry::Kind BKind) {
1875 MachOBindEntry Start(Opcodes, is64, BKind);
1876 Start.moveToFirst();
1878 MachOBindEntry Finish(Opcodes, is64, BKind);
1881 return iterator_range<bind_iterator>(bind_iterator(Start),
1882 bind_iterator(Finish));
1885 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1886 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1887 MachOBindEntry::Kind::Regular);
1890 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1891 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1892 MachOBindEntry::Kind::Lazy);
1895 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1896 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1897 MachOBindEntry::Kind::Weak);
1900 MachOObjectFile::load_command_iterator
1901 MachOObjectFile::begin_load_commands() const {
1902 return LoadCommands.begin();
1905 MachOObjectFile::load_command_iterator
1906 MachOObjectFile::end_load_commands() const {
1907 return LoadCommands.end();
1910 iterator_range<MachOObjectFile::load_command_iterator>
1911 MachOObjectFile::load_commands() const {
1912 return iterator_range<load_command_iterator>(begin_load_commands(),
1913 end_load_commands());
1917 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1918 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1919 return parseSegmentOrSectionName(Raw.data());
1923 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1924 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1925 const section_base *Base =
1926 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1927 return makeArrayRef(Base->sectname);
1931 MachOObjectFile::getSectionRawFinalSegmentName(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->segname);
1939 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1941 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1943 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1946 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1947 const MachO::any_relocation_info &RE) const {
1948 if (isLittleEndian())
1949 return RE.r_word1 & 0xffffff;
1950 return RE.r_word1 >> 8;
1953 bool MachOObjectFile::getPlainRelocationExternal(
1954 const MachO::any_relocation_info &RE) const {
1955 if (isLittleEndian())
1956 return (RE.r_word1 >> 27) & 1;
1957 return (RE.r_word1 >> 4) & 1;
1960 bool MachOObjectFile::getScatteredRelocationScattered(
1961 const MachO::any_relocation_info &RE) const {
1962 return RE.r_word0 >> 31;
1965 uint32_t MachOObjectFile::getScatteredRelocationValue(
1966 const MachO::any_relocation_info &RE) const {
1970 uint32_t MachOObjectFile::getScatteredRelocationType(
1971 const MachO::any_relocation_info &RE) const {
1972 return (RE.r_word0 >> 24) & 0xf;
1975 unsigned MachOObjectFile::getAnyRelocationAddress(
1976 const MachO::any_relocation_info &RE) const {
1977 if (isRelocationScattered(RE))
1978 return getScatteredRelocationAddress(RE);
1979 return getPlainRelocationAddress(RE);
1982 unsigned MachOObjectFile::getAnyRelocationPCRel(
1983 const MachO::any_relocation_info &RE) const {
1984 if (isRelocationScattered(RE))
1985 return getScatteredRelocationPCRel(this, RE);
1986 return getPlainRelocationPCRel(this, RE);
1989 unsigned MachOObjectFile::getAnyRelocationLength(
1990 const MachO::any_relocation_info &RE) const {
1991 if (isRelocationScattered(RE))
1992 return getScatteredRelocationLength(RE);
1993 return getPlainRelocationLength(this, RE);
1997 MachOObjectFile::getAnyRelocationType(
1998 const MachO::any_relocation_info &RE) const {
1999 if (isRelocationScattered(RE))
2000 return getScatteredRelocationType(RE);
2001 return getPlainRelocationType(this, RE);
2005 MachOObjectFile::getAnyRelocationSection(
2006 const MachO::any_relocation_info &RE) const {
2007 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2008 return *section_end();
2009 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2010 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2011 return *section_end();
2013 DRI.d.a = SecNum - 1;
2014 return SectionRef(DRI, this);
2017 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2018 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2019 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2022 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2023 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2024 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2027 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2028 unsigned Index) const {
2029 const char *Sec = getSectionPtr(this, L, Index);
2030 return getStruct<MachO::section>(this, Sec);
2033 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2034 unsigned Index) const {
2035 const char *Sec = getSectionPtr(this, L, Index);
2036 return getStruct<MachO::section_64>(this, Sec);
2040 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2041 const char *P = reinterpret_cast<const char *>(DRI.p);
2042 return getStruct<MachO::nlist>(this, P);
2046 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2047 const char *P = reinterpret_cast<const char *>(DRI.p);
2048 return getStruct<MachO::nlist_64>(this, P);
2051 MachO::linkedit_data_command
2052 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2056 MachO::segment_command
2057 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::segment_command>(this, L.Ptr);
2061 MachO::segment_command_64
2062 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2063 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2066 MachO::linker_option_command
2067 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2071 MachO::version_min_command
2072 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2073 return getStruct<MachO::version_min_command>(this, L.Ptr);
2076 MachO::dylib_command
2077 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2078 return getStruct<MachO::dylib_command>(this, L.Ptr);
2081 MachO::dyld_info_command
2082 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2083 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2086 MachO::dylinker_command
2087 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2088 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2092 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2093 return getStruct<MachO::uuid_command>(this, L.Ptr);
2096 MachO::rpath_command
2097 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2098 return getStruct<MachO::rpath_command>(this, L.Ptr);
2101 MachO::source_version_command
2102 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2103 return getStruct<MachO::source_version_command>(this, L.Ptr);
2106 MachO::entry_point_command
2107 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2108 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2111 MachO::encryption_info_command
2112 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2113 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2116 MachO::encryption_info_command_64
2117 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2118 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2121 MachO::sub_framework_command
2122 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2123 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2126 MachO::sub_umbrella_command
2127 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2128 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2131 MachO::sub_library_command
2132 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2133 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2136 MachO::sub_client_command
2137 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2138 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2141 MachO::routines_command
2142 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2143 return getStruct<MachO::routines_command>(this, L.Ptr);
2146 MachO::routines_command_64
2147 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2148 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2151 MachO::thread_command
2152 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2153 return getStruct<MachO::thread_command>(this, L.Ptr);
2156 MachO::any_relocation_info
2157 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2162 MachO::section_64 Sect = getSection64(Sec);
2163 Offset = Sect.reloff;
2165 MachO::section Sect = getSection(Sec);
2166 Offset = Sect.reloff;
2169 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2170 getPtr(this, Offset)) + Rel.d.b;
2171 return getStruct<MachO::any_relocation_info>(
2172 this, reinterpret_cast<const char *>(P));
2175 MachO::data_in_code_entry
2176 MachOObjectFile::getDice(DataRefImpl Rel) const {
2177 const char *P = reinterpret_cast<const char *>(Rel.p);
2178 return getStruct<MachO::data_in_code_entry>(this, P);
2181 const MachO::mach_header &MachOObjectFile::getHeader() const {
2185 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2190 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2191 const MachO::dysymtab_command &DLC,
2192 unsigned Index) const {
2193 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2194 return getStruct<uint32_t>(this, getPtr(this, Offset));
2197 MachO::data_in_code_entry
2198 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2199 unsigned Index) const {
2200 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2201 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2204 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2206 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2208 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2209 MachO::symtab_command Cmd;
2210 Cmd.cmd = MachO::LC_SYMTAB;
2211 Cmd.cmdsize = sizeof(MachO::symtab_command);
2219 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2220 if (DysymtabLoadCmd)
2221 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2223 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2224 MachO::dysymtab_command Cmd;
2225 Cmd.cmd = MachO::LC_DYSYMTAB;
2226 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2237 Cmd.extrefsymoff = 0;
2238 Cmd.nextrefsyms = 0;
2239 Cmd.indirectsymoff = 0;
2240 Cmd.nindirectsyms = 0;
2248 MachO::linkedit_data_command
2249 MachOObjectFile::getDataInCodeLoadCommand() const {
2250 if (DataInCodeLoadCmd)
2251 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2253 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2254 MachO::linkedit_data_command Cmd;
2255 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2256 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2262 MachO::linkedit_data_command
2263 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2264 if (LinkOptHintsLoadCmd)
2265 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2267 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2269 MachO::linkedit_data_command Cmd;
2270 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2271 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2277 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2278 if (!DyldInfoLoadCmd)
2279 return ArrayRef<uint8_t>();
2281 MachO::dyld_info_command DyldInfo
2282 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2283 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2284 getPtr(this, DyldInfo.rebase_off));
2285 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2288 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2289 if (!DyldInfoLoadCmd)
2290 return ArrayRef<uint8_t>();
2292 MachO::dyld_info_command DyldInfo
2293 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2294 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2295 getPtr(this, DyldInfo.bind_off));
2296 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2299 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2300 if (!DyldInfoLoadCmd)
2301 return ArrayRef<uint8_t>();
2303 MachO::dyld_info_command DyldInfo
2304 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2305 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2306 getPtr(this, DyldInfo.weak_bind_off));
2307 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2310 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2311 if (!DyldInfoLoadCmd)
2312 return ArrayRef<uint8_t>();
2314 MachO::dyld_info_command DyldInfo
2315 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2316 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2317 getPtr(this, DyldInfo.lazy_bind_off));
2318 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2321 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2322 if (!DyldInfoLoadCmd)
2323 return ArrayRef<uint8_t>();
2325 MachO::dyld_info_command DyldInfo
2326 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2327 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2328 getPtr(this, DyldInfo.export_off));
2329 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2332 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2334 return ArrayRef<uint8_t>();
2335 // Returning a pointer is fine as uuid doesn't need endian swapping.
2336 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2337 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2340 StringRef MachOObjectFile::getStringTableData() const {
2341 MachO::symtab_command S = getSymtabLoadCommand();
2342 return getData().substr(S.stroff, S.strsize);
2345 bool MachOObjectFile::is64Bit() const {
2346 return getType() == getMachOType(false, true) ||
2347 getType() == getMachOType(true, true);
2350 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2351 SmallVectorImpl<uint64_t> &Out) const {
2352 DataExtractor extractor(ObjectFile::getData(), true, 0);
2354 uint32_t offset = Index;
2356 while (uint64_t delta = extractor.getULEB128(&offset)) {
2358 Out.push_back(data);
2362 bool MachOObjectFile::isRelocatableObject() const {
2363 return getHeader().filetype == MachO::MH_OBJECT;
2366 ErrorOr<std::unique_ptr<MachOObjectFile>>
2367 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2368 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2370 std::unique_ptr<MachOObjectFile> Ret;
2371 if (Magic == "\xFE\xED\xFA\xCE")
2372 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2373 else if (Magic == "\xCE\xFA\xED\xFE")
2374 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2375 else if (Magic == "\xFE\xED\xFA\xCF")
2376 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2377 else if (Magic == "\xCF\xFA\xED\xFE")
2378 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2380 return object_error::parse_failed;
2384 return std::move(Ret);