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::getSymbolValueImpl(DataRefImpl Sym) const {
372 return getNValue(Sym);
375 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
376 return getSymbolValue(Sym);
379 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
380 uint32_t flags = getSymbolFlags(DRI);
381 if (flags & SymbolRef::SF_Common) {
382 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
383 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
388 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
389 return getNValue(DRI);
392 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
393 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
394 uint8_t n_type = Entry.n_type;
396 // If this is a STAB debugging symbol, we can do nothing more.
397 if (n_type & MachO::N_STAB)
398 return SymbolRef::ST_Debug;
400 switch (n_type & MachO::N_TYPE) {
402 return SymbolRef::ST_Unknown;
404 return SymbolRef::ST_Function;
406 return SymbolRef::ST_Other;
409 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
412 uint8_t MachOType = Entry.n_type;
413 uint16_t MachOFlags = Entry.n_desc;
415 uint32_t Result = SymbolRef::SF_None;
417 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
418 Result |= SymbolRef::SF_Indirect;
420 if (MachOType & MachO::N_STAB)
421 Result |= SymbolRef::SF_FormatSpecific;
423 if (MachOType & MachO::N_EXT) {
424 Result |= SymbolRef::SF_Global;
425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
427 Result |= SymbolRef::SF_Common;
429 Result |= SymbolRef::SF_Undefined;
432 if (!(MachOType & MachO::N_PEXT))
433 Result |= SymbolRef::SF_Exported;
436 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
437 Result |= SymbolRef::SF_Weak;
439 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
440 Result |= SymbolRef::SF_Thumb;
442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
443 Result |= SymbolRef::SF_Absolute;
448 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
449 section_iterator &Res) const {
450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
451 uint8_t index = Entry.n_sect;
458 if (DRI.d.a >= Sections.size())
459 report_fatal_error("getSymbolSection: Invalid section index.");
460 Res = section_iterator(SectionRef(DRI, this));
463 return std::error_code();
466 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
467 MachO::nlist_base Entry =
468 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
469 return Entry.n_sect - 1;
472 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
476 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
477 StringRef &Result) const {
478 ArrayRef<char> Raw = getSectionRawName(Sec);
479 Result = parseSegmentOrSectionName(Raw.data());
480 return std::error_code();
483 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
485 return getSection64(Sec).addr;
486 return getSection(Sec).addr;
489 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
491 return getSection64(Sec).size;
492 return getSection(Sec).size;
495 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
496 StringRef &Res) const {
501 MachO::section_64 Sect = getSection64(Sec);
502 Offset = Sect.offset;
505 MachO::section Sect = getSection(Sec);
506 Offset = Sect.offset;
510 Res = this->getData().substr(Offset, Size);
511 return std::error_code();
514 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
517 MachO::section_64 Sect = getSection64(Sec);
520 MachO::section Sect = getSection(Sec);
524 return uint64_t(1) << Align;
527 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
528 uint32_t Flags = getSectionFlags(this, Sec);
529 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
532 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
533 uint32_t Flags = getSectionFlags(this, Sec);
534 unsigned SectionType = Flags & MachO::SECTION_TYPE;
535 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
536 !(SectionType == MachO::S_ZEROFILL ||
537 SectionType == MachO::S_GB_ZEROFILL);
540 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 unsigned SectionType = Flags & MachO::SECTION_TYPE;
543 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
544 (SectionType == MachO::S_ZEROFILL ||
545 SectionType == MachO::S_GB_ZEROFILL);
548 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
549 return Sec.getRawDataRefImpl().d.a;
552 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
553 // FIXME: Unimplemented.
557 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
561 return relocation_iterator(RelocationRef(Ret, this));
565 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
568 MachO::section_64 Sect = getSection64(Sec);
571 MachO::section Sect = getSection(Sec);
578 return relocation_iterator(RelocationRef(Ret, this));
581 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
585 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
586 assert(getHeader().filetype == MachO::MH_OBJECT &&
587 "Only implemented for MH_OBJECT");
588 MachO::any_relocation_info RE = getRelocation(Rel);
589 return getAnyRelocationAddress(RE);
593 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
594 MachO::any_relocation_info RE = getRelocation(Rel);
595 if (isRelocationScattered(RE))
598 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
599 bool isExtern = getPlainRelocationExternal(RE);
603 MachO::symtab_command S = getSymtabLoadCommand();
604 unsigned SymbolTableEntrySize = is64Bit() ?
605 sizeof(MachO::nlist_64) :
606 sizeof(MachO::nlist);
607 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
609 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
610 return symbol_iterator(SymbolRef(Sym, this));
614 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
615 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
618 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
619 MachO::any_relocation_info RE = getRelocation(Rel);
620 return getAnyRelocationType(RE);
623 void MachOObjectFile::getRelocationTypeName(
624 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
626 uint64_t RType = getRelocationType(Rel);
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());
732 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
733 MachO::any_relocation_info RE = getRelocation(Rel);
734 return getAnyRelocationLength(RE);
738 // guessLibraryShortName() is passed a name of a dynamic library and returns a
739 // guess on what the short name is. Then name is returned as a substring of the
740 // StringRef Name passed in. The name of the dynamic library is recognized as
741 // a framework if it has one of the two following forms:
742 // Foo.framework/Versions/A/Foo
744 // Where A and Foo can be any string. And may contain a trailing suffix
745 // starting with an underbar. If the Name is recognized as a framework then
746 // isFramework is set to true else it is set to false. If the Name has a
747 // suffix then Suffix is set to the substring in Name that contains the suffix
748 // else it is set to a NULL StringRef.
750 // The Name of the dynamic library is recognized as a library name if it has
751 // one of the two following forms:
754 // The library may have a suffix trailing the name Foo of the form:
755 // libFoo_profile.A.dylib
756 // libFoo_profile.dylib
758 // The Name of the dynamic library is also recognized as a library name if it
759 // has the following form:
762 // If the Name of the dynamic library is none of the forms above then a NULL
763 // StringRef is returned.
765 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
768 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
769 size_t a, b, c, d, Idx;
772 Suffix = StringRef();
774 // Pull off the last component and make Foo point to it
776 if (a == Name.npos || a == 0)
778 Foo = Name.slice(a+1, Name.npos);
780 // Look for a suffix starting with a '_'
781 Idx = Foo.rfind('_');
782 if (Idx != Foo.npos && Foo.size() >= 2) {
783 Suffix = Foo.slice(Idx, Foo.npos);
784 Foo = Foo.slice(0, Idx);
787 // First look for the form Foo.framework/Foo
788 b = Name.rfind('/', a);
793 F = Name.slice(Idx, Idx + Foo.size());
794 DotFramework = Name.slice(Idx + Foo.size(),
795 Idx + Foo.size() + sizeof(".framework/")-1);
796 if (F == Foo && DotFramework == ".framework/") {
801 // Next look for the form Foo.framework/Versions/A/Foo
804 c = Name.rfind('/', b);
805 if (c == Name.npos || c == 0)
807 V = Name.slice(c+1, Name.npos);
808 if (!V.startswith("Versions/"))
810 d = Name.rfind('/', c);
815 F = Name.slice(Idx, Idx + Foo.size());
816 DotFramework = Name.slice(Idx + Foo.size(),
817 Idx + Foo.size() + sizeof(".framework/")-1);
818 if (F == Foo && DotFramework == ".framework/") {
824 // pull off the suffix after the "." and make a point to it
826 if (a == Name.npos || a == 0)
828 Dylib = Name.slice(a, Name.npos);
829 if (Dylib != ".dylib")
832 // First pull off the version letter for the form Foo.A.dylib if any.
834 Dot = Name.slice(a-2, a-1);
839 b = Name.rfind('/', a);
844 // ignore any suffix after an underbar like Foo_profile.A.dylib
845 Idx = Name.find('_', b);
846 if (Idx != Name.npos && Idx != b) {
847 Lib = Name.slice(b, Idx);
848 Suffix = Name.slice(Idx, a);
851 Lib = Name.slice(b, a);
852 // There are incorrect library names of the form:
853 // libATS.A_profile.dylib so check for these.
854 if (Lib.size() >= 3) {
855 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
857 Lib = Lib.slice(0, Lib.size()-2);
862 Qtx = Name.slice(a, Name.npos);
865 b = Name.rfind('/', a);
867 Lib = Name.slice(0, a);
869 Lib = Name.slice(b+1, a);
870 // There are library names of the form: QT.A.qtx so check for these.
871 if (Lib.size() >= 3) {
872 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
874 Lib = Lib.slice(0, Lib.size()-2);
879 // getLibraryShortNameByIndex() is used to get the short name of the library
880 // for an undefined symbol in a linked Mach-O binary that was linked with the
881 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
882 // It is passed the index (0 - based) of the library as translated from
883 // GET_LIBRARY_ORDINAL (1 - based).
884 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
885 StringRef &Res) const {
886 if (Index >= Libraries.size())
887 return object_error::parse_failed;
889 // If the cache of LibrariesShortNames is not built up do that first for
890 // all the Libraries.
891 if (LibrariesShortNames.size() == 0) {
892 for (unsigned i = 0; i < Libraries.size(); i++) {
893 MachO::dylib_command D =
894 getStruct<MachO::dylib_command>(this, Libraries[i]);
895 if (D.dylib.name >= D.cmdsize)
896 return object_error::parse_failed;
897 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
898 StringRef Name = StringRef(P);
899 if (D.dylib.name+Name.size() >= D.cmdsize)
900 return object_error::parse_failed;
903 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
904 if (shortName.empty())
905 LibrariesShortNames.push_back(Name);
907 LibrariesShortNames.push_back(shortName);
911 Res = LibrariesShortNames[Index];
912 return std::error_code();
916 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
918 Sec.d.a = Rel->getRawDataRefImpl().d.a;
919 return section_iterator(SectionRef(Sec, this));
922 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
923 return getSymbolByIndex(0);
926 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
929 return basic_symbol_iterator(SymbolRef(DRI, this));
931 MachO::symtab_command Symtab = getSymtabLoadCommand();
932 unsigned SymbolTableEntrySize = is64Bit() ?
933 sizeof(MachO::nlist_64) :
934 sizeof(MachO::nlist);
935 unsigned Offset = Symtab.symoff +
936 Symtab.nsyms * SymbolTableEntrySize;
937 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
938 return basic_symbol_iterator(SymbolRef(DRI, this));
941 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
944 return basic_symbol_iterator(SymbolRef(DRI, this));
946 MachO::symtab_command Symtab = getSymtabLoadCommand();
947 if (Index >= Symtab.nsyms)
948 report_fatal_error("Requested symbol index is out of range.");
949 unsigned SymbolTableEntrySize =
950 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
951 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
952 DRI.p += Index * SymbolTableEntrySize;
953 return basic_symbol_iterator(SymbolRef(DRI, this));
956 section_iterator MachOObjectFile::section_begin() const {
958 return section_iterator(SectionRef(DRI, this));
961 section_iterator MachOObjectFile::section_end() const {
963 DRI.d.a = Sections.size();
964 return section_iterator(SectionRef(DRI, this));
967 uint8_t MachOObjectFile::getBytesInAddress() const {
968 return is64Bit() ? 8 : 4;
971 StringRef MachOObjectFile::getFileFormatName() const {
972 unsigned CPUType = getCPUType(this);
975 case llvm::MachO::CPU_TYPE_I386:
976 return "Mach-O 32-bit i386";
977 case llvm::MachO::CPU_TYPE_ARM:
979 case llvm::MachO::CPU_TYPE_POWERPC:
980 return "Mach-O 32-bit ppc";
982 return "Mach-O 32-bit unknown";
987 case llvm::MachO::CPU_TYPE_X86_64:
988 return "Mach-O 64-bit x86-64";
989 case llvm::MachO::CPU_TYPE_ARM64:
990 return "Mach-O arm64";
991 case llvm::MachO::CPU_TYPE_POWERPC64:
992 return "Mach-O 64-bit ppc64";
994 return "Mach-O 64-bit unknown";
998 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1000 case llvm::MachO::CPU_TYPE_I386:
1002 case llvm::MachO::CPU_TYPE_X86_64:
1003 return Triple::x86_64;
1004 case llvm::MachO::CPU_TYPE_ARM:
1006 case llvm::MachO::CPU_TYPE_ARM64:
1007 return Triple::aarch64;
1008 case llvm::MachO::CPU_TYPE_POWERPC:
1010 case llvm::MachO::CPU_TYPE_POWERPC64:
1011 return Triple::ppc64;
1013 return Triple::UnknownArch;
1017 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1018 const char **McpuDefault) {
1020 *McpuDefault = nullptr;
1023 case MachO::CPU_TYPE_I386:
1024 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1025 case MachO::CPU_SUBTYPE_I386_ALL:
1026 return Triple("i386-apple-darwin");
1030 case MachO::CPU_TYPE_X86_64:
1031 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1032 case MachO::CPU_SUBTYPE_X86_64_ALL:
1033 return Triple("x86_64-apple-darwin");
1034 case MachO::CPU_SUBTYPE_X86_64_H:
1035 return Triple("x86_64h-apple-darwin");
1039 case MachO::CPU_TYPE_ARM:
1040 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1041 case MachO::CPU_SUBTYPE_ARM_V4T:
1042 return Triple("armv4t-apple-darwin");
1043 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1044 return Triple("armv5e-apple-darwin");
1045 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1046 return Triple("xscale-apple-darwin");
1047 case MachO::CPU_SUBTYPE_ARM_V6:
1048 return Triple("armv6-apple-darwin");
1049 case MachO::CPU_SUBTYPE_ARM_V6M:
1051 *McpuDefault = "cortex-m0";
1052 return Triple("armv6m-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_V7:
1054 return Triple("armv7-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_V7EM:
1057 *McpuDefault = "cortex-m4";
1058 return Triple("armv7em-apple-darwin");
1059 case MachO::CPU_SUBTYPE_ARM_V7K:
1060 return Triple("armv7k-apple-darwin");
1061 case MachO::CPU_SUBTYPE_ARM_V7M:
1063 *McpuDefault = "cortex-m3";
1064 return Triple("armv7m-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V7S:
1066 return Triple("armv7s-apple-darwin");
1070 case MachO::CPU_TYPE_ARM64:
1071 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1072 case MachO::CPU_SUBTYPE_ARM64_ALL:
1073 return Triple("arm64-apple-darwin");
1077 case MachO::CPU_TYPE_POWERPC:
1078 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1079 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1080 return Triple("ppc-apple-darwin");
1084 case MachO::CPU_TYPE_POWERPC64:
1085 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1086 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1087 return Triple("ppc64-apple-darwin");
1096 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1097 const char **McpuDefault) {
1099 *McpuDefault = nullptr;
1102 case MachO::CPU_TYPE_ARM:
1103 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1104 case MachO::CPU_SUBTYPE_ARM_V4T:
1105 return Triple("thumbv4t-apple-darwin");
1106 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1107 return Triple("thumbv5e-apple-darwin");
1108 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1109 return Triple("xscale-apple-darwin");
1110 case MachO::CPU_SUBTYPE_ARM_V6:
1111 return Triple("thumbv6-apple-darwin");
1112 case MachO::CPU_SUBTYPE_ARM_V6M:
1114 *McpuDefault = "cortex-m0";
1115 return Triple("thumbv6m-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_V7:
1117 return Triple("thumbv7-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_V7EM:
1120 *McpuDefault = "cortex-m4";
1121 return Triple("thumbv7em-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_V7K:
1123 return Triple("thumbv7k-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V7M:
1126 *McpuDefault = "cortex-m3";
1127 return Triple("thumbv7m-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V7S:
1129 return Triple("thumbv7s-apple-darwin");
1138 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1139 const char **McpuDefault,
1140 Triple *ThumbTriple) {
1141 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1142 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1147 Triple MachOObjectFile::getHostArch() {
1148 return Triple(sys::getDefaultTargetTriple());
1151 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1152 return StringSwitch<bool>(ArchFlag)
1154 .Case("x86_64", true)
1155 .Case("x86_64h", true)
1156 .Case("armv4t", true)
1158 .Case("armv5e", true)
1159 .Case("armv6", true)
1160 .Case("armv6m", true)
1161 .Case("armv7", true)
1162 .Case("armv7em", true)
1163 .Case("armv7k", true)
1164 .Case("armv7m", true)
1165 .Case("armv7s", true)
1166 .Case("arm64", true)
1168 .Case("ppc64", true)
1172 unsigned MachOObjectFile::getArch() const {
1173 return getArch(getCPUType(this));
1176 Triple MachOObjectFile::getArch(const char **McpuDefault,
1177 Triple *ThumbTriple) const {
1178 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1179 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1182 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1185 return section_rel_begin(DRI);
1188 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1191 return section_rel_end(DRI);
1194 dice_iterator MachOObjectFile::begin_dices() const {
1196 if (!DataInCodeLoadCmd)
1197 return dice_iterator(DiceRef(DRI, this));
1199 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1200 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1201 return dice_iterator(DiceRef(DRI, this));
1204 dice_iterator MachOObjectFile::end_dices() const {
1206 if (!DataInCodeLoadCmd)
1207 return dice_iterator(DiceRef(DRI, this));
1209 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1210 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1211 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1212 return dice_iterator(DiceRef(DRI, this));
1215 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1216 : Trie(T), Malformed(false), Done(false) { }
1218 void ExportEntry::moveToFirst() {
1220 pushDownUntilBottom();
1223 void ExportEntry::moveToEnd() {
1228 bool ExportEntry::operator==(const ExportEntry &Other) const {
1229 // Common case, one at end, other iterating from begin.
1230 if (Done || Other.Done)
1231 return (Done == Other.Done);
1232 // Not equal if different stack sizes.
1233 if (Stack.size() != Other.Stack.size())
1235 // Not equal if different cumulative strings.
1236 if (!CumulativeString.equals(Other.CumulativeString))
1238 // Equal if all nodes in both stacks match.
1239 for (unsigned i=0; i < Stack.size(); ++i) {
1240 if (Stack[i].Start != Other.Stack[i].Start)
1246 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1248 uint64_t Result = decodeULEB128(Ptr, &Count);
1250 if (Ptr > Trie.end()) {
1257 StringRef ExportEntry::name() const {
1258 return CumulativeString;
1261 uint64_t ExportEntry::flags() const {
1262 return Stack.back().Flags;
1265 uint64_t ExportEntry::address() const {
1266 return Stack.back().Address;
1269 uint64_t ExportEntry::other() const {
1270 return Stack.back().Other;
1273 StringRef ExportEntry::otherName() const {
1274 const char* ImportName = Stack.back().ImportName;
1276 return StringRef(ImportName);
1280 uint32_t ExportEntry::nodeOffset() const {
1281 return Stack.back().Start - Trie.begin();
1284 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1285 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1286 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1287 ParentStringLength(0), IsExportNode(false) {
1290 void ExportEntry::pushNode(uint64_t offset) {
1291 const uint8_t *Ptr = Trie.begin() + offset;
1292 NodeState State(Ptr);
1293 uint64_t ExportInfoSize = readULEB128(State.Current);
1294 State.IsExportNode = (ExportInfoSize != 0);
1295 const uint8_t* Children = State.Current + ExportInfoSize;
1296 if (State.IsExportNode) {
1297 State.Flags = readULEB128(State.Current);
1298 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1300 State.Other = readULEB128(State.Current); // dylib ordinal
1301 State.ImportName = reinterpret_cast<const char*>(State.Current);
1303 State.Address = readULEB128(State.Current);
1304 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1305 State.Other = readULEB128(State.Current);
1308 State.ChildCount = *Children;
1309 State.Current = Children + 1;
1310 State.NextChildIndex = 0;
1311 State.ParentStringLength = CumulativeString.size();
1312 Stack.push_back(State);
1315 void ExportEntry::pushDownUntilBottom() {
1316 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1317 NodeState &Top = Stack.back();
1318 CumulativeString.resize(Top.ParentStringLength);
1319 for (;*Top.Current != 0; Top.Current++) {
1320 char C = *Top.Current;
1321 CumulativeString.push_back(C);
1324 uint64_t childNodeIndex = readULEB128(Top.Current);
1325 Top.NextChildIndex += 1;
1326 pushNode(childNodeIndex);
1328 if (!Stack.back().IsExportNode) {
1334 // We have a trie data structure and need a way to walk it that is compatible
1335 // with the C++ iterator model. The solution is a non-recursive depth first
1336 // traversal where the iterator contains a stack of parent nodes along with a
1337 // string that is the accumulation of all edge strings along the parent chain
1340 // There is one "export" node for each exported symbol. But because some
1341 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1342 // node may have child nodes too.
1344 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1345 // child until hitting a node with no children (which is an export node or
1346 // else the trie is malformed). On the way down, each node is pushed on the
1347 // stack ivar. If there is no more ways down, it pops up one and tries to go
1348 // down a sibling path until a childless node is reached.
1349 void ExportEntry::moveNext() {
1350 if (Stack.empty() || !Stack.back().IsExportNode) {
1357 while (!Stack.empty()) {
1358 NodeState &Top = Stack.back();
1359 if (Top.NextChildIndex < Top.ChildCount) {
1360 pushDownUntilBottom();
1361 // Now at the next export node.
1364 if (Top.IsExportNode) {
1365 // This node has no children but is itself an export node.
1366 CumulativeString.resize(Top.ParentStringLength);
1375 iterator_range<export_iterator>
1376 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1377 ExportEntry Start(Trie);
1378 if (Trie.size() == 0)
1381 Start.moveToFirst();
1383 ExportEntry Finish(Trie);
1386 return iterator_range<export_iterator>(export_iterator(Start),
1387 export_iterator(Finish));
1390 iterator_range<export_iterator> MachOObjectFile::exports() const {
1391 return exports(getDyldInfoExportsTrie());
1395 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1396 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1397 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1398 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1400 void MachORebaseEntry::moveToFirst() {
1401 Ptr = Opcodes.begin();
1405 void MachORebaseEntry::moveToEnd() {
1406 Ptr = Opcodes.end();
1407 RemainingLoopCount = 0;
1411 void MachORebaseEntry::moveNext() {
1412 // If in the middle of some loop, move to next rebasing in loop.
1413 SegmentOffset += AdvanceAmount;
1414 if (RemainingLoopCount) {
1415 --RemainingLoopCount;
1418 if (Ptr == Opcodes.end()) {
1423 while (More && !Malformed) {
1424 // Parse next opcode and set up next loop.
1425 uint8_t Byte = *Ptr++;
1426 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1427 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1429 case MachO::REBASE_OPCODE_DONE:
1433 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1435 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1436 RebaseType = ImmValue;
1439 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1440 << "RebaseType=" << (int) RebaseType << "\n");
1442 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1443 SegmentIndex = ImmValue;
1444 SegmentOffset = readULEB128();
1447 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1448 << "SegmentIndex=" << SegmentIndex << ", "
1449 << format("SegmentOffset=0x%06X", SegmentOffset)
1452 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1453 SegmentOffset += readULEB128();
1454 DEBUG_WITH_TYPE("mach-o-rebase",
1455 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1456 << format("SegmentOffset=0x%06X",
1457 SegmentOffset) << "\n");
1459 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1460 SegmentOffset += ImmValue * PointerSize;
1461 DEBUG_WITH_TYPE("mach-o-rebase",
1462 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1463 << format("SegmentOffset=0x%06X",
1464 SegmentOffset) << "\n");
1466 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1467 AdvanceAmount = PointerSize;
1468 RemainingLoopCount = ImmValue - 1;
1471 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1472 << format("SegmentOffset=0x%06X", SegmentOffset)
1473 << ", AdvanceAmount=" << AdvanceAmount
1474 << ", RemainingLoopCount=" << RemainingLoopCount
1477 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1478 AdvanceAmount = PointerSize;
1479 RemainingLoopCount = readULEB128() - 1;
1482 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1483 << format("SegmentOffset=0x%06X", SegmentOffset)
1484 << ", AdvanceAmount=" << AdvanceAmount
1485 << ", RemainingLoopCount=" << RemainingLoopCount
1488 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1489 AdvanceAmount = readULEB128() + PointerSize;
1490 RemainingLoopCount = 0;
1493 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1494 << format("SegmentOffset=0x%06X", SegmentOffset)
1495 << ", AdvanceAmount=" << AdvanceAmount
1496 << ", RemainingLoopCount=" << RemainingLoopCount
1499 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1500 RemainingLoopCount = readULEB128() - 1;
1501 AdvanceAmount = readULEB128() + PointerSize;
1504 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1505 << format("SegmentOffset=0x%06X", SegmentOffset)
1506 << ", AdvanceAmount=" << AdvanceAmount
1507 << ", RemainingLoopCount=" << RemainingLoopCount
1516 uint64_t MachORebaseEntry::readULEB128() {
1518 uint64_t Result = decodeULEB128(Ptr, &Count);
1520 if (Ptr > Opcodes.end()) {
1521 Ptr = Opcodes.end();
1527 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1529 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1531 StringRef MachORebaseEntry::typeName() const {
1532 switch (RebaseType) {
1533 case MachO::REBASE_TYPE_POINTER:
1535 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1536 return "text abs32";
1537 case MachO::REBASE_TYPE_TEXT_PCREL32:
1538 return "text rel32";
1543 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1544 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1545 return (Ptr == Other.Ptr) &&
1546 (RemainingLoopCount == Other.RemainingLoopCount) &&
1547 (Done == Other.Done);
1550 iterator_range<rebase_iterator>
1551 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1552 MachORebaseEntry Start(Opcodes, is64);
1553 Start.moveToFirst();
1555 MachORebaseEntry Finish(Opcodes, is64);
1558 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1559 rebase_iterator(Finish));
1562 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1563 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1567 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1569 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1570 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1571 BindType(0), PointerSize(is64Bit ? 8 : 4),
1572 TableKind(BK), Malformed(false), Done(false) {}
1574 void MachOBindEntry::moveToFirst() {
1575 Ptr = Opcodes.begin();
1579 void MachOBindEntry::moveToEnd() {
1580 Ptr = Opcodes.end();
1581 RemainingLoopCount = 0;
1585 void MachOBindEntry::moveNext() {
1586 // If in the middle of some loop, move to next binding in loop.
1587 SegmentOffset += AdvanceAmount;
1588 if (RemainingLoopCount) {
1589 --RemainingLoopCount;
1592 if (Ptr == Opcodes.end()) {
1597 while (More && !Malformed) {
1598 // Parse next opcode and set up next loop.
1599 uint8_t Byte = *Ptr++;
1600 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1601 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1602 int8_t SignExtended;
1603 const uint8_t *SymStart;
1605 case MachO::BIND_OPCODE_DONE:
1606 if (TableKind == Kind::Lazy) {
1607 // Lazying bindings have a DONE opcode between entries. Need to ignore
1608 // it to advance to next entry. But need not if this is last entry.
1609 bool NotLastEntry = false;
1610 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1612 NotLastEntry = true;
1621 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1623 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1627 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1628 << "Ordinal=" << Ordinal << "\n");
1630 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1631 Ordinal = readULEB128();
1634 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1635 << "Ordinal=" << Ordinal << "\n");
1637 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1639 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1640 Ordinal = SignExtended;
1645 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1646 << "Ordinal=" << Ordinal << "\n");
1648 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1654 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1659 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1660 << "SymbolName=" << SymbolName << "\n");
1661 if (TableKind == Kind::Weak) {
1662 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1666 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1667 BindType = ImmValue;
1670 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1671 << "BindType=" << (int)BindType << "\n");
1673 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1674 Addend = readSLEB128();
1675 if (TableKind == Kind::Lazy)
1679 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1680 << "Addend=" << Addend << "\n");
1682 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1683 SegmentIndex = ImmValue;
1684 SegmentOffset = readULEB128();
1687 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1688 << "SegmentIndex=" << SegmentIndex << ", "
1689 << format("SegmentOffset=0x%06X", SegmentOffset)
1692 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1693 SegmentOffset += readULEB128();
1694 DEBUG_WITH_TYPE("mach-o-bind",
1695 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1696 << format("SegmentOffset=0x%06X",
1697 SegmentOffset) << "\n");
1699 case MachO::BIND_OPCODE_DO_BIND:
1700 AdvanceAmount = PointerSize;
1701 RemainingLoopCount = 0;
1702 DEBUG_WITH_TYPE("mach-o-bind",
1703 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1704 << format("SegmentOffset=0x%06X",
1705 SegmentOffset) << "\n");
1707 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1708 AdvanceAmount = readULEB128() + PointerSize;
1709 RemainingLoopCount = 0;
1710 if (TableKind == Kind::Lazy)
1714 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1715 << format("SegmentOffset=0x%06X", SegmentOffset)
1716 << ", AdvanceAmount=" << AdvanceAmount
1717 << ", RemainingLoopCount=" << RemainingLoopCount
1720 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1721 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1722 RemainingLoopCount = 0;
1723 if (TableKind == Kind::Lazy)
1725 DEBUG_WITH_TYPE("mach-o-bind",
1727 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1728 << format("SegmentOffset=0x%06X",
1729 SegmentOffset) << "\n");
1731 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1732 RemainingLoopCount = readULEB128() - 1;
1733 AdvanceAmount = readULEB128() + PointerSize;
1734 if (TableKind == Kind::Lazy)
1738 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1739 << format("SegmentOffset=0x%06X", SegmentOffset)
1740 << ", AdvanceAmount=" << AdvanceAmount
1741 << ", RemainingLoopCount=" << RemainingLoopCount
1750 uint64_t MachOBindEntry::readULEB128() {
1752 uint64_t Result = decodeULEB128(Ptr, &Count);
1754 if (Ptr > Opcodes.end()) {
1755 Ptr = Opcodes.end();
1761 int64_t MachOBindEntry::readSLEB128() {
1763 int64_t Result = decodeSLEB128(Ptr, &Count);
1765 if (Ptr > Opcodes.end()) {
1766 Ptr = Opcodes.end();
1773 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1775 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1777 StringRef MachOBindEntry::typeName() const {
1779 case MachO::BIND_TYPE_POINTER:
1781 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1782 return "text abs32";
1783 case MachO::BIND_TYPE_TEXT_PCREL32:
1784 return "text rel32";
1789 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1791 int64_t MachOBindEntry::addend() const { return Addend; }
1793 uint32_t MachOBindEntry::flags() const { return Flags; }
1795 int MachOBindEntry::ordinal() const { return Ordinal; }
1797 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1798 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1799 return (Ptr == Other.Ptr) &&
1800 (RemainingLoopCount == Other.RemainingLoopCount) &&
1801 (Done == Other.Done);
1804 iterator_range<bind_iterator>
1805 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1806 MachOBindEntry::Kind BKind) {
1807 MachOBindEntry Start(Opcodes, is64, BKind);
1808 Start.moveToFirst();
1810 MachOBindEntry Finish(Opcodes, is64, BKind);
1813 return iterator_range<bind_iterator>(bind_iterator(Start),
1814 bind_iterator(Finish));
1817 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1818 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1819 MachOBindEntry::Kind::Regular);
1822 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1823 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1824 MachOBindEntry::Kind::Lazy);
1827 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1828 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1829 MachOBindEntry::Kind::Weak);
1832 MachOObjectFile::load_command_iterator
1833 MachOObjectFile::begin_load_commands() const {
1834 return LoadCommands.begin();
1837 MachOObjectFile::load_command_iterator
1838 MachOObjectFile::end_load_commands() const {
1839 return LoadCommands.end();
1842 iterator_range<MachOObjectFile::load_command_iterator>
1843 MachOObjectFile::load_commands() const {
1844 return iterator_range<load_command_iterator>(begin_load_commands(),
1845 end_load_commands());
1849 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1850 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1851 return parseSegmentOrSectionName(Raw.data());
1855 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1856 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1857 const section_base *Base =
1858 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1859 return makeArrayRef(Base->sectname);
1863 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1864 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1865 const section_base *Base =
1866 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1867 return makeArrayRef(Base->segname);
1871 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1873 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1875 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1878 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1879 const MachO::any_relocation_info &RE) const {
1880 if (isLittleEndian())
1881 return RE.r_word1 & 0xffffff;
1882 return RE.r_word1 >> 8;
1885 bool MachOObjectFile::getPlainRelocationExternal(
1886 const MachO::any_relocation_info &RE) const {
1887 if (isLittleEndian())
1888 return (RE.r_word1 >> 27) & 1;
1889 return (RE.r_word1 >> 4) & 1;
1892 bool MachOObjectFile::getScatteredRelocationScattered(
1893 const MachO::any_relocation_info &RE) const {
1894 return RE.r_word0 >> 31;
1897 uint32_t MachOObjectFile::getScatteredRelocationValue(
1898 const MachO::any_relocation_info &RE) const {
1902 uint32_t MachOObjectFile::getScatteredRelocationType(
1903 const MachO::any_relocation_info &RE) const {
1904 return (RE.r_word0 >> 24) & 0xf;
1907 unsigned MachOObjectFile::getAnyRelocationAddress(
1908 const MachO::any_relocation_info &RE) const {
1909 if (isRelocationScattered(RE))
1910 return getScatteredRelocationAddress(RE);
1911 return getPlainRelocationAddress(RE);
1914 unsigned MachOObjectFile::getAnyRelocationPCRel(
1915 const MachO::any_relocation_info &RE) const {
1916 if (isRelocationScattered(RE))
1917 return getScatteredRelocationPCRel(this, RE);
1918 return getPlainRelocationPCRel(this, RE);
1921 unsigned MachOObjectFile::getAnyRelocationLength(
1922 const MachO::any_relocation_info &RE) const {
1923 if (isRelocationScattered(RE))
1924 return getScatteredRelocationLength(RE);
1925 return getPlainRelocationLength(this, RE);
1929 MachOObjectFile::getAnyRelocationType(
1930 const MachO::any_relocation_info &RE) const {
1931 if (isRelocationScattered(RE))
1932 return getScatteredRelocationType(RE);
1933 return getPlainRelocationType(this, RE);
1937 MachOObjectFile::getAnyRelocationSection(
1938 const MachO::any_relocation_info &RE) const {
1939 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1940 return *section_end();
1941 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1942 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1943 return *section_end();
1945 DRI.d.a = SecNum - 1;
1946 return SectionRef(DRI, this);
1949 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1950 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1951 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1954 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1955 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1956 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1959 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1960 unsigned Index) const {
1961 const char *Sec = getSectionPtr(this, L, Index);
1962 return getStruct<MachO::section>(this, Sec);
1965 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1966 unsigned Index) const {
1967 const char *Sec = getSectionPtr(this, L, Index);
1968 return getStruct<MachO::section_64>(this, Sec);
1972 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1973 const char *P = reinterpret_cast<const char *>(DRI.p);
1974 return getStruct<MachO::nlist>(this, P);
1978 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1979 const char *P = reinterpret_cast<const char *>(DRI.p);
1980 return getStruct<MachO::nlist_64>(this, P);
1983 MachO::linkedit_data_command
1984 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1985 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1988 MachO::segment_command
1989 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1990 return getStruct<MachO::segment_command>(this, L.Ptr);
1993 MachO::segment_command_64
1994 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1995 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1998 MachO::linker_option_command
1999 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2000 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2003 MachO::version_min_command
2004 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2005 return getStruct<MachO::version_min_command>(this, L.Ptr);
2008 MachO::dylib_command
2009 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2010 return getStruct<MachO::dylib_command>(this, L.Ptr);
2013 MachO::dyld_info_command
2014 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2015 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2018 MachO::dylinker_command
2019 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2020 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2024 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2025 return getStruct<MachO::uuid_command>(this, L.Ptr);
2028 MachO::rpath_command
2029 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2030 return getStruct<MachO::rpath_command>(this, L.Ptr);
2033 MachO::source_version_command
2034 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2035 return getStruct<MachO::source_version_command>(this, L.Ptr);
2038 MachO::entry_point_command
2039 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2040 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2043 MachO::encryption_info_command
2044 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2045 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2048 MachO::encryption_info_command_64
2049 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2050 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2053 MachO::sub_framework_command
2054 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2055 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2058 MachO::sub_umbrella_command
2059 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2063 MachO::sub_library_command
2064 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2068 MachO::sub_client_command
2069 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2073 MachO::routines_command
2074 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::routines_command>(this, L.Ptr);
2078 MachO::routines_command_64
2079 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2083 MachO::thread_command
2084 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::thread_command>(this, L.Ptr);
2088 MachO::any_relocation_info
2089 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2094 MachO::section_64 Sect = getSection64(Sec);
2095 Offset = Sect.reloff;
2097 MachO::section Sect = getSection(Sec);
2098 Offset = Sect.reloff;
2101 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2102 getPtr(this, Offset)) + Rel.d.b;
2103 return getStruct<MachO::any_relocation_info>(
2104 this, reinterpret_cast<const char *>(P));
2107 MachO::data_in_code_entry
2108 MachOObjectFile::getDice(DataRefImpl Rel) const {
2109 const char *P = reinterpret_cast<const char *>(Rel.p);
2110 return getStruct<MachO::data_in_code_entry>(this, P);
2113 const MachO::mach_header &MachOObjectFile::getHeader() const {
2117 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2122 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2123 const MachO::dysymtab_command &DLC,
2124 unsigned Index) const {
2125 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2126 return getStruct<uint32_t>(this, getPtr(this, Offset));
2129 MachO::data_in_code_entry
2130 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2131 unsigned Index) const {
2132 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2133 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2136 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2138 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2140 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2141 MachO::symtab_command Cmd;
2142 Cmd.cmd = MachO::LC_SYMTAB;
2143 Cmd.cmdsize = sizeof(MachO::symtab_command);
2151 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2152 if (DysymtabLoadCmd)
2153 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2155 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2156 MachO::dysymtab_command Cmd;
2157 Cmd.cmd = MachO::LC_DYSYMTAB;
2158 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2169 Cmd.extrefsymoff = 0;
2170 Cmd.nextrefsyms = 0;
2171 Cmd.indirectsymoff = 0;
2172 Cmd.nindirectsyms = 0;
2180 MachO::linkedit_data_command
2181 MachOObjectFile::getDataInCodeLoadCommand() const {
2182 if (DataInCodeLoadCmd)
2183 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2185 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2186 MachO::linkedit_data_command Cmd;
2187 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2188 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2194 MachO::linkedit_data_command
2195 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2196 if (LinkOptHintsLoadCmd)
2197 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2199 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2201 MachO::linkedit_data_command Cmd;
2202 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2203 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2209 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2210 if (!DyldInfoLoadCmd)
2211 return ArrayRef<uint8_t>();
2213 MachO::dyld_info_command DyldInfo
2214 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2215 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2216 getPtr(this, DyldInfo.rebase_off));
2217 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2220 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2221 if (!DyldInfoLoadCmd)
2222 return ArrayRef<uint8_t>();
2224 MachO::dyld_info_command DyldInfo
2225 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2226 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2227 getPtr(this, DyldInfo.bind_off));
2228 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2231 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2232 if (!DyldInfoLoadCmd)
2233 return ArrayRef<uint8_t>();
2235 MachO::dyld_info_command DyldInfo
2236 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2237 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2238 getPtr(this, DyldInfo.weak_bind_off));
2239 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2242 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2243 if (!DyldInfoLoadCmd)
2244 return ArrayRef<uint8_t>();
2246 MachO::dyld_info_command DyldInfo
2247 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2248 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2249 getPtr(this, DyldInfo.lazy_bind_off));
2250 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2253 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2254 if (!DyldInfoLoadCmd)
2255 return ArrayRef<uint8_t>();
2257 MachO::dyld_info_command DyldInfo
2258 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2259 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2260 getPtr(this, DyldInfo.export_off));
2261 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2264 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2266 return ArrayRef<uint8_t>();
2267 // Returning a pointer is fine as uuid doesn't need endian swapping.
2268 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2269 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2272 StringRef MachOObjectFile::getStringTableData() const {
2273 MachO::symtab_command S = getSymtabLoadCommand();
2274 return getData().substr(S.stroff, S.strsize);
2277 bool MachOObjectFile::is64Bit() const {
2278 return getType() == getMachOType(false, true) ||
2279 getType() == getMachOType(true, true);
2282 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2283 SmallVectorImpl<uint64_t> &Out) const {
2284 DataExtractor extractor(ObjectFile::getData(), true, 0);
2286 uint32_t offset = Index;
2288 while (uint64_t delta = extractor.getULEB128(&offset)) {
2290 Out.push_back(data);
2294 bool MachOObjectFile::isRelocatableObject() const {
2295 return getHeader().filetype == MachO::MH_OBJECT;
2298 ErrorOr<std::unique_ptr<MachOObjectFile>>
2299 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2300 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2302 std::unique_ptr<MachOObjectFile> Ret;
2303 if (Magic == "\xFE\xED\xFA\xCE")
2304 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2305 else if (Magic == "\xCE\xFA\xED\xFE")
2306 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2307 else if (Magic == "\xFE\xED\xFA\xCF")
2308 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2309 else if (Magic == "\xCF\xFA\xED\xFE")
2310 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2312 return object_error::parse_failed;
2316 return std::move(Ret);