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);
68 template <typename SegmentCmd>
69 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
71 const unsigned SectionSize = sizeof(SegmentCmd);
72 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
73 S.nsects * SectionSize > Cmdsize - sizeof(S))
75 "Number of sections too large for size of load command.");
80 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
81 const MachOObjectFile::LoadCommandInfo &L) {
83 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
86 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
90 static bool isPageZeroSegment(const MachOObjectFile *O,
91 const MachOObjectFile::LoadCommandInfo &L) {
93 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
94 return StringRef("__PAGEZERO").equals(S.segname);
96 MachO::segment_command S = O->getSegmentLoadCommand(L);
97 return StringRef("__PAGEZERO").equals(S.segname);
102 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
104 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
106 bool Is64 = O->is64Bit();
107 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
108 sizeof(MachO::segment_command);
109 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
110 sizeof(MachO::section);
112 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
113 return reinterpret_cast<const char*>(SectionAddr);
116 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
117 return O->getData().substr(Offset, 1).data();
120 static MachO::nlist_base
121 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
122 const char *P = reinterpret_cast<const char *>(DRI.p);
123 return getStruct<MachO::nlist_base>(O, P);
126 static StringRef parseSegmentOrSectionName(const char *P) {
130 // Not null terminated, so this is a 16 char string.
131 return StringRef(P, 16);
134 // Helper to advance a section or symbol iterator multiple increments at a time.
136 static void advance(T &it, size_t Val) {
141 static unsigned getCPUType(const MachOObjectFile *O) {
142 return O->getHeader().cputype;
146 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
151 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
152 return RE.r_word0 & 0xffffff;
155 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
156 const MachO::any_relocation_info &RE) {
157 if (O->isLittleEndian())
158 return (RE.r_word1 >> 24) & 1;
159 return (RE.r_word1 >> 7) & 1;
163 getScatteredRelocationPCRel(const MachOObjectFile *O,
164 const MachO::any_relocation_info &RE) {
165 return (RE.r_word0 >> 30) & 1;
168 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
169 const MachO::any_relocation_info &RE) {
170 if (O->isLittleEndian())
171 return (RE.r_word1 >> 25) & 3;
172 return (RE.r_word1 >> 5) & 3;
176 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
177 return (RE.r_word0 >> 28) & 3;
180 static unsigned getPlainRelocationType(const MachOObjectFile *O,
181 const MachO::any_relocation_info &RE) {
182 if (O->isLittleEndian())
183 return RE.r_word1 >> 28;
184 return RE.r_word1 & 0xf;
187 static uint32_t getSectionFlags(const MachOObjectFile *O,
190 MachO::section_64 Sect = O->getSection64(Sec);
193 MachO::section Sect = O->getSection(Sec);
197 static ErrorOr<MachOObjectFile::LoadCommandInfo>
198 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
199 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
201 return CmdOrErr.getError();
202 if (CmdOrErr->cmdsize < 8)
203 return object_error::macho_small_load_command;
204 MachOObjectFile::LoadCommandInfo Load;
206 Load.C = CmdOrErr.get();
210 static ErrorOr<MachOObjectFile::LoadCommandInfo>
211 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
212 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
213 : sizeof(MachO::mach_header);
214 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
217 static ErrorOr<MachOObjectFile::LoadCommandInfo>
218 getNextLoadCommandInfo(const MachOObjectFile *Obj,
219 const MachOObjectFile::LoadCommandInfo &L) {
220 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
223 template <typename T>
224 static void parseHeader(const MachOObjectFile *Obj, T &Header,
225 std::error_code &EC) {
226 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
228 Header = HeaderOrErr.get();
230 EC = HeaderOrErr.getError();
233 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
234 bool Is64bits, std::error_code &EC)
235 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
236 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
237 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
238 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
239 HasPageZeroSegment(false) {
241 parseHeader(this, Header64, EC);
243 // First fields of MachO::mach_header_64 are the same as
244 // in MachO::mach_header.
245 parseHeader(this, *reinterpret_cast<MachO::mach_header *>(&this->Header64),
250 uint32_t LoadCommandCount = getHeader().ncmds;
251 if (LoadCommandCount == 0)
254 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
255 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
257 auto LoadOrErr = getFirstLoadCommandInfo(this);
259 EC = LoadOrErr.getError();
262 LoadCommandInfo Load = LoadOrErr.get();
263 for (unsigned I = 0; I < LoadCommandCount; ++I) {
264 LoadCommands.push_back(Load);
265 if (Load.C.cmd == MachO::LC_SYMTAB) {
266 // Multiple symbol tables
268 EC = object_error::parse_failed;
271 SymtabLoadCmd = Load.Ptr;
272 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
273 // Multiple dynamic symbol tables
274 if (DysymtabLoadCmd) {
275 EC = object_error::parse_failed;
278 DysymtabLoadCmd = Load.Ptr;
279 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
280 // Multiple data in code tables
281 if (DataInCodeLoadCmd) {
282 EC = object_error::parse_failed;
285 DataInCodeLoadCmd = Load.Ptr;
286 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
287 // Multiple linker optimization hint tables
288 if (LinkOptHintsLoadCmd) {
289 EC = object_error::parse_failed;
292 LinkOptHintsLoadCmd = Load.Ptr;
293 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
294 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
295 // Multiple dyldinfo load commands
296 if (DyldInfoLoadCmd) {
297 EC = object_error::parse_failed;
300 DyldInfoLoadCmd = Load.Ptr;
301 } else if (Load.C.cmd == MachO::LC_UUID) {
302 // Multiple UUID load commands
304 EC = object_error::parse_failed;
307 UuidLoadCmd = Load.Ptr;
308 } else if (Load.C.cmd == SegmentLoadType) {
309 const unsigned SegmentLoadSize = this->is64Bit()
310 ? sizeof(MachO::segment_command_64)
311 : sizeof(MachO::segment_command);
312 if (Load.C.cmdsize < SegmentLoadSize)
313 report_fatal_error("Segment load command size is too small.");
315 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
316 for (unsigned J = 0; J < NumSections; ++J) {
317 const char *Sec = getSectionPtr(this, Load, J);
318 Sections.push_back(Sec);
320 if (isPageZeroSegment(this, Load))
321 HasPageZeroSegment = true;
322 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
324 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
325 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
326 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
327 Libraries.push_back(Load.Ptr);
329 if (I < LoadCommandCount - 1) {
330 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
332 EC = LoadOrErr.getError();
335 Load = LoadOrErr.get();
338 assert(LoadCommands.size() == LoadCommandCount);
341 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
342 unsigned SymbolTableEntrySize = is64Bit() ?
343 sizeof(MachO::nlist_64) :
344 sizeof(MachO::nlist);
345 Symb.p += SymbolTableEntrySize;
348 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
349 StringRef &Res) const {
350 StringRef StringTable = getStringTableData();
351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
352 const char *Start = &StringTable.data()[Entry.n_strx];
353 if (Start < getData().begin() || Start >= getData().end())
355 "Symbol name entry points before beginning or past end of file.");
356 Res = StringRef(Start);
357 return object_error::success;
360 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
361 DataRefImpl DRI = Sec.getRawDataRefImpl();
362 uint32_t Flags = getSectionFlags(this, DRI);
363 return Flags & MachO::SECTION_TYPE;
366 // getIndirectName() returns the name of the alias'ed symbol who's string table
367 // index is in the n_value field.
368 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
369 StringRef &Res) const {
370 StringRef StringTable = getStringTableData();
373 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
374 NValue = Entry.n_value;
375 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
376 return object_error::parse_failed;
378 MachO::nlist Entry = getSymbolTableEntry(Symb);
379 NValue = Entry.n_value;
380 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
381 return object_error::parse_failed;
383 if (NValue >= StringTable.size())
384 return object_error::parse_failed;
385 const char *Start = &StringTable.data()[NValue];
386 Res = StringRef(Start);
387 return object_error::success;
390 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
391 uint64_t &Res) const {
393 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
394 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
396 Res = UnknownAddressOrSize;
400 MachO::nlist Entry = getSymbolTableEntry(Symb);
401 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
403 Res = UnknownAddressOrSize;
407 return object_error::success;
410 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
411 uint32_t flags = getSymbolFlags(DRI);
412 if (flags & SymbolRef::SF_Common) {
413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
414 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
419 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
421 getSymbolAddress(DRI, Value);
422 uint32_t flags = getSymbolFlags(DRI);
423 if (flags & SymbolRef::SF_Common)
425 return UnknownAddressOrSize;
428 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
429 SymbolRef::Type &Res) const {
430 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
431 uint8_t n_type = Entry.n_type;
433 Res = SymbolRef::ST_Other;
435 // If this is a STAB debugging symbol, we can do nothing more.
436 if (n_type & MachO::N_STAB) {
437 Res = SymbolRef::ST_Debug;
438 return object_error::success;
441 switch (n_type & MachO::N_TYPE) {
443 Res = SymbolRef::ST_Unknown;
446 Res = SymbolRef::ST_Function;
449 return object_error::success;
452 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
453 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
455 uint8_t MachOType = Entry.n_type;
456 uint16_t MachOFlags = Entry.n_desc;
458 uint32_t Result = SymbolRef::SF_None;
460 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
461 Result |= SymbolRef::SF_Undefined;
463 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
464 Result |= SymbolRef::SF_Indirect;
466 if (MachOType & MachO::N_STAB)
467 Result |= SymbolRef::SF_FormatSpecific;
469 if (MachOType & MachO::N_EXT) {
470 Result |= SymbolRef::SF_Global;
471 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
473 getSymbolAddress(DRI, Value);
474 if (Value && Value != UnknownAddressOrSize)
475 Result |= SymbolRef::SF_Common;
478 if (!(MachOType & MachO::N_PEXT))
479 Result |= SymbolRef::SF_Exported;
482 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
483 Result |= SymbolRef::SF_Weak;
485 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
486 Result |= SymbolRef::SF_Thumb;
488 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
489 Result |= SymbolRef::SF_Absolute;
494 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
495 section_iterator &Res) const {
496 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
497 uint8_t index = Entry.n_sect;
504 if (DRI.d.a >= Sections.size())
505 report_fatal_error("getSymbolSection: Invalid section index.");
506 Res = section_iterator(SectionRef(DRI, this));
509 return object_error::success;
512 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
516 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
517 StringRef &Result) const {
518 ArrayRef<char> Raw = getSectionRawName(Sec);
519 Result = parseSegmentOrSectionName(Raw.data());
520 return object_error::success;
523 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
525 return getSection64(Sec).addr;
526 return getSection(Sec).addr;
529 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
531 return getSection64(Sec).size;
532 return getSection(Sec).size;
535 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
536 StringRef &Res) const {
541 MachO::section_64 Sect = getSection64(Sec);
542 Offset = Sect.offset;
545 MachO::section Sect = getSection(Sec);
546 Offset = Sect.offset;
550 Res = this->getData().substr(Offset, Size);
551 return object_error::success;
554 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
557 MachO::section_64 Sect = getSection64(Sec);
560 MachO::section Sect = getSection(Sec);
564 return uint64_t(1) << Align;
567 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
568 uint32_t Flags = getSectionFlags(this, Sec);
569 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
572 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
573 uint32_t Flags = getSectionFlags(this, Sec);
574 unsigned SectionType = Flags & MachO::SECTION_TYPE;
575 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
576 !(SectionType == MachO::S_ZEROFILL ||
577 SectionType == MachO::S_GB_ZEROFILL);
580 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
581 uint32_t Flags = getSectionFlags(this, Sec);
582 unsigned SectionType = Flags & MachO::SECTION_TYPE;
583 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
584 (SectionType == MachO::S_ZEROFILL ||
585 SectionType == MachO::S_GB_ZEROFILL);
588 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
589 // FIXME: Unimplemented.
593 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
594 DataRefImpl Symb) const {
596 this->getSymbolType(Symb, ST);
597 if (ST == SymbolRef::ST_Unknown)
600 uint64_t SectBegin = getSectionAddress(Sec);
601 uint64_t SectEnd = getSectionSize(Sec);
602 SectEnd += SectBegin;
605 getSymbolAddress(Symb, SymAddr);
606 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
609 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
613 return relocation_iterator(RelocationRef(Ret, this));
617 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
620 MachO::section_64 Sect = getSection64(Sec);
623 MachO::section Sect = getSection(Sec);
630 return relocation_iterator(RelocationRef(Ret, this));
633 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
637 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
638 uint64_t &Res) const {
640 getRelocationOffset(Rel, Offset);
644 uint64_t SecAddress = getSectionAddress(Sec);
645 Res = SecAddress + Offset;
646 return object_error::success;
649 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
650 uint64_t &Res) const {
651 assert(getHeader().filetype == MachO::MH_OBJECT &&
652 "Only implemented for MH_OBJECT");
653 MachO::any_relocation_info RE = getRelocation(Rel);
654 Res = getAnyRelocationAddress(RE);
655 return object_error::success;
659 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
660 MachO::any_relocation_info RE = getRelocation(Rel);
661 if (isRelocationScattered(RE))
664 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
665 bool isExtern = getPlainRelocationExternal(RE);
669 MachO::symtab_command S = getSymtabLoadCommand();
670 unsigned SymbolTableEntrySize = is64Bit() ?
671 sizeof(MachO::nlist_64) :
672 sizeof(MachO::nlist);
673 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
675 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
676 return symbol_iterator(SymbolRef(Sym, this));
680 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
681 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
684 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
685 uint64_t &Res) const {
686 MachO::any_relocation_info RE = getRelocation(Rel);
687 Res = getAnyRelocationType(RE);
688 return object_error::success;
692 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
693 SmallVectorImpl<char> &Result) const {
696 getRelocationType(Rel, RType);
698 unsigned Arch = this->getArch();
702 static const char *const Table[] = {
703 "GENERIC_RELOC_VANILLA",
704 "GENERIC_RELOC_PAIR",
705 "GENERIC_RELOC_SECTDIFF",
706 "GENERIC_RELOC_PB_LA_PTR",
707 "GENERIC_RELOC_LOCAL_SECTDIFF",
708 "GENERIC_RELOC_TLV" };
716 case Triple::x86_64: {
717 static const char *const Table[] = {
718 "X86_64_RELOC_UNSIGNED",
719 "X86_64_RELOC_SIGNED",
720 "X86_64_RELOC_BRANCH",
721 "X86_64_RELOC_GOT_LOAD",
723 "X86_64_RELOC_SUBTRACTOR",
724 "X86_64_RELOC_SIGNED_1",
725 "X86_64_RELOC_SIGNED_2",
726 "X86_64_RELOC_SIGNED_4",
727 "X86_64_RELOC_TLV" };
736 static const char *const Table[] = {
739 "ARM_RELOC_SECTDIFF",
740 "ARM_RELOC_LOCAL_SECTDIFF",
741 "ARM_RELOC_PB_LA_PTR",
743 "ARM_THUMB_RELOC_BR22",
744 "ARM_THUMB_32BIT_BRANCH",
746 "ARM_RELOC_HALF_SECTDIFF" };
754 case Triple::aarch64: {
755 static const char *const Table[] = {
756 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
757 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
758 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
759 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
760 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
764 if (RType >= array_lengthof(Table))
771 static const char *const Table[] = {
780 "PPC_RELOC_SECTDIFF",
781 "PPC_RELOC_PB_LA_PTR",
782 "PPC_RELOC_HI16_SECTDIFF",
783 "PPC_RELOC_LO16_SECTDIFF",
784 "PPC_RELOC_HA16_SECTDIFF",
786 "PPC_RELOC_LO14_SECTDIFF",
787 "PPC_RELOC_LOCAL_SECTDIFF" };
795 case Triple::UnknownArch:
799 Result.append(res.begin(), res.end());
800 return object_error::success;
803 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
804 bool &Result) const {
805 unsigned Arch = getArch();
807 getRelocationType(Rel, Type);
811 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
813 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
814 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
815 } else if (Arch == Triple::x86_64) {
816 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
817 // an X86_64_RELOC_SUBTRACTOR.
818 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
819 DataRefImpl RelPrev = Rel;
822 getRelocationType(RelPrev, PrevType);
823 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
828 return object_error::success;
831 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
832 MachO::any_relocation_info RE = getRelocation(Rel);
833 return getAnyRelocationLength(RE);
837 // guessLibraryShortName() is passed a name of a dynamic library and returns a
838 // guess on what the short name is. Then name is returned as a substring of the
839 // StringRef Name passed in. The name of the dynamic library is recognized as
840 // a framework if it has one of the two following forms:
841 // Foo.framework/Versions/A/Foo
843 // Where A and Foo can be any string. And may contain a trailing suffix
844 // starting with an underbar. If the Name is recognized as a framework then
845 // isFramework is set to true else it is set to false. If the Name has a
846 // suffix then Suffix is set to the substring in Name that contains the suffix
847 // else it is set to a NULL StringRef.
849 // The Name of the dynamic library is recognized as a library name if it has
850 // one of the two following forms:
853 // The library may have a suffix trailing the name Foo of the form:
854 // libFoo_profile.A.dylib
855 // libFoo_profile.dylib
857 // The Name of the dynamic library is also recognized as a library name if it
858 // has the following form:
861 // If the Name of the dynamic library is none of the forms above then a NULL
862 // StringRef is returned.
864 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
867 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
868 size_t a, b, c, d, Idx;
871 Suffix = StringRef();
873 // Pull off the last component and make Foo point to it
875 if (a == Name.npos || a == 0)
877 Foo = Name.slice(a+1, Name.npos);
879 // Look for a suffix starting with a '_'
880 Idx = Foo.rfind('_');
881 if (Idx != Foo.npos && Foo.size() >= 2) {
882 Suffix = Foo.slice(Idx, Foo.npos);
883 Foo = Foo.slice(0, Idx);
886 // First look for the form Foo.framework/Foo
887 b = Name.rfind('/', a);
892 F = Name.slice(Idx, Idx + Foo.size());
893 DotFramework = Name.slice(Idx + Foo.size(),
894 Idx + Foo.size() + sizeof(".framework/")-1);
895 if (F == Foo && DotFramework == ".framework/") {
900 // Next look for the form Foo.framework/Versions/A/Foo
903 c = Name.rfind('/', b);
904 if (c == Name.npos || c == 0)
906 V = Name.slice(c+1, Name.npos);
907 if (!V.startswith("Versions/"))
909 d = Name.rfind('/', c);
914 F = Name.slice(Idx, Idx + Foo.size());
915 DotFramework = Name.slice(Idx + Foo.size(),
916 Idx + Foo.size() + sizeof(".framework/")-1);
917 if (F == Foo && DotFramework == ".framework/") {
923 // pull off the suffix after the "." and make a point to it
925 if (a == Name.npos || a == 0)
927 Dylib = Name.slice(a, Name.npos);
928 if (Dylib != ".dylib")
931 // First pull off the version letter for the form Foo.A.dylib if any.
933 Dot = Name.slice(a-2, a-1);
938 b = Name.rfind('/', a);
943 // ignore any suffix after an underbar like Foo_profile.A.dylib
944 Idx = Name.find('_', b);
945 if (Idx != Name.npos && Idx != b) {
946 Lib = Name.slice(b, Idx);
947 Suffix = Name.slice(Idx, a);
950 Lib = Name.slice(b, a);
951 // There are incorrect library names of the form:
952 // libATS.A_profile.dylib so check for these.
953 if (Lib.size() >= 3) {
954 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
956 Lib = Lib.slice(0, Lib.size()-2);
961 Qtx = Name.slice(a, Name.npos);
964 b = Name.rfind('/', a);
966 Lib = Name.slice(0, a);
968 Lib = Name.slice(b+1, a);
969 // There are library names of the form: QT.A.qtx so check for these.
970 if (Lib.size() >= 3) {
971 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
973 Lib = Lib.slice(0, Lib.size()-2);
978 // getLibraryShortNameByIndex() is used to get the short name of the library
979 // for an undefined symbol in a linked Mach-O binary that was linked with the
980 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
981 // It is passed the index (0 - based) of the library as translated from
982 // GET_LIBRARY_ORDINAL (1 - based).
983 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
984 StringRef &Res) const {
985 if (Index >= Libraries.size())
986 return object_error::parse_failed;
988 // If the cache of LibrariesShortNames is not built up do that first for
989 // all the Libraries.
990 if (LibrariesShortNames.size() == 0) {
991 for (unsigned i = 0; i < Libraries.size(); i++) {
992 MachO::dylib_command D =
993 getStruct<MachO::dylib_command>(this, Libraries[i]);
994 if (D.dylib.name >= D.cmdsize)
995 return object_error::parse_failed;
996 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
997 StringRef Name = StringRef(P);
998 if (D.dylib.name+Name.size() >= D.cmdsize)
999 return object_error::parse_failed;
1002 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1003 if (shortName.empty())
1004 LibrariesShortNames.push_back(Name);
1006 LibrariesShortNames.push_back(shortName);
1010 Res = LibrariesShortNames[Index];
1011 return object_error::success;
1014 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1015 return getSymbolByIndex(0);
1018 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1021 return basic_symbol_iterator(SymbolRef(DRI, this));
1023 MachO::symtab_command Symtab = getSymtabLoadCommand();
1024 unsigned SymbolTableEntrySize = is64Bit() ?
1025 sizeof(MachO::nlist_64) :
1026 sizeof(MachO::nlist);
1027 unsigned Offset = Symtab.symoff +
1028 Symtab.nsyms * SymbolTableEntrySize;
1029 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1030 return basic_symbol_iterator(SymbolRef(DRI, this));
1033 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1036 return basic_symbol_iterator(SymbolRef(DRI, this));
1038 MachO::symtab_command Symtab = getSymtabLoadCommand();
1039 if (Index >= Symtab.nsyms)
1040 report_fatal_error("Requested symbol index is out of range.");
1041 unsigned SymbolTableEntrySize =
1042 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1043 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1044 DRI.p += Index * SymbolTableEntrySize;
1045 return basic_symbol_iterator(SymbolRef(DRI, this));
1048 section_iterator MachOObjectFile::section_begin() const {
1050 return section_iterator(SectionRef(DRI, this));
1053 section_iterator MachOObjectFile::section_end() const {
1055 DRI.d.a = Sections.size();
1056 return section_iterator(SectionRef(DRI, this));
1059 uint8_t MachOObjectFile::getBytesInAddress() const {
1060 return is64Bit() ? 8 : 4;
1063 StringRef MachOObjectFile::getFileFormatName() const {
1064 unsigned CPUType = getCPUType(this);
1067 case llvm::MachO::CPU_TYPE_I386:
1068 return "Mach-O 32-bit i386";
1069 case llvm::MachO::CPU_TYPE_ARM:
1070 return "Mach-O arm";
1071 case llvm::MachO::CPU_TYPE_POWERPC:
1072 return "Mach-O 32-bit ppc";
1074 return "Mach-O 32-bit unknown";
1079 case llvm::MachO::CPU_TYPE_X86_64:
1080 return "Mach-O 64-bit x86-64";
1081 case llvm::MachO::CPU_TYPE_ARM64:
1082 return "Mach-O arm64";
1083 case llvm::MachO::CPU_TYPE_POWERPC64:
1084 return "Mach-O 64-bit ppc64";
1086 return "Mach-O 64-bit unknown";
1090 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1092 case llvm::MachO::CPU_TYPE_I386:
1094 case llvm::MachO::CPU_TYPE_X86_64:
1095 return Triple::x86_64;
1096 case llvm::MachO::CPU_TYPE_ARM:
1098 case llvm::MachO::CPU_TYPE_ARM64:
1099 return Triple::aarch64;
1100 case llvm::MachO::CPU_TYPE_POWERPC:
1102 case llvm::MachO::CPU_TYPE_POWERPC64:
1103 return Triple::ppc64;
1105 return Triple::UnknownArch;
1109 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1110 const char **McpuDefault) {
1112 *McpuDefault = nullptr;
1115 case MachO::CPU_TYPE_I386:
1116 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1117 case MachO::CPU_SUBTYPE_I386_ALL:
1118 return Triple("i386-apple-darwin");
1122 case MachO::CPU_TYPE_X86_64:
1123 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1124 case MachO::CPU_SUBTYPE_X86_64_ALL:
1125 return Triple("x86_64-apple-darwin");
1126 case MachO::CPU_SUBTYPE_X86_64_H:
1127 return Triple("x86_64h-apple-darwin");
1131 case MachO::CPU_TYPE_ARM:
1132 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1133 case MachO::CPU_SUBTYPE_ARM_V4T:
1134 return Triple("armv4t-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1136 return Triple("armv5e-apple-darwin");
1137 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1138 return Triple("xscale-apple-darwin");
1139 case MachO::CPU_SUBTYPE_ARM_V6:
1140 return Triple("armv6-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_V6M:
1143 *McpuDefault = "cortex-m0";
1144 return Triple("armv6m-apple-darwin");
1145 case MachO::CPU_SUBTYPE_ARM_V7:
1146 return Triple("armv7-apple-darwin");
1147 case MachO::CPU_SUBTYPE_ARM_V7EM:
1149 *McpuDefault = "cortex-m4";
1150 return Triple("armv7em-apple-darwin");
1151 case MachO::CPU_SUBTYPE_ARM_V7K:
1152 return Triple("armv7k-apple-darwin");
1153 case MachO::CPU_SUBTYPE_ARM_V7M:
1155 *McpuDefault = "cortex-m3";
1156 return Triple("armv7m-apple-darwin");
1157 case MachO::CPU_SUBTYPE_ARM_V7S:
1158 return Triple("armv7s-apple-darwin");
1162 case MachO::CPU_TYPE_ARM64:
1163 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1164 case MachO::CPU_SUBTYPE_ARM64_ALL:
1165 return Triple("arm64-apple-darwin");
1169 case MachO::CPU_TYPE_POWERPC:
1170 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1171 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1172 return Triple("ppc-apple-darwin");
1176 case MachO::CPU_TYPE_POWERPC64:
1177 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1178 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1179 return Triple("ppc64-apple-darwin");
1188 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1189 const char **McpuDefault) {
1191 *McpuDefault = nullptr;
1194 case MachO::CPU_TYPE_ARM:
1195 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1196 case MachO::CPU_SUBTYPE_ARM_V4T:
1197 return Triple("thumbv4t-apple-darwin");
1198 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1199 return Triple("thumbv5e-apple-darwin");
1200 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1201 return Triple("xscale-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V6:
1203 return Triple("thumbv6-apple-darwin");
1204 case MachO::CPU_SUBTYPE_ARM_V6M:
1206 *McpuDefault = "cortex-m0";
1207 return Triple("thumbv6m-apple-darwin");
1208 case MachO::CPU_SUBTYPE_ARM_V7:
1209 return Triple("thumbv7-apple-darwin");
1210 case MachO::CPU_SUBTYPE_ARM_V7EM:
1212 *McpuDefault = "cortex-m4";
1213 return Triple("thumbv7em-apple-darwin");
1214 case MachO::CPU_SUBTYPE_ARM_V7K:
1215 return Triple("thumbv7k-apple-darwin");
1216 case MachO::CPU_SUBTYPE_ARM_V7M:
1218 *McpuDefault = "cortex-m3";
1219 return Triple("thumbv7m-apple-darwin");
1220 case MachO::CPU_SUBTYPE_ARM_V7S:
1221 return Triple("thumbv7s-apple-darwin");
1230 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1231 const char **McpuDefault,
1232 Triple *ThumbTriple) {
1233 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1234 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1239 Triple MachOObjectFile::getHostArch() {
1240 return Triple(sys::getDefaultTargetTriple());
1243 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1244 return StringSwitch<bool>(ArchFlag)
1246 .Case("x86_64", true)
1247 .Case("x86_64h", true)
1248 .Case("armv4t", true)
1250 .Case("armv5e", true)
1251 .Case("armv6", true)
1252 .Case("armv6m", true)
1253 .Case("armv7em", true)
1254 .Case("armv7k", true)
1255 .Case("armv7m", true)
1256 .Case("armv7s", true)
1257 .Case("arm64", true)
1259 .Case("ppc64", true)
1263 unsigned MachOObjectFile::getArch() const {
1264 return getArch(getCPUType(this));
1267 Triple MachOObjectFile::getArch(const char **McpuDefault,
1268 Triple *ThumbTriple) const {
1269 const auto &Header = getHeader();
1270 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1271 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1274 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1277 return section_rel_begin(DRI);
1280 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1283 return section_rel_end(DRI);
1286 dice_iterator MachOObjectFile::begin_dices() const {
1288 if (!DataInCodeLoadCmd)
1289 return dice_iterator(DiceRef(DRI, this));
1291 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1292 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1293 return dice_iterator(DiceRef(DRI, this));
1296 dice_iterator MachOObjectFile::end_dices() const {
1298 if (!DataInCodeLoadCmd)
1299 return dice_iterator(DiceRef(DRI, this));
1301 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1302 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1303 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1304 return dice_iterator(DiceRef(DRI, this));
1307 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1308 : Trie(T), Malformed(false), Done(false) { }
1310 void ExportEntry::moveToFirst() {
1312 pushDownUntilBottom();
1315 void ExportEntry::moveToEnd() {
1320 bool ExportEntry::operator==(const ExportEntry &Other) const {
1321 // Common case, one at end, other iterating from begin.
1322 if (Done || Other.Done)
1323 return (Done == Other.Done);
1324 // Not equal if different stack sizes.
1325 if (Stack.size() != Other.Stack.size())
1327 // Not equal if different cumulative strings.
1328 if (!CumulativeString.equals(Other.CumulativeString))
1330 // Equal if all nodes in both stacks match.
1331 for (unsigned i=0; i < Stack.size(); ++i) {
1332 if (Stack[i].Start != Other.Stack[i].Start)
1338 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1340 uint64_t Result = decodeULEB128(Ptr, &Count);
1342 if (Ptr > Trie.end()) {
1349 StringRef ExportEntry::name() const {
1350 return CumulativeString;
1353 uint64_t ExportEntry::flags() const {
1354 return Stack.back().Flags;
1357 uint64_t ExportEntry::address() const {
1358 return Stack.back().Address;
1361 uint64_t ExportEntry::other() const {
1362 return Stack.back().Other;
1365 StringRef ExportEntry::otherName() const {
1366 const char* ImportName = Stack.back().ImportName;
1368 return StringRef(ImportName);
1372 uint32_t ExportEntry::nodeOffset() const {
1373 return Stack.back().Start - Trie.begin();
1376 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1377 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1378 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1379 ParentStringLength(0), IsExportNode(false) {
1382 void ExportEntry::pushNode(uint64_t offset) {
1383 const uint8_t *Ptr = Trie.begin() + offset;
1384 NodeState State(Ptr);
1385 uint64_t ExportInfoSize = readULEB128(State.Current);
1386 State.IsExportNode = (ExportInfoSize != 0);
1387 const uint8_t* Children = State.Current + ExportInfoSize;
1388 if (State.IsExportNode) {
1389 State.Flags = readULEB128(State.Current);
1390 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1392 State.Other = readULEB128(State.Current); // dylib ordinal
1393 State.ImportName = reinterpret_cast<const char*>(State.Current);
1395 State.Address = readULEB128(State.Current);
1396 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1397 State.Other = readULEB128(State.Current);
1400 State.ChildCount = *Children;
1401 State.Current = Children + 1;
1402 State.NextChildIndex = 0;
1403 State.ParentStringLength = CumulativeString.size();
1404 Stack.push_back(State);
1407 void ExportEntry::pushDownUntilBottom() {
1408 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1409 NodeState &Top = Stack.back();
1410 CumulativeString.resize(Top.ParentStringLength);
1411 for (;*Top.Current != 0; Top.Current++) {
1412 char C = *Top.Current;
1413 CumulativeString.push_back(C);
1416 uint64_t childNodeIndex = readULEB128(Top.Current);
1417 Top.NextChildIndex += 1;
1418 pushNode(childNodeIndex);
1420 if (!Stack.back().IsExportNode) {
1426 // We have a trie data structure and need a way to walk it that is compatible
1427 // with the C++ iterator model. The solution is a non-recursive depth first
1428 // traversal where the iterator contains a stack of parent nodes along with a
1429 // string that is the accumulation of all edge strings along the parent chain
1432 // There is one "export" node for each exported symbol. But because some
1433 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1434 // node may have child nodes too.
1436 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1437 // child until hitting a node with no children (which is an export node or
1438 // else the trie is malformed). On the way down, each node is pushed on the
1439 // stack ivar. If there is no more ways down, it pops up one and tries to go
1440 // down a sibling path until a childless node is reached.
1441 void ExportEntry::moveNext() {
1442 if (Stack.empty() || !Stack.back().IsExportNode) {
1449 while (!Stack.empty()) {
1450 NodeState &Top = Stack.back();
1451 if (Top.NextChildIndex < Top.ChildCount) {
1452 pushDownUntilBottom();
1453 // Now at the next export node.
1456 if (Top.IsExportNode) {
1457 // This node has no children but is itself an export node.
1458 CumulativeString.resize(Top.ParentStringLength);
1467 iterator_range<export_iterator>
1468 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1469 ExportEntry Start(Trie);
1470 if (Trie.size() == 0)
1473 Start.moveToFirst();
1475 ExportEntry Finish(Trie);
1478 return iterator_range<export_iterator>(export_iterator(Start),
1479 export_iterator(Finish));
1482 iterator_range<export_iterator> MachOObjectFile::exports() const {
1483 return exports(getDyldInfoExportsTrie());
1487 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1488 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1489 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1490 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1492 void MachORebaseEntry::moveToFirst() {
1493 Ptr = Opcodes.begin();
1497 void MachORebaseEntry::moveToEnd() {
1498 Ptr = Opcodes.end();
1499 RemainingLoopCount = 0;
1503 void MachORebaseEntry::moveNext() {
1504 // If in the middle of some loop, move to next rebasing in loop.
1505 SegmentOffset += AdvanceAmount;
1506 if (RemainingLoopCount) {
1507 --RemainingLoopCount;
1510 if (Ptr == Opcodes.end()) {
1515 while (More && !Malformed) {
1516 // Parse next opcode and set up next loop.
1517 uint8_t Byte = *Ptr++;
1518 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1519 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1521 case MachO::REBASE_OPCODE_DONE:
1525 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1527 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1528 RebaseType = ImmValue;
1531 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1532 << "RebaseType=" << (int) RebaseType << "\n");
1534 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1535 SegmentIndex = ImmValue;
1536 SegmentOffset = readULEB128();
1539 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1540 << "SegmentIndex=" << SegmentIndex << ", "
1541 << format("SegmentOffset=0x%06X", SegmentOffset)
1544 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1545 SegmentOffset += readULEB128();
1546 DEBUG_WITH_TYPE("mach-o-rebase",
1547 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1548 << format("SegmentOffset=0x%06X",
1549 SegmentOffset) << "\n");
1551 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1552 SegmentOffset += ImmValue * PointerSize;
1553 DEBUG_WITH_TYPE("mach-o-rebase",
1554 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1555 << format("SegmentOffset=0x%06X",
1556 SegmentOffset) << "\n");
1558 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1559 AdvanceAmount = PointerSize;
1560 RemainingLoopCount = ImmValue - 1;
1563 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1564 << format("SegmentOffset=0x%06X", SegmentOffset)
1565 << ", AdvanceAmount=" << AdvanceAmount
1566 << ", RemainingLoopCount=" << RemainingLoopCount
1569 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1570 AdvanceAmount = PointerSize;
1571 RemainingLoopCount = readULEB128() - 1;
1574 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1575 << format("SegmentOffset=0x%06X", SegmentOffset)
1576 << ", AdvanceAmount=" << AdvanceAmount
1577 << ", RemainingLoopCount=" << RemainingLoopCount
1580 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1581 AdvanceAmount = readULEB128() + PointerSize;
1582 RemainingLoopCount = 0;
1585 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1586 << format("SegmentOffset=0x%06X", SegmentOffset)
1587 << ", AdvanceAmount=" << AdvanceAmount
1588 << ", RemainingLoopCount=" << RemainingLoopCount
1591 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1592 RemainingLoopCount = readULEB128() - 1;
1593 AdvanceAmount = readULEB128() + PointerSize;
1596 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1597 << format("SegmentOffset=0x%06X", SegmentOffset)
1598 << ", AdvanceAmount=" << AdvanceAmount
1599 << ", RemainingLoopCount=" << RemainingLoopCount
1608 uint64_t MachORebaseEntry::readULEB128() {
1610 uint64_t Result = decodeULEB128(Ptr, &Count);
1612 if (Ptr > Opcodes.end()) {
1613 Ptr = Opcodes.end();
1619 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1621 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1623 StringRef MachORebaseEntry::typeName() const {
1624 switch (RebaseType) {
1625 case MachO::REBASE_TYPE_POINTER:
1627 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1628 return "text abs32";
1629 case MachO::REBASE_TYPE_TEXT_PCREL32:
1630 return "text rel32";
1635 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1636 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1637 return (Ptr == Other.Ptr) &&
1638 (RemainingLoopCount == Other.RemainingLoopCount) &&
1639 (Done == Other.Done);
1642 iterator_range<rebase_iterator>
1643 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1644 MachORebaseEntry Start(Opcodes, is64);
1645 Start.moveToFirst();
1647 MachORebaseEntry Finish(Opcodes, is64);
1650 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1651 rebase_iterator(Finish));
1654 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1655 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1659 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1661 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1662 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1663 BindType(0), PointerSize(is64Bit ? 8 : 4),
1664 TableKind(BK), Malformed(false), Done(false) {}
1666 void MachOBindEntry::moveToFirst() {
1667 Ptr = Opcodes.begin();
1671 void MachOBindEntry::moveToEnd() {
1672 Ptr = Opcodes.end();
1673 RemainingLoopCount = 0;
1677 void MachOBindEntry::moveNext() {
1678 // If in the middle of some loop, move to next binding in loop.
1679 SegmentOffset += AdvanceAmount;
1680 if (RemainingLoopCount) {
1681 --RemainingLoopCount;
1684 if (Ptr == Opcodes.end()) {
1689 while (More && !Malformed) {
1690 // Parse next opcode and set up next loop.
1691 uint8_t Byte = *Ptr++;
1692 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1693 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1694 int8_t SignExtended;
1695 const uint8_t *SymStart;
1697 case MachO::BIND_OPCODE_DONE:
1698 if (TableKind == Kind::Lazy) {
1699 // Lazying bindings have a DONE opcode between entries. Need to ignore
1700 // it to advance to next entry. But need not if this is last entry.
1701 bool NotLastEntry = false;
1702 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1704 NotLastEntry = true;
1713 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1715 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1720 << "Ordinal=" << Ordinal << "\n");
1722 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1723 Ordinal = readULEB128();
1726 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1727 << "Ordinal=" << Ordinal << "\n");
1729 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1731 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1732 Ordinal = SignExtended;
1737 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1738 << "Ordinal=" << Ordinal << "\n");
1740 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1746 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1751 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1752 << "SymbolName=" << SymbolName << "\n");
1753 if (TableKind == Kind::Weak) {
1754 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1758 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1759 BindType = ImmValue;
1762 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1763 << "BindType=" << (int)BindType << "\n");
1765 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1766 Addend = readSLEB128();
1767 if (TableKind == Kind::Lazy)
1771 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1772 << "Addend=" << Addend << "\n");
1774 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1775 SegmentIndex = ImmValue;
1776 SegmentOffset = readULEB128();
1779 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1780 << "SegmentIndex=" << SegmentIndex << ", "
1781 << format("SegmentOffset=0x%06X", SegmentOffset)
1784 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1785 SegmentOffset += readULEB128();
1786 DEBUG_WITH_TYPE("mach-o-bind",
1787 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1788 << format("SegmentOffset=0x%06X",
1789 SegmentOffset) << "\n");
1791 case MachO::BIND_OPCODE_DO_BIND:
1792 AdvanceAmount = PointerSize;
1793 RemainingLoopCount = 0;
1794 DEBUG_WITH_TYPE("mach-o-bind",
1795 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1796 << format("SegmentOffset=0x%06X",
1797 SegmentOffset) << "\n");
1799 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1800 AdvanceAmount = readULEB128() + PointerSize;
1801 RemainingLoopCount = 0;
1802 if (TableKind == Kind::Lazy)
1806 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1807 << format("SegmentOffset=0x%06X", SegmentOffset)
1808 << ", AdvanceAmount=" << AdvanceAmount
1809 << ", RemainingLoopCount=" << RemainingLoopCount
1812 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1813 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1814 RemainingLoopCount = 0;
1815 if (TableKind == Kind::Lazy)
1817 DEBUG_WITH_TYPE("mach-o-bind",
1819 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1820 << format("SegmentOffset=0x%06X",
1821 SegmentOffset) << "\n");
1823 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1824 RemainingLoopCount = readULEB128() - 1;
1825 AdvanceAmount = readULEB128() + PointerSize;
1826 if (TableKind == Kind::Lazy)
1830 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1831 << format("SegmentOffset=0x%06X", SegmentOffset)
1832 << ", AdvanceAmount=" << AdvanceAmount
1833 << ", RemainingLoopCount=" << RemainingLoopCount
1842 uint64_t MachOBindEntry::readULEB128() {
1844 uint64_t Result = decodeULEB128(Ptr, &Count);
1846 if (Ptr > Opcodes.end()) {
1847 Ptr = Opcodes.end();
1853 int64_t MachOBindEntry::readSLEB128() {
1855 int64_t Result = decodeSLEB128(Ptr, &Count);
1857 if (Ptr > Opcodes.end()) {
1858 Ptr = Opcodes.end();
1865 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1867 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1869 StringRef MachOBindEntry::typeName() const {
1871 case MachO::BIND_TYPE_POINTER:
1873 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1874 return "text abs32";
1875 case MachO::BIND_TYPE_TEXT_PCREL32:
1876 return "text rel32";
1881 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1883 int64_t MachOBindEntry::addend() const { return Addend; }
1885 uint32_t MachOBindEntry::flags() const { return Flags; }
1887 int MachOBindEntry::ordinal() const { return Ordinal; }
1889 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1890 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1891 return (Ptr == Other.Ptr) &&
1892 (RemainingLoopCount == Other.RemainingLoopCount) &&
1893 (Done == Other.Done);
1896 iterator_range<bind_iterator>
1897 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1898 MachOBindEntry::Kind BKind) {
1899 MachOBindEntry Start(Opcodes, is64, BKind);
1900 Start.moveToFirst();
1902 MachOBindEntry Finish(Opcodes, is64, BKind);
1905 return iterator_range<bind_iterator>(bind_iterator(Start),
1906 bind_iterator(Finish));
1909 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1910 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1911 MachOBindEntry::Kind::Regular);
1914 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1915 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1916 MachOBindEntry::Kind::Lazy);
1919 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1920 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1921 MachOBindEntry::Kind::Weak);
1924 MachOObjectFile::load_command_iterator
1925 MachOObjectFile::begin_load_commands() const {
1926 return LoadCommands.begin();
1929 MachOObjectFile::load_command_iterator
1930 MachOObjectFile::end_load_commands() const {
1931 return LoadCommands.end();
1934 iterator_range<MachOObjectFile::load_command_iterator>
1935 MachOObjectFile::load_commands() const {
1936 return iterator_range<load_command_iterator>(begin_load_commands(),
1937 end_load_commands());
1941 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1942 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1943 return parseSegmentOrSectionName(Raw.data());
1947 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1948 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1949 const section_base *Base =
1950 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1951 return makeArrayRef(Base->sectname);
1955 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1956 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1957 const section_base *Base =
1958 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1959 return makeArrayRef(Base->segname);
1963 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1965 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1967 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1970 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1971 const MachO::any_relocation_info &RE) const {
1972 if (isLittleEndian())
1973 return RE.r_word1 & 0xffffff;
1974 return RE.r_word1 >> 8;
1977 bool MachOObjectFile::getPlainRelocationExternal(
1978 const MachO::any_relocation_info &RE) const {
1979 if (isLittleEndian())
1980 return (RE.r_word1 >> 27) & 1;
1981 return (RE.r_word1 >> 4) & 1;
1984 bool MachOObjectFile::getScatteredRelocationScattered(
1985 const MachO::any_relocation_info &RE) const {
1986 return RE.r_word0 >> 31;
1989 uint32_t MachOObjectFile::getScatteredRelocationValue(
1990 const MachO::any_relocation_info &RE) const {
1994 uint32_t MachOObjectFile::getScatteredRelocationType(
1995 const MachO::any_relocation_info &RE) const {
1996 return (RE.r_word0 >> 24) & 0xf;
1999 unsigned MachOObjectFile::getAnyRelocationAddress(
2000 const MachO::any_relocation_info &RE) const {
2001 if (isRelocationScattered(RE))
2002 return getScatteredRelocationAddress(RE);
2003 return getPlainRelocationAddress(RE);
2006 unsigned MachOObjectFile::getAnyRelocationPCRel(
2007 const MachO::any_relocation_info &RE) const {
2008 if (isRelocationScattered(RE))
2009 return getScatteredRelocationPCRel(this, RE);
2010 return getPlainRelocationPCRel(this, RE);
2013 unsigned MachOObjectFile::getAnyRelocationLength(
2014 const MachO::any_relocation_info &RE) const {
2015 if (isRelocationScattered(RE))
2016 return getScatteredRelocationLength(RE);
2017 return getPlainRelocationLength(this, RE);
2021 MachOObjectFile::getAnyRelocationType(
2022 const MachO::any_relocation_info &RE) const {
2023 if (isRelocationScattered(RE))
2024 return getScatteredRelocationType(RE);
2025 return getPlainRelocationType(this, RE);
2029 MachOObjectFile::getAnyRelocationSection(
2030 const MachO::any_relocation_info &RE) const {
2031 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2032 return *section_end();
2033 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2036 return SectionRef(DRI, this);
2039 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2040 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2041 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2044 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2045 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2046 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2049 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2050 unsigned Index) const {
2051 const char *Sec = getSectionPtr(this, L, Index);
2052 return getStruct<MachO::section>(this, Sec);
2055 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2056 unsigned Index) const {
2057 const char *Sec = getSectionPtr(this, L, Index);
2058 return getStruct<MachO::section_64>(this, Sec);
2062 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2063 const char *P = reinterpret_cast<const char *>(DRI.p);
2064 return getStruct<MachO::nlist>(this, P);
2068 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2069 const char *P = reinterpret_cast<const char *>(DRI.p);
2070 return getStruct<MachO::nlist_64>(this, P);
2073 MachO::linkedit_data_command
2074 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2078 MachO::segment_command
2079 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::segment_command>(this, L.Ptr);
2083 MachO::segment_command_64
2084 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2088 MachO::linker_option_command
2089 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2093 MachO::version_min_command
2094 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2095 return getStruct<MachO::version_min_command>(this, L.Ptr);
2098 MachO::dylib_command
2099 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2100 return getStruct<MachO::dylib_command>(this, L.Ptr);
2103 MachO::dyld_info_command
2104 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2105 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2108 MachO::dylinker_command
2109 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2110 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2114 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2115 return getStruct<MachO::uuid_command>(this, L.Ptr);
2118 MachO::rpath_command
2119 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2120 return getStruct<MachO::rpath_command>(this, L.Ptr);
2123 MachO::source_version_command
2124 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2125 return getStruct<MachO::source_version_command>(this, L.Ptr);
2128 MachO::entry_point_command
2129 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2130 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2133 MachO::encryption_info_command
2134 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2135 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2138 MachO::encryption_info_command_64
2139 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2140 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2143 MachO::sub_framework_command
2144 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2145 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2148 MachO::sub_umbrella_command
2149 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2150 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2153 MachO::sub_library_command
2154 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2155 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2158 MachO::sub_client_command
2159 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2160 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2163 MachO::routines_command
2164 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2165 return getStruct<MachO::routines_command>(this, L.Ptr);
2168 MachO::routines_command_64
2169 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2170 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2173 MachO::thread_command
2174 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2175 return getStruct<MachO::thread_command>(this, L.Ptr);
2178 MachO::any_relocation_info
2179 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2184 MachO::section_64 Sect = getSection64(Sec);
2185 Offset = Sect.reloff;
2187 MachO::section Sect = getSection(Sec);
2188 Offset = Sect.reloff;
2191 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2192 getPtr(this, Offset)) + Rel.d.b;
2193 return getStruct<MachO::any_relocation_info>(
2194 this, reinterpret_cast<const char *>(P));
2197 MachO::data_in_code_entry
2198 MachOObjectFile::getDice(DataRefImpl Rel) const {
2199 const char *P = reinterpret_cast<const char *>(Rel.p);
2200 return getStruct<MachO::data_in_code_entry>(this, P);
2203 const MachO::mach_header &MachOObjectFile::getHeader() const {
2204 // First fields of MachO::mach_header_64 are the same as
2205 // in MachO::mach_header.
2206 return *reinterpret_cast<const MachO::mach_header *>(&this->Header64);
2209 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2214 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2215 const MachO::dysymtab_command &DLC,
2216 unsigned Index) const {
2217 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2218 return getStruct<uint32_t>(this, getPtr(this, Offset));
2221 MachO::data_in_code_entry
2222 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2223 unsigned Index) const {
2224 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2225 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2228 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2230 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2232 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2233 MachO::symtab_command Cmd;
2234 Cmd.cmd = MachO::LC_SYMTAB;
2235 Cmd.cmdsize = sizeof(MachO::symtab_command);
2243 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2244 if (DysymtabLoadCmd)
2245 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2247 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2248 MachO::dysymtab_command Cmd;
2249 Cmd.cmd = MachO::LC_DYSYMTAB;
2250 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2261 Cmd.extrefsymoff = 0;
2262 Cmd.nextrefsyms = 0;
2263 Cmd.indirectsymoff = 0;
2264 Cmd.nindirectsyms = 0;
2272 MachO::linkedit_data_command
2273 MachOObjectFile::getDataInCodeLoadCommand() const {
2274 if (DataInCodeLoadCmd)
2275 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2277 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2278 MachO::linkedit_data_command Cmd;
2279 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2280 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2286 MachO::linkedit_data_command
2287 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2288 if (LinkOptHintsLoadCmd)
2289 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2291 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2293 MachO::linkedit_data_command Cmd;
2294 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2295 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2301 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2302 if (!DyldInfoLoadCmd)
2303 return ArrayRef<uint8_t>();
2305 MachO::dyld_info_command DyldInfo
2306 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2307 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2308 getPtr(this, DyldInfo.rebase_off));
2309 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2312 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2313 if (!DyldInfoLoadCmd)
2314 return ArrayRef<uint8_t>();
2316 MachO::dyld_info_command DyldInfo
2317 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2318 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2319 getPtr(this, DyldInfo.bind_off));
2320 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2323 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2324 if (!DyldInfoLoadCmd)
2325 return ArrayRef<uint8_t>();
2327 MachO::dyld_info_command DyldInfo
2328 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2329 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2330 getPtr(this, DyldInfo.weak_bind_off));
2331 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2334 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2335 if (!DyldInfoLoadCmd)
2336 return ArrayRef<uint8_t>();
2338 MachO::dyld_info_command DyldInfo
2339 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2340 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2341 getPtr(this, DyldInfo.lazy_bind_off));
2342 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2345 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2346 if (!DyldInfoLoadCmd)
2347 return ArrayRef<uint8_t>();
2349 MachO::dyld_info_command DyldInfo
2350 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2351 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2352 getPtr(this, DyldInfo.export_off));
2353 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2356 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2358 return ArrayRef<uint8_t>();
2359 // Returning a pointer is fine as uuid doesn't need endian swapping.
2360 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2361 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2364 StringRef MachOObjectFile::getStringTableData() const {
2365 MachO::symtab_command S = getSymtabLoadCommand();
2366 return getData().substr(S.stroff, S.strsize);
2369 bool MachOObjectFile::is64Bit() const {
2370 return getType() == getMachOType(false, true) ||
2371 getType() == getMachOType(true, true);
2374 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2375 SmallVectorImpl<uint64_t> &Out) const {
2376 DataExtractor extractor(ObjectFile::getData(), true, 0);
2378 uint32_t offset = Index;
2380 while (uint64_t delta = extractor.getULEB128(&offset)) {
2382 Out.push_back(data);
2386 bool MachOObjectFile::isRelocatableObject() const {
2387 return getHeader().filetype == MachO::MH_OBJECT;
2390 ErrorOr<std::unique_ptr<MachOObjectFile>>
2391 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2392 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2394 std::unique_ptr<MachOObjectFile> Ret;
2395 if (Magic == "\xFE\xED\xFA\xCE")
2396 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2397 else if (Magic == "\xCE\xFA\xED\xFE")
2398 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2399 else if (Magic == "\xFE\xED\xFA\xCF")
2400 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2401 else if (Magic == "\xCF\xFA\xED\xFE")
2402 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2404 return object_error::parse_failed;
2408 return std::move(Ret);