1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
41 // FIXME: Replace all uses of this function with getStructOrErr.
43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
87 static MachO::nlist_base
88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
93 static StringRef parseSegmentOrSectionName(const char *P) {
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
101 // Helper to advance a section or symbol iterator multiple increments at a time.
103 static void advance(T &it, size_t Val) {
108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile *O,
157 MachO::section_64 Sect = O->getSection64(Sec);
160 MachO::section Sect = O->getSection(Sec);
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
173 Load.C = CmdOrErr.get();
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
190 template <typename T>
191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
195 Header = HeaderOrErr.get();
197 EC = HeaderOrErr.getError();
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
235 parseHeader(this, Header64, EC);
237 parseHeader(this, Header, EC);
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
247 EC = LoadOrErr.getError();
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
256 EC = object_error::parse_failed;
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
292 EC = object_error::parse_failed;
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
314 EC = LoadOrErr.getError();
317 Load = LoadOrErr.get();
320 assert(LoadCommands.size() == LoadCommandCount);
323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
330 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331 StringRef StringTable = getStringTableData();
332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333 const char *Start = &StringTable.data()[Entry.n_strx];
334 if (Start < getData().begin() || Start >= getData().end())
336 "Symbol name entry points before beginning or past end of file.");
337 return StringRef(Start);
340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
359 StringRef StringTable = getStringTableData();
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
368 return std::error_code();
371 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
372 uint64_t NValue = getNValue(Sym);
373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
374 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
375 return UnknownAddress;
379 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
380 return getSymbolValue(Sym);
383 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
384 uint32_t flags = getSymbolFlags(DRI);
385 if (flags & SymbolRef::SF_Common) {
386 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
387 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
392 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
393 return getNValue(DRI);
396 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
397 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
398 uint8_t n_type = Entry.n_type;
400 // If this is a STAB debugging symbol, we can do nothing more.
401 if (n_type & MachO::N_STAB)
402 return SymbolRef::ST_Debug;
404 switch (n_type & MachO::N_TYPE) {
406 return SymbolRef::ST_Unknown;
408 return SymbolRef::ST_Function;
410 return SymbolRef::ST_Other;
413 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
414 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
416 uint8_t MachOType = Entry.n_type;
417 uint16_t MachOFlags = Entry.n_desc;
419 uint32_t Result = SymbolRef::SF_None;
421 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
422 Result |= SymbolRef::SF_Indirect;
424 if (MachOType & MachO::N_STAB)
425 Result |= SymbolRef::SF_FormatSpecific;
427 if (MachOType & MachO::N_EXT) {
428 Result |= SymbolRef::SF_Global;
429 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
431 Result |= SymbolRef::SF_Common;
433 Result |= SymbolRef::SF_Undefined;
436 if (!(MachOType & MachO::N_PEXT))
437 Result |= SymbolRef::SF_Exported;
440 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
441 Result |= SymbolRef::SF_Weak;
443 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
444 Result |= SymbolRef::SF_Thumb;
446 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
447 Result |= SymbolRef::SF_Absolute;
452 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
453 section_iterator &Res) const {
454 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
455 uint8_t index = Entry.n_sect;
462 if (DRI.d.a >= Sections.size())
463 report_fatal_error("getSymbolSection: Invalid section index.");
464 Res = section_iterator(SectionRef(DRI, this));
467 return std::error_code();
470 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
471 MachO::nlist_base Entry =
472 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
473 return Entry.n_sect - 1;
476 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
480 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
481 StringRef &Result) const {
482 ArrayRef<char> Raw = getSectionRawName(Sec);
483 Result = parseSegmentOrSectionName(Raw.data());
484 return std::error_code();
487 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
489 return getSection64(Sec).addr;
490 return getSection(Sec).addr;
493 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
495 return getSection64(Sec).size;
496 return getSection(Sec).size;
499 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
500 StringRef &Res) const {
505 MachO::section_64 Sect = getSection64(Sec);
506 Offset = Sect.offset;
509 MachO::section Sect = getSection(Sec);
510 Offset = Sect.offset;
514 Res = this->getData().substr(Offset, Size);
515 return std::error_code();
518 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
521 MachO::section_64 Sect = getSection64(Sec);
524 MachO::section Sect = getSection(Sec);
528 return uint64_t(1) << Align;
531 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
532 uint32_t Flags = getSectionFlags(this, Sec);
533 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
536 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
537 uint32_t Flags = getSectionFlags(this, Sec);
538 unsigned SectionType = Flags & MachO::SECTION_TYPE;
539 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
540 !(SectionType == MachO::S_ZEROFILL ||
541 SectionType == MachO::S_GB_ZEROFILL);
544 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
545 uint32_t Flags = getSectionFlags(this, Sec);
546 unsigned SectionType = Flags & MachO::SECTION_TYPE;
547 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
548 (SectionType == MachO::S_ZEROFILL ||
549 SectionType == MachO::S_GB_ZEROFILL);
552 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
553 return Sec.getRawDataRefImpl().d.a;
556 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
557 // FIXME: Unimplemented.
561 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
565 return relocation_iterator(RelocationRef(Ret, this));
569 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
572 MachO::section_64 Sect = getSection64(Sec);
575 MachO::section Sect = getSection(Sec);
582 return relocation_iterator(RelocationRef(Ret, this));
585 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
589 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
590 assert(getHeader().filetype == MachO::MH_OBJECT &&
591 "Only implemented for MH_OBJECT");
592 MachO::any_relocation_info RE = getRelocation(Rel);
593 return getAnyRelocationAddress(RE);
597 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
598 MachO::any_relocation_info RE = getRelocation(Rel);
599 if (isRelocationScattered(RE))
602 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
603 bool isExtern = getPlainRelocationExternal(RE);
607 MachO::symtab_command S = getSymtabLoadCommand();
608 unsigned SymbolTableEntrySize = is64Bit() ?
609 sizeof(MachO::nlist_64) :
610 sizeof(MachO::nlist);
611 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
613 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
614 return symbol_iterator(SymbolRef(Sym, this));
618 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
619 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
622 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
623 MachO::any_relocation_info RE = getRelocation(Rel);
624 return getAnyRelocationType(RE);
627 void MachOObjectFile::getRelocationTypeName(
628 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
630 uint64_t RType = getRelocationType(Rel);
632 unsigned Arch = this->getArch();
636 static const char *const Table[] = {
637 "GENERIC_RELOC_VANILLA",
638 "GENERIC_RELOC_PAIR",
639 "GENERIC_RELOC_SECTDIFF",
640 "GENERIC_RELOC_PB_LA_PTR",
641 "GENERIC_RELOC_LOCAL_SECTDIFF",
642 "GENERIC_RELOC_TLV" };
650 case Triple::x86_64: {
651 static const char *const Table[] = {
652 "X86_64_RELOC_UNSIGNED",
653 "X86_64_RELOC_SIGNED",
654 "X86_64_RELOC_BRANCH",
655 "X86_64_RELOC_GOT_LOAD",
657 "X86_64_RELOC_SUBTRACTOR",
658 "X86_64_RELOC_SIGNED_1",
659 "X86_64_RELOC_SIGNED_2",
660 "X86_64_RELOC_SIGNED_4",
661 "X86_64_RELOC_TLV" };
670 static const char *const Table[] = {
673 "ARM_RELOC_SECTDIFF",
674 "ARM_RELOC_LOCAL_SECTDIFF",
675 "ARM_RELOC_PB_LA_PTR",
677 "ARM_THUMB_RELOC_BR22",
678 "ARM_THUMB_32BIT_BRANCH",
680 "ARM_RELOC_HALF_SECTDIFF" };
688 case Triple::aarch64: {
689 static const char *const Table[] = {
690 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
691 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
692 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
693 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
694 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
698 if (RType >= array_lengthof(Table))
705 static const char *const Table[] = {
714 "PPC_RELOC_SECTDIFF",
715 "PPC_RELOC_PB_LA_PTR",
716 "PPC_RELOC_HI16_SECTDIFF",
717 "PPC_RELOC_LO16_SECTDIFF",
718 "PPC_RELOC_HA16_SECTDIFF",
720 "PPC_RELOC_LO14_SECTDIFF",
721 "PPC_RELOC_LOCAL_SECTDIFF" };
729 case Triple::UnknownArch:
733 Result.append(res.begin(), res.end());
736 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
737 MachO::any_relocation_info RE = getRelocation(Rel);
738 return getAnyRelocationLength(RE);
742 // guessLibraryShortName() is passed a name of a dynamic library and returns a
743 // guess on what the short name is. Then name is returned as a substring of the
744 // StringRef Name passed in. The name of the dynamic library is recognized as
745 // a framework if it has one of the two following forms:
746 // Foo.framework/Versions/A/Foo
748 // Where A and Foo can be any string. And may contain a trailing suffix
749 // starting with an underbar. If the Name is recognized as a framework then
750 // isFramework is set to true else it is set to false. If the Name has a
751 // suffix then Suffix is set to the substring in Name that contains the suffix
752 // else it is set to a NULL StringRef.
754 // The Name of the dynamic library is recognized as a library name if it has
755 // one of the two following forms:
758 // The library may have a suffix trailing the name Foo of the form:
759 // libFoo_profile.A.dylib
760 // libFoo_profile.dylib
762 // The Name of the dynamic library is also recognized as a library name if it
763 // has the following form:
766 // If the Name of the dynamic library is none of the forms above then a NULL
767 // StringRef is returned.
769 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
772 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
773 size_t a, b, c, d, Idx;
776 Suffix = StringRef();
778 // Pull off the last component and make Foo point to it
780 if (a == Name.npos || a == 0)
782 Foo = Name.slice(a+1, Name.npos);
784 // Look for a suffix starting with a '_'
785 Idx = Foo.rfind('_');
786 if (Idx != Foo.npos && Foo.size() >= 2) {
787 Suffix = Foo.slice(Idx, Foo.npos);
788 Foo = Foo.slice(0, Idx);
791 // First look for the form Foo.framework/Foo
792 b = Name.rfind('/', a);
797 F = Name.slice(Idx, Idx + Foo.size());
798 DotFramework = Name.slice(Idx + Foo.size(),
799 Idx + Foo.size() + sizeof(".framework/")-1);
800 if (F == Foo && DotFramework == ".framework/") {
805 // Next look for the form Foo.framework/Versions/A/Foo
808 c = Name.rfind('/', b);
809 if (c == Name.npos || c == 0)
811 V = Name.slice(c+1, Name.npos);
812 if (!V.startswith("Versions/"))
814 d = Name.rfind('/', c);
819 F = Name.slice(Idx, Idx + Foo.size());
820 DotFramework = Name.slice(Idx + Foo.size(),
821 Idx + Foo.size() + sizeof(".framework/")-1);
822 if (F == Foo && DotFramework == ".framework/") {
828 // pull off the suffix after the "." and make a point to it
830 if (a == Name.npos || a == 0)
832 Dylib = Name.slice(a, Name.npos);
833 if (Dylib != ".dylib")
836 // First pull off the version letter for the form Foo.A.dylib if any.
838 Dot = Name.slice(a-2, a-1);
843 b = Name.rfind('/', a);
848 // ignore any suffix after an underbar like Foo_profile.A.dylib
849 Idx = Name.find('_', b);
850 if (Idx != Name.npos && Idx != b) {
851 Lib = Name.slice(b, Idx);
852 Suffix = Name.slice(Idx, a);
855 Lib = Name.slice(b, a);
856 // There are incorrect library names of the form:
857 // libATS.A_profile.dylib so check for these.
858 if (Lib.size() >= 3) {
859 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
861 Lib = Lib.slice(0, Lib.size()-2);
866 Qtx = Name.slice(a, Name.npos);
869 b = Name.rfind('/', a);
871 Lib = Name.slice(0, a);
873 Lib = Name.slice(b+1, a);
874 // There are library names of the form: QT.A.qtx so check for these.
875 if (Lib.size() >= 3) {
876 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
878 Lib = Lib.slice(0, Lib.size()-2);
883 // getLibraryShortNameByIndex() is used to get the short name of the library
884 // for an undefined symbol in a linked Mach-O binary that was linked with the
885 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
886 // It is passed the index (0 - based) of the library as translated from
887 // GET_LIBRARY_ORDINAL (1 - based).
888 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
889 StringRef &Res) const {
890 if (Index >= Libraries.size())
891 return object_error::parse_failed;
893 // If the cache of LibrariesShortNames is not built up do that first for
894 // all the Libraries.
895 if (LibrariesShortNames.size() == 0) {
896 for (unsigned i = 0; i < Libraries.size(); i++) {
897 MachO::dylib_command D =
898 getStruct<MachO::dylib_command>(this, Libraries[i]);
899 if (D.dylib.name >= D.cmdsize)
900 return object_error::parse_failed;
901 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
902 StringRef Name = StringRef(P);
903 if (D.dylib.name+Name.size() >= D.cmdsize)
904 return object_error::parse_failed;
907 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
908 if (shortName.empty())
909 LibrariesShortNames.push_back(Name);
911 LibrariesShortNames.push_back(shortName);
915 Res = LibrariesShortNames[Index];
916 return std::error_code();
920 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
922 Sec.d.a = Rel->getRawDataRefImpl().d.a;
923 return section_iterator(SectionRef(Sec, this));
926 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
927 return getSymbolByIndex(0);
930 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
933 return basic_symbol_iterator(SymbolRef(DRI, this));
935 MachO::symtab_command Symtab = getSymtabLoadCommand();
936 unsigned SymbolTableEntrySize = is64Bit() ?
937 sizeof(MachO::nlist_64) :
938 sizeof(MachO::nlist);
939 unsigned Offset = Symtab.symoff +
940 Symtab.nsyms * SymbolTableEntrySize;
941 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
942 return basic_symbol_iterator(SymbolRef(DRI, this));
945 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
948 return basic_symbol_iterator(SymbolRef(DRI, this));
950 MachO::symtab_command Symtab = getSymtabLoadCommand();
951 if (Index >= Symtab.nsyms)
952 report_fatal_error("Requested symbol index is out of range.");
953 unsigned SymbolTableEntrySize =
954 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
955 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
956 DRI.p += Index * SymbolTableEntrySize;
957 return basic_symbol_iterator(SymbolRef(DRI, this));
960 section_iterator MachOObjectFile::section_begin() const {
962 return section_iterator(SectionRef(DRI, this));
965 section_iterator MachOObjectFile::section_end() const {
967 DRI.d.a = Sections.size();
968 return section_iterator(SectionRef(DRI, this));
971 uint8_t MachOObjectFile::getBytesInAddress() const {
972 return is64Bit() ? 8 : 4;
975 StringRef MachOObjectFile::getFileFormatName() const {
976 unsigned CPUType = getCPUType(this);
979 case llvm::MachO::CPU_TYPE_I386:
980 return "Mach-O 32-bit i386";
981 case llvm::MachO::CPU_TYPE_ARM:
983 case llvm::MachO::CPU_TYPE_POWERPC:
984 return "Mach-O 32-bit ppc";
986 return "Mach-O 32-bit unknown";
991 case llvm::MachO::CPU_TYPE_X86_64:
992 return "Mach-O 64-bit x86-64";
993 case llvm::MachO::CPU_TYPE_ARM64:
994 return "Mach-O arm64";
995 case llvm::MachO::CPU_TYPE_POWERPC64:
996 return "Mach-O 64-bit ppc64";
998 return "Mach-O 64-bit unknown";
1002 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1004 case llvm::MachO::CPU_TYPE_I386:
1006 case llvm::MachO::CPU_TYPE_X86_64:
1007 return Triple::x86_64;
1008 case llvm::MachO::CPU_TYPE_ARM:
1010 case llvm::MachO::CPU_TYPE_ARM64:
1011 return Triple::aarch64;
1012 case llvm::MachO::CPU_TYPE_POWERPC:
1014 case llvm::MachO::CPU_TYPE_POWERPC64:
1015 return Triple::ppc64;
1017 return Triple::UnknownArch;
1021 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1022 const char **McpuDefault) {
1024 *McpuDefault = nullptr;
1027 case MachO::CPU_TYPE_I386:
1028 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1029 case MachO::CPU_SUBTYPE_I386_ALL:
1030 return Triple("i386-apple-darwin");
1034 case MachO::CPU_TYPE_X86_64:
1035 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1036 case MachO::CPU_SUBTYPE_X86_64_ALL:
1037 return Triple("x86_64-apple-darwin");
1038 case MachO::CPU_SUBTYPE_X86_64_H:
1039 return Triple("x86_64h-apple-darwin");
1043 case MachO::CPU_TYPE_ARM:
1044 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1045 case MachO::CPU_SUBTYPE_ARM_V4T:
1046 return Triple("armv4t-apple-darwin");
1047 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1048 return Triple("armv5e-apple-darwin");
1049 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1050 return Triple("xscale-apple-darwin");
1051 case MachO::CPU_SUBTYPE_ARM_V6:
1052 return Triple("armv6-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_V6M:
1055 *McpuDefault = "cortex-m0";
1056 return Triple("armv6m-apple-darwin");
1057 case MachO::CPU_SUBTYPE_ARM_V7:
1058 return Triple("armv7-apple-darwin");
1059 case MachO::CPU_SUBTYPE_ARM_V7EM:
1061 *McpuDefault = "cortex-m4";
1062 return Triple("armv7em-apple-darwin");
1063 case MachO::CPU_SUBTYPE_ARM_V7K:
1064 return Triple("armv7k-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V7M:
1067 *McpuDefault = "cortex-m3";
1068 return Triple("armv7m-apple-darwin");
1069 case MachO::CPU_SUBTYPE_ARM_V7S:
1070 return Triple("armv7s-apple-darwin");
1074 case MachO::CPU_TYPE_ARM64:
1075 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1076 case MachO::CPU_SUBTYPE_ARM64_ALL:
1077 return Triple("arm64-apple-darwin");
1081 case MachO::CPU_TYPE_POWERPC:
1082 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1083 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1084 return Triple("ppc-apple-darwin");
1088 case MachO::CPU_TYPE_POWERPC64:
1089 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1090 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1091 return Triple("ppc64-apple-darwin");
1100 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1101 const char **McpuDefault) {
1103 *McpuDefault = nullptr;
1106 case MachO::CPU_TYPE_ARM:
1107 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1108 case MachO::CPU_SUBTYPE_ARM_V4T:
1109 return Triple("thumbv4t-apple-darwin");
1110 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1111 return Triple("thumbv5e-apple-darwin");
1112 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1113 return Triple("xscale-apple-darwin");
1114 case MachO::CPU_SUBTYPE_ARM_V6:
1115 return Triple("thumbv6-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_V6M:
1118 *McpuDefault = "cortex-m0";
1119 return Triple("thumbv6m-apple-darwin");
1120 case MachO::CPU_SUBTYPE_ARM_V7:
1121 return Triple("thumbv7-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_V7EM:
1124 *McpuDefault = "cortex-m4";
1125 return Triple("thumbv7em-apple-darwin");
1126 case MachO::CPU_SUBTYPE_ARM_V7K:
1127 return Triple("thumbv7k-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V7M:
1130 *McpuDefault = "cortex-m3";
1131 return Triple("thumbv7m-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V7S:
1133 return Triple("thumbv7s-apple-darwin");
1142 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1143 const char **McpuDefault,
1144 Triple *ThumbTriple) {
1145 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1146 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1151 Triple MachOObjectFile::getHostArch() {
1152 return Triple(sys::getDefaultTargetTriple());
1155 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1156 return StringSwitch<bool>(ArchFlag)
1158 .Case("x86_64", true)
1159 .Case("x86_64h", true)
1160 .Case("armv4t", true)
1162 .Case("armv5e", true)
1163 .Case("armv6", true)
1164 .Case("armv6m", true)
1165 .Case("armv7", true)
1166 .Case("armv7em", true)
1167 .Case("armv7k", true)
1168 .Case("armv7m", true)
1169 .Case("armv7s", true)
1170 .Case("arm64", true)
1172 .Case("ppc64", true)
1176 unsigned MachOObjectFile::getArch() const {
1177 return getArch(getCPUType(this));
1180 Triple MachOObjectFile::getArch(const char **McpuDefault,
1181 Triple *ThumbTriple) const {
1182 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1183 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1186 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1189 return section_rel_begin(DRI);
1192 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1195 return section_rel_end(DRI);
1198 dice_iterator MachOObjectFile::begin_dices() const {
1200 if (!DataInCodeLoadCmd)
1201 return dice_iterator(DiceRef(DRI, this));
1203 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1204 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1205 return dice_iterator(DiceRef(DRI, this));
1208 dice_iterator MachOObjectFile::end_dices() const {
1210 if (!DataInCodeLoadCmd)
1211 return dice_iterator(DiceRef(DRI, this));
1213 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1214 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1215 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1216 return dice_iterator(DiceRef(DRI, this));
1219 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1220 : Trie(T), Malformed(false), Done(false) { }
1222 void ExportEntry::moveToFirst() {
1224 pushDownUntilBottom();
1227 void ExportEntry::moveToEnd() {
1232 bool ExportEntry::operator==(const ExportEntry &Other) const {
1233 // Common case, one at end, other iterating from begin.
1234 if (Done || Other.Done)
1235 return (Done == Other.Done);
1236 // Not equal if different stack sizes.
1237 if (Stack.size() != Other.Stack.size())
1239 // Not equal if different cumulative strings.
1240 if (!CumulativeString.equals(Other.CumulativeString))
1242 // Equal if all nodes in both stacks match.
1243 for (unsigned i=0; i < Stack.size(); ++i) {
1244 if (Stack[i].Start != Other.Stack[i].Start)
1250 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1252 uint64_t Result = decodeULEB128(Ptr, &Count);
1254 if (Ptr > Trie.end()) {
1261 StringRef ExportEntry::name() const {
1262 return CumulativeString;
1265 uint64_t ExportEntry::flags() const {
1266 return Stack.back().Flags;
1269 uint64_t ExportEntry::address() const {
1270 return Stack.back().Address;
1273 uint64_t ExportEntry::other() const {
1274 return Stack.back().Other;
1277 StringRef ExportEntry::otherName() const {
1278 const char* ImportName = Stack.back().ImportName;
1280 return StringRef(ImportName);
1284 uint32_t ExportEntry::nodeOffset() const {
1285 return Stack.back().Start - Trie.begin();
1288 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1289 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1290 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1291 ParentStringLength(0), IsExportNode(false) {
1294 void ExportEntry::pushNode(uint64_t offset) {
1295 const uint8_t *Ptr = Trie.begin() + offset;
1296 NodeState State(Ptr);
1297 uint64_t ExportInfoSize = readULEB128(State.Current);
1298 State.IsExportNode = (ExportInfoSize != 0);
1299 const uint8_t* Children = State.Current + ExportInfoSize;
1300 if (State.IsExportNode) {
1301 State.Flags = readULEB128(State.Current);
1302 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1304 State.Other = readULEB128(State.Current); // dylib ordinal
1305 State.ImportName = reinterpret_cast<const char*>(State.Current);
1307 State.Address = readULEB128(State.Current);
1308 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1309 State.Other = readULEB128(State.Current);
1312 State.ChildCount = *Children;
1313 State.Current = Children + 1;
1314 State.NextChildIndex = 0;
1315 State.ParentStringLength = CumulativeString.size();
1316 Stack.push_back(State);
1319 void ExportEntry::pushDownUntilBottom() {
1320 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1321 NodeState &Top = Stack.back();
1322 CumulativeString.resize(Top.ParentStringLength);
1323 for (;*Top.Current != 0; Top.Current++) {
1324 char C = *Top.Current;
1325 CumulativeString.push_back(C);
1328 uint64_t childNodeIndex = readULEB128(Top.Current);
1329 Top.NextChildIndex += 1;
1330 pushNode(childNodeIndex);
1332 if (!Stack.back().IsExportNode) {
1338 // We have a trie data structure and need a way to walk it that is compatible
1339 // with the C++ iterator model. The solution is a non-recursive depth first
1340 // traversal where the iterator contains a stack of parent nodes along with a
1341 // string that is the accumulation of all edge strings along the parent chain
1344 // There is one "export" node for each exported symbol. But because some
1345 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1346 // node may have child nodes too.
1348 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1349 // child until hitting a node with no children (which is an export node or
1350 // else the trie is malformed). On the way down, each node is pushed on the
1351 // stack ivar. If there is no more ways down, it pops up one and tries to go
1352 // down a sibling path until a childless node is reached.
1353 void ExportEntry::moveNext() {
1354 if (Stack.empty() || !Stack.back().IsExportNode) {
1361 while (!Stack.empty()) {
1362 NodeState &Top = Stack.back();
1363 if (Top.NextChildIndex < Top.ChildCount) {
1364 pushDownUntilBottom();
1365 // Now at the next export node.
1368 if (Top.IsExportNode) {
1369 // This node has no children but is itself an export node.
1370 CumulativeString.resize(Top.ParentStringLength);
1379 iterator_range<export_iterator>
1380 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1381 ExportEntry Start(Trie);
1382 if (Trie.size() == 0)
1385 Start.moveToFirst();
1387 ExportEntry Finish(Trie);
1390 return iterator_range<export_iterator>(export_iterator(Start),
1391 export_iterator(Finish));
1394 iterator_range<export_iterator> MachOObjectFile::exports() const {
1395 return exports(getDyldInfoExportsTrie());
1399 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1400 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1401 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1402 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1404 void MachORebaseEntry::moveToFirst() {
1405 Ptr = Opcodes.begin();
1409 void MachORebaseEntry::moveToEnd() {
1410 Ptr = Opcodes.end();
1411 RemainingLoopCount = 0;
1415 void MachORebaseEntry::moveNext() {
1416 // If in the middle of some loop, move to next rebasing in loop.
1417 SegmentOffset += AdvanceAmount;
1418 if (RemainingLoopCount) {
1419 --RemainingLoopCount;
1422 if (Ptr == Opcodes.end()) {
1427 while (More && !Malformed) {
1428 // Parse next opcode and set up next loop.
1429 uint8_t Byte = *Ptr++;
1430 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1431 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1433 case MachO::REBASE_OPCODE_DONE:
1437 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1439 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1440 RebaseType = ImmValue;
1443 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1444 << "RebaseType=" << (int) RebaseType << "\n");
1446 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1447 SegmentIndex = ImmValue;
1448 SegmentOffset = readULEB128();
1451 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1452 << "SegmentIndex=" << SegmentIndex << ", "
1453 << format("SegmentOffset=0x%06X", SegmentOffset)
1456 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1457 SegmentOffset += readULEB128();
1458 DEBUG_WITH_TYPE("mach-o-rebase",
1459 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1460 << format("SegmentOffset=0x%06X",
1461 SegmentOffset) << "\n");
1463 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1464 SegmentOffset += ImmValue * PointerSize;
1465 DEBUG_WITH_TYPE("mach-o-rebase",
1466 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1467 << format("SegmentOffset=0x%06X",
1468 SegmentOffset) << "\n");
1470 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1471 AdvanceAmount = PointerSize;
1472 RemainingLoopCount = ImmValue - 1;
1475 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1476 << format("SegmentOffset=0x%06X", SegmentOffset)
1477 << ", AdvanceAmount=" << AdvanceAmount
1478 << ", RemainingLoopCount=" << RemainingLoopCount
1481 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1482 AdvanceAmount = PointerSize;
1483 RemainingLoopCount = readULEB128() - 1;
1486 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1487 << format("SegmentOffset=0x%06X", SegmentOffset)
1488 << ", AdvanceAmount=" << AdvanceAmount
1489 << ", RemainingLoopCount=" << RemainingLoopCount
1492 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1493 AdvanceAmount = readULEB128() + PointerSize;
1494 RemainingLoopCount = 0;
1497 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1498 << format("SegmentOffset=0x%06X", SegmentOffset)
1499 << ", AdvanceAmount=" << AdvanceAmount
1500 << ", RemainingLoopCount=" << RemainingLoopCount
1503 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1504 RemainingLoopCount = readULEB128() - 1;
1505 AdvanceAmount = readULEB128() + PointerSize;
1508 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1509 << format("SegmentOffset=0x%06X", SegmentOffset)
1510 << ", AdvanceAmount=" << AdvanceAmount
1511 << ", RemainingLoopCount=" << RemainingLoopCount
1520 uint64_t MachORebaseEntry::readULEB128() {
1522 uint64_t Result = decodeULEB128(Ptr, &Count);
1524 if (Ptr > Opcodes.end()) {
1525 Ptr = Opcodes.end();
1531 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1533 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1535 StringRef MachORebaseEntry::typeName() const {
1536 switch (RebaseType) {
1537 case MachO::REBASE_TYPE_POINTER:
1539 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1540 return "text abs32";
1541 case MachO::REBASE_TYPE_TEXT_PCREL32:
1542 return "text rel32";
1547 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1548 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1549 return (Ptr == Other.Ptr) &&
1550 (RemainingLoopCount == Other.RemainingLoopCount) &&
1551 (Done == Other.Done);
1554 iterator_range<rebase_iterator>
1555 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1556 MachORebaseEntry Start(Opcodes, is64);
1557 Start.moveToFirst();
1559 MachORebaseEntry Finish(Opcodes, is64);
1562 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1563 rebase_iterator(Finish));
1566 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1567 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1571 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1573 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1574 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1575 BindType(0), PointerSize(is64Bit ? 8 : 4),
1576 TableKind(BK), Malformed(false), Done(false) {}
1578 void MachOBindEntry::moveToFirst() {
1579 Ptr = Opcodes.begin();
1583 void MachOBindEntry::moveToEnd() {
1584 Ptr = Opcodes.end();
1585 RemainingLoopCount = 0;
1589 void MachOBindEntry::moveNext() {
1590 // If in the middle of some loop, move to next binding in loop.
1591 SegmentOffset += AdvanceAmount;
1592 if (RemainingLoopCount) {
1593 --RemainingLoopCount;
1596 if (Ptr == Opcodes.end()) {
1601 while (More && !Malformed) {
1602 // Parse next opcode and set up next loop.
1603 uint8_t Byte = *Ptr++;
1604 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1605 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1606 int8_t SignExtended;
1607 const uint8_t *SymStart;
1609 case MachO::BIND_OPCODE_DONE:
1610 if (TableKind == Kind::Lazy) {
1611 // Lazying bindings have a DONE opcode between entries. Need to ignore
1612 // it to advance to next entry. But need not if this is last entry.
1613 bool NotLastEntry = false;
1614 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1616 NotLastEntry = true;
1625 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1627 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1631 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1632 << "Ordinal=" << Ordinal << "\n");
1634 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1635 Ordinal = readULEB128();
1638 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1639 << "Ordinal=" << Ordinal << "\n");
1641 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1643 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1644 Ordinal = SignExtended;
1649 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1650 << "Ordinal=" << Ordinal << "\n");
1652 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1658 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1663 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1664 << "SymbolName=" << SymbolName << "\n");
1665 if (TableKind == Kind::Weak) {
1666 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1670 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1671 BindType = ImmValue;
1674 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1675 << "BindType=" << (int)BindType << "\n");
1677 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1678 Addend = readSLEB128();
1679 if (TableKind == Kind::Lazy)
1683 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1684 << "Addend=" << Addend << "\n");
1686 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1687 SegmentIndex = ImmValue;
1688 SegmentOffset = readULEB128();
1691 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1692 << "SegmentIndex=" << SegmentIndex << ", "
1693 << format("SegmentOffset=0x%06X", SegmentOffset)
1696 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1697 SegmentOffset += readULEB128();
1698 DEBUG_WITH_TYPE("mach-o-bind",
1699 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1700 << format("SegmentOffset=0x%06X",
1701 SegmentOffset) << "\n");
1703 case MachO::BIND_OPCODE_DO_BIND:
1704 AdvanceAmount = PointerSize;
1705 RemainingLoopCount = 0;
1706 DEBUG_WITH_TYPE("mach-o-bind",
1707 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1708 << format("SegmentOffset=0x%06X",
1709 SegmentOffset) << "\n");
1711 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1712 AdvanceAmount = readULEB128() + PointerSize;
1713 RemainingLoopCount = 0;
1714 if (TableKind == Kind::Lazy)
1718 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1719 << format("SegmentOffset=0x%06X", SegmentOffset)
1720 << ", AdvanceAmount=" << AdvanceAmount
1721 << ", RemainingLoopCount=" << RemainingLoopCount
1724 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1725 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1726 RemainingLoopCount = 0;
1727 if (TableKind == Kind::Lazy)
1729 DEBUG_WITH_TYPE("mach-o-bind",
1731 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1732 << format("SegmentOffset=0x%06X",
1733 SegmentOffset) << "\n");
1735 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1736 RemainingLoopCount = readULEB128() - 1;
1737 AdvanceAmount = readULEB128() + PointerSize;
1738 if (TableKind == Kind::Lazy)
1742 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1743 << format("SegmentOffset=0x%06X", SegmentOffset)
1744 << ", AdvanceAmount=" << AdvanceAmount
1745 << ", RemainingLoopCount=" << RemainingLoopCount
1754 uint64_t MachOBindEntry::readULEB128() {
1756 uint64_t Result = decodeULEB128(Ptr, &Count);
1758 if (Ptr > Opcodes.end()) {
1759 Ptr = Opcodes.end();
1765 int64_t MachOBindEntry::readSLEB128() {
1767 int64_t Result = decodeSLEB128(Ptr, &Count);
1769 if (Ptr > Opcodes.end()) {
1770 Ptr = Opcodes.end();
1777 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1779 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1781 StringRef MachOBindEntry::typeName() const {
1783 case MachO::BIND_TYPE_POINTER:
1785 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1786 return "text abs32";
1787 case MachO::BIND_TYPE_TEXT_PCREL32:
1788 return "text rel32";
1793 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1795 int64_t MachOBindEntry::addend() const { return Addend; }
1797 uint32_t MachOBindEntry::flags() const { return Flags; }
1799 int MachOBindEntry::ordinal() const { return Ordinal; }
1801 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1802 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1803 return (Ptr == Other.Ptr) &&
1804 (RemainingLoopCount == Other.RemainingLoopCount) &&
1805 (Done == Other.Done);
1808 iterator_range<bind_iterator>
1809 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1810 MachOBindEntry::Kind BKind) {
1811 MachOBindEntry Start(Opcodes, is64, BKind);
1812 Start.moveToFirst();
1814 MachOBindEntry Finish(Opcodes, is64, BKind);
1817 return iterator_range<bind_iterator>(bind_iterator(Start),
1818 bind_iterator(Finish));
1821 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1822 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1823 MachOBindEntry::Kind::Regular);
1826 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1827 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1828 MachOBindEntry::Kind::Lazy);
1831 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1832 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1833 MachOBindEntry::Kind::Weak);
1836 MachOObjectFile::load_command_iterator
1837 MachOObjectFile::begin_load_commands() const {
1838 return LoadCommands.begin();
1841 MachOObjectFile::load_command_iterator
1842 MachOObjectFile::end_load_commands() const {
1843 return LoadCommands.end();
1846 iterator_range<MachOObjectFile::load_command_iterator>
1847 MachOObjectFile::load_commands() const {
1848 return iterator_range<load_command_iterator>(begin_load_commands(),
1849 end_load_commands());
1853 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1854 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1855 return parseSegmentOrSectionName(Raw.data());
1859 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1860 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1861 const section_base *Base =
1862 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1863 return makeArrayRef(Base->sectname);
1867 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1868 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1869 const section_base *Base =
1870 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1871 return makeArrayRef(Base->segname);
1875 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1877 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1879 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1882 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1883 const MachO::any_relocation_info &RE) const {
1884 if (isLittleEndian())
1885 return RE.r_word1 & 0xffffff;
1886 return RE.r_word1 >> 8;
1889 bool MachOObjectFile::getPlainRelocationExternal(
1890 const MachO::any_relocation_info &RE) const {
1891 if (isLittleEndian())
1892 return (RE.r_word1 >> 27) & 1;
1893 return (RE.r_word1 >> 4) & 1;
1896 bool MachOObjectFile::getScatteredRelocationScattered(
1897 const MachO::any_relocation_info &RE) const {
1898 return RE.r_word0 >> 31;
1901 uint32_t MachOObjectFile::getScatteredRelocationValue(
1902 const MachO::any_relocation_info &RE) const {
1906 uint32_t MachOObjectFile::getScatteredRelocationType(
1907 const MachO::any_relocation_info &RE) const {
1908 return (RE.r_word0 >> 24) & 0xf;
1911 unsigned MachOObjectFile::getAnyRelocationAddress(
1912 const MachO::any_relocation_info &RE) const {
1913 if (isRelocationScattered(RE))
1914 return getScatteredRelocationAddress(RE);
1915 return getPlainRelocationAddress(RE);
1918 unsigned MachOObjectFile::getAnyRelocationPCRel(
1919 const MachO::any_relocation_info &RE) const {
1920 if (isRelocationScattered(RE))
1921 return getScatteredRelocationPCRel(this, RE);
1922 return getPlainRelocationPCRel(this, RE);
1925 unsigned MachOObjectFile::getAnyRelocationLength(
1926 const MachO::any_relocation_info &RE) const {
1927 if (isRelocationScattered(RE))
1928 return getScatteredRelocationLength(RE);
1929 return getPlainRelocationLength(this, RE);
1933 MachOObjectFile::getAnyRelocationType(
1934 const MachO::any_relocation_info &RE) const {
1935 if (isRelocationScattered(RE))
1936 return getScatteredRelocationType(RE);
1937 return getPlainRelocationType(this, RE);
1941 MachOObjectFile::getAnyRelocationSection(
1942 const MachO::any_relocation_info &RE) const {
1943 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1944 return *section_end();
1945 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1946 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1947 return *section_end();
1949 DRI.d.a = SecNum - 1;
1950 return SectionRef(DRI, this);
1953 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1954 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1955 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1958 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1959 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1960 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1963 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1964 unsigned Index) const {
1965 const char *Sec = getSectionPtr(this, L, Index);
1966 return getStruct<MachO::section>(this, Sec);
1969 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1970 unsigned Index) const {
1971 const char *Sec = getSectionPtr(this, L, Index);
1972 return getStruct<MachO::section_64>(this, Sec);
1976 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1977 const char *P = reinterpret_cast<const char *>(DRI.p);
1978 return getStruct<MachO::nlist>(this, P);
1982 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1983 const char *P = reinterpret_cast<const char *>(DRI.p);
1984 return getStruct<MachO::nlist_64>(this, P);
1987 MachO::linkedit_data_command
1988 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1989 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1992 MachO::segment_command
1993 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1994 return getStruct<MachO::segment_command>(this, L.Ptr);
1997 MachO::segment_command_64
1998 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1999 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2002 MachO::linker_option_command
2003 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2004 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2007 MachO::version_min_command
2008 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2009 return getStruct<MachO::version_min_command>(this, L.Ptr);
2012 MachO::dylib_command
2013 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2014 return getStruct<MachO::dylib_command>(this, L.Ptr);
2017 MachO::dyld_info_command
2018 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2019 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2022 MachO::dylinker_command
2023 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2024 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2028 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2029 return getStruct<MachO::uuid_command>(this, L.Ptr);
2032 MachO::rpath_command
2033 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2034 return getStruct<MachO::rpath_command>(this, L.Ptr);
2037 MachO::source_version_command
2038 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2039 return getStruct<MachO::source_version_command>(this, L.Ptr);
2042 MachO::entry_point_command
2043 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2044 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2047 MachO::encryption_info_command
2048 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2049 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2052 MachO::encryption_info_command_64
2053 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2054 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2057 MachO::sub_framework_command
2058 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2059 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2062 MachO::sub_umbrella_command
2063 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2064 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2067 MachO::sub_library_command
2068 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2069 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2072 MachO::sub_client_command
2073 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2074 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2077 MachO::routines_command
2078 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2079 return getStruct<MachO::routines_command>(this, L.Ptr);
2082 MachO::routines_command_64
2083 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2084 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2087 MachO::thread_command
2088 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::thread_command>(this, L.Ptr);
2092 MachO::any_relocation_info
2093 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2098 MachO::section_64 Sect = getSection64(Sec);
2099 Offset = Sect.reloff;
2101 MachO::section Sect = getSection(Sec);
2102 Offset = Sect.reloff;
2105 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2106 getPtr(this, Offset)) + Rel.d.b;
2107 return getStruct<MachO::any_relocation_info>(
2108 this, reinterpret_cast<const char *>(P));
2111 MachO::data_in_code_entry
2112 MachOObjectFile::getDice(DataRefImpl Rel) const {
2113 const char *P = reinterpret_cast<const char *>(Rel.p);
2114 return getStruct<MachO::data_in_code_entry>(this, P);
2117 const MachO::mach_header &MachOObjectFile::getHeader() const {
2121 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2126 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2127 const MachO::dysymtab_command &DLC,
2128 unsigned Index) const {
2129 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2130 return getStruct<uint32_t>(this, getPtr(this, Offset));
2133 MachO::data_in_code_entry
2134 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2135 unsigned Index) const {
2136 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2137 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2140 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2142 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2144 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2145 MachO::symtab_command Cmd;
2146 Cmd.cmd = MachO::LC_SYMTAB;
2147 Cmd.cmdsize = sizeof(MachO::symtab_command);
2155 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2156 if (DysymtabLoadCmd)
2157 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2159 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2160 MachO::dysymtab_command Cmd;
2161 Cmd.cmd = MachO::LC_DYSYMTAB;
2162 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2173 Cmd.extrefsymoff = 0;
2174 Cmd.nextrefsyms = 0;
2175 Cmd.indirectsymoff = 0;
2176 Cmd.nindirectsyms = 0;
2184 MachO::linkedit_data_command
2185 MachOObjectFile::getDataInCodeLoadCommand() const {
2186 if (DataInCodeLoadCmd)
2187 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2189 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2190 MachO::linkedit_data_command Cmd;
2191 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2192 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2198 MachO::linkedit_data_command
2199 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2200 if (LinkOptHintsLoadCmd)
2201 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2203 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2205 MachO::linkedit_data_command Cmd;
2206 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2207 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2213 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2214 if (!DyldInfoLoadCmd)
2215 return ArrayRef<uint8_t>();
2217 MachO::dyld_info_command DyldInfo
2218 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2219 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2220 getPtr(this, DyldInfo.rebase_off));
2221 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2224 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2225 if (!DyldInfoLoadCmd)
2226 return ArrayRef<uint8_t>();
2228 MachO::dyld_info_command DyldInfo
2229 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2230 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2231 getPtr(this, DyldInfo.bind_off));
2232 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2235 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2236 if (!DyldInfoLoadCmd)
2237 return ArrayRef<uint8_t>();
2239 MachO::dyld_info_command DyldInfo
2240 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2241 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2242 getPtr(this, DyldInfo.weak_bind_off));
2243 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2246 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2247 if (!DyldInfoLoadCmd)
2248 return ArrayRef<uint8_t>();
2250 MachO::dyld_info_command DyldInfo
2251 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2252 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2253 getPtr(this, DyldInfo.lazy_bind_off));
2254 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2257 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2258 if (!DyldInfoLoadCmd)
2259 return ArrayRef<uint8_t>();
2261 MachO::dyld_info_command DyldInfo
2262 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2263 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2264 getPtr(this, DyldInfo.export_off));
2265 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2268 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2270 return ArrayRef<uint8_t>();
2271 // Returning a pointer is fine as uuid doesn't need endian swapping.
2272 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2273 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2276 StringRef MachOObjectFile::getStringTableData() const {
2277 MachO::symtab_command S = getSymtabLoadCommand();
2278 return getData().substr(S.stroff, S.strsize);
2281 bool MachOObjectFile::is64Bit() const {
2282 return getType() == getMachOType(false, true) ||
2283 getType() == getMachOType(true, true);
2286 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2287 SmallVectorImpl<uint64_t> &Out) const {
2288 DataExtractor extractor(ObjectFile::getData(), true, 0);
2290 uint32_t offset = Index;
2292 while (uint64_t delta = extractor.getULEB128(&offset)) {
2294 Out.push_back(data);
2298 bool MachOObjectFile::isRelocatableObject() const {
2299 return getHeader().filetype == MachO::MH_OBJECT;
2302 ErrorOr<std::unique_ptr<MachOObjectFile>>
2303 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2304 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2306 std::unique_ptr<MachOObjectFile> Ret;
2307 if (Magic == "\xFE\xED\xFA\xCE")
2308 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2309 else if (Magic == "\xCE\xFA\xED\xFE")
2310 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2311 else if (Magic == "\xFE\xED\xFA\xCF")
2312 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2313 else if (Magic == "\xCF\xFA\xED\xFE")
2314 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2316 return object_error::parse_failed;
2320 return std::move(Ret);