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 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
403 SymbolRef::Type &Res) const {
404 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
405 uint8_t n_type = Entry.n_type;
407 Res = SymbolRef::ST_Other;
409 // If this is a STAB debugging symbol, we can do nothing more.
410 if (n_type & MachO::N_STAB) {
411 Res = SymbolRef::ST_Debug;
412 return std::error_code();
415 switch (n_type & MachO::N_TYPE) {
417 Res = SymbolRef::ST_Unknown;
420 Res = SymbolRef::ST_Function;
423 return std::error_code();
426 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
427 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
429 uint8_t MachOType = Entry.n_type;
430 uint16_t MachOFlags = Entry.n_desc;
432 uint32_t Result = SymbolRef::SF_None;
434 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
435 Result |= SymbolRef::SF_Undefined;
437 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
438 Result |= SymbolRef::SF_Indirect;
440 if (MachOType & MachO::N_STAB)
441 Result |= SymbolRef::SF_FormatSpecific;
443 if (MachOType & MachO::N_EXT) {
444 Result |= SymbolRef::SF_Global;
445 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
447 getSymbolAddress(DRI, Value);
448 if (Value && Value != UnknownAddress)
449 Result |= SymbolRef::SF_Common;
452 if (!(MachOType & MachO::N_PEXT))
453 Result |= SymbolRef::SF_Exported;
456 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
457 Result |= SymbolRef::SF_Weak;
459 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
460 Result |= SymbolRef::SF_Thumb;
462 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
463 Result |= SymbolRef::SF_Absolute;
468 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
469 section_iterator &Res) const {
470 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
471 uint8_t index = Entry.n_sect;
478 if (DRI.d.a >= Sections.size())
479 report_fatal_error("getSymbolSection: Invalid section index.");
480 Res = section_iterator(SectionRef(DRI, this));
483 return std::error_code();
486 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
490 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
491 StringRef &Result) const {
492 ArrayRef<char> Raw = getSectionRawName(Sec);
493 Result = parseSegmentOrSectionName(Raw.data());
494 return std::error_code();
497 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
499 return getSection64(Sec).addr;
500 return getSection(Sec).addr;
503 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
505 return getSection64(Sec).size;
506 return getSection(Sec).size;
509 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
510 StringRef &Res) const {
515 MachO::section_64 Sect = getSection64(Sec);
516 Offset = Sect.offset;
519 MachO::section Sect = getSection(Sec);
520 Offset = Sect.offset;
524 Res = this->getData().substr(Offset, Size);
525 return std::error_code();
528 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
531 MachO::section_64 Sect = getSection64(Sec);
534 MachO::section Sect = getSection(Sec);
538 return uint64_t(1) << Align;
541 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
542 uint32_t Flags = getSectionFlags(this, Sec);
543 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
546 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
547 uint32_t Flags = getSectionFlags(this, Sec);
548 unsigned SectionType = Flags & MachO::SECTION_TYPE;
549 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
550 !(SectionType == MachO::S_ZEROFILL ||
551 SectionType == MachO::S_GB_ZEROFILL);
554 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
555 uint32_t Flags = getSectionFlags(this, Sec);
556 unsigned SectionType = Flags & MachO::SECTION_TYPE;
557 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
558 (SectionType == MachO::S_ZEROFILL ||
559 SectionType == MachO::S_GB_ZEROFILL);
562 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
563 // FIXME: Unimplemented.
567 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
568 DataRefImpl Symb) const {
570 this->getSymbolType(Symb, ST);
571 if (ST == SymbolRef::ST_Unknown)
574 uint64_t SectBegin = getSectionAddress(Sec);
575 uint64_t SectEnd = getSectionSize(Sec);
576 SectEnd += SectBegin;
579 getSymbolAddress(Symb, SymAddr);
580 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
583 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
587 return relocation_iterator(RelocationRef(Ret, this));
591 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
594 MachO::section_64 Sect = getSection64(Sec);
597 MachO::section Sect = getSection(Sec);
604 return relocation_iterator(RelocationRef(Ret, this));
607 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
611 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
612 uint64_t &Res) const {
614 getRelocationOffset(Rel, Offset);
618 uint64_t SecAddress = getSectionAddress(Sec);
619 Res = SecAddress + Offset;
620 return std::error_code();
623 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
624 uint64_t &Res) const {
625 assert(getHeader().filetype == MachO::MH_OBJECT &&
626 "Only implemented for MH_OBJECT");
627 MachO::any_relocation_info RE = getRelocation(Rel);
628 Res = getAnyRelocationAddress(RE);
629 return std::error_code();
633 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
634 MachO::any_relocation_info RE = getRelocation(Rel);
635 if (isRelocationScattered(RE))
638 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
639 bool isExtern = getPlainRelocationExternal(RE);
643 MachO::symtab_command S = getSymtabLoadCommand();
644 unsigned SymbolTableEntrySize = is64Bit() ?
645 sizeof(MachO::nlist_64) :
646 sizeof(MachO::nlist);
647 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
649 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
650 return symbol_iterator(SymbolRef(Sym, this));
654 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
655 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
658 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
659 uint64_t &Res) const {
660 MachO::any_relocation_info RE = getRelocation(Rel);
661 Res = getAnyRelocationType(RE);
662 return std::error_code();
666 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
667 SmallVectorImpl<char> &Result) const {
670 getRelocationType(Rel, RType);
672 unsigned Arch = this->getArch();
676 static const char *const Table[] = {
677 "GENERIC_RELOC_VANILLA",
678 "GENERIC_RELOC_PAIR",
679 "GENERIC_RELOC_SECTDIFF",
680 "GENERIC_RELOC_PB_LA_PTR",
681 "GENERIC_RELOC_LOCAL_SECTDIFF",
682 "GENERIC_RELOC_TLV" };
690 case Triple::x86_64: {
691 static const char *const Table[] = {
692 "X86_64_RELOC_UNSIGNED",
693 "X86_64_RELOC_SIGNED",
694 "X86_64_RELOC_BRANCH",
695 "X86_64_RELOC_GOT_LOAD",
697 "X86_64_RELOC_SUBTRACTOR",
698 "X86_64_RELOC_SIGNED_1",
699 "X86_64_RELOC_SIGNED_2",
700 "X86_64_RELOC_SIGNED_4",
701 "X86_64_RELOC_TLV" };
710 static const char *const Table[] = {
713 "ARM_RELOC_SECTDIFF",
714 "ARM_RELOC_LOCAL_SECTDIFF",
715 "ARM_RELOC_PB_LA_PTR",
717 "ARM_THUMB_RELOC_BR22",
718 "ARM_THUMB_32BIT_BRANCH",
720 "ARM_RELOC_HALF_SECTDIFF" };
728 case Triple::aarch64: {
729 static const char *const Table[] = {
730 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
731 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
732 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
733 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
734 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
738 if (RType >= array_lengthof(Table))
745 static const char *const Table[] = {
754 "PPC_RELOC_SECTDIFF",
755 "PPC_RELOC_PB_LA_PTR",
756 "PPC_RELOC_HI16_SECTDIFF",
757 "PPC_RELOC_LO16_SECTDIFF",
758 "PPC_RELOC_HA16_SECTDIFF",
760 "PPC_RELOC_LO14_SECTDIFF",
761 "PPC_RELOC_LOCAL_SECTDIFF" };
769 case Triple::UnknownArch:
773 Result.append(res.begin(), res.end());
774 return std::error_code();
777 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
778 bool &Result) const {
779 unsigned Arch = getArch();
781 getRelocationType(Rel, Type);
785 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
787 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
788 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
789 } else if (Arch == Triple::x86_64) {
790 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
791 // an X86_64_RELOC_SUBTRACTOR.
792 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
793 DataRefImpl RelPrev = Rel;
796 getRelocationType(RelPrev, PrevType);
797 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
802 return std::error_code();
805 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
806 MachO::any_relocation_info RE = getRelocation(Rel);
807 return getAnyRelocationLength(RE);
811 // guessLibraryShortName() is passed a name of a dynamic library and returns a
812 // guess on what the short name is. Then name is returned as a substring of the
813 // StringRef Name passed in. The name of the dynamic library is recognized as
814 // a framework if it has one of the two following forms:
815 // Foo.framework/Versions/A/Foo
817 // Where A and Foo can be any string. And may contain a trailing suffix
818 // starting with an underbar. If the Name is recognized as a framework then
819 // isFramework is set to true else it is set to false. If the Name has a
820 // suffix then Suffix is set to the substring in Name that contains the suffix
821 // else it is set to a NULL StringRef.
823 // The Name of the dynamic library is recognized as a library name if it has
824 // one of the two following forms:
827 // The library may have a suffix trailing the name Foo of the form:
828 // libFoo_profile.A.dylib
829 // libFoo_profile.dylib
831 // The Name of the dynamic library is also recognized as a library name if it
832 // has the following form:
835 // If the Name of the dynamic library is none of the forms above then a NULL
836 // StringRef is returned.
838 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
841 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
842 size_t a, b, c, d, Idx;
845 Suffix = StringRef();
847 // Pull off the last component and make Foo point to it
849 if (a == Name.npos || a == 0)
851 Foo = Name.slice(a+1, Name.npos);
853 // Look for a suffix starting with a '_'
854 Idx = Foo.rfind('_');
855 if (Idx != Foo.npos && Foo.size() >= 2) {
856 Suffix = Foo.slice(Idx, Foo.npos);
857 Foo = Foo.slice(0, Idx);
860 // First look for the form Foo.framework/Foo
861 b = Name.rfind('/', a);
866 F = Name.slice(Idx, Idx + Foo.size());
867 DotFramework = Name.slice(Idx + Foo.size(),
868 Idx + Foo.size() + sizeof(".framework/")-1);
869 if (F == Foo && DotFramework == ".framework/") {
874 // Next look for the form Foo.framework/Versions/A/Foo
877 c = Name.rfind('/', b);
878 if (c == Name.npos || c == 0)
880 V = Name.slice(c+1, Name.npos);
881 if (!V.startswith("Versions/"))
883 d = Name.rfind('/', c);
888 F = Name.slice(Idx, Idx + Foo.size());
889 DotFramework = Name.slice(Idx + Foo.size(),
890 Idx + Foo.size() + sizeof(".framework/")-1);
891 if (F == Foo && DotFramework == ".framework/") {
897 // pull off the suffix after the "." and make a point to it
899 if (a == Name.npos || a == 0)
901 Dylib = Name.slice(a, Name.npos);
902 if (Dylib != ".dylib")
905 // First pull off the version letter for the form Foo.A.dylib if any.
907 Dot = Name.slice(a-2, a-1);
912 b = Name.rfind('/', a);
917 // ignore any suffix after an underbar like Foo_profile.A.dylib
918 Idx = Name.find('_', b);
919 if (Idx != Name.npos && Idx != b) {
920 Lib = Name.slice(b, Idx);
921 Suffix = Name.slice(Idx, a);
924 Lib = Name.slice(b, a);
925 // There are incorrect library names of the form:
926 // libATS.A_profile.dylib so check for these.
927 if (Lib.size() >= 3) {
928 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
930 Lib = Lib.slice(0, Lib.size()-2);
935 Qtx = Name.slice(a, Name.npos);
938 b = Name.rfind('/', a);
940 Lib = Name.slice(0, a);
942 Lib = Name.slice(b+1, a);
943 // There are library names of the form: QT.A.qtx so check for these.
944 if (Lib.size() >= 3) {
945 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
947 Lib = Lib.slice(0, Lib.size()-2);
952 // getLibraryShortNameByIndex() is used to get the short name of the library
953 // for an undefined symbol in a linked Mach-O binary that was linked with the
954 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
955 // It is passed the index (0 - based) of the library as translated from
956 // GET_LIBRARY_ORDINAL (1 - based).
957 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
958 StringRef &Res) const {
959 if (Index >= Libraries.size())
960 return object_error::parse_failed;
962 // If the cache of LibrariesShortNames is not built up do that first for
963 // all the Libraries.
964 if (LibrariesShortNames.size() == 0) {
965 for (unsigned i = 0; i < Libraries.size(); i++) {
966 MachO::dylib_command D =
967 getStruct<MachO::dylib_command>(this, Libraries[i]);
968 if (D.dylib.name >= D.cmdsize)
969 return object_error::parse_failed;
970 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
971 StringRef Name = StringRef(P);
972 if (D.dylib.name+Name.size() >= D.cmdsize)
973 return object_error::parse_failed;
976 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
977 if (shortName.empty())
978 LibrariesShortNames.push_back(Name);
980 LibrariesShortNames.push_back(shortName);
984 Res = LibrariesShortNames[Index];
985 return std::error_code();
988 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
989 return getSymbolByIndex(0);
992 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
995 return basic_symbol_iterator(SymbolRef(DRI, this));
997 MachO::symtab_command Symtab = getSymtabLoadCommand();
998 unsigned SymbolTableEntrySize = is64Bit() ?
999 sizeof(MachO::nlist_64) :
1000 sizeof(MachO::nlist);
1001 unsigned Offset = Symtab.symoff +
1002 Symtab.nsyms * SymbolTableEntrySize;
1003 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1004 return basic_symbol_iterator(SymbolRef(DRI, this));
1007 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1010 return basic_symbol_iterator(SymbolRef(DRI, this));
1012 MachO::symtab_command Symtab = getSymtabLoadCommand();
1013 if (Index >= Symtab.nsyms)
1014 report_fatal_error("Requested symbol index is out of range.");
1015 unsigned SymbolTableEntrySize =
1016 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1017 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1018 DRI.p += Index * SymbolTableEntrySize;
1019 return basic_symbol_iterator(SymbolRef(DRI, this));
1022 section_iterator MachOObjectFile::section_begin() const {
1024 return section_iterator(SectionRef(DRI, this));
1027 section_iterator MachOObjectFile::section_end() const {
1029 DRI.d.a = Sections.size();
1030 return section_iterator(SectionRef(DRI, this));
1033 uint8_t MachOObjectFile::getBytesInAddress() const {
1034 return is64Bit() ? 8 : 4;
1037 StringRef MachOObjectFile::getFileFormatName() const {
1038 unsigned CPUType = getCPUType(this);
1041 case llvm::MachO::CPU_TYPE_I386:
1042 return "Mach-O 32-bit i386";
1043 case llvm::MachO::CPU_TYPE_ARM:
1044 return "Mach-O arm";
1045 case llvm::MachO::CPU_TYPE_POWERPC:
1046 return "Mach-O 32-bit ppc";
1048 return "Mach-O 32-bit unknown";
1053 case llvm::MachO::CPU_TYPE_X86_64:
1054 return "Mach-O 64-bit x86-64";
1055 case llvm::MachO::CPU_TYPE_ARM64:
1056 return "Mach-O arm64";
1057 case llvm::MachO::CPU_TYPE_POWERPC64:
1058 return "Mach-O 64-bit ppc64";
1060 return "Mach-O 64-bit unknown";
1064 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1066 case llvm::MachO::CPU_TYPE_I386:
1068 case llvm::MachO::CPU_TYPE_X86_64:
1069 return Triple::x86_64;
1070 case llvm::MachO::CPU_TYPE_ARM:
1072 case llvm::MachO::CPU_TYPE_ARM64:
1073 return Triple::aarch64;
1074 case llvm::MachO::CPU_TYPE_POWERPC:
1076 case llvm::MachO::CPU_TYPE_POWERPC64:
1077 return Triple::ppc64;
1079 return Triple::UnknownArch;
1083 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1084 const char **McpuDefault) {
1086 *McpuDefault = nullptr;
1089 case MachO::CPU_TYPE_I386:
1090 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1091 case MachO::CPU_SUBTYPE_I386_ALL:
1092 return Triple("i386-apple-darwin");
1096 case MachO::CPU_TYPE_X86_64:
1097 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1098 case MachO::CPU_SUBTYPE_X86_64_ALL:
1099 return Triple("x86_64-apple-darwin");
1100 case MachO::CPU_SUBTYPE_X86_64_H:
1101 return Triple("x86_64h-apple-darwin");
1105 case MachO::CPU_TYPE_ARM:
1106 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1107 case MachO::CPU_SUBTYPE_ARM_V4T:
1108 return Triple("armv4t-apple-darwin");
1109 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1110 return Triple("armv5e-apple-darwin");
1111 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1112 return Triple("xscale-apple-darwin");
1113 case MachO::CPU_SUBTYPE_ARM_V6:
1114 return Triple("armv6-apple-darwin");
1115 case MachO::CPU_SUBTYPE_ARM_V6M:
1117 *McpuDefault = "cortex-m0";
1118 return Triple("armv6m-apple-darwin");
1119 case MachO::CPU_SUBTYPE_ARM_V7:
1120 return Triple("armv7-apple-darwin");
1121 case MachO::CPU_SUBTYPE_ARM_V7EM:
1123 *McpuDefault = "cortex-m4";
1124 return Triple("armv7em-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V7K:
1126 return Triple("armv7k-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_V7M:
1129 *McpuDefault = "cortex-m3";
1130 return Triple("armv7m-apple-darwin");
1131 case MachO::CPU_SUBTYPE_ARM_V7S:
1132 return Triple("armv7s-apple-darwin");
1136 case MachO::CPU_TYPE_ARM64:
1137 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1138 case MachO::CPU_SUBTYPE_ARM64_ALL:
1139 return Triple("arm64-apple-darwin");
1143 case MachO::CPU_TYPE_POWERPC:
1144 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1145 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1146 return Triple("ppc-apple-darwin");
1150 case MachO::CPU_TYPE_POWERPC64:
1151 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1152 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1153 return Triple("ppc64-apple-darwin");
1162 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1163 const char **McpuDefault) {
1165 *McpuDefault = nullptr;
1168 case MachO::CPU_TYPE_ARM:
1169 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1170 case MachO::CPU_SUBTYPE_ARM_V4T:
1171 return Triple("thumbv4t-apple-darwin");
1172 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1173 return Triple("thumbv5e-apple-darwin");
1174 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1175 return Triple("xscale-apple-darwin");
1176 case MachO::CPU_SUBTYPE_ARM_V6:
1177 return Triple("thumbv6-apple-darwin");
1178 case MachO::CPU_SUBTYPE_ARM_V6M:
1180 *McpuDefault = "cortex-m0";
1181 return Triple("thumbv6m-apple-darwin");
1182 case MachO::CPU_SUBTYPE_ARM_V7:
1183 return Triple("thumbv7-apple-darwin");
1184 case MachO::CPU_SUBTYPE_ARM_V7EM:
1186 *McpuDefault = "cortex-m4";
1187 return Triple("thumbv7em-apple-darwin");
1188 case MachO::CPU_SUBTYPE_ARM_V7K:
1189 return Triple("thumbv7k-apple-darwin");
1190 case MachO::CPU_SUBTYPE_ARM_V7M:
1192 *McpuDefault = "cortex-m3";
1193 return Triple("thumbv7m-apple-darwin");
1194 case MachO::CPU_SUBTYPE_ARM_V7S:
1195 return Triple("thumbv7s-apple-darwin");
1204 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1205 const char **McpuDefault,
1206 Triple *ThumbTriple) {
1207 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1208 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1213 Triple MachOObjectFile::getHostArch() {
1214 return Triple(sys::getDefaultTargetTriple());
1217 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1218 return StringSwitch<bool>(ArchFlag)
1220 .Case("x86_64", true)
1221 .Case("x86_64h", true)
1222 .Case("armv4t", true)
1224 .Case("armv5e", true)
1225 .Case("armv6", true)
1226 .Case("armv6m", true)
1227 .Case("armv7", true)
1228 .Case("armv7em", true)
1229 .Case("armv7k", true)
1230 .Case("armv7m", true)
1231 .Case("armv7s", true)
1232 .Case("arm64", true)
1234 .Case("ppc64", true)
1238 unsigned MachOObjectFile::getArch() const {
1239 return getArch(getCPUType(this));
1242 Triple MachOObjectFile::getArch(const char **McpuDefault,
1243 Triple *ThumbTriple) const {
1244 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1245 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1248 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1251 return section_rel_begin(DRI);
1254 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1257 return section_rel_end(DRI);
1260 dice_iterator MachOObjectFile::begin_dices() const {
1262 if (!DataInCodeLoadCmd)
1263 return dice_iterator(DiceRef(DRI, this));
1265 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1266 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1267 return dice_iterator(DiceRef(DRI, this));
1270 dice_iterator MachOObjectFile::end_dices() const {
1272 if (!DataInCodeLoadCmd)
1273 return dice_iterator(DiceRef(DRI, this));
1275 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1276 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1277 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1278 return dice_iterator(DiceRef(DRI, this));
1281 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1282 : Trie(T), Malformed(false), Done(false) { }
1284 void ExportEntry::moveToFirst() {
1286 pushDownUntilBottom();
1289 void ExportEntry::moveToEnd() {
1294 bool ExportEntry::operator==(const ExportEntry &Other) const {
1295 // Common case, one at end, other iterating from begin.
1296 if (Done || Other.Done)
1297 return (Done == Other.Done);
1298 // Not equal if different stack sizes.
1299 if (Stack.size() != Other.Stack.size())
1301 // Not equal if different cumulative strings.
1302 if (!CumulativeString.equals(Other.CumulativeString))
1304 // Equal if all nodes in both stacks match.
1305 for (unsigned i=0; i < Stack.size(); ++i) {
1306 if (Stack[i].Start != Other.Stack[i].Start)
1312 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1314 uint64_t Result = decodeULEB128(Ptr, &Count);
1316 if (Ptr > Trie.end()) {
1323 StringRef ExportEntry::name() const {
1324 return CumulativeString;
1327 uint64_t ExportEntry::flags() const {
1328 return Stack.back().Flags;
1331 uint64_t ExportEntry::address() const {
1332 return Stack.back().Address;
1335 uint64_t ExportEntry::other() const {
1336 return Stack.back().Other;
1339 StringRef ExportEntry::otherName() const {
1340 const char* ImportName = Stack.back().ImportName;
1342 return StringRef(ImportName);
1346 uint32_t ExportEntry::nodeOffset() const {
1347 return Stack.back().Start - Trie.begin();
1350 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1351 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1352 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1353 ParentStringLength(0), IsExportNode(false) {
1356 void ExportEntry::pushNode(uint64_t offset) {
1357 const uint8_t *Ptr = Trie.begin() + offset;
1358 NodeState State(Ptr);
1359 uint64_t ExportInfoSize = readULEB128(State.Current);
1360 State.IsExportNode = (ExportInfoSize != 0);
1361 const uint8_t* Children = State.Current + ExportInfoSize;
1362 if (State.IsExportNode) {
1363 State.Flags = readULEB128(State.Current);
1364 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1366 State.Other = readULEB128(State.Current); // dylib ordinal
1367 State.ImportName = reinterpret_cast<const char*>(State.Current);
1369 State.Address = readULEB128(State.Current);
1370 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1371 State.Other = readULEB128(State.Current);
1374 State.ChildCount = *Children;
1375 State.Current = Children + 1;
1376 State.NextChildIndex = 0;
1377 State.ParentStringLength = CumulativeString.size();
1378 Stack.push_back(State);
1381 void ExportEntry::pushDownUntilBottom() {
1382 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1383 NodeState &Top = Stack.back();
1384 CumulativeString.resize(Top.ParentStringLength);
1385 for (;*Top.Current != 0; Top.Current++) {
1386 char C = *Top.Current;
1387 CumulativeString.push_back(C);
1390 uint64_t childNodeIndex = readULEB128(Top.Current);
1391 Top.NextChildIndex += 1;
1392 pushNode(childNodeIndex);
1394 if (!Stack.back().IsExportNode) {
1400 // We have a trie data structure and need a way to walk it that is compatible
1401 // with the C++ iterator model. The solution is a non-recursive depth first
1402 // traversal where the iterator contains a stack of parent nodes along with a
1403 // string that is the accumulation of all edge strings along the parent chain
1406 // There is one "export" node for each exported symbol. But because some
1407 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1408 // node may have child nodes too.
1410 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1411 // child until hitting a node with no children (which is an export node or
1412 // else the trie is malformed). On the way down, each node is pushed on the
1413 // stack ivar. If there is no more ways down, it pops up one and tries to go
1414 // down a sibling path until a childless node is reached.
1415 void ExportEntry::moveNext() {
1416 if (Stack.empty() || !Stack.back().IsExportNode) {
1423 while (!Stack.empty()) {
1424 NodeState &Top = Stack.back();
1425 if (Top.NextChildIndex < Top.ChildCount) {
1426 pushDownUntilBottom();
1427 // Now at the next export node.
1430 if (Top.IsExportNode) {
1431 // This node has no children but is itself an export node.
1432 CumulativeString.resize(Top.ParentStringLength);
1441 iterator_range<export_iterator>
1442 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1443 ExportEntry Start(Trie);
1444 if (Trie.size() == 0)
1447 Start.moveToFirst();
1449 ExportEntry Finish(Trie);
1452 return iterator_range<export_iterator>(export_iterator(Start),
1453 export_iterator(Finish));
1456 iterator_range<export_iterator> MachOObjectFile::exports() const {
1457 return exports(getDyldInfoExportsTrie());
1461 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1462 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1463 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1464 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1466 void MachORebaseEntry::moveToFirst() {
1467 Ptr = Opcodes.begin();
1471 void MachORebaseEntry::moveToEnd() {
1472 Ptr = Opcodes.end();
1473 RemainingLoopCount = 0;
1477 void MachORebaseEntry::moveNext() {
1478 // If in the middle of some loop, move to next rebasing in loop.
1479 SegmentOffset += AdvanceAmount;
1480 if (RemainingLoopCount) {
1481 --RemainingLoopCount;
1484 if (Ptr == Opcodes.end()) {
1489 while (More && !Malformed) {
1490 // Parse next opcode and set up next loop.
1491 uint8_t Byte = *Ptr++;
1492 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1493 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1495 case MachO::REBASE_OPCODE_DONE:
1499 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1501 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1502 RebaseType = ImmValue;
1505 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1506 << "RebaseType=" << (int) RebaseType << "\n");
1508 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1509 SegmentIndex = ImmValue;
1510 SegmentOffset = readULEB128();
1513 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1514 << "SegmentIndex=" << SegmentIndex << ", "
1515 << format("SegmentOffset=0x%06X", SegmentOffset)
1518 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1519 SegmentOffset += readULEB128();
1520 DEBUG_WITH_TYPE("mach-o-rebase",
1521 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1522 << format("SegmentOffset=0x%06X",
1523 SegmentOffset) << "\n");
1525 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1526 SegmentOffset += ImmValue * PointerSize;
1527 DEBUG_WITH_TYPE("mach-o-rebase",
1528 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1529 << format("SegmentOffset=0x%06X",
1530 SegmentOffset) << "\n");
1532 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1533 AdvanceAmount = PointerSize;
1534 RemainingLoopCount = ImmValue - 1;
1537 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1538 << format("SegmentOffset=0x%06X", SegmentOffset)
1539 << ", AdvanceAmount=" << AdvanceAmount
1540 << ", RemainingLoopCount=" << RemainingLoopCount
1543 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1544 AdvanceAmount = PointerSize;
1545 RemainingLoopCount = readULEB128() - 1;
1548 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1549 << format("SegmentOffset=0x%06X", SegmentOffset)
1550 << ", AdvanceAmount=" << AdvanceAmount
1551 << ", RemainingLoopCount=" << RemainingLoopCount
1554 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1555 AdvanceAmount = readULEB128() + PointerSize;
1556 RemainingLoopCount = 0;
1559 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1560 << format("SegmentOffset=0x%06X", SegmentOffset)
1561 << ", AdvanceAmount=" << AdvanceAmount
1562 << ", RemainingLoopCount=" << RemainingLoopCount
1565 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1566 RemainingLoopCount = readULEB128() - 1;
1567 AdvanceAmount = readULEB128() + PointerSize;
1570 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1571 << format("SegmentOffset=0x%06X", SegmentOffset)
1572 << ", AdvanceAmount=" << AdvanceAmount
1573 << ", RemainingLoopCount=" << RemainingLoopCount
1582 uint64_t MachORebaseEntry::readULEB128() {
1584 uint64_t Result = decodeULEB128(Ptr, &Count);
1586 if (Ptr > Opcodes.end()) {
1587 Ptr = Opcodes.end();
1593 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1595 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1597 StringRef MachORebaseEntry::typeName() const {
1598 switch (RebaseType) {
1599 case MachO::REBASE_TYPE_POINTER:
1601 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1602 return "text abs32";
1603 case MachO::REBASE_TYPE_TEXT_PCREL32:
1604 return "text rel32";
1609 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1610 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1611 return (Ptr == Other.Ptr) &&
1612 (RemainingLoopCount == Other.RemainingLoopCount) &&
1613 (Done == Other.Done);
1616 iterator_range<rebase_iterator>
1617 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1618 MachORebaseEntry Start(Opcodes, is64);
1619 Start.moveToFirst();
1621 MachORebaseEntry Finish(Opcodes, is64);
1624 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1625 rebase_iterator(Finish));
1628 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1629 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1633 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1635 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1636 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1637 BindType(0), PointerSize(is64Bit ? 8 : 4),
1638 TableKind(BK), Malformed(false), Done(false) {}
1640 void MachOBindEntry::moveToFirst() {
1641 Ptr = Opcodes.begin();
1645 void MachOBindEntry::moveToEnd() {
1646 Ptr = Opcodes.end();
1647 RemainingLoopCount = 0;
1651 void MachOBindEntry::moveNext() {
1652 // If in the middle of some loop, move to next binding in loop.
1653 SegmentOffset += AdvanceAmount;
1654 if (RemainingLoopCount) {
1655 --RemainingLoopCount;
1658 if (Ptr == Opcodes.end()) {
1663 while (More && !Malformed) {
1664 // Parse next opcode and set up next loop.
1665 uint8_t Byte = *Ptr++;
1666 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1667 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1668 int8_t SignExtended;
1669 const uint8_t *SymStart;
1671 case MachO::BIND_OPCODE_DONE:
1672 if (TableKind == Kind::Lazy) {
1673 // Lazying bindings have a DONE opcode between entries. Need to ignore
1674 // it to advance to next entry. But need not if this is last entry.
1675 bool NotLastEntry = false;
1676 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1678 NotLastEntry = true;
1687 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1689 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1693 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1694 << "Ordinal=" << Ordinal << "\n");
1696 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1697 Ordinal = readULEB128();
1700 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1701 << "Ordinal=" << Ordinal << "\n");
1703 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1705 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1706 Ordinal = SignExtended;
1711 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1712 << "Ordinal=" << Ordinal << "\n");
1714 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1720 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1725 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1726 << "SymbolName=" << SymbolName << "\n");
1727 if (TableKind == Kind::Weak) {
1728 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1732 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1733 BindType = ImmValue;
1736 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1737 << "BindType=" << (int)BindType << "\n");
1739 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1740 Addend = readSLEB128();
1741 if (TableKind == Kind::Lazy)
1745 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1746 << "Addend=" << Addend << "\n");
1748 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1749 SegmentIndex = ImmValue;
1750 SegmentOffset = readULEB128();
1753 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1754 << "SegmentIndex=" << SegmentIndex << ", "
1755 << format("SegmentOffset=0x%06X", SegmentOffset)
1758 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1759 SegmentOffset += readULEB128();
1760 DEBUG_WITH_TYPE("mach-o-bind",
1761 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1765 case MachO::BIND_OPCODE_DO_BIND:
1766 AdvanceAmount = PointerSize;
1767 RemainingLoopCount = 0;
1768 DEBUG_WITH_TYPE("mach-o-bind",
1769 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1770 << format("SegmentOffset=0x%06X",
1771 SegmentOffset) << "\n");
1773 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1774 AdvanceAmount = readULEB128() + PointerSize;
1775 RemainingLoopCount = 0;
1776 if (TableKind == Kind::Lazy)
1780 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1781 << format("SegmentOffset=0x%06X", SegmentOffset)
1782 << ", AdvanceAmount=" << AdvanceAmount
1783 << ", RemainingLoopCount=" << RemainingLoopCount
1786 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1787 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1788 RemainingLoopCount = 0;
1789 if (TableKind == Kind::Lazy)
1791 DEBUG_WITH_TYPE("mach-o-bind",
1793 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1794 << format("SegmentOffset=0x%06X",
1795 SegmentOffset) << "\n");
1797 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1798 RemainingLoopCount = readULEB128() - 1;
1799 AdvanceAmount = readULEB128() + PointerSize;
1800 if (TableKind == Kind::Lazy)
1804 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1805 << format("SegmentOffset=0x%06X", SegmentOffset)
1806 << ", AdvanceAmount=" << AdvanceAmount
1807 << ", RemainingLoopCount=" << RemainingLoopCount
1816 uint64_t MachOBindEntry::readULEB128() {
1818 uint64_t Result = decodeULEB128(Ptr, &Count);
1820 if (Ptr > Opcodes.end()) {
1821 Ptr = Opcodes.end();
1827 int64_t MachOBindEntry::readSLEB128() {
1829 int64_t Result = decodeSLEB128(Ptr, &Count);
1831 if (Ptr > Opcodes.end()) {
1832 Ptr = Opcodes.end();
1839 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1841 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1843 StringRef MachOBindEntry::typeName() const {
1845 case MachO::BIND_TYPE_POINTER:
1847 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1848 return "text abs32";
1849 case MachO::BIND_TYPE_TEXT_PCREL32:
1850 return "text rel32";
1855 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1857 int64_t MachOBindEntry::addend() const { return Addend; }
1859 uint32_t MachOBindEntry::flags() const { return Flags; }
1861 int MachOBindEntry::ordinal() const { return Ordinal; }
1863 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1864 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1865 return (Ptr == Other.Ptr) &&
1866 (RemainingLoopCount == Other.RemainingLoopCount) &&
1867 (Done == Other.Done);
1870 iterator_range<bind_iterator>
1871 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1872 MachOBindEntry::Kind BKind) {
1873 MachOBindEntry Start(Opcodes, is64, BKind);
1874 Start.moveToFirst();
1876 MachOBindEntry Finish(Opcodes, is64, BKind);
1879 return iterator_range<bind_iterator>(bind_iterator(Start),
1880 bind_iterator(Finish));
1883 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1884 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1885 MachOBindEntry::Kind::Regular);
1888 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1889 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1890 MachOBindEntry::Kind::Lazy);
1893 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1894 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1895 MachOBindEntry::Kind::Weak);
1898 MachOObjectFile::load_command_iterator
1899 MachOObjectFile::begin_load_commands() const {
1900 return LoadCommands.begin();
1903 MachOObjectFile::load_command_iterator
1904 MachOObjectFile::end_load_commands() const {
1905 return LoadCommands.end();
1908 iterator_range<MachOObjectFile::load_command_iterator>
1909 MachOObjectFile::load_commands() const {
1910 return iterator_range<load_command_iterator>(begin_load_commands(),
1911 end_load_commands());
1915 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1916 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1917 return parseSegmentOrSectionName(Raw.data());
1921 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1922 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1923 const section_base *Base =
1924 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1925 return makeArrayRef(Base->sectname);
1929 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1930 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1931 const section_base *Base =
1932 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1933 return makeArrayRef(Base->segname);
1937 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1939 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1941 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1944 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1945 const MachO::any_relocation_info &RE) const {
1946 if (isLittleEndian())
1947 return RE.r_word1 & 0xffffff;
1948 return RE.r_word1 >> 8;
1951 bool MachOObjectFile::getPlainRelocationExternal(
1952 const MachO::any_relocation_info &RE) const {
1953 if (isLittleEndian())
1954 return (RE.r_word1 >> 27) & 1;
1955 return (RE.r_word1 >> 4) & 1;
1958 bool MachOObjectFile::getScatteredRelocationScattered(
1959 const MachO::any_relocation_info &RE) const {
1960 return RE.r_word0 >> 31;
1963 uint32_t MachOObjectFile::getScatteredRelocationValue(
1964 const MachO::any_relocation_info &RE) const {
1968 uint32_t MachOObjectFile::getScatteredRelocationType(
1969 const MachO::any_relocation_info &RE) const {
1970 return (RE.r_word0 >> 24) & 0xf;
1973 unsigned MachOObjectFile::getAnyRelocationAddress(
1974 const MachO::any_relocation_info &RE) const {
1975 if (isRelocationScattered(RE))
1976 return getScatteredRelocationAddress(RE);
1977 return getPlainRelocationAddress(RE);
1980 unsigned MachOObjectFile::getAnyRelocationPCRel(
1981 const MachO::any_relocation_info &RE) const {
1982 if (isRelocationScattered(RE))
1983 return getScatteredRelocationPCRel(this, RE);
1984 return getPlainRelocationPCRel(this, RE);
1987 unsigned MachOObjectFile::getAnyRelocationLength(
1988 const MachO::any_relocation_info &RE) const {
1989 if (isRelocationScattered(RE))
1990 return getScatteredRelocationLength(RE);
1991 return getPlainRelocationLength(this, RE);
1995 MachOObjectFile::getAnyRelocationType(
1996 const MachO::any_relocation_info &RE) const {
1997 if (isRelocationScattered(RE))
1998 return getScatteredRelocationType(RE);
1999 return getPlainRelocationType(this, RE);
2003 MachOObjectFile::getAnyRelocationSection(
2004 const MachO::any_relocation_info &RE) const {
2005 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2006 return *section_end();
2007 unsigned SecNum = getPlainRelocationSymbolNum(RE);
2008 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
2009 return *section_end();
2011 DRI.d.a = SecNum - 1;
2012 return SectionRef(DRI, this);
2015 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2016 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2017 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2020 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2021 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2022 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2025 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2026 unsigned Index) const {
2027 const char *Sec = getSectionPtr(this, L, Index);
2028 return getStruct<MachO::section>(this, Sec);
2031 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2032 unsigned Index) const {
2033 const char *Sec = getSectionPtr(this, L, Index);
2034 return getStruct<MachO::section_64>(this, Sec);
2038 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2039 const char *P = reinterpret_cast<const char *>(DRI.p);
2040 return getStruct<MachO::nlist>(this, P);
2044 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2045 const char *P = reinterpret_cast<const char *>(DRI.p);
2046 return getStruct<MachO::nlist_64>(this, P);
2049 MachO::linkedit_data_command
2050 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2051 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2054 MachO::segment_command
2055 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2056 return getStruct<MachO::segment_command>(this, L.Ptr);
2059 MachO::segment_command_64
2060 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2061 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2064 MachO::linker_option_command
2065 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2066 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2069 MachO::version_min_command
2070 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2071 return getStruct<MachO::version_min_command>(this, L.Ptr);
2074 MachO::dylib_command
2075 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2076 return getStruct<MachO::dylib_command>(this, L.Ptr);
2079 MachO::dyld_info_command
2080 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2081 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2084 MachO::dylinker_command
2085 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2086 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2090 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2091 return getStruct<MachO::uuid_command>(this, L.Ptr);
2094 MachO::rpath_command
2095 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2096 return getStruct<MachO::rpath_command>(this, L.Ptr);
2099 MachO::source_version_command
2100 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2101 return getStruct<MachO::source_version_command>(this, L.Ptr);
2104 MachO::entry_point_command
2105 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2106 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2109 MachO::encryption_info_command
2110 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2111 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2114 MachO::encryption_info_command_64
2115 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2116 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2119 MachO::sub_framework_command
2120 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2121 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2124 MachO::sub_umbrella_command
2125 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2126 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2129 MachO::sub_library_command
2130 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2131 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2134 MachO::sub_client_command
2135 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2136 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2139 MachO::routines_command
2140 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2141 return getStruct<MachO::routines_command>(this, L.Ptr);
2144 MachO::routines_command_64
2145 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2146 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2149 MachO::thread_command
2150 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2151 return getStruct<MachO::thread_command>(this, L.Ptr);
2154 MachO::any_relocation_info
2155 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2160 MachO::section_64 Sect = getSection64(Sec);
2161 Offset = Sect.reloff;
2163 MachO::section Sect = getSection(Sec);
2164 Offset = Sect.reloff;
2167 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2168 getPtr(this, Offset)) + Rel.d.b;
2169 return getStruct<MachO::any_relocation_info>(
2170 this, reinterpret_cast<const char *>(P));
2173 MachO::data_in_code_entry
2174 MachOObjectFile::getDice(DataRefImpl Rel) const {
2175 const char *P = reinterpret_cast<const char *>(Rel.p);
2176 return getStruct<MachO::data_in_code_entry>(this, P);
2179 const MachO::mach_header &MachOObjectFile::getHeader() const {
2183 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2188 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2189 const MachO::dysymtab_command &DLC,
2190 unsigned Index) const {
2191 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2192 return getStruct<uint32_t>(this, getPtr(this, Offset));
2195 MachO::data_in_code_entry
2196 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2197 unsigned Index) const {
2198 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2199 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2202 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2204 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2206 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2207 MachO::symtab_command Cmd;
2208 Cmd.cmd = MachO::LC_SYMTAB;
2209 Cmd.cmdsize = sizeof(MachO::symtab_command);
2217 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2218 if (DysymtabLoadCmd)
2219 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2221 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2222 MachO::dysymtab_command Cmd;
2223 Cmd.cmd = MachO::LC_DYSYMTAB;
2224 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2235 Cmd.extrefsymoff = 0;
2236 Cmd.nextrefsyms = 0;
2237 Cmd.indirectsymoff = 0;
2238 Cmd.nindirectsyms = 0;
2246 MachO::linkedit_data_command
2247 MachOObjectFile::getDataInCodeLoadCommand() const {
2248 if (DataInCodeLoadCmd)
2249 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2251 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2252 MachO::linkedit_data_command Cmd;
2253 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2254 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2260 MachO::linkedit_data_command
2261 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2262 if (LinkOptHintsLoadCmd)
2263 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2265 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2267 MachO::linkedit_data_command Cmd;
2268 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2269 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2275 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2276 if (!DyldInfoLoadCmd)
2277 return ArrayRef<uint8_t>();
2279 MachO::dyld_info_command DyldInfo
2280 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2281 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2282 getPtr(this, DyldInfo.rebase_off));
2283 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2286 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2287 if (!DyldInfoLoadCmd)
2288 return ArrayRef<uint8_t>();
2290 MachO::dyld_info_command DyldInfo
2291 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2292 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2293 getPtr(this, DyldInfo.bind_off));
2294 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2297 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2298 if (!DyldInfoLoadCmd)
2299 return ArrayRef<uint8_t>();
2301 MachO::dyld_info_command DyldInfo
2302 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2303 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2304 getPtr(this, DyldInfo.weak_bind_off));
2305 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2308 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2309 if (!DyldInfoLoadCmd)
2310 return ArrayRef<uint8_t>();
2312 MachO::dyld_info_command DyldInfo
2313 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2314 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2315 getPtr(this, DyldInfo.lazy_bind_off));
2316 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2319 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2320 if (!DyldInfoLoadCmd)
2321 return ArrayRef<uint8_t>();
2323 MachO::dyld_info_command DyldInfo
2324 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2325 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2326 getPtr(this, DyldInfo.export_off));
2327 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2330 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2332 return ArrayRef<uint8_t>();
2333 // Returning a pointer is fine as uuid doesn't need endian swapping.
2334 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2335 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2338 StringRef MachOObjectFile::getStringTableData() const {
2339 MachO::symtab_command S = getSymtabLoadCommand();
2340 return getData().substr(S.stroff, S.strsize);
2343 bool MachOObjectFile::is64Bit() const {
2344 return getType() == getMachOType(false, true) ||
2345 getType() == getMachOType(true, true);
2348 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2349 SmallVectorImpl<uint64_t> &Out) const {
2350 DataExtractor extractor(ObjectFile::getData(), true, 0);
2352 uint32_t offset = Index;
2354 while (uint64_t delta = extractor.getULEB128(&offset)) {
2356 Out.push_back(data);
2360 bool MachOObjectFile::isRelocatableObject() const {
2361 return getHeader().filetype == MachO::MH_OBJECT;
2364 ErrorOr<std::unique_ptr<MachOObjectFile>>
2365 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2366 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2368 std::unique_ptr<MachOObjectFile> Ret;
2369 if (Magic == "\xFE\xED\xFA\xCE")
2370 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2371 else if (Magic == "\xCE\xFA\xED\xFE")
2372 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2373 else if (Magic == "\xFE\xED\xFA\xCF")
2374 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2375 else if (Magic == "\xCF\xFA\xED\xFE")
2376 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2378 return object_error::parse_failed;
2382 return std::move(Ret);