1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
41 // FIXME: Replace all uses of this function with getStructOrErr.
43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
87 static MachO::nlist_base
88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
93 static StringRef parseSegmentOrSectionName(const char *P) {
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
101 // Helper to advance a section or symbol iterator multiple increments at a time.
103 static void advance(T &it, size_t Val) {
108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile *O,
157 MachO::section_64 Sect = O->getSection64(Sec);
160 MachO::section Sect = O->getSection(Sec);
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
173 Load.C = CmdOrErr.get();
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
190 template <typename T>
191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
195 Header = HeaderOrErr.get();
197 EC = HeaderOrErr.getError();
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
235 parseHeader(this, Header64, EC);
237 parseHeader(this, Header, EC);
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
247 EC = LoadOrErr.getError();
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
256 EC = object_error::parse_failed;
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
292 EC = object_error::parse_failed;
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
314 EC = LoadOrErr.getError();
317 Load = LoadOrErr.get();
320 assert(LoadCommands.size() == LoadCommandCount);
323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
330 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
334 const char *Start = &StringTable.data()[Entry.n_strx];
335 if (Start < getData().begin() || Start >= getData().end())
337 "Symbol name entry points before beginning or past end of file.");
338 Res = StringRef(Start);
339 return std::error_code();
342 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
343 DataRefImpl DRI = Sec.getRawDataRefImpl();
344 uint32_t Flags = getSectionFlags(this, DRI);
345 return Flags & MachO::SECTION_TYPE;
348 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
350 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
351 return Entry.n_value;
353 MachO::nlist Entry = getSymbolTableEntry(Sym);
354 return Entry.n_value;
357 // getIndirectName() returns the name of the alias'ed symbol who's string table
358 // index is in the n_value field.
359 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
360 StringRef &Res) const {
361 StringRef StringTable = getStringTableData();
362 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
363 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
364 return object_error::parse_failed;
365 uint64_t NValue = getNValue(Symb);
366 if (NValue >= StringTable.size())
367 return object_error::parse_failed;
368 const char *Start = &StringTable.data()[NValue];
369 Res = StringRef(Start);
370 return std::error_code();
373 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
374 uint64_t NValue = getNValue(Sym);
375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
377 return UnknownAddress;
381 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
382 uint64_t &Res) const {
383 Res = getSymbolValue(Sym);
384 return std::error_code();
387 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
388 uint32_t flags = getSymbolFlags(DRI);
389 if (flags & SymbolRef::SF_Common) {
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
391 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
396 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
398 getSymbolAddress(DRI, Value);
402 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
403 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
404 uint8_t n_type = Entry.n_type;
406 // If this is a STAB debugging symbol, we can do nothing more.
407 if (n_type & MachO::N_STAB)
408 return SymbolRef::ST_Debug;
410 switch (n_type & MachO::N_TYPE) {
412 return SymbolRef::ST_Unknown;
414 return SymbolRef::ST_Function;
416 return SymbolRef::ST_Other;
419 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
420 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
422 uint8_t MachOType = Entry.n_type;
423 uint16_t MachOFlags = Entry.n_desc;
425 uint32_t Result = SymbolRef::SF_None;
427 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
428 Result |= SymbolRef::SF_Undefined;
430 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
431 Result |= SymbolRef::SF_Indirect;
433 if (MachOType & MachO::N_STAB)
434 Result |= SymbolRef::SF_FormatSpecific;
436 if (MachOType & MachO::N_EXT) {
437 Result |= SymbolRef::SF_Global;
438 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
440 getSymbolAddress(DRI, Value);
441 if (Value && Value != UnknownAddress)
442 Result |= SymbolRef::SF_Common;
445 if (!(MachOType & MachO::N_PEXT))
446 Result |= SymbolRef::SF_Exported;
449 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
450 Result |= SymbolRef::SF_Weak;
452 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
453 Result |= SymbolRef::SF_Thumb;
455 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
456 Result |= SymbolRef::SF_Absolute;
461 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
462 section_iterator &Res) const {
463 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
464 uint8_t index = Entry.n_sect;
471 if (DRI.d.a >= Sections.size())
472 report_fatal_error("getSymbolSection: Invalid section index.");
473 Res = section_iterator(SectionRef(DRI, this));
476 return std::error_code();
479 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
480 MachO::nlist_base Entry =
481 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
482 return Entry.n_sect - 1;
485 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
489 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
490 StringRef &Result) const {
491 ArrayRef<char> Raw = getSectionRawName(Sec);
492 Result = parseSegmentOrSectionName(Raw.data());
493 return std::error_code();
496 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
498 return getSection64(Sec).addr;
499 return getSection(Sec).addr;
502 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
504 return getSection64(Sec).size;
505 return getSection(Sec).size;
508 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
509 StringRef &Res) const {
514 MachO::section_64 Sect = getSection64(Sec);
515 Offset = Sect.offset;
518 MachO::section Sect = getSection(Sec);
519 Offset = Sect.offset;
523 Res = this->getData().substr(Offset, Size);
524 return std::error_code();
527 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
530 MachO::section_64 Sect = getSection64(Sec);
533 MachO::section Sect = getSection(Sec);
537 return uint64_t(1) << Align;
540 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
545 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
546 uint32_t Flags = getSectionFlags(this, Sec);
547 unsigned SectionType = Flags & MachO::SECTION_TYPE;
548 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
549 !(SectionType == MachO::S_ZEROFILL ||
550 SectionType == MachO::S_GB_ZEROFILL);
553 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
554 uint32_t Flags = getSectionFlags(this, Sec);
555 unsigned SectionType = Flags & MachO::SECTION_TYPE;
556 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
557 (SectionType == MachO::S_ZEROFILL ||
558 SectionType == MachO::S_GB_ZEROFILL);
561 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
562 return Sec.getRawDataRefImpl().d.a;
565 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
566 // FIXME: Unimplemented.
570 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
571 DataRefImpl Symb) const {
572 SymbolRef::Type ST = getSymbolType(Symb);
573 if (ST == SymbolRef::ST_Unknown)
576 uint64_t SectBegin = getSectionAddress(Sec);
577 uint64_t SectEnd = getSectionSize(Sec);
578 SectEnd += SectBegin;
581 getSymbolAddress(Symb, SymAddr);
582 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
585 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
589 return relocation_iterator(RelocationRef(Ret, this));
593 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
596 MachO::section_64 Sect = getSection64(Sec);
599 MachO::section Sect = getSection(Sec);
606 return relocation_iterator(RelocationRef(Ret, this));
609 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
613 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
614 uint64_t &Res) const {
615 uint64_t Offset = getRelocationOffset(Rel);
619 uint64_t SecAddress = getSectionAddress(Sec);
620 Res = SecAddress + Offset;
621 return std::error_code();
624 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
625 assert(getHeader().filetype == MachO::MH_OBJECT &&
626 "Only implemented for MH_OBJECT");
627 MachO::any_relocation_info RE = getRelocation(Rel);
628 return getAnyRelocationAddress(RE);
632 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
633 MachO::any_relocation_info RE = getRelocation(Rel);
634 if (isRelocationScattered(RE))
637 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
638 bool isExtern = getPlainRelocationExternal(RE);
642 MachO::symtab_command S = getSymtabLoadCommand();
643 unsigned SymbolTableEntrySize = is64Bit() ?
644 sizeof(MachO::nlist_64) :
645 sizeof(MachO::nlist);
646 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
648 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
649 return symbol_iterator(SymbolRef(Sym, this));
653 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
654 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
657 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
658 MachO::any_relocation_info RE = getRelocation(Rel);
659 return getAnyRelocationType(RE);
662 void MachOObjectFile::getRelocationTypeName(
663 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
665 uint64_t RType = getRelocationType(Rel);
667 unsigned Arch = this->getArch();
671 static const char *const Table[] = {
672 "GENERIC_RELOC_VANILLA",
673 "GENERIC_RELOC_PAIR",
674 "GENERIC_RELOC_SECTDIFF",
675 "GENERIC_RELOC_PB_LA_PTR",
676 "GENERIC_RELOC_LOCAL_SECTDIFF",
677 "GENERIC_RELOC_TLV" };
685 case Triple::x86_64: {
686 static const char *const Table[] = {
687 "X86_64_RELOC_UNSIGNED",
688 "X86_64_RELOC_SIGNED",
689 "X86_64_RELOC_BRANCH",
690 "X86_64_RELOC_GOT_LOAD",
692 "X86_64_RELOC_SUBTRACTOR",
693 "X86_64_RELOC_SIGNED_1",
694 "X86_64_RELOC_SIGNED_2",
695 "X86_64_RELOC_SIGNED_4",
696 "X86_64_RELOC_TLV" };
705 static const char *const Table[] = {
708 "ARM_RELOC_SECTDIFF",
709 "ARM_RELOC_LOCAL_SECTDIFF",
710 "ARM_RELOC_PB_LA_PTR",
712 "ARM_THUMB_RELOC_BR22",
713 "ARM_THUMB_32BIT_BRANCH",
715 "ARM_RELOC_HALF_SECTDIFF" };
723 case Triple::aarch64: {
724 static const char *const Table[] = {
725 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
726 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
727 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
728 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
729 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
733 if (RType >= array_lengthof(Table))
740 static const char *const Table[] = {
749 "PPC_RELOC_SECTDIFF",
750 "PPC_RELOC_PB_LA_PTR",
751 "PPC_RELOC_HI16_SECTDIFF",
752 "PPC_RELOC_LO16_SECTDIFF",
753 "PPC_RELOC_HA16_SECTDIFF",
755 "PPC_RELOC_LO14_SECTDIFF",
756 "PPC_RELOC_LOCAL_SECTDIFF" };
764 case Triple::UnknownArch:
768 Result.append(res.begin(), res.end());
771 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
772 MachO::any_relocation_info RE = getRelocation(Rel);
773 return getAnyRelocationLength(RE);
777 // guessLibraryShortName() is passed a name of a dynamic library and returns a
778 // guess on what the short name is. Then name is returned as a substring of the
779 // StringRef Name passed in. The name of the dynamic library is recognized as
780 // a framework if it has one of the two following forms:
781 // Foo.framework/Versions/A/Foo
783 // Where A and Foo can be any string. And may contain a trailing suffix
784 // starting with an underbar. If the Name is recognized as a framework then
785 // isFramework is set to true else it is set to false. If the Name has a
786 // suffix then Suffix is set to the substring in Name that contains the suffix
787 // else it is set to a NULL StringRef.
789 // The Name of the dynamic library is recognized as a library name if it has
790 // one of the two following forms:
793 // The library may have a suffix trailing the name Foo of the form:
794 // libFoo_profile.A.dylib
795 // libFoo_profile.dylib
797 // The Name of the dynamic library is also recognized as a library name if it
798 // has the following form:
801 // If the Name of the dynamic library is none of the forms above then a NULL
802 // StringRef is returned.
804 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
807 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
808 size_t a, b, c, d, Idx;
811 Suffix = StringRef();
813 // Pull off the last component and make Foo point to it
815 if (a == Name.npos || a == 0)
817 Foo = Name.slice(a+1, Name.npos);
819 // Look for a suffix starting with a '_'
820 Idx = Foo.rfind('_');
821 if (Idx != Foo.npos && Foo.size() >= 2) {
822 Suffix = Foo.slice(Idx, Foo.npos);
823 Foo = Foo.slice(0, Idx);
826 // First look for the form Foo.framework/Foo
827 b = Name.rfind('/', a);
832 F = Name.slice(Idx, Idx + Foo.size());
833 DotFramework = Name.slice(Idx + Foo.size(),
834 Idx + Foo.size() + sizeof(".framework/")-1);
835 if (F == Foo && DotFramework == ".framework/") {
840 // Next look for the form Foo.framework/Versions/A/Foo
843 c = Name.rfind('/', b);
844 if (c == Name.npos || c == 0)
846 V = Name.slice(c+1, Name.npos);
847 if (!V.startswith("Versions/"))
849 d = Name.rfind('/', c);
854 F = Name.slice(Idx, Idx + Foo.size());
855 DotFramework = Name.slice(Idx + Foo.size(),
856 Idx + Foo.size() + sizeof(".framework/")-1);
857 if (F == Foo && DotFramework == ".framework/") {
863 // pull off the suffix after the "." and make a point to it
865 if (a == Name.npos || a == 0)
867 Dylib = Name.slice(a, Name.npos);
868 if (Dylib != ".dylib")
871 // First pull off the version letter for the form Foo.A.dylib if any.
873 Dot = Name.slice(a-2, a-1);
878 b = Name.rfind('/', a);
883 // ignore any suffix after an underbar like Foo_profile.A.dylib
884 Idx = Name.find('_', b);
885 if (Idx != Name.npos && Idx != b) {
886 Lib = Name.slice(b, Idx);
887 Suffix = Name.slice(Idx, a);
890 Lib = Name.slice(b, a);
891 // There are incorrect library names of the form:
892 // libATS.A_profile.dylib so check for these.
893 if (Lib.size() >= 3) {
894 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
896 Lib = Lib.slice(0, Lib.size()-2);
901 Qtx = Name.slice(a, Name.npos);
904 b = Name.rfind('/', a);
906 Lib = Name.slice(0, a);
908 Lib = Name.slice(b+1, a);
909 // There are library names of the form: QT.A.qtx so check for these.
910 if (Lib.size() >= 3) {
911 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
913 Lib = Lib.slice(0, Lib.size()-2);
918 // getLibraryShortNameByIndex() is used to get the short name of the library
919 // for an undefined symbol in a linked Mach-O binary that was linked with the
920 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
921 // It is passed the index (0 - based) of the library as translated from
922 // GET_LIBRARY_ORDINAL (1 - based).
923 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
924 StringRef &Res) const {
925 if (Index >= Libraries.size())
926 return object_error::parse_failed;
928 // If the cache of LibrariesShortNames is not built up do that first for
929 // all the Libraries.
930 if (LibrariesShortNames.size() == 0) {
931 for (unsigned i = 0; i < Libraries.size(); i++) {
932 MachO::dylib_command D =
933 getStruct<MachO::dylib_command>(this, Libraries[i]);
934 if (D.dylib.name >= D.cmdsize)
935 return object_error::parse_failed;
936 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
937 StringRef Name = StringRef(P);
938 if (D.dylib.name+Name.size() >= D.cmdsize)
939 return object_error::parse_failed;
942 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
943 if (shortName.empty())
944 LibrariesShortNames.push_back(Name);
946 LibrariesShortNames.push_back(shortName);
950 Res = LibrariesShortNames[Index];
951 return std::error_code();
954 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
955 return getSymbolByIndex(0);
958 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
961 return basic_symbol_iterator(SymbolRef(DRI, this));
963 MachO::symtab_command Symtab = getSymtabLoadCommand();
964 unsigned SymbolTableEntrySize = is64Bit() ?
965 sizeof(MachO::nlist_64) :
966 sizeof(MachO::nlist);
967 unsigned Offset = Symtab.symoff +
968 Symtab.nsyms * SymbolTableEntrySize;
969 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
970 return basic_symbol_iterator(SymbolRef(DRI, this));
973 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
976 return basic_symbol_iterator(SymbolRef(DRI, this));
978 MachO::symtab_command Symtab = getSymtabLoadCommand();
979 if (Index >= Symtab.nsyms)
980 report_fatal_error("Requested symbol index is out of range.");
981 unsigned SymbolTableEntrySize =
982 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
983 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
984 DRI.p += Index * SymbolTableEntrySize;
985 return basic_symbol_iterator(SymbolRef(DRI, this));
988 section_iterator MachOObjectFile::section_begin() const {
990 return section_iterator(SectionRef(DRI, this));
993 section_iterator MachOObjectFile::section_end() const {
995 DRI.d.a = Sections.size();
996 return section_iterator(SectionRef(DRI, this));
999 uint8_t MachOObjectFile::getBytesInAddress() const {
1000 return is64Bit() ? 8 : 4;
1003 StringRef MachOObjectFile::getFileFormatName() const {
1004 unsigned CPUType = getCPUType(this);
1007 case llvm::MachO::CPU_TYPE_I386:
1008 return "Mach-O 32-bit i386";
1009 case llvm::MachO::CPU_TYPE_ARM:
1010 return "Mach-O arm";
1011 case llvm::MachO::CPU_TYPE_POWERPC:
1012 return "Mach-O 32-bit ppc";
1014 return "Mach-O 32-bit unknown";
1019 case llvm::MachO::CPU_TYPE_X86_64:
1020 return "Mach-O 64-bit x86-64";
1021 case llvm::MachO::CPU_TYPE_ARM64:
1022 return "Mach-O arm64";
1023 case llvm::MachO::CPU_TYPE_POWERPC64:
1024 return "Mach-O 64-bit ppc64";
1026 return "Mach-O 64-bit unknown";
1030 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1032 case llvm::MachO::CPU_TYPE_I386:
1034 case llvm::MachO::CPU_TYPE_X86_64:
1035 return Triple::x86_64;
1036 case llvm::MachO::CPU_TYPE_ARM:
1038 case llvm::MachO::CPU_TYPE_ARM64:
1039 return Triple::aarch64;
1040 case llvm::MachO::CPU_TYPE_POWERPC:
1042 case llvm::MachO::CPU_TYPE_POWERPC64:
1043 return Triple::ppc64;
1045 return Triple::UnknownArch;
1049 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1050 const char **McpuDefault) {
1052 *McpuDefault = nullptr;
1055 case MachO::CPU_TYPE_I386:
1056 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1057 case MachO::CPU_SUBTYPE_I386_ALL:
1058 return Triple("i386-apple-darwin");
1062 case MachO::CPU_TYPE_X86_64:
1063 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1064 case MachO::CPU_SUBTYPE_X86_64_ALL:
1065 return Triple("x86_64-apple-darwin");
1066 case MachO::CPU_SUBTYPE_X86_64_H:
1067 return Triple("x86_64h-apple-darwin");
1071 case MachO::CPU_TYPE_ARM:
1072 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1073 case MachO::CPU_SUBTYPE_ARM_V4T:
1074 return Triple("armv4t-apple-darwin");
1075 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1076 return Triple("armv5e-apple-darwin");
1077 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1078 return Triple("xscale-apple-darwin");
1079 case MachO::CPU_SUBTYPE_ARM_V6:
1080 return Triple("armv6-apple-darwin");
1081 case MachO::CPU_SUBTYPE_ARM_V6M:
1083 *McpuDefault = "cortex-m0";
1084 return Triple("armv6m-apple-darwin");
1085 case MachO::CPU_SUBTYPE_ARM_V7:
1086 return Triple("armv7-apple-darwin");
1087 case MachO::CPU_SUBTYPE_ARM_V7EM:
1089 *McpuDefault = "cortex-m4";
1090 return Triple("armv7em-apple-darwin");
1091 case MachO::CPU_SUBTYPE_ARM_V7K:
1092 return Triple("armv7k-apple-darwin");
1093 case MachO::CPU_SUBTYPE_ARM_V7M:
1095 *McpuDefault = "cortex-m3";
1096 return Triple("armv7m-apple-darwin");
1097 case MachO::CPU_SUBTYPE_ARM_V7S:
1098 return Triple("armv7s-apple-darwin");
1102 case MachO::CPU_TYPE_ARM64:
1103 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1104 case MachO::CPU_SUBTYPE_ARM64_ALL:
1105 return Triple("arm64-apple-darwin");
1109 case MachO::CPU_TYPE_POWERPC:
1110 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1111 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1112 return Triple("ppc-apple-darwin");
1116 case MachO::CPU_TYPE_POWERPC64:
1117 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1118 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1119 return Triple("ppc64-apple-darwin");
1128 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1129 const char **McpuDefault) {
1131 *McpuDefault = nullptr;
1134 case MachO::CPU_TYPE_ARM:
1135 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1136 case MachO::CPU_SUBTYPE_ARM_V4T:
1137 return Triple("thumbv4t-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1139 return Triple("thumbv5e-apple-darwin");
1140 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1141 return Triple("xscale-apple-darwin");
1142 case MachO::CPU_SUBTYPE_ARM_V6:
1143 return Triple("thumbv6-apple-darwin");
1144 case MachO::CPU_SUBTYPE_ARM_V6M:
1146 *McpuDefault = "cortex-m0";
1147 return Triple("thumbv6m-apple-darwin");
1148 case MachO::CPU_SUBTYPE_ARM_V7:
1149 return Triple("thumbv7-apple-darwin");
1150 case MachO::CPU_SUBTYPE_ARM_V7EM:
1152 *McpuDefault = "cortex-m4";
1153 return Triple("thumbv7em-apple-darwin");
1154 case MachO::CPU_SUBTYPE_ARM_V7K:
1155 return Triple("thumbv7k-apple-darwin");
1156 case MachO::CPU_SUBTYPE_ARM_V7M:
1158 *McpuDefault = "cortex-m3";
1159 return Triple("thumbv7m-apple-darwin");
1160 case MachO::CPU_SUBTYPE_ARM_V7S:
1161 return Triple("thumbv7s-apple-darwin");
1170 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1171 const char **McpuDefault,
1172 Triple *ThumbTriple) {
1173 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1174 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1179 Triple MachOObjectFile::getHostArch() {
1180 return Triple(sys::getDefaultTargetTriple());
1183 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1184 return StringSwitch<bool>(ArchFlag)
1186 .Case("x86_64", true)
1187 .Case("x86_64h", true)
1188 .Case("armv4t", true)
1190 .Case("armv5e", true)
1191 .Case("armv6", true)
1192 .Case("armv6m", true)
1193 .Case("armv7", true)
1194 .Case("armv7em", true)
1195 .Case("armv7k", true)
1196 .Case("armv7m", true)
1197 .Case("armv7s", true)
1198 .Case("arm64", true)
1200 .Case("ppc64", true)
1204 unsigned MachOObjectFile::getArch() const {
1205 return getArch(getCPUType(this));
1208 Triple MachOObjectFile::getArch(const char **McpuDefault,
1209 Triple *ThumbTriple) const {
1210 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1211 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1214 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1217 return section_rel_begin(DRI);
1220 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1223 return section_rel_end(DRI);
1226 dice_iterator MachOObjectFile::begin_dices() const {
1228 if (!DataInCodeLoadCmd)
1229 return dice_iterator(DiceRef(DRI, this));
1231 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1233 return dice_iterator(DiceRef(DRI, this));
1236 dice_iterator MachOObjectFile::end_dices() const {
1238 if (!DataInCodeLoadCmd)
1239 return dice_iterator(DiceRef(DRI, this));
1241 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1242 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1243 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1244 return dice_iterator(DiceRef(DRI, this));
1247 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1248 : Trie(T), Malformed(false), Done(false) { }
1250 void ExportEntry::moveToFirst() {
1252 pushDownUntilBottom();
1255 void ExportEntry::moveToEnd() {
1260 bool ExportEntry::operator==(const ExportEntry &Other) const {
1261 // Common case, one at end, other iterating from begin.
1262 if (Done || Other.Done)
1263 return (Done == Other.Done);
1264 // Not equal if different stack sizes.
1265 if (Stack.size() != Other.Stack.size())
1267 // Not equal if different cumulative strings.
1268 if (!CumulativeString.equals(Other.CumulativeString))
1270 // Equal if all nodes in both stacks match.
1271 for (unsigned i=0; i < Stack.size(); ++i) {
1272 if (Stack[i].Start != Other.Stack[i].Start)
1278 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1280 uint64_t Result = decodeULEB128(Ptr, &Count);
1282 if (Ptr > Trie.end()) {
1289 StringRef ExportEntry::name() const {
1290 return CumulativeString;
1293 uint64_t ExportEntry::flags() const {
1294 return Stack.back().Flags;
1297 uint64_t ExportEntry::address() const {
1298 return Stack.back().Address;
1301 uint64_t ExportEntry::other() const {
1302 return Stack.back().Other;
1305 StringRef ExportEntry::otherName() const {
1306 const char* ImportName = Stack.back().ImportName;
1308 return StringRef(ImportName);
1312 uint32_t ExportEntry::nodeOffset() const {
1313 return Stack.back().Start - Trie.begin();
1316 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1317 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1318 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1319 ParentStringLength(0), IsExportNode(false) {
1322 void ExportEntry::pushNode(uint64_t offset) {
1323 const uint8_t *Ptr = Trie.begin() + offset;
1324 NodeState State(Ptr);
1325 uint64_t ExportInfoSize = readULEB128(State.Current);
1326 State.IsExportNode = (ExportInfoSize != 0);
1327 const uint8_t* Children = State.Current + ExportInfoSize;
1328 if (State.IsExportNode) {
1329 State.Flags = readULEB128(State.Current);
1330 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1332 State.Other = readULEB128(State.Current); // dylib ordinal
1333 State.ImportName = reinterpret_cast<const char*>(State.Current);
1335 State.Address = readULEB128(State.Current);
1336 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1337 State.Other = readULEB128(State.Current);
1340 State.ChildCount = *Children;
1341 State.Current = Children + 1;
1342 State.NextChildIndex = 0;
1343 State.ParentStringLength = CumulativeString.size();
1344 Stack.push_back(State);
1347 void ExportEntry::pushDownUntilBottom() {
1348 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1349 NodeState &Top = Stack.back();
1350 CumulativeString.resize(Top.ParentStringLength);
1351 for (;*Top.Current != 0; Top.Current++) {
1352 char C = *Top.Current;
1353 CumulativeString.push_back(C);
1356 uint64_t childNodeIndex = readULEB128(Top.Current);
1357 Top.NextChildIndex += 1;
1358 pushNode(childNodeIndex);
1360 if (!Stack.back().IsExportNode) {
1366 // We have a trie data structure and need a way to walk it that is compatible
1367 // with the C++ iterator model. The solution is a non-recursive depth first
1368 // traversal where the iterator contains a stack of parent nodes along with a
1369 // string that is the accumulation of all edge strings along the parent chain
1372 // There is one "export" node for each exported symbol. But because some
1373 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1374 // node may have child nodes too.
1376 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1377 // child until hitting a node with no children (which is an export node or
1378 // else the trie is malformed). On the way down, each node is pushed on the
1379 // stack ivar. If there is no more ways down, it pops up one and tries to go
1380 // down a sibling path until a childless node is reached.
1381 void ExportEntry::moveNext() {
1382 if (Stack.empty() || !Stack.back().IsExportNode) {
1389 while (!Stack.empty()) {
1390 NodeState &Top = Stack.back();
1391 if (Top.NextChildIndex < Top.ChildCount) {
1392 pushDownUntilBottom();
1393 // Now at the next export node.
1396 if (Top.IsExportNode) {
1397 // This node has no children but is itself an export node.
1398 CumulativeString.resize(Top.ParentStringLength);
1407 iterator_range<export_iterator>
1408 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1409 ExportEntry Start(Trie);
1410 if (Trie.size() == 0)
1413 Start.moveToFirst();
1415 ExportEntry Finish(Trie);
1418 return iterator_range<export_iterator>(export_iterator(Start),
1419 export_iterator(Finish));
1422 iterator_range<export_iterator> MachOObjectFile::exports() const {
1423 return exports(getDyldInfoExportsTrie());
1427 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1428 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1429 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1430 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1432 void MachORebaseEntry::moveToFirst() {
1433 Ptr = Opcodes.begin();
1437 void MachORebaseEntry::moveToEnd() {
1438 Ptr = Opcodes.end();
1439 RemainingLoopCount = 0;
1443 void MachORebaseEntry::moveNext() {
1444 // If in the middle of some loop, move to next rebasing in loop.
1445 SegmentOffset += AdvanceAmount;
1446 if (RemainingLoopCount) {
1447 --RemainingLoopCount;
1450 if (Ptr == Opcodes.end()) {
1455 while (More && !Malformed) {
1456 // Parse next opcode and set up next loop.
1457 uint8_t Byte = *Ptr++;
1458 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1459 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1461 case MachO::REBASE_OPCODE_DONE:
1465 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1467 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1468 RebaseType = ImmValue;
1471 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1472 << "RebaseType=" << (int) RebaseType << "\n");
1474 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1475 SegmentIndex = ImmValue;
1476 SegmentOffset = readULEB128();
1479 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1480 << "SegmentIndex=" << SegmentIndex << ", "
1481 << format("SegmentOffset=0x%06X", SegmentOffset)
1484 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1485 SegmentOffset += readULEB128();
1486 DEBUG_WITH_TYPE("mach-o-rebase",
1487 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1488 << format("SegmentOffset=0x%06X",
1489 SegmentOffset) << "\n");
1491 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1492 SegmentOffset += ImmValue * PointerSize;
1493 DEBUG_WITH_TYPE("mach-o-rebase",
1494 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1495 << format("SegmentOffset=0x%06X",
1496 SegmentOffset) << "\n");
1498 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1499 AdvanceAmount = PointerSize;
1500 RemainingLoopCount = ImmValue - 1;
1503 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1504 << format("SegmentOffset=0x%06X", SegmentOffset)
1505 << ", AdvanceAmount=" << AdvanceAmount
1506 << ", RemainingLoopCount=" << RemainingLoopCount
1509 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1510 AdvanceAmount = PointerSize;
1511 RemainingLoopCount = readULEB128() - 1;
1514 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1515 << format("SegmentOffset=0x%06X", SegmentOffset)
1516 << ", AdvanceAmount=" << AdvanceAmount
1517 << ", RemainingLoopCount=" << RemainingLoopCount
1520 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1521 AdvanceAmount = readULEB128() + PointerSize;
1522 RemainingLoopCount = 0;
1525 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1526 << format("SegmentOffset=0x%06X", SegmentOffset)
1527 << ", AdvanceAmount=" << AdvanceAmount
1528 << ", RemainingLoopCount=" << RemainingLoopCount
1531 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1532 RemainingLoopCount = readULEB128() - 1;
1533 AdvanceAmount = readULEB128() + PointerSize;
1536 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1537 << format("SegmentOffset=0x%06X", SegmentOffset)
1538 << ", AdvanceAmount=" << AdvanceAmount
1539 << ", RemainingLoopCount=" << RemainingLoopCount
1548 uint64_t MachORebaseEntry::readULEB128() {
1550 uint64_t Result = decodeULEB128(Ptr, &Count);
1552 if (Ptr > Opcodes.end()) {
1553 Ptr = Opcodes.end();
1559 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1561 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1563 StringRef MachORebaseEntry::typeName() const {
1564 switch (RebaseType) {
1565 case MachO::REBASE_TYPE_POINTER:
1567 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1568 return "text abs32";
1569 case MachO::REBASE_TYPE_TEXT_PCREL32:
1570 return "text rel32";
1575 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1576 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1577 return (Ptr == Other.Ptr) &&
1578 (RemainingLoopCount == Other.RemainingLoopCount) &&
1579 (Done == Other.Done);
1582 iterator_range<rebase_iterator>
1583 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1584 MachORebaseEntry Start(Opcodes, is64);
1585 Start.moveToFirst();
1587 MachORebaseEntry Finish(Opcodes, is64);
1590 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1591 rebase_iterator(Finish));
1594 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1595 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1599 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1601 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1602 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1603 BindType(0), PointerSize(is64Bit ? 8 : 4),
1604 TableKind(BK), Malformed(false), Done(false) {}
1606 void MachOBindEntry::moveToFirst() {
1607 Ptr = Opcodes.begin();
1611 void MachOBindEntry::moveToEnd() {
1612 Ptr = Opcodes.end();
1613 RemainingLoopCount = 0;
1617 void MachOBindEntry::moveNext() {
1618 // If in the middle of some loop, move to next binding in loop.
1619 SegmentOffset += AdvanceAmount;
1620 if (RemainingLoopCount) {
1621 --RemainingLoopCount;
1624 if (Ptr == Opcodes.end()) {
1629 while (More && !Malformed) {
1630 // Parse next opcode and set up next loop.
1631 uint8_t Byte = *Ptr++;
1632 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1633 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1634 int8_t SignExtended;
1635 const uint8_t *SymStart;
1637 case MachO::BIND_OPCODE_DONE:
1638 if (TableKind == Kind::Lazy) {
1639 // Lazying bindings have a DONE opcode between entries. Need to ignore
1640 // it to advance to next entry. But need not if this is last entry.
1641 bool NotLastEntry = false;
1642 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1644 NotLastEntry = true;
1653 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1655 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1659 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1660 << "Ordinal=" << Ordinal << "\n");
1662 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1663 Ordinal = readULEB128();
1666 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1667 << "Ordinal=" << Ordinal << "\n");
1669 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1671 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1672 Ordinal = SignExtended;
1677 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1678 << "Ordinal=" << Ordinal << "\n");
1680 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1686 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1691 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1692 << "SymbolName=" << SymbolName << "\n");
1693 if (TableKind == Kind::Weak) {
1694 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1698 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1699 BindType = ImmValue;
1702 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1703 << "BindType=" << (int)BindType << "\n");
1705 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1706 Addend = readSLEB128();
1707 if (TableKind == Kind::Lazy)
1711 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1712 << "Addend=" << Addend << "\n");
1714 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1715 SegmentIndex = ImmValue;
1716 SegmentOffset = readULEB128();
1719 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1720 << "SegmentIndex=" << SegmentIndex << ", "
1721 << format("SegmentOffset=0x%06X", SegmentOffset)
1724 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1725 SegmentOffset += readULEB128();
1726 DEBUG_WITH_TYPE("mach-o-bind",
1727 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1728 << format("SegmentOffset=0x%06X",
1729 SegmentOffset) << "\n");
1731 case MachO::BIND_OPCODE_DO_BIND:
1732 AdvanceAmount = PointerSize;
1733 RemainingLoopCount = 0;
1734 DEBUG_WITH_TYPE("mach-o-bind",
1735 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1736 << format("SegmentOffset=0x%06X",
1737 SegmentOffset) << "\n");
1739 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1740 AdvanceAmount = readULEB128() + PointerSize;
1741 RemainingLoopCount = 0;
1742 if (TableKind == Kind::Lazy)
1746 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1747 << format("SegmentOffset=0x%06X", SegmentOffset)
1748 << ", AdvanceAmount=" << AdvanceAmount
1749 << ", RemainingLoopCount=" << RemainingLoopCount
1752 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1753 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1754 RemainingLoopCount = 0;
1755 if (TableKind == Kind::Lazy)
1757 DEBUG_WITH_TYPE("mach-o-bind",
1759 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1760 << format("SegmentOffset=0x%06X",
1761 SegmentOffset) << "\n");
1763 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1764 RemainingLoopCount = readULEB128() - 1;
1765 AdvanceAmount = readULEB128() + PointerSize;
1766 if (TableKind == Kind::Lazy)
1770 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1771 << format("SegmentOffset=0x%06X", SegmentOffset)
1772 << ", AdvanceAmount=" << AdvanceAmount
1773 << ", RemainingLoopCount=" << RemainingLoopCount
1782 uint64_t MachOBindEntry::readULEB128() {
1784 uint64_t Result = decodeULEB128(Ptr, &Count);
1786 if (Ptr > Opcodes.end()) {
1787 Ptr = Opcodes.end();
1793 int64_t MachOBindEntry::readSLEB128() {
1795 int64_t Result = decodeSLEB128(Ptr, &Count);
1797 if (Ptr > Opcodes.end()) {
1798 Ptr = Opcodes.end();
1805 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1807 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1809 StringRef MachOBindEntry::typeName() const {
1811 case MachO::BIND_TYPE_POINTER:
1813 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1814 return "text abs32";
1815 case MachO::BIND_TYPE_TEXT_PCREL32:
1816 return "text rel32";
1821 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1823 int64_t MachOBindEntry::addend() const { return Addend; }
1825 uint32_t MachOBindEntry::flags() const { return Flags; }
1827 int MachOBindEntry::ordinal() const { return Ordinal; }
1829 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1830 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1831 return (Ptr == Other.Ptr) &&
1832 (RemainingLoopCount == Other.RemainingLoopCount) &&
1833 (Done == Other.Done);
1836 iterator_range<bind_iterator>
1837 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1838 MachOBindEntry::Kind BKind) {
1839 MachOBindEntry Start(Opcodes, is64, BKind);
1840 Start.moveToFirst();
1842 MachOBindEntry Finish(Opcodes, is64, BKind);
1845 return iterator_range<bind_iterator>(bind_iterator(Start),
1846 bind_iterator(Finish));
1849 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1850 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1851 MachOBindEntry::Kind::Regular);
1854 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1855 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1856 MachOBindEntry::Kind::Lazy);
1859 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1860 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1861 MachOBindEntry::Kind::Weak);
1864 MachOObjectFile::load_command_iterator
1865 MachOObjectFile::begin_load_commands() const {
1866 return LoadCommands.begin();
1869 MachOObjectFile::load_command_iterator
1870 MachOObjectFile::end_load_commands() const {
1871 return LoadCommands.end();
1874 iterator_range<MachOObjectFile::load_command_iterator>
1875 MachOObjectFile::load_commands() const {
1876 return iterator_range<load_command_iterator>(begin_load_commands(),
1877 end_load_commands());
1881 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1882 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1883 return parseSegmentOrSectionName(Raw.data());
1887 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1888 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1889 const section_base *Base =
1890 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1891 return makeArrayRef(Base->sectname);
1895 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1896 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1897 const section_base *Base =
1898 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1899 return makeArrayRef(Base->segname);
1903 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1905 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1907 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1910 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1911 const MachO::any_relocation_info &RE) const {
1912 if (isLittleEndian())
1913 return RE.r_word1 & 0xffffff;
1914 return RE.r_word1 >> 8;
1917 bool MachOObjectFile::getPlainRelocationExternal(
1918 const MachO::any_relocation_info &RE) const {
1919 if (isLittleEndian())
1920 return (RE.r_word1 >> 27) & 1;
1921 return (RE.r_word1 >> 4) & 1;
1924 bool MachOObjectFile::getScatteredRelocationScattered(
1925 const MachO::any_relocation_info &RE) const {
1926 return RE.r_word0 >> 31;
1929 uint32_t MachOObjectFile::getScatteredRelocationValue(
1930 const MachO::any_relocation_info &RE) const {
1934 uint32_t MachOObjectFile::getScatteredRelocationType(
1935 const MachO::any_relocation_info &RE) const {
1936 return (RE.r_word0 >> 24) & 0xf;
1939 unsigned MachOObjectFile::getAnyRelocationAddress(
1940 const MachO::any_relocation_info &RE) const {
1941 if (isRelocationScattered(RE))
1942 return getScatteredRelocationAddress(RE);
1943 return getPlainRelocationAddress(RE);
1946 unsigned MachOObjectFile::getAnyRelocationPCRel(
1947 const MachO::any_relocation_info &RE) const {
1948 if (isRelocationScattered(RE))
1949 return getScatteredRelocationPCRel(this, RE);
1950 return getPlainRelocationPCRel(this, RE);
1953 unsigned MachOObjectFile::getAnyRelocationLength(
1954 const MachO::any_relocation_info &RE) const {
1955 if (isRelocationScattered(RE))
1956 return getScatteredRelocationLength(RE);
1957 return getPlainRelocationLength(this, RE);
1961 MachOObjectFile::getAnyRelocationType(
1962 const MachO::any_relocation_info &RE) const {
1963 if (isRelocationScattered(RE))
1964 return getScatteredRelocationType(RE);
1965 return getPlainRelocationType(this, RE);
1969 MachOObjectFile::getAnyRelocationSection(
1970 const MachO::any_relocation_info &RE) const {
1971 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1972 return *section_end();
1973 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1974 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1975 return *section_end();
1977 DRI.d.a = SecNum - 1;
1978 return SectionRef(DRI, this);
1981 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1982 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1983 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1986 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1987 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1988 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1991 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1992 unsigned Index) const {
1993 const char *Sec = getSectionPtr(this, L, Index);
1994 return getStruct<MachO::section>(this, Sec);
1997 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1998 unsigned Index) const {
1999 const char *Sec = getSectionPtr(this, L, Index);
2000 return getStruct<MachO::section_64>(this, Sec);
2004 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2005 const char *P = reinterpret_cast<const char *>(DRI.p);
2006 return getStruct<MachO::nlist>(this, P);
2010 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2011 const char *P = reinterpret_cast<const char *>(DRI.p);
2012 return getStruct<MachO::nlist_64>(this, P);
2015 MachO::linkedit_data_command
2016 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2017 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2020 MachO::segment_command
2021 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2022 return getStruct<MachO::segment_command>(this, L.Ptr);
2025 MachO::segment_command_64
2026 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2027 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2030 MachO::linker_option_command
2031 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2032 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2035 MachO::version_min_command
2036 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2037 return getStruct<MachO::version_min_command>(this, L.Ptr);
2040 MachO::dylib_command
2041 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2042 return getStruct<MachO::dylib_command>(this, L.Ptr);
2045 MachO::dyld_info_command
2046 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2047 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2050 MachO::dylinker_command
2051 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2052 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2056 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2057 return getStruct<MachO::uuid_command>(this, L.Ptr);
2060 MachO::rpath_command
2061 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2062 return getStruct<MachO::rpath_command>(this, L.Ptr);
2065 MachO::source_version_command
2066 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2067 return getStruct<MachO::source_version_command>(this, L.Ptr);
2070 MachO::entry_point_command
2071 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2072 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2075 MachO::encryption_info_command
2076 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2077 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2080 MachO::encryption_info_command_64
2081 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2082 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2085 MachO::sub_framework_command
2086 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2087 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2090 MachO::sub_umbrella_command
2091 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2092 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2095 MachO::sub_library_command
2096 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2097 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2100 MachO::sub_client_command
2101 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2102 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2105 MachO::routines_command
2106 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2107 return getStruct<MachO::routines_command>(this, L.Ptr);
2110 MachO::routines_command_64
2111 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2112 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2115 MachO::thread_command
2116 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2117 return getStruct<MachO::thread_command>(this, L.Ptr);
2120 MachO::any_relocation_info
2121 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2126 MachO::section_64 Sect = getSection64(Sec);
2127 Offset = Sect.reloff;
2129 MachO::section Sect = getSection(Sec);
2130 Offset = Sect.reloff;
2133 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2134 getPtr(this, Offset)) + Rel.d.b;
2135 return getStruct<MachO::any_relocation_info>(
2136 this, reinterpret_cast<const char *>(P));
2139 MachO::data_in_code_entry
2140 MachOObjectFile::getDice(DataRefImpl Rel) const {
2141 const char *P = reinterpret_cast<const char *>(Rel.p);
2142 return getStruct<MachO::data_in_code_entry>(this, P);
2145 const MachO::mach_header &MachOObjectFile::getHeader() const {
2149 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2154 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2155 const MachO::dysymtab_command &DLC,
2156 unsigned Index) const {
2157 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2158 return getStruct<uint32_t>(this, getPtr(this, Offset));
2161 MachO::data_in_code_entry
2162 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2163 unsigned Index) const {
2164 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2165 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2168 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2170 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2172 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2173 MachO::symtab_command Cmd;
2174 Cmd.cmd = MachO::LC_SYMTAB;
2175 Cmd.cmdsize = sizeof(MachO::symtab_command);
2183 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2184 if (DysymtabLoadCmd)
2185 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2187 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2188 MachO::dysymtab_command Cmd;
2189 Cmd.cmd = MachO::LC_DYSYMTAB;
2190 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2201 Cmd.extrefsymoff = 0;
2202 Cmd.nextrefsyms = 0;
2203 Cmd.indirectsymoff = 0;
2204 Cmd.nindirectsyms = 0;
2212 MachO::linkedit_data_command
2213 MachOObjectFile::getDataInCodeLoadCommand() const {
2214 if (DataInCodeLoadCmd)
2215 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2217 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2218 MachO::linkedit_data_command Cmd;
2219 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2220 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2226 MachO::linkedit_data_command
2227 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2228 if (LinkOptHintsLoadCmd)
2229 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2231 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2233 MachO::linkedit_data_command Cmd;
2234 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2235 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2241 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2242 if (!DyldInfoLoadCmd)
2243 return ArrayRef<uint8_t>();
2245 MachO::dyld_info_command DyldInfo
2246 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2247 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2248 getPtr(this, DyldInfo.rebase_off));
2249 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2252 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2253 if (!DyldInfoLoadCmd)
2254 return ArrayRef<uint8_t>();
2256 MachO::dyld_info_command DyldInfo
2257 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2258 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2259 getPtr(this, DyldInfo.bind_off));
2260 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2263 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2264 if (!DyldInfoLoadCmd)
2265 return ArrayRef<uint8_t>();
2267 MachO::dyld_info_command DyldInfo
2268 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2269 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2270 getPtr(this, DyldInfo.weak_bind_off));
2271 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2274 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2275 if (!DyldInfoLoadCmd)
2276 return ArrayRef<uint8_t>();
2278 MachO::dyld_info_command DyldInfo
2279 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2280 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2281 getPtr(this, DyldInfo.lazy_bind_off));
2282 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2285 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2286 if (!DyldInfoLoadCmd)
2287 return ArrayRef<uint8_t>();
2289 MachO::dyld_info_command DyldInfo
2290 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2291 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2292 getPtr(this, DyldInfo.export_off));
2293 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2296 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2298 return ArrayRef<uint8_t>();
2299 // Returning a pointer is fine as uuid doesn't need endian swapping.
2300 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2301 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2304 StringRef MachOObjectFile::getStringTableData() const {
2305 MachO::symtab_command S = getSymtabLoadCommand();
2306 return getData().substr(S.stroff, S.strsize);
2309 bool MachOObjectFile::is64Bit() const {
2310 return getType() == getMachOType(false, true) ||
2311 getType() == getMachOType(true, true);
2314 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2315 SmallVectorImpl<uint64_t> &Out) const {
2316 DataExtractor extractor(ObjectFile::getData(), true, 0);
2318 uint32_t offset = Index;
2320 while (uint64_t delta = extractor.getULEB128(&offset)) {
2322 Out.push_back(data);
2326 bool MachOObjectFile::isRelocatableObject() const {
2327 return getHeader().filetype == MachO::MH_OBJECT;
2330 ErrorOr<std::unique_ptr<MachOObjectFile>>
2331 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2332 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2334 std::unique_ptr<MachOObjectFile> Ret;
2335 if (Magic == "\xFE\xED\xFA\xCE")
2336 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2337 else if (Magic == "\xCE\xFA\xED\xFE")
2338 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2339 else if (Magic == "\xFE\xED\xFA\xCF")
2340 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2341 else if (Magic == "\xCF\xFA\xED\xFE")
2342 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2344 return object_error::parse_failed;
2348 return std::move(Ret);