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_UNDF)
422 Result |= SymbolRef::SF_Undefined;
424 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
425 Result |= SymbolRef::SF_Indirect;
427 if (MachOType & MachO::N_STAB)
428 Result |= SymbolRef::SF_FormatSpecific;
430 if (MachOType & MachO::N_EXT) {
431 Result |= SymbolRef::SF_Global;
432 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
434 Result |= SymbolRef::SF_Common;
437 if (!(MachOType & MachO::N_PEXT))
438 Result |= SymbolRef::SF_Exported;
441 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
442 Result |= SymbolRef::SF_Weak;
444 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
445 Result |= SymbolRef::SF_Thumb;
447 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
448 Result |= SymbolRef::SF_Absolute;
453 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
454 section_iterator &Res) const {
455 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
456 uint8_t index = Entry.n_sect;
463 if (DRI.d.a >= Sections.size())
464 report_fatal_error("getSymbolSection: Invalid section index.");
465 Res = section_iterator(SectionRef(DRI, this));
468 return std::error_code();
471 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
472 MachO::nlist_base Entry =
473 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
474 return Entry.n_sect - 1;
477 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
481 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
482 StringRef &Result) const {
483 ArrayRef<char> Raw = getSectionRawName(Sec);
484 Result = parseSegmentOrSectionName(Raw.data());
485 return std::error_code();
488 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
490 return getSection64(Sec).addr;
491 return getSection(Sec).addr;
494 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
496 return getSection64(Sec).size;
497 return getSection(Sec).size;
500 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
501 StringRef &Res) const {
506 MachO::section_64 Sect = getSection64(Sec);
507 Offset = Sect.offset;
510 MachO::section Sect = getSection(Sec);
511 Offset = Sect.offset;
515 Res = this->getData().substr(Offset, Size);
516 return std::error_code();
519 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
522 MachO::section_64 Sect = getSection64(Sec);
525 MachO::section Sect = getSection(Sec);
529 return uint64_t(1) << Align;
532 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
533 uint32_t Flags = getSectionFlags(this, Sec);
534 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
537 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
538 uint32_t Flags = getSectionFlags(this, Sec);
539 unsigned SectionType = Flags & MachO::SECTION_TYPE;
540 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
541 !(SectionType == MachO::S_ZEROFILL ||
542 SectionType == MachO::S_GB_ZEROFILL);
545 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
546 uint32_t Flags = getSectionFlags(this, Sec);
547 unsigned SectionType = Flags & MachO::SECTION_TYPE;
548 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
549 (SectionType == MachO::S_ZEROFILL ||
550 SectionType == MachO::S_GB_ZEROFILL);
553 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
554 return Sec.getRawDataRefImpl().d.a;
557 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
558 // FIXME: Unimplemented.
562 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
566 return relocation_iterator(RelocationRef(Ret, this));
570 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
573 MachO::section_64 Sect = getSection64(Sec);
576 MachO::section Sect = getSection(Sec);
583 return relocation_iterator(RelocationRef(Ret, this));
586 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
590 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
591 assert(getHeader().filetype == MachO::MH_OBJECT &&
592 "Only implemented for MH_OBJECT");
593 MachO::any_relocation_info RE = getRelocation(Rel);
594 return getAnyRelocationAddress(RE);
598 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
599 MachO::any_relocation_info RE = getRelocation(Rel);
600 if (isRelocationScattered(RE))
603 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
604 bool isExtern = getPlainRelocationExternal(RE);
608 MachO::symtab_command S = getSymtabLoadCommand();
609 unsigned SymbolTableEntrySize = is64Bit() ?
610 sizeof(MachO::nlist_64) :
611 sizeof(MachO::nlist);
612 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
614 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
615 return symbol_iterator(SymbolRef(Sym, this));
619 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
620 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
623 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
624 MachO::any_relocation_info RE = getRelocation(Rel);
625 return getAnyRelocationType(RE);
628 void MachOObjectFile::getRelocationTypeName(
629 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
631 uint64_t RType = getRelocationType(Rel);
633 unsigned Arch = this->getArch();
637 static const char *const Table[] = {
638 "GENERIC_RELOC_VANILLA",
639 "GENERIC_RELOC_PAIR",
640 "GENERIC_RELOC_SECTDIFF",
641 "GENERIC_RELOC_PB_LA_PTR",
642 "GENERIC_RELOC_LOCAL_SECTDIFF",
643 "GENERIC_RELOC_TLV" };
651 case Triple::x86_64: {
652 static const char *const Table[] = {
653 "X86_64_RELOC_UNSIGNED",
654 "X86_64_RELOC_SIGNED",
655 "X86_64_RELOC_BRANCH",
656 "X86_64_RELOC_GOT_LOAD",
658 "X86_64_RELOC_SUBTRACTOR",
659 "X86_64_RELOC_SIGNED_1",
660 "X86_64_RELOC_SIGNED_2",
661 "X86_64_RELOC_SIGNED_4",
662 "X86_64_RELOC_TLV" };
671 static const char *const Table[] = {
674 "ARM_RELOC_SECTDIFF",
675 "ARM_RELOC_LOCAL_SECTDIFF",
676 "ARM_RELOC_PB_LA_PTR",
678 "ARM_THUMB_RELOC_BR22",
679 "ARM_THUMB_32BIT_BRANCH",
681 "ARM_RELOC_HALF_SECTDIFF" };
689 case Triple::aarch64: {
690 static const char *const Table[] = {
691 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
692 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
693 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
694 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
695 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
699 if (RType >= array_lengthof(Table))
706 static const char *const Table[] = {
715 "PPC_RELOC_SECTDIFF",
716 "PPC_RELOC_PB_LA_PTR",
717 "PPC_RELOC_HI16_SECTDIFF",
718 "PPC_RELOC_LO16_SECTDIFF",
719 "PPC_RELOC_HA16_SECTDIFF",
721 "PPC_RELOC_LO14_SECTDIFF",
722 "PPC_RELOC_LOCAL_SECTDIFF" };
730 case Triple::UnknownArch:
734 Result.append(res.begin(), res.end());
737 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
738 MachO::any_relocation_info RE = getRelocation(Rel);
739 return getAnyRelocationLength(RE);
743 // guessLibraryShortName() is passed a name of a dynamic library and returns a
744 // guess on what the short name is. Then name is returned as a substring of the
745 // StringRef Name passed in. The name of the dynamic library is recognized as
746 // a framework if it has one of the two following forms:
747 // Foo.framework/Versions/A/Foo
749 // Where A and Foo can be any string. And may contain a trailing suffix
750 // starting with an underbar. If the Name is recognized as a framework then
751 // isFramework is set to true else it is set to false. If the Name has a
752 // suffix then Suffix is set to the substring in Name that contains the suffix
753 // else it is set to a NULL StringRef.
755 // The Name of the dynamic library is recognized as a library name if it has
756 // one of the two following forms:
759 // The library may have a suffix trailing the name Foo of the form:
760 // libFoo_profile.A.dylib
761 // libFoo_profile.dylib
763 // The Name of the dynamic library is also recognized as a library name if it
764 // has the following form:
767 // If the Name of the dynamic library is none of the forms above then a NULL
768 // StringRef is returned.
770 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
773 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
774 size_t a, b, c, d, Idx;
777 Suffix = StringRef();
779 // Pull off the last component and make Foo point to it
781 if (a == Name.npos || a == 0)
783 Foo = Name.slice(a+1, Name.npos);
785 // Look for a suffix starting with a '_'
786 Idx = Foo.rfind('_');
787 if (Idx != Foo.npos && Foo.size() >= 2) {
788 Suffix = Foo.slice(Idx, Foo.npos);
789 Foo = Foo.slice(0, Idx);
792 // First look for the form Foo.framework/Foo
793 b = Name.rfind('/', a);
798 F = Name.slice(Idx, Idx + Foo.size());
799 DotFramework = Name.slice(Idx + Foo.size(),
800 Idx + Foo.size() + sizeof(".framework/")-1);
801 if (F == Foo && DotFramework == ".framework/") {
806 // Next look for the form Foo.framework/Versions/A/Foo
809 c = Name.rfind('/', b);
810 if (c == Name.npos || c == 0)
812 V = Name.slice(c+1, Name.npos);
813 if (!V.startswith("Versions/"))
815 d = Name.rfind('/', c);
820 F = Name.slice(Idx, Idx + Foo.size());
821 DotFramework = Name.slice(Idx + Foo.size(),
822 Idx + Foo.size() + sizeof(".framework/")-1);
823 if (F == Foo && DotFramework == ".framework/") {
829 // pull off the suffix after the "." and make a point to it
831 if (a == Name.npos || a == 0)
833 Dylib = Name.slice(a, Name.npos);
834 if (Dylib != ".dylib")
837 // First pull off the version letter for the form Foo.A.dylib if any.
839 Dot = Name.slice(a-2, a-1);
844 b = Name.rfind('/', a);
849 // ignore any suffix after an underbar like Foo_profile.A.dylib
850 Idx = Name.find('_', b);
851 if (Idx != Name.npos && Idx != b) {
852 Lib = Name.slice(b, Idx);
853 Suffix = Name.slice(Idx, a);
856 Lib = Name.slice(b, a);
857 // There are incorrect library names of the form:
858 // libATS.A_profile.dylib so check for these.
859 if (Lib.size() >= 3) {
860 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
862 Lib = Lib.slice(0, Lib.size()-2);
867 Qtx = Name.slice(a, Name.npos);
870 b = Name.rfind('/', a);
872 Lib = Name.slice(0, a);
874 Lib = Name.slice(b+1, a);
875 // There are library names of the form: QT.A.qtx so check for these.
876 if (Lib.size() >= 3) {
877 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
879 Lib = Lib.slice(0, Lib.size()-2);
884 // getLibraryShortNameByIndex() is used to get the short name of the library
885 // for an undefined symbol in a linked Mach-O binary that was linked with the
886 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
887 // It is passed the index (0 - based) of the library as translated from
888 // GET_LIBRARY_ORDINAL (1 - based).
889 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
890 StringRef &Res) const {
891 if (Index >= Libraries.size())
892 return object_error::parse_failed;
894 // If the cache of LibrariesShortNames is not built up do that first for
895 // all the Libraries.
896 if (LibrariesShortNames.size() == 0) {
897 for (unsigned i = 0; i < Libraries.size(); i++) {
898 MachO::dylib_command D =
899 getStruct<MachO::dylib_command>(this, Libraries[i]);
900 if (D.dylib.name >= D.cmdsize)
901 return object_error::parse_failed;
902 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
903 StringRef Name = StringRef(P);
904 if (D.dylib.name+Name.size() >= D.cmdsize)
905 return object_error::parse_failed;
908 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
909 if (shortName.empty())
910 LibrariesShortNames.push_back(Name);
912 LibrariesShortNames.push_back(shortName);
916 Res = LibrariesShortNames[Index];
917 return std::error_code();
921 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
923 Sec.d.a = Rel->getRawDataRefImpl().d.a;
924 return section_iterator(SectionRef(Sec, this));
927 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
928 return getSymbolByIndex(0);
931 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
934 return basic_symbol_iterator(SymbolRef(DRI, this));
936 MachO::symtab_command Symtab = getSymtabLoadCommand();
937 unsigned SymbolTableEntrySize = is64Bit() ?
938 sizeof(MachO::nlist_64) :
939 sizeof(MachO::nlist);
940 unsigned Offset = Symtab.symoff +
941 Symtab.nsyms * SymbolTableEntrySize;
942 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
943 return basic_symbol_iterator(SymbolRef(DRI, this));
946 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
949 return basic_symbol_iterator(SymbolRef(DRI, this));
951 MachO::symtab_command Symtab = getSymtabLoadCommand();
952 if (Index >= Symtab.nsyms)
953 report_fatal_error("Requested symbol index is out of range.");
954 unsigned SymbolTableEntrySize =
955 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
956 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
957 DRI.p += Index * SymbolTableEntrySize;
958 return basic_symbol_iterator(SymbolRef(DRI, this));
961 section_iterator MachOObjectFile::section_begin() const {
963 return section_iterator(SectionRef(DRI, this));
966 section_iterator MachOObjectFile::section_end() const {
968 DRI.d.a = Sections.size();
969 return section_iterator(SectionRef(DRI, this));
972 uint8_t MachOObjectFile::getBytesInAddress() const {
973 return is64Bit() ? 8 : 4;
976 StringRef MachOObjectFile::getFileFormatName() const {
977 unsigned CPUType = getCPUType(this);
980 case llvm::MachO::CPU_TYPE_I386:
981 return "Mach-O 32-bit i386";
982 case llvm::MachO::CPU_TYPE_ARM:
984 case llvm::MachO::CPU_TYPE_POWERPC:
985 return "Mach-O 32-bit ppc";
987 return "Mach-O 32-bit unknown";
992 case llvm::MachO::CPU_TYPE_X86_64:
993 return "Mach-O 64-bit x86-64";
994 case llvm::MachO::CPU_TYPE_ARM64:
995 return "Mach-O arm64";
996 case llvm::MachO::CPU_TYPE_POWERPC64:
997 return "Mach-O 64-bit ppc64";
999 return "Mach-O 64-bit unknown";
1003 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1005 case llvm::MachO::CPU_TYPE_I386:
1007 case llvm::MachO::CPU_TYPE_X86_64:
1008 return Triple::x86_64;
1009 case llvm::MachO::CPU_TYPE_ARM:
1011 case llvm::MachO::CPU_TYPE_ARM64:
1012 return Triple::aarch64;
1013 case llvm::MachO::CPU_TYPE_POWERPC:
1015 case llvm::MachO::CPU_TYPE_POWERPC64:
1016 return Triple::ppc64;
1018 return Triple::UnknownArch;
1022 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1023 const char **McpuDefault) {
1025 *McpuDefault = nullptr;
1028 case MachO::CPU_TYPE_I386:
1029 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1030 case MachO::CPU_SUBTYPE_I386_ALL:
1031 return Triple("i386-apple-darwin");
1035 case MachO::CPU_TYPE_X86_64:
1036 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1037 case MachO::CPU_SUBTYPE_X86_64_ALL:
1038 return Triple("x86_64-apple-darwin");
1039 case MachO::CPU_SUBTYPE_X86_64_H:
1040 return Triple("x86_64h-apple-darwin");
1044 case MachO::CPU_TYPE_ARM:
1045 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1046 case MachO::CPU_SUBTYPE_ARM_V4T:
1047 return Triple("armv4t-apple-darwin");
1048 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1049 return Triple("armv5e-apple-darwin");
1050 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1051 return Triple("xscale-apple-darwin");
1052 case MachO::CPU_SUBTYPE_ARM_V6:
1053 return Triple("armv6-apple-darwin");
1054 case MachO::CPU_SUBTYPE_ARM_V6M:
1056 *McpuDefault = "cortex-m0";
1057 return Triple("armv6m-apple-darwin");
1058 case MachO::CPU_SUBTYPE_ARM_V7:
1059 return Triple("armv7-apple-darwin");
1060 case MachO::CPU_SUBTYPE_ARM_V7EM:
1062 *McpuDefault = "cortex-m4";
1063 return Triple("armv7em-apple-darwin");
1064 case MachO::CPU_SUBTYPE_ARM_V7K:
1065 return Triple("armv7k-apple-darwin");
1066 case MachO::CPU_SUBTYPE_ARM_V7M:
1068 *McpuDefault = "cortex-m3";
1069 return Triple("armv7m-apple-darwin");
1070 case MachO::CPU_SUBTYPE_ARM_V7S:
1071 return Triple("armv7s-apple-darwin");
1075 case MachO::CPU_TYPE_ARM64:
1076 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1077 case MachO::CPU_SUBTYPE_ARM64_ALL:
1078 return Triple("arm64-apple-darwin");
1082 case MachO::CPU_TYPE_POWERPC:
1083 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1084 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1085 return Triple("ppc-apple-darwin");
1089 case MachO::CPU_TYPE_POWERPC64:
1090 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1091 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1092 return Triple("ppc64-apple-darwin");
1101 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1102 const char **McpuDefault) {
1104 *McpuDefault = nullptr;
1107 case MachO::CPU_TYPE_ARM:
1108 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1109 case MachO::CPU_SUBTYPE_ARM_V4T:
1110 return Triple("thumbv4t-apple-darwin");
1111 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1112 return Triple("thumbv5e-apple-darwin");
1113 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1114 return Triple("xscale-apple-darwin");
1115 case MachO::CPU_SUBTYPE_ARM_V6:
1116 return Triple("thumbv6-apple-darwin");
1117 case MachO::CPU_SUBTYPE_ARM_V6M:
1119 *McpuDefault = "cortex-m0";
1120 return Triple("thumbv6m-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V7:
1122 return Triple("thumbv7-apple-darwin");
1123 case MachO::CPU_SUBTYPE_ARM_V7EM:
1125 *McpuDefault = "cortex-m4";
1126 return Triple("thumbv7em-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V7K:
1128 return Triple("thumbv7k-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V7M:
1131 *McpuDefault = "cortex-m3";
1132 return Triple("thumbv7m-apple-darwin");
1133 case MachO::CPU_SUBTYPE_ARM_V7S:
1134 return Triple("thumbv7s-apple-darwin");
1143 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1144 const char **McpuDefault,
1145 Triple *ThumbTriple) {
1146 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1147 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1152 Triple MachOObjectFile::getHostArch() {
1153 return Triple(sys::getDefaultTargetTriple());
1156 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1157 return StringSwitch<bool>(ArchFlag)
1159 .Case("x86_64", true)
1160 .Case("x86_64h", true)
1161 .Case("armv4t", true)
1163 .Case("armv5e", true)
1164 .Case("armv6", true)
1165 .Case("armv6m", true)
1166 .Case("armv7", true)
1167 .Case("armv7em", true)
1168 .Case("armv7k", true)
1169 .Case("armv7m", true)
1170 .Case("armv7s", true)
1171 .Case("arm64", true)
1173 .Case("ppc64", true)
1177 unsigned MachOObjectFile::getArch() const {
1178 return getArch(getCPUType(this));
1181 Triple MachOObjectFile::getArch(const char **McpuDefault,
1182 Triple *ThumbTriple) const {
1183 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1184 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1187 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1190 return section_rel_begin(DRI);
1193 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1196 return section_rel_end(DRI);
1199 dice_iterator MachOObjectFile::begin_dices() const {
1201 if (!DataInCodeLoadCmd)
1202 return dice_iterator(DiceRef(DRI, this));
1204 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1205 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1206 return dice_iterator(DiceRef(DRI, this));
1209 dice_iterator MachOObjectFile::end_dices() const {
1211 if (!DataInCodeLoadCmd)
1212 return dice_iterator(DiceRef(DRI, this));
1214 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1215 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1216 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1217 return dice_iterator(DiceRef(DRI, this));
1220 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1221 : Trie(T), Malformed(false), Done(false) { }
1223 void ExportEntry::moveToFirst() {
1225 pushDownUntilBottom();
1228 void ExportEntry::moveToEnd() {
1233 bool ExportEntry::operator==(const ExportEntry &Other) const {
1234 // Common case, one at end, other iterating from begin.
1235 if (Done || Other.Done)
1236 return (Done == Other.Done);
1237 // Not equal if different stack sizes.
1238 if (Stack.size() != Other.Stack.size())
1240 // Not equal if different cumulative strings.
1241 if (!CumulativeString.equals(Other.CumulativeString))
1243 // Equal if all nodes in both stacks match.
1244 for (unsigned i=0; i < Stack.size(); ++i) {
1245 if (Stack[i].Start != Other.Stack[i].Start)
1251 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1253 uint64_t Result = decodeULEB128(Ptr, &Count);
1255 if (Ptr > Trie.end()) {
1262 StringRef ExportEntry::name() const {
1263 return CumulativeString;
1266 uint64_t ExportEntry::flags() const {
1267 return Stack.back().Flags;
1270 uint64_t ExportEntry::address() const {
1271 return Stack.back().Address;
1274 uint64_t ExportEntry::other() const {
1275 return Stack.back().Other;
1278 StringRef ExportEntry::otherName() const {
1279 const char* ImportName = Stack.back().ImportName;
1281 return StringRef(ImportName);
1285 uint32_t ExportEntry::nodeOffset() const {
1286 return Stack.back().Start - Trie.begin();
1289 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1290 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1291 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1292 ParentStringLength(0), IsExportNode(false) {
1295 void ExportEntry::pushNode(uint64_t offset) {
1296 const uint8_t *Ptr = Trie.begin() + offset;
1297 NodeState State(Ptr);
1298 uint64_t ExportInfoSize = readULEB128(State.Current);
1299 State.IsExportNode = (ExportInfoSize != 0);
1300 const uint8_t* Children = State.Current + ExportInfoSize;
1301 if (State.IsExportNode) {
1302 State.Flags = readULEB128(State.Current);
1303 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1305 State.Other = readULEB128(State.Current); // dylib ordinal
1306 State.ImportName = reinterpret_cast<const char*>(State.Current);
1308 State.Address = readULEB128(State.Current);
1309 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1310 State.Other = readULEB128(State.Current);
1313 State.ChildCount = *Children;
1314 State.Current = Children + 1;
1315 State.NextChildIndex = 0;
1316 State.ParentStringLength = CumulativeString.size();
1317 Stack.push_back(State);
1320 void ExportEntry::pushDownUntilBottom() {
1321 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1322 NodeState &Top = Stack.back();
1323 CumulativeString.resize(Top.ParentStringLength);
1324 for (;*Top.Current != 0; Top.Current++) {
1325 char C = *Top.Current;
1326 CumulativeString.push_back(C);
1329 uint64_t childNodeIndex = readULEB128(Top.Current);
1330 Top.NextChildIndex += 1;
1331 pushNode(childNodeIndex);
1333 if (!Stack.back().IsExportNode) {
1339 // We have a trie data structure and need a way to walk it that is compatible
1340 // with the C++ iterator model. The solution is a non-recursive depth first
1341 // traversal where the iterator contains a stack of parent nodes along with a
1342 // string that is the accumulation of all edge strings along the parent chain
1345 // There is one "export" node for each exported symbol. But because some
1346 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1347 // node may have child nodes too.
1349 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1350 // child until hitting a node with no children (which is an export node or
1351 // else the trie is malformed). On the way down, each node is pushed on the
1352 // stack ivar. If there is no more ways down, it pops up one and tries to go
1353 // down a sibling path until a childless node is reached.
1354 void ExportEntry::moveNext() {
1355 if (Stack.empty() || !Stack.back().IsExportNode) {
1362 while (!Stack.empty()) {
1363 NodeState &Top = Stack.back();
1364 if (Top.NextChildIndex < Top.ChildCount) {
1365 pushDownUntilBottom();
1366 // Now at the next export node.
1369 if (Top.IsExportNode) {
1370 // This node has no children but is itself an export node.
1371 CumulativeString.resize(Top.ParentStringLength);
1380 iterator_range<export_iterator>
1381 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1382 ExportEntry Start(Trie);
1383 if (Trie.size() == 0)
1386 Start.moveToFirst();
1388 ExportEntry Finish(Trie);
1391 return iterator_range<export_iterator>(export_iterator(Start),
1392 export_iterator(Finish));
1395 iterator_range<export_iterator> MachOObjectFile::exports() const {
1396 return exports(getDyldInfoExportsTrie());
1400 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1401 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1402 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1403 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1405 void MachORebaseEntry::moveToFirst() {
1406 Ptr = Opcodes.begin();
1410 void MachORebaseEntry::moveToEnd() {
1411 Ptr = Opcodes.end();
1412 RemainingLoopCount = 0;
1416 void MachORebaseEntry::moveNext() {
1417 // If in the middle of some loop, move to next rebasing in loop.
1418 SegmentOffset += AdvanceAmount;
1419 if (RemainingLoopCount) {
1420 --RemainingLoopCount;
1423 if (Ptr == Opcodes.end()) {
1428 while (More && !Malformed) {
1429 // Parse next opcode and set up next loop.
1430 uint8_t Byte = *Ptr++;
1431 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1432 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1434 case MachO::REBASE_OPCODE_DONE:
1438 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1440 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1441 RebaseType = ImmValue;
1444 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1445 << "RebaseType=" << (int) RebaseType << "\n");
1447 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1448 SegmentIndex = ImmValue;
1449 SegmentOffset = readULEB128();
1452 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1453 << "SegmentIndex=" << SegmentIndex << ", "
1454 << format("SegmentOffset=0x%06X", SegmentOffset)
1457 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1458 SegmentOffset += readULEB128();
1459 DEBUG_WITH_TYPE("mach-o-rebase",
1460 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1461 << format("SegmentOffset=0x%06X",
1462 SegmentOffset) << "\n");
1464 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1465 SegmentOffset += ImmValue * PointerSize;
1466 DEBUG_WITH_TYPE("mach-o-rebase",
1467 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1468 << format("SegmentOffset=0x%06X",
1469 SegmentOffset) << "\n");
1471 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1472 AdvanceAmount = PointerSize;
1473 RemainingLoopCount = ImmValue - 1;
1476 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1477 << format("SegmentOffset=0x%06X", SegmentOffset)
1478 << ", AdvanceAmount=" << AdvanceAmount
1479 << ", RemainingLoopCount=" << RemainingLoopCount
1482 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1483 AdvanceAmount = PointerSize;
1484 RemainingLoopCount = readULEB128() - 1;
1487 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1488 << format("SegmentOffset=0x%06X", SegmentOffset)
1489 << ", AdvanceAmount=" << AdvanceAmount
1490 << ", RemainingLoopCount=" << RemainingLoopCount
1493 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1494 AdvanceAmount = readULEB128() + PointerSize;
1495 RemainingLoopCount = 0;
1498 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1499 << format("SegmentOffset=0x%06X", SegmentOffset)
1500 << ", AdvanceAmount=" << AdvanceAmount
1501 << ", RemainingLoopCount=" << RemainingLoopCount
1504 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1505 RemainingLoopCount = readULEB128() - 1;
1506 AdvanceAmount = readULEB128() + PointerSize;
1509 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1510 << format("SegmentOffset=0x%06X", SegmentOffset)
1511 << ", AdvanceAmount=" << AdvanceAmount
1512 << ", RemainingLoopCount=" << RemainingLoopCount
1521 uint64_t MachORebaseEntry::readULEB128() {
1523 uint64_t Result = decodeULEB128(Ptr, &Count);
1525 if (Ptr > Opcodes.end()) {
1526 Ptr = Opcodes.end();
1532 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1534 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1536 StringRef MachORebaseEntry::typeName() const {
1537 switch (RebaseType) {
1538 case MachO::REBASE_TYPE_POINTER:
1540 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1541 return "text abs32";
1542 case MachO::REBASE_TYPE_TEXT_PCREL32:
1543 return "text rel32";
1548 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1549 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1550 return (Ptr == Other.Ptr) &&
1551 (RemainingLoopCount == Other.RemainingLoopCount) &&
1552 (Done == Other.Done);
1555 iterator_range<rebase_iterator>
1556 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1557 MachORebaseEntry Start(Opcodes, is64);
1558 Start.moveToFirst();
1560 MachORebaseEntry Finish(Opcodes, is64);
1563 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1564 rebase_iterator(Finish));
1567 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1568 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1572 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1574 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1575 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1576 BindType(0), PointerSize(is64Bit ? 8 : 4),
1577 TableKind(BK), Malformed(false), Done(false) {}
1579 void MachOBindEntry::moveToFirst() {
1580 Ptr = Opcodes.begin();
1584 void MachOBindEntry::moveToEnd() {
1585 Ptr = Opcodes.end();
1586 RemainingLoopCount = 0;
1590 void MachOBindEntry::moveNext() {
1591 // If in the middle of some loop, move to next binding in loop.
1592 SegmentOffset += AdvanceAmount;
1593 if (RemainingLoopCount) {
1594 --RemainingLoopCount;
1597 if (Ptr == Opcodes.end()) {
1602 while (More && !Malformed) {
1603 // Parse next opcode and set up next loop.
1604 uint8_t Byte = *Ptr++;
1605 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1606 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1607 int8_t SignExtended;
1608 const uint8_t *SymStart;
1610 case MachO::BIND_OPCODE_DONE:
1611 if (TableKind == Kind::Lazy) {
1612 // Lazying bindings have a DONE opcode between entries. Need to ignore
1613 // it to advance to next entry. But need not if this is last entry.
1614 bool NotLastEntry = false;
1615 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1617 NotLastEntry = true;
1626 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1628 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1632 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1633 << "Ordinal=" << Ordinal << "\n");
1635 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1636 Ordinal = readULEB128();
1639 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1640 << "Ordinal=" << Ordinal << "\n");
1642 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1644 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1645 Ordinal = SignExtended;
1650 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1651 << "Ordinal=" << Ordinal << "\n");
1653 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1659 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1664 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1665 << "SymbolName=" << SymbolName << "\n");
1666 if (TableKind == Kind::Weak) {
1667 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1671 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1672 BindType = ImmValue;
1675 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1676 << "BindType=" << (int)BindType << "\n");
1678 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1679 Addend = readSLEB128();
1680 if (TableKind == Kind::Lazy)
1684 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1685 << "Addend=" << Addend << "\n");
1687 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1688 SegmentIndex = ImmValue;
1689 SegmentOffset = readULEB128();
1692 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1693 << "SegmentIndex=" << SegmentIndex << ", "
1694 << format("SegmentOffset=0x%06X", SegmentOffset)
1697 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1698 SegmentOffset += readULEB128();
1699 DEBUG_WITH_TYPE("mach-o-bind",
1700 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1701 << format("SegmentOffset=0x%06X",
1702 SegmentOffset) << "\n");
1704 case MachO::BIND_OPCODE_DO_BIND:
1705 AdvanceAmount = PointerSize;
1706 RemainingLoopCount = 0;
1707 DEBUG_WITH_TYPE("mach-o-bind",
1708 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1709 << format("SegmentOffset=0x%06X",
1710 SegmentOffset) << "\n");
1712 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1713 AdvanceAmount = readULEB128() + PointerSize;
1714 RemainingLoopCount = 0;
1715 if (TableKind == Kind::Lazy)
1719 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1720 << format("SegmentOffset=0x%06X", SegmentOffset)
1721 << ", AdvanceAmount=" << AdvanceAmount
1722 << ", RemainingLoopCount=" << RemainingLoopCount
1725 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1726 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1727 RemainingLoopCount = 0;
1728 if (TableKind == Kind::Lazy)
1730 DEBUG_WITH_TYPE("mach-o-bind",
1732 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1733 << format("SegmentOffset=0x%06X",
1734 SegmentOffset) << "\n");
1736 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1737 RemainingLoopCount = readULEB128() - 1;
1738 AdvanceAmount = readULEB128() + PointerSize;
1739 if (TableKind == Kind::Lazy)
1743 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1744 << format("SegmentOffset=0x%06X", SegmentOffset)
1745 << ", AdvanceAmount=" << AdvanceAmount
1746 << ", RemainingLoopCount=" << RemainingLoopCount
1755 uint64_t MachOBindEntry::readULEB128() {
1757 uint64_t Result = decodeULEB128(Ptr, &Count);
1759 if (Ptr > Opcodes.end()) {
1760 Ptr = Opcodes.end();
1766 int64_t MachOBindEntry::readSLEB128() {
1768 int64_t Result = decodeSLEB128(Ptr, &Count);
1770 if (Ptr > Opcodes.end()) {
1771 Ptr = Opcodes.end();
1778 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1780 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1782 StringRef MachOBindEntry::typeName() const {
1784 case MachO::BIND_TYPE_POINTER:
1786 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1787 return "text abs32";
1788 case MachO::BIND_TYPE_TEXT_PCREL32:
1789 return "text rel32";
1794 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1796 int64_t MachOBindEntry::addend() const { return Addend; }
1798 uint32_t MachOBindEntry::flags() const { return Flags; }
1800 int MachOBindEntry::ordinal() const { return Ordinal; }
1802 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1803 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1804 return (Ptr == Other.Ptr) &&
1805 (RemainingLoopCount == Other.RemainingLoopCount) &&
1806 (Done == Other.Done);
1809 iterator_range<bind_iterator>
1810 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1811 MachOBindEntry::Kind BKind) {
1812 MachOBindEntry Start(Opcodes, is64, BKind);
1813 Start.moveToFirst();
1815 MachOBindEntry Finish(Opcodes, is64, BKind);
1818 return iterator_range<bind_iterator>(bind_iterator(Start),
1819 bind_iterator(Finish));
1822 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1823 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1824 MachOBindEntry::Kind::Regular);
1827 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1828 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1829 MachOBindEntry::Kind::Lazy);
1832 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1833 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1834 MachOBindEntry::Kind::Weak);
1837 MachOObjectFile::load_command_iterator
1838 MachOObjectFile::begin_load_commands() const {
1839 return LoadCommands.begin();
1842 MachOObjectFile::load_command_iterator
1843 MachOObjectFile::end_load_commands() const {
1844 return LoadCommands.end();
1847 iterator_range<MachOObjectFile::load_command_iterator>
1848 MachOObjectFile::load_commands() const {
1849 return iterator_range<load_command_iterator>(begin_load_commands(),
1850 end_load_commands());
1854 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1855 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1856 return parseSegmentOrSectionName(Raw.data());
1860 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1861 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1862 const section_base *Base =
1863 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1864 return makeArrayRef(Base->sectname);
1868 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1869 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1870 const section_base *Base =
1871 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1872 return makeArrayRef(Base->segname);
1876 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1878 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1880 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1883 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1884 const MachO::any_relocation_info &RE) const {
1885 if (isLittleEndian())
1886 return RE.r_word1 & 0xffffff;
1887 return RE.r_word1 >> 8;
1890 bool MachOObjectFile::getPlainRelocationExternal(
1891 const MachO::any_relocation_info &RE) const {
1892 if (isLittleEndian())
1893 return (RE.r_word1 >> 27) & 1;
1894 return (RE.r_word1 >> 4) & 1;
1897 bool MachOObjectFile::getScatteredRelocationScattered(
1898 const MachO::any_relocation_info &RE) const {
1899 return RE.r_word0 >> 31;
1902 uint32_t MachOObjectFile::getScatteredRelocationValue(
1903 const MachO::any_relocation_info &RE) const {
1907 uint32_t MachOObjectFile::getScatteredRelocationType(
1908 const MachO::any_relocation_info &RE) const {
1909 return (RE.r_word0 >> 24) & 0xf;
1912 unsigned MachOObjectFile::getAnyRelocationAddress(
1913 const MachO::any_relocation_info &RE) const {
1914 if (isRelocationScattered(RE))
1915 return getScatteredRelocationAddress(RE);
1916 return getPlainRelocationAddress(RE);
1919 unsigned MachOObjectFile::getAnyRelocationPCRel(
1920 const MachO::any_relocation_info &RE) const {
1921 if (isRelocationScattered(RE))
1922 return getScatteredRelocationPCRel(this, RE);
1923 return getPlainRelocationPCRel(this, RE);
1926 unsigned MachOObjectFile::getAnyRelocationLength(
1927 const MachO::any_relocation_info &RE) const {
1928 if (isRelocationScattered(RE))
1929 return getScatteredRelocationLength(RE);
1930 return getPlainRelocationLength(this, RE);
1934 MachOObjectFile::getAnyRelocationType(
1935 const MachO::any_relocation_info &RE) const {
1936 if (isRelocationScattered(RE))
1937 return getScatteredRelocationType(RE);
1938 return getPlainRelocationType(this, RE);
1942 MachOObjectFile::getAnyRelocationSection(
1943 const MachO::any_relocation_info &RE) const {
1944 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1945 return *section_end();
1946 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1947 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1948 return *section_end();
1950 DRI.d.a = SecNum - 1;
1951 return SectionRef(DRI, this);
1954 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1955 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1956 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1959 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1960 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1961 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1964 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1965 unsigned Index) const {
1966 const char *Sec = getSectionPtr(this, L, Index);
1967 return getStruct<MachO::section>(this, Sec);
1970 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1971 unsigned Index) const {
1972 const char *Sec = getSectionPtr(this, L, Index);
1973 return getStruct<MachO::section_64>(this, Sec);
1977 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1978 const char *P = reinterpret_cast<const char *>(DRI.p);
1979 return getStruct<MachO::nlist>(this, P);
1983 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1984 const char *P = reinterpret_cast<const char *>(DRI.p);
1985 return getStruct<MachO::nlist_64>(this, P);
1988 MachO::linkedit_data_command
1989 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1990 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1993 MachO::segment_command
1994 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1995 return getStruct<MachO::segment_command>(this, L.Ptr);
1998 MachO::segment_command_64
1999 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2000 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2003 MachO::linker_option_command
2004 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2005 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2008 MachO::version_min_command
2009 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2010 return getStruct<MachO::version_min_command>(this, L.Ptr);
2013 MachO::dylib_command
2014 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2015 return getStruct<MachO::dylib_command>(this, L.Ptr);
2018 MachO::dyld_info_command
2019 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2020 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2023 MachO::dylinker_command
2024 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2025 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2029 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2030 return getStruct<MachO::uuid_command>(this, L.Ptr);
2033 MachO::rpath_command
2034 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2035 return getStruct<MachO::rpath_command>(this, L.Ptr);
2038 MachO::source_version_command
2039 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2040 return getStruct<MachO::source_version_command>(this, L.Ptr);
2043 MachO::entry_point_command
2044 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2045 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2048 MachO::encryption_info_command
2049 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2050 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2053 MachO::encryption_info_command_64
2054 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2055 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2058 MachO::sub_framework_command
2059 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2063 MachO::sub_umbrella_command
2064 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2068 MachO::sub_library_command
2069 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2073 MachO::sub_client_command
2074 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2078 MachO::routines_command
2079 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::routines_command>(this, L.Ptr);
2083 MachO::routines_command_64
2084 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2088 MachO::thread_command
2089 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::thread_command>(this, L.Ptr);
2093 MachO::any_relocation_info
2094 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2099 MachO::section_64 Sect = getSection64(Sec);
2100 Offset = Sect.reloff;
2102 MachO::section Sect = getSection(Sec);
2103 Offset = Sect.reloff;
2106 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2107 getPtr(this, Offset)) + Rel.d.b;
2108 return getStruct<MachO::any_relocation_info>(
2109 this, reinterpret_cast<const char *>(P));
2112 MachO::data_in_code_entry
2113 MachOObjectFile::getDice(DataRefImpl Rel) const {
2114 const char *P = reinterpret_cast<const char *>(Rel.p);
2115 return getStruct<MachO::data_in_code_entry>(this, P);
2118 const MachO::mach_header &MachOObjectFile::getHeader() const {
2122 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2127 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2128 const MachO::dysymtab_command &DLC,
2129 unsigned Index) const {
2130 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2131 return getStruct<uint32_t>(this, getPtr(this, Offset));
2134 MachO::data_in_code_entry
2135 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2136 unsigned Index) const {
2137 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2138 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2141 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2143 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2145 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2146 MachO::symtab_command Cmd;
2147 Cmd.cmd = MachO::LC_SYMTAB;
2148 Cmd.cmdsize = sizeof(MachO::symtab_command);
2156 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2157 if (DysymtabLoadCmd)
2158 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2160 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2161 MachO::dysymtab_command Cmd;
2162 Cmd.cmd = MachO::LC_DYSYMTAB;
2163 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2174 Cmd.extrefsymoff = 0;
2175 Cmd.nextrefsyms = 0;
2176 Cmd.indirectsymoff = 0;
2177 Cmd.nindirectsyms = 0;
2185 MachO::linkedit_data_command
2186 MachOObjectFile::getDataInCodeLoadCommand() const {
2187 if (DataInCodeLoadCmd)
2188 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2190 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2191 MachO::linkedit_data_command Cmd;
2192 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2193 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2199 MachO::linkedit_data_command
2200 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2201 if (LinkOptHintsLoadCmd)
2202 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2204 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2206 MachO::linkedit_data_command Cmd;
2207 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2208 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2214 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2215 if (!DyldInfoLoadCmd)
2216 return ArrayRef<uint8_t>();
2218 MachO::dyld_info_command DyldInfo
2219 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2220 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2221 getPtr(this, DyldInfo.rebase_off));
2222 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2225 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2226 if (!DyldInfoLoadCmd)
2227 return ArrayRef<uint8_t>();
2229 MachO::dyld_info_command DyldInfo
2230 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2231 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2232 getPtr(this, DyldInfo.bind_off));
2233 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2236 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2237 if (!DyldInfoLoadCmd)
2238 return ArrayRef<uint8_t>();
2240 MachO::dyld_info_command DyldInfo
2241 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2242 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2243 getPtr(this, DyldInfo.weak_bind_off));
2244 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2247 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2248 if (!DyldInfoLoadCmd)
2249 return ArrayRef<uint8_t>();
2251 MachO::dyld_info_command DyldInfo
2252 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2253 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2254 getPtr(this, DyldInfo.lazy_bind_off));
2255 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2258 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2259 if (!DyldInfoLoadCmd)
2260 return ArrayRef<uint8_t>();
2262 MachO::dyld_info_command DyldInfo
2263 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2264 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2265 getPtr(this, DyldInfo.export_off));
2266 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2269 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2271 return ArrayRef<uint8_t>();
2272 // Returning a pointer is fine as uuid doesn't need endian swapping.
2273 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2274 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2277 StringRef MachOObjectFile::getStringTableData() const {
2278 MachO::symtab_command S = getSymtabLoadCommand();
2279 return getData().substr(S.stroff, S.strsize);
2282 bool MachOObjectFile::is64Bit() const {
2283 return getType() == getMachOType(false, true) ||
2284 getType() == getMachOType(true, true);
2287 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2288 SmallVectorImpl<uint64_t> &Out) const {
2289 DataExtractor extractor(ObjectFile::getData(), true, 0);
2291 uint32_t offset = Index;
2293 while (uint64_t delta = extractor.getULEB128(&offset)) {
2295 Out.push_back(data);
2299 bool MachOObjectFile::isRelocatableObject() const {
2300 return getHeader().filetype == MachO::MH_OBJECT;
2303 ErrorOr<std::unique_ptr<MachOObjectFile>>
2304 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2305 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2307 std::unique_ptr<MachOObjectFile> Ret;
2308 if (Magic == "\xFE\xED\xFA\xCE")
2309 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2310 else if (Magic == "\xCE\xFA\xED\xFE")
2311 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2312 else if (Magic == "\xFE\xED\xFA\xCF")
2313 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2314 else if (Magic == "\xCF\xFA\xED\xFE")
2315 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2317 return object_error::parse_failed;
2321 return std::move(Ret);