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 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
380 uint64_t &Res) const {
381 Res = getSymbolValue(Sym);
382 return std::error_code();
385 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
386 uint32_t flags = getSymbolFlags(DRI);
387 if (flags & SymbolRef::SF_Common) {
388 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
389 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
394 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
396 getSymbolAddress(DRI, Value);
400 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
401 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
402 uint8_t n_type = Entry.n_type;
404 // If this is a STAB debugging symbol, we can do nothing more.
405 if (n_type & MachO::N_STAB)
406 return SymbolRef::ST_Debug;
408 switch (n_type & MachO::N_TYPE) {
410 return SymbolRef::ST_Unknown;
412 return SymbolRef::ST_Function;
414 return SymbolRef::ST_Other;
417 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
418 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
420 uint8_t MachOType = Entry.n_type;
421 uint16_t MachOFlags = Entry.n_desc;
423 uint32_t Result = SymbolRef::SF_None;
425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
426 Result |= SymbolRef::SF_Undefined;
428 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
429 Result |= SymbolRef::SF_Indirect;
431 if (MachOType & MachO::N_STAB)
432 Result |= SymbolRef::SF_FormatSpecific;
434 if (MachOType & MachO::N_EXT) {
435 Result |= SymbolRef::SF_Global;
436 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
438 getSymbolAddress(DRI, Value);
439 if (Value && Value != UnknownAddress)
440 Result |= SymbolRef::SF_Common;
443 if (!(MachOType & MachO::N_PEXT))
444 Result |= SymbolRef::SF_Exported;
447 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
448 Result |= SymbolRef::SF_Weak;
450 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
451 Result |= SymbolRef::SF_Thumb;
453 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
454 Result |= SymbolRef::SF_Absolute;
459 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
460 section_iterator &Res) const {
461 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
462 uint8_t index = Entry.n_sect;
469 if (DRI.d.a >= Sections.size())
470 report_fatal_error("getSymbolSection: Invalid section index.");
471 Res = section_iterator(SectionRef(DRI, this));
474 return std::error_code();
477 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
478 MachO::nlist_base Entry =
479 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
480 return Entry.n_sect - 1;
483 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
487 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
488 StringRef &Result) const {
489 ArrayRef<char> Raw = getSectionRawName(Sec);
490 Result = parseSegmentOrSectionName(Raw.data());
491 return std::error_code();
494 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
496 return getSection64(Sec).addr;
497 return getSection(Sec).addr;
500 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
502 return getSection64(Sec).size;
503 return getSection(Sec).size;
506 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
507 StringRef &Res) const {
512 MachO::section_64 Sect = getSection64(Sec);
513 Offset = Sect.offset;
516 MachO::section Sect = getSection(Sec);
517 Offset = Sect.offset;
521 Res = this->getData().substr(Offset, Size);
522 return std::error_code();
525 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
528 MachO::section_64 Sect = getSection64(Sec);
531 MachO::section Sect = getSection(Sec);
535 return uint64_t(1) << Align;
538 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
539 uint32_t Flags = getSectionFlags(this, Sec);
540 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
543 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
544 uint32_t Flags = getSectionFlags(this, Sec);
545 unsigned SectionType = Flags & MachO::SECTION_TYPE;
546 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
547 !(SectionType == MachO::S_ZEROFILL ||
548 SectionType == MachO::S_GB_ZEROFILL);
551 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
552 uint32_t Flags = getSectionFlags(this, Sec);
553 unsigned SectionType = Flags & MachO::SECTION_TYPE;
554 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
555 (SectionType == MachO::S_ZEROFILL ||
556 SectionType == MachO::S_GB_ZEROFILL);
559 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
560 return Sec.getRawDataRefImpl().d.a;
563 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
564 // FIXME: Unimplemented.
568 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
572 return relocation_iterator(RelocationRef(Ret, this));
576 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
579 MachO::section_64 Sect = getSection64(Sec);
582 MachO::section Sect = getSection(Sec);
589 return relocation_iterator(RelocationRef(Ret, this));
592 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
596 ErrorOr<uint64_t> MachOObjectFile::getRelocationAddress(DataRefImpl Rel) const {
597 uint64_t Offset = getRelocationOffset(Rel);
601 uint64_t SecAddress = getSectionAddress(Sec);
602 return SecAddress + Offset;
605 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
606 assert(getHeader().filetype == MachO::MH_OBJECT &&
607 "Only implemented for MH_OBJECT");
608 MachO::any_relocation_info RE = getRelocation(Rel);
609 return getAnyRelocationAddress(RE);
613 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
614 MachO::any_relocation_info RE = getRelocation(Rel);
615 if (isRelocationScattered(RE))
618 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
619 bool isExtern = getPlainRelocationExternal(RE);
623 MachO::symtab_command S = getSymtabLoadCommand();
624 unsigned SymbolTableEntrySize = is64Bit() ?
625 sizeof(MachO::nlist_64) :
626 sizeof(MachO::nlist);
627 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
629 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
630 return symbol_iterator(SymbolRef(Sym, this));
634 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
635 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
638 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
639 MachO::any_relocation_info RE = getRelocation(Rel);
640 return getAnyRelocationType(RE);
643 void MachOObjectFile::getRelocationTypeName(
644 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
646 uint64_t RType = getRelocationType(Rel);
648 unsigned Arch = this->getArch();
652 static const char *const Table[] = {
653 "GENERIC_RELOC_VANILLA",
654 "GENERIC_RELOC_PAIR",
655 "GENERIC_RELOC_SECTDIFF",
656 "GENERIC_RELOC_PB_LA_PTR",
657 "GENERIC_RELOC_LOCAL_SECTDIFF",
658 "GENERIC_RELOC_TLV" };
666 case Triple::x86_64: {
667 static const char *const Table[] = {
668 "X86_64_RELOC_UNSIGNED",
669 "X86_64_RELOC_SIGNED",
670 "X86_64_RELOC_BRANCH",
671 "X86_64_RELOC_GOT_LOAD",
673 "X86_64_RELOC_SUBTRACTOR",
674 "X86_64_RELOC_SIGNED_1",
675 "X86_64_RELOC_SIGNED_2",
676 "X86_64_RELOC_SIGNED_4",
677 "X86_64_RELOC_TLV" };
686 static const char *const Table[] = {
689 "ARM_RELOC_SECTDIFF",
690 "ARM_RELOC_LOCAL_SECTDIFF",
691 "ARM_RELOC_PB_LA_PTR",
693 "ARM_THUMB_RELOC_BR22",
694 "ARM_THUMB_32BIT_BRANCH",
696 "ARM_RELOC_HALF_SECTDIFF" };
704 case Triple::aarch64: {
705 static const char *const Table[] = {
706 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
707 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
708 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
709 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
710 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
714 if (RType >= array_lengthof(Table))
721 static const char *const Table[] = {
730 "PPC_RELOC_SECTDIFF",
731 "PPC_RELOC_PB_LA_PTR",
732 "PPC_RELOC_HI16_SECTDIFF",
733 "PPC_RELOC_LO16_SECTDIFF",
734 "PPC_RELOC_HA16_SECTDIFF",
736 "PPC_RELOC_LO14_SECTDIFF",
737 "PPC_RELOC_LOCAL_SECTDIFF" };
745 case Triple::UnknownArch:
749 Result.append(res.begin(), res.end());
752 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
753 MachO::any_relocation_info RE = getRelocation(Rel);
754 return getAnyRelocationLength(RE);
758 // guessLibraryShortName() is passed a name of a dynamic library and returns a
759 // guess on what the short name is. Then name is returned as a substring of the
760 // StringRef Name passed in. The name of the dynamic library is recognized as
761 // a framework if it has one of the two following forms:
762 // Foo.framework/Versions/A/Foo
764 // Where A and Foo can be any string. And may contain a trailing suffix
765 // starting with an underbar. If the Name is recognized as a framework then
766 // isFramework is set to true else it is set to false. If the Name has a
767 // suffix then Suffix is set to the substring in Name that contains the suffix
768 // else it is set to a NULL StringRef.
770 // The Name of the dynamic library is recognized as a library name if it has
771 // one of the two following forms:
774 // The library may have a suffix trailing the name Foo of the form:
775 // libFoo_profile.A.dylib
776 // libFoo_profile.dylib
778 // The Name of the dynamic library is also recognized as a library name if it
779 // has the following form:
782 // If the Name of the dynamic library is none of the forms above then a NULL
783 // StringRef is returned.
785 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
788 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
789 size_t a, b, c, d, Idx;
792 Suffix = StringRef();
794 // Pull off the last component and make Foo point to it
796 if (a == Name.npos || a == 0)
798 Foo = Name.slice(a+1, Name.npos);
800 // Look for a suffix starting with a '_'
801 Idx = Foo.rfind('_');
802 if (Idx != Foo.npos && Foo.size() >= 2) {
803 Suffix = Foo.slice(Idx, Foo.npos);
804 Foo = Foo.slice(0, Idx);
807 // First look for the form Foo.framework/Foo
808 b = Name.rfind('/', a);
813 F = Name.slice(Idx, Idx + Foo.size());
814 DotFramework = Name.slice(Idx + Foo.size(),
815 Idx + Foo.size() + sizeof(".framework/")-1);
816 if (F == Foo && DotFramework == ".framework/") {
821 // Next look for the form Foo.framework/Versions/A/Foo
824 c = Name.rfind('/', b);
825 if (c == Name.npos || c == 0)
827 V = Name.slice(c+1, Name.npos);
828 if (!V.startswith("Versions/"))
830 d = Name.rfind('/', c);
835 F = Name.slice(Idx, Idx + Foo.size());
836 DotFramework = Name.slice(Idx + Foo.size(),
837 Idx + Foo.size() + sizeof(".framework/")-1);
838 if (F == Foo && DotFramework == ".framework/") {
844 // pull off the suffix after the "." and make a point to it
846 if (a == Name.npos || a == 0)
848 Dylib = Name.slice(a, Name.npos);
849 if (Dylib != ".dylib")
852 // First pull off the version letter for the form Foo.A.dylib if any.
854 Dot = Name.slice(a-2, a-1);
859 b = Name.rfind('/', a);
864 // ignore any suffix after an underbar like Foo_profile.A.dylib
865 Idx = Name.find('_', b);
866 if (Idx != Name.npos && Idx != b) {
867 Lib = Name.slice(b, Idx);
868 Suffix = Name.slice(Idx, a);
871 Lib = Name.slice(b, a);
872 // There are incorrect library names of the form:
873 // libATS.A_profile.dylib so check for these.
874 if (Lib.size() >= 3) {
875 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
877 Lib = Lib.slice(0, Lib.size()-2);
882 Qtx = Name.slice(a, Name.npos);
885 b = Name.rfind('/', a);
887 Lib = Name.slice(0, a);
889 Lib = Name.slice(b+1, a);
890 // There are library names of the form: QT.A.qtx so check for these.
891 if (Lib.size() >= 3) {
892 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
894 Lib = Lib.slice(0, Lib.size()-2);
899 // getLibraryShortNameByIndex() is used to get the short name of the library
900 // for an undefined symbol in a linked Mach-O binary that was linked with the
901 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
902 // It is passed the index (0 - based) of the library as translated from
903 // GET_LIBRARY_ORDINAL (1 - based).
904 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
905 StringRef &Res) const {
906 if (Index >= Libraries.size())
907 return object_error::parse_failed;
909 // If the cache of LibrariesShortNames is not built up do that first for
910 // all the Libraries.
911 if (LibrariesShortNames.size() == 0) {
912 for (unsigned i = 0; i < Libraries.size(); i++) {
913 MachO::dylib_command D =
914 getStruct<MachO::dylib_command>(this, Libraries[i]);
915 if (D.dylib.name >= D.cmdsize)
916 return object_error::parse_failed;
917 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
918 StringRef Name = StringRef(P);
919 if (D.dylib.name+Name.size() >= D.cmdsize)
920 return object_error::parse_failed;
923 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
924 if (shortName.empty())
925 LibrariesShortNames.push_back(Name);
927 LibrariesShortNames.push_back(shortName);
931 Res = LibrariesShortNames[Index];
932 return std::error_code();
935 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
936 return getSymbolByIndex(0);
939 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
942 return basic_symbol_iterator(SymbolRef(DRI, this));
944 MachO::symtab_command Symtab = getSymtabLoadCommand();
945 unsigned SymbolTableEntrySize = is64Bit() ?
946 sizeof(MachO::nlist_64) :
947 sizeof(MachO::nlist);
948 unsigned Offset = Symtab.symoff +
949 Symtab.nsyms * SymbolTableEntrySize;
950 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
951 return basic_symbol_iterator(SymbolRef(DRI, this));
954 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
957 return basic_symbol_iterator(SymbolRef(DRI, this));
959 MachO::symtab_command Symtab = getSymtabLoadCommand();
960 if (Index >= Symtab.nsyms)
961 report_fatal_error("Requested symbol index is out of range.");
962 unsigned SymbolTableEntrySize =
963 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
964 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
965 DRI.p += Index * SymbolTableEntrySize;
966 return basic_symbol_iterator(SymbolRef(DRI, this));
969 section_iterator MachOObjectFile::section_begin() const {
971 return section_iterator(SectionRef(DRI, this));
974 section_iterator MachOObjectFile::section_end() const {
976 DRI.d.a = Sections.size();
977 return section_iterator(SectionRef(DRI, this));
980 uint8_t MachOObjectFile::getBytesInAddress() const {
981 return is64Bit() ? 8 : 4;
984 StringRef MachOObjectFile::getFileFormatName() const {
985 unsigned CPUType = getCPUType(this);
988 case llvm::MachO::CPU_TYPE_I386:
989 return "Mach-O 32-bit i386";
990 case llvm::MachO::CPU_TYPE_ARM:
992 case llvm::MachO::CPU_TYPE_POWERPC:
993 return "Mach-O 32-bit ppc";
995 return "Mach-O 32-bit unknown";
1000 case llvm::MachO::CPU_TYPE_X86_64:
1001 return "Mach-O 64-bit x86-64";
1002 case llvm::MachO::CPU_TYPE_ARM64:
1003 return "Mach-O arm64";
1004 case llvm::MachO::CPU_TYPE_POWERPC64:
1005 return "Mach-O 64-bit ppc64";
1007 return "Mach-O 64-bit unknown";
1011 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1013 case llvm::MachO::CPU_TYPE_I386:
1015 case llvm::MachO::CPU_TYPE_X86_64:
1016 return Triple::x86_64;
1017 case llvm::MachO::CPU_TYPE_ARM:
1019 case llvm::MachO::CPU_TYPE_ARM64:
1020 return Triple::aarch64;
1021 case llvm::MachO::CPU_TYPE_POWERPC:
1023 case llvm::MachO::CPU_TYPE_POWERPC64:
1024 return Triple::ppc64;
1026 return Triple::UnknownArch;
1030 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1031 const char **McpuDefault) {
1033 *McpuDefault = nullptr;
1036 case MachO::CPU_TYPE_I386:
1037 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1038 case MachO::CPU_SUBTYPE_I386_ALL:
1039 return Triple("i386-apple-darwin");
1043 case MachO::CPU_TYPE_X86_64:
1044 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1045 case MachO::CPU_SUBTYPE_X86_64_ALL:
1046 return Triple("x86_64-apple-darwin");
1047 case MachO::CPU_SUBTYPE_X86_64_H:
1048 return Triple("x86_64h-apple-darwin");
1052 case MachO::CPU_TYPE_ARM:
1053 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054 case MachO::CPU_SUBTYPE_ARM_V4T:
1055 return Triple("armv4t-apple-darwin");
1056 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1057 return Triple("armv5e-apple-darwin");
1058 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1059 return Triple("xscale-apple-darwin");
1060 case MachO::CPU_SUBTYPE_ARM_V6:
1061 return Triple("armv6-apple-darwin");
1062 case MachO::CPU_SUBTYPE_ARM_V6M:
1064 *McpuDefault = "cortex-m0";
1065 return Triple("armv6m-apple-darwin");
1066 case MachO::CPU_SUBTYPE_ARM_V7:
1067 return Triple("armv7-apple-darwin");
1068 case MachO::CPU_SUBTYPE_ARM_V7EM:
1070 *McpuDefault = "cortex-m4";
1071 return Triple("armv7em-apple-darwin");
1072 case MachO::CPU_SUBTYPE_ARM_V7K:
1073 return Triple("armv7k-apple-darwin");
1074 case MachO::CPU_SUBTYPE_ARM_V7M:
1076 *McpuDefault = "cortex-m3";
1077 return Triple("armv7m-apple-darwin");
1078 case MachO::CPU_SUBTYPE_ARM_V7S:
1079 return Triple("armv7s-apple-darwin");
1083 case MachO::CPU_TYPE_ARM64:
1084 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1085 case MachO::CPU_SUBTYPE_ARM64_ALL:
1086 return Triple("arm64-apple-darwin");
1090 case MachO::CPU_TYPE_POWERPC:
1091 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1092 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1093 return Triple("ppc-apple-darwin");
1097 case MachO::CPU_TYPE_POWERPC64:
1098 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1099 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1100 return Triple("ppc64-apple-darwin");
1109 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1110 const char **McpuDefault) {
1112 *McpuDefault = nullptr;
1115 case MachO::CPU_TYPE_ARM:
1116 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1117 case MachO::CPU_SUBTYPE_ARM_V4T:
1118 return Triple("thumbv4t-apple-darwin");
1119 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1120 return Triple("thumbv5e-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1122 return Triple("xscale-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V6:
1124 return Triple("thumbv6-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V6M:
1127 *McpuDefault = "cortex-m0";
1128 return Triple("thumbv6m-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V7:
1130 return Triple("thumbv7-apple-darwin");
1131 case MachO::CPU_SUBTYPE_ARM_V7EM:
1133 *McpuDefault = "cortex-m4";
1134 return Triple("thumbv7em-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V7K:
1136 return Triple("thumbv7k-apple-darwin");
1137 case MachO::CPU_SUBTYPE_ARM_V7M:
1139 *McpuDefault = "cortex-m3";
1140 return Triple("thumbv7m-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_V7S:
1142 return Triple("thumbv7s-apple-darwin");
1151 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1152 const char **McpuDefault,
1153 Triple *ThumbTriple) {
1154 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1155 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1160 Triple MachOObjectFile::getHostArch() {
1161 return Triple(sys::getDefaultTargetTriple());
1164 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1165 return StringSwitch<bool>(ArchFlag)
1167 .Case("x86_64", true)
1168 .Case("x86_64h", true)
1169 .Case("armv4t", true)
1171 .Case("armv5e", true)
1172 .Case("armv6", true)
1173 .Case("armv6m", true)
1174 .Case("armv7", true)
1175 .Case("armv7em", true)
1176 .Case("armv7k", true)
1177 .Case("armv7m", true)
1178 .Case("armv7s", true)
1179 .Case("arm64", true)
1181 .Case("ppc64", true)
1185 unsigned MachOObjectFile::getArch() const {
1186 return getArch(getCPUType(this));
1189 Triple MachOObjectFile::getArch(const char **McpuDefault,
1190 Triple *ThumbTriple) const {
1191 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1192 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1195 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1198 return section_rel_begin(DRI);
1201 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1204 return section_rel_end(DRI);
1207 dice_iterator MachOObjectFile::begin_dices() const {
1209 if (!DataInCodeLoadCmd)
1210 return dice_iterator(DiceRef(DRI, this));
1212 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1213 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1214 return dice_iterator(DiceRef(DRI, this));
1217 dice_iterator MachOObjectFile::end_dices() const {
1219 if (!DataInCodeLoadCmd)
1220 return dice_iterator(DiceRef(DRI, this));
1222 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1223 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1224 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1225 return dice_iterator(DiceRef(DRI, this));
1228 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1229 : Trie(T), Malformed(false), Done(false) { }
1231 void ExportEntry::moveToFirst() {
1233 pushDownUntilBottom();
1236 void ExportEntry::moveToEnd() {
1241 bool ExportEntry::operator==(const ExportEntry &Other) const {
1242 // Common case, one at end, other iterating from begin.
1243 if (Done || Other.Done)
1244 return (Done == Other.Done);
1245 // Not equal if different stack sizes.
1246 if (Stack.size() != Other.Stack.size())
1248 // Not equal if different cumulative strings.
1249 if (!CumulativeString.equals(Other.CumulativeString))
1251 // Equal if all nodes in both stacks match.
1252 for (unsigned i=0; i < Stack.size(); ++i) {
1253 if (Stack[i].Start != Other.Stack[i].Start)
1259 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1261 uint64_t Result = decodeULEB128(Ptr, &Count);
1263 if (Ptr > Trie.end()) {
1270 StringRef ExportEntry::name() const {
1271 return CumulativeString;
1274 uint64_t ExportEntry::flags() const {
1275 return Stack.back().Flags;
1278 uint64_t ExportEntry::address() const {
1279 return Stack.back().Address;
1282 uint64_t ExportEntry::other() const {
1283 return Stack.back().Other;
1286 StringRef ExportEntry::otherName() const {
1287 const char* ImportName = Stack.back().ImportName;
1289 return StringRef(ImportName);
1293 uint32_t ExportEntry::nodeOffset() const {
1294 return Stack.back().Start - Trie.begin();
1297 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1298 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1299 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1300 ParentStringLength(0), IsExportNode(false) {
1303 void ExportEntry::pushNode(uint64_t offset) {
1304 const uint8_t *Ptr = Trie.begin() + offset;
1305 NodeState State(Ptr);
1306 uint64_t ExportInfoSize = readULEB128(State.Current);
1307 State.IsExportNode = (ExportInfoSize != 0);
1308 const uint8_t* Children = State.Current + ExportInfoSize;
1309 if (State.IsExportNode) {
1310 State.Flags = readULEB128(State.Current);
1311 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1313 State.Other = readULEB128(State.Current); // dylib ordinal
1314 State.ImportName = reinterpret_cast<const char*>(State.Current);
1316 State.Address = readULEB128(State.Current);
1317 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1318 State.Other = readULEB128(State.Current);
1321 State.ChildCount = *Children;
1322 State.Current = Children + 1;
1323 State.NextChildIndex = 0;
1324 State.ParentStringLength = CumulativeString.size();
1325 Stack.push_back(State);
1328 void ExportEntry::pushDownUntilBottom() {
1329 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1330 NodeState &Top = Stack.back();
1331 CumulativeString.resize(Top.ParentStringLength);
1332 for (;*Top.Current != 0; Top.Current++) {
1333 char C = *Top.Current;
1334 CumulativeString.push_back(C);
1337 uint64_t childNodeIndex = readULEB128(Top.Current);
1338 Top.NextChildIndex += 1;
1339 pushNode(childNodeIndex);
1341 if (!Stack.back().IsExportNode) {
1347 // We have a trie data structure and need a way to walk it that is compatible
1348 // with the C++ iterator model. The solution is a non-recursive depth first
1349 // traversal where the iterator contains a stack of parent nodes along with a
1350 // string that is the accumulation of all edge strings along the parent chain
1353 // There is one "export" node for each exported symbol. But because some
1354 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1355 // node may have child nodes too.
1357 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1358 // child until hitting a node with no children (which is an export node or
1359 // else the trie is malformed). On the way down, each node is pushed on the
1360 // stack ivar. If there is no more ways down, it pops up one and tries to go
1361 // down a sibling path until a childless node is reached.
1362 void ExportEntry::moveNext() {
1363 if (Stack.empty() || !Stack.back().IsExportNode) {
1370 while (!Stack.empty()) {
1371 NodeState &Top = Stack.back();
1372 if (Top.NextChildIndex < Top.ChildCount) {
1373 pushDownUntilBottom();
1374 // Now at the next export node.
1377 if (Top.IsExportNode) {
1378 // This node has no children but is itself an export node.
1379 CumulativeString.resize(Top.ParentStringLength);
1388 iterator_range<export_iterator>
1389 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1390 ExportEntry Start(Trie);
1391 if (Trie.size() == 0)
1394 Start.moveToFirst();
1396 ExportEntry Finish(Trie);
1399 return iterator_range<export_iterator>(export_iterator(Start),
1400 export_iterator(Finish));
1403 iterator_range<export_iterator> MachOObjectFile::exports() const {
1404 return exports(getDyldInfoExportsTrie());
1408 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1409 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1410 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1411 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1413 void MachORebaseEntry::moveToFirst() {
1414 Ptr = Opcodes.begin();
1418 void MachORebaseEntry::moveToEnd() {
1419 Ptr = Opcodes.end();
1420 RemainingLoopCount = 0;
1424 void MachORebaseEntry::moveNext() {
1425 // If in the middle of some loop, move to next rebasing in loop.
1426 SegmentOffset += AdvanceAmount;
1427 if (RemainingLoopCount) {
1428 --RemainingLoopCount;
1431 if (Ptr == Opcodes.end()) {
1436 while (More && !Malformed) {
1437 // Parse next opcode and set up next loop.
1438 uint8_t Byte = *Ptr++;
1439 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1440 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1442 case MachO::REBASE_OPCODE_DONE:
1446 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1448 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1449 RebaseType = ImmValue;
1452 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1453 << "RebaseType=" << (int) RebaseType << "\n");
1455 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1456 SegmentIndex = ImmValue;
1457 SegmentOffset = readULEB128();
1460 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1461 << "SegmentIndex=" << SegmentIndex << ", "
1462 << format("SegmentOffset=0x%06X", SegmentOffset)
1465 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1466 SegmentOffset += readULEB128();
1467 DEBUG_WITH_TYPE("mach-o-rebase",
1468 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1469 << format("SegmentOffset=0x%06X",
1470 SegmentOffset) << "\n");
1472 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1473 SegmentOffset += ImmValue * PointerSize;
1474 DEBUG_WITH_TYPE("mach-o-rebase",
1475 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1476 << format("SegmentOffset=0x%06X",
1477 SegmentOffset) << "\n");
1479 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1480 AdvanceAmount = PointerSize;
1481 RemainingLoopCount = ImmValue - 1;
1484 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1485 << format("SegmentOffset=0x%06X", SegmentOffset)
1486 << ", AdvanceAmount=" << AdvanceAmount
1487 << ", RemainingLoopCount=" << RemainingLoopCount
1490 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1491 AdvanceAmount = PointerSize;
1492 RemainingLoopCount = readULEB128() - 1;
1495 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1496 << format("SegmentOffset=0x%06X", SegmentOffset)
1497 << ", AdvanceAmount=" << AdvanceAmount
1498 << ", RemainingLoopCount=" << RemainingLoopCount
1501 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1502 AdvanceAmount = readULEB128() + PointerSize;
1503 RemainingLoopCount = 0;
1506 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1507 << format("SegmentOffset=0x%06X", SegmentOffset)
1508 << ", AdvanceAmount=" << AdvanceAmount
1509 << ", RemainingLoopCount=" << RemainingLoopCount
1512 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1513 RemainingLoopCount = readULEB128() - 1;
1514 AdvanceAmount = readULEB128() + PointerSize;
1517 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1518 << format("SegmentOffset=0x%06X", SegmentOffset)
1519 << ", AdvanceAmount=" << AdvanceAmount
1520 << ", RemainingLoopCount=" << RemainingLoopCount
1529 uint64_t MachORebaseEntry::readULEB128() {
1531 uint64_t Result = decodeULEB128(Ptr, &Count);
1533 if (Ptr > Opcodes.end()) {
1534 Ptr = Opcodes.end();
1540 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1542 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1544 StringRef MachORebaseEntry::typeName() const {
1545 switch (RebaseType) {
1546 case MachO::REBASE_TYPE_POINTER:
1548 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1549 return "text abs32";
1550 case MachO::REBASE_TYPE_TEXT_PCREL32:
1551 return "text rel32";
1556 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1557 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1558 return (Ptr == Other.Ptr) &&
1559 (RemainingLoopCount == Other.RemainingLoopCount) &&
1560 (Done == Other.Done);
1563 iterator_range<rebase_iterator>
1564 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1565 MachORebaseEntry Start(Opcodes, is64);
1566 Start.moveToFirst();
1568 MachORebaseEntry Finish(Opcodes, is64);
1571 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1572 rebase_iterator(Finish));
1575 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1576 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1580 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1582 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1583 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1584 BindType(0), PointerSize(is64Bit ? 8 : 4),
1585 TableKind(BK), Malformed(false), Done(false) {}
1587 void MachOBindEntry::moveToFirst() {
1588 Ptr = Opcodes.begin();
1592 void MachOBindEntry::moveToEnd() {
1593 Ptr = Opcodes.end();
1594 RemainingLoopCount = 0;
1598 void MachOBindEntry::moveNext() {
1599 // If in the middle of some loop, move to next binding in loop.
1600 SegmentOffset += AdvanceAmount;
1601 if (RemainingLoopCount) {
1602 --RemainingLoopCount;
1605 if (Ptr == Opcodes.end()) {
1610 while (More && !Malformed) {
1611 // Parse next opcode and set up next loop.
1612 uint8_t Byte = *Ptr++;
1613 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1614 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1615 int8_t SignExtended;
1616 const uint8_t *SymStart;
1618 case MachO::BIND_OPCODE_DONE:
1619 if (TableKind == Kind::Lazy) {
1620 // Lazying bindings have a DONE opcode between entries. Need to ignore
1621 // it to advance to next entry. But need not if this is last entry.
1622 bool NotLastEntry = false;
1623 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1625 NotLastEntry = true;
1634 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1636 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1640 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1641 << "Ordinal=" << Ordinal << "\n");
1643 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1644 Ordinal = readULEB128();
1647 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1648 << "Ordinal=" << Ordinal << "\n");
1650 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1652 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1653 Ordinal = SignExtended;
1658 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1659 << "Ordinal=" << Ordinal << "\n");
1661 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1667 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1672 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1673 << "SymbolName=" << SymbolName << "\n");
1674 if (TableKind == Kind::Weak) {
1675 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1679 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1680 BindType = ImmValue;
1683 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1684 << "BindType=" << (int)BindType << "\n");
1686 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1687 Addend = readSLEB128();
1688 if (TableKind == Kind::Lazy)
1692 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1693 << "Addend=" << Addend << "\n");
1695 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1696 SegmentIndex = ImmValue;
1697 SegmentOffset = readULEB128();
1700 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1701 << "SegmentIndex=" << SegmentIndex << ", "
1702 << format("SegmentOffset=0x%06X", SegmentOffset)
1705 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1706 SegmentOffset += readULEB128();
1707 DEBUG_WITH_TYPE("mach-o-bind",
1708 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1709 << format("SegmentOffset=0x%06X",
1710 SegmentOffset) << "\n");
1712 case MachO::BIND_OPCODE_DO_BIND:
1713 AdvanceAmount = PointerSize;
1714 RemainingLoopCount = 0;
1715 DEBUG_WITH_TYPE("mach-o-bind",
1716 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1717 << format("SegmentOffset=0x%06X",
1718 SegmentOffset) << "\n");
1720 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1721 AdvanceAmount = readULEB128() + PointerSize;
1722 RemainingLoopCount = 0;
1723 if (TableKind == Kind::Lazy)
1727 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1728 << format("SegmentOffset=0x%06X", SegmentOffset)
1729 << ", AdvanceAmount=" << AdvanceAmount
1730 << ", RemainingLoopCount=" << RemainingLoopCount
1733 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1734 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1735 RemainingLoopCount = 0;
1736 if (TableKind == Kind::Lazy)
1738 DEBUG_WITH_TYPE("mach-o-bind",
1740 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1741 << format("SegmentOffset=0x%06X",
1742 SegmentOffset) << "\n");
1744 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1745 RemainingLoopCount = readULEB128() - 1;
1746 AdvanceAmount = readULEB128() + PointerSize;
1747 if (TableKind == Kind::Lazy)
1751 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1752 << format("SegmentOffset=0x%06X", SegmentOffset)
1753 << ", AdvanceAmount=" << AdvanceAmount
1754 << ", RemainingLoopCount=" << RemainingLoopCount
1763 uint64_t MachOBindEntry::readULEB128() {
1765 uint64_t Result = decodeULEB128(Ptr, &Count);
1767 if (Ptr > Opcodes.end()) {
1768 Ptr = Opcodes.end();
1774 int64_t MachOBindEntry::readSLEB128() {
1776 int64_t Result = decodeSLEB128(Ptr, &Count);
1778 if (Ptr > Opcodes.end()) {
1779 Ptr = Opcodes.end();
1786 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1788 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1790 StringRef MachOBindEntry::typeName() const {
1792 case MachO::BIND_TYPE_POINTER:
1794 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1795 return "text abs32";
1796 case MachO::BIND_TYPE_TEXT_PCREL32:
1797 return "text rel32";
1802 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1804 int64_t MachOBindEntry::addend() const { return Addend; }
1806 uint32_t MachOBindEntry::flags() const { return Flags; }
1808 int MachOBindEntry::ordinal() const { return Ordinal; }
1810 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1811 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1812 return (Ptr == Other.Ptr) &&
1813 (RemainingLoopCount == Other.RemainingLoopCount) &&
1814 (Done == Other.Done);
1817 iterator_range<bind_iterator>
1818 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1819 MachOBindEntry::Kind BKind) {
1820 MachOBindEntry Start(Opcodes, is64, BKind);
1821 Start.moveToFirst();
1823 MachOBindEntry Finish(Opcodes, is64, BKind);
1826 return iterator_range<bind_iterator>(bind_iterator(Start),
1827 bind_iterator(Finish));
1830 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1831 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1832 MachOBindEntry::Kind::Regular);
1835 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1836 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1837 MachOBindEntry::Kind::Lazy);
1840 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1841 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1842 MachOBindEntry::Kind::Weak);
1845 MachOObjectFile::load_command_iterator
1846 MachOObjectFile::begin_load_commands() const {
1847 return LoadCommands.begin();
1850 MachOObjectFile::load_command_iterator
1851 MachOObjectFile::end_load_commands() const {
1852 return LoadCommands.end();
1855 iterator_range<MachOObjectFile::load_command_iterator>
1856 MachOObjectFile::load_commands() const {
1857 return iterator_range<load_command_iterator>(begin_load_commands(),
1858 end_load_commands());
1862 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1863 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1864 return parseSegmentOrSectionName(Raw.data());
1868 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1869 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1870 const section_base *Base =
1871 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1872 return makeArrayRef(Base->sectname);
1876 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1877 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1878 const section_base *Base =
1879 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1880 return makeArrayRef(Base->segname);
1884 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1886 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1888 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1891 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1892 const MachO::any_relocation_info &RE) const {
1893 if (isLittleEndian())
1894 return RE.r_word1 & 0xffffff;
1895 return RE.r_word1 >> 8;
1898 bool MachOObjectFile::getPlainRelocationExternal(
1899 const MachO::any_relocation_info &RE) const {
1900 if (isLittleEndian())
1901 return (RE.r_word1 >> 27) & 1;
1902 return (RE.r_word1 >> 4) & 1;
1905 bool MachOObjectFile::getScatteredRelocationScattered(
1906 const MachO::any_relocation_info &RE) const {
1907 return RE.r_word0 >> 31;
1910 uint32_t MachOObjectFile::getScatteredRelocationValue(
1911 const MachO::any_relocation_info &RE) const {
1915 uint32_t MachOObjectFile::getScatteredRelocationType(
1916 const MachO::any_relocation_info &RE) const {
1917 return (RE.r_word0 >> 24) & 0xf;
1920 unsigned MachOObjectFile::getAnyRelocationAddress(
1921 const MachO::any_relocation_info &RE) const {
1922 if (isRelocationScattered(RE))
1923 return getScatteredRelocationAddress(RE);
1924 return getPlainRelocationAddress(RE);
1927 unsigned MachOObjectFile::getAnyRelocationPCRel(
1928 const MachO::any_relocation_info &RE) const {
1929 if (isRelocationScattered(RE))
1930 return getScatteredRelocationPCRel(this, RE);
1931 return getPlainRelocationPCRel(this, RE);
1934 unsigned MachOObjectFile::getAnyRelocationLength(
1935 const MachO::any_relocation_info &RE) const {
1936 if (isRelocationScattered(RE))
1937 return getScatteredRelocationLength(RE);
1938 return getPlainRelocationLength(this, RE);
1942 MachOObjectFile::getAnyRelocationType(
1943 const MachO::any_relocation_info &RE) const {
1944 if (isRelocationScattered(RE))
1945 return getScatteredRelocationType(RE);
1946 return getPlainRelocationType(this, RE);
1950 MachOObjectFile::getAnyRelocationSection(
1951 const MachO::any_relocation_info &RE) const {
1952 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1953 return *section_end();
1954 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1955 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1956 return *section_end();
1958 DRI.d.a = SecNum - 1;
1959 return SectionRef(DRI, this);
1962 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1963 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1964 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1967 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1968 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1969 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1972 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1973 unsigned Index) const {
1974 const char *Sec = getSectionPtr(this, L, Index);
1975 return getStruct<MachO::section>(this, Sec);
1978 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1979 unsigned Index) const {
1980 const char *Sec = getSectionPtr(this, L, Index);
1981 return getStruct<MachO::section_64>(this, Sec);
1985 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1986 const char *P = reinterpret_cast<const char *>(DRI.p);
1987 return getStruct<MachO::nlist>(this, P);
1991 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1992 const char *P = reinterpret_cast<const char *>(DRI.p);
1993 return getStruct<MachO::nlist_64>(this, P);
1996 MachO::linkedit_data_command
1997 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1998 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2001 MachO::segment_command
2002 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2003 return getStruct<MachO::segment_command>(this, L.Ptr);
2006 MachO::segment_command_64
2007 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2008 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2011 MachO::linker_option_command
2012 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2013 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2016 MachO::version_min_command
2017 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2018 return getStruct<MachO::version_min_command>(this, L.Ptr);
2021 MachO::dylib_command
2022 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2023 return getStruct<MachO::dylib_command>(this, L.Ptr);
2026 MachO::dyld_info_command
2027 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2028 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2031 MachO::dylinker_command
2032 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2033 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2037 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2038 return getStruct<MachO::uuid_command>(this, L.Ptr);
2041 MachO::rpath_command
2042 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2043 return getStruct<MachO::rpath_command>(this, L.Ptr);
2046 MachO::source_version_command
2047 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2048 return getStruct<MachO::source_version_command>(this, L.Ptr);
2051 MachO::entry_point_command
2052 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2056 MachO::encryption_info_command
2057 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2061 MachO::encryption_info_command_64
2062 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2063 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2066 MachO::sub_framework_command
2067 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2071 MachO::sub_umbrella_command
2072 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2073 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2076 MachO::sub_library_command
2077 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2078 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2081 MachO::sub_client_command
2082 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2083 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2086 MachO::routines_command
2087 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2088 return getStruct<MachO::routines_command>(this, L.Ptr);
2091 MachO::routines_command_64
2092 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2093 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2096 MachO::thread_command
2097 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2098 return getStruct<MachO::thread_command>(this, L.Ptr);
2101 MachO::any_relocation_info
2102 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2107 MachO::section_64 Sect = getSection64(Sec);
2108 Offset = Sect.reloff;
2110 MachO::section Sect = getSection(Sec);
2111 Offset = Sect.reloff;
2114 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2115 getPtr(this, Offset)) + Rel.d.b;
2116 return getStruct<MachO::any_relocation_info>(
2117 this, reinterpret_cast<const char *>(P));
2120 MachO::data_in_code_entry
2121 MachOObjectFile::getDice(DataRefImpl Rel) const {
2122 const char *P = reinterpret_cast<const char *>(Rel.p);
2123 return getStruct<MachO::data_in_code_entry>(this, P);
2126 const MachO::mach_header &MachOObjectFile::getHeader() const {
2130 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2135 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2136 const MachO::dysymtab_command &DLC,
2137 unsigned Index) const {
2138 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2139 return getStruct<uint32_t>(this, getPtr(this, Offset));
2142 MachO::data_in_code_entry
2143 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2144 unsigned Index) const {
2145 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2146 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2149 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2151 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2153 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2154 MachO::symtab_command Cmd;
2155 Cmd.cmd = MachO::LC_SYMTAB;
2156 Cmd.cmdsize = sizeof(MachO::symtab_command);
2164 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2165 if (DysymtabLoadCmd)
2166 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2168 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2169 MachO::dysymtab_command Cmd;
2170 Cmd.cmd = MachO::LC_DYSYMTAB;
2171 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2182 Cmd.extrefsymoff = 0;
2183 Cmd.nextrefsyms = 0;
2184 Cmd.indirectsymoff = 0;
2185 Cmd.nindirectsyms = 0;
2193 MachO::linkedit_data_command
2194 MachOObjectFile::getDataInCodeLoadCommand() const {
2195 if (DataInCodeLoadCmd)
2196 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2198 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2199 MachO::linkedit_data_command Cmd;
2200 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2201 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2207 MachO::linkedit_data_command
2208 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2209 if (LinkOptHintsLoadCmd)
2210 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2212 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2214 MachO::linkedit_data_command Cmd;
2215 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2216 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2222 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2223 if (!DyldInfoLoadCmd)
2224 return ArrayRef<uint8_t>();
2226 MachO::dyld_info_command DyldInfo
2227 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2228 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2229 getPtr(this, DyldInfo.rebase_off));
2230 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2233 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2234 if (!DyldInfoLoadCmd)
2235 return ArrayRef<uint8_t>();
2237 MachO::dyld_info_command DyldInfo
2238 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2239 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2240 getPtr(this, DyldInfo.bind_off));
2241 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2244 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2245 if (!DyldInfoLoadCmd)
2246 return ArrayRef<uint8_t>();
2248 MachO::dyld_info_command DyldInfo
2249 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2250 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2251 getPtr(this, DyldInfo.weak_bind_off));
2252 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2255 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2256 if (!DyldInfoLoadCmd)
2257 return ArrayRef<uint8_t>();
2259 MachO::dyld_info_command DyldInfo
2260 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2261 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2262 getPtr(this, DyldInfo.lazy_bind_off));
2263 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2266 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2267 if (!DyldInfoLoadCmd)
2268 return ArrayRef<uint8_t>();
2270 MachO::dyld_info_command DyldInfo
2271 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2272 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2273 getPtr(this, DyldInfo.export_off));
2274 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2277 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2279 return ArrayRef<uint8_t>();
2280 // Returning a pointer is fine as uuid doesn't need endian swapping.
2281 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2282 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2285 StringRef MachOObjectFile::getStringTableData() const {
2286 MachO::symtab_command S = getSymtabLoadCommand();
2287 return getData().substr(S.stroff, S.strsize);
2290 bool MachOObjectFile::is64Bit() const {
2291 return getType() == getMachOType(false, true) ||
2292 getType() == getMachOType(true, true);
2295 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2296 SmallVectorImpl<uint64_t> &Out) const {
2297 DataExtractor extractor(ObjectFile::getData(), true, 0);
2299 uint32_t offset = Index;
2301 while (uint64_t delta = extractor.getULEB128(&offset)) {
2303 Out.push_back(data);
2307 bool MachOObjectFile::isRelocatableObject() const {
2308 return getHeader().filetype == MachO::MH_OBJECT;
2311 ErrorOr<std::unique_ptr<MachOObjectFile>>
2312 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2313 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2315 std::unique_ptr<MachOObjectFile> Ret;
2316 if (Magic == "\xFE\xED\xFA\xCE")
2317 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2318 else if (Magic == "\xCE\xFA\xED\xFE")
2319 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2320 else if (Magic == "\xFE\xED\xFA\xCF")
2321 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2322 else if (Magic == "\xCF\xFA\xED\xFE")
2323 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2325 return object_error::parse_failed;
2329 return std::move(Ret);