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 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331 StringRef StringTable = getStringTableData();
332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333 const char *Start = &StringTable.data()[Entry.n_strx];
334 if (Start < getData().begin() || Start >= getData().end())
336 "Symbol name entry points before beginning or past end of file.");
337 return StringRef(Start);
340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
359 StringRef StringTable = getStringTableData();
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
368 return std::error_code();
371 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
372 uint64_t NValue = getNValue(Sym);
373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
374 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
375 return UnknownAddress;
379 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
380 return getSymbolValue(Sym);
383 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
384 uint32_t flags = getSymbolFlags(DRI);
385 if (flags & SymbolRef::SF_Common) {
386 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
387 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
392 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
393 return getSymbolValue(DRI);
396 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
397 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
398 uint8_t n_type = Entry.n_type;
400 // If this is a STAB debugging symbol, we can do nothing more.
401 if (n_type & MachO::N_STAB)
402 return SymbolRef::ST_Debug;
404 switch (n_type & MachO::N_TYPE) {
406 return SymbolRef::ST_Unknown;
408 return SymbolRef::ST_Function;
410 return SymbolRef::ST_Other;
413 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
414 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
416 uint8_t MachOType = Entry.n_type;
417 uint16_t MachOFlags = Entry.n_desc;
419 uint32_t Result = SymbolRef::SF_None;
421 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
422 Result |= SymbolRef::SF_Undefined;
424 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
425 Result |= SymbolRef::SF_Indirect;
427 if (MachOType & MachO::N_STAB)
428 Result |= SymbolRef::SF_FormatSpecific;
430 if (MachOType & MachO::N_EXT) {
431 Result |= SymbolRef::SF_Global;
432 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
433 uint64_t Value = getSymbolValue(DRI);
434 if (Value && Value != UnknownAddress)
435 Result |= SymbolRef::SF_Common;
438 if (!(MachOType & MachO::N_PEXT))
439 Result |= SymbolRef::SF_Exported;
442 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
443 Result |= SymbolRef::SF_Weak;
445 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
446 Result |= SymbolRef::SF_Thumb;
448 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
449 Result |= SymbolRef::SF_Absolute;
454 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
455 section_iterator &Res) const {
456 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
457 uint8_t index = Entry.n_sect;
464 if (DRI.d.a >= Sections.size())
465 report_fatal_error("getSymbolSection: Invalid section index.");
466 Res = section_iterator(SectionRef(DRI, this));
469 return std::error_code();
472 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
473 MachO::nlist_base Entry =
474 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
475 return Entry.n_sect - 1;
478 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
482 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
483 StringRef &Result) const {
484 ArrayRef<char> Raw = getSectionRawName(Sec);
485 Result = parseSegmentOrSectionName(Raw.data());
486 return std::error_code();
489 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
491 return getSection64(Sec).addr;
492 return getSection(Sec).addr;
495 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
497 return getSection64(Sec).size;
498 return getSection(Sec).size;
501 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
502 StringRef &Res) const {
507 MachO::section_64 Sect = getSection64(Sec);
508 Offset = Sect.offset;
511 MachO::section Sect = getSection(Sec);
512 Offset = Sect.offset;
516 Res = this->getData().substr(Offset, Size);
517 return std::error_code();
520 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
523 MachO::section_64 Sect = getSection64(Sec);
526 MachO::section Sect = getSection(Sec);
530 return uint64_t(1) << Align;
533 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
534 uint32_t Flags = getSectionFlags(this, Sec);
535 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
538 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
539 uint32_t Flags = getSectionFlags(this, Sec);
540 unsigned SectionType = Flags & MachO::SECTION_TYPE;
541 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
542 !(SectionType == MachO::S_ZEROFILL ||
543 SectionType == MachO::S_GB_ZEROFILL);
546 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
547 uint32_t Flags = getSectionFlags(this, Sec);
548 unsigned SectionType = Flags & MachO::SECTION_TYPE;
549 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
550 (SectionType == MachO::S_ZEROFILL ||
551 SectionType == MachO::S_GB_ZEROFILL);
554 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
555 return Sec.getRawDataRefImpl().d.a;
558 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
559 // FIXME: Unimplemented.
563 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
567 return relocation_iterator(RelocationRef(Ret, this));
571 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
574 MachO::section_64 Sect = getSection64(Sec);
577 MachO::section Sect = getSection(Sec);
584 return relocation_iterator(RelocationRef(Ret, this));
587 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
591 ErrorOr<uint64_t> MachOObjectFile::getRelocationAddress(DataRefImpl Rel) const {
592 uint64_t Offset = getRelocationOffset(Rel);
596 uint64_t SecAddress = getSectionAddress(Sec);
597 return SecAddress + Offset;
600 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
601 assert(getHeader().filetype == MachO::MH_OBJECT &&
602 "Only implemented for MH_OBJECT");
603 MachO::any_relocation_info RE = getRelocation(Rel);
604 return getAnyRelocationAddress(RE);
608 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
609 MachO::any_relocation_info RE = getRelocation(Rel);
610 if (isRelocationScattered(RE))
613 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
614 bool isExtern = getPlainRelocationExternal(RE);
618 MachO::symtab_command S = getSymtabLoadCommand();
619 unsigned SymbolTableEntrySize = is64Bit() ?
620 sizeof(MachO::nlist_64) :
621 sizeof(MachO::nlist);
622 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
624 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
625 return symbol_iterator(SymbolRef(Sym, this));
629 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
630 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
633 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
634 MachO::any_relocation_info RE = getRelocation(Rel);
635 return getAnyRelocationType(RE);
638 void MachOObjectFile::getRelocationTypeName(
639 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
641 uint64_t RType = getRelocationType(Rel);
643 unsigned Arch = this->getArch();
647 static const char *const Table[] = {
648 "GENERIC_RELOC_VANILLA",
649 "GENERIC_RELOC_PAIR",
650 "GENERIC_RELOC_SECTDIFF",
651 "GENERIC_RELOC_PB_LA_PTR",
652 "GENERIC_RELOC_LOCAL_SECTDIFF",
653 "GENERIC_RELOC_TLV" };
661 case Triple::x86_64: {
662 static const char *const Table[] = {
663 "X86_64_RELOC_UNSIGNED",
664 "X86_64_RELOC_SIGNED",
665 "X86_64_RELOC_BRANCH",
666 "X86_64_RELOC_GOT_LOAD",
668 "X86_64_RELOC_SUBTRACTOR",
669 "X86_64_RELOC_SIGNED_1",
670 "X86_64_RELOC_SIGNED_2",
671 "X86_64_RELOC_SIGNED_4",
672 "X86_64_RELOC_TLV" };
681 static const char *const Table[] = {
684 "ARM_RELOC_SECTDIFF",
685 "ARM_RELOC_LOCAL_SECTDIFF",
686 "ARM_RELOC_PB_LA_PTR",
688 "ARM_THUMB_RELOC_BR22",
689 "ARM_THUMB_32BIT_BRANCH",
691 "ARM_RELOC_HALF_SECTDIFF" };
699 case Triple::aarch64: {
700 static const char *const Table[] = {
701 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
702 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
703 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
704 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
705 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
709 if (RType >= array_lengthof(Table))
716 static const char *const Table[] = {
725 "PPC_RELOC_SECTDIFF",
726 "PPC_RELOC_PB_LA_PTR",
727 "PPC_RELOC_HI16_SECTDIFF",
728 "PPC_RELOC_LO16_SECTDIFF",
729 "PPC_RELOC_HA16_SECTDIFF",
731 "PPC_RELOC_LO14_SECTDIFF",
732 "PPC_RELOC_LOCAL_SECTDIFF" };
740 case Triple::UnknownArch:
744 Result.append(res.begin(), res.end());
747 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
748 MachO::any_relocation_info RE = getRelocation(Rel);
749 return getAnyRelocationLength(RE);
753 // guessLibraryShortName() is passed a name of a dynamic library and returns a
754 // guess on what the short name is. Then name is returned as a substring of the
755 // StringRef Name passed in. The name of the dynamic library is recognized as
756 // a framework if it has one of the two following forms:
757 // Foo.framework/Versions/A/Foo
759 // Where A and Foo can be any string. And may contain a trailing suffix
760 // starting with an underbar. If the Name is recognized as a framework then
761 // isFramework is set to true else it is set to false. If the Name has a
762 // suffix then Suffix is set to the substring in Name that contains the suffix
763 // else it is set to a NULL StringRef.
765 // The Name of the dynamic library is recognized as a library name if it has
766 // one of the two following forms:
769 // The library may have a suffix trailing the name Foo of the form:
770 // libFoo_profile.A.dylib
771 // libFoo_profile.dylib
773 // The Name of the dynamic library is also recognized as a library name if it
774 // has the following form:
777 // If the Name of the dynamic library is none of the forms above then a NULL
778 // StringRef is returned.
780 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
783 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
784 size_t a, b, c, d, Idx;
787 Suffix = StringRef();
789 // Pull off the last component and make Foo point to it
791 if (a == Name.npos || a == 0)
793 Foo = Name.slice(a+1, Name.npos);
795 // Look for a suffix starting with a '_'
796 Idx = Foo.rfind('_');
797 if (Idx != Foo.npos && Foo.size() >= 2) {
798 Suffix = Foo.slice(Idx, Foo.npos);
799 Foo = Foo.slice(0, Idx);
802 // First look for the form Foo.framework/Foo
803 b = Name.rfind('/', a);
808 F = Name.slice(Idx, Idx + Foo.size());
809 DotFramework = Name.slice(Idx + Foo.size(),
810 Idx + Foo.size() + sizeof(".framework/")-1);
811 if (F == Foo && DotFramework == ".framework/") {
816 // Next look for the form Foo.framework/Versions/A/Foo
819 c = Name.rfind('/', b);
820 if (c == Name.npos || c == 0)
822 V = Name.slice(c+1, Name.npos);
823 if (!V.startswith("Versions/"))
825 d = Name.rfind('/', c);
830 F = Name.slice(Idx, Idx + Foo.size());
831 DotFramework = Name.slice(Idx + Foo.size(),
832 Idx + Foo.size() + sizeof(".framework/")-1);
833 if (F == Foo && DotFramework == ".framework/") {
839 // pull off the suffix after the "." and make a point to it
841 if (a == Name.npos || a == 0)
843 Dylib = Name.slice(a, Name.npos);
844 if (Dylib != ".dylib")
847 // First pull off the version letter for the form Foo.A.dylib if any.
849 Dot = Name.slice(a-2, a-1);
854 b = Name.rfind('/', a);
859 // ignore any suffix after an underbar like Foo_profile.A.dylib
860 Idx = Name.find('_', b);
861 if (Idx != Name.npos && Idx != b) {
862 Lib = Name.slice(b, Idx);
863 Suffix = Name.slice(Idx, a);
866 Lib = Name.slice(b, a);
867 // There are incorrect library names of the form:
868 // libATS.A_profile.dylib so check for these.
869 if (Lib.size() >= 3) {
870 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
872 Lib = Lib.slice(0, Lib.size()-2);
877 Qtx = Name.slice(a, Name.npos);
880 b = Name.rfind('/', a);
882 Lib = Name.slice(0, a);
884 Lib = Name.slice(b+1, a);
885 // There are library names of the form: QT.A.qtx so check for these.
886 if (Lib.size() >= 3) {
887 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
889 Lib = Lib.slice(0, Lib.size()-2);
894 // getLibraryShortNameByIndex() is used to get the short name of the library
895 // for an undefined symbol in a linked Mach-O binary that was linked with the
896 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
897 // It is passed the index (0 - based) of the library as translated from
898 // GET_LIBRARY_ORDINAL (1 - based).
899 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
900 StringRef &Res) const {
901 if (Index >= Libraries.size())
902 return object_error::parse_failed;
904 // If the cache of LibrariesShortNames is not built up do that first for
905 // all the Libraries.
906 if (LibrariesShortNames.size() == 0) {
907 for (unsigned i = 0; i < Libraries.size(); i++) {
908 MachO::dylib_command D =
909 getStruct<MachO::dylib_command>(this, Libraries[i]);
910 if (D.dylib.name >= D.cmdsize)
911 return object_error::parse_failed;
912 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
913 StringRef Name = StringRef(P);
914 if (D.dylib.name+Name.size() >= D.cmdsize)
915 return object_error::parse_failed;
918 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
919 if (shortName.empty())
920 LibrariesShortNames.push_back(Name);
922 LibrariesShortNames.push_back(shortName);
926 Res = LibrariesShortNames[Index];
927 return std::error_code();
930 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
931 return getSymbolByIndex(0);
934 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
937 return basic_symbol_iterator(SymbolRef(DRI, this));
939 MachO::symtab_command Symtab = getSymtabLoadCommand();
940 unsigned SymbolTableEntrySize = is64Bit() ?
941 sizeof(MachO::nlist_64) :
942 sizeof(MachO::nlist);
943 unsigned Offset = Symtab.symoff +
944 Symtab.nsyms * SymbolTableEntrySize;
945 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
946 return basic_symbol_iterator(SymbolRef(DRI, this));
949 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
952 return basic_symbol_iterator(SymbolRef(DRI, this));
954 MachO::symtab_command Symtab = getSymtabLoadCommand();
955 if (Index >= Symtab.nsyms)
956 report_fatal_error("Requested symbol index is out of range.");
957 unsigned SymbolTableEntrySize =
958 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
959 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
960 DRI.p += Index * SymbolTableEntrySize;
961 return basic_symbol_iterator(SymbolRef(DRI, this));
964 section_iterator MachOObjectFile::section_begin() const {
966 return section_iterator(SectionRef(DRI, this));
969 section_iterator MachOObjectFile::section_end() const {
971 DRI.d.a = Sections.size();
972 return section_iterator(SectionRef(DRI, this));
975 uint8_t MachOObjectFile::getBytesInAddress() const {
976 return is64Bit() ? 8 : 4;
979 StringRef MachOObjectFile::getFileFormatName() const {
980 unsigned CPUType = getCPUType(this);
983 case llvm::MachO::CPU_TYPE_I386:
984 return "Mach-O 32-bit i386";
985 case llvm::MachO::CPU_TYPE_ARM:
987 case llvm::MachO::CPU_TYPE_POWERPC:
988 return "Mach-O 32-bit ppc";
990 return "Mach-O 32-bit unknown";
995 case llvm::MachO::CPU_TYPE_X86_64:
996 return "Mach-O 64-bit x86-64";
997 case llvm::MachO::CPU_TYPE_ARM64:
998 return "Mach-O arm64";
999 case llvm::MachO::CPU_TYPE_POWERPC64:
1000 return "Mach-O 64-bit ppc64";
1002 return "Mach-O 64-bit unknown";
1006 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1008 case llvm::MachO::CPU_TYPE_I386:
1010 case llvm::MachO::CPU_TYPE_X86_64:
1011 return Triple::x86_64;
1012 case llvm::MachO::CPU_TYPE_ARM:
1014 case llvm::MachO::CPU_TYPE_ARM64:
1015 return Triple::aarch64;
1016 case llvm::MachO::CPU_TYPE_POWERPC:
1018 case llvm::MachO::CPU_TYPE_POWERPC64:
1019 return Triple::ppc64;
1021 return Triple::UnknownArch;
1025 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1026 const char **McpuDefault) {
1028 *McpuDefault = nullptr;
1031 case MachO::CPU_TYPE_I386:
1032 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1033 case MachO::CPU_SUBTYPE_I386_ALL:
1034 return Triple("i386-apple-darwin");
1038 case MachO::CPU_TYPE_X86_64:
1039 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1040 case MachO::CPU_SUBTYPE_X86_64_ALL:
1041 return Triple("x86_64-apple-darwin");
1042 case MachO::CPU_SUBTYPE_X86_64_H:
1043 return Triple("x86_64h-apple-darwin");
1047 case MachO::CPU_TYPE_ARM:
1048 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1049 case MachO::CPU_SUBTYPE_ARM_V4T:
1050 return Triple("armv4t-apple-darwin");
1051 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1052 return Triple("armv5e-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1054 return Triple("xscale-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_V6:
1056 return Triple("armv6-apple-darwin");
1057 case MachO::CPU_SUBTYPE_ARM_V6M:
1059 *McpuDefault = "cortex-m0";
1060 return Triple("armv6m-apple-darwin");
1061 case MachO::CPU_SUBTYPE_ARM_V7:
1062 return Triple("armv7-apple-darwin");
1063 case MachO::CPU_SUBTYPE_ARM_V7EM:
1065 *McpuDefault = "cortex-m4";
1066 return Triple("armv7em-apple-darwin");
1067 case MachO::CPU_SUBTYPE_ARM_V7K:
1068 return Triple("armv7k-apple-darwin");
1069 case MachO::CPU_SUBTYPE_ARM_V7M:
1071 *McpuDefault = "cortex-m3";
1072 return Triple("armv7m-apple-darwin");
1073 case MachO::CPU_SUBTYPE_ARM_V7S:
1074 return Triple("armv7s-apple-darwin");
1078 case MachO::CPU_TYPE_ARM64:
1079 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1080 case MachO::CPU_SUBTYPE_ARM64_ALL:
1081 return Triple("arm64-apple-darwin");
1085 case MachO::CPU_TYPE_POWERPC:
1086 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1087 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1088 return Triple("ppc-apple-darwin");
1092 case MachO::CPU_TYPE_POWERPC64:
1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1095 return Triple("ppc64-apple-darwin");
1104 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1105 const char **McpuDefault) {
1107 *McpuDefault = nullptr;
1110 case MachO::CPU_TYPE_ARM:
1111 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1112 case MachO::CPU_SUBTYPE_ARM_V4T:
1113 return Triple("thumbv4t-apple-darwin");
1114 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1115 return Triple("thumbv5e-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1117 return Triple("xscale-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_V6:
1119 return Triple("thumbv6-apple-darwin");
1120 case MachO::CPU_SUBTYPE_ARM_V6M:
1122 *McpuDefault = "cortex-m0";
1123 return Triple("thumbv6m-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V7:
1125 return Triple("thumbv7-apple-darwin");
1126 case MachO::CPU_SUBTYPE_ARM_V7EM:
1128 *McpuDefault = "cortex-m4";
1129 return Triple("thumbv7em-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_V7K:
1131 return Triple("thumbv7k-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V7M:
1134 *McpuDefault = "cortex-m3";
1135 return Triple("thumbv7m-apple-darwin");
1136 case MachO::CPU_SUBTYPE_ARM_V7S:
1137 return Triple("thumbv7s-apple-darwin");
1146 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1147 const char **McpuDefault,
1148 Triple *ThumbTriple) {
1149 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1150 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1155 Triple MachOObjectFile::getHostArch() {
1156 return Triple(sys::getDefaultTargetTriple());
1159 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1160 return StringSwitch<bool>(ArchFlag)
1162 .Case("x86_64", true)
1163 .Case("x86_64h", true)
1164 .Case("armv4t", true)
1166 .Case("armv5e", true)
1167 .Case("armv6", true)
1168 .Case("armv6m", true)
1169 .Case("armv7", true)
1170 .Case("armv7em", true)
1171 .Case("armv7k", true)
1172 .Case("armv7m", true)
1173 .Case("armv7s", true)
1174 .Case("arm64", true)
1176 .Case("ppc64", true)
1180 unsigned MachOObjectFile::getArch() const {
1181 return getArch(getCPUType(this));
1184 Triple MachOObjectFile::getArch(const char **McpuDefault,
1185 Triple *ThumbTriple) const {
1186 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1187 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1190 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1193 return section_rel_begin(DRI);
1196 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1199 return section_rel_end(DRI);
1202 dice_iterator MachOObjectFile::begin_dices() const {
1204 if (!DataInCodeLoadCmd)
1205 return dice_iterator(DiceRef(DRI, this));
1207 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1208 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1209 return dice_iterator(DiceRef(DRI, this));
1212 dice_iterator MachOObjectFile::end_dices() const {
1214 if (!DataInCodeLoadCmd)
1215 return dice_iterator(DiceRef(DRI, this));
1217 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1218 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1219 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1220 return dice_iterator(DiceRef(DRI, this));
1223 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1224 : Trie(T), Malformed(false), Done(false) { }
1226 void ExportEntry::moveToFirst() {
1228 pushDownUntilBottom();
1231 void ExportEntry::moveToEnd() {
1236 bool ExportEntry::operator==(const ExportEntry &Other) const {
1237 // Common case, one at end, other iterating from begin.
1238 if (Done || Other.Done)
1239 return (Done == Other.Done);
1240 // Not equal if different stack sizes.
1241 if (Stack.size() != Other.Stack.size())
1243 // Not equal if different cumulative strings.
1244 if (!CumulativeString.equals(Other.CumulativeString))
1246 // Equal if all nodes in both stacks match.
1247 for (unsigned i=0; i < Stack.size(); ++i) {
1248 if (Stack[i].Start != Other.Stack[i].Start)
1254 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1256 uint64_t Result = decodeULEB128(Ptr, &Count);
1258 if (Ptr > Trie.end()) {
1265 StringRef ExportEntry::name() const {
1266 return CumulativeString;
1269 uint64_t ExportEntry::flags() const {
1270 return Stack.back().Flags;
1273 uint64_t ExportEntry::address() const {
1274 return Stack.back().Address;
1277 uint64_t ExportEntry::other() const {
1278 return Stack.back().Other;
1281 StringRef ExportEntry::otherName() const {
1282 const char* ImportName = Stack.back().ImportName;
1284 return StringRef(ImportName);
1288 uint32_t ExportEntry::nodeOffset() const {
1289 return Stack.back().Start - Trie.begin();
1292 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1293 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1294 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1295 ParentStringLength(0), IsExportNode(false) {
1298 void ExportEntry::pushNode(uint64_t offset) {
1299 const uint8_t *Ptr = Trie.begin() + offset;
1300 NodeState State(Ptr);
1301 uint64_t ExportInfoSize = readULEB128(State.Current);
1302 State.IsExportNode = (ExportInfoSize != 0);
1303 const uint8_t* Children = State.Current + ExportInfoSize;
1304 if (State.IsExportNode) {
1305 State.Flags = readULEB128(State.Current);
1306 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1308 State.Other = readULEB128(State.Current); // dylib ordinal
1309 State.ImportName = reinterpret_cast<const char*>(State.Current);
1311 State.Address = readULEB128(State.Current);
1312 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1313 State.Other = readULEB128(State.Current);
1316 State.ChildCount = *Children;
1317 State.Current = Children + 1;
1318 State.NextChildIndex = 0;
1319 State.ParentStringLength = CumulativeString.size();
1320 Stack.push_back(State);
1323 void ExportEntry::pushDownUntilBottom() {
1324 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1325 NodeState &Top = Stack.back();
1326 CumulativeString.resize(Top.ParentStringLength);
1327 for (;*Top.Current != 0; Top.Current++) {
1328 char C = *Top.Current;
1329 CumulativeString.push_back(C);
1332 uint64_t childNodeIndex = readULEB128(Top.Current);
1333 Top.NextChildIndex += 1;
1334 pushNode(childNodeIndex);
1336 if (!Stack.back().IsExportNode) {
1342 // We have a trie data structure and need a way to walk it that is compatible
1343 // with the C++ iterator model. The solution is a non-recursive depth first
1344 // traversal where the iterator contains a stack of parent nodes along with a
1345 // string that is the accumulation of all edge strings along the parent chain
1348 // There is one "export" node for each exported symbol. But because some
1349 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1350 // node may have child nodes too.
1352 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1353 // child until hitting a node with no children (which is an export node or
1354 // else the trie is malformed). On the way down, each node is pushed on the
1355 // stack ivar. If there is no more ways down, it pops up one and tries to go
1356 // down a sibling path until a childless node is reached.
1357 void ExportEntry::moveNext() {
1358 if (Stack.empty() || !Stack.back().IsExportNode) {
1365 while (!Stack.empty()) {
1366 NodeState &Top = Stack.back();
1367 if (Top.NextChildIndex < Top.ChildCount) {
1368 pushDownUntilBottom();
1369 // Now at the next export node.
1372 if (Top.IsExportNode) {
1373 // This node has no children but is itself an export node.
1374 CumulativeString.resize(Top.ParentStringLength);
1383 iterator_range<export_iterator>
1384 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1385 ExportEntry Start(Trie);
1386 if (Trie.size() == 0)
1389 Start.moveToFirst();
1391 ExportEntry Finish(Trie);
1394 return iterator_range<export_iterator>(export_iterator(Start),
1395 export_iterator(Finish));
1398 iterator_range<export_iterator> MachOObjectFile::exports() const {
1399 return exports(getDyldInfoExportsTrie());
1403 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1404 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1405 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1406 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1408 void MachORebaseEntry::moveToFirst() {
1409 Ptr = Opcodes.begin();
1413 void MachORebaseEntry::moveToEnd() {
1414 Ptr = Opcodes.end();
1415 RemainingLoopCount = 0;
1419 void MachORebaseEntry::moveNext() {
1420 // If in the middle of some loop, move to next rebasing in loop.
1421 SegmentOffset += AdvanceAmount;
1422 if (RemainingLoopCount) {
1423 --RemainingLoopCount;
1426 if (Ptr == Opcodes.end()) {
1431 while (More && !Malformed) {
1432 // Parse next opcode and set up next loop.
1433 uint8_t Byte = *Ptr++;
1434 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1435 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1437 case MachO::REBASE_OPCODE_DONE:
1441 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1443 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1444 RebaseType = ImmValue;
1447 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1448 << "RebaseType=" << (int) RebaseType << "\n");
1450 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1451 SegmentIndex = ImmValue;
1452 SegmentOffset = readULEB128();
1455 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1456 << "SegmentIndex=" << SegmentIndex << ", "
1457 << format("SegmentOffset=0x%06X", SegmentOffset)
1460 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1461 SegmentOffset += readULEB128();
1462 DEBUG_WITH_TYPE("mach-o-rebase",
1463 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1464 << format("SegmentOffset=0x%06X",
1465 SegmentOffset) << "\n");
1467 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1468 SegmentOffset += ImmValue * PointerSize;
1469 DEBUG_WITH_TYPE("mach-o-rebase",
1470 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1471 << format("SegmentOffset=0x%06X",
1472 SegmentOffset) << "\n");
1474 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1475 AdvanceAmount = PointerSize;
1476 RemainingLoopCount = ImmValue - 1;
1479 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1480 << format("SegmentOffset=0x%06X", SegmentOffset)
1481 << ", AdvanceAmount=" << AdvanceAmount
1482 << ", RemainingLoopCount=" << RemainingLoopCount
1485 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1486 AdvanceAmount = PointerSize;
1487 RemainingLoopCount = readULEB128() - 1;
1490 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1491 << format("SegmentOffset=0x%06X", SegmentOffset)
1492 << ", AdvanceAmount=" << AdvanceAmount
1493 << ", RemainingLoopCount=" << RemainingLoopCount
1496 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1497 AdvanceAmount = readULEB128() + PointerSize;
1498 RemainingLoopCount = 0;
1501 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1502 << format("SegmentOffset=0x%06X", SegmentOffset)
1503 << ", AdvanceAmount=" << AdvanceAmount
1504 << ", RemainingLoopCount=" << RemainingLoopCount
1507 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1508 RemainingLoopCount = readULEB128() - 1;
1509 AdvanceAmount = readULEB128() + PointerSize;
1512 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1513 << format("SegmentOffset=0x%06X", SegmentOffset)
1514 << ", AdvanceAmount=" << AdvanceAmount
1515 << ", RemainingLoopCount=" << RemainingLoopCount
1524 uint64_t MachORebaseEntry::readULEB128() {
1526 uint64_t Result = decodeULEB128(Ptr, &Count);
1528 if (Ptr > Opcodes.end()) {
1529 Ptr = Opcodes.end();
1535 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1537 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1539 StringRef MachORebaseEntry::typeName() const {
1540 switch (RebaseType) {
1541 case MachO::REBASE_TYPE_POINTER:
1543 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1544 return "text abs32";
1545 case MachO::REBASE_TYPE_TEXT_PCREL32:
1546 return "text rel32";
1551 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1552 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1553 return (Ptr == Other.Ptr) &&
1554 (RemainingLoopCount == Other.RemainingLoopCount) &&
1555 (Done == Other.Done);
1558 iterator_range<rebase_iterator>
1559 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1560 MachORebaseEntry Start(Opcodes, is64);
1561 Start.moveToFirst();
1563 MachORebaseEntry Finish(Opcodes, is64);
1566 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1567 rebase_iterator(Finish));
1570 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1571 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1575 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1577 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1578 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1579 BindType(0), PointerSize(is64Bit ? 8 : 4),
1580 TableKind(BK), Malformed(false), Done(false) {}
1582 void MachOBindEntry::moveToFirst() {
1583 Ptr = Opcodes.begin();
1587 void MachOBindEntry::moveToEnd() {
1588 Ptr = Opcodes.end();
1589 RemainingLoopCount = 0;
1593 void MachOBindEntry::moveNext() {
1594 // If in the middle of some loop, move to next binding in loop.
1595 SegmentOffset += AdvanceAmount;
1596 if (RemainingLoopCount) {
1597 --RemainingLoopCount;
1600 if (Ptr == Opcodes.end()) {
1605 while (More && !Malformed) {
1606 // Parse next opcode and set up next loop.
1607 uint8_t Byte = *Ptr++;
1608 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1609 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1610 int8_t SignExtended;
1611 const uint8_t *SymStart;
1613 case MachO::BIND_OPCODE_DONE:
1614 if (TableKind == Kind::Lazy) {
1615 // Lazying bindings have a DONE opcode between entries. Need to ignore
1616 // it to advance to next entry. But need not if this is last entry.
1617 bool NotLastEntry = false;
1618 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1620 NotLastEntry = true;
1629 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1631 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1635 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1636 << "Ordinal=" << Ordinal << "\n");
1638 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1639 Ordinal = readULEB128();
1642 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1643 << "Ordinal=" << Ordinal << "\n");
1645 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1647 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1648 Ordinal = SignExtended;
1653 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1654 << "Ordinal=" << Ordinal << "\n");
1656 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1662 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1667 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1668 << "SymbolName=" << SymbolName << "\n");
1669 if (TableKind == Kind::Weak) {
1670 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1674 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1675 BindType = ImmValue;
1678 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1679 << "BindType=" << (int)BindType << "\n");
1681 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1682 Addend = readSLEB128();
1683 if (TableKind == Kind::Lazy)
1687 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1688 << "Addend=" << Addend << "\n");
1690 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1691 SegmentIndex = ImmValue;
1692 SegmentOffset = readULEB128();
1695 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1696 << "SegmentIndex=" << SegmentIndex << ", "
1697 << format("SegmentOffset=0x%06X", SegmentOffset)
1700 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1701 SegmentOffset += readULEB128();
1702 DEBUG_WITH_TYPE("mach-o-bind",
1703 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1704 << format("SegmentOffset=0x%06X",
1705 SegmentOffset) << "\n");
1707 case MachO::BIND_OPCODE_DO_BIND:
1708 AdvanceAmount = PointerSize;
1709 RemainingLoopCount = 0;
1710 DEBUG_WITH_TYPE("mach-o-bind",
1711 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1712 << format("SegmentOffset=0x%06X",
1713 SegmentOffset) << "\n");
1715 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1716 AdvanceAmount = readULEB128() + PointerSize;
1717 RemainingLoopCount = 0;
1718 if (TableKind == Kind::Lazy)
1722 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1723 << format("SegmentOffset=0x%06X", SegmentOffset)
1724 << ", AdvanceAmount=" << AdvanceAmount
1725 << ", RemainingLoopCount=" << RemainingLoopCount
1728 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1729 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1730 RemainingLoopCount = 0;
1731 if (TableKind == Kind::Lazy)
1733 DEBUG_WITH_TYPE("mach-o-bind",
1735 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1736 << format("SegmentOffset=0x%06X",
1737 SegmentOffset) << "\n");
1739 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1740 RemainingLoopCount = readULEB128() - 1;
1741 AdvanceAmount = readULEB128() + PointerSize;
1742 if (TableKind == Kind::Lazy)
1746 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1747 << format("SegmentOffset=0x%06X", SegmentOffset)
1748 << ", AdvanceAmount=" << AdvanceAmount
1749 << ", RemainingLoopCount=" << RemainingLoopCount
1758 uint64_t MachOBindEntry::readULEB128() {
1760 uint64_t Result = decodeULEB128(Ptr, &Count);
1762 if (Ptr > Opcodes.end()) {
1763 Ptr = Opcodes.end();
1769 int64_t MachOBindEntry::readSLEB128() {
1771 int64_t Result = decodeSLEB128(Ptr, &Count);
1773 if (Ptr > Opcodes.end()) {
1774 Ptr = Opcodes.end();
1781 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1783 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1785 StringRef MachOBindEntry::typeName() const {
1787 case MachO::BIND_TYPE_POINTER:
1789 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1790 return "text abs32";
1791 case MachO::BIND_TYPE_TEXT_PCREL32:
1792 return "text rel32";
1797 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1799 int64_t MachOBindEntry::addend() const { return Addend; }
1801 uint32_t MachOBindEntry::flags() const { return Flags; }
1803 int MachOBindEntry::ordinal() const { return Ordinal; }
1805 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1806 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1807 return (Ptr == Other.Ptr) &&
1808 (RemainingLoopCount == Other.RemainingLoopCount) &&
1809 (Done == Other.Done);
1812 iterator_range<bind_iterator>
1813 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1814 MachOBindEntry::Kind BKind) {
1815 MachOBindEntry Start(Opcodes, is64, BKind);
1816 Start.moveToFirst();
1818 MachOBindEntry Finish(Opcodes, is64, BKind);
1821 return iterator_range<bind_iterator>(bind_iterator(Start),
1822 bind_iterator(Finish));
1825 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1826 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1827 MachOBindEntry::Kind::Regular);
1830 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1831 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1832 MachOBindEntry::Kind::Lazy);
1835 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1836 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1837 MachOBindEntry::Kind::Weak);
1840 MachOObjectFile::load_command_iterator
1841 MachOObjectFile::begin_load_commands() const {
1842 return LoadCommands.begin();
1845 MachOObjectFile::load_command_iterator
1846 MachOObjectFile::end_load_commands() const {
1847 return LoadCommands.end();
1850 iterator_range<MachOObjectFile::load_command_iterator>
1851 MachOObjectFile::load_commands() const {
1852 return iterator_range<load_command_iterator>(begin_load_commands(),
1853 end_load_commands());
1857 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1858 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1859 return parseSegmentOrSectionName(Raw.data());
1863 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1864 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1865 const section_base *Base =
1866 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1867 return makeArrayRef(Base->sectname);
1871 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1872 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1873 const section_base *Base =
1874 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1875 return makeArrayRef(Base->segname);
1879 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1881 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1883 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1886 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1887 const MachO::any_relocation_info &RE) const {
1888 if (isLittleEndian())
1889 return RE.r_word1 & 0xffffff;
1890 return RE.r_word1 >> 8;
1893 bool MachOObjectFile::getPlainRelocationExternal(
1894 const MachO::any_relocation_info &RE) const {
1895 if (isLittleEndian())
1896 return (RE.r_word1 >> 27) & 1;
1897 return (RE.r_word1 >> 4) & 1;
1900 bool MachOObjectFile::getScatteredRelocationScattered(
1901 const MachO::any_relocation_info &RE) const {
1902 return RE.r_word0 >> 31;
1905 uint32_t MachOObjectFile::getScatteredRelocationValue(
1906 const MachO::any_relocation_info &RE) const {
1910 uint32_t MachOObjectFile::getScatteredRelocationType(
1911 const MachO::any_relocation_info &RE) const {
1912 return (RE.r_word0 >> 24) & 0xf;
1915 unsigned MachOObjectFile::getAnyRelocationAddress(
1916 const MachO::any_relocation_info &RE) const {
1917 if (isRelocationScattered(RE))
1918 return getScatteredRelocationAddress(RE);
1919 return getPlainRelocationAddress(RE);
1922 unsigned MachOObjectFile::getAnyRelocationPCRel(
1923 const MachO::any_relocation_info &RE) const {
1924 if (isRelocationScattered(RE))
1925 return getScatteredRelocationPCRel(this, RE);
1926 return getPlainRelocationPCRel(this, RE);
1929 unsigned MachOObjectFile::getAnyRelocationLength(
1930 const MachO::any_relocation_info &RE) const {
1931 if (isRelocationScattered(RE))
1932 return getScatteredRelocationLength(RE);
1933 return getPlainRelocationLength(this, RE);
1937 MachOObjectFile::getAnyRelocationType(
1938 const MachO::any_relocation_info &RE) const {
1939 if (isRelocationScattered(RE))
1940 return getScatteredRelocationType(RE);
1941 return getPlainRelocationType(this, RE);
1945 MachOObjectFile::getAnyRelocationSection(
1946 const MachO::any_relocation_info &RE) const {
1947 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1948 return *section_end();
1949 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1950 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1951 return *section_end();
1953 DRI.d.a = SecNum - 1;
1954 return SectionRef(DRI, this);
1957 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1958 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1959 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1962 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1963 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1964 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1967 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1968 unsigned Index) const {
1969 const char *Sec = getSectionPtr(this, L, Index);
1970 return getStruct<MachO::section>(this, Sec);
1973 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1974 unsigned Index) const {
1975 const char *Sec = getSectionPtr(this, L, Index);
1976 return getStruct<MachO::section_64>(this, Sec);
1980 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1981 const char *P = reinterpret_cast<const char *>(DRI.p);
1982 return getStruct<MachO::nlist>(this, P);
1986 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1987 const char *P = reinterpret_cast<const char *>(DRI.p);
1988 return getStruct<MachO::nlist_64>(this, P);
1991 MachO::linkedit_data_command
1992 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1993 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1996 MachO::segment_command
1997 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1998 return getStruct<MachO::segment_command>(this, L.Ptr);
2001 MachO::segment_command_64
2002 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2003 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2006 MachO::linker_option_command
2007 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2008 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2011 MachO::version_min_command
2012 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2013 return getStruct<MachO::version_min_command>(this, L.Ptr);
2016 MachO::dylib_command
2017 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2018 return getStruct<MachO::dylib_command>(this, L.Ptr);
2021 MachO::dyld_info_command
2022 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2023 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2026 MachO::dylinker_command
2027 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2028 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2032 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2033 return getStruct<MachO::uuid_command>(this, L.Ptr);
2036 MachO::rpath_command
2037 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2038 return getStruct<MachO::rpath_command>(this, L.Ptr);
2041 MachO::source_version_command
2042 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2043 return getStruct<MachO::source_version_command>(this, L.Ptr);
2046 MachO::entry_point_command
2047 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2048 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2051 MachO::encryption_info_command
2052 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2056 MachO::encryption_info_command_64
2057 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2061 MachO::sub_framework_command
2062 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2063 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2066 MachO::sub_umbrella_command
2067 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2071 MachO::sub_library_command
2072 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2073 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2076 MachO::sub_client_command
2077 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2078 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2081 MachO::routines_command
2082 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2083 return getStruct<MachO::routines_command>(this, L.Ptr);
2086 MachO::routines_command_64
2087 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2088 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2091 MachO::thread_command
2092 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2093 return getStruct<MachO::thread_command>(this, L.Ptr);
2096 MachO::any_relocation_info
2097 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2102 MachO::section_64 Sect = getSection64(Sec);
2103 Offset = Sect.reloff;
2105 MachO::section Sect = getSection(Sec);
2106 Offset = Sect.reloff;
2109 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2110 getPtr(this, Offset)) + Rel.d.b;
2111 return getStruct<MachO::any_relocation_info>(
2112 this, reinterpret_cast<const char *>(P));
2115 MachO::data_in_code_entry
2116 MachOObjectFile::getDice(DataRefImpl Rel) const {
2117 const char *P = reinterpret_cast<const char *>(Rel.p);
2118 return getStruct<MachO::data_in_code_entry>(this, P);
2121 const MachO::mach_header &MachOObjectFile::getHeader() const {
2125 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2130 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2131 const MachO::dysymtab_command &DLC,
2132 unsigned Index) const {
2133 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2134 return getStruct<uint32_t>(this, getPtr(this, Offset));
2137 MachO::data_in_code_entry
2138 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2139 unsigned Index) const {
2140 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2141 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2144 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2146 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2148 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2149 MachO::symtab_command Cmd;
2150 Cmd.cmd = MachO::LC_SYMTAB;
2151 Cmd.cmdsize = sizeof(MachO::symtab_command);
2159 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2160 if (DysymtabLoadCmd)
2161 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2163 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2164 MachO::dysymtab_command Cmd;
2165 Cmd.cmd = MachO::LC_DYSYMTAB;
2166 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2177 Cmd.extrefsymoff = 0;
2178 Cmd.nextrefsyms = 0;
2179 Cmd.indirectsymoff = 0;
2180 Cmd.nindirectsyms = 0;
2188 MachO::linkedit_data_command
2189 MachOObjectFile::getDataInCodeLoadCommand() const {
2190 if (DataInCodeLoadCmd)
2191 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2193 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2194 MachO::linkedit_data_command Cmd;
2195 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2196 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2202 MachO::linkedit_data_command
2203 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2204 if (LinkOptHintsLoadCmd)
2205 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2207 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2209 MachO::linkedit_data_command Cmd;
2210 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2211 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2217 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2218 if (!DyldInfoLoadCmd)
2219 return ArrayRef<uint8_t>();
2221 MachO::dyld_info_command DyldInfo
2222 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2223 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2224 getPtr(this, DyldInfo.rebase_off));
2225 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2228 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2229 if (!DyldInfoLoadCmd)
2230 return ArrayRef<uint8_t>();
2232 MachO::dyld_info_command DyldInfo
2233 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2234 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2235 getPtr(this, DyldInfo.bind_off));
2236 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2239 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2240 if (!DyldInfoLoadCmd)
2241 return ArrayRef<uint8_t>();
2243 MachO::dyld_info_command DyldInfo
2244 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2245 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2246 getPtr(this, DyldInfo.weak_bind_off));
2247 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2250 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2251 if (!DyldInfoLoadCmd)
2252 return ArrayRef<uint8_t>();
2254 MachO::dyld_info_command DyldInfo
2255 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2256 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2257 getPtr(this, DyldInfo.lazy_bind_off));
2258 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2261 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2262 if (!DyldInfoLoadCmd)
2263 return ArrayRef<uint8_t>();
2265 MachO::dyld_info_command DyldInfo
2266 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2267 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2268 getPtr(this, DyldInfo.export_off));
2269 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2272 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2274 return ArrayRef<uint8_t>();
2275 // Returning a pointer is fine as uuid doesn't need endian swapping.
2276 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2277 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2280 StringRef MachOObjectFile::getStringTableData() const {
2281 MachO::symtab_command S = getSymtabLoadCommand();
2282 return getData().substr(S.stroff, S.strsize);
2285 bool MachOObjectFile::is64Bit() const {
2286 return getType() == getMachOType(false, true) ||
2287 getType() == getMachOType(true, true);
2290 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2291 SmallVectorImpl<uint64_t> &Out) const {
2292 DataExtractor extractor(ObjectFile::getData(), true, 0);
2294 uint32_t offset = Index;
2296 while (uint64_t delta = extractor.getULEB128(&offset)) {
2298 Out.push_back(data);
2302 bool MachOObjectFile::isRelocatableObject() const {
2303 return getHeader().filetype == MachO::MH_OBJECT;
2306 ErrorOr<std::unique_ptr<MachOObjectFile>>
2307 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2308 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2310 std::unique_ptr<MachOObjectFile> Ret;
2311 if (Magic == "\xFE\xED\xFA\xCE")
2312 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2313 else if (Magic == "\xCE\xFA\xED\xFE")
2314 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2315 else if (Magic == "\xFE\xED\xFA\xCF")
2316 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2317 else if (Magic == "\xCF\xFA\xED\xFE")
2318 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2320 return object_error::parse_failed;
2324 return std::move(Ret);