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 object_error::success;
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 // First fields of MachO::mach_header_64 are the same as
238 // in MachO::mach_header.
239 parseHeader(this, *reinterpret_cast<MachO::mach_header *>(&this->Header64),
244 uint32_t LoadCommandCount = getHeader().ncmds;
245 if (LoadCommandCount == 0)
248 auto LoadOrErr = getFirstLoadCommandInfo(this);
250 EC = LoadOrErr.getError();
253 LoadCommandInfo Load = LoadOrErr.get();
254 for (unsigned I = 0; I < LoadCommandCount; ++I) {
255 LoadCommands.push_back(Load);
256 if (Load.C.cmd == MachO::LC_SYMTAB) {
257 // Multiple symbol tables
259 EC = object_error::parse_failed;
262 SymtabLoadCmd = Load.Ptr;
263 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
264 // Multiple dynamic symbol tables
265 if (DysymtabLoadCmd) {
266 EC = object_error::parse_failed;
269 DysymtabLoadCmd = Load.Ptr;
270 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
271 // Multiple data in code tables
272 if (DataInCodeLoadCmd) {
273 EC = object_error::parse_failed;
276 DataInCodeLoadCmd = Load.Ptr;
277 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
278 // Multiple linker optimization hint tables
279 if (LinkOptHintsLoadCmd) {
280 EC = object_error::parse_failed;
283 LinkOptHintsLoadCmd = Load.Ptr;
284 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
285 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
286 // Multiple dyldinfo load commands
287 if (DyldInfoLoadCmd) {
288 EC = object_error::parse_failed;
291 DyldInfoLoadCmd = Load.Ptr;
292 } else if (Load.C.cmd == MachO::LC_UUID) {
293 // Multiple UUID load commands
295 EC = object_error::parse_failed;
298 UuidLoadCmd = Load.Ptr;
299 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
300 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
301 this, Load, Sections, HasPageZeroSegment)))
303 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
304 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
305 this, Load, Sections, HasPageZeroSegment)))
307 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
309 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
310 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
311 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
312 Libraries.push_back(Load.Ptr);
314 if (I < LoadCommandCount - 1) {
315 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
317 EC = LoadOrErr.getError();
320 Load = LoadOrErr.get();
323 assert(LoadCommands.size() == LoadCommandCount);
326 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
327 unsigned SymbolTableEntrySize = is64Bit() ?
328 sizeof(MachO::nlist_64) :
329 sizeof(MachO::nlist);
330 Symb.p += SymbolTableEntrySize;
333 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
334 StringRef &Res) const {
335 StringRef StringTable = getStringTableData();
336 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
337 const char *Start = &StringTable.data()[Entry.n_strx];
338 if (Start < getData().begin() || Start >= getData().end())
340 "Symbol name entry points before beginning or past end of file.");
341 Res = StringRef(Start);
342 return object_error::success;
345 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
346 DataRefImpl DRI = Sec.getRawDataRefImpl();
347 uint32_t Flags = getSectionFlags(this, DRI);
348 return Flags & MachO::SECTION_TYPE;
351 // getIndirectName() returns the name of the alias'ed symbol who's string table
352 // index is in the n_value field.
353 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
354 StringRef &Res) const {
355 StringRef StringTable = getStringTableData();
358 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
359 NValue = Entry.n_value;
360 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
361 return object_error::parse_failed;
363 MachO::nlist Entry = getSymbolTableEntry(Symb);
364 NValue = Entry.n_value;
365 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
366 return object_error::parse_failed;
368 if (NValue >= StringTable.size())
369 return object_error::parse_failed;
370 const char *Start = &StringTable.data()[NValue];
371 Res = StringRef(Start);
372 return object_error::success;
375 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
376 uint64_t &Res) const {
378 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
379 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
381 Res = UnknownAddressOrSize;
385 MachO::nlist Entry = getSymbolTableEntry(Symb);
386 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
388 Res = UnknownAddressOrSize;
392 return object_error::success;
395 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
396 uint32_t flags = getSymbolFlags(DRI);
397 if (flags & SymbolRef::SF_Common) {
398 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
399 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
404 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
406 getSymbolAddress(DRI, Value);
407 uint32_t flags = getSymbolFlags(DRI);
408 if (flags & SymbolRef::SF_Common)
410 return UnknownAddressOrSize;
413 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
414 SymbolRef::Type &Res) const {
415 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
416 uint8_t n_type = Entry.n_type;
418 Res = SymbolRef::ST_Other;
420 // If this is a STAB debugging symbol, we can do nothing more.
421 if (n_type & MachO::N_STAB) {
422 Res = SymbolRef::ST_Debug;
423 return object_error::success;
426 switch (n_type & MachO::N_TYPE) {
428 Res = SymbolRef::ST_Unknown;
431 Res = SymbolRef::ST_Function;
434 return object_error::success;
437 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
438 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
440 uint8_t MachOType = Entry.n_type;
441 uint16_t MachOFlags = Entry.n_desc;
443 uint32_t Result = SymbolRef::SF_None;
445 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
446 Result |= SymbolRef::SF_Undefined;
448 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
449 Result |= SymbolRef::SF_Indirect;
451 if (MachOType & MachO::N_STAB)
452 Result |= SymbolRef::SF_FormatSpecific;
454 if (MachOType & MachO::N_EXT) {
455 Result |= SymbolRef::SF_Global;
456 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
458 getSymbolAddress(DRI, Value);
459 if (Value && Value != UnknownAddressOrSize)
460 Result |= SymbolRef::SF_Common;
463 if (!(MachOType & MachO::N_PEXT))
464 Result |= SymbolRef::SF_Exported;
467 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
468 Result |= SymbolRef::SF_Weak;
470 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
471 Result |= SymbolRef::SF_Thumb;
473 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
474 Result |= SymbolRef::SF_Absolute;
479 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
480 section_iterator &Res) const {
481 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
482 uint8_t index = Entry.n_sect;
489 if (DRI.d.a >= Sections.size())
490 report_fatal_error("getSymbolSection: Invalid section index.");
491 Res = section_iterator(SectionRef(DRI, this));
494 return object_error::success;
497 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
501 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
502 StringRef &Result) const {
503 ArrayRef<char> Raw = getSectionRawName(Sec);
504 Result = parseSegmentOrSectionName(Raw.data());
505 return object_error::success;
508 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
510 return getSection64(Sec).addr;
511 return getSection(Sec).addr;
514 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
516 return getSection64(Sec).size;
517 return getSection(Sec).size;
520 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
521 StringRef &Res) const {
526 MachO::section_64 Sect = getSection64(Sec);
527 Offset = Sect.offset;
530 MachO::section Sect = getSection(Sec);
531 Offset = Sect.offset;
535 Res = this->getData().substr(Offset, Size);
536 return object_error::success;
539 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
542 MachO::section_64 Sect = getSection64(Sec);
545 MachO::section Sect = getSection(Sec);
549 return uint64_t(1) << Align;
552 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
553 uint32_t Flags = getSectionFlags(this, Sec);
554 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
557 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
558 uint32_t Flags = getSectionFlags(this, Sec);
559 unsigned SectionType = Flags & MachO::SECTION_TYPE;
560 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
561 !(SectionType == MachO::S_ZEROFILL ||
562 SectionType == MachO::S_GB_ZEROFILL);
565 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
566 uint32_t Flags = getSectionFlags(this, Sec);
567 unsigned SectionType = Flags & MachO::SECTION_TYPE;
568 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
569 (SectionType == MachO::S_ZEROFILL ||
570 SectionType == MachO::S_GB_ZEROFILL);
573 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
574 // FIXME: Unimplemented.
578 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
579 DataRefImpl Symb) const {
581 this->getSymbolType(Symb, ST);
582 if (ST == SymbolRef::ST_Unknown)
585 uint64_t SectBegin = getSectionAddress(Sec);
586 uint64_t SectEnd = getSectionSize(Sec);
587 SectEnd += SectBegin;
590 getSymbolAddress(Symb, SymAddr);
591 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
594 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
598 return relocation_iterator(RelocationRef(Ret, this));
602 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
605 MachO::section_64 Sect = getSection64(Sec);
608 MachO::section Sect = getSection(Sec);
615 return relocation_iterator(RelocationRef(Ret, this));
618 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
622 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
623 uint64_t &Res) const {
625 getRelocationOffset(Rel, Offset);
629 uint64_t SecAddress = getSectionAddress(Sec);
630 Res = SecAddress + Offset;
631 return object_error::success;
634 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
635 uint64_t &Res) const {
636 assert(getHeader().filetype == MachO::MH_OBJECT &&
637 "Only implemented for MH_OBJECT");
638 MachO::any_relocation_info RE = getRelocation(Rel);
639 Res = getAnyRelocationAddress(RE);
640 return object_error::success;
644 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
645 MachO::any_relocation_info RE = getRelocation(Rel);
646 if (isRelocationScattered(RE))
649 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
650 bool isExtern = getPlainRelocationExternal(RE);
654 MachO::symtab_command S = getSymtabLoadCommand();
655 unsigned SymbolTableEntrySize = is64Bit() ?
656 sizeof(MachO::nlist_64) :
657 sizeof(MachO::nlist);
658 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
660 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
661 return symbol_iterator(SymbolRef(Sym, this));
665 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
666 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
669 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
670 uint64_t &Res) const {
671 MachO::any_relocation_info RE = getRelocation(Rel);
672 Res = getAnyRelocationType(RE);
673 return object_error::success;
677 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
678 SmallVectorImpl<char> &Result) const {
681 getRelocationType(Rel, RType);
683 unsigned Arch = this->getArch();
687 static const char *const Table[] = {
688 "GENERIC_RELOC_VANILLA",
689 "GENERIC_RELOC_PAIR",
690 "GENERIC_RELOC_SECTDIFF",
691 "GENERIC_RELOC_PB_LA_PTR",
692 "GENERIC_RELOC_LOCAL_SECTDIFF",
693 "GENERIC_RELOC_TLV" };
701 case Triple::x86_64: {
702 static const char *const Table[] = {
703 "X86_64_RELOC_UNSIGNED",
704 "X86_64_RELOC_SIGNED",
705 "X86_64_RELOC_BRANCH",
706 "X86_64_RELOC_GOT_LOAD",
708 "X86_64_RELOC_SUBTRACTOR",
709 "X86_64_RELOC_SIGNED_1",
710 "X86_64_RELOC_SIGNED_2",
711 "X86_64_RELOC_SIGNED_4",
712 "X86_64_RELOC_TLV" };
721 static const char *const Table[] = {
724 "ARM_RELOC_SECTDIFF",
725 "ARM_RELOC_LOCAL_SECTDIFF",
726 "ARM_RELOC_PB_LA_PTR",
728 "ARM_THUMB_RELOC_BR22",
729 "ARM_THUMB_32BIT_BRANCH",
731 "ARM_RELOC_HALF_SECTDIFF" };
739 case Triple::aarch64: {
740 static const char *const Table[] = {
741 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
742 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
743 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
744 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
745 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
749 if (RType >= array_lengthof(Table))
756 static const char *const Table[] = {
765 "PPC_RELOC_SECTDIFF",
766 "PPC_RELOC_PB_LA_PTR",
767 "PPC_RELOC_HI16_SECTDIFF",
768 "PPC_RELOC_LO16_SECTDIFF",
769 "PPC_RELOC_HA16_SECTDIFF",
771 "PPC_RELOC_LO14_SECTDIFF",
772 "PPC_RELOC_LOCAL_SECTDIFF" };
780 case Triple::UnknownArch:
784 Result.append(res.begin(), res.end());
785 return object_error::success;
788 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
789 bool &Result) const {
790 unsigned Arch = getArch();
792 getRelocationType(Rel, Type);
796 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
798 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
799 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
800 } else if (Arch == Triple::x86_64) {
801 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
802 // an X86_64_RELOC_SUBTRACTOR.
803 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
804 DataRefImpl RelPrev = Rel;
807 getRelocationType(RelPrev, PrevType);
808 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
813 return object_error::success;
816 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
817 MachO::any_relocation_info RE = getRelocation(Rel);
818 return getAnyRelocationLength(RE);
822 // guessLibraryShortName() is passed a name of a dynamic library and returns a
823 // guess on what the short name is. Then name is returned as a substring of the
824 // StringRef Name passed in. The name of the dynamic library is recognized as
825 // a framework if it has one of the two following forms:
826 // Foo.framework/Versions/A/Foo
828 // Where A and Foo can be any string. And may contain a trailing suffix
829 // starting with an underbar. If the Name is recognized as a framework then
830 // isFramework is set to true else it is set to false. If the Name has a
831 // suffix then Suffix is set to the substring in Name that contains the suffix
832 // else it is set to a NULL StringRef.
834 // The Name of the dynamic library is recognized as a library name if it has
835 // one of the two following forms:
838 // The library may have a suffix trailing the name Foo of the form:
839 // libFoo_profile.A.dylib
840 // libFoo_profile.dylib
842 // The Name of the dynamic library is also recognized as a library name if it
843 // has the following form:
846 // If the Name of the dynamic library is none of the forms above then a NULL
847 // StringRef is returned.
849 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
852 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
853 size_t a, b, c, d, Idx;
856 Suffix = StringRef();
858 // Pull off the last component and make Foo point to it
860 if (a == Name.npos || a == 0)
862 Foo = Name.slice(a+1, Name.npos);
864 // Look for a suffix starting with a '_'
865 Idx = Foo.rfind('_');
866 if (Idx != Foo.npos && Foo.size() >= 2) {
867 Suffix = Foo.slice(Idx, Foo.npos);
868 Foo = Foo.slice(0, Idx);
871 // First look for the form Foo.framework/Foo
872 b = Name.rfind('/', a);
877 F = Name.slice(Idx, Idx + Foo.size());
878 DotFramework = Name.slice(Idx + Foo.size(),
879 Idx + Foo.size() + sizeof(".framework/")-1);
880 if (F == Foo && DotFramework == ".framework/") {
885 // Next look for the form Foo.framework/Versions/A/Foo
888 c = Name.rfind('/', b);
889 if (c == Name.npos || c == 0)
891 V = Name.slice(c+1, Name.npos);
892 if (!V.startswith("Versions/"))
894 d = Name.rfind('/', c);
899 F = Name.slice(Idx, Idx + Foo.size());
900 DotFramework = Name.slice(Idx + Foo.size(),
901 Idx + Foo.size() + sizeof(".framework/")-1);
902 if (F == Foo && DotFramework == ".framework/") {
908 // pull off the suffix after the "." and make a point to it
910 if (a == Name.npos || a == 0)
912 Dylib = Name.slice(a, Name.npos);
913 if (Dylib != ".dylib")
916 // First pull off the version letter for the form Foo.A.dylib if any.
918 Dot = Name.slice(a-2, a-1);
923 b = Name.rfind('/', a);
928 // ignore any suffix after an underbar like Foo_profile.A.dylib
929 Idx = Name.find('_', b);
930 if (Idx != Name.npos && Idx != b) {
931 Lib = Name.slice(b, Idx);
932 Suffix = Name.slice(Idx, a);
935 Lib = Name.slice(b, a);
936 // There are incorrect library names of the form:
937 // libATS.A_profile.dylib so check for these.
938 if (Lib.size() >= 3) {
939 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
941 Lib = Lib.slice(0, Lib.size()-2);
946 Qtx = Name.slice(a, Name.npos);
949 b = Name.rfind('/', a);
951 Lib = Name.slice(0, a);
953 Lib = Name.slice(b+1, a);
954 // There are library names of the form: QT.A.qtx so check for these.
955 if (Lib.size() >= 3) {
956 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
958 Lib = Lib.slice(0, Lib.size()-2);
963 // getLibraryShortNameByIndex() is used to get the short name of the library
964 // for an undefined symbol in a linked Mach-O binary that was linked with the
965 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
966 // It is passed the index (0 - based) of the library as translated from
967 // GET_LIBRARY_ORDINAL (1 - based).
968 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
969 StringRef &Res) const {
970 if (Index >= Libraries.size())
971 return object_error::parse_failed;
973 // If the cache of LibrariesShortNames is not built up do that first for
974 // all the Libraries.
975 if (LibrariesShortNames.size() == 0) {
976 for (unsigned i = 0; i < Libraries.size(); i++) {
977 MachO::dylib_command D =
978 getStruct<MachO::dylib_command>(this, Libraries[i]);
979 if (D.dylib.name >= D.cmdsize)
980 return object_error::parse_failed;
981 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
982 StringRef Name = StringRef(P);
983 if (D.dylib.name+Name.size() >= D.cmdsize)
984 return object_error::parse_failed;
987 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
988 if (shortName.empty())
989 LibrariesShortNames.push_back(Name);
991 LibrariesShortNames.push_back(shortName);
995 Res = LibrariesShortNames[Index];
996 return object_error::success;
999 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1000 return getSymbolByIndex(0);
1003 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1006 return basic_symbol_iterator(SymbolRef(DRI, this));
1008 MachO::symtab_command Symtab = getSymtabLoadCommand();
1009 unsigned SymbolTableEntrySize = is64Bit() ?
1010 sizeof(MachO::nlist_64) :
1011 sizeof(MachO::nlist);
1012 unsigned Offset = Symtab.symoff +
1013 Symtab.nsyms * SymbolTableEntrySize;
1014 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1015 return basic_symbol_iterator(SymbolRef(DRI, this));
1018 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1021 return basic_symbol_iterator(SymbolRef(DRI, this));
1023 MachO::symtab_command Symtab = getSymtabLoadCommand();
1024 if (Index >= Symtab.nsyms)
1025 report_fatal_error("Requested symbol index is out of range.");
1026 unsigned SymbolTableEntrySize =
1027 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1028 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1029 DRI.p += Index * SymbolTableEntrySize;
1030 return basic_symbol_iterator(SymbolRef(DRI, this));
1033 section_iterator MachOObjectFile::section_begin() const {
1035 return section_iterator(SectionRef(DRI, this));
1038 section_iterator MachOObjectFile::section_end() const {
1040 DRI.d.a = Sections.size();
1041 return section_iterator(SectionRef(DRI, this));
1044 uint8_t MachOObjectFile::getBytesInAddress() const {
1045 return is64Bit() ? 8 : 4;
1048 StringRef MachOObjectFile::getFileFormatName() const {
1049 unsigned CPUType = getCPUType(this);
1052 case llvm::MachO::CPU_TYPE_I386:
1053 return "Mach-O 32-bit i386";
1054 case llvm::MachO::CPU_TYPE_ARM:
1055 return "Mach-O arm";
1056 case llvm::MachO::CPU_TYPE_POWERPC:
1057 return "Mach-O 32-bit ppc";
1059 return "Mach-O 32-bit unknown";
1064 case llvm::MachO::CPU_TYPE_X86_64:
1065 return "Mach-O 64-bit x86-64";
1066 case llvm::MachO::CPU_TYPE_ARM64:
1067 return "Mach-O arm64";
1068 case llvm::MachO::CPU_TYPE_POWERPC64:
1069 return "Mach-O 64-bit ppc64";
1071 return "Mach-O 64-bit unknown";
1075 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1077 case llvm::MachO::CPU_TYPE_I386:
1079 case llvm::MachO::CPU_TYPE_X86_64:
1080 return Triple::x86_64;
1081 case llvm::MachO::CPU_TYPE_ARM:
1083 case llvm::MachO::CPU_TYPE_ARM64:
1084 return Triple::aarch64;
1085 case llvm::MachO::CPU_TYPE_POWERPC:
1087 case llvm::MachO::CPU_TYPE_POWERPC64:
1088 return Triple::ppc64;
1090 return Triple::UnknownArch;
1094 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1095 const char **McpuDefault) {
1097 *McpuDefault = nullptr;
1100 case MachO::CPU_TYPE_I386:
1101 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1102 case MachO::CPU_SUBTYPE_I386_ALL:
1103 return Triple("i386-apple-darwin");
1107 case MachO::CPU_TYPE_X86_64:
1108 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1109 case MachO::CPU_SUBTYPE_X86_64_ALL:
1110 return Triple("x86_64-apple-darwin");
1111 case MachO::CPU_SUBTYPE_X86_64_H:
1112 return Triple("x86_64h-apple-darwin");
1116 case MachO::CPU_TYPE_ARM:
1117 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1118 case MachO::CPU_SUBTYPE_ARM_V4T:
1119 return Triple("armv4t-apple-darwin");
1120 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1121 return Triple("armv5e-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1123 return Triple("xscale-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V6:
1125 return Triple("armv6-apple-darwin");
1126 case MachO::CPU_SUBTYPE_ARM_V6M:
1128 *McpuDefault = "cortex-m0";
1129 return Triple("armv6m-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_V7:
1131 return Triple("armv7-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V7EM:
1134 *McpuDefault = "cortex-m4";
1135 return Triple("armv7em-apple-darwin");
1136 case MachO::CPU_SUBTYPE_ARM_V7K:
1137 return Triple("armv7k-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7M:
1140 *McpuDefault = "cortex-m3";
1141 return Triple("armv7m-apple-darwin");
1142 case MachO::CPU_SUBTYPE_ARM_V7S:
1143 return Triple("armv7s-apple-darwin");
1147 case MachO::CPU_TYPE_ARM64:
1148 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1149 case MachO::CPU_SUBTYPE_ARM64_ALL:
1150 return Triple("arm64-apple-darwin");
1154 case MachO::CPU_TYPE_POWERPC:
1155 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1156 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1157 return Triple("ppc-apple-darwin");
1161 case MachO::CPU_TYPE_POWERPC64:
1162 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1163 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1164 return Triple("ppc64-apple-darwin");
1173 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1174 const char **McpuDefault) {
1176 *McpuDefault = nullptr;
1179 case MachO::CPU_TYPE_ARM:
1180 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1181 case MachO::CPU_SUBTYPE_ARM_V4T:
1182 return Triple("thumbv4t-apple-darwin");
1183 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1184 return Triple("thumbv5e-apple-darwin");
1185 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1186 return Triple("xscale-apple-darwin");
1187 case MachO::CPU_SUBTYPE_ARM_V6:
1188 return Triple("thumbv6-apple-darwin");
1189 case MachO::CPU_SUBTYPE_ARM_V6M:
1191 *McpuDefault = "cortex-m0";
1192 return Triple("thumbv6m-apple-darwin");
1193 case MachO::CPU_SUBTYPE_ARM_V7:
1194 return Triple("thumbv7-apple-darwin");
1195 case MachO::CPU_SUBTYPE_ARM_V7EM:
1197 *McpuDefault = "cortex-m4";
1198 return Triple("thumbv7em-apple-darwin");
1199 case MachO::CPU_SUBTYPE_ARM_V7K:
1200 return Triple("thumbv7k-apple-darwin");
1201 case MachO::CPU_SUBTYPE_ARM_V7M:
1203 *McpuDefault = "cortex-m3";
1204 return Triple("thumbv7m-apple-darwin");
1205 case MachO::CPU_SUBTYPE_ARM_V7S:
1206 return Triple("thumbv7s-apple-darwin");
1215 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1216 const char **McpuDefault,
1217 Triple *ThumbTriple) {
1218 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1219 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1224 Triple MachOObjectFile::getHostArch() {
1225 return Triple(sys::getDefaultTargetTriple());
1228 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1229 return StringSwitch<bool>(ArchFlag)
1231 .Case("x86_64", true)
1232 .Case("x86_64h", true)
1233 .Case("armv4t", true)
1235 .Case("armv5e", true)
1236 .Case("armv6", true)
1237 .Case("armv6m", true)
1238 .Case("armv7em", true)
1239 .Case("armv7k", true)
1240 .Case("armv7m", true)
1241 .Case("armv7s", true)
1242 .Case("arm64", true)
1244 .Case("ppc64", true)
1248 unsigned MachOObjectFile::getArch() const {
1249 return getArch(getCPUType(this));
1252 Triple MachOObjectFile::getArch(const char **McpuDefault,
1253 Triple *ThumbTriple) const {
1254 const auto &Header = getHeader();
1255 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1256 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1259 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1262 return section_rel_begin(DRI);
1265 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1268 return section_rel_end(DRI);
1271 dice_iterator MachOObjectFile::begin_dices() const {
1273 if (!DataInCodeLoadCmd)
1274 return dice_iterator(DiceRef(DRI, this));
1276 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1277 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1278 return dice_iterator(DiceRef(DRI, this));
1281 dice_iterator MachOObjectFile::end_dices() const {
1283 if (!DataInCodeLoadCmd)
1284 return dice_iterator(DiceRef(DRI, this));
1286 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1287 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1288 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1289 return dice_iterator(DiceRef(DRI, this));
1292 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1293 : Trie(T), Malformed(false), Done(false) { }
1295 void ExportEntry::moveToFirst() {
1297 pushDownUntilBottom();
1300 void ExportEntry::moveToEnd() {
1305 bool ExportEntry::operator==(const ExportEntry &Other) const {
1306 // Common case, one at end, other iterating from begin.
1307 if (Done || Other.Done)
1308 return (Done == Other.Done);
1309 // Not equal if different stack sizes.
1310 if (Stack.size() != Other.Stack.size())
1312 // Not equal if different cumulative strings.
1313 if (!CumulativeString.equals(Other.CumulativeString))
1315 // Equal if all nodes in both stacks match.
1316 for (unsigned i=0; i < Stack.size(); ++i) {
1317 if (Stack[i].Start != Other.Stack[i].Start)
1323 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1325 uint64_t Result = decodeULEB128(Ptr, &Count);
1327 if (Ptr > Trie.end()) {
1334 StringRef ExportEntry::name() const {
1335 return CumulativeString;
1338 uint64_t ExportEntry::flags() const {
1339 return Stack.back().Flags;
1342 uint64_t ExportEntry::address() const {
1343 return Stack.back().Address;
1346 uint64_t ExportEntry::other() const {
1347 return Stack.back().Other;
1350 StringRef ExportEntry::otherName() const {
1351 const char* ImportName = Stack.back().ImportName;
1353 return StringRef(ImportName);
1357 uint32_t ExportEntry::nodeOffset() const {
1358 return Stack.back().Start - Trie.begin();
1361 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1362 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1363 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1364 ParentStringLength(0), IsExportNode(false) {
1367 void ExportEntry::pushNode(uint64_t offset) {
1368 const uint8_t *Ptr = Trie.begin() + offset;
1369 NodeState State(Ptr);
1370 uint64_t ExportInfoSize = readULEB128(State.Current);
1371 State.IsExportNode = (ExportInfoSize != 0);
1372 const uint8_t* Children = State.Current + ExportInfoSize;
1373 if (State.IsExportNode) {
1374 State.Flags = readULEB128(State.Current);
1375 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1377 State.Other = readULEB128(State.Current); // dylib ordinal
1378 State.ImportName = reinterpret_cast<const char*>(State.Current);
1380 State.Address = readULEB128(State.Current);
1381 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1382 State.Other = readULEB128(State.Current);
1385 State.ChildCount = *Children;
1386 State.Current = Children + 1;
1387 State.NextChildIndex = 0;
1388 State.ParentStringLength = CumulativeString.size();
1389 Stack.push_back(State);
1392 void ExportEntry::pushDownUntilBottom() {
1393 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1394 NodeState &Top = Stack.back();
1395 CumulativeString.resize(Top.ParentStringLength);
1396 for (;*Top.Current != 0; Top.Current++) {
1397 char C = *Top.Current;
1398 CumulativeString.push_back(C);
1401 uint64_t childNodeIndex = readULEB128(Top.Current);
1402 Top.NextChildIndex += 1;
1403 pushNode(childNodeIndex);
1405 if (!Stack.back().IsExportNode) {
1411 // We have a trie data structure and need a way to walk it that is compatible
1412 // with the C++ iterator model. The solution is a non-recursive depth first
1413 // traversal where the iterator contains a stack of parent nodes along with a
1414 // string that is the accumulation of all edge strings along the parent chain
1417 // There is one "export" node for each exported symbol. But because some
1418 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1419 // node may have child nodes too.
1421 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1422 // child until hitting a node with no children (which is an export node or
1423 // else the trie is malformed). On the way down, each node is pushed on the
1424 // stack ivar. If there is no more ways down, it pops up one and tries to go
1425 // down a sibling path until a childless node is reached.
1426 void ExportEntry::moveNext() {
1427 if (Stack.empty() || !Stack.back().IsExportNode) {
1434 while (!Stack.empty()) {
1435 NodeState &Top = Stack.back();
1436 if (Top.NextChildIndex < Top.ChildCount) {
1437 pushDownUntilBottom();
1438 // Now at the next export node.
1441 if (Top.IsExportNode) {
1442 // This node has no children but is itself an export node.
1443 CumulativeString.resize(Top.ParentStringLength);
1452 iterator_range<export_iterator>
1453 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1454 ExportEntry Start(Trie);
1455 if (Trie.size() == 0)
1458 Start.moveToFirst();
1460 ExportEntry Finish(Trie);
1463 return iterator_range<export_iterator>(export_iterator(Start),
1464 export_iterator(Finish));
1467 iterator_range<export_iterator> MachOObjectFile::exports() const {
1468 return exports(getDyldInfoExportsTrie());
1472 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1473 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1474 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1475 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1477 void MachORebaseEntry::moveToFirst() {
1478 Ptr = Opcodes.begin();
1482 void MachORebaseEntry::moveToEnd() {
1483 Ptr = Opcodes.end();
1484 RemainingLoopCount = 0;
1488 void MachORebaseEntry::moveNext() {
1489 // If in the middle of some loop, move to next rebasing in loop.
1490 SegmentOffset += AdvanceAmount;
1491 if (RemainingLoopCount) {
1492 --RemainingLoopCount;
1495 if (Ptr == Opcodes.end()) {
1500 while (More && !Malformed) {
1501 // Parse next opcode and set up next loop.
1502 uint8_t Byte = *Ptr++;
1503 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1504 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1506 case MachO::REBASE_OPCODE_DONE:
1510 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1512 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1513 RebaseType = ImmValue;
1516 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1517 << "RebaseType=" << (int) RebaseType << "\n");
1519 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1520 SegmentIndex = ImmValue;
1521 SegmentOffset = readULEB128();
1524 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1525 << "SegmentIndex=" << SegmentIndex << ", "
1526 << format("SegmentOffset=0x%06X", SegmentOffset)
1529 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1530 SegmentOffset += readULEB128();
1531 DEBUG_WITH_TYPE("mach-o-rebase",
1532 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1533 << format("SegmentOffset=0x%06X",
1534 SegmentOffset) << "\n");
1536 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1537 SegmentOffset += ImmValue * PointerSize;
1538 DEBUG_WITH_TYPE("mach-o-rebase",
1539 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1540 << format("SegmentOffset=0x%06X",
1541 SegmentOffset) << "\n");
1543 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1544 AdvanceAmount = PointerSize;
1545 RemainingLoopCount = ImmValue - 1;
1548 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1549 << format("SegmentOffset=0x%06X", SegmentOffset)
1550 << ", AdvanceAmount=" << AdvanceAmount
1551 << ", RemainingLoopCount=" << RemainingLoopCount
1554 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1555 AdvanceAmount = PointerSize;
1556 RemainingLoopCount = readULEB128() - 1;
1559 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1560 << format("SegmentOffset=0x%06X", SegmentOffset)
1561 << ", AdvanceAmount=" << AdvanceAmount
1562 << ", RemainingLoopCount=" << RemainingLoopCount
1565 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1566 AdvanceAmount = readULEB128() + PointerSize;
1567 RemainingLoopCount = 0;
1570 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1571 << format("SegmentOffset=0x%06X", SegmentOffset)
1572 << ", AdvanceAmount=" << AdvanceAmount
1573 << ", RemainingLoopCount=" << RemainingLoopCount
1576 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1577 RemainingLoopCount = readULEB128() - 1;
1578 AdvanceAmount = readULEB128() + PointerSize;
1581 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1582 << format("SegmentOffset=0x%06X", SegmentOffset)
1583 << ", AdvanceAmount=" << AdvanceAmount
1584 << ", RemainingLoopCount=" << RemainingLoopCount
1593 uint64_t MachORebaseEntry::readULEB128() {
1595 uint64_t Result = decodeULEB128(Ptr, &Count);
1597 if (Ptr > Opcodes.end()) {
1598 Ptr = Opcodes.end();
1604 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1606 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1608 StringRef MachORebaseEntry::typeName() const {
1609 switch (RebaseType) {
1610 case MachO::REBASE_TYPE_POINTER:
1612 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1613 return "text abs32";
1614 case MachO::REBASE_TYPE_TEXT_PCREL32:
1615 return "text rel32";
1620 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1621 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1622 return (Ptr == Other.Ptr) &&
1623 (RemainingLoopCount == Other.RemainingLoopCount) &&
1624 (Done == Other.Done);
1627 iterator_range<rebase_iterator>
1628 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1629 MachORebaseEntry Start(Opcodes, is64);
1630 Start.moveToFirst();
1632 MachORebaseEntry Finish(Opcodes, is64);
1635 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1636 rebase_iterator(Finish));
1639 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1640 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1644 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1646 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1647 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1648 BindType(0), PointerSize(is64Bit ? 8 : 4),
1649 TableKind(BK), Malformed(false), Done(false) {}
1651 void MachOBindEntry::moveToFirst() {
1652 Ptr = Opcodes.begin();
1656 void MachOBindEntry::moveToEnd() {
1657 Ptr = Opcodes.end();
1658 RemainingLoopCount = 0;
1662 void MachOBindEntry::moveNext() {
1663 // If in the middle of some loop, move to next binding in loop.
1664 SegmentOffset += AdvanceAmount;
1665 if (RemainingLoopCount) {
1666 --RemainingLoopCount;
1669 if (Ptr == Opcodes.end()) {
1674 while (More && !Malformed) {
1675 // Parse next opcode and set up next loop.
1676 uint8_t Byte = *Ptr++;
1677 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1678 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1679 int8_t SignExtended;
1680 const uint8_t *SymStart;
1682 case MachO::BIND_OPCODE_DONE:
1683 if (TableKind == Kind::Lazy) {
1684 // Lazying bindings have a DONE opcode between entries. Need to ignore
1685 // it to advance to next entry. But need not if this is last entry.
1686 bool NotLastEntry = false;
1687 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1689 NotLastEntry = true;
1698 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1700 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1704 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1705 << "Ordinal=" << Ordinal << "\n");
1707 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1708 Ordinal = readULEB128();
1711 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1712 << "Ordinal=" << Ordinal << "\n");
1714 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1716 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1717 Ordinal = SignExtended;
1722 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1723 << "Ordinal=" << Ordinal << "\n");
1725 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1731 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1736 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1737 << "SymbolName=" << SymbolName << "\n");
1738 if (TableKind == Kind::Weak) {
1739 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1743 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1744 BindType = ImmValue;
1747 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1748 << "BindType=" << (int)BindType << "\n");
1750 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1751 Addend = readSLEB128();
1752 if (TableKind == Kind::Lazy)
1756 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1757 << "Addend=" << Addend << "\n");
1759 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1760 SegmentIndex = ImmValue;
1761 SegmentOffset = readULEB128();
1764 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1765 << "SegmentIndex=" << SegmentIndex << ", "
1766 << format("SegmentOffset=0x%06X", SegmentOffset)
1769 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1770 SegmentOffset += readULEB128();
1771 DEBUG_WITH_TYPE("mach-o-bind",
1772 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1773 << format("SegmentOffset=0x%06X",
1774 SegmentOffset) << "\n");
1776 case MachO::BIND_OPCODE_DO_BIND:
1777 AdvanceAmount = PointerSize;
1778 RemainingLoopCount = 0;
1779 DEBUG_WITH_TYPE("mach-o-bind",
1780 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1781 << format("SegmentOffset=0x%06X",
1782 SegmentOffset) << "\n");
1784 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1785 AdvanceAmount = readULEB128() + PointerSize;
1786 RemainingLoopCount = 0;
1787 if (TableKind == Kind::Lazy)
1791 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1792 << format("SegmentOffset=0x%06X", SegmentOffset)
1793 << ", AdvanceAmount=" << AdvanceAmount
1794 << ", RemainingLoopCount=" << RemainingLoopCount
1797 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1798 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1799 RemainingLoopCount = 0;
1800 if (TableKind == Kind::Lazy)
1802 DEBUG_WITH_TYPE("mach-o-bind",
1804 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1805 << format("SegmentOffset=0x%06X",
1806 SegmentOffset) << "\n");
1808 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1809 RemainingLoopCount = readULEB128() - 1;
1810 AdvanceAmount = readULEB128() + PointerSize;
1811 if (TableKind == Kind::Lazy)
1815 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1816 << format("SegmentOffset=0x%06X", SegmentOffset)
1817 << ", AdvanceAmount=" << AdvanceAmount
1818 << ", RemainingLoopCount=" << RemainingLoopCount
1827 uint64_t MachOBindEntry::readULEB128() {
1829 uint64_t Result = decodeULEB128(Ptr, &Count);
1831 if (Ptr > Opcodes.end()) {
1832 Ptr = Opcodes.end();
1838 int64_t MachOBindEntry::readSLEB128() {
1840 int64_t Result = decodeSLEB128(Ptr, &Count);
1842 if (Ptr > Opcodes.end()) {
1843 Ptr = Opcodes.end();
1850 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1852 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1854 StringRef MachOBindEntry::typeName() const {
1856 case MachO::BIND_TYPE_POINTER:
1858 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1859 return "text abs32";
1860 case MachO::BIND_TYPE_TEXT_PCREL32:
1861 return "text rel32";
1866 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1868 int64_t MachOBindEntry::addend() const { return Addend; }
1870 uint32_t MachOBindEntry::flags() const { return Flags; }
1872 int MachOBindEntry::ordinal() const { return Ordinal; }
1874 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1875 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1876 return (Ptr == Other.Ptr) &&
1877 (RemainingLoopCount == Other.RemainingLoopCount) &&
1878 (Done == Other.Done);
1881 iterator_range<bind_iterator>
1882 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1883 MachOBindEntry::Kind BKind) {
1884 MachOBindEntry Start(Opcodes, is64, BKind);
1885 Start.moveToFirst();
1887 MachOBindEntry Finish(Opcodes, is64, BKind);
1890 return iterator_range<bind_iterator>(bind_iterator(Start),
1891 bind_iterator(Finish));
1894 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1895 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1896 MachOBindEntry::Kind::Regular);
1899 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1900 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1901 MachOBindEntry::Kind::Lazy);
1904 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1905 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1906 MachOBindEntry::Kind::Weak);
1909 MachOObjectFile::load_command_iterator
1910 MachOObjectFile::begin_load_commands() const {
1911 return LoadCommands.begin();
1914 MachOObjectFile::load_command_iterator
1915 MachOObjectFile::end_load_commands() const {
1916 return LoadCommands.end();
1919 iterator_range<MachOObjectFile::load_command_iterator>
1920 MachOObjectFile::load_commands() const {
1921 return iterator_range<load_command_iterator>(begin_load_commands(),
1922 end_load_commands());
1926 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1927 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1928 return parseSegmentOrSectionName(Raw.data());
1932 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1933 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1934 const section_base *Base =
1935 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1936 return makeArrayRef(Base->sectname);
1940 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1941 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1942 const section_base *Base =
1943 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1944 return makeArrayRef(Base->segname);
1948 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1950 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1952 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1955 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1956 const MachO::any_relocation_info &RE) const {
1957 if (isLittleEndian())
1958 return RE.r_word1 & 0xffffff;
1959 return RE.r_word1 >> 8;
1962 bool MachOObjectFile::getPlainRelocationExternal(
1963 const MachO::any_relocation_info &RE) const {
1964 if (isLittleEndian())
1965 return (RE.r_word1 >> 27) & 1;
1966 return (RE.r_word1 >> 4) & 1;
1969 bool MachOObjectFile::getScatteredRelocationScattered(
1970 const MachO::any_relocation_info &RE) const {
1971 return RE.r_word0 >> 31;
1974 uint32_t MachOObjectFile::getScatteredRelocationValue(
1975 const MachO::any_relocation_info &RE) const {
1979 uint32_t MachOObjectFile::getScatteredRelocationType(
1980 const MachO::any_relocation_info &RE) const {
1981 return (RE.r_word0 >> 24) & 0xf;
1984 unsigned MachOObjectFile::getAnyRelocationAddress(
1985 const MachO::any_relocation_info &RE) const {
1986 if (isRelocationScattered(RE))
1987 return getScatteredRelocationAddress(RE);
1988 return getPlainRelocationAddress(RE);
1991 unsigned MachOObjectFile::getAnyRelocationPCRel(
1992 const MachO::any_relocation_info &RE) const {
1993 if (isRelocationScattered(RE))
1994 return getScatteredRelocationPCRel(this, RE);
1995 return getPlainRelocationPCRel(this, RE);
1998 unsigned MachOObjectFile::getAnyRelocationLength(
1999 const MachO::any_relocation_info &RE) const {
2000 if (isRelocationScattered(RE))
2001 return getScatteredRelocationLength(RE);
2002 return getPlainRelocationLength(this, RE);
2006 MachOObjectFile::getAnyRelocationType(
2007 const MachO::any_relocation_info &RE) const {
2008 if (isRelocationScattered(RE))
2009 return getScatteredRelocationType(RE);
2010 return getPlainRelocationType(this, RE);
2014 MachOObjectFile::getAnyRelocationSection(
2015 const MachO::any_relocation_info &RE) const {
2016 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2017 return *section_end();
2018 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2021 return SectionRef(DRI, this);
2024 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2025 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2026 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2029 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2030 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2031 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2034 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2035 unsigned Index) const {
2036 const char *Sec = getSectionPtr(this, L, Index);
2037 return getStruct<MachO::section>(this, Sec);
2040 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2041 unsigned Index) const {
2042 const char *Sec = getSectionPtr(this, L, Index);
2043 return getStruct<MachO::section_64>(this, Sec);
2047 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2048 const char *P = reinterpret_cast<const char *>(DRI.p);
2049 return getStruct<MachO::nlist>(this, P);
2053 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2054 const char *P = reinterpret_cast<const char *>(DRI.p);
2055 return getStruct<MachO::nlist_64>(this, P);
2058 MachO::linkedit_data_command
2059 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2063 MachO::segment_command
2064 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::segment_command>(this, L.Ptr);
2068 MachO::segment_command_64
2069 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2073 MachO::linker_option_command
2074 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2078 MachO::version_min_command
2079 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::version_min_command>(this, L.Ptr);
2083 MachO::dylib_command
2084 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::dylib_command>(this, L.Ptr);
2088 MachO::dyld_info_command
2089 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2093 MachO::dylinker_command
2094 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2095 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2099 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2100 return getStruct<MachO::uuid_command>(this, L.Ptr);
2103 MachO::rpath_command
2104 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2105 return getStruct<MachO::rpath_command>(this, L.Ptr);
2108 MachO::source_version_command
2109 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2110 return getStruct<MachO::source_version_command>(this, L.Ptr);
2113 MachO::entry_point_command
2114 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2115 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2118 MachO::encryption_info_command
2119 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2120 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2123 MachO::encryption_info_command_64
2124 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2125 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2128 MachO::sub_framework_command
2129 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2130 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2133 MachO::sub_umbrella_command
2134 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2135 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2138 MachO::sub_library_command
2139 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2140 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2143 MachO::sub_client_command
2144 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2145 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2148 MachO::routines_command
2149 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2150 return getStruct<MachO::routines_command>(this, L.Ptr);
2153 MachO::routines_command_64
2154 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2155 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2158 MachO::thread_command
2159 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2160 return getStruct<MachO::thread_command>(this, L.Ptr);
2163 MachO::any_relocation_info
2164 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2169 MachO::section_64 Sect = getSection64(Sec);
2170 Offset = Sect.reloff;
2172 MachO::section Sect = getSection(Sec);
2173 Offset = Sect.reloff;
2176 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2177 getPtr(this, Offset)) + Rel.d.b;
2178 return getStruct<MachO::any_relocation_info>(
2179 this, reinterpret_cast<const char *>(P));
2182 MachO::data_in_code_entry
2183 MachOObjectFile::getDice(DataRefImpl Rel) const {
2184 const char *P = reinterpret_cast<const char *>(Rel.p);
2185 return getStruct<MachO::data_in_code_entry>(this, P);
2188 const MachO::mach_header &MachOObjectFile::getHeader() const {
2189 // First fields of MachO::mach_header_64 are the same as
2190 // in MachO::mach_header.
2191 return *reinterpret_cast<const MachO::mach_header *>(&this->Header64);
2194 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2199 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2200 const MachO::dysymtab_command &DLC,
2201 unsigned Index) const {
2202 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2203 return getStruct<uint32_t>(this, getPtr(this, Offset));
2206 MachO::data_in_code_entry
2207 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2208 unsigned Index) const {
2209 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2210 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2213 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2215 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2217 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2218 MachO::symtab_command Cmd;
2219 Cmd.cmd = MachO::LC_SYMTAB;
2220 Cmd.cmdsize = sizeof(MachO::symtab_command);
2228 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2229 if (DysymtabLoadCmd)
2230 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2232 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2233 MachO::dysymtab_command Cmd;
2234 Cmd.cmd = MachO::LC_DYSYMTAB;
2235 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2246 Cmd.extrefsymoff = 0;
2247 Cmd.nextrefsyms = 0;
2248 Cmd.indirectsymoff = 0;
2249 Cmd.nindirectsyms = 0;
2257 MachO::linkedit_data_command
2258 MachOObjectFile::getDataInCodeLoadCommand() const {
2259 if (DataInCodeLoadCmd)
2260 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2262 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2263 MachO::linkedit_data_command Cmd;
2264 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2265 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2271 MachO::linkedit_data_command
2272 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2273 if (LinkOptHintsLoadCmd)
2274 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2276 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2278 MachO::linkedit_data_command Cmd;
2279 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2280 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2286 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2287 if (!DyldInfoLoadCmd)
2288 return ArrayRef<uint8_t>();
2290 MachO::dyld_info_command DyldInfo
2291 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2292 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2293 getPtr(this, DyldInfo.rebase_off));
2294 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2297 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2298 if (!DyldInfoLoadCmd)
2299 return ArrayRef<uint8_t>();
2301 MachO::dyld_info_command DyldInfo
2302 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2303 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2304 getPtr(this, DyldInfo.bind_off));
2305 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2308 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2309 if (!DyldInfoLoadCmd)
2310 return ArrayRef<uint8_t>();
2312 MachO::dyld_info_command DyldInfo
2313 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2314 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2315 getPtr(this, DyldInfo.weak_bind_off));
2316 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2319 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2320 if (!DyldInfoLoadCmd)
2321 return ArrayRef<uint8_t>();
2323 MachO::dyld_info_command DyldInfo
2324 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2325 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2326 getPtr(this, DyldInfo.lazy_bind_off));
2327 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2330 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2331 if (!DyldInfoLoadCmd)
2332 return ArrayRef<uint8_t>();
2334 MachO::dyld_info_command DyldInfo
2335 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2336 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2337 getPtr(this, DyldInfo.export_off));
2338 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2341 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2343 return ArrayRef<uint8_t>();
2344 // Returning a pointer is fine as uuid doesn't need endian swapping.
2345 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2346 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2349 StringRef MachOObjectFile::getStringTableData() const {
2350 MachO::symtab_command S = getSymtabLoadCommand();
2351 return getData().substr(S.stroff, S.strsize);
2354 bool MachOObjectFile::is64Bit() const {
2355 return getType() == getMachOType(false, true) ||
2356 getType() == getMachOType(true, true);
2359 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2360 SmallVectorImpl<uint64_t> &Out) const {
2361 DataExtractor extractor(ObjectFile::getData(), true, 0);
2363 uint32_t offset = Index;
2365 while (uint64_t delta = extractor.getULEB128(&offset)) {
2367 Out.push_back(data);
2371 bool MachOObjectFile::isRelocatableObject() const {
2372 return getHeader().filetype == MachO::MH_OBJECT;
2375 ErrorOr<std::unique_ptr<MachOObjectFile>>
2376 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2377 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2379 std::unique_ptr<MachOObjectFile> Ret;
2380 if (Magic == "\xFE\xED\xFA\xCE")
2381 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2382 else if (Magic == "\xCE\xFA\xED\xFE")
2383 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2384 else if (Magic == "\xFE\xED\xFA\xCF")
2385 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2386 else if (Magic == "\xCF\xFA\xED\xFE")
2387 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2389 return object_error::parse_failed;
2393 return std::move(Ret);