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 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
333 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
334 const char *Start = &StringTable.data()[Entry.n_strx];
335 if (Start < getData().begin() || Start >= getData().end())
337 "Symbol name entry points before beginning or past end of file.");
338 Res = StringRef(Start);
339 return std::error_code();
342 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
343 DataRefImpl DRI = Sec.getRawDataRefImpl();
344 uint32_t Flags = getSectionFlags(this, DRI);
345 return Flags & MachO::SECTION_TYPE;
348 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
350 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
351 return Entry.n_value;
353 MachO::nlist Entry = getSymbolTableEntry(Sym);
354 return Entry.n_value;
357 // getIndirectName() returns the name of the alias'ed symbol who's string table
358 // index is in the n_value field.
359 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
360 StringRef &Res) const {
361 StringRef StringTable = getStringTableData();
362 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
363 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
364 return object_error::parse_failed;
365 uint64_t NValue = getNValue(Symb);
366 if (NValue >= StringTable.size())
367 return object_error::parse_failed;
368 const char *Start = &StringTable.data()[NValue];
369 Res = StringRef(Start);
370 return std::error_code();
373 uint64_t MachOObjectFile::getSymbolValue(DataRefImpl Sym) const {
374 uint64_t NValue = getNValue(Sym);
375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Sym);
376 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0)
377 return UnknownAddress;
381 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Sym,
382 uint64_t &Res) const {
383 Res = getSymbolValue(Sym);
384 return std::error_code();
387 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
388 uint32_t flags = getSymbolFlags(DRI);
389 if (flags & SymbolRef::SF_Common) {
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
391 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
396 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
398 getSymbolAddress(DRI, Value);
402 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
403 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
404 uint8_t n_type = Entry.n_type;
406 // If this is a STAB debugging symbol, we can do nothing more.
407 if (n_type & MachO::N_STAB)
408 return SymbolRef::ST_Debug;
410 switch (n_type & MachO::N_TYPE) {
412 return SymbolRef::ST_Unknown;
414 return SymbolRef::ST_Function;
416 return SymbolRef::ST_Other;
419 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
420 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
422 uint8_t MachOType = Entry.n_type;
423 uint16_t MachOFlags = Entry.n_desc;
425 uint32_t Result = SymbolRef::SF_None;
427 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
428 Result |= SymbolRef::SF_Undefined;
430 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
431 Result |= SymbolRef::SF_Indirect;
433 if (MachOType & MachO::N_STAB)
434 Result |= SymbolRef::SF_FormatSpecific;
436 if (MachOType & MachO::N_EXT) {
437 Result |= SymbolRef::SF_Global;
438 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
440 getSymbolAddress(DRI, Value);
441 if (Value && Value != UnknownAddress)
442 Result |= SymbolRef::SF_Common;
445 if (!(MachOType & MachO::N_PEXT))
446 Result |= SymbolRef::SF_Exported;
449 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
450 Result |= SymbolRef::SF_Weak;
452 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
453 Result |= SymbolRef::SF_Thumb;
455 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
456 Result |= SymbolRef::SF_Absolute;
461 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
462 section_iterator &Res) const {
463 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
464 uint8_t index = Entry.n_sect;
471 if (DRI.d.a >= Sections.size())
472 report_fatal_error("getSymbolSection: Invalid section index.");
473 Res = section_iterator(SectionRef(DRI, this));
476 return std::error_code();
479 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
480 MachO::nlist_base Entry =
481 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
482 return Entry.n_sect - 1;
485 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
489 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
490 StringRef &Result) const {
491 ArrayRef<char> Raw = getSectionRawName(Sec);
492 Result = parseSegmentOrSectionName(Raw.data());
493 return std::error_code();
496 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
498 return getSection64(Sec).addr;
499 return getSection(Sec).addr;
502 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
504 return getSection64(Sec).size;
505 return getSection(Sec).size;
508 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
509 StringRef &Res) const {
514 MachO::section_64 Sect = getSection64(Sec);
515 Offset = Sect.offset;
518 MachO::section Sect = getSection(Sec);
519 Offset = Sect.offset;
523 Res = this->getData().substr(Offset, Size);
524 return std::error_code();
527 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
530 MachO::section_64 Sect = getSection64(Sec);
533 MachO::section Sect = getSection(Sec);
537 return uint64_t(1) << Align;
540 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
541 uint32_t Flags = getSectionFlags(this, Sec);
542 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
545 bool MachOObjectFile::isSectionData(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 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
554 uint32_t Flags = getSectionFlags(this, Sec);
555 unsigned SectionType = Flags & MachO::SECTION_TYPE;
556 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
557 (SectionType == MachO::S_ZEROFILL ||
558 SectionType == MachO::S_GB_ZEROFILL);
561 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
562 return Sec.getRawDataRefImpl().d.a;
565 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
566 // FIXME: Unimplemented.
570 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
571 DataRefImpl Symb) const {
572 SymbolRef::Type ST = getSymbolType(Symb);
573 if (ST == SymbolRef::ST_Unknown)
576 uint64_t SectBegin = getSectionAddress(Sec);
577 uint64_t SectEnd = getSectionSize(Sec);
578 SectEnd += SectBegin;
581 getSymbolAddress(Symb, SymAddr);
582 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
585 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
589 return relocation_iterator(RelocationRef(Ret, this));
593 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
596 MachO::section_64 Sect = getSection64(Sec);
599 MachO::section Sect = getSection(Sec);
606 return relocation_iterator(RelocationRef(Ret, this));
609 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
613 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
614 uint64_t &Res) const {
615 uint64_t Offset = getRelocationOffset(Rel);
619 uint64_t SecAddress = getSectionAddress(Sec);
620 Res = SecAddress + Offset;
621 return std::error_code();
624 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
625 assert(getHeader().filetype == MachO::MH_OBJECT &&
626 "Only implemented for MH_OBJECT");
627 MachO::any_relocation_info RE = getRelocation(Rel);
628 return getAnyRelocationAddress(RE);
632 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
633 MachO::any_relocation_info RE = getRelocation(Rel);
634 if (isRelocationScattered(RE))
637 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
638 bool isExtern = getPlainRelocationExternal(RE);
642 MachO::symtab_command S = getSymtabLoadCommand();
643 unsigned SymbolTableEntrySize = is64Bit() ?
644 sizeof(MachO::nlist_64) :
645 sizeof(MachO::nlist);
646 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
648 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
649 return symbol_iterator(SymbolRef(Sym, this));
653 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
654 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
657 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
658 MachO::any_relocation_info RE = getRelocation(Rel);
659 return getAnyRelocationType(RE);
663 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
664 SmallVectorImpl<char> &Result) const {
666 uint64_t RType = getRelocationType(Rel);
668 unsigned Arch = this->getArch();
672 static const char *const Table[] = {
673 "GENERIC_RELOC_VANILLA",
674 "GENERIC_RELOC_PAIR",
675 "GENERIC_RELOC_SECTDIFF",
676 "GENERIC_RELOC_PB_LA_PTR",
677 "GENERIC_RELOC_LOCAL_SECTDIFF",
678 "GENERIC_RELOC_TLV" };
686 case Triple::x86_64: {
687 static const char *const Table[] = {
688 "X86_64_RELOC_UNSIGNED",
689 "X86_64_RELOC_SIGNED",
690 "X86_64_RELOC_BRANCH",
691 "X86_64_RELOC_GOT_LOAD",
693 "X86_64_RELOC_SUBTRACTOR",
694 "X86_64_RELOC_SIGNED_1",
695 "X86_64_RELOC_SIGNED_2",
696 "X86_64_RELOC_SIGNED_4",
697 "X86_64_RELOC_TLV" };
706 static const char *const Table[] = {
709 "ARM_RELOC_SECTDIFF",
710 "ARM_RELOC_LOCAL_SECTDIFF",
711 "ARM_RELOC_PB_LA_PTR",
713 "ARM_THUMB_RELOC_BR22",
714 "ARM_THUMB_32BIT_BRANCH",
716 "ARM_RELOC_HALF_SECTDIFF" };
724 case Triple::aarch64: {
725 static const char *const Table[] = {
726 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
727 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
728 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
729 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
730 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
734 if (RType >= array_lengthof(Table))
741 static const char *const Table[] = {
750 "PPC_RELOC_SECTDIFF",
751 "PPC_RELOC_PB_LA_PTR",
752 "PPC_RELOC_HI16_SECTDIFF",
753 "PPC_RELOC_LO16_SECTDIFF",
754 "PPC_RELOC_HA16_SECTDIFF",
756 "PPC_RELOC_LO14_SECTDIFF",
757 "PPC_RELOC_LOCAL_SECTDIFF" };
765 case Triple::UnknownArch:
769 Result.append(res.begin(), res.end());
770 return std::error_code();
773 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
774 bool &Result) const {
775 unsigned Arch = getArch();
776 uint64_t Type = getRelocationType(Rel);
780 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
782 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
783 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
784 } else if (Arch == Triple::x86_64) {
785 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
786 // an X86_64_RELOC_SUBTRACTOR.
787 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
788 DataRefImpl RelPrev = Rel;
790 uint64_t PrevType = getRelocationType(RelPrev);
791 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
796 return std::error_code();
799 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
800 MachO::any_relocation_info RE = getRelocation(Rel);
801 return getAnyRelocationLength(RE);
805 // guessLibraryShortName() is passed a name of a dynamic library and returns a
806 // guess on what the short name is. Then name is returned as a substring of the
807 // StringRef Name passed in. The name of the dynamic library is recognized as
808 // a framework if it has one of the two following forms:
809 // Foo.framework/Versions/A/Foo
811 // Where A and Foo can be any string. And may contain a trailing suffix
812 // starting with an underbar. If the Name is recognized as a framework then
813 // isFramework is set to true else it is set to false. If the Name has a
814 // suffix then Suffix is set to the substring in Name that contains the suffix
815 // else it is set to a NULL StringRef.
817 // The Name of the dynamic library is recognized as a library name if it has
818 // one of the two following forms:
821 // The library may have a suffix trailing the name Foo of the form:
822 // libFoo_profile.A.dylib
823 // libFoo_profile.dylib
825 // The Name of the dynamic library is also recognized as a library name if it
826 // has the following form:
829 // If the Name of the dynamic library is none of the forms above then a NULL
830 // StringRef is returned.
832 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
835 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
836 size_t a, b, c, d, Idx;
839 Suffix = StringRef();
841 // Pull off the last component and make Foo point to it
843 if (a == Name.npos || a == 0)
845 Foo = Name.slice(a+1, Name.npos);
847 // Look for a suffix starting with a '_'
848 Idx = Foo.rfind('_');
849 if (Idx != Foo.npos && Foo.size() >= 2) {
850 Suffix = Foo.slice(Idx, Foo.npos);
851 Foo = Foo.slice(0, Idx);
854 // First look for the form Foo.framework/Foo
855 b = Name.rfind('/', a);
860 F = Name.slice(Idx, Idx + Foo.size());
861 DotFramework = Name.slice(Idx + Foo.size(),
862 Idx + Foo.size() + sizeof(".framework/")-1);
863 if (F == Foo && DotFramework == ".framework/") {
868 // Next look for the form Foo.framework/Versions/A/Foo
871 c = Name.rfind('/', b);
872 if (c == Name.npos || c == 0)
874 V = Name.slice(c+1, Name.npos);
875 if (!V.startswith("Versions/"))
877 d = Name.rfind('/', c);
882 F = Name.slice(Idx, Idx + Foo.size());
883 DotFramework = Name.slice(Idx + Foo.size(),
884 Idx + Foo.size() + sizeof(".framework/")-1);
885 if (F == Foo && DotFramework == ".framework/") {
891 // pull off the suffix after the "." and make a point to it
893 if (a == Name.npos || a == 0)
895 Dylib = Name.slice(a, Name.npos);
896 if (Dylib != ".dylib")
899 // First pull off the version letter for the form Foo.A.dylib if any.
901 Dot = Name.slice(a-2, a-1);
906 b = Name.rfind('/', a);
911 // ignore any suffix after an underbar like Foo_profile.A.dylib
912 Idx = Name.find('_', b);
913 if (Idx != Name.npos && Idx != b) {
914 Lib = Name.slice(b, Idx);
915 Suffix = Name.slice(Idx, a);
918 Lib = Name.slice(b, a);
919 // There are incorrect library names of the form:
920 // libATS.A_profile.dylib so check for these.
921 if (Lib.size() >= 3) {
922 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
924 Lib = Lib.slice(0, Lib.size()-2);
929 Qtx = Name.slice(a, Name.npos);
932 b = Name.rfind('/', a);
934 Lib = Name.slice(0, a);
936 Lib = Name.slice(b+1, a);
937 // There are library names of the form: QT.A.qtx so check for these.
938 if (Lib.size() >= 3) {
939 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
941 Lib = Lib.slice(0, Lib.size()-2);
946 // getLibraryShortNameByIndex() is used to get the short name of the library
947 // for an undefined symbol in a linked Mach-O binary that was linked with the
948 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
949 // It is passed the index (0 - based) of the library as translated from
950 // GET_LIBRARY_ORDINAL (1 - based).
951 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
952 StringRef &Res) const {
953 if (Index >= Libraries.size())
954 return object_error::parse_failed;
956 // If the cache of LibrariesShortNames is not built up do that first for
957 // all the Libraries.
958 if (LibrariesShortNames.size() == 0) {
959 for (unsigned i = 0; i < Libraries.size(); i++) {
960 MachO::dylib_command D =
961 getStruct<MachO::dylib_command>(this, Libraries[i]);
962 if (D.dylib.name >= D.cmdsize)
963 return object_error::parse_failed;
964 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
965 StringRef Name = StringRef(P);
966 if (D.dylib.name+Name.size() >= D.cmdsize)
967 return object_error::parse_failed;
970 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
971 if (shortName.empty())
972 LibrariesShortNames.push_back(Name);
974 LibrariesShortNames.push_back(shortName);
978 Res = LibrariesShortNames[Index];
979 return std::error_code();
982 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
983 return getSymbolByIndex(0);
986 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
989 return basic_symbol_iterator(SymbolRef(DRI, this));
991 MachO::symtab_command Symtab = getSymtabLoadCommand();
992 unsigned SymbolTableEntrySize = is64Bit() ?
993 sizeof(MachO::nlist_64) :
994 sizeof(MachO::nlist);
995 unsigned Offset = Symtab.symoff +
996 Symtab.nsyms * SymbolTableEntrySize;
997 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
998 return basic_symbol_iterator(SymbolRef(DRI, this));
1001 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1004 return basic_symbol_iterator(SymbolRef(DRI, this));
1006 MachO::symtab_command Symtab = getSymtabLoadCommand();
1007 if (Index >= Symtab.nsyms)
1008 report_fatal_error("Requested symbol index is out of range.");
1009 unsigned SymbolTableEntrySize =
1010 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1011 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1012 DRI.p += Index * SymbolTableEntrySize;
1013 return basic_symbol_iterator(SymbolRef(DRI, this));
1016 section_iterator MachOObjectFile::section_begin() const {
1018 return section_iterator(SectionRef(DRI, this));
1021 section_iterator MachOObjectFile::section_end() const {
1023 DRI.d.a = Sections.size();
1024 return section_iterator(SectionRef(DRI, this));
1027 uint8_t MachOObjectFile::getBytesInAddress() const {
1028 return is64Bit() ? 8 : 4;
1031 StringRef MachOObjectFile::getFileFormatName() const {
1032 unsigned CPUType = getCPUType(this);
1035 case llvm::MachO::CPU_TYPE_I386:
1036 return "Mach-O 32-bit i386";
1037 case llvm::MachO::CPU_TYPE_ARM:
1038 return "Mach-O arm";
1039 case llvm::MachO::CPU_TYPE_POWERPC:
1040 return "Mach-O 32-bit ppc";
1042 return "Mach-O 32-bit unknown";
1047 case llvm::MachO::CPU_TYPE_X86_64:
1048 return "Mach-O 64-bit x86-64";
1049 case llvm::MachO::CPU_TYPE_ARM64:
1050 return "Mach-O arm64";
1051 case llvm::MachO::CPU_TYPE_POWERPC64:
1052 return "Mach-O 64-bit ppc64";
1054 return "Mach-O 64-bit unknown";
1058 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1060 case llvm::MachO::CPU_TYPE_I386:
1062 case llvm::MachO::CPU_TYPE_X86_64:
1063 return Triple::x86_64;
1064 case llvm::MachO::CPU_TYPE_ARM:
1066 case llvm::MachO::CPU_TYPE_ARM64:
1067 return Triple::aarch64;
1068 case llvm::MachO::CPU_TYPE_POWERPC:
1070 case llvm::MachO::CPU_TYPE_POWERPC64:
1071 return Triple::ppc64;
1073 return Triple::UnknownArch;
1077 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1078 const char **McpuDefault) {
1080 *McpuDefault = nullptr;
1083 case MachO::CPU_TYPE_I386:
1084 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1085 case MachO::CPU_SUBTYPE_I386_ALL:
1086 return Triple("i386-apple-darwin");
1090 case MachO::CPU_TYPE_X86_64:
1091 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1092 case MachO::CPU_SUBTYPE_X86_64_ALL:
1093 return Triple("x86_64-apple-darwin");
1094 case MachO::CPU_SUBTYPE_X86_64_H:
1095 return Triple("x86_64h-apple-darwin");
1099 case MachO::CPU_TYPE_ARM:
1100 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1101 case MachO::CPU_SUBTYPE_ARM_V4T:
1102 return Triple("armv4t-apple-darwin");
1103 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1104 return Triple("armv5e-apple-darwin");
1105 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1106 return Triple("xscale-apple-darwin");
1107 case MachO::CPU_SUBTYPE_ARM_V6:
1108 return Triple("armv6-apple-darwin");
1109 case MachO::CPU_SUBTYPE_ARM_V6M:
1111 *McpuDefault = "cortex-m0";
1112 return Triple("armv6m-apple-darwin");
1113 case MachO::CPU_SUBTYPE_ARM_V7:
1114 return Triple("armv7-apple-darwin");
1115 case MachO::CPU_SUBTYPE_ARM_V7EM:
1117 *McpuDefault = "cortex-m4";
1118 return Triple("armv7em-apple-darwin");
1119 case MachO::CPU_SUBTYPE_ARM_V7K:
1120 return Triple("armv7k-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V7M:
1123 *McpuDefault = "cortex-m3";
1124 return Triple("armv7m-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V7S:
1126 return Triple("armv7s-apple-darwin");
1130 case MachO::CPU_TYPE_ARM64:
1131 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1132 case MachO::CPU_SUBTYPE_ARM64_ALL:
1133 return Triple("arm64-apple-darwin");
1137 case MachO::CPU_TYPE_POWERPC:
1138 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1139 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1140 return Triple("ppc-apple-darwin");
1144 case MachO::CPU_TYPE_POWERPC64:
1145 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1146 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1147 return Triple("ppc64-apple-darwin");
1156 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1157 const char **McpuDefault) {
1159 *McpuDefault = nullptr;
1162 case MachO::CPU_TYPE_ARM:
1163 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1164 case MachO::CPU_SUBTYPE_ARM_V4T:
1165 return Triple("thumbv4t-apple-darwin");
1166 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1167 return Triple("thumbv5e-apple-darwin");
1168 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1169 return Triple("xscale-apple-darwin");
1170 case MachO::CPU_SUBTYPE_ARM_V6:
1171 return Triple("thumbv6-apple-darwin");
1172 case MachO::CPU_SUBTYPE_ARM_V6M:
1174 *McpuDefault = "cortex-m0";
1175 return Triple("thumbv6m-apple-darwin");
1176 case MachO::CPU_SUBTYPE_ARM_V7:
1177 return Triple("thumbv7-apple-darwin");
1178 case MachO::CPU_SUBTYPE_ARM_V7EM:
1180 *McpuDefault = "cortex-m4";
1181 return Triple("thumbv7em-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_V7K:
1183 return Triple("thumbv7k-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V7M:
1186 *McpuDefault = "cortex-m3";
1187 return Triple("thumbv7m-apple-darwin");
1188 case MachO::CPU_SUBTYPE_ARM_V7S:
1189 return Triple("thumbv7s-apple-darwin");
1198 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1199 const char **McpuDefault,
1200 Triple *ThumbTriple) {
1201 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1202 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1207 Triple MachOObjectFile::getHostArch() {
1208 return Triple(sys::getDefaultTargetTriple());
1211 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1212 return StringSwitch<bool>(ArchFlag)
1214 .Case("x86_64", true)
1215 .Case("x86_64h", true)
1216 .Case("armv4t", true)
1218 .Case("armv5e", true)
1219 .Case("armv6", true)
1220 .Case("armv6m", true)
1221 .Case("armv7", true)
1222 .Case("armv7em", true)
1223 .Case("armv7k", true)
1224 .Case("armv7m", true)
1225 .Case("armv7s", true)
1226 .Case("arm64", true)
1228 .Case("ppc64", true)
1232 unsigned MachOObjectFile::getArch() const {
1233 return getArch(getCPUType(this));
1236 Triple MachOObjectFile::getArch(const char **McpuDefault,
1237 Triple *ThumbTriple) const {
1238 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1239 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1242 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1245 return section_rel_begin(DRI);
1248 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1251 return section_rel_end(DRI);
1254 dice_iterator MachOObjectFile::begin_dices() const {
1256 if (!DataInCodeLoadCmd)
1257 return dice_iterator(DiceRef(DRI, this));
1259 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1260 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1261 return dice_iterator(DiceRef(DRI, this));
1264 dice_iterator MachOObjectFile::end_dices() const {
1266 if (!DataInCodeLoadCmd)
1267 return dice_iterator(DiceRef(DRI, this));
1269 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1270 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1271 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1272 return dice_iterator(DiceRef(DRI, this));
1275 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1276 : Trie(T), Malformed(false), Done(false) { }
1278 void ExportEntry::moveToFirst() {
1280 pushDownUntilBottom();
1283 void ExportEntry::moveToEnd() {
1288 bool ExportEntry::operator==(const ExportEntry &Other) const {
1289 // Common case, one at end, other iterating from begin.
1290 if (Done || Other.Done)
1291 return (Done == Other.Done);
1292 // Not equal if different stack sizes.
1293 if (Stack.size() != Other.Stack.size())
1295 // Not equal if different cumulative strings.
1296 if (!CumulativeString.equals(Other.CumulativeString))
1298 // Equal if all nodes in both stacks match.
1299 for (unsigned i=0; i < Stack.size(); ++i) {
1300 if (Stack[i].Start != Other.Stack[i].Start)
1306 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1308 uint64_t Result = decodeULEB128(Ptr, &Count);
1310 if (Ptr > Trie.end()) {
1317 StringRef ExportEntry::name() const {
1318 return CumulativeString;
1321 uint64_t ExportEntry::flags() const {
1322 return Stack.back().Flags;
1325 uint64_t ExportEntry::address() const {
1326 return Stack.back().Address;
1329 uint64_t ExportEntry::other() const {
1330 return Stack.back().Other;
1333 StringRef ExportEntry::otherName() const {
1334 const char* ImportName = Stack.back().ImportName;
1336 return StringRef(ImportName);
1340 uint32_t ExportEntry::nodeOffset() const {
1341 return Stack.back().Start - Trie.begin();
1344 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1345 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1346 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1347 ParentStringLength(0), IsExportNode(false) {
1350 void ExportEntry::pushNode(uint64_t offset) {
1351 const uint8_t *Ptr = Trie.begin() + offset;
1352 NodeState State(Ptr);
1353 uint64_t ExportInfoSize = readULEB128(State.Current);
1354 State.IsExportNode = (ExportInfoSize != 0);
1355 const uint8_t* Children = State.Current + ExportInfoSize;
1356 if (State.IsExportNode) {
1357 State.Flags = readULEB128(State.Current);
1358 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1360 State.Other = readULEB128(State.Current); // dylib ordinal
1361 State.ImportName = reinterpret_cast<const char*>(State.Current);
1363 State.Address = readULEB128(State.Current);
1364 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1365 State.Other = readULEB128(State.Current);
1368 State.ChildCount = *Children;
1369 State.Current = Children + 1;
1370 State.NextChildIndex = 0;
1371 State.ParentStringLength = CumulativeString.size();
1372 Stack.push_back(State);
1375 void ExportEntry::pushDownUntilBottom() {
1376 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1377 NodeState &Top = Stack.back();
1378 CumulativeString.resize(Top.ParentStringLength);
1379 for (;*Top.Current != 0; Top.Current++) {
1380 char C = *Top.Current;
1381 CumulativeString.push_back(C);
1384 uint64_t childNodeIndex = readULEB128(Top.Current);
1385 Top.NextChildIndex += 1;
1386 pushNode(childNodeIndex);
1388 if (!Stack.back().IsExportNode) {
1394 // We have a trie data structure and need a way to walk it that is compatible
1395 // with the C++ iterator model. The solution is a non-recursive depth first
1396 // traversal where the iterator contains a stack of parent nodes along with a
1397 // string that is the accumulation of all edge strings along the parent chain
1400 // There is one "export" node for each exported symbol. But because some
1401 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1402 // node may have child nodes too.
1404 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1405 // child until hitting a node with no children (which is an export node or
1406 // else the trie is malformed). On the way down, each node is pushed on the
1407 // stack ivar. If there is no more ways down, it pops up one and tries to go
1408 // down a sibling path until a childless node is reached.
1409 void ExportEntry::moveNext() {
1410 if (Stack.empty() || !Stack.back().IsExportNode) {
1417 while (!Stack.empty()) {
1418 NodeState &Top = Stack.back();
1419 if (Top.NextChildIndex < Top.ChildCount) {
1420 pushDownUntilBottom();
1421 // Now at the next export node.
1424 if (Top.IsExportNode) {
1425 // This node has no children but is itself an export node.
1426 CumulativeString.resize(Top.ParentStringLength);
1435 iterator_range<export_iterator>
1436 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1437 ExportEntry Start(Trie);
1438 if (Trie.size() == 0)
1441 Start.moveToFirst();
1443 ExportEntry Finish(Trie);
1446 return iterator_range<export_iterator>(export_iterator(Start),
1447 export_iterator(Finish));
1450 iterator_range<export_iterator> MachOObjectFile::exports() const {
1451 return exports(getDyldInfoExportsTrie());
1455 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1456 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1457 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1458 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1460 void MachORebaseEntry::moveToFirst() {
1461 Ptr = Opcodes.begin();
1465 void MachORebaseEntry::moveToEnd() {
1466 Ptr = Opcodes.end();
1467 RemainingLoopCount = 0;
1471 void MachORebaseEntry::moveNext() {
1472 // If in the middle of some loop, move to next rebasing in loop.
1473 SegmentOffset += AdvanceAmount;
1474 if (RemainingLoopCount) {
1475 --RemainingLoopCount;
1478 if (Ptr == Opcodes.end()) {
1483 while (More && !Malformed) {
1484 // Parse next opcode and set up next loop.
1485 uint8_t Byte = *Ptr++;
1486 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1487 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1489 case MachO::REBASE_OPCODE_DONE:
1493 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1495 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1496 RebaseType = ImmValue;
1499 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1500 << "RebaseType=" << (int) RebaseType << "\n");
1502 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1503 SegmentIndex = ImmValue;
1504 SegmentOffset = readULEB128();
1507 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1508 << "SegmentIndex=" << SegmentIndex << ", "
1509 << format("SegmentOffset=0x%06X", SegmentOffset)
1512 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1513 SegmentOffset += readULEB128();
1514 DEBUG_WITH_TYPE("mach-o-rebase",
1515 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1516 << format("SegmentOffset=0x%06X",
1517 SegmentOffset) << "\n");
1519 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1520 SegmentOffset += ImmValue * PointerSize;
1521 DEBUG_WITH_TYPE("mach-o-rebase",
1522 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1523 << format("SegmentOffset=0x%06X",
1524 SegmentOffset) << "\n");
1526 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1527 AdvanceAmount = PointerSize;
1528 RemainingLoopCount = ImmValue - 1;
1531 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1532 << format("SegmentOffset=0x%06X", SegmentOffset)
1533 << ", AdvanceAmount=" << AdvanceAmount
1534 << ", RemainingLoopCount=" << RemainingLoopCount
1537 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1538 AdvanceAmount = PointerSize;
1539 RemainingLoopCount = readULEB128() - 1;
1542 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1543 << format("SegmentOffset=0x%06X", SegmentOffset)
1544 << ", AdvanceAmount=" << AdvanceAmount
1545 << ", RemainingLoopCount=" << RemainingLoopCount
1548 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1549 AdvanceAmount = readULEB128() + PointerSize;
1550 RemainingLoopCount = 0;
1553 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1554 << format("SegmentOffset=0x%06X", SegmentOffset)
1555 << ", AdvanceAmount=" << AdvanceAmount
1556 << ", RemainingLoopCount=" << RemainingLoopCount
1559 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1560 RemainingLoopCount = readULEB128() - 1;
1561 AdvanceAmount = readULEB128() + PointerSize;
1564 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1565 << format("SegmentOffset=0x%06X", SegmentOffset)
1566 << ", AdvanceAmount=" << AdvanceAmount
1567 << ", RemainingLoopCount=" << RemainingLoopCount
1576 uint64_t MachORebaseEntry::readULEB128() {
1578 uint64_t Result = decodeULEB128(Ptr, &Count);
1580 if (Ptr > Opcodes.end()) {
1581 Ptr = Opcodes.end();
1587 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1589 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1591 StringRef MachORebaseEntry::typeName() const {
1592 switch (RebaseType) {
1593 case MachO::REBASE_TYPE_POINTER:
1595 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1596 return "text abs32";
1597 case MachO::REBASE_TYPE_TEXT_PCREL32:
1598 return "text rel32";
1603 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1604 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1605 return (Ptr == Other.Ptr) &&
1606 (RemainingLoopCount == Other.RemainingLoopCount) &&
1607 (Done == Other.Done);
1610 iterator_range<rebase_iterator>
1611 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1612 MachORebaseEntry Start(Opcodes, is64);
1613 Start.moveToFirst();
1615 MachORebaseEntry Finish(Opcodes, is64);
1618 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1619 rebase_iterator(Finish));
1622 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1623 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1627 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1629 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1630 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1631 BindType(0), PointerSize(is64Bit ? 8 : 4),
1632 TableKind(BK), Malformed(false), Done(false) {}
1634 void MachOBindEntry::moveToFirst() {
1635 Ptr = Opcodes.begin();
1639 void MachOBindEntry::moveToEnd() {
1640 Ptr = Opcodes.end();
1641 RemainingLoopCount = 0;
1645 void MachOBindEntry::moveNext() {
1646 // If in the middle of some loop, move to next binding in loop.
1647 SegmentOffset += AdvanceAmount;
1648 if (RemainingLoopCount) {
1649 --RemainingLoopCount;
1652 if (Ptr == Opcodes.end()) {
1657 while (More && !Malformed) {
1658 // Parse next opcode and set up next loop.
1659 uint8_t Byte = *Ptr++;
1660 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1661 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1662 int8_t SignExtended;
1663 const uint8_t *SymStart;
1665 case MachO::BIND_OPCODE_DONE:
1666 if (TableKind == Kind::Lazy) {
1667 // Lazying bindings have a DONE opcode between entries. Need to ignore
1668 // it to advance to next entry. But need not if this is last entry.
1669 bool NotLastEntry = false;
1670 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1672 NotLastEntry = true;
1681 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1683 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1687 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1688 << "Ordinal=" << Ordinal << "\n");
1690 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1691 Ordinal = readULEB128();
1694 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1695 << "Ordinal=" << Ordinal << "\n");
1697 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1699 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1700 Ordinal = SignExtended;
1705 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1706 << "Ordinal=" << Ordinal << "\n");
1708 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1714 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1719 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1720 << "SymbolName=" << SymbolName << "\n");
1721 if (TableKind == Kind::Weak) {
1722 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1726 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1727 BindType = ImmValue;
1730 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1731 << "BindType=" << (int)BindType << "\n");
1733 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1734 Addend = readSLEB128();
1735 if (TableKind == Kind::Lazy)
1739 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1740 << "Addend=" << Addend << "\n");
1742 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1743 SegmentIndex = ImmValue;
1744 SegmentOffset = readULEB128();
1747 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1748 << "SegmentIndex=" << SegmentIndex << ", "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1752 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1753 SegmentOffset += readULEB128();
1754 DEBUG_WITH_TYPE("mach-o-bind",
1755 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1756 << format("SegmentOffset=0x%06X",
1757 SegmentOffset) << "\n");
1759 case MachO::BIND_OPCODE_DO_BIND:
1760 AdvanceAmount = PointerSize;
1761 RemainingLoopCount = 0;
1762 DEBUG_WITH_TYPE("mach-o-bind",
1763 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1764 << format("SegmentOffset=0x%06X",
1765 SegmentOffset) << "\n");
1767 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1768 AdvanceAmount = readULEB128() + PointerSize;
1769 RemainingLoopCount = 0;
1770 if (TableKind == Kind::Lazy)
1774 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1775 << format("SegmentOffset=0x%06X", SegmentOffset)
1776 << ", AdvanceAmount=" << AdvanceAmount
1777 << ", RemainingLoopCount=" << RemainingLoopCount
1780 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1781 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1782 RemainingLoopCount = 0;
1783 if (TableKind == Kind::Lazy)
1785 DEBUG_WITH_TYPE("mach-o-bind",
1787 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1788 << format("SegmentOffset=0x%06X",
1789 SegmentOffset) << "\n");
1791 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1792 RemainingLoopCount = readULEB128() - 1;
1793 AdvanceAmount = readULEB128() + PointerSize;
1794 if (TableKind == Kind::Lazy)
1798 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1799 << format("SegmentOffset=0x%06X", SegmentOffset)
1800 << ", AdvanceAmount=" << AdvanceAmount
1801 << ", RemainingLoopCount=" << RemainingLoopCount
1810 uint64_t MachOBindEntry::readULEB128() {
1812 uint64_t Result = decodeULEB128(Ptr, &Count);
1814 if (Ptr > Opcodes.end()) {
1815 Ptr = Opcodes.end();
1821 int64_t MachOBindEntry::readSLEB128() {
1823 int64_t Result = decodeSLEB128(Ptr, &Count);
1825 if (Ptr > Opcodes.end()) {
1826 Ptr = Opcodes.end();
1833 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1835 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1837 StringRef MachOBindEntry::typeName() const {
1839 case MachO::BIND_TYPE_POINTER:
1841 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1842 return "text abs32";
1843 case MachO::BIND_TYPE_TEXT_PCREL32:
1844 return "text rel32";
1849 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1851 int64_t MachOBindEntry::addend() const { return Addend; }
1853 uint32_t MachOBindEntry::flags() const { return Flags; }
1855 int MachOBindEntry::ordinal() const { return Ordinal; }
1857 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1858 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1859 return (Ptr == Other.Ptr) &&
1860 (RemainingLoopCount == Other.RemainingLoopCount) &&
1861 (Done == Other.Done);
1864 iterator_range<bind_iterator>
1865 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1866 MachOBindEntry::Kind BKind) {
1867 MachOBindEntry Start(Opcodes, is64, BKind);
1868 Start.moveToFirst();
1870 MachOBindEntry Finish(Opcodes, is64, BKind);
1873 return iterator_range<bind_iterator>(bind_iterator(Start),
1874 bind_iterator(Finish));
1877 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1878 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1879 MachOBindEntry::Kind::Regular);
1882 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1883 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1884 MachOBindEntry::Kind::Lazy);
1887 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1888 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1889 MachOBindEntry::Kind::Weak);
1892 MachOObjectFile::load_command_iterator
1893 MachOObjectFile::begin_load_commands() const {
1894 return LoadCommands.begin();
1897 MachOObjectFile::load_command_iterator
1898 MachOObjectFile::end_load_commands() const {
1899 return LoadCommands.end();
1902 iterator_range<MachOObjectFile::load_command_iterator>
1903 MachOObjectFile::load_commands() const {
1904 return iterator_range<load_command_iterator>(begin_load_commands(),
1905 end_load_commands());
1909 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1910 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1911 return parseSegmentOrSectionName(Raw.data());
1915 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1916 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1917 const section_base *Base =
1918 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1919 return makeArrayRef(Base->sectname);
1923 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1924 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1925 const section_base *Base =
1926 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1927 return makeArrayRef(Base->segname);
1931 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1933 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1935 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1938 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1939 const MachO::any_relocation_info &RE) const {
1940 if (isLittleEndian())
1941 return RE.r_word1 & 0xffffff;
1942 return RE.r_word1 >> 8;
1945 bool MachOObjectFile::getPlainRelocationExternal(
1946 const MachO::any_relocation_info &RE) const {
1947 if (isLittleEndian())
1948 return (RE.r_word1 >> 27) & 1;
1949 return (RE.r_word1 >> 4) & 1;
1952 bool MachOObjectFile::getScatteredRelocationScattered(
1953 const MachO::any_relocation_info &RE) const {
1954 return RE.r_word0 >> 31;
1957 uint32_t MachOObjectFile::getScatteredRelocationValue(
1958 const MachO::any_relocation_info &RE) const {
1962 uint32_t MachOObjectFile::getScatteredRelocationType(
1963 const MachO::any_relocation_info &RE) const {
1964 return (RE.r_word0 >> 24) & 0xf;
1967 unsigned MachOObjectFile::getAnyRelocationAddress(
1968 const MachO::any_relocation_info &RE) const {
1969 if (isRelocationScattered(RE))
1970 return getScatteredRelocationAddress(RE);
1971 return getPlainRelocationAddress(RE);
1974 unsigned MachOObjectFile::getAnyRelocationPCRel(
1975 const MachO::any_relocation_info &RE) const {
1976 if (isRelocationScattered(RE))
1977 return getScatteredRelocationPCRel(this, RE);
1978 return getPlainRelocationPCRel(this, RE);
1981 unsigned MachOObjectFile::getAnyRelocationLength(
1982 const MachO::any_relocation_info &RE) const {
1983 if (isRelocationScattered(RE))
1984 return getScatteredRelocationLength(RE);
1985 return getPlainRelocationLength(this, RE);
1989 MachOObjectFile::getAnyRelocationType(
1990 const MachO::any_relocation_info &RE) const {
1991 if (isRelocationScattered(RE))
1992 return getScatteredRelocationType(RE);
1993 return getPlainRelocationType(this, RE);
1997 MachOObjectFile::getAnyRelocationSection(
1998 const MachO::any_relocation_info &RE) const {
1999 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2000 return *section_end();
2001 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2002 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2003 return *section_end();
2005 DRI.d.a = SecNum - 1;
2006 return SectionRef(DRI, this);
2009 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2010 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2011 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2014 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2015 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2016 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2019 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2020 unsigned Index) const {
2021 const char *Sec = getSectionPtr(this, L, Index);
2022 return getStruct<MachO::section>(this, Sec);
2025 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2026 unsigned Index) const {
2027 const char *Sec = getSectionPtr(this, L, Index);
2028 return getStruct<MachO::section_64>(this, Sec);
2032 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2033 const char *P = reinterpret_cast<const char *>(DRI.p);
2034 return getStruct<MachO::nlist>(this, P);
2038 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2039 const char *P = reinterpret_cast<const char *>(DRI.p);
2040 return getStruct<MachO::nlist_64>(this, P);
2043 MachO::linkedit_data_command
2044 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2045 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2048 MachO::segment_command
2049 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2050 return getStruct<MachO::segment_command>(this, L.Ptr);
2053 MachO::segment_command_64
2054 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2055 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2058 MachO::linker_option_command
2059 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2060 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2063 MachO::version_min_command
2064 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2065 return getStruct<MachO::version_min_command>(this, L.Ptr);
2068 MachO::dylib_command
2069 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2070 return getStruct<MachO::dylib_command>(this, L.Ptr);
2073 MachO::dyld_info_command
2074 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2075 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2078 MachO::dylinker_command
2079 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2080 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2084 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2085 return getStruct<MachO::uuid_command>(this, L.Ptr);
2088 MachO::rpath_command
2089 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2090 return getStruct<MachO::rpath_command>(this, L.Ptr);
2093 MachO::source_version_command
2094 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2095 return getStruct<MachO::source_version_command>(this, L.Ptr);
2098 MachO::entry_point_command
2099 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2100 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2103 MachO::encryption_info_command
2104 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2105 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2108 MachO::encryption_info_command_64
2109 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2110 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2113 MachO::sub_framework_command
2114 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2115 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2118 MachO::sub_umbrella_command
2119 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2120 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2123 MachO::sub_library_command
2124 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2125 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2128 MachO::sub_client_command
2129 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2130 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2133 MachO::routines_command
2134 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2135 return getStruct<MachO::routines_command>(this, L.Ptr);
2138 MachO::routines_command_64
2139 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2140 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2143 MachO::thread_command
2144 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2145 return getStruct<MachO::thread_command>(this, L.Ptr);
2148 MachO::any_relocation_info
2149 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2154 MachO::section_64 Sect = getSection64(Sec);
2155 Offset = Sect.reloff;
2157 MachO::section Sect = getSection(Sec);
2158 Offset = Sect.reloff;
2161 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2162 getPtr(this, Offset)) + Rel.d.b;
2163 return getStruct<MachO::any_relocation_info>(
2164 this, reinterpret_cast<const char *>(P));
2167 MachO::data_in_code_entry
2168 MachOObjectFile::getDice(DataRefImpl Rel) const {
2169 const char *P = reinterpret_cast<const char *>(Rel.p);
2170 return getStruct<MachO::data_in_code_entry>(this, P);
2173 const MachO::mach_header &MachOObjectFile::getHeader() const {
2177 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2182 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2183 const MachO::dysymtab_command &DLC,
2184 unsigned Index) const {
2185 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2186 return getStruct<uint32_t>(this, getPtr(this, Offset));
2189 MachO::data_in_code_entry
2190 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2191 unsigned Index) const {
2192 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2193 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2196 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2198 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2200 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2201 MachO::symtab_command Cmd;
2202 Cmd.cmd = MachO::LC_SYMTAB;
2203 Cmd.cmdsize = sizeof(MachO::symtab_command);
2211 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2212 if (DysymtabLoadCmd)
2213 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2215 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2216 MachO::dysymtab_command Cmd;
2217 Cmd.cmd = MachO::LC_DYSYMTAB;
2218 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2229 Cmd.extrefsymoff = 0;
2230 Cmd.nextrefsyms = 0;
2231 Cmd.indirectsymoff = 0;
2232 Cmd.nindirectsyms = 0;
2240 MachO::linkedit_data_command
2241 MachOObjectFile::getDataInCodeLoadCommand() const {
2242 if (DataInCodeLoadCmd)
2243 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2245 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2246 MachO::linkedit_data_command Cmd;
2247 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2248 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2254 MachO::linkedit_data_command
2255 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2256 if (LinkOptHintsLoadCmd)
2257 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2259 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2261 MachO::linkedit_data_command Cmd;
2262 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2263 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2269 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2270 if (!DyldInfoLoadCmd)
2271 return ArrayRef<uint8_t>();
2273 MachO::dyld_info_command DyldInfo
2274 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2275 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2276 getPtr(this, DyldInfo.rebase_off));
2277 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2280 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2281 if (!DyldInfoLoadCmd)
2282 return ArrayRef<uint8_t>();
2284 MachO::dyld_info_command DyldInfo
2285 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2286 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2287 getPtr(this, DyldInfo.bind_off));
2288 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2291 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2292 if (!DyldInfoLoadCmd)
2293 return ArrayRef<uint8_t>();
2295 MachO::dyld_info_command DyldInfo
2296 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2297 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2298 getPtr(this, DyldInfo.weak_bind_off));
2299 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2302 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2303 if (!DyldInfoLoadCmd)
2304 return ArrayRef<uint8_t>();
2306 MachO::dyld_info_command DyldInfo
2307 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2308 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2309 getPtr(this, DyldInfo.lazy_bind_off));
2310 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2313 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2314 if (!DyldInfoLoadCmd)
2315 return ArrayRef<uint8_t>();
2317 MachO::dyld_info_command DyldInfo
2318 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2319 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2320 getPtr(this, DyldInfo.export_off));
2321 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2324 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2326 return ArrayRef<uint8_t>();
2327 // Returning a pointer is fine as uuid doesn't need endian swapping.
2328 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2329 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2332 StringRef MachOObjectFile::getStringTableData() const {
2333 MachO::symtab_command S = getSymtabLoadCommand();
2334 return getData().substr(S.stroff, S.strsize);
2337 bool MachOObjectFile::is64Bit() const {
2338 return getType() == getMachOType(false, true) ||
2339 getType() == getMachOType(true, true);
2342 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2343 SmallVectorImpl<uint64_t> &Out) const {
2344 DataExtractor extractor(ObjectFile::getData(), true, 0);
2346 uint32_t offset = Index;
2348 while (uint64_t delta = extractor.getULEB128(&offset)) {
2350 Out.push_back(data);
2354 bool MachOObjectFile::isRelocatableObject() const {
2355 return getHeader().filetype == MachO::MH_OBJECT;
2358 ErrorOr<std::unique_ptr<MachOObjectFile>>
2359 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2360 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2362 std::unique_ptr<MachOObjectFile> Ret;
2363 if (Magic == "\xFE\xED\xFA\xCE")
2364 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2365 else if (Magic == "\xCE\xFA\xED\xFE")
2366 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2367 else if (Magic == "\xFE\xED\xFA\xCF")
2368 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2369 else if (Magic == "\xCF\xFA\xED\xFE")
2370 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2372 return object_error::parse_failed;
2376 return std::move(Ret);