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;
42 static T getStruct(const MachOObjectFile *O, const char *P) {
43 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
50 MachO::swapStruct(Cmd);
54 template <typename SegmentCmd>
55 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
61 "Number of sections too large for size of load command.");
66 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
76 static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
88 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
90 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
92 bool Is64 = O->is64Bit();
93 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
99 return reinterpret_cast<const char*>(SectionAddr);
102 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
106 static MachO::nlist_base
107 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
108 const char *P = reinterpret_cast<const char *>(DRI.p);
109 return getStruct<MachO::nlist_base>(O, P);
112 static StringRef parseSegmentOrSectionName(const char *P) {
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
120 // Helper to advance a section or symbol iterator multiple increments at a time.
122 static void advance(T &it, size_t Val) {
127 static unsigned getCPUType(const MachOObjectFile *O) {
128 return O->getHeader().cputype;
132 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
137 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138 return RE.r_word0 & 0xffffff;
141 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
142 const MachO::any_relocation_info &RE) {
143 if (O->isLittleEndian())
144 return (RE.r_word1 >> 24) & 1;
145 return (RE.r_word1 >> 7) & 1;
149 getScatteredRelocationPCRel(const MachOObjectFile *O,
150 const MachO::any_relocation_info &RE) {
151 return (RE.r_word0 >> 30) & 1;
154 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
155 const MachO::any_relocation_info &RE) {
156 if (O->isLittleEndian())
157 return (RE.r_word1 >> 25) & 3;
158 return (RE.r_word1 >> 5) & 3;
162 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
163 return (RE.r_word0 >> 28) & 3;
166 static unsigned getPlainRelocationType(const MachOObjectFile *O,
167 const MachO::any_relocation_info &RE) {
168 if (O->isLittleEndian())
169 return RE.r_word1 >> 28;
170 return RE.r_word1 & 0xf;
173 static uint32_t getSectionFlags(const MachOObjectFile *O,
176 MachO::section_64 Sect = O->getSection64(Sec);
179 MachO::section Sect = O->getSection(Sec);
183 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
184 bool Is64bits, std::error_code &EC)
185 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
186 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
187 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
188 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
189 HasPageZeroSegment(false) {
190 uint32_t LoadCommandCount = this->getHeader().ncmds;
191 if (LoadCommandCount == 0)
194 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
195 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
197 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
198 for (unsigned I = 0; ; ++I) {
199 if (Load.C.cmd == MachO::LC_SYMTAB) {
200 // Multiple symbol tables
202 EC = object_error::parse_failed;
205 SymtabLoadCmd = Load.Ptr;
206 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
207 // Multiple dynamic symbol tables
208 if (DysymtabLoadCmd) {
209 EC = object_error::parse_failed;
212 DysymtabLoadCmd = Load.Ptr;
213 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
214 // Multiple data in code tables
215 if (DataInCodeLoadCmd) {
216 EC = object_error::parse_failed;
219 DataInCodeLoadCmd = Load.Ptr;
220 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
221 // Multiple linker optimization hint tables
222 if (LinkOptHintsLoadCmd) {
223 EC = object_error::parse_failed;
226 LinkOptHintsLoadCmd = Load.Ptr;
227 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
228 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
229 // Multiple dyldinfo load commands
230 if (DyldInfoLoadCmd) {
231 EC = object_error::parse_failed;
234 DyldInfoLoadCmd = Load.Ptr;
235 } else if (Load.C.cmd == MachO::LC_UUID) {
236 // Multiple UUID load commands
238 EC = object_error::parse_failed;
241 UuidLoadCmd = Load.Ptr;
242 } else if (Load.C.cmd == SegmentLoadType) {
243 const unsigned SegmentLoadSize = this->is64Bit()
244 ? sizeof(MachO::segment_command_64)
245 : sizeof(MachO::segment_command);
246 if (Load.C.cmdsize < SegmentLoadSize)
247 report_fatal_error("Segment load command size is too small.");
249 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
250 for (unsigned J = 0; J < NumSections; ++J) {
251 const char *Sec = getSectionPtr(this, Load, J);
252 Sections.push_back(Sec);
254 if (isPageZeroSegment(this, Load))
255 HasPageZeroSegment = true;
256 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
257 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
258 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
259 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
260 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
261 Libraries.push_back(Load.Ptr);
264 if (I == LoadCommandCount - 1)
267 Load = getNextLoadCommandInfo(Load);
271 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
272 unsigned SymbolTableEntrySize = is64Bit() ?
273 sizeof(MachO::nlist_64) :
274 sizeof(MachO::nlist);
275 Symb.p += SymbolTableEntrySize;
278 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
279 StringRef &Res) const {
280 StringRef StringTable = getStringTableData();
281 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
282 const char *Start = &StringTable.data()[Entry.n_strx];
283 if (Start < getData().begin() || Start >= getData().end())
285 "Symbol name entry points before beginning or past end of file.");
286 Res = StringRef(Start);
287 return object_error::success;
290 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
291 DataRefImpl DRI = Sec.getRawDataRefImpl();
292 uint32_t Flags = getSectionFlags(this, DRI);
293 return Flags & MachO::SECTION_TYPE;
296 // getIndirectName() returns the name of the alias'ed symbol who's string table
297 // index is in the n_value field.
298 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
299 StringRef &Res) const {
300 StringRef StringTable = getStringTableData();
303 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
304 NValue = Entry.n_value;
305 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
306 return object_error::parse_failed;
308 MachO::nlist Entry = getSymbolTableEntry(Symb);
309 NValue = Entry.n_value;
310 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
311 return object_error::parse_failed;
313 if (NValue >= StringTable.size())
314 return object_error::parse_failed;
315 const char *Start = &StringTable.data()[NValue];
316 Res = StringRef(Start);
317 return object_error::success;
320 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
321 uint64_t &Res) const {
323 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
324 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
326 Res = UnknownAddressOrSize;
330 MachO::nlist Entry = getSymbolTableEntry(Symb);
331 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
333 Res = UnknownAddressOrSize;
337 return object_error::success;
340 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
341 uint32_t flags = getSymbolFlags(DRI);
342 if (flags & SymbolRef::SF_Common) {
343 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
344 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
349 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
351 getSymbolAddress(DRI, Value);
352 uint32_t flags = getSymbolFlags(DRI);
353 if (flags & SymbolRef::SF_Common)
355 return UnknownAddressOrSize;
358 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
359 SymbolRef::Type &Res) const {
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 uint8_t n_type = Entry.n_type;
363 Res = SymbolRef::ST_Other;
365 // If this is a STAB debugging symbol, we can do nothing more.
366 if (n_type & MachO::N_STAB) {
367 Res = SymbolRef::ST_Debug;
368 return object_error::success;
371 switch (n_type & MachO::N_TYPE) {
373 Res = SymbolRef::ST_Unknown;
376 Res = SymbolRef::ST_Function;
379 return object_error::success;
382 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
383 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
385 uint8_t MachOType = Entry.n_type;
386 uint16_t MachOFlags = Entry.n_desc;
388 uint32_t Result = SymbolRef::SF_None;
390 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
391 Result |= SymbolRef::SF_Undefined;
393 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
394 Result |= SymbolRef::SF_Indirect;
396 if (MachOType & MachO::N_STAB)
397 Result |= SymbolRef::SF_FormatSpecific;
399 if (MachOType & MachO::N_EXT) {
400 Result |= SymbolRef::SF_Global;
401 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
403 getSymbolAddress(DRI, Value);
404 if (Value && Value != UnknownAddressOrSize)
405 Result |= SymbolRef::SF_Common;
408 if (!(MachOType & MachO::N_PEXT))
409 Result |= SymbolRef::SF_Exported;
412 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
413 Result |= SymbolRef::SF_Weak;
415 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
416 Result |= SymbolRef::SF_Thumb;
418 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
419 Result |= SymbolRef::SF_Absolute;
424 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
425 section_iterator &Res) const {
426 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
427 uint8_t index = Entry.n_sect;
434 if (DRI.d.a >= Sections.size())
435 report_fatal_error("getSymbolSection: Invalid section index.");
436 Res = section_iterator(SectionRef(DRI, this));
439 return object_error::success;
442 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
446 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
447 StringRef &Result) const {
448 ArrayRef<char> Raw = getSectionRawName(Sec);
449 Result = parseSegmentOrSectionName(Raw.data());
450 return object_error::success;
453 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
455 return getSection64(Sec).addr;
456 return getSection(Sec).addr;
459 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
461 return getSection64(Sec).size;
462 return getSection(Sec).size;
465 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
466 StringRef &Res) const {
471 MachO::section_64 Sect = getSection64(Sec);
472 Offset = Sect.offset;
475 MachO::section Sect = getSection(Sec);
476 Offset = Sect.offset;
480 Res = this->getData().substr(Offset, Size);
481 return object_error::success;
484 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
487 MachO::section_64 Sect = getSection64(Sec);
490 MachO::section Sect = getSection(Sec);
494 return uint64_t(1) << Align;
497 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
498 uint32_t Flags = getSectionFlags(this, Sec);
499 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
502 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
503 uint32_t Flags = getSectionFlags(this, Sec);
504 unsigned SectionType = Flags & MachO::SECTION_TYPE;
505 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
506 !(SectionType == MachO::S_ZEROFILL ||
507 SectionType == MachO::S_GB_ZEROFILL);
510 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
511 uint32_t Flags = getSectionFlags(this, Sec);
512 unsigned SectionType = Flags & MachO::SECTION_TYPE;
513 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
514 (SectionType == MachO::S_ZEROFILL ||
515 SectionType == MachO::S_GB_ZEROFILL);
518 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
519 // FIXME: Unimplemented.
523 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
524 DataRefImpl Symb) const {
526 this->getSymbolType(Symb, ST);
527 if (ST == SymbolRef::ST_Unknown)
530 uint64_t SectBegin = getSectionAddress(Sec);
531 uint64_t SectEnd = getSectionSize(Sec);
532 SectEnd += SectBegin;
535 getSymbolAddress(Symb, SymAddr);
536 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
539 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
543 return relocation_iterator(RelocationRef(Ret, this));
547 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
550 MachO::section_64 Sect = getSection64(Sec);
553 MachO::section Sect = getSection(Sec);
560 return relocation_iterator(RelocationRef(Ret, this));
563 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
567 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
568 uint64_t &Res) const {
570 getRelocationOffset(Rel, Offset);
574 uint64_t SecAddress = getSectionAddress(Sec);
575 Res = SecAddress + Offset;
576 return object_error::success;
579 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
580 uint64_t &Res) const {
581 assert(getHeader().filetype == MachO::MH_OBJECT &&
582 "Only implemented for MH_OBJECT");
583 MachO::any_relocation_info RE = getRelocation(Rel);
584 Res = getAnyRelocationAddress(RE);
585 return object_error::success;
589 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
590 MachO::any_relocation_info RE = getRelocation(Rel);
591 if (isRelocationScattered(RE))
594 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
595 bool isExtern = getPlainRelocationExternal(RE);
599 MachO::symtab_command S = getSymtabLoadCommand();
600 unsigned SymbolTableEntrySize = is64Bit() ?
601 sizeof(MachO::nlist_64) :
602 sizeof(MachO::nlist);
603 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
605 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
606 return symbol_iterator(SymbolRef(Sym, this));
610 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
611 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
614 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
615 uint64_t &Res) const {
616 MachO::any_relocation_info RE = getRelocation(Rel);
617 Res = getAnyRelocationType(RE);
618 return object_error::success;
622 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
623 SmallVectorImpl<char> &Result) const {
626 getRelocationType(Rel, RType);
628 unsigned Arch = this->getArch();
632 static const char *const Table[] = {
633 "GENERIC_RELOC_VANILLA",
634 "GENERIC_RELOC_PAIR",
635 "GENERIC_RELOC_SECTDIFF",
636 "GENERIC_RELOC_PB_LA_PTR",
637 "GENERIC_RELOC_LOCAL_SECTDIFF",
638 "GENERIC_RELOC_TLV" };
646 case Triple::x86_64: {
647 static const char *const Table[] = {
648 "X86_64_RELOC_UNSIGNED",
649 "X86_64_RELOC_SIGNED",
650 "X86_64_RELOC_BRANCH",
651 "X86_64_RELOC_GOT_LOAD",
653 "X86_64_RELOC_SUBTRACTOR",
654 "X86_64_RELOC_SIGNED_1",
655 "X86_64_RELOC_SIGNED_2",
656 "X86_64_RELOC_SIGNED_4",
657 "X86_64_RELOC_TLV" };
666 static const char *const Table[] = {
669 "ARM_RELOC_SECTDIFF",
670 "ARM_RELOC_LOCAL_SECTDIFF",
671 "ARM_RELOC_PB_LA_PTR",
673 "ARM_THUMB_RELOC_BR22",
674 "ARM_THUMB_32BIT_BRANCH",
676 "ARM_RELOC_HALF_SECTDIFF" };
684 case Triple::aarch64: {
685 static const char *const Table[] = {
686 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
687 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
688 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
689 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
690 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
694 if (RType >= array_lengthof(Table))
701 static const char *const Table[] = {
710 "PPC_RELOC_SECTDIFF",
711 "PPC_RELOC_PB_LA_PTR",
712 "PPC_RELOC_HI16_SECTDIFF",
713 "PPC_RELOC_LO16_SECTDIFF",
714 "PPC_RELOC_HA16_SECTDIFF",
716 "PPC_RELOC_LO14_SECTDIFF",
717 "PPC_RELOC_LOCAL_SECTDIFF" };
725 case Triple::UnknownArch:
729 Result.append(res.begin(), res.end());
730 return object_error::success;
733 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
734 bool &Result) const {
735 unsigned Arch = getArch();
737 getRelocationType(Rel, Type);
741 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
743 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
744 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
745 } else if (Arch == Triple::x86_64) {
746 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
747 // an X86_64_RELOC_SUBTRACTOR.
748 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
749 DataRefImpl RelPrev = Rel;
752 getRelocationType(RelPrev, PrevType);
753 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
758 return object_error::success;
761 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
762 MachO::any_relocation_info RE = getRelocation(Rel);
763 return getAnyRelocationLength(RE);
767 // guessLibraryShortName() is passed a name of a dynamic library and returns a
768 // guess on what the short name is. Then name is returned as a substring of the
769 // StringRef Name passed in. The name of the dynamic library is recognized as
770 // a framework if it has one of the two following forms:
771 // Foo.framework/Versions/A/Foo
773 // Where A and Foo can be any string. And may contain a trailing suffix
774 // starting with an underbar. If the Name is recognized as a framework then
775 // isFramework is set to true else it is set to false. If the Name has a
776 // suffix then Suffix is set to the substring in Name that contains the suffix
777 // else it is set to a NULL StringRef.
779 // The Name of the dynamic library is recognized as a library name if it has
780 // one of the two following forms:
783 // The library may have a suffix trailing the name Foo of the form:
784 // libFoo_profile.A.dylib
785 // libFoo_profile.dylib
787 // The Name of the dynamic library is also recognized as a library name if it
788 // has the following form:
791 // If the Name of the dynamic library is none of the forms above then a NULL
792 // StringRef is returned.
794 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
797 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
798 size_t a, b, c, d, Idx;
801 Suffix = StringRef();
803 // Pull off the last component and make Foo point to it
805 if (a == Name.npos || a == 0)
807 Foo = Name.slice(a+1, Name.npos);
809 // Look for a suffix starting with a '_'
810 Idx = Foo.rfind('_');
811 if (Idx != Foo.npos && Foo.size() >= 2) {
812 Suffix = Foo.slice(Idx, Foo.npos);
813 Foo = Foo.slice(0, Idx);
816 // First look for the form Foo.framework/Foo
817 b = Name.rfind('/', a);
822 F = Name.slice(Idx, Idx + Foo.size());
823 DotFramework = Name.slice(Idx + Foo.size(),
824 Idx + Foo.size() + sizeof(".framework/")-1);
825 if (F == Foo && DotFramework == ".framework/") {
830 // Next look for the form Foo.framework/Versions/A/Foo
833 c = Name.rfind('/', b);
834 if (c == Name.npos || c == 0)
836 V = Name.slice(c+1, Name.npos);
837 if (!V.startswith("Versions/"))
839 d = Name.rfind('/', c);
844 F = Name.slice(Idx, Idx + Foo.size());
845 DotFramework = Name.slice(Idx + Foo.size(),
846 Idx + Foo.size() + sizeof(".framework/")-1);
847 if (F == Foo && DotFramework == ".framework/") {
853 // pull off the suffix after the "." and make a point to it
855 if (a == Name.npos || a == 0)
857 Dylib = Name.slice(a, Name.npos);
858 if (Dylib != ".dylib")
861 // First pull off the version letter for the form Foo.A.dylib if any.
863 Dot = Name.slice(a-2, a-1);
868 b = Name.rfind('/', a);
873 // ignore any suffix after an underbar like Foo_profile.A.dylib
874 Idx = Name.find('_', b);
875 if (Idx != Name.npos && Idx != b) {
876 Lib = Name.slice(b, Idx);
877 Suffix = Name.slice(Idx, a);
880 Lib = Name.slice(b, a);
881 // There are incorrect library names of the form:
882 // libATS.A_profile.dylib so check for these.
883 if (Lib.size() >= 3) {
884 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
886 Lib = Lib.slice(0, Lib.size()-2);
891 Qtx = Name.slice(a, Name.npos);
894 b = Name.rfind('/', a);
896 Lib = Name.slice(0, a);
898 Lib = Name.slice(b+1, a);
899 // There are library names of the form: QT.A.qtx so check for these.
900 if (Lib.size() >= 3) {
901 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
903 Lib = Lib.slice(0, Lib.size()-2);
908 // getLibraryShortNameByIndex() is used to get the short name of the library
909 // for an undefined symbol in a linked Mach-O binary that was linked with the
910 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
911 // It is passed the index (0 - based) of the library as translated from
912 // GET_LIBRARY_ORDINAL (1 - based).
913 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
914 StringRef &Res) const {
915 if (Index >= Libraries.size())
916 return object_error::parse_failed;
918 // If the cache of LibrariesShortNames is not built up do that first for
919 // all the Libraries.
920 if (LibrariesShortNames.size() == 0) {
921 for (unsigned i = 0; i < Libraries.size(); i++) {
922 MachO::dylib_command D =
923 getStruct<MachO::dylib_command>(this, Libraries[i]);
924 if (D.dylib.name >= D.cmdsize)
925 return object_error::parse_failed;
926 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
927 StringRef Name = StringRef(P);
928 if (D.dylib.name+Name.size() >= D.cmdsize)
929 return object_error::parse_failed;
932 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
933 if (shortName.empty())
934 LibrariesShortNames.push_back(Name);
936 LibrariesShortNames.push_back(shortName);
940 Res = LibrariesShortNames[Index];
941 return object_error::success;
944 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
945 return getSymbolByIndex(0);
948 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
951 return basic_symbol_iterator(SymbolRef(DRI, this));
953 MachO::symtab_command Symtab = getSymtabLoadCommand();
954 unsigned SymbolTableEntrySize = is64Bit() ?
955 sizeof(MachO::nlist_64) :
956 sizeof(MachO::nlist);
957 unsigned Offset = Symtab.symoff +
958 Symtab.nsyms * SymbolTableEntrySize;
959 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
960 return basic_symbol_iterator(SymbolRef(DRI, this));
963 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
966 return basic_symbol_iterator(SymbolRef(DRI, this));
968 MachO::symtab_command Symtab = getSymtabLoadCommand();
969 if (Index >= Symtab.nsyms)
970 report_fatal_error("Requested symbol index is out of range.");
971 unsigned SymbolTableEntrySize =
972 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
973 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
974 DRI.p += Index * SymbolTableEntrySize;
975 return basic_symbol_iterator(SymbolRef(DRI, this));
978 section_iterator MachOObjectFile::section_begin() const {
980 return section_iterator(SectionRef(DRI, this));
983 section_iterator MachOObjectFile::section_end() const {
985 DRI.d.a = Sections.size();
986 return section_iterator(SectionRef(DRI, this));
989 uint8_t MachOObjectFile::getBytesInAddress() const {
990 return is64Bit() ? 8 : 4;
993 StringRef MachOObjectFile::getFileFormatName() const {
994 unsigned CPUType = getCPUType(this);
997 case llvm::MachO::CPU_TYPE_I386:
998 return "Mach-O 32-bit i386";
999 case llvm::MachO::CPU_TYPE_ARM:
1000 return "Mach-O arm";
1001 case llvm::MachO::CPU_TYPE_POWERPC:
1002 return "Mach-O 32-bit ppc";
1004 return "Mach-O 32-bit unknown";
1009 case llvm::MachO::CPU_TYPE_X86_64:
1010 return "Mach-O 64-bit x86-64";
1011 case llvm::MachO::CPU_TYPE_ARM64:
1012 return "Mach-O arm64";
1013 case llvm::MachO::CPU_TYPE_POWERPC64:
1014 return "Mach-O 64-bit ppc64";
1016 return "Mach-O 64-bit unknown";
1020 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1022 case llvm::MachO::CPU_TYPE_I386:
1024 case llvm::MachO::CPU_TYPE_X86_64:
1025 return Triple::x86_64;
1026 case llvm::MachO::CPU_TYPE_ARM:
1028 case llvm::MachO::CPU_TYPE_ARM64:
1029 return Triple::aarch64;
1030 case llvm::MachO::CPU_TYPE_POWERPC:
1032 case llvm::MachO::CPU_TYPE_POWERPC64:
1033 return Triple::ppc64;
1035 return Triple::UnknownArch;
1039 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1040 const char **McpuDefault) {
1042 *McpuDefault = nullptr;
1045 case MachO::CPU_TYPE_I386:
1046 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1047 case MachO::CPU_SUBTYPE_I386_ALL:
1048 return Triple("i386-apple-darwin");
1052 case MachO::CPU_TYPE_X86_64:
1053 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1054 case MachO::CPU_SUBTYPE_X86_64_ALL:
1055 return Triple("x86_64-apple-darwin");
1056 case MachO::CPU_SUBTYPE_X86_64_H:
1057 return Triple("x86_64h-apple-darwin");
1061 case MachO::CPU_TYPE_ARM:
1062 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1063 case MachO::CPU_SUBTYPE_ARM_V4T:
1064 return Triple("armv4t-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1066 return Triple("armv5e-apple-darwin");
1067 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1068 return Triple("xscale-apple-darwin");
1069 case MachO::CPU_SUBTYPE_ARM_V6:
1070 return Triple("armv6-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V6M:
1073 *McpuDefault = "cortex-m0";
1074 return Triple("armv6m-apple-darwin");
1075 case MachO::CPU_SUBTYPE_ARM_V7:
1076 return Triple("armv7-apple-darwin");
1077 case MachO::CPU_SUBTYPE_ARM_V7EM:
1079 *McpuDefault = "cortex-m4";
1080 return Triple("armv7em-apple-darwin");
1081 case MachO::CPU_SUBTYPE_ARM_V7K:
1082 return Triple("armv7k-apple-darwin");
1083 case MachO::CPU_SUBTYPE_ARM_V7M:
1085 *McpuDefault = "cortex-m3";
1086 return Triple("armv7m-apple-darwin");
1087 case MachO::CPU_SUBTYPE_ARM_V7S:
1088 return Triple("armv7s-apple-darwin");
1092 case MachO::CPU_TYPE_ARM64:
1093 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1094 case MachO::CPU_SUBTYPE_ARM64_ALL:
1095 return Triple("arm64-apple-darwin");
1099 case MachO::CPU_TYPE_POWERPC:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1102 return Triple("ppc-apple-darwin");
1106 case MachO::CPU_TYPE_POWERPC64:
1107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1108 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1109 return Triple("ppc64-apple-darwin");
1118 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1119 const char **McpuDefault) {
1121 *McpuDefault = nullptr;
1124 case MachO::CPU_TYPE_ARM:
1125 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1126 case MachO::CPU_SUBTYPE_ARM_V4T:
1127 return Triple("thumbv4t-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1129 return Triple("thumbv5e-apple-darwin");
1130 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1131 return Triple("xscale-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V6:
1133 return Triple("thumbv6-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V6M:
1136 *McpuDefault = "cortex-m0";
1137 return Triple("thumbv6m-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7:
1139 return Triple("thumbv7-apple-darwin");
1140 case MachO::CPU_SUBTYPE_ARM_V7EM:
1142 *McpuDefault = "cortex-m4";
1143 return Triple("thumbv7em-apple-darwin");
1144 case MachO::CPU_SUBTYPE_ARM_V7K:
1145 return Triple("thumbv7k-apple-darwin");
1146 case MachO::CPU_SUBTYPE_ARM_V7M:
1148 *McpuDefault = "cortex-m3";
1149 return Triple("thumbv7m-apple-darwin");
1150 case MachO::CPU_SUBTYPE_ARM_V7S:
1151 return Triple("thumbv7s-apple-darwin");
1160 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1161 const char **McpuDefault,
1162 Triple *ThumbTriple) {
1163 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1164 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1169 Triple MachOObjectFile::getHostArch() {
1170 return Triple(sys::getDefaultTargetTriple());
1173 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1174 return StringSwitch<bool>(ArchFlag)
1176 .Case("x86_64", true)
1177 .Case("x86_64h", true)
1178 .Case("armv4t", true)
1180 .Case("armv5e", true)
1181 .Case("armv6", true)
1182 .Case("armv6m", true)
1183 .Case("armv7em", true)
1184 .Case("armv7k", true)
1185 .Case("armv7m", true)
1186 .Case("armv7s", true)
1187 .Case("arm64", true)
1189 .Case("ppc64", true)
1193 unsigned MachOObjectFile::getArch() const {
1194 return getArch(getCPUType(this));
1197 Triple MachOObjectFile::getArch(const char **McpuDefault,
1198 Triple *ThumbTriple) const {
1201 MachO::mach_header_64 H_64;
1202 H_64 = getHeader64();
1203 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1204 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1207 MachO::mach_header H;
1209 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1210 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1216 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1219 return section_rel_begin(DRI);
1222 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1225 return section_rel_end(DRI);
1228 dice_iterator MachOObjectFile::begin_dices() const {
1230 if (!DataInCodeLoadCmd)
1231 return dice_iterator(DiceRef(DRI, this));
1233 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1234 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1235 return dice_iterator(DiceRef(DRI, this));
1238 dice_iterator MachOObjectFile::end_dices() const {
1240 if (!DataInCodeLoadCmd)
1241 return dice_iterator(DiceRef(DRI, this));
1243 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1244 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1245 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1246 return dice_iterator(DiceRef(DRI, this));
1249 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1250 : Trie(T), Malformed(false), Done(false) { }
1252 void ExportEntry::moveToFirst() {
1254 pushDownUntilBottom();
1257 void ExportEntry::moveToEnd() {
1262 bool ExportEntry::operator==(const ExportEntry &Other) const {
1263 // Common case, one at end, other iterating from begin.
1264 if (Done || Other.Done)
1265 return (Done == Other.Done);
1266 // Not equal if different stack sizes.
1267 if (Stack.size() != Other.Stack.size())
1269 // Not equal if different cumulative strings.
1270 if (!CumulativeString.equals(Other.CumulativeString))
1272 // Equal if all nodes in both stacks match.
1273 for (unsigned i=0; i < Stack.size(); ++i) {
1274 if (Stack[i].Start != Other.Stack[i].Start)
1280 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1282 uint64_t Result = decodeULEB128(Ptr, &Count);
1284 if (Ptr > Trie.end()) {
1291 StringRef ExportEntry::name() const {
1292 return CumulativeString;
1295 uint64_t ExportEntry::flags() const {
1296 return Stack.back().Flags;
1299 uint64_t ExportEntry::address() const {
1300 return Stack.back().Address;
1303 uint64_t ExportEntry::other() const {
1304 return Stack.back().Other;
1307 StringRef ExportEntry::otherName() const {
1308 const char* ImportName = Stack.back().ImportName;
1310 return StringRef(ImportName);
1314 uint32_t ExportEntry::nodeOffset() const {
1315 return Stack.back().Start - Trie.begin();
1318 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1319 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1320 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1321 ParentStringLength(0), IsExportNode(false) {
1324 void ExportEntry::pushNode(uint64_t offset) {
1325 const uint8_t *Ptr = Trie.begin() + offset;
1326 NodeState State(Ptr);
1327 uint64_t ExportInfoSize = readULEB128(State.Current);
1328 State.IsExportNode = (ExportInfoSize != 0);
1329 const uint8_t* Children = State.Current + ExportInfoSize;
1330 if (State.IsExportNode) {
1331 State.Flags = readULEB128(State.Current);
1332 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1334 State.Other = readULEB128(State.Current); // dylib ordinal
1335 State.ImportName = reinterpret_cast<const char*>(State.Current);
1337 State.Address = readULEB128(State.Current);
1338 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1339 State.Other = readULEB128(State.Current);
1342 State.ChildCount = *Children;
1343 State.Current = Children + 1;
1344 State.NextChildIndex = 0;
1345 State.ParentStringLength = CumulativeString.size();
1346 Stack.push_back(State);
1349 void ExportEntry::pushDownUntilBottom() {
1350 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1351 NodeState &Top = Stack.back();
1352 CumulativeString.resize(Top.ParentStringLength);
1353 for (;*Top.Current != 0; Top.Current++) {
1354 char C = *Top.Current;
1355 CumulativeString.push_back(C);
1358 uint64_t childNodeIndex = readULEB128(Top.Current);
1359 Top.NextChildIndex += 1;
1360 pushNode(childNodeIndex);
1362 if (!Stack.back().IsExportNode) {
1368 // We have a trie data structure and need a way to walk it that is compatible
1369 // with the C++ iterator model. The solution is a non-recursive depth first
1370 // traversal where the iterator contains a stack of parent nodes along with a
1371 // string that is the accumulation of all edge strings along the parent chain
1374 // There is one "export" node for each exported symbol. But because some
1375 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1376 // node may have child nodes too.
1378 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1379 // child until hitting a node with no children (which is an export node or
1380 // else the trie is malformed). On the way down, each node is pushed on the
1381 // stack ivar. If there is no more ways down, it pops up one and tries to go
1382 // down a sibling path until a childless node is reached.
1383 void ExportEntry::moveNext() {
1384 if (Stack.empty() || !Stack.back().IsExportNode) {
1391 while (!Stack.empty()) {
1392 NodeState &Top = Stack.back();
1393 if (Top.NextChildIndex < Top.ChildCount) {
1394 pushDownUntilBottom();
1395 // Now at the next export node.
1398 if (Top.IsExportNode) {
1399 // This node has no children but is itself an export node.
1400 CumulativeString.resize(Top.ParentStringLength);
1409 iterator_range<export_iterator>
1410 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1411 ExportEntry Start(Trie);
1412 if (Trie.size() == 0)
1415 Start.moveToFirst();
1417 ExportEntry Finish(Trie);
1420 return iterator_range<export_iterator>(export_iterator(Start),
1421 export_iterator(Finish));
1424 iterator_range<export_iterator> MachOObjectFile::exports() const {
1425 return exports(getDyldInfoExportsTrie());
1429 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1430 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1431 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1432 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1434 void MachORebaseEntry::moveToFirst() {
1435 Ptr = Opcodes.begin();
1439 void MachORebaseEntry::moveToEnd() {
1440 Ptr = Opcodes.end();
1441 RemainingLoopCount = 0;
1445 void MachORebaseEntry::moveNext() {
1446 // If in the middle of some loop, move to next rebasing in loop.
1447 SegmentOffset += AdvanceAmount;
1448 if (RemainingLoopCount) {
1449 --RemainingLoopCount;
1452 if (Ptr == Opcodes.end()) {
1457 while (More && !Malformed) {
1458 // Parse next opcode and set up next loop.
1459 uint8_t Byte = *Ptr++;
1460 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1461 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1463 case MachO::REBASE_OPCODE_DONE:
1467 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1469 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1470 RebaseType = ImmValue;
1473 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1474 << "RebaseType=" << (int) RebaseType << "\n");
1476 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1477 SegmentIndex = ImmValue;
1478 SegmentOffset = readULEB128();
1481 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1482 << "SegmentIndex=" << SegmentIndex << ", "
1483 << format("SegmentOffset=0x%06X", SegmentOffset)
1486 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1487 SegmentOffset += readULEB128();
1488 DEBUG_WITH_TYPE("mach-o-rebase",
1489 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1490 << format("SegmentOffset=0x%06X",
1491 SegmentOffset) << "\n");
1493 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1494 SegmentOffset += ImmValue * PointerSize;
1495 DEBUG_WITH_TYPE("mach-o-rebase",
1496 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1497 << format("SegmentOffset=0x%06X",
1498 SegmentOffset) << "\n");
1500 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1501 AdvanceAmount = PointerSize;
1502 RemainingLoopCount = ImmValue - 1;
1505 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1506 << format("SegmentOffset=0x%06X", SegmentOffset)
1507 << ", AdvanceAmount=" << AdvanceAmount
1508 << ", RemainingLoopCount=" << RemainingLoopCount
1511 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1512 AdvanceAmount = PointerSize;
1513 RemainingLoopCount = readULEB128() - 1;
1516 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1517 << format("SegmentOffset=0x%06X", SegmentOffset)
1518 << ", AdvanceAmount=" << AdvanceAmount
1519 << ", RemainingLoopCount=" << RemainingLoopCount
1522 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1523 AdvanceAmount = readULEB128() + PointerSize;
1524 RemainingLoopCount = 0;
1527 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1528 << format("SegmentOffset=0x%06X", SegmentOffset)
1529 << ", AdvanceAmount=" << AdvanceAmount
1530 << ", RemainingLoopCount=" << RemainingLoopCount
1533 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1534 RemainingLoopCount = readULEB128() - 1;
1535 AdvanceAmount = readULEB128() + PointerSize;
1538 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1539 << format("SegmentOffset=0x%06X", SegmentOffset)
1540 << ", AdvanceAmount=" << AdvanceAmount
1541 << ", RemainingLoopCount=" << RemainingLoopCount
1550 uint64_t MachORebaseEntry::readULEB128() {
1552 uint64_t Result = decodeULEB128(Ptr, &Count);
1554 if (Ptr > Opcodes.end()) {
1555 Ptr = Opcodes.end();
1561 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1563 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1565 StringRef MachORebaseEntry::typeName() const {
1566 switch (RebaseType) {
1567 case MachO::REBASE_TYPE_POINTER:
1569 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1570 return "text abs32";
1571 case MachO::REBASE_TYPE_TEXT_PCREL32:
1572 return "text rel32";
1577 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1578 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1579 return (Ptr == Other.Ptr) &&
1580 (RemainingLoopCount == Other.RemainingLoopCount) &&
1581 (Done == Other.Done);
1584 iterator_range<rebase_iterator>
1585 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1586 MachORebaseEntry Start(Opcodes, is64);
1587 Start.moveToFirst();
1589 MachORebaseEntry Finish(Opcodes, is64);
1592 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1593 rebase_iterator(Finish));
1596 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1597 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1601 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1603 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1604 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1605 BindType(0), PointerSize(is64Bit ? 8 : 4),
1606 TableKind(BK), Malformed(false), Done(false) {}
1608 void MachOBindEntry::moveToFirst() {
1609 Ptr = Opcodes.begin();
1613 void MachOBindEntry::moveToEnd() {
1614 Ptr = Opcodes.end();
1615 RemainingLoopCount = 0;
1619 void MachOBindEntry::moveNext() {
1620 // If in the middle of some loop, move to next binding in loop.
1621 SegmentOffset += AdvanceAmount;
1622 if (RemainingLoopCount) {
1623 --RemainingLoopCount;
1626 if (Ptr == Opcodes.end()) {
1631 while (More && !Malformed) {
1632 // Parse next opcode and set up next loop.
1633 uint8_t Byte = *Ptr++;
1634 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1635 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1636 int8_t SignExtended;
1637 const uint8_t *SymStart;
1639 case MachO::BIND_OPCODE_DONE:
1640 if (TableKind == Kind::Lazy) {
1641 // Lazying bindings have a DONE opcode between entries. Need to ignore
1642 // it to advance to next entry. But need not if this is last entry.
1643 bool NotLastEntry = false;
1644 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1646 NotLastEntry = true;
1655 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1657 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1661 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1662 << "Ordinal=" << Ordinal << "\n");
1664 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1665 Ordinal = readULEB128();
1668 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1669 << "Ordinal=" << Ordinal << "\n");
1671 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1673 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1674 Ordinal = SignExtended;
1679 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1680 << "Ordinal=" << Ordinal << "\n");
1682 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1688 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1693 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1694 << "SymbolName=" << SymbolName << "\n");
1695 if (TableKind == Kind::Weak) {
1696 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1700 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1701 BindType = ImmValue;
1704 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1705 << "BindType=" << (int)BindType << "\n");
1707 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1708 Addend = readSLEB128();
1709 if (TableKind == Kind::Lazy)
1713 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1714 << "Addend=" << Addend << "\n");
1716 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1717 SegmentIndex = ImmValue;
1718 SegmentOffset = readULEB128();
1721 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1722 << "SegmentIndex=" << SegmentIndex << ", "
1723 << format("SegmentOffset=0x%06X", SegmentOffset)
1726 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1727 SegmentOffset += readULEB128();
1728 DEBUG_WITH_TYPE("mach-o-bind",
1729 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1730 << format("SegmentOffset=0x%06X",
1731 SegmentOffset) << "\n");
1733 case MachO::BIND_OPCODE_DO_BIND:
1734 AdvanceAmount = PointerSize;
1735 RemainingLoopCount = 0;
1736 DEBUG_WITH_TYPE("mach-o-bind",
1737 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1738 << format("SegmentOffset=0x%06X",
1739 SegmentOffset) << "\n");
1741 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1742 AdvanceAmount = readULEB128() + PointerSize;
1743 RemainingLoopCount = 0;
1744 if (TableKind == Kind::Lazy)
1748 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1754 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1755 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1756 RemainingLoopCount = 0;
1757 if (TableKind == Kind::Lazy)
1759 DEBUG_WITH_TYPE("mach-o-bind",
1761 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1765 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1766 RemainingLoopCount = readULEB128() - 1;
1767 AdvanceAmount = readULEB128() + PointerSize;
1768 if (TableKind == Kind::Lazy)
1772 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1773 << format("SegmentOffset=0x%06X", SegmentOffset)
1774 << ", AdvanceAmount=" << AdvanceAmount
1775 << ", RemainingLoopCount=" << RemainingLoopCount
1784 uint64_t MachOBindEntry::readULEB128() {
1786 uint64_t Result = decodeULEB128(Ptr, &Count);
1788 if (Ptr > Opcodes.end()) {
1789 Ptr = Opcodes.end();
1795 int64_t MachOBindEntry::readSLEB128() {
1797 int64_t Result = decodeSLEB128(Ptr, &Count);
1799 if (Ptr > Opcodes.end()) {
1800 Ptr = Opcodes.end();
1807 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1809 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1811 StringRef MachOBindEntry::typeName() const {
1813 case MachO::BIND_TYPE_POINTER:
1815 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1816 return "text abs32";
1817 case MachO::BIND_TYPE_TEXT_PCREL32:
1818 return "text rel32";
1823 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1825 int64_t MachOBindEntry::addend() const { return Addend; }
1827 uint32_t MachOBindEntry::flags() const { return Flags; }
1829 int MachOBindEntry::ordinal() const { return Ordinal; }
1831 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1832 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1833 return (Ptr == Other.Ptr) &&
1834 (RemainingLoopCount == Other.RemainingLoopCount) &&
1835 (Done == Other.Done);
1838 iterator_range<bind_iterator>
1839 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1840 MachOBindEntry::Kind BKind) {
1841 MachOBindEntry Start(Opcodes, is64, BKind);
1842 Start.moveToFirst();
1844 MachOBindEntry Finish(Opcodes, is64, BKind);
1847 return iterator_range<bind_iterator>(bind_iterator(Start),
1848 bind_iterator(Finish));
1851 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1852 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1853 MachOBindEntry::Kind::Regular);
1856 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1857 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1858 MachOBindEntry::Kind::Lazy);
1861 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1862 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1863 MachOBindEntry::Kind::Weak);
1867 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1868 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1869 return parseSegmentOrSectionName(Raw.data());
1873 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1874 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1875 const section_base *Base =
1876 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1877 return makeArrayRef(Base->sectname);
1881 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1882 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1883 const section_base *Base =
1884 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1885 return makeArrayRef(Base->segname);
1889 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1891 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1893 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1896 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1897 const MachO::any_relocation_info &RE) const {
1898 if (isLittleEndian())
1899 return RE.r_word1 & 0xffffff;
1900 return RE.r_word1 >> 8;
1903 bool MachOObjectFile::getPlainRelocationExternal(
1904 const MachO::any_relocation_info &RE) const {
1905 if (isLittleEndian())
1906 return (RE.r_word1 >> 27) & 1;
1907 return (RE.r_word1 >> 4) & 1;
1910 bool MachOObjectFile::getScatteredRelocationScattered(
1911 const MachO::any_relocation_info &RE) const {
1912 return RE.r_word0 >> 31;
1915 uint32_t MachOObjectFile::getScatteredRelocationValue(
1916 const MachO::any_relocation_info &RE) const {
1920 uint32_t MachOObjectFile::getScatteredRelocationType(
1921 const MachO::any_relocation_info &RE) const {
1922 return (RE.r_word0 >> 24) & 0xf;
1925 unsigned MachOObjectFile::getAnyRelocationAddress(
1926 const MachO::any_relocation_info &RE) const {
1927 if (isRelocationScattered(RE))
1928 return getScatteredRelocationAddress(RE);
1929 return getPlainRelocationAddress(RE);
1932 unsigned MachOObjectFile::getAnyRelocationPCRel(
1933 const MachO::any_relocation_info &RE) const {
1934 if (isRelocationScattered(RE))
1935 return getScatteredRelocationPCRel(this, RE);
1936 return getPlainRelocationPCRel(this, RE);
1939 unsigned MachOObjectFile::getAnyRelocationLength(
1940 const MachO::any_relocation_info &RE) const {
1941 if (isRelocationScattered(RE))
1942 return getScatteredRelocationLength(RE);
1943 return getPlainRelocationLength(this, RE);
1947 MachOObjectFile::getAnyRelocationType(
1948 const MachO::any_relocation_info &RE) const {
1949 if (isRelocationScattered(RE))
1950 return getScatteredRelocationType(RE);
1951 return getPlainRelocationType(this, RE);
1955 MachOObjectFile::getAnyRelocationSection(
1956 const MachO::any_relocation_info &RE) const {
1957 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1958 return *section_end();
1959 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1962 return SectionRef(DRI, this);
1965 MachOObjectFile::LoadCommandInfo
1966 MachOObjectFile::getFirstLoadCommandInfo() const {
1967 MachOObjectFile::LoadCommandInfo Load;
1969 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1970 sizeof(MachO::mach_header);
1971 Load.Ptr = getPtr(this, HeaderSize);
1972 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1973 if (Load.C.cmdsize < 8)
1974 report_fatal_error("Load command with size < 8 bytes.");
1978 MachOObjectFile::LoadCommandInfo
1979 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1980 MachOObjectFile::LoadCommandInfo Next;
1981 Next.Ptr = L.Ptr + L.C.cmdsize;
1982 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1983 if (Next.C.cmdsize < 8)
1984 report_fatal_error("Load command with size < 8 bytes.");
1988 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1989 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1990 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1993 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1994 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1995 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1998 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1999 unsigned Index) const {
2000 const char *Sec = getSectionPtr(this, L, Index);
2001 return getStruct<MachO::section>(this, Sec);
2004 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2005 unsigned Index) const {
2006 const char *Sec = getSectionPtr(this, L, Index);
2007 return getStruct<MachO::section_64>(this, Sec);
2011 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2012 const char *P = reinterpret_cast<const char *>(DRI.p);
2013 return getStruct<MachO::nlist>(this, P);
2017 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2018 const char *P = reinterpret_cast<const char *>(DRI.p);
2019 return getStruct<MachO::nlist_64>(this, P);
2022 MachO::linkedit_data_command
2023 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2024 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2027 MachO::segment_command
2028 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2029 return getStruct<MachO::segment_command>(this, L.Ptr);
2032 MachO::segment_command_64
2033 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2034 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2037 MachO::linker_option_command
2038 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2039 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2042 MachO::version_min_command
2043 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2044 return getStruct<MachO::version_min_command>(this, L.Ptr);
2047 MachO::dylib_command
2048 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2049 return getStruct<MachO::dylib_command>(this, L.Ptr);
2052 MachO::dyld_info_command
2053 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2054 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2057 MachO::dylinker_command
2058 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2059 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2063 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2064 return getStruct<MachO::uuid_command>(this, L.Ptr);
2067 MachO::rpath_command
2068 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2069 return getStruct<MachO::rpath_command>(this, L.Ptr);
2072 MachO::source_version_command
2073 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2074 return getStruct<MachO::source_version_command>(this, L.Ptr);
2077 MachO::entry_point_command
2078 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2079 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2082 MachO::encryption_info_command
2083 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2084 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2087 MachO::encryption_info_command_64
2088 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2092 MachO::sub_framework_command
2093 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2097 MachO::sub_umbrella_command
2098 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2099 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2102 MachO::sub_library_command
2103 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2104 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2107 MachO::sub_client_command
2108 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2112 MachO::routines_command
2113 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::routines_command>(this, L.Ptr);
2117 MachO::routines_command_64
2118 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2122 MachO::thread_command
2123 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::thread_command>(this, L.Ptr);
2127 MachO::any_relocation_info
2128 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2133 MachO::section_64 Sect = getSection64(Sec);
2134 Offset = Sect.reloff;
2136 MachO::section Sect = getSection(Sec);
2137 Offset = Sect.reloff;
2140 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2141 getPtr(this, Offset)) + Rel.d.b;
2142 return getStruct<MachO::any_relocation_info>(
2143 this, reinterpret_cast<const char *>(P));
2146 MachO::data_in_code_entry
2147 MachOObjectFile::getDice(DataRefImpl Rel) const {
2148 const char *P = reinterpret_cast<const char *>(Rel.p);
2149 return getStruct<MachO::data_in_code_entry>(this, P);
2152 MachO::mach_header MachOObjectFile::getHeader() const {
2153 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2156 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2157 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2160 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2161 const MachO::dysymtab_command &DLC,
2162 unsigned Index) const {
2163 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2164 return getStruct<uint32_t>(this, getPtr(this, Offset));
2167 MachO::data_in_code_entry
2168 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2169 unsigned Index) const {
2170 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2171 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2174 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2176 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2178 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2179 MachO::symtab_command Cmd;
2180 Cmd.cmd = MachO::LC_SYMTAB;
2181 Cmd.cmdsize = sizeof(MachO::symtab_command);
2189 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2190 if (DysymtabLoadCmd)
2191 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2193 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2194 MachO::dysymtab_command Cmd;
2195 Cmd.cmd = MachO::LC_DYSYMTAB;
2196 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2207 Cmd.extrefsymoff = 0;
2208 Cmd.nextrefsyms = 0;
2209 Cmd.indirectsymoff = 0;
2210 Cmd.nindirectsyms = 0;
2218 MachO::linkedit_data_command
2219 MachOObjectFile::getDataInCodeLoadCommand() const {
2220 if (DataInCodeLoadCmd)
2221 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2223 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2224 MachO::linkedit_data_command Cmd;
2225 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2226 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2232 MachO::linkedit_data_command
2233 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2234 if (LinkOptHintsLoadCmd)
2235 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2237 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2239 MachO::linkedit_data_command Cmd;
2240 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2241 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2247 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2248 if (!DyldInfoLoadCmd)
2249 return ArrayRef<uint8_t>();
2251 MachO::dyld_info_command DyldInfo
2252 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2253 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2254 getPtr(this, DyldInfo.rebase_off));
2255 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2258 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2259 if (!DyldInfoLoadCmd)
2260 return ArrayRef<uint8_t>();
2262 MachO::dyld_info_command DyldInfo
2263 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2264 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2265 getPtr(this, DyldInfo.bind_off));
2266 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2269 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2270 if (!DyldInfoLoadCmd)
2271 return ArrayRef<uint8_t>();
2273 MachO::dyld_info_command DyldInfo
2274 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2275 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2276 getPtr(this, DyldInfo.weak_bind_off));
2277 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2280 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2281 if (!DyldInfoLoadCmd)
2282 return ArrayRef<uint8_t>();
2284 MachO::dyld_info_command DyldInfo
2285 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2286 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2287 getPtr(this, DyldInfo.lazy_bind_off));
2288 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2291 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2292 if (!DyldInfoLoadCmd)
2293 return ArrayRef<uint8_t>();
2295 MachO::dyld_info_command DyldInfo
2296 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2297 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2298 getPtr(this, DyldInfo.export_off));
2299 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2302 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2304 return ArrayRef<uint8_t>();
2305 // Returning a pointer is fine as uuid doesn't need endian swapping.
2306 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2307 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2310 StringRef MachOObjectFile::getStringTableData() const {
2311 MachO::symtab_command S = getSymtabLoadCommand();
2312 return getData().substr(S.stroff, S.strsize);
2315 bool MachOObjectFile::is64Bit() const {
2316 return getType() == getMachOType(false, true) ||
2317 getType() == getMachOType(true, true);
2320 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2321 SmallVectorImpl<uint64_t> &Out) const {
2322 DataExtractor extractor(ObjectFile::getData(), true, 0);
2324 uint32_t offset = Index;
2326 while (uint64_t delta = extractor.getULEB128(&offset)) {
2328 Out.push_back(data);
2332 bool MachOObjectFile::isRelocatableObject() const {
2333 return getHeader().filetype == MachO::MH_OBJECT;
2336 ErrorOr<std::unique_ptr<MachOObjectFile>>
2337 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2338 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2340 std::unique_ptr<MachOObjectFile> Ret;
2341 if (Magic == "\xFE\xED\xFA\xCE")
2342 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2343 else if (Magic == "\xCE\xFA\xED\xFE")
2344 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2345 else if (Magic == "\xFE\xED\xFA\xCF")
2346 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2347 else if (Magic == "\xCF\xFA\xED\xFE")
2348 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2350 return object_error::parse_failed;
2354 return std::move(Ret);