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 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
592 assert(getHeader().filetype == MachO::MH_OBJECT &&
593 "Only implemented for MH_OBJECT");
594 MachO::any_relocation_info RE = getRelocation(Rel);
595 return getAnyRelocationAddress(RE);
599 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
600 MachO::any_relocation_info RE = getRelocation(Rel);
601 if (isRelocationScattered(RE))
604 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
605 bool isExtern = getPlainRelocationExternal(RE);
609 MachO::symtab_command S = getSymtabLoadCommand();
610 unsigned SymbolTableEntrySize = is64Bit() ?
611 sizeof(MachO::nlist_64) :
612 sizeof(MachO::nlist);
613 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
615 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
616 return symbol_iterator(SymbolRef(Sym, this));
620 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
621 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
624 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
625 MachO::any_relocation_info RE = getRelocation(Rel);
626 return getAnyRelocationType(RE);
629 void MachOObjectFile::getRelocationTypeName(
630 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
632 uint64_t RType = getRelocationType(Rel);
634 unsigned Arch = this->getArch();
638 static const char *const Table[] = {
639 "GENERIC_RELOC_VANILLA",
640 "GENERIC_RELOC_PAIR",
641 "GENERIC_RELOC_SECTDIFF",
642 "GENERIC_RELOC_PB_LA_PTR",
643 "GENERIC_RELOC_LOCAL_SECTDIFF",
644 "GENERIC_RELOC_TLV" };
652 case Triple::x86_64: {
653 static const char *const Table[] = {
654 "X86_64_RELOC_UNSIGNED",
655 "X86_64_RELOC_SIGNED",
656 "X86_64_RELOC_BRANCH",
657 "X86_64_RELOC_GOT_LOAD",
659 "X86_64_RELOC_SUBTRACTOR",
660 "X86_64_RELOC_SIGNED_1",
661 "X86_64_RELOC_SIGNED_2",
662 "X86_64_RELOC_SIGNED_4",
663 "X86_64_RELOC_TLV" };
672 static const char *const Table[] = {
675 "ARM_RELOC_SECTDIFF",
676 "ARM_RELOC_LOCAL_SECTDIFF",
677 "ARM_RELOC_PB_LA_PTR",
679 "ARM_THUMB_RELOC_BR22",
680 "ARM_THUMB_32BIT_BRANCH",
682 "ARM_RELOC_HALF_SECTDIFF" };
690 case Triple::aarch64: {
691 static const char *const Table[] = {
692 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
693 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
694 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
695 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
696 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
700 if (RType >= array_lengthof(Table))
707 static const char *const Table[] = {
716 "PPC_RELOC_SECTDIFF",
717 "PPC_RELOC_PB_LA_PTR",
718 "PPC_RELOC_HI16_SECTDIFF",
719 "PPC_RELOC_LO16_SECTDIFF",
720 "PPC_RELOC_HA16_SECTDIFF",
722 "PPC_RELOC_LO14_SECTDIFF",
723 "PPC_RELOC_LOCAL_SECTDIFF" };
731 case Triple::UnknownArch:
735 Result.append(res.begin(), res.end());
738 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
739 MachO::any_relocation_info RE = getRelocation(Rel);
740 return getAnyRelocationLength(RE);
744 // guessLibraryShortName() is passed a name of a dynamic library and returns a
745 // guess on what the short name is. Then name is returned as a substring of the
746 // StringRef Name passed in. The name of the dynamic library is recognized as
747 // a framework if it has one of the two following forms:
748 // Foo.framework/Versions/A/Foo
750 // Where A and Foo can be any string. And may contain a trailing suffix
751 // starting with an underbar. If the Name is recognized as a framework then
752 // isFramework is set to true else it is set to false. If the Name has a
753 // suffix then Suffix is set to the substring in Name that contains the suffix
754 // else it is set to a NULL StringRef.
756 // The Name of the dynamic library is recognized as a library name if it has
757 // one of the two following forms:
760 // The library may have a suffix trailing the name Foo of the form:
761 // libFoo_profile.A.dylib
762 // libFoo_profile.dylib
764 // The Name of the dynamic library is also recognized as a library name if it
765 // has the following form:
768 // If the Name of the dynamic library is none of the forms above then a NULL
769 // StringRef is returned.
771 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
774 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
775 size_t a, b, c, d, Idx;
778 Suffix = StringRef();
780 // Pull off the last component and make Foo point to it
782 if (a == Name.npos || a == 0)
784 Foo = Name.slice(a+1, Name.npos);
786 // Look for a suffix starting with a '_'
787 Idx = Foo.rfind('_');
788 if (Idx != Foo.npos && Foo.size() >= 2) {
789 Suffix = Foo.slice(Idx, Foo.npos);
790 Foo = Foo.slice(0, Idx);
793 // First look for the form Foo.framework/Foo
794 b = Name.rfind('/', a);
799 F = Name.slice(Idx, Idx + Foo.size());
800 DotFramework = Name.slice(Idx + Foo.size(),
801 Idx + Foo.size() + sizeof(".framework/")-1);
802 if (F == Foo && DotFramework == ".framework/") {
807 // Next look for the form Foo.framework/Versions/A/Foo
810 c = Name.rfind('/', b);
811 if (c == Name.npos || c == 0)
813 V = Name.slice(c+1, Name.npos);
814 if (!V.startswith("Versions/"))
816 d = Name.rfind('/', c);
821 F = Name.slice(Idx, Idx + Foo.size());
822 DotFramework = Name.slice(Idx + Foo.size(),
823 Idx + Foo.size() + sizeof(".framework/")-1);
824 if (F == Foo && DotFramework == ".framework/") {
830 // pull off the suffix after the "." and make a point to it
832 if (a == Name.npos || a == 0)
834 Dylib = Name.slice(a, Name.npos);
835 if (Dylib != ".dylib")
838 // First pull off the version letter for the form Foo.A.dylib if any.
840 Dot = Name.slice(a-2, a-1);
845 b = Name.rfind('/', a);
850 // ignore any suffix after an underbar like Foo_profile.A.dylib
851 Idx = Name.find('_', b);
852 if (Idx != Name.npos && Idx != b) {
853 Lib = Name.slice(b, Idx);
854 Suffix = Name.slice(Idx, a);
857 Lib = Name.slice(b, a);
858 // There are incorrect library names of the form:
859 // libATS.A_profile.dylib so check for these.
860 if (Lib.size() >= 3) {
861 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
863 Lib = Lib.slice(0, Lib.size()-2);
868 Qtx = Name.slice(a, Name.npos);
871 b = Name.rfind('/', a);
873 Lib = Name.slice(0, a);
875 Lib = Name.slice(b+1, a);
876 // There are library names of the form: QT.A.qtx so check for these.
877 if (Lib.size() >= 3) {
878 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
880 Lib = Lib.slice(0, Lib.size()-2);
885 // getLibraryShortNameByIndex() is used to get the short name of the library
886 // for an undefined symbol in a linked Mach-O binary that was linked with the
887 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
888 // It is passed the index (0 - based) of the library as translated from
889 // GET_LIBRARY_ORDINAL (1 - based).
890 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
891 StringRef &Res) const {
892 if (Index >= Libraries.size())
893 return object_error::parse_failed;
895 // If the cache of LibrariesShortNames is not built up do that first for
896 // all the Libraries.
897 if (LibrariesShortNames.size() == 0) {
898 for (unsigned i = 0; i < Libraries.size(); i++) {
899 MachO::dylib_command D =
900 getStruct<MachO::dylib_command>(this, Libraries[i]);
901 if (D.dylib.name >= D.cmdsize)
902 return object_error::parse_failed;
903 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
904 StringRef Name = StringRef(P);
905 if (D.dylib.name+Name.size() >= D.cmdsize)
906 return object_error::parse_failed;
909 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
910 if (shortName.empty())
911 LibrariesShortNames.push_back(Name);
913 LibrariesShortNames.push_back(shortName);
917 Res = LibrariesShortNames[Index];
918 return std::error_code();
922 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
924 Sec.d.a = Rel->getRawDataRefImpl().d.a;
925 return section_iterator(SectionRef(Sec, this));
928 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
929 return getSymbolByIndex(0);
932 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
935 return basic_symbol_iterator(SymbolRef(DRI, this));
937 MachO::symtab_command Symtab = getSymtabLoadCommand();
938 unsigned SymbolTableEntrySize = is64Bit() ?
939 sizeof(MachO::nlist_64) :
940 sizeof(MachO::nlist);
941 unsigned Offset = Symtab.symoff +
942 Symtab.nsyms * SymbolTableEntrySize;
943 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
944 return basic_symbol_iterator(SymbolRef(DRI, this));
947 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
950 return basic_symbol_iterator(SymbolRef(DRI, this));
952 MachO::symtab_command Symtab = getSymtabLoadCommand();
953 if (Index >= Symtab.nsyms)
954 report_fatal_error("Requested symbol index is out of range.");
955 unsigned SymbolTableEntrySize =
956 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
957 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
958 DRI.p += Index * SymbolTableEntrySize;
959 return basic_symbol_iterator(SymbolRef(DRI, this));
962 section_iterator MachOObjectFile::section_begin() const {
964 return section_iterator(SectionRef(DRI, this));
967 section_iterator MachOObjectFile::section_end() const {
969 DRI.d.a = Sections.size();
970 return section_iterator(SectionRef(DRI, this));
973 uint8_t MachOObjectFile::getBytesInAddress() const {
974 return is64Bit() ? 8 : 4;
977 StringRef MachOObjectFile::getFileFormatName() const {
978 unsigned CPUType = getCPUType(this);
981 case llvm::MachO::CPU_TYPE_I386:
982 return "Mach-O 32-bit i386";
983 case llvm::MachO::CPU_TYPE_ARM:
985 case llvm::MachO::CPU_TYPE_POWERPC:
986 return "Mach-O 32-bit ppc";
988 return "Mach-O 32-bit unknown";
993 case llvm::MachO::CPU_TYPE_X86_64:
994 return "Mach-O 64-bit x86-64";
995 case llvm::MachO::CPU_TYPE_ARM64:
996 return "Mach-O arm64";
997 case llvm::MachO::CPU_TYPE_POWERPC64:
998 return "Mach-O 64-bit ppc64";
1000 return "Mach-O 64-bit unknown";
1004 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1006 case llvm::MachO::CPU_TYPE_I386:
1008 case llvm::MachO::CPU_TYPE_X86_64:
1009 return Triple::x86_64;
1010 case llvm::MachO::CPU_TYPE_ARM:
1012 case llvm::MachO::CPU_TYPE_ARM64:
1013 return Triple::aarch64;
1014 case llvm::MachO::CPU_TYPE_POWERPC:
1016 case llvm::MachO::CPU_TYPE_POWERPC64:
1017 return Triple::ppc64;
1019 return Triple::UnknownArch;
1023 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1024 const char **McpuDefault) {
1026 *McpuDefault = nullptr;
1029 case MachO::CPU_TYPE_I386:
1030 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1031 case MachO::CPU_SUBTYPE_I386_ALL:
1032 return Triple("i386-apple-darwin");
1036 case MachO::CPU_TYPE_X86_64:
1037 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1038 case MachO::CPU_SUBTYPE_X86_64_ALL:
1039 return Triple("x86_64-apple-darwin");
1040 case MachO::CPU_SUBTYPE_X86_64_H:
1041 return Triple("x86_64h-apple-darwin");
1045 case MachO::CPU_TYPE_ARM:
1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047 case MachO::CPU_SUBTYPE_ARM_V4T:
1048 return Triple("armv4t-apple-darwin");
1049 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1050 return Triple("armv5e-apple-darwin");
1051 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1052 return Triple("xscale-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_V6:
1054 return Triple("armv6-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_V6M:
1057 *McpuDefault = "cortex-m0";
1058 return Triple("armv6m-apple-darwin");
1059 case MachO::CPU_SUBTYPE_ARM_V7:
1060 return Triple("armv7-apple-darwin");
1061 case MachO::CPU_SUBTYPE_ARM_V7EM:
1063 *McpuDefault = "cortex-m4";
1064 return Triple("armv7em-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V7K:
1066 return Triple("armv7k-apple-darwin");
1067 case MachO::CPU_SUBTYPE_ARM_V7M:
1069 *McpuDefault = "cortex-m3";
1070 return Triple("armv7m-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V7S:
1072 return Triple("armv7s-apple-darwin");
1076 case MachO::CPU_TYPE_ARM64:
1077 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1078 case MachO::CPU_SUBTYPE_ARM64_ALL:
1079 return Triple("arm64-apple-darwin");
1083 case MachO::CPU_TYPE_POWERPC:
1084 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1085 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1086 return Triple("ppc-apple-darwin");
1090 case MachO::CPU_TYPE_POWERPC64:
1091 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1092 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1093 return Triple("ppc64-apple-darwin");
1102 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1103 const char **McpuDefault) {
1105 *McpuDefault = nullptr;
1108 case MachO::CPU_TYPE_ARM:
1109 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1110 case MachO::CPU_SUBTYPE_ARM_V4T:
1111 return Triple("thumbv4t-apple-darwin");
1112 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1113 return Triple("thumbv5e-apple-darwin");
1114 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1115 return Triple("xscale-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_V6:
1117 return Triple("thumbv6-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_V6M:
1120 *McpuDefault = "cortex-m0";
1121 return Triple("thumbv6m-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_V7:
1123 return Triple("thumbv7-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V7EM:
1126 *McpuDefault = "cortex-m4";
1127 return Triple("thumbv7em-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V7K:
1129 return Triple("thumbv7k-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_V7M:
1132 *McpuDefault = "cortex-m3";
1133 return Triple("thumbv7m-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V7S:
1135 return Triple("thumbv7s-apple-darwin");
1144 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1145 const char **McpuDefault,
1146 Triple *ThumbTriple) {
1147 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1148 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1153 Triple MachOObjectFile::getHostArch() {
1154 return Triple(sys::getDefaultTargetTriple());
1157 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1158 return StringSwitch<bool>(ArchFlag)
1160 .Case("x86_64", true)
1161 .Case("x86_64h", true)
1162 .Case("armv4t", true)
1164 .Case("armv5e", true)
1165 .Case("armv6", true)
1166 .Case("armv6m", true)
1167 .Case("armv7", true)
1168 .Case("armv7em", true)
1169 .Case("armv7k", true)
1170 .Case("armv7m", true)
1171 .Case("armv7s", true)
1172 .Case("arm64", true)
1174 .Case("ppc64", true)
1178 unsigned MachOObjectFile::getArch() const {
1179 return getArch(getCPUType(this));
1182 Triple MachOObjectFile::getArch(const char **McpuDefault,
1183 Triple *ThumbTriple) const {
1184 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1185 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1188 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1191 return section_rel_begin(DRI);
1194 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1197 return section_rel_end(DRI);
1200 dice_iterator MachOObjectFile::begin_dices() const {
1202 if (!DataInCodeLoadCmd)
1203 return dice_iterator(DiceRef(DRI, this));
1205 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1206 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1207 return dice_iterator(DiceRef(DRI, this));
1210 dice_iterator MachOObjectFile::end_dices() const {
1212 if (!DataInCodeLoadCmd)
1213 return dice_iterator(DiceRef(DRI, this));
1215 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1216 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1217 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1218 return dice_iterator(DiceRef(DRI, this));
1221 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1222 : Trie(T), Malformed(false), Done(false) { }
1224 void ExportEntry::moveToFirst() {
1226 pushDownUntilBottom();
1229 void ExportEntry::moveToEnd() {
1234 bool ExportEntry::operator==(const ExportEntry &Other) const {
1235 // Common case, one at end, other iterating from begin.
1236 if (Done || Other.Done)
1237 return (Done == Other.Done);
1238 // Not equal if different stack sizes.
1239 if (Stack.size() != Other.Stack.size())
1241 // Not equal if different cumulative strings.
1242 if (!CumulativeString.equals(Other.CumulativeString))
1244 // Equal if all nodes in both stacks match.
1245 for (unsigned i=0; i < Stack.size(); ++i) {
1246 if (Stack[i].Start != Other.Stack[i].Start)
1252 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1254 uint64_t Result = decodeULEB128(Ptr, &Count);
1256 if (Ptr > Trie.end()) {
1263 StringRef ExportEntry::name() const {
1264 return CumulativeString;
1267 uint64_t ExportEntry::flags() const {
1268 return Stack.back().Flags;
1271 uint64_t ExportEntry::address() const {
1272 return Stack.back().Address;
1275 uint64_t ExportEntry::other() const {
1276 return Stack.back().Other;
1279 StringRef ExportEntry::otherName() const {
1280 const char* ImportName = Stack.back().ImportName;
1282 return StringRef(ImportName);
1286 uint32_t ExportEntry::nodeOffset() const {
1287 return Stack.back().Start - Trie.begin();
1290 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1291 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1292 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1293 ParentStringLength(0), IsExportNode(false) {
1296 void ExportEntry::pushNode(uint64_t offset) {
1297 const uint8_t *Ptr = Trie.begin() + offset;
1298 NodeState State(Ptr);
1299 uint64_t ExportInfoSize = readULEB128(State.Current);
1300 State.IsExportNode = (ExportInfoSize != 0);
1301 const uint8_t* Children = State.Current + ExportInfoSize;
1302 if (State.IsExportNode) {
1303 State.Flags = readULEB128(State.Current);
1304 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1306 State.Other = readULEB128(State.Current); // dylib ordinal
1307 State.ImportName = reinterpret_cast<const char*>(State.Current);
1309 State.Address = readULEB128(State.Current);
1310 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1311 State.Other = readULEB128(State.Current);
1314 State.ChildCount = *Children;
1315 State.Current = Children + 1;
1316 State.NextChildIndex = 0;
1317 State.ParentStringLength = CumulativeString.size();
1318 Stack.push_back(State);
1321 void ExportEntry::pushDownUntilBottom() {
1322 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1323 NodeState &Top = Stack.back();
1324 CumulativeString.resize(Top.ParentStringLength);
1325 for (;*Top.Current != 0; Top.Current++) {
1326 char C = *Top.Current;
1327 CumulativeString.push_back(C);
1330 uint64_t childNodeIndex = readULEB128(Top.Current);
1331 Top.NextChildIndex += 1;
1332 pushNode(childNodeIndex);
1334 if (!Stack.back().IsExportNode) {
1340 // We have a trie data structure and need a way to walk it that is compatible
1341 // with the C++ iterator model. The solution is a non-recursive depth first
1342 // traversal where the iterator contains a stack of parent nodes along with a
1343 // string that is the accumulation of all edge strings along the parent chain
1346 // There is one "export" node for each exported symbol. But because some
1347 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1348 // node may have child nodes too.
1350 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1351 // child until hitting a node with no children (which is an export node or
1352 // else the trie is malformed). On the way down, each node is pushed on the
1353 // stack ivar. If there is no more ways down, it pops up one and tries to go
1354 // down a sibling path until a childless node is reached.
1355 void ExportEntry::moveNext() {
1356 if (Stack.empty() || !Stack.back().IsExportNode) {
1363 while (!Stack.empty()) {
1364 NodeState &Top = Stack.back();
1365 if (Top.NextChildIndex < Top.ChildCount) {
1366 pushDownUntilBottom();
1367 // Now at the next export node.
1370 if (Top.IsExportNode) {
1371 // This node has no children but is itself an export node.
1372 CumulativeString.resize(Top.ParentStringLength);
1381 iterator_range<export_iterator>
1382 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1383 ExportEntry Start(Trie);
1384 if (Trie.size() == 0)
1387 Start.moveToFirst();
1389 ExportEntry Finish(Trie);
1392 return iterator_range<export_iterator>(export_iterator(Start),
1393 export_iterator(Finish));
1396 iterator_range<export_iterator> MachOObjectFile::exports() const {
1397 return exports(getDyldInfoExportsTrie());
1401 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1402 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1403 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1404 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1406 void MachORebaseEntry::moveToFirst() {
1407 Ptr = Opcodes.begin();
1411 void MachORebaseEntry::moveToEnd() {
1412 Ptr = Opcodes.end();
1413 RemainingLoopCount = 0;
1417 void MachORebaseEntry::moveNext() {
1418 // If in the middle of some loop, move to next rebasing in loop.
1419 SegmentOffset += AdvanceAmount;
1420 if (RemainingLoopCount) {
1421 --RemainingLoopCount;
1424 if (Ptr == Opcodes.end()) {
1429 while (More && !Malformed) {
1430 // Parse next opcode and set up next loop.
1431 uint8_t Byte = *Ptr++;
1432 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1433 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1435 case MachO::REBASE_OPCODE_DONE:
1439 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1441 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1442 RebaseType = ImmValue;
1445 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1446 << "RebaseType=" << (int) RebaseType << "\n");
1448 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1449 SegmentIndex = ImmValue;
1450 SegmentOffset = readULEB128();
1453 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1454 << "SegmentIndex=" << SegmentIndex << ", "
1455 << format("SegmentOffset=0x%06X", SegmentOffset)
1458 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1459 SegmentOffset += readULEB128();
1460 DEBUG_WITH_TYPE("mach-o-rebase",
1461 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1462 << format("SegmentOffset=0x%06X",
1463 SegmentOffset) << "\n");
1465 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1466 SegmentOffset += ImmValue * PointerSize;
1467 DEBUG_WITH_TYPE("mach-o-rebase",
1468 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1469 << format("SegmentOffset=0x%06X",
1470 SegmentOffset) << "\n");
1472 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1473 AdvanceAmount = PointerSize;
1474 RemainingLoopCount = ImmValue - 1;
1477 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1478 << format("SegmentOffset=0x%06X", SegmentOffset)
1479 << ", AdvanceAmount=" << AdvanceAmount
1480 << ", RemainingLoopCount=" << RemainingLoopCount
1483 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1484 AdvanceAmount = PointerSize;
1485 RemainingLoopCount = readULEB128() - 1;
1488 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1489 << format("SegmentOffset=0x%06X", SegmentOffset)
1490 << ", AdvanceAmount=" << AdvanceAmount
1491 << ", RemainingLoopCount=" << RemainingLoopCount
1494 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1495 AdvanceAmount = readULEB128() + PointerSize;
1496 RemainingLoopCount = 0;
1499 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1500 << format("SegmentOffset=0x%06X", SegmentOffset)
1501 << ", AdvanceAmount=" << AdvanceAmount
1502 << ", RemainingLoopCount=" << RemainingLoopCount
1505 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1506 RemainingLoopCount = readULEB128() - 1;
1507 AdvanceAmount = readULEB128() + PointerSize;
1510 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1511 << format("SegmentOffset=0x%06X", SegmentOffset)
1512 << ", AdvanceAmount=" << AdvanceAmount
1513 << ", RemainingLoopCount=" << RemainingLoopCount
1522 uint64_t MachORebaseEntry::readULEB128() {
1524 uint64_t Result = decodeULEB128(Ptr, &Count);
1526 if (Ptr > Opcodes.end()) {
1527 Ptr = Opcodes.end();
1533 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1535 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1537 StringRef MachORebaseEntry::typeName() const {
1538 switch (RebaseType) {
1539 case MachO::REBASE_TYPE_POINTER:
1541 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1542 return "text abs32";
1543 case MachO::REBASE_TYPE_TEXT_PCREL32:
1544 return "text rel32";
1549 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1550 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1551 return (Ptr == Other.Ptr) &&
1552 (RemainingLoopCount == Other.RemainingLoopCount) &&
1553 (Done == Other.Done);
1556 iterator_range<rebase_iterator>
1557 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1558 MachORebaseEntry Start(Opcodes, is64);
1559 Start.moveToFirst();
1561 MachORebaseEntry Finish(Opcodes, is64);
1564 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1565 rebase_iterator(Finish));
1568 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1569 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1573 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1575 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1576 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1577 BindType(0), PointerSize(is64Bit ? 8 : 4),
1578 TableKind(BK), Malformed(false), Done(false) {}
1580 void MachOBindEntry::moveToFirst() {
1581 Ptr = Opcodes.begin();
1585 void MachOBindEntry::moveToEnd() {
1586 Ptr = Opcodes.end();
1587 RemainingLoopCount = 0;
1591 void MachOBindEntry::moveNext() {
1592 // If in the middle of some loop, move to next binding in loop.
1593 SegmentOffset += AdvanceAmount;
1594 if (RemainingLoopCount) {
1595 --RemainingLoopCount;
1598 if (Ptr == Opcodes.end()) {
1603 while (More && !Malformed) {
1604 // Parse next opcode and set up next loop.
1605 uint8_t Byte = *Ptr++;
1606 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1607 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1608 int8_t SignExtended;
1609 const uint8_t *SymStart;
1611 case MachO::BIND_OPCODE_DONE:
1612 if (TableKind == Kind::Lazy) {
1613 // Lazying bindings have a DONE opcode between entries. Need to ignore
1614 // it to advance to next entry. But need not if this is last entry.
1615 bool NotLastEntry = false;
1616 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1618 NotLastEntry = true;
1627 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1629 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1633 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1634 << "Ordinal=" << Ordinal << "\n");
1636 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1637 Ordinal = readULEB128();
1640 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1641 << "Ordinal=" << Ordinal << "\n");
1643 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1645 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1646 Ordinal = SignExtended;
1651 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1652 << "Ordinal=" << Ordinal << "\n");
1654 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1660 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1665 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1666 << "SymbolName=" << SymbolName << "\n");
1667 if (TableKind == Kind::Weak) {
1668 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1672 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1673 BindType = ImmValue;
1676 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1677 << "BindType=" << (int)BindType << "\n");
1679 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1680 Addend = readSLEB128();
1681 if (TableKind == Kind::Lazy)
1685 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1686 << "Addend=" << Addend << "\n");
1688 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1689 SegmentIndex = ImmValue;
1690 SegmentOffset = readULEB128();
1693 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1694 << "SegmentIndex=" << SegmentIndex << ", "
1695 << format("SegmentOffset=0x%06X", SegmentOffset)
1698 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1699 SegmentOffset += readULEB128();
1700 DEBUG_WITH_TYPE("mach-o-bind",
1701 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1702 << format("SegmentOffset=0x%06X",
1703 SegmentOffset) << "\n");
1705 case MachO::BIND_OPCODE_DO_BIND:
1706 AdvanceAmount = PointerSize;
1707 RemainingLoopCount = 0;
1708 DEBUG_WITH_TYPE("mach-o-bind",
1709 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1710 << format("SegmentOffset=0x%06X",
1711 SegmentOffset) << "\n");
1713 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1714 AdvanceAmount = readULEB128() + PointerSize;
1715 RemainingLoopCount = 0;
1716 if (TableKind == Kind::Lazy)
1720 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1721 << format("SegmentOffset=0x%06X", SegmentOffset)
1722 << ", AdvanceAmount=" << AdvanceAmount
1723 << ", RemainingLoopCount=" << RemainingLoopCount
1726 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1727 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1728 RemainingLoopCount = 0;
1729 if (TableKind == Kind::Lazy)
1731 DEBUG_WITH_TYPE("mach-o-bind",
1733 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1734 << format("SegmentOffset=0x%06X",
1735 SegmentOffset) << "\n");
1737 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1738 RemainingLoopCount = readULEB128() - 1;
1739 AdvanceAmount = readULEB128() + PointerSize;
1740 if (TableKind == Kind::Lazy)
1744 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1745 << format("SegmentOffset=0x%06X", SegmentOffset)
1746 << ", AdvanceAmount=" << AdvanceAmount
1747 << ", RemainingLoopCount=" << RemainingLoopCount
1756 uint64_t MachOBindEntry::readULEB128() {
1758 uint64_t Result = decodeULEB128(Ptr, &Count);
1760 if (Ptr > Opcodes.end()) {
1761 Ptr = Opcodes.end();
1767 int64_t MachOBindEntry::readSLEB128() {
1769 int64_t Result = decodeSLEB128(Ptr, &Count);
1771 if (Ptr > Opcodes.end()) {
1772 Ptr = Opcodes.end();
1779 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1781 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1783 StringRef MachOBindEntry::typeName() const {
1785 case MachO::BIND_TYPE_POINTER:
1787 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1788 return "text abs32";
1789 case MachO::BIND_TYPE_TEXT_PCREL32:
1790 return "text rel32";
1795 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1797 int64_t MachOBindEntry::addend() const { return Addend; }
1799 uint32_t MachOBindEntry::flags() const { return Flags; }
1801 int MachOBindEntry::ordinal() const { return Ordinal; }
1803 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1804 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1805 return (Ptr == Other.Ptr) &&
1806 (RemainingLoopCount == Other.RemainingLoopCount) &&
1807 (Done == Other.Done);
1810 iterator_range<bind_iterator>
1811 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1812 MachOBindEntry::Kind BKind) {
1813 MachOBindEntry Start(Opcodes, is64, BKind);
1814 Start.moveToFirst();
1816 MachOBindEntry Finish(Opcodes, is64, BKind);
1819 return iterator_range<bind_iterator>(bind_iterator(Start),
1820 bind_iterator(Finish));
1823 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1824 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1825 MachOBindEntry::Kind::Regular);
1828 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1829 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1830 MachOBindEntry::Kind::Lazy);
1833 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1834 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1835 MachOBindEntry::Kind::Weak);
1838 MachOObjectFile::load_command_iterator
1839 MachOObjectFile::begin_load_commands() const {
1840 return LoadCommands.begin();
1843 MachOObjectFile::load_command_iterator
1844 MachOObjectFile::end_load_commands() const {
1845 return LoadCommands.end();
1848 iterator_range<MachOObjectFile::load_command_iterator>
1849 MachOObjectFile::load_commands() const {
1850 return iterator_range<load_command_iterator>(begin_load_commands(),
1851 end_load_commands());
1855 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1856 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1857 return parseSegmentOrSectionName(Raw.data());
1861 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1862 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1863 const section_base *Base =
1864 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1865 return makeArrayRef(Base->sectname);
1869 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1870 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1871 const section_base *Base =
1872 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1873 return makeArrayRef(Base->segname);
1877 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1879 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1881 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1884 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1885 const MachO::any_relocation_info &RE) const {
1886 if (isLittleEndian())
1887 return RE.r_word1 & 0xffffff;
1888 return RE.r_word1 >> 8;
1891 bool MachOObjectFile::getPlainRelocationExternal(
1892 const MachO::any_relocation_info &RE) const {
1893 if (isLittleEndian())
1894 return (RE.r_word1 >> 27) & 1;
1895 return (RE.r_word1 >> 4) & 1;
1898 bool MachOObjectFile::getScatteredRelocationScattered(
1899 const MachO::any_relocation_info &RE) const {
1900 return RE.r_word0 >> 31;
1903 uint32_t MachOObjectFile::getScatteredRelocationValue(
1904 const MachO::any_relocation_info &RE) const {
1908 uint32_t MachOObjectFile::getScatteredRelocationType(
1909 const MachO::any_relocation_info &RE) const {
1910 return (RE.r_word0 >> 24) & 0xf;
1913 unsigned MachOObjectFile::getAnyRelocationAddress(
1914 const MachO::any_relocation_info &RE) const {
1915 if (isRelocationScattered(RE))
1916 return getScatteredRelocationAddress(RE);
1917 return getPlainRelocationAddress(RE);
1920 unsigned MachOObjectFile::getAnyRelocationPCRel(
1921 const MachO::any_relocation_info &RE) const {
1922 if (isRelocationScattered(RE))
1923 return getScatteredRelocationPCRel(this, RE);
1924 return getPlainRelocationPCRel(this, RE);
1927 unsigned MachOObjectFile::getAnyRelocationLength(
1928 const MachO::any_relocation_info &RE) const {
1929 if (isRelocationScattered(RE))
1930 return getScatteredRelocationLength(RE);
1931 return getPlainRelocationLength(this, RE);
1935 MachOObjectFile::getAnyRelocationType(
1936 const MachO::any_relocation_info &RE) const {
1937 if (isRelocationScattered(RE))
1938 return getScatteredRelocationType(RE);
1939 return getPlainRelocationType(this, RE);
1943 MachOObjectFile::getAnyRelocationSection(
1944 const MachO::any_relocation_info &RE) const {
1945 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1946 return *section_end();
1947 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1948 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1949 return *section_end();
1951 DRI.d.a = SecNum - 1;
1952 return SectionRef(DRI, this);
1955 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1956 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1957 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1960 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1961 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1962 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1965 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1966 unsigned Index) const {
1967 const char *Sec = getSectionPtr(this, L, Index);
1968 return getStruct<MachO::section>(this, Sec);
1971 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1972 unsigned Index) const {
1973 const char *Sec = getSectionPtr(this, L, Index);
1974 return getStruct<MachO::section_64>(this, Sec);
1978 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1979 const char *P = reinterpret_cast<const char *>(DRI.p);
1980 return getStruct<MachO::nlist>(this, P);
1984 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1985 const char *P = reinterpret_cast<const char *>(DRI.p);
1986 return getStruct<MachO::nlist_64>(this, P);
1989 MachO::linkedit_data_command
1990 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1991 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1994 MachO::segment_command
1995 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1996 return getStruct<MachO::segment_command>(this, L.Ptr);
1999 MachO::segment_command_64
2000 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2001 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2004 MachO::linker_option_command
2005 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2006 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2009 MachO::version_min_command
2010 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2011 return getStruct<MachO::version_min_command>(this, L.Ptr);
2014 MachO::dylib_command
2015 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2016 return getStruct<MachO::dylib_command>(this, L.Ptr);
2019 MachO::dyld_info_command
2020 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2021 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2024 MachO::dylinker_command
2025 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2026 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2030 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2031 return getStruct<MachO::uuid_command>(this, L.Ptr);
2034 MachO::rpath_command
2035 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2036 return getStruct<MachO::rpath_command>(this, L.Ptr);
2039 MachO::source_version_command
2040 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2041 return getStruct<MachO::source_version_command>(this, L.Ptr);
2044 MachO::entry_point_command
2045 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2046 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2049 MachO::encryption_info_command
2050 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2051 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2054 MachO::encryption_info_command_64
2055 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2056 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2059 MachO::sub_framework_command
2060 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2061 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2064 MachO::sub_umbrella_command
2065 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2066 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2069 MachO::sub_library_command
2070 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2071 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2074 MachO::sub_client_command
2075 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2079 MachO::routines_command
2080 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::routines_command>(this, L.Ptr);
2084 MachO::routines_command_64
2085 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2089 MachO::thread_command
2090 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::thread_command>(this, L.Ptr);
2094 MachO::any_relocation_info
2095 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2100 MachO::section_64 Sect = getSection64(Sec);
2101 Offset = Sect.reloff;
2103 MachO::section Sect = getSection(Sec);
2104 Offset = Sect.reloff;
2107 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2108 getPtr(this, Offset)) + Rel.d.b;
2109 return getStruct<MachO::any_relocation_info>(
2110 this, reinterpret_cast<const char *>(P));
2113 MachO::data_in_code_entry
2114 MachOObjectFile::getDice(DataRefImpl Rel) const {
2115 const char *P = reinterpret_cast<const char *>(Rel.p);
2116 return getStruct<MachO::data_in_code_entry>(this, P);
2119 const MachO::mach_header &MachOObjectFile::getHeader() const {
2123 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2128 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2129 const MachO::dysymtab_command &DLC,
2130 unsigned Index) const {
2131 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2132 return getStruct<uint32_t>(this, getPtr(this, Offset));
2135 MachO::data_in_code_entry
2136 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2137 unsigned Index) const {
2138 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2139 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2142 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2144 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2146 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2147 MachO::symtab_command Cmd;
2148 Cmd.cmd = MachO::LC_SYMTAB;
2149 Cmd.cmdsize = sizeof(MachO::symtab_command);
2157 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2158 if (DysymtabLoadCmd)
2159 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2161 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2162 MachO::dysymtab_command Cmd;
2163 Cmd.cmd = MachO::LC_DYSYMTAB;
2164 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2175 Cmd.extrefsymoff = 0;
2176 Cmd.nextrefsyms = 0;
2177 Cmd.indirectsymoff = 0;
2178 Cmd.nindirectsyms = 0;
2186 MachO::linkedit_data_command
2187 MachOObjectFile::getDataInCodeLoadCommand() const {
2188 if (DataInCodeLoadCmd)
2189 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2191 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2192 MachO::linkedit_data_command Cmd;
2193 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2194 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2200 MachO::linkedit_data_command
2201 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2202 if (LinkOptHintsLoadCmd)
2203 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2205 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2207 MachO::linkedit_data_command Cmd;
2208 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2209 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2215 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2216 if (!DyldInfoLoadCmd)
2217 return ArrayRef<uint8_t>();
2219 MachO::dyld_info_command DyldInfo
2220 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2221 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2222 getPtr(this, DyldInfo.rebase_off));
2223 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2226 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2227 if (!DyldInfoLoadCmd)
2228 return ArrayRef<uint8_t>();
2230 MachO::dyld_info_command DyldInfo
2231 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2232 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2233 getPtr(this, DyldInfo.bind_off));
2234 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2237 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2238 if (!DyldInfoLoadCmd)
2239 return ArrayRef<uint8_t>();
2241 MachO::dyld_info_command DyldInfo
2242 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2243 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2244 getPtr(this, DyldInfo.weak_bind_off));
2245 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2248 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2249 if (!DyldInfoLoadCmd)
2250 return ArrayRef<uint8_t>();
2252 MachO::dyld_info_command DyldInfo
2253 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2254 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2255 getPtr(this, DyldInfo.lazy_bind_off));
2256 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2259 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2260 if (!DyldInfoLoadCmd)
2261 return ArrayRef<uint8_t>();
2263 MachO::dyld_info_command DyldInfo
2264 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2265 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2266 getPtr(this, DyldInfo.export_off));
2267 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2270 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2272 return ArrayRef<uint8_t>();
2273 // Returning a pointer is fine as uuid doesn't need endian swapping.
2274 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2275 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2278 StringRef MachOObjectFile::getStringTableData() const {
2279 MachO::symtab_command S = getSymtabLoadCommand();
2280 return getData().substr(S.stroff, S.strsize);
2283 bool MachOObjectFile::is64Bit() const {
2284 return getType() == getMachOType(false, true) ||
2285 getType() == getMachOType(true, true);
2288 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2289 SmallVectorImpl<uint64_t> &Out) const {
2290 DataExtractor extractor(ObjectFile::getData(), true, 0);
2292 uint32_t offset = Index;
2294 while (uint64_t delta = extractor.getULEB128(&offset)) {
2296 Out.push_back(data);
2300 bool MachOObjectFile::isRelocatableObject() const {
2301 return getHeader().filetype == MachO::MH_OBJECT;
2304 ErrorOr<std::unique_ptr<MachOObjectFile>>
2305 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2306 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2308 std::unique_ptr<MachOObjectFile> Ret;
2309 if (Magic == "\xFE\xED\xFA\xCE")
2310 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2311 else if (Magic == "\xCE\xFA\xED\xFE")
2312 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2313 else if (Magic == "\xFE\xED\xFA\xCF")
2314 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2315 else if (Magic == "\xCF\xFA\xED\xFE")
2316 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2318 return object_error::parse_failed;
2322 return std::move(Ret);