1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
41 // FIXME: Replace all uses of this function with getStructOrErr.
43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
87 static MachO::nlist_base
88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
93 static StringRef parseSegmentOrSectionName(const char *P) {
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
101 // Helper to advance a section or symbol iterator multiple increments at a time.
103 static void advance(T &it, size_t Val) {
108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile *O,
157 MachO::section_64 Sect = O->getSection64(Sec);
160 MachO::section Sect = O->getSection(Sec);
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
173 Load.C = CmdOrErr.get();
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
190 template <typename T>
191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
195 Header = HeaderOrErr.get();
197 EC = HeaderOrErr.getError();
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
235 parseHeader(this, Header64, EC);
237 parseHeader(this, Header, EC);
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
247 EC = LoadOrErr.getError();
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
256 EC = object_error::parse_failed;
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
292 EC = object_error::parse_failed;
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
314 EC = LoadOrErr.getError();
317 Load = LoadOrErr.get();
320 assert(LoadCommands.size() == LoadCommandCount);
323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
330 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331 StringRef StringTable = getStringTableData();
332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333 const char *Start = &StringTable.data()[Entry.n_strx];
334 if (Start < getData().begin() || Start >= getData().end())
336 "Symbol name entry points before beginning or past end of file.");
337 return StringRef(Start);
340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
359 StringRef StringTable = getStringTableData();
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
368 return std::error_code();
371 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
372 uint64_t NValue = getNValue(Sym);
373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
374 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
375 return UnknownAddress;
379 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
380 uint64_t &Res) const {
381 Res = getSymbolValue(Sym);
382 return std::error_code();
385 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
386 uint32_t flags = getSymbolFlags(DRI);
387 if (flags & SymbolRef::SF_Common) {
388 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
389 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
394 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
395 return getSymbolValue(DRI);
398 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
399 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
400 uint8_t n_type = Entry.n_type;
402 // If this is a STAB debugging symbol, we can do nothing more.
403 if (n_type & MachO::N_STAB)
404 return SymbolRef::ST_Debug;
406 switch (n_type & MachO::N_TYPE) {
408 return SymbolRef::ST_Unknown;
410 return SymbolRef::ST_Function;
412 return SymbolRef::ST_Other;
415 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
416 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
418 uint8_t MachOType = Entry.n_type;
419 uint16_t MachOFlags = Entry.n_desc;
421 uint32_t Result = SymbolRef::SF_None;
423 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
424 Result |= SymbolRef::SF_Undefined;
426 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
427 Result |= SymbolRef::SF_Indirect;
429 if (MachOType & MachO::N_STAB)
430 Result |= SymbolRef::SF_FormatSpecific;
432 if (MachOType & MachO::N_EXT) {
433 Result |= SymbolRef::SF_Global;
434 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
435 uint64_t Value = getSymbolValue(DRI);
436 if (Value && Value != UnknownAddress)
437 Result |= SymbolRef::SF_Common;
440 if (!(MachOType & MachO::N_PEXT))
441 Result |= SymbolRef::SF_Exported;
444 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
445 Result |= SymbolRef::SF_Weak;
447 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
448 Result |= SymbolRef::SF_Thumb;
450 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
451 Result |= SymbolRef::SF_Absolute;
456 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
457 section_iterator &Res) const {
458 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
459 uint8_t index = Entry.n_sect;
466 if (DRI.d.a >= Sections.size())
467 report_fatal_error("getSymbolSection: Invalid section index.");
468 Res = section_iterator(SectionRef(DRI, this));
471 return std::error_code();
474 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
475 MachO::nlist_base Entry =
476 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
477 return Entry.n_sect - 1;
480 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
484 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
485 StringRef &Result) const {
486 ArrayRef<char> Raw = getSectionRawName(Sec);
487 Result = parseSegmentOrSectionName(Raw.data());
488 return std::error_code();
491 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
493 return getSection64(Sec).addr;
494 return getSection(Sec).addr;
497 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
499 return getSection64(Sec).size;
500 return getSection(Sec).size;
503 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
504 StringRef &Res) const {
509 MachO::section_64 Sect = getSection64(Sec);
510 Offset = Sect.offset;
513 MachO::section Sect = getSection(Sec);
514 Offset = Sect.offset;
518 Res = this->getData().substr(Offset, Size);
519 return std::error_code();
522 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
525 MachO::section_64 Sect = getSection64(Sec);
528 MachO::section Sect = getSection(Sec);
532 return uint64_t(1) << Align;
535 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
536 uint32_t Flags = getSectionFlags(this, Sec);
537 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
540 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 unsigned SectionType = Flags & MachO::SECTION_TYPE;
543 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
544 !(SectionType == MachO::S_ZEROFILL ||
545 SectionType == MachO::S_GB_ZEROFILL);
548 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
549 uint32_t Flags = getSectionFlags(this, Sec);
550 unsigned SectionType = Flags & MachO::SECTION_TYPE;
551 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
552 (SectionType == MachO::S_ZEROFILL ||
553 SectionType == MachO::S_GB_ZEROFILL);
556 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
557 return Sec.getRawDataRefImpl().d.a;
560 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
561 // FIXME: Unimplemented.
565 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
569 return relocation_iterator(RelocationRef(Ret, this));
573 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
576 MachO::section_64 Sect = getSection64(Sec);
579 MachO::section Sect = getSection(Sec);
586 return relocation_iterator(RelocationRef(Ret, this));
589 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
593 ErrorOr<uint64_t> MachOObjectFile::getRelocationAddress(DataRefImpl Rel) const {
594 uint64_t Offset = getRelocationOffset(Rel);
598 uint64_t SecAddress = getSectionAddress(Sec);
599 return SecAddress + Offset;
602 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
603 assert(getHeader().filetype == MachO::MH_OBJECT &&
604 "Only implemented for MH_OBJECT");
605 MachO::any_relocation_info RE = getRelocation(Rel);
606 return getAnyRelocationAddress(RE);
610 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
611 MachO::any_relocation_info RE = getRelocation(Rel);
612 if (isRelocationScattered(RE))
615 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
616 bool isExtern = getPlainRelocationExternal(RE);
620 MachO::symtab_command S = getSymtabLoadCommand();
621 unsigned SymbolTableEntrySize = is64Bit() ?
622 sizeof(MachO::nlist_64) :
623 sizeof(MachO::nlist);
624 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
626 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
627 return symbol_iterator(SymbolRef(Sym, this));
631 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
632 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
635 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
636 MachO::any_relocation_info RE = getRelocation(Rel);
637 return getAnyRelocationType(RE);
640 void MachOObjectFile::getRelocationTypeName(
641 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
643 uint64_t RType = getRelocationType(Rel);
645 unsigned Arch = this->getArch();
649 static const char *const Table[] = {
650 "GENERIC_RELOC_VANILLA",
651 "GENERIC_RELOC_PAIR",
652 "GENERIC_RELOC_SECTDIFF",
653 "GENERIC_RELOC_PB_LA_PTR",
654 "GENERIC_RELOC_LOCAL_SECTDIFF",
655 "GENERIC_RELOC_TLV" };
663 case Triple::x86_64: {
664 static const char *const Table[] = {
665 "X86_64_RELOC_UNSIGNED",
666 "X86_64_RELOC_SIGNED",
667 "X86_64_RELOC_BRANCH",
668 "X86_64_RELOC_GOT_LOAD",
670 "X86_64_RELOC_SUBTRACTOR",
671 "X86_64_RELOC_SIGNED_1",
672 "X86_64_RELOC_SIGNED_2",
673 "X86_64_RELOC_SIGNED_4",
674 "X86_64_RELOC_TLV" };
683 static const char *const Table[] = {
686 "ARM_RELOC_SECTDIFF",
687 "ARM_RELOC_LOCAL_SECTDIFF",
688 "ARM_RELOC_PB_LA_PTR",
690 "ARM_THUMB_RELOC_BR22",
691 "ARM_THUMB_32BIT_BRANCH",
693 "ARM_RELOC_HALF_SECTDIFF" };
701 case Triple::aarch64: {
702 static const char *const Table[] = {
703 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
704 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
705 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
706 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
707 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
711 if (RType >= array_lengthof(Table))
718 static const char *const Table[] = {
727 "PPC_RELOC_SECTDIFF",
728 "PPC_RELOC_PB_LA_PTR",
729 "PPC_RELOC_HI16_SECTDIFF",
730 "PPC_RELOC_LO16_SECTDIFF",
731 "PPC_RELOC_HA16_SECTDIFF",
733 "PPC_RELOC_LO14_SECTDIFF",
734 "PPC_RELOC_LOCAL_SECTDIFF" };
742 case Triple::UnknownArch:
746 Result.append(res.begin(), res.end());
749 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
750 MachO::any_relocation_info RE = getRelocation(Rel);
751 return getAnyRelocationLength(RE);
755 // guessLibraryShortName() is passed a name of a dynamic library and returns a
756 // guess on what the short name is. Then name is returned as a substring of the
757 // StringRef Name passed in. The name of the dynamic library is recognized as
758 // a framework if it has one of the two following forms:
759 // Foo.framework/Versions/A/Foo
761 // Where A and Foo can be any string. And may contain a trailing suffix
762 // starting with an underbar. If the Name is recognized as a framework then
763 // isFramework is set to true else it is set to false. If the Name has a
764 // suffix then Suffix is set to the substring in Name that contains the suffix
765 // else it is set to a NULL StringRef.
767 // The Name of the dynamic library is recognized as a library name if it has
768 // one of the two following forms:
771 // The library may have a suffix trailing the name Foo of the form:
772 // libFoo_profile.A.dylib
773 // libFoo_profile.dylib
775 // The Name of the dynamic library is also recognized as a library name if it
776 // has the following form:
779 // If the Name of the dynamic library is none of the forms above then a NULL
780 // StringRef is returned.
782 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
785 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
786 size_t a, b, c, d, Idx;
789 Suffix = StringRef();
791 // Pull off the last component and make Foo point to it
793 if (a == Name.npos || a == 0)
795 Foo = Name.slice(a+1, Name.npos);
797 // Look for a suffix starting with a '_'
798 Idx = Foo.rfind('_');
799 if (Idx != Foo.npos && Foo.size() >= 2) {
800 Suffix = Foo.slice(Idx, Foo.npos);
801 Foo = Foo.slice(0, Idx);
804 // First look for the form Foo.framework/Foo
805 b = Name.rfind('/', a);
810 F = Name.slice(Idx, Idx + Foo.size());
811 DotFramework = Name.slice(Idx + Foo.size(),
812 Idx + Foo.size() + sizeof(".framework/")-1);
813 if (F == Foo && DotFramework == ".framework/") {
818 // Next look for the form Foo.framework/Versions/A/Foo
821 c = Name.rfind('/', b);
822 if (c == Name.npos || c == 0)
824 V = Name.slice(c+1, Name.npos);
825 if (!V.startswith("Versions/"))
827 d = Name.rfind('/', c);
832 F = Name.slice(Idx, Idx + Foo.size());
833 DotFramework = Name.slice(Idx + Foo.size(),
834 Idx + Foo.size() + sizeof(".framework/")-1);
835 if (F == Foo && DotFramework == ".framework/") {
841 // pull off the suffix after the "." and make a point to it
843 if (a == Name.npos || a == 0)
845 Dylib = Name.slice(a, Name.npos);
846 if (Dylib != ".dylib")
849 // First pull off the version letter for the form Foo.A.dylib if any.
851 Dot = Name.slice(a-2, a-1);
856 b = Name.rfind('/', a);
861 // ignore any suffix after an underbar like Foo_profile.A.dylib
862 Idx = Name.find('_', b);
863 if (Idx != Name.npos && Idx != b) {
864 Lib = Name.slice(b, Idx);
865 Suffix = Name.slice(Idx, a);
868 Lib = Name.slice(b, a);
869 // There are incorrect library names of the form:
870 // libATS.A_profile.dylib so check for these.
871 if (Lib.size() >= 3) {
872 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
874 Lib = Lib.slice(0, Lib.size()-2);
879 Qtx = Name.slice(a, Name.npos);
882 b = Name.rfind('/', a);
884 Lib = Name.slice(0, a);
886 Lib = Name.slice(b+1, a);
887 // There are library names of the form: QT.A.qtx so check for these.
888 if (Lib.size() >= 3) {
889 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
891 Lib = Lib.slice(0, Lib.size()-2);
896 // getLibraryShortNameByIndex() is used to get the short name of the library
897 // for an undefined symbol in a linked Mach-O binary that was linked with the
898 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
899 // It is passed the index (0 - based) of the library as translated from
900 // GET_LIBRARY_ORDINAL (1 - based).
901 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
902 StringRef &Res) const {
903 if (Index >= Libraries.size())
904 return object_error::parse_failed;
906 // If the cache of LibrariesShortNames is not built up do that first for
907 // all the Libraries.
908 if (LibrariesShortNames.size() == 0) {
909 for (unsigned i = 0; i < Libraries.size(); i++) {
910 MachO::dylib_command D =
911 getStruct<MachO::dylib_command>(this, Libraries[i]);
912 if (D.dylib.name >= D.cmdsize)
913 return object_error::parse_failed;
914 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
915 StringRef Name = StringRef(P);
916 if (D.dylib.name+Name.size() >= D.cmdsize)
917 return object_error::parse_failed;
920 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
921 if (shortName.empty())
922 LibrariesShortNames.push_back(Name);
924 LibrariesShortNames.push_back(shortName);
928 Res = LibrariesShortNames[Index];
929 return std::error_code();
932 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
933 return getSymbolByIndex(0);
936 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
939 return basic_symbol_iterator(SymbolRef(DRI, this));
941 MachO::symtab_command Symtab = getSymtabLoadCommand();
942 unsigned SymbolTableEntrySize = is64Bit() ?
943 sizeof(MachO::nlist_64) :
944 sizeof(MachO::nlist);
945 unsigned Offset = Symtab.symoff +
946 Symtab.nsyms * SymbolTableEntrySize;
947 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
948 return basic_symbol_iterator(SymbolRef(DRI, this));
951 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
954 return basic_symbol_iterator(SymbolRef(DRI, this));
956 MachO::symtab_command Symtab = getSymtabLoadCommand();
957 if (Index >= Symtab.nsyms)
958 report_fatal_error("Requested symbol index is out of range.");
959 unsigned SymbolTableEntrySize =
960 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
961 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
962 DRI.p += Index * SymbolTableEntrySize;
963 return basic_symbol_iterator(SymbolRef(DRI, this));
966 section_iterator MachOObjectFile::section_begin() const {
968 return section_iterator(SectionRef(DRI, this));
971 section_iterator MachOObjectFile::section_end() const {
973 DRI.d.a = Sections.size();
974 return section_iterator(SectionRef(DRI, this));
977 uint8_t MachOObjectFile::getBytesInAddress() const {
978 return is64Bit() ? 8 : 4;
981 StringRef MachOObjectFile::getFileFormatName() const {
982 unsigned CPUType = getCPUType(this);
985 case llvm::MachO::CPU_TYPE_I386:
986 return "Mach-O 32-bit i386";
987 case llvm::MachO::CPU_TYPE_ARM:
989 case llvm::MachO::CPU_TYPE_POWERPC:
990 return "Mach-O 32-bit ppc";
992 return "Mach-O 32-bit unknown";
997 case llvm::MachO::CPU_TYPE_X86_64:
998 return "Mach-O 64-bit x86-64";
999 case llvm::MachO::CPU_TYPE_ARM64:
1000 return "Mach-O arm64";
1001 case llvm::MachO::CPU_TYPE_POWERPC64:
1002 return "Mach-O 64-bit ppc64";
1004 return "Mach-O 64-bit unknown";
1008 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1010 case llvm::MachO::CPU_TYPE_I386:
1012 case llvm::MachO::CPU_TYPE_X86_64:
1013 return Triple::x86_64;
1014 case llvm::MachO::CPU_TYPE_ARM:
1016 case llvm::MachO::CPU_TYPE_ARM64:
1017 return Triple::aarch64;
1018 case llvm::MachO::CPU_TYPE_POWERPC:
1020 case llvm::MachO::CPU_TYPE_POWERPC64:
1021 return Triple::ppc64;
1023 return Triple::UnknownArch;
1027 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1028 const char **McpuDefault) {
1030 *McpuDefault = nullptr;
1033 case MachO::CPU_TYPE_I386:
1034 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1035 case MachO::CPU_SUBTYPE_I386_ALL:
1036 return Triple("i386-apple-darwin");
1040 case MachO::CPU_TYPE_X86_64:
1041 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1042 case MachO::CPU_SUBTYPE_X86_64_ALL:
1043 return Triple("x86_64-apple-darwin");
1044 case MachO::CPU_SUBTYPE_X86_64_H:
1045 return Triple("x86_64h-apple-darwin");
1049 case MachO::CPU_TYPE_ARM:
1050 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1051 case MachO::CPU_SUBTYPE_ARM_V4T:
1052 return Triple("armv4t-apple-darwin");
1053 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1054 return Triple("armv5e-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1056 return Triple("xscale-apple-darwin");
1057 case MachO::CPU_SUBTYPE_ARM_V6:
1058 return Triple("armv6-apple-darwin");
1059 case MachO::CPU_SUBTYPE_ARM_V6M:
1061 *McpuDefault = "cortex-m0";
1062 return Triple("armv6m-apple-darwin");
1063 case MachO::CPU_SUBTYPE_ARM_V7:
1064 return Triple("armv7-apple-darwin");
1065 case MachO::CPU_SUBTYPE_ARM_V7EM:
1067 *McpuDefault = "cortex-m4";
1068 return Triple("armv7em-apple-darwin");
1069 case MachO::CPU_SUBTYPE_ARM_V7K:
1070 return Triple("armv7k-apple-darwin");
1071 case MachO::CPU_SUBTYPE_ARM_V7M:
1073 *McpuDefault = "cortex-m3";
1074 return Triple("armv7m-apple-darwin");
1075 case MachO::CPU_SUBTYPE_ARM_V7S:
1076 return Triple("armv7s-apple-darwin");
1080 case MachO::CPU_TYPE_ARM64:
1081 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1082 case MachO::CPU_SUBTYPE_ARM64_ALL:
1083 return Triple("arm64-apple-darwin");
1087 case MachO::CPU_TYPE_POWERPC:
1088 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1089 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1090 return Triple("ppc-apple-darwin");
1094 case MachO::CPU_TYPE_POWERPC64:
1095 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1096 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1097 return Triple("ppc64-apple-darwin");
1106 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1107 const char **McpuDefault) {
1109 *McpuDefault = nullptr;
1112 case MachO::CPU_TYPE_ARM:
1113 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1114 case MachO::CPU_SUBTYPE_ARM_V4T:
1115 return Triple("thumbv4t-apple-darwin");
1116 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1117 return Triple("thumbv5e-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1119 return Triple("xscale-apple-darwin");
1120 case MachO::CPU_SUBTYPE_ARM_V6:
1121 return Triple("thumbv6-apple-darwin");
1122 case MachO::CPU_SUBTYPE_ARM_V6M:
1124 *McpuDefault = "cortex-m0";
1125 return Triple("thumbv6m-apple-darwin");
1126 case MachO::CPU_SUBTYPE_ARM_V7:
1127 return Triple("thumbv7-apple-darwin");
1128 case MachO::CPU_SUBTYPE_ARM_V7EM:
1130 *McpuDefault = "cortex-m4";
1131 return Triple("thumbv7em-apple-darwin");
1132 case MachO::CPU_SUBTYPE_ARM_V7K:
1133 return Triple("thumbv7k-apple-darwin");
1134 case MachO::CPU_SUBTYPE_ARM_V7M:
1136 *McpuDefault = "cortex-m3";
1137 return Triple("thumbv7m-apple-darwin");
1138 case MachO::CPU_SUBTYPE_ARM_V7S:
1139 return Triple("thumbv7s-apple-darwin");
1148 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1149 const char **McpuDefault,
1150 Triple *ThumbTriple) {
1151 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1152 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1157 Triple MachOObjectFile::getHostArch() {
1158 return Triple(sys::getDefaultTargetTriple());
1161 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1162 return StringSwitch<bool>(ArchFlag)
1164 .Case("x86_64", true)
1165 .Case("x86_64h", true)
1166 .Case("armv4t", true)
1168 .Case("armv5e", true)
1169 .Case("armv6", true)
1170 .Case("armv6m", true)
1171 .Case("armv7", true)
1172 .Case("armv7em", true)
1173 .Case("armv7k", true)
1174 .Case("armv7m", true)
1175 .Case("armv7s", true)
1176 .Case("arm64", true)
1178 .Case("ppc64", true)
1182 unsigned MachOObjectFile::getArch() const {
1183 return getArch(getCPUType(this));
1186 Triple MachOObjectFile::getArch(const char **McpuDefault,
1187 Triple *ThumbTriple) const {
1188 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1189 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1192 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1195 return section_rel_begin(DRI);
1198 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1201 return section_rel_end(DRI);
1204 dice_iterator MachOObjectFile::begin_dices() const {
1206 if (!DataInCodeLoadCmd)
1207 return dice_iterator(DiceRef(DRI, this));
1209 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1210 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1211 return dice_iterator(DiceRef(DRI, this));
1214 dice_iterator MachOObjectFile::end_dices() const {
1216 if (!DataInCodeLoadCmd)
1217 return dice_iterator(DiceRef(DRI, this));
1219 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1220 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1221 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1222 return dice_iterator(DiceRef(DRI, this));
1225 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1226 : Trie(T), Malformed(false), Done(false) { }
1228 void ExportEntry::moveToFirst() {
1230 pushDownUntilBottom();
1233 void ExportEntry::moveToEnd() {
1238 bool ExportEntry::operator==(const ExportEntry &Other) const {
1239 // Common case, one at end, other iterating from begin.
1240 if (Done || Other.Done)
1241 return (Done == Other.Done);
1242 // Not equal if different stack sizes.
1243 if (Stack.size() != Other.Stack.size())
1245 // Not equal if different cumulative strings.
1246 if (!CumulativeString.equals(Other.CumulativeString))
1248 // Equal if all nodes in both stacks match.
1249 for (unsigned i=0; i < Stack.size(); ++i) {
1250 if (Stack[i].Start != Other.Stack[i].Start)
1256 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1258 uint64_t Result = decodeULEB128(Ptr, &Count);
1260 if (Ptr > Trie.end()) {
1267 StringRef ExportEntry::name() const {
1268 return CumulativeString;
1271 uint64_t ExportEntry::flags() const {
1272 return Stack.back().Flags;
1275 uint64_t ExportEntry::address() const {
1276 return Stack.back().Address;
1279 uint64_t ExportEntry::other() const {
1280 return Stack.back().Other;
1283 StringRef ExportEntry::otherName() const {
1284 const char* ImportName = Stack.back().ImportName;
1286 return StringRef(ImportName);
1290 uint32_t ExportEntry::nodeOffset() const {
1291 return Stack.back().Start - Trie.begin();
1294 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1295 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1296 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1297 ParentStringLength(0), IsExportNode(false) {
1300 void ExportEntry::pushNode(uint64_t offset) {
1301 const uint8_t *Ptr = Trie.begin() + offset;
1302 NodeState State(Ptr);
1303 uint64_t ExportInfoSize = readULEB128(State.Current);
1304 State.IsExportNode = (ExportInfoSize != 0);
1305 const uint8_t* Children = State.Current + ExportInfoSize;
1306 if (State.IsExportNode) {
1307 State.Flags = readULEB128(State.Current);
1308 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1310 State.Other = readULEB128(State.Current); // dylib ordinal
1311 State.ImportName = reinterpret_cast<const char*>(State.Current);
1313 State.Address = readULEB128(State.Current);
1314 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1315 State.Other = readULEB128(State.Current);
1318 State.ChildCount = *Children;
1319 State.Current = Children + 1;
1320 State.NextChildIndex = 0;
1321 State.ParentStringLength = CumulativeString.size();
1322 Stack.push_back(State);
1325 void ExportEntry::pushDownUntilBottom() {
1326 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1327 NodeState &Top = Stack.back();
1328 CumulativeString.resize(Top.ParentStringLength);
1329 for (;*Top.Current != 0; Top.Current++) {
1330 char C = *Top.Current;
1331 CumulativeString.push_back(C);
1334 uint64_t childNodeIndex = readULEB128(Top.Current);
1335 Top.NextChildIndex += 1;
1336 pushNode(childNodeIndex);
1338 if (!Stack.back().IsExportNode) {
1344 // We have a trie data structure and need a way to walk it that is compatible
1345 // with the C++ iterator model. The solution is a non-recursive depth first
1346 // traversal where the iterator contains a stack of parent nodes along with a
1347 // string that is the accumulation of all edge strings along the parent chain
1350 // There is one "export" node for each exported symbol. But because some
1351 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1352 // node may have child nodes too.
1354 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1355 // child until hitting a node with no children (which is an export node or
1356 // else the trie is malformed). On the way down, each node is pushed on the
1357 // stack ivar. If there is no more ways down, it pops up one and tries to go
1358 // down a sibling path until a childless node is reached.
1359 void ExportEntry::moveNext() {
1360 if (Stack.empty() || !Stack.back().IsExportNode) {
1367 while (!Stack.empty()) {
1368 NodeState &Top = Stack.back();
1369 if (Top.NextChildIndex < Top.ChildCount) {
1370 pushDownUntilBottom();
1371 // Now at the next export node.
1374 if (Top.IsExportNode) {
1375 // This node has no children but is itself an export node.
1376 CumulativeString.resize(Top.ParentStringLength);
1385 iterator_range<export_iterator>
1386 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1387 ExportEntry Start(Trie);
1388 if (Trie.size() == 0)
1391 Start.moveToFirst();
1393 ExportEntry Finish(Trie);
1396 return iterator_range<export_iterator>(export_iterator(Start),
1397 export_iterator(Finish));
1400 iterator_range<export_iterator> MachOObjectFile::exports() const {
1401 return exports(getDyldInfoExportsTrie());
1405 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1406 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1407 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1408 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1410 void MachORebaseEntry::moveToFirst() {
1411 Ptr = Opcodes.begin();
1415 void MachORebaseEntry::moveToEnd() {
1416 Ptr = Opcodes.end();
1417 RemainingLoopCount = 0;
1421 void MachORebaseEntry::moveNext() {
1422 // If in the middle of some loop, move to next rebasing in loop.
1423 SegmentOffset += AdvanceAmount;
1424 if (RemainingLoopCount) {
1425 --RemainingLoopCount;
1428 if (Ptr == Opcodes.end()) {
1433 while (More && !Malformed) {
1434 // Parse next opcode and set up next loop.
1435 uint8_t Byte = *Ptr++;
1436 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1437 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1439 case MachO::REBASE_OPCODE_DONE:
1443 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1445 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1446 RebaseType = ImmValue;
1449 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1450 << "RebaseType=" << (int) RebaseType << "\n");
1452 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1453 SegmentIndex = ImmValue;
1454 SegmentOffset = readULEB128();
1457 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1458 << "SegmentIndex=" << SegmentIndex << ", "
1459 << format("SegmentOffset=0x%06X", SegmentOffset)
1462 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1463 SegmentOffset += readULEB128();
1464 DEBUG_WITH_TYPE("mach-o-rebase",
1465 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1466 << format("SegmentOffset=0x%06X",
1467 SegmentOffset) << "\n");
1469 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1470 SegmentOffset += ImmValue * PointerSize;
1471 DEBUG_WITH_TYPE("mach-o-rebase",
1472 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1473 << format("SegmentOffset=0x%06X",
1474 SegmentOffset) << "\n");
1476 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1477 AdvanceAmount = PointerSize;
1478 RemainingLoopCount = ImmValue - 1;
1481 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1482 << format("SegmentOffset=0x%06X", SegmentOffset)
1483 << ", AdvanceAmount=" << AdvanceAmount
1484 << ", RemainingLoopCount=" << RemainingLoopCount
1487 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1488 AdvanceAmount = PointerSize;
1489 RemainingLoopCount = readULEB128() - 1;
1492 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1493 << format("SegmentOffset=0x%06X", SegmentOffset)
1494 << ", AdvanceAmount=" << AdvanceAmount
1495 << ", RemainingLoopCount=" << RemainingLoopCount
1498 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1499 AdvanceAmount = readULEB128() + PointerSize;
1500 RemainingLoopCount = 0;
1503 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1504 << format("SegmentOffset=0x%06X", SegmentOffset)
1505 << ", AdvanceAmount=" << AdvanceAmount
1506 << ", RemainingLoopCount=" << RemainingLoopCount
1509 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1510 RemainingLoopCount = readULEB128() - 1;
1511 AdvanceAmount = readULEB128() + PointerSize;
1514 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1515 << format("SegmentOffset=0x%06X", SegmentOffset)
1516 << ", AdvanceAmount=" << AdvanceAmount
1517 << ", RemainingLoopCount=" << RemainingLoopCount
1526 uint64_t MachORebaseEntry::readULEB128() {
1528 uint64_t Result = decodeULEB128(Ptr, &Count);
1530 if (Ptr > Opcodes.end()) {
1531 Ptr = Opcodes.end();
1537 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1539 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1541 StringRef MachORebaseEntry::typeName() const {
1542 switch (RebaseType) {
1543 case MachO::REBASE_TYPE_POINTER:
1545 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1546 return "text abs32";
1547 case MachO::REBASE_TYPE_TEXT_PCREL32:
1548 return "text rel32";
1553 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1554 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1555 return (Ptr == Other.Ptr) &&
1556 (RemainingLoopCount == Other.RemainingLoopCount) &&
1557 (Done == Other.Done);
1560 iterator_range<rebase_iterator>
1561 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1562 MachORebaseEntry Start(Opcodes, is64);
1563 Start.moveToFirst();
1565 MachORebaseEntry Finish(Opcodes, is64);
1568 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1569 rebase_iterator(Finish));
1572 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1573 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1577 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1579 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1580 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1581 BindType(0), PointerSize(is64Bit ? 8 : 4),
1582 TableKind(BK), Malformed(false), Done(false) {}
1584 void MachOBindEntry::moveToFirst() {
1585 Ptr = Opcodes.begin();
1589 void MachOBindEntry::moveToEnd() {
1590 Ptr = Opcodes.end();
1591 RemainingLoopCount = 0;
1595 void MachOBindEntry::moveNext() {
1596 // If in the middle of some loop, move to next binding in loop.
1597 SegmentOffset += AdvanceAmount;
1598 if (RemainingLoopCount) {
1599 --RemainingLoopCount;
1602 if (Ptr == Opcodes.end()) {
1607 while (More && !Malformed) {
1608 // Parse next opcode and set up next loop.
1609 uint8_t Byte = *Ptr++;
1610 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1611 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1612 int8_t SignExtended;
1613 const uint8_t *SymStart;
1615 case MachO::BIND_OPCODE_DONE:
1616 if (TableKind == Kind::Lazy) {
1617 // Lazying bindings have a DONE opcode between entries. Need to ignore
1618 // it to advance to next entry. But need not if this is last entry.
1619 bool NotLastEntry = false;
1620 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1622 NotLastEntry = true;
1631 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1633 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1637 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1638 << "Ordinal=" << Ordinal << "\n");
1640 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1641 Ordinal = readULEB128();
1644 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1645 << "Ordinal=" << Ordinal << "\n");
1647 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1649 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1650 Ordinal = SignExtended;
1655 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1656 << "Ordinal=" << Ordinal << "\n");
1658 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1664 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1669 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1670 << "SymbolName=" << SymbolName << "\n");
1671 if (TableKind == Kind::Weak) {
1672 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1676 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1677 BindType = ImmValue;
1680 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1681 << "BindType=" << (int)BindType << "\n");
1683 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1684 Addend = readSLEB128();
1685 if (TableKind == Kind::Lazy)
1689 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1690 << "Addend=" << Addend << "\n");
1692 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1693 SegmentIndex = ImmValue;
1694 SegmentOffset = readULEB128();
1697 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1698 << "SegmentIndex=" << SegmentIndex << ", "
1699 << format("SegmentOffset=0x%06X", SegmentOffset)
1702 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1703 SegmentOffset += readULEB128();
1704 DEBUG_WITH_TYPE("mach-o-bind",
1705 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1706 << format("SegmentOffset=0x%06X",
1707 SegmentOffset) << "\n");
1709 case MachO::BIND_OPCODE_DO_BIND:
1710 AdvanceAmount = PointerSize;
1711 RemainingLoopCount = 0;
1712 DEBUG_WITH_TYPE("mach-o-bind",
1713 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1714 << format("SegmentOffset=0x%06X",
1715 SegmentOffset) << "\n");
1717 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1718 AdvanceAmount = readULEB128() + PointerSize;
1719 RemainingLoopCount = 0;
1720 if (TableKind == Kind::Lazy)
1724 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1725 << format("SegmentOffset=0x%06X", SegmentOffset)
1726 << ", AdvanceAmount=" << AdvanceAmount
1727 << ", RemainingLoopCount=" << RemainingLoopCount
1730 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1731 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1732 RemainingLoopCount = 0;
1733 if (TableKind == Kind::Lazy)
1735 DEBUG_WITH_TYPE("mach-o-bind",
1737 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1738 << format("SegmentOffset=0x%06X",
1739 SegmentOffset) << "\n");
1741 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1742 RemainingLoopCount = readULEB128() - 1;
1743 AdvanceAmount = readULEB128() + PointerSize;
1744 if (TableKind == Kind::Lazy)
1748 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1760 uint64_t MachOBindEntry::readULEB128() {
1762 uint64_t Result = decodeULEB128(Ptr, &Count);
1764 if (Ptr > Opcodes.end()) {
1765 Ptr = Opcodes.end();
1771 int64_t MachOBindEntry::readSLEB128() {
1773 int64_t Result = decodeSLEB128(Ptr, &Count);
1775 if (Ptr > Opcodes.end()) {
1776 Ptr = Opcodes.end();
1783 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1785 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1787 StringRef MachOBindEntry::typeName() const {
1789 case MachO::BIND_TYPE_POINTER:
1791 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1792 return "text abs32";
1793 case MachO::BIND_TYPE_TEXT_PCREL32:
1794 return "text rel32";
1799 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1801 int64_t MachOBindEntry::addend() const { return Addend; }
1803 uint32_t MachOBindEntry::flags() const { return Flags; }
1805 int MachOBindEntry::ordinal() const { return Ordinal; }
1807 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1808 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1809 return (Ptr == Other.Ptr) &&
1810 (RemainingLoopCount == Other.RemainingLoopCount) &&
1811 (Done == Other.Done);
1814 iterator_range<bind_iterator>
1815 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1816 MachOBindEntry::Kind BKind) {
1817 MachOBindEntry Start(Opcodes, is64, BKind);
1818 Start.moveToFirst();
1820 MachOBindEntry Finish(Opcodes, is64, BKind);
1823 return iterator_range<bind_iterator>(bind_iterator(Start),
1824 bind_iterator(Finish));
1827 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1828 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1829 MachOBindEntry::Kind::Regular);
1832 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1833 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1834 MachOBindEntry::Kind::Lazy);
1837 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1838 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1839 MachOBindEntry::Kind::Weak);
1842 MachOObjectFile::load_command_iterator
1843 MachOObjectFile::begin_load_commands() const {
1844 return LoadCommands.begin();
1847 MachOObjectFile::load_command_iterator
1848 MachOObjectFile::end_load_commands() const {
1849 return LoadCommands.end();
1852 iterator_range<MachOObjectFile::load_command_iterator>
1853 MachOObjectFile::load_commands() const {
1854 return iterator_range<load_command_iterator>(begin_load_commands(),
1855 end_load_commands());
1859 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1860 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1861 return parseSegmentOrSectionName(Raw.data());
1865 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1866 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1867 const section_base *Base =
1868 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1869 return makeArrayRef(Base->sectname);
1873 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1874 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1875 const section_base *Base =
1876 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1877 return makeArrayRef(Base->segname);
1881 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1883 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1885 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1888 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1889 const MachO::any_relocation_info &RE) const {
1890 if (isLittleEndian())
1891 return RE.r_word1 & 0xffffff;
1892 return RE.r_word1 >> 8;
1895 bool MachOObjectFile::getPlainRelocationExternal(
1896 const MachO::any_relocation_info &RE) const {
1897 if (isLittleEndian())
1898 return (RE.r_word1 >> 27) & 1;
1899 return (RE.r_word1 >> 4) & 1;
1902 bool MachOObjectFile::getScatteredRelocationScattered(
1903 const MachO::any_relocation_info &RE) const {
1904 return RE.r_word0 >> 31;
1907 uint32_t MachOObjectFile::getScatteredRelocationValue(
1908 const MachO::any_relocation_info &RE) const {
1912 uint32_t MachOObjectFile::getScatteredRelocationType(
1913 const MachO::any_relocation_info &RE) const {
1914 return (RE.r_word0 >> 24) & 0xf;
1917 unsigned MachOObjectFile::getAnyRelocationAddress(
1918 const MachO::any_relocation_info &RE) const {
1919 if (isRelocationScattered(RE))
1920 return getScatteredRelocationAddress(RE);
1921 return getPlainRelocationAddress(RE);
1924 unsigned MachOObjectFile::getAnyRelocationPCRel(
1925 const MachO::any_relocation_info &RE) const {
1926 if (isRelocationScattered(RE))
1927 return getScatteredRelocationPCRel(this, RE);
1928 return getPlainRelocationPCRel(this, RE);
1931 unsigned MachOObjectFile::getAnyRelocationLength(
1932 const MachO::any_relocation_info &RE) const {
1933 if (isRelocationScattered(RE))
1934 return getScatteredRelocationLength(RE);
1935 return getPlainRelocationLength(this, RE);
1939 MachOObjectFile::getAnyRelocationType(
1940 const MachO::any_relocation_info &RE) const {
1941 if (isRelocationScattered(RE))
1942 return getScatteredRelocationType(RE);
1943 return getPlainRelocationType(this, RE);
1947 MachOObjectFile::getAnyRelocationSection(
1948 const MachO::any_relocation_info &RE) const {
1949 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1950 return *section_end();
1951 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1952 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1953 return *section_end();
1955 DRI.d.a = SecNum - 1;
1956 return SectionRef(DRI, this);
1959 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1960 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1961 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1964 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1965 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1966 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1969 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1970 unsigned Index) const {
1971 const char *Sec = getSectionPtr(this, L, Index);
1972 return getStruct<MachO::section>(this, Sec);
1975 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1976 unsigned Index) const {
1977 const char *Sec = getSectionPtr(this, L, Index);
1978 return getStruct<MachO::section_64>(this, Sec);
1982 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1983 const char *P = reinterpret_cast<const char *>(DRI.p);
1984 return getStruct<MachO::nlist>(this, P);
1988 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1989 const char *P = reinterpret_cast<const char *>(DRI.p);
1990 return getStruct<MachO::nlist_64>(this, P);
1993 MachO::linkedit_data_command
1994 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1995 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1998 MachO::segment_command
1999 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2000 return getStruct<MachO::segment_command>(this, L.Ptr);
2003 MachO::segment_command_64
2004 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2005 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2008 MachO::linker_option_command
2009 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2010 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2013 MachO::version_min_command
2014 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2015 return getStruct<MachO::version_min_command>(this, L.Ptr);
2018 MachO::dylib_command
2019 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2020 return getStruct<MachO::dylib_command>(this, L.Ptr);
2023 MachO::dyld_info_command
2024 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2025 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2028 MachO::dylinker_command
2029 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2030 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2034 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2035 return getStruct<MachO::uuid_command>(this, L.Ptr);
2038 MachO::rpath_command
2039 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2040 return getStruct<MachO::rpath_command>(this, L.Ptr);
2043 MachO::source_version_command
2044 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2045 return getStruct<MachO::source_version_command>(this, L.Ptr);
2048 MachO::entry_point_command
2049 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2050 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2053 MachO::encryption_info_command
2054 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2055 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2058 MachO::encryption_info_command_64
2059 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2063 MachO::sub_framework_command
2064 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2068 MachO::sub_umbrella_command
2069 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2073 MachO::sub_library_command
2074 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2078 MachO::sub_client_command
2079 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2083 MachO::routines_command
2084 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::routines_command>(this, L.Ptr);
2088 MachO::routines_command_64
2089 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2093 MachO::thread_command
2094 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2095 return getStruct<MachO::thread_command>(this, L.Ptr);
2098 MachO::any_relocation_info
2099 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2104 MachO::section_64 Sect = getSection64(Sec);
2105 Offset = Sect.reloff;
2107 MachO::section Sect = getSection(Sec);
2108 Offset = Sect.reloff;
2111 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2112 getPtr(this, Offset)) + Rel.d.b;
2113 return getStruct<MachO::any_relocation_info>(
2114 this, reinterpret_cast<const char *>(P));
2117 MachO::data_in_code_entry
2118 MachOObjectFile::getDice(DataRefImpl Rel) const {
2119 const char *P = reinterpret_cast<const char *>(Rel.p);
2120 return getStruct<MachO::data_in_code_entry>(this, P);
2123 const MachO::mach_header &MachOObjectFile::getHeader() const {
2127 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2132 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2133 const MachO::dysymtab_command &DLC,
2134 unsigned Index) const {
2135 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2136 return getStruct<uint32_t>(this, getPtr(this, Offset));
2139 MachO::data_in_code_entry
2140 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2141 unsigned Index) const {
2142 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2143 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2146 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2148 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2150 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2151 MachO::symtab_command Cmd;
2152 Cmd.cmd = MachO::LC_SYMTAB;
2153 Cmd.cmdsize = sizeof(MachO::symtab_command);
2161 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2162 if (DysymtabLoadCmd)
2163 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2165 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2166 MachO::dysymtab_command Cmd;
2167 Cmd.cmd = MachO::LC_DYSYMTAB;
2168 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2179 Cmd.extrefsymoff = 0;
2180 Cmd.nextrefsyms = 0;
2181 Cmd.indirectsymoff = 0;
2182 Cmd.nindirectsyms = 0;
2190 MachO::linkedit_data_command
2191 MachOObjectFile::getDataInCodeLoadCommand() const {
2192 if (DataInCodeLoadCmd)
2193 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2195 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2196 MachO::linkedit_data_command Cmd;
2197 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2198 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2204 MachO::linkedit_data_command
2205 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2206 if (LinkOptHintsLoadCmd)
2207 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2209 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2211 MachO::linkedit_data_command Cmd;
2212 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2213 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2219 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2220 if (!DyldInfoLoadCmd)
2221 return ArrayRef<uint8_t>();
2223 MachO::dyld_info_command DyldInfo
2224 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2225 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2226 getPtr(this, DyldInfo.rebase_off));
2227 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2230 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2231 if (!DyldInfoLoadCmd)
2232 return ArrayRef<uint8_t>();
2234 MachO::dyld_info_command DyldInfo
2235 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2236 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2237 getPtr(this, DyldInfo.bind_off));
2238 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2241 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2242 if (!DyldInfoLoadCmd)
2243 return ArrayRef<uint8_t>();
2245 MachO::dyld_info_command DyldInfo
2246 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2247 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2248 getPtr(this, DyldInfo.weak_bind_off));
2249 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2252 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2253 if (!DyldInfoLoadCmd)
2254 return ArrayRef<uint8_t>();
2256 MachO::dyld_info_command DyldInfo
2257 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2258 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2259 getPtr(this, DyldInfo.lazy_bind_off));
2260 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2263 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2264 if (!DyldInfoLoadCmd)
2265 return ArrayRef<uint8_t>();
2267 MachO::dyld_info_command DyldInfo
2268 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2269 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2270 getPtr(this, DyldInfo.export_off));
2271 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2274 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2276 return ArrayRef<uint8_t>();
2277 // Returning a pointer is fine as uuid doesn't need endian swapping.
2278 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2279 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2282 StringRef MachOObjectFile::getStringTableData() const {
2283 MachO::symtab_command S = getSymtabLoadCommand();
2284 return getData().substr(S.stroff, S.strsize);
2287 bool MachOObjectFile::is64Bit() const {
2288 return getType() == getMachOType(false, true) ||
2289 getType() == getMachOType(true, true);
2292 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2293 SmallVectorImpl<uint64_t> &Out) const {
2294 DataExtractor extractor(ObjectFile::getData(), true, 0);
2296 uint32_t offset = Index;
2298 while (uint64_t delta = extractor.getULEB128(&offset)) {
2300 Out.push_back(data);
2304 bool MachOObjectFile::isRelocatableObject() const {
2305 return getHeader().filetype == MachO::MH_OBJECT;
2308 ErrorOr<std::unique_ptr<MachOObjectFile>>
2309 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2310 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2312 std::unique_ptr<MachOObjectFile> Ret;
2313 if (Magic == "\xFE\xED\xFA\xCE")
2314 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2315 else if (Magic == "\xCE\xFA\xED\xFE")
2316 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2317 else if (Magic == "\xFE\xED\xFA\xCF")
2318 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2319 else if (Magic == "\xCF\xFA\xED\xFE")
2320 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2322 return object_error::parse_failed;
2326 return std::move(Ret);