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);
68 template <typename SegmentCmd>
69 static ErrorOr<uint32_t> getSegmentLoadCommandNumSections(const SegmentCmd &S,
71 const unsigned SectionSize = sizeof(SegmentCmd);
72 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
73 S.nsects * SectionSize > Cmdsize - sizeof(S))
74 return object_error::macho_load_segment_too_many_sections;
78 static ErrorOr<uint32_t>
79 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
80 const MachOObjectFile::LoadCommandInfo &L) {
82 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
85 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
89 static bool isPageZeroSegment(const MachOObjectFile *O,
90 const MachOObjectFile::LoadCommandInfo &L) {
92 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
93 return StringRef("__PAGEZERO").equals(S.segname);
95 MachO::segment_command S = O->getSegmentLoadCommand(L);
96 return StringRef("__PAGEZERO").equals(S.segname);
101 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
103 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
105 bool Is64 = O->is64Bit();
106 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
107 sizeof(MachO::segment_command);
108 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
109 sizeof(MachO::section);
111 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
112 return reinterpret_cast<const char*>(SectionAddr);
115 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
116 return O->getData().substr(Offset, 1).data();
119 static MachO::nlist_base
120 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
121 const char *P = reinterpret_cast<const char *>(DRI.p);
122 return getStruct<MachO::nlist_base>(O, P);
125 static StringRef parseSegmentOrSectionName(const char *P) {
129 // Not null terminated, so this is a 16 char string.
130 return StringRef(P, 16);
133 // Helper to advance a section or symbol iterator multiple increments at a time.
135 static void advance(T &it, size_t Val) {
140 static unsigned getCPUType(const MachOObjectFile *O) {
141 return O->getHeader().cputype;
145 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
150 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
151 return RE.r_word0 & 0xffffff;
154 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
155 const MachO::any_relocation_info &RE) {
156 if (O->isLittleEndian())
157 return (RE.r_word1 >> 24) & 1;
158 return (RE.r_word1 >> 7) & 1;
162 getScatteredRelocationPCRel(const MachOObjectFile *O,
163 const MachO::any_relocation_info &RE) {
164 return (RE.r_word0 >> 30) & 1;
167 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
168 const MachO::any_relocation_info &RE) {
169 if (O->isLittleEndian())
170 return (RE.r_word1 >> 25) & 3;
171 return (RE.r_word1 >> 5) & 3;
175 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
176 return (RE.r_word0 >> 28) & 3;
179 static unsigned getPlainRelocationType(const MachOObjectFile *O,
180 const MachO::any_relocation_info &RE) {
181 if (O->isLittleEndian())
182 return RE.r_word1 >> 28;
183 return RE.r_word1 & 0xf;
186 static uint32_t getSectionFlags(const MachOObjectFile *O,
189 MachO::section_64 Sect = O->getSection64(Sec);
192 MachO::section Sect = O->getSection(Sec);
196 static ErrorOr<MachOObjectFile::LoadCommandInfo>
197 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
198 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
200 return CmdOrErr.getError();
201 if (CmdOrErr->cmdsize < 8)
202 return object_error::macho_small_load_command;
203 MachOObjectFile::LoadCommandInfo Load;
205 Load.C = CmdOrErr.get();
209 static ErrorOr<MachOObjectFile::LoadCommandInfo>
210 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
211 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
212 : sizeof(MachO::mach_header);
213 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
216 static ErrorOr<MachOObjectFile::LoadCommandInfo>
217 getNextLoadCommandInfo(const MachOObjectFile *Obj,
218 const MachOObjectFile::LoadCommandInfo &L) {
219 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
222 template <typename T>
223 static void parseHeader(const MachOObjectFile *Obj, T &Header,
224 std::error_code &EC) {
225 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
227 Header = HeaderOrErr.get();
229 EC = HeaderOrErr.getError();
232 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
236 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
237 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
238 HasPageZeroSegment(false) {
240 parseHeader(this, Header64, EC);
242 // First fields of MachO::mach_header_64 are the same as
243 // in MachO::mach_header.
244 parseHeader(this, *reinterpret_cast<MachO::mach_header *>(&this->Header64),
249 uint32_t LoadCommandCount = getHeader().ncmds;
250 if (LoadCommandCount == 0)
253 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
254 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
256 auto LoadOrErr = getFirstLoadCommandInfo(this);
258 EC = LoadOrErr.getError();
261 LoadCommandInfo Load = LoadOrErr.get();
262 for (unsigned I = 0; I < LoadCommandCount; ++I) {
263 LoadCommands.push_back(Load);
264 if (Load.C.cmd == MachO::LC_SYMTAB) {
265 // Multiple symbol tables
267 EC = object_error::parse_failed;
270 SymtabLoadCmd = Load.Ptr;
271 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
272 // Multiple dynamic symbol tables
273 if (DysymtabLoadCmd) {
274 EC = object_error::parse_failed;
277 DysymtabLoadCmd = Load.Ptr;
278 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
279 // Multiple data in code tables
280 if (DataInCodeLoadCmd) {
281 EC = object_error::parse_failed;
284 DataInCodeLoadCmd = Load.Ptr;
285 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
286 // Multiple linker optimization hint tables
287 if (LinkOptHintsLoadCmd) {
288 EC = object_error::parse_failed;
291 LinkOptHintsLoadCmd = Load.Ptr;
292 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
293 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
294 // Multiple dyldinfo load commands
295 if (DyldInfoLoadCmd) {
296 EC = object_error::parse_failed;
299 DyldInfoLoadCmd = Load.Ptr;
300 } else if (Load.C.cmd == MachO::LC_UUID) {
301 // Multiple UUID load commands
303 EC = object_error::parse_failed;
306 UuidLoadCmd = Load.Ptr;
307 } else if (Load.C.cmd == SegmentLoadType) {
308 const unsigned SegmentLoadSize = is64Bit()
309 ? sizeof(MachO::segment_command_64)
310 : sizeof(MachO::segment_command);
311 if (Load.C.cmdsize < SegmentLoadSize) {
312 EC = object_error::macho_load_segment_too_small;
315 auto NumSectionsOrErr = getSegmentLoadCommandNumSections(this, Load);
316 if (!NumSectionsOrErr) {
317 EC = NumSectionsOrErr.getError();
320 for (unsigned J = 0; J < NumSectionsOrErr.get(); ++J) {
321 const char *Sec = getSectionPtr(this, Load, J);
322 Sections.push_back(Sec);
324 if (isPageZeroSegment(this, Load))
325 HasPageZeroSegment = true;
326 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
327 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
328 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
329 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
330 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
331 Libraries.push_back(Load.Ptr);
333 if (I < LoadCommandCount - 1) {
334 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
336 EC = LoadOrErr.getError();
339 Load = LoadOrErr.get();
342 assert(LoadCommands.size() == LoadCommandCount);
345 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
346 unsigned SymbolTableEntrySize = is64Bit() ?
347 sizeof(MachO::nlist_64) :
348 sizeof(MachO::nlist);
349 Symb.p += SymbolTableEntrySize;
352 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
353 StringRef &Res) const {
354 StringRef StringTable = getStringTableData();
355 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
356 const char *Start = &StringTable.data()[Entry.n_strx];
357 if (Start < getData().begin() || Start >= getData().end())
359 "Symbol name entry points before beginning or past end of file.");
360 Res = StringRef(Start);
361 return object_error::success;
364 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
365 DataRefImpl DRI = Sec.getRawDataRefImpl();
366 uint32_t Flags = getSectionFlags(this, DRI);
367 return Flags & MachO::SECTION_TYPE;
370 // getIndirectName() returns the name of the alias'ed symbol who's string table
371 // index is in the n_value field.
372 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
373 StringRef &Res) const {
374 StringRef StringTable = getStringTableData();
377 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
378 NValue = Entry.n_value;
379 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
380 return object_error::parse_failed;
382 MachO::nlist Entry = getSymbolTableEntry(Symb);
383 NValue = Entry.n_value;
384 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
385 return object_error::parse_failed;
387 if (NValue >= StringTable.size())
388 return object_error::parse_failed;
389 const char *Start = &StringTable.data()[NValue];
390 Res = StringRef(Start);
391 return object_error::success;
394 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
395 uint64_t &Res) const {
397 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
398 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
400 Res = UnknownAddressOrSize;
404 MachO::nlist Entry = getSymbolTableEntry(Symb);
405 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
407 Res = UnknownAddressOrSize;
411 return object_error::success;
414 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
415 uint32_t flags = getSymbolFlags(DRI);
416 if (flags & SymbolRef::SF_Common) {
417 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
418 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
423 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
425 getSymbolAddress(DRI, Value);
426 uint32_t flags = getSymbolFlags(DRI);
427 if (flags & SymbolRef::SF_Common)
429 return UnknownAddressOrSize;
432 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
433 SymbolRef::Type &Res) const {
434 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
435 uint8_t n_type = Entry.n_type;
437 Res = SymbolRef::ST_Other;
439 // If this is a STAB debugging symbol, we can do nothing more.
440 if (n_type & MachO::N_STAB) {
441 Res = SymbolRef::ST_Debug;
442 return object_error::success;
445 switch (n_type & MachO::N_TYPE) {
447 Res = SymbolRef::ST_Unknown;
450 Res = SymbolRef::ST_Function;
453 return object_error::success;
456 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
459 uint8_t MachOType = Entry.n_type;
460 uint16_t MachOFlags = Entry.n_desc;
462 uint32_t Result = SymbolRef::SF_None;
464 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
465 Result |= SymbolRef::SF_Undefined;
467 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
468 Result |= SymbolRef::SF_Indirect;
470 if (MachOType & MachO::N_STAB)
471 Result |= SymbolRef::SF_FormatSpecific;
473 if (MachOType & MachO::N_EXT) {
474 Result |= SymbolRef::SF_Global;
475 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
477 getSymbolAddress(DRI, Value);
478 if (Value && Value != UnknownAddressOrSize)
479 Result |= SymbolRef::SF_Common;
482 if (!(MachOType & MachO::N_PEXT))
483 Result |= SymbolRef::SF_Exported;
486 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
487 Result |= SymbolRef::SF_Weak;
489 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
490 Result |= SymbolRef::SF_Thumb;
492 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
493 Result |= SymbolRef::SF_Absolute;
498 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
499 section_iterator &Res) const {
500 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
501 uint8_t index = Entry.n_sect;
508 if (DRI.d.a >= Sections.size())
509 report_fatal_error("getSymbolSection: Invalid section index.");
510 Res = section_iterator(SectionRef(DRI, this));
513 return object_error::success;
516 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
520 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
521 StringRef &Result) const {
522 ArrayRef<char> Raw = getSectionRawName(Sec);
523 Result = parseSegmentOrSectionName(Raw.data());
524 return object_error::success;
527 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
529 return getSection64(Sec).addr;
530 return getSection(Sec).addr;
533 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
535 return getSection64(Sec).size;
536 return getSection(Sec).size;
539 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
540 StringRef &Res) const {
545 MachO::section_64 Sect = getSection64(Sec);
546 Offset = Sect.offset;
549 MachO::section Sect = getSection(Sec);
550 Offset = Sect.offset;
554 Res = this->getData().substr(Offset, Size);
555 return object_error::success;
558 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
561 MachO::section_64 Sect = getSection64(Sec);
564 MachO::section Sect = getSection(Sec);
568 return uint64_t(1) << Align;
571 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
572 uint32_t Flags = getSectionFlags(this, Sec);
573 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
576 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
577 uint32_t Flags = getSectionFlags(this, Sec);
578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
579 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
580 !(SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL);
584 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
585 uint32_t Flags = getSectionFlags(this, Sec);
586 unsigned SectionType = Flags & MachO::SECTION_TYPE;
587 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
588 (SectionType == MachO::S_ZEROFILL ||
589 SectionType == MachO::S_GB_ZEROFILL);
592 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
593 // FIXME: Unimplemented.
597 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
598 DataRefImpl Symb) const {
600 this->getSymbolType(Symb, ST);
601 if (ST == SymbolRef::ST_Unknown)
604 uint64_t SectBegin = getSectionAddress(Sec);
605 uint64_t SectEnd = getSectionSize(Sec);
606 SectEnd += SectBegin;
609 getSymbolAddress(Symb, SymAddr);
610 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
613 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
617 return relocation_iterator(RelocationRef(Ret, this));
621 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
624 MachO::section_64 Sect = getSection64(Sec);
627 MachO::section Sect = getSection(Sec);
634 return relocation_iterator(RelocationRef(Ret, this));
637 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
641 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
642 uint64_t &Res) const {
644 getRelocationOffset(Rel, Offset);
648 uint64_t SecAddress = getSectionAddress(Sec);
649 Res = SecAddress + Offset;
650 return object_error::success;
653 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
654 uint64_t &Res) const {
655 assert(getHeader().filetype == MachO::MH_OBJECT &&
656 "Only implemented for MH_OBJECT");
657 MachO::any_relocation_info RE = getRelocation(Rel);
658 Res = getAnyRelocationAddress(RE);
659 return object_error::success;
663 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
664 MachO::any_relocation_info RE = getRelocation(Rel);
665 if (isRelocationScattered(RE))
668 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
669 bool isExtern = getPlainRelocationExternal(RE);
673 MachO::symtab_command S = getSymtabLoadCommand();
674 unsigned SymbolTableEntrySize = is64Bit() ?
675 sizeof(MachO::nlist_64) :
676 sizeof(MachO::nlist);
677 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
679 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
680 return symbol_iterator(SymbolRef(Sym, this));
684 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
685 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
688 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
689 uint64_t &Res) const {
690 MachO::any_relocation_info RE = getRelocation(Rel);
691 Res = getAnyRelocationType(RE);
692 return object_error::success;
696 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
697 SmallVectorImpl<char> &Result) const {
700 getRelocationType(Rel, RType);
702 unsigned Arch = this->getArch();
706 static const char *const Table[] = {
707 "GENERIC_RELOC_VANILLA",
708 "GENERIC_RELOC_PAIR",
709 "GENERIC_RELOC_SECTDIFF",
710 "GENERIC_RELOC_PB_LA_PTR",
711 "GENERIC_RELOC_LOCAL_SECTDIFF",
712 "GENERIC_RELOC_TLV" };
720 case Triple::x86_64: {
721 static const char *const Table[] = {
722 "X86_64_RELOC_UNSIGNED",
723 "X86_64_RELOC_SIGNED",
724 "X86_64_RELOC_BRANCH",
725 "X86_64_RELOC_GOT_LOAD",
727 "X86_64_RELOC_SUBTRACTOR",
728 "X86_64_RELOC_SIGNED_1",
729 "X86_64_RELOC_SIGNED_2",
730 "X86_64_RELOC_SIGNED_4",
731 "X86_64_RELOC_TLV" };
740 static const char *const Table[] = {
743 "ARM_RELOC_SECTDIFF",
744 "ARM_RELOC_LOCAL_SECTDIFF",
745 "ARM_RELOC_PB_LA_PTR",
747 "ARM_THUMB_RELOC_BR22",
748 "ARM_THUMB_32BIT_BRANCH",
750 "ARM_RELOC_HALF_SECTDIFF" };
758 case Triple::aarch64: {
759 static const char *const Table[] = {
760 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
761 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
762 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
763 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
764 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
768 if (RType >= array_lengthof(Table))
775 static const char *const Table[] = {
784 "PPC_RELOC_SECTDIFF",
785 "PPC_RELOC_PB_LA_PTR",
786 "PPC_RELOC_HI16_SECTDIFF",
787 "PPC_RELOC_LO16_SECTDIFF",
788 "PPC_RELOC_HA16_SECTDIFF",
790 "PPC_RELOC_LO14_SECTDIFF",
791 "PPC_RELOC_LOCAL_SECTDIFF" };
799 case Triple::UnknownArch:
803 Result.append(res.begin(), res.end());
804 return object_error::success;
807 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
808 bool &Result) const {
809 unsigned Arch = getArch();
811 getRelocationType(Rel, Type);
815 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
817 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
818 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
819 } else if (Arch == Triple::x86_64) {
820 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
821 // an X86_64_RELOC_SUBTRACTOR.
822 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
823 DataRefImpl RelPrev = Rel;
826 getRelocationType(RelPrev, PrevType);
827 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
832 return object_error::success;
835 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
836 MachO::any_relocation_info RE = getRelocation(Rel);
837 return getAnyRelocationLength(RE);
841 // guessLibraryShortName() is passed a name of a dynamic library and returns a
842 // guess on what the short name is. Then name is returned as a substring of the
843 // StringRef Name passed in. The name of the dynamic library is recognized as
844 // a framework if it has one of the two following forms:
845 // Foo.framework/Versions/A/Foo
847 // Where A and Foo can be any string. And may contain a trailing suffix
848 // starting with an underbar. If the Name is recognized as a framework then
849 // isFramework is set to true else it is set to false. If the Name has a
850 // suffix then Suffix is set to the substring in Name that contains the suffix
851 // else it is set to a NULL StringRef.
853 // The Name of the dynamic library is recognized as a library name if it has
854 // one of the two following forms:
857 // The library may have a suffix trailing the name Foo of the form:
858 // libFoo_profile.A.dylib
859 // libFoo_profile.dylib
861 // The Name of the dynamic library is also recognized as a library name if it
862 // has the following form:
865 // If the Name of the dynamic library is none of the forms above then a NULL
866 // StringRef is returned.
868 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
871 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
872 size_t a, b, c, d, Idx;
875 Suffix = StringRef();
877 // Pull off the last component and make Foo point to it
879 if (a == Name.npos || a == 0)
881 Foo = Name.slice(a+1, Name.npos);
883 // Look for a suffix starting with a '_'
884 Idx = Foo.rfind('_');
885 if (Idx != Foo.npos && Foo.size() >= 2) {
886 Suffix = Foo.slice(Idx, Foo.npos);
887 Foo = Foo.slice(0, Idx);
890 // First look for the form Foo.framework/Foo
891 b = Name.rfind('/', a);
896 F = Name.slice(Idx, Idx + Foo.size());
897 DotFramework = Name.slice(Idx + Foo.size(),
898 Idx + Foo.size() + sizeof(".framework/")-1);
899 if (F == Foo && DotFramework == ".framework/") {
904 // Next look for the form Foo.framework/Versions/A/Foo
907 c = Name.rfind('/', b);
908 if (c == Name.npos || c == 0)
910 V = Name.slice(c+1, Name.npos);
911 if (!V.startswith("Versions/"))
913 d = Name.rfind('/', c);
918 F = Name.slice(Idx, Idx + Foo.size());
919 DotFramework = Name.slice(Idx + Foo.size(),
920 Idx + Foo.size() + sizeof(".framework/")-1);
921 if (F == Foo && DotFramework == ".framework/") {
927 // pull off the suffix after the "." and make a point to it
929 if (a == Name.npos || a == 0)
931 Dylib = Name.slice(a, Name.npos);
932 if (Dylib != ".dylib")
935 // First pull off the version letter for the form Foo.A.dylib if any.
937 Dot = Name.slice(a-2, a-1);
942 b = Name.rfind('/', a);
947 // ignore any suffix after an underbar like Foo_profile.A.dylib
948 Idx = Name.find('_', b);
949 if (Idx != Name.npos && Idx != b) {
950 Lib = Name.slice(b, Idx);
951 Suffix = Name.slice(Idx, a);
954 Lib = Name.slice(b, a);
955 // There are incorrect library names of the form:
956 // libATS.A_profile.dylib so check for these.
957 if (Lib.size() >= 3) {
958 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
960 Lib = Lib.slice(0, Lib.size()-2);
965 Qtx = Name.slice(a, Name.npos);
968 b = Name.rfind('/', a);
970 Lib = Name.slice(0, a);
972 Lib = Name.slice(b+1, a);
973 // There are library names of the form: QT.A.qtx so check for these.
974 if (Lib.size() >= 3) {
975 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
977 Lib = Lib.slice(0, Lib.size()-2);
982 // getLibraryShortNameByIndex() is used to get the short name of the library
983 // for an undefined symbol in a linked Mach-O binary that was linked with the
984 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
985 // It is passed the index (0 - based) of the library as translated from
986 // GET_LIBRARY_ORDINAL (1 - based).
987 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
988 StringRef &Res) const {
989 if (Index >= Libraries.size())
990 return object_error::parse_failed;
992 // If the cache of LibrariesShortNames is not built up do that first for
993 // all the Libraries.
994 if (LibrariesShortNames.size() == 0) {
995 for (unsigned i = 0; i < Libraries.size(); i++) {
996 MachO::dylib_command D =
997 getStruct<MachO::dylib_command>(this, Libraries[i]);
998 if (D.dylib.name >= D.cmdsize)
999 return object_error::parse_failed;
1000 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1001 StringRef Name = StringRef(P);
1002 if (D.dylib.name+Name.size() >= D.cmdsize)
1003 return object_error::parse_failed;
1006 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1007 if (shortName.empty())
1008 LibrariesShortNames.push_back(Name);
1010 LibrariesShortNames.push_back(shortName);
1014 Res = LibrariesShortNames[Index];
1015 return object_error::success;
1018 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1019 return getSymbolByIndex(0);
1022 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1025 return basic_symbol_iterator(SymbolRef(DRI, this));
1027 MachO::symtab_command Symtab = getSymtabLoadCommand();
1028 unsigned SymbolTableEntrySize = is64Bit() ?
1029 sizeof(MachO::nlist_64) :
1030 sizeof(MachO::nlist);
1031 unsigned Offset = Symtab.symoff +
1032 Symtab.nsyms * SymbolTableEntrySize;
1033 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1034 return basic_symbol_iterator(SymbolRef(DRI, this));
1037 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1040 return basic_symbol_iterator(SymbolRef(DRI, this));
1042 MachO::symtab_command Symtab = getSymtabLoadCommand();
1043 if (Index >= Symtab.nsyms)
1044 report_fatal_error("Requested symbol index is out of range.");
1045 unsigned SymbolTableEntrySize =
1046 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1047 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1048 DRI.p += Index * SymbolTableEntrySize;
1049 return basic_symbol_iterator(SymbolRef(DRI, this));
1052 section_iterator MachOObjectFile::section_begin() const {
1054 return section_iterator(SectionRef(DRI, this));
1057 section_iterator MachOObjectFile::section_end() const {
1059 DRI.d.a = Sections.size();
1060 return section_iterator(SectionRef(DRI, this));
1063 uint8_t MachOObjectFile::getBytesInAddress() const {
1064 return is64Bit() ? 8 : 4;
1067 StringRef MachOObjectFile::getFileFormatName() const {
1068 unsigned CPUType = getCPUType(this);
1071 case llvm::MachO::CPU_TYPE_I386:
1072 return "Mach-O 32-bit i386";
1073 case llvm::MachO::CPU_TYPE_ARM:
1074 return "Mach-O arm";
1075 case llvm::MachO::CPU_TYPE_POWERPC:
1076 return "Mach-O 32-bit ppc";
1078 return "Mach-O 32-bit unknown";
1083 case llvm::MachO::CPU_TYPE_X86_64:
1084 return "Mach-O 64-bit x86-64";
1085 case llvm::MachO::CPU_TYPE_ARM64:
1086 return "Mach-O arm64";
1087 case llvm::MachO::CPU_TYPE_POWERPC64:
1088 return "Mach-O 64-bit ppc64";
1090 return "Mach-O 64-bit unknown";
1094 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1096 case llvm::MachO::CPU_TYPE_I386:
1098 case llvm::MachO::CPU_TYPE_X86_64:
1099 return Triple::x86_64;
1100 case llvm::MachO::CPU_TYPE_ARM:
1102 case llvm::MachO::CPU_TYPE_ARM64:
1103 return Triple::aarch64;
1104 case llvm::MachO::CPU_TYPE_POWERPC:
1106 case llvm::MachO::CPU_TYPE_POWERPC64:
1107 return Triple::ppc64;
1109 return Triple::UnknownArch;
1113 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1114 const char **McpuDefault) {
1116 *McpuDefault = nullptr;
1119 case MachO::CPU_TYPE_I386:
1120 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1121 case MachO::CPU_SUBTYPE_I386_ALL:
1122 return Triple("i386-apple-darwin");
1126 case MachO::CPU_TYPE_X86_64:
1127 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1128 case MachO::CPU_SUBTYPE_X86_64_ALL:
1129 return Triple("x86_64-apple-darwin");
1130 case MachO::CPU_SUBTYPE_X86_64_H:
1131 return Triple("x86_64h-apple-darwin");
1135 case MachO::CPU_TYPE_ARM:
1136 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1137 case MachO::CPU_SUBTYPE_ARM_V4T:
1138 return Triple("armv4t-apple-darwin");
1139 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1140 return Triple("armv5e-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1142 return Triple("xscale-apple-darwin");
1143 case MachO::CPU_SUBTYPE_ARM_V6:
1144 return Triple("armv6-apple-darwin");
1145 case MachO::CPU_SUBTYPE_ARM_V6M:
1147 *McpuDefault = "cortex-m0";
1148 return Triple("armv6m-apple-darwin");
1149 case MachO::CPU_SUBTYPE_ARM_V7:
1150 return Triple("armv7-apple-darwin");
1151 case MachO::CPU_SUBTYPE_ARM_V7EM:
1153 *McpuDefault = "cortex-m4";
1154 return Triple("armv7em-apple-darwin");
1155 case MachO::CPU_SUBTYPE_ARM_V7K:
1156 return Triple("armv7k-apple-darwin");
1157 case MachO::CPU_SUBTYPE_ARM_V7M:
1159 *McpuDefault = "cortex-m3";
1160 return Triple("armv7m-apple-darwin");
1161 case MachO::CPU_SUBTYPE_ARM_V7S:
1162 return Triple("armv7s-apple-darwin");
1166 case MachO::CPU_TYPE_ARM64:
1167 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1168 case MachO::CPU_SUBTYPE_ARM64_ALL:
1169 return Triple("arm64-apple-darwin");
1173 case MachO::CPU_TYPE_POWERPC:
1174 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1175 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1176 return Triple("ppc-apple-darwin");
1180 case MachO::CPU_TYPE_POWERPC64:
1181 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1182 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1183 return Triple("ppc64-apple-darwin");
1192 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1193 const char **McpuDefault) {
1195 *McpuDefault = nullptr;
1198 case MachO::CPU_TYPE_ARM:
1199 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1200 case MachO::CPU_SUBTYPE_ARM_V4T:
1201 return Triple("thumbv4t-apple-darwin");
1202 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1203 return Triple("thumbv5e-apple-darwin");
1204 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1205 return Triple("xscale-apple-darwin");
1206 case MachO::CPU_SUBTYPE_ARM_V6:
1207 return Triple("thumbv6-apple-darwin");
1208 case MachO::CPU_SUBTYPE_ARM_V6M:
1210 *McpuDefault = "cortex-m0";
1211 return Triple("thumbv6m-apple-darwin");
1212 case MachO::CPU_SUBTYPE_ARM_V7:
1213 return Triple("thumbv7-apple-darwin");
1214 case MachO::CPU_SUBTYPE_ARM_V7EM:
1216 *McpuDefault = "cortex-m4";
1217 return Triple("thumbv7em-apple-darwin");
1218 case MachO::CPU_SUBTYPE_ARM_V7K:
1219 return Triple("thumbv7k-apple-darwin");
1220 case MachO::CPU_SUBTYPE_ARM_V7M:
1222 *McpuDefault = "cortex-m3";
1223 return Triple("thumbv7m-apple-darwin");
1224 case MachO::CPU_SUBTYPE_ARM_V7S:
1225 return Triple("thumbv7s-apple-darwin");
1234 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1235 const char **McpuDefault,
1236 Triple *ThumbTriple) {
1237 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1238 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1243 Triple MachOObjectFile::getHostArch() {
1244 return Triple(sys::getDefaultTargetTriple());
1247 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1248 return StringSwitch<bool>(ArchFlag)
1250 .Case("x86_64", true)
1251 .Case("x86_64h", true)
1252 .Case("armv4t", true)
1254 .Case("armv5e", true)
1255 .Case("armv6", true)
1256 .Case("armv6m", true)
1257 .Case("armv7em", true)
1258 .Case("armv7k", true)
1259 .Case("armv7m", true)
1260 .Case("armv7s", true)
1261 .Case("arm64", true)
1263 .Case("ppc64", true)
1267 unsigned MachOObjectFile::getArch() const {
1268 return getArch(getCPUType(this));
1271 Triple MachOObjectFile::getArch(const char **McpuDefault,
1272 Triple *ThumbTriple) const {
1273 const auto &Header = getHeader();
1274 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1275 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1278 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1281 return section_rel_begin(DRI);
1284 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1287 return section_rel_end(DRI);
1290 dice_iterator MachOObjectFile::begin_dices() const {
1292 if (!DataInCodeLoadCmd)
1293 return dice_iterator(DiceRef(DRI, this));
1295 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1296 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1297 return dice_iterator(DiceRef(DRI, this));
1300 dice_iterator MachOObjectFile::end_dices() const {
1302 if (!DataInCodeLoadCmd)
1303 return dice_iterator(DiceRef(DRI, this));
1305 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1306 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1307 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1308 return dice_iterator(DiceRef(DRI, this));
1311 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1312 : Trie(T), Malformed(false), Done(false) { }
1314 void ExportEntry::moveToFirst() {
1316 pushDownUntilBottom();
1319 void ExportEntry::moveToEnd() {
1324 bool ExportEntry::operator==(const ExportEntry &Other) const {
1325 // Common case, one at end, other iterating from begin.
1326 if (Done || Other.Done)
1327 return (Done == Other.Done);
1328 // Not equal if different stack sizes.
1329 if (Stack.size() != Other.Stack.size())
1331 // Not equal if different cumulative strings.
1332 if (!CumulativeString.equals(Other.CumulativeString))
1334 // Equal if all nodes in both stacks match.
1335 for (unsigned i=0; i < Stack.size(); ++i) {
1336 if (Stack[i].Start != Other.Stack[i].Start)
1342 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1344 uint64_t Result = decodeULEB128(Ptr, &Count);
1346 if (Ptr > Trie.end()) {
1353 StringRef ExportEntry::name() const {
1354 return CumulativeString;
1357 uint64_t ExportEntry::flags() const {
1358 return Stack.back().Flags;
1361 uint64_t ExportEntry::address() const {
1362 return Stack.back().Address;
1365 uint64_t ExportEntry::other() const {
1366 return Stack.back().Other;
1369 StringRef ExportEntry::otherName() const {
1370 const char* ImportName = Stack.back().ImportName;
1372 return StringRef(ImportName);
1376 uint32_t ExportEntry::nodeOffset() const {
1377 return Stack.back().Start - Trie.begin();
1380 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1381 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1382 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1383 ParentStringLength(0), IsExportNode(false) {
1386 void ExportEntry::pushNode(uint64_t offset) {
1387 const uint8_t *Ptr = Trie.begin() + offset;
1388 NodeState State(Ptr);
1389 uint64_t ExportInfoSize = readULEB128(State.Current);
1390 State.IsExportNode = (ExportInfoSize != 0);
1391 const uint8_t* Children = State.Current + ExportInfoSize;
1392 if (State.IsExportNode) {
1393 State.Flags = readULEB128(State.Current);
1394 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1396 State.Other = readULEB128(State.Current); // dylib ordinal
1397 State.ImportName = reinterpret_cast<const char*>(State.Current);
1399 State.Address = readULEB128(State.Current);
1400 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1401 State.Other = readULEB128(State.Current);
1404 State.ChildCount = *Children;
1405 State.Current = Children + 1;
1406 State.NextChildIndex = 0;
1407 State.ParentStringLength = CumulativeString.size();
1408 Stack.push_back(State);
1411 void ExportEntry::pushDownUntilBottom() {
1412 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1413 NodeState &Top = Stack.back();
1414 CumulativeString.resize(Top.ParentStringLength);
1415 for (;*Top.Current != 0; Top.Current++) {
1416 char C = *Top.Current;
1417 CumulativeString.push_back(C);
1420 uint64_t childNodeIndex = readULEB128(Top.Current);
1421 Top.NextChildIndex += 1;
1422 pushNode(childNodeIndex);
1424 if (!Stack.back().IsExportNode) {
1430 // We have a trie data structure and need a way to walk it that is compatible
1431 // with the C++ iterator model. The solution is a non-recursive depth first
1432 // traversal where the iterator contains a stack of parent nodes along with a
1433 // string that is the accumulation of all edge strings along the parent chain
1436 // There is one "export" node for each exported symbol. But because some
1437 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1438 // node may have child nodes too.
1440 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1441 // child until hitting a node with no children (which is an export node or
1442 // else the trie is malformed). On the way down, each node is pushed on the
1443 // stack ivar. If there is no more ways down, it pops up one and tries to go
1444 // down a sibling path until a childless node is reached.
1445 void ExportEntry::moveNext() {
1446 if (Stack.empty() || !Stack.back().IsExportNode) {
1453 while (!Stack.empty()) {
1454 NodeState &Top = Stack.back();
1455 if (Top.NextChildIndex < Top.ChildCount) {
1456 pushDownUntilBottom();
1457 // Now at the next export node.
1460 if (Top.IsExportNode) {
1461 // This node has no children but is itself an export node.
1462 CumulativeString.resize(Top.ParentStringLength);
1471 iterator_range<export_iterator>
1472 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1473 ExportEntry Start(Trie);
1474 if (Trie.size() == 0)
1477 Start.moveToFirst();
1479 ExportEntry Finish(Trie);
1482 return iterator_range<export_iterator>(export_iterator(Start),
1483 export_iterator(Finish));
1486 iterator_range<export_iterator> MachOObjectFile::exports() const {
1487 return exports(getDyldInfoExportsTrie());
1491 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1492 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1493 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1494 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1496 void MachORebaseEntry::moveToFirst() {
1497 Ptr = Opcodes.begin();
1501 void MachORebaseEntry::moveToEnd() {
1502 Ptr = Opcodes.end();
1503 RemainingLoopCount = 0;
1507 void MachORebaseEntry::moveNext() {
1508 // If in the middle of some loop, move to next rebasing in loop.
1509 SegmentOffset += AdvanceAmount;
1510 if (RemainingLoopCount) {
1511 --RemainingLoopCount;
1514 if (Ptr == Opcodes.end()) {
1519 while (More && !Malformed) {
1520 // Parse next opcode and set up next loop.
1521 uint8_t Byte = *Ptr++;
1522 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1523 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1525 case MachO::REBASE_OPCODE_DONE:
1529 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1531 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1532 RebaseType = ImmValue;
1535 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1536 << "RebaseType=" << (int) RebaseType << "\n");
1538 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1539 SegmentIndex = ImmValue;
1540 SegmentOffset = readULEB128();
1543 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1544 << "SegmentIndex=" << SegmentIndex << ", "
1545 << format("SegmentOffset=0x%06X", SegmentOffset)
1548 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1549 SegmentOffset += readULEB128();
1550 DEBUG_WITH_TYPE("mach-o-rebase",
1551 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1552 << format("SegmentOffset=0x%06X",
1553 SegmentOffset) << "\n");
1555 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1556 SegmentOffset += ImmValue * PointerSize;
1557 DEBUG_WITH_TYPE("mach-o-rebase",
1558 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1559 << format("SegmentOffset=0x%06X",
1560 SegmentOffset) << "\n");
1562 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1563 AdvanceAmount = PointerSize;
1564 RemainingLoopCount = ImmValue - 1;
1567 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1568 << format("SegmentOffset=0x%06X", SegmentOffset)
1569 << ", AdvanceAmount=" << AdvanceAmount
1570 << ", RemainingLoopCount=" << RemainingLoopCount
1573 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1574 AdvanceAmount = PointerSize;
1575 RemainingLoopCount = readULEB128() - 1;
1578 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1579 << format("SegmentOffset=0x%06X", SegmentOffset)
1580 << ", AdvanceAmount=" << AdvanceAmount
1581 << ", RemainingLoopCount=" << RemainingLoopCount
1584 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1585 AdvanceAmount = readULEB128() + PointerSize;
1586 RemainingLoopCount = 0;
1589 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1590 << format("SegmentOffset=0x%06X", SegmentOffset)
1591 << ", AdvanceAmount=" << AdvanceAmount
1592 << ", RemainingLoopCount=" << RemainingLoopCount
1595 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1596 RemainingLoopCount = readULEB128() - 1;
1597 AdvanceAmount = readULEB128() + PointerSize;
1600 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1601 << format("SegmentOffset=0x%06X", SegmentOffset)
1602 << ", AdvanceAmount=" << AdvanceAmount
1603 << ", RemainingLoopCount=" << RemainingLoopCount
1612 uint64_t MachORebaseEntry::readULEB128() {
1614 uint64_t Result = decodeULEB128(Ptr, &Count);
1616 if (Ptr > Opcodes.end()) {
1617 Ptr = Opcodes.end();
1623 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1625 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1627 StringRef MachORebaseEntry::typeName() const {
1628 switch (RebaseType) {
1629 case MachO::REBASE_TYPE_POINTER:
1631 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1632 return "text abs32";
1633 case MachO::REBASE_TYPE_TEXT_PCREL32:
1634 return "text rel32";
1639 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1640 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1641 return (Ptr == Other.Ptr) &&
1642 (RemainingLoopCount == Other.RemainingLoopCount) &&
1643 (Done == Other.Done);
1646 iterator_range<rebase_iterator>
1647 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1648 MachORebaseEntry Start(Opcodes, is64);
1649 Start.moveToFirst();
1651 MachORebaseEntry Finish(Opcodes, is64);
1654 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1655 rebase_iterator(Finish));
1658 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1659 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1663 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1665 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1666 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1667 BindType(0), PointerSize(is64Bit ? 8 : 4),
1668 TableKind(BK), Malformed(false), Done(false) {}
1670 void MachOBindEntry::moveToFirst() {
1671 Ptr = Opcodes.begin();
1675 void MachOBindEntry::moveToEnd() {
1676 Ptr = Opcodes.end();
1677 RemainingLoopCount = 0;
1681 void MachOBindEntry::moveNext() {
1682 // If in the middle of some loop, move to next binding in loop.
1683 SegmentOffset += AdvanceAmount;
1684 if (RemainingLoopCount) {
1685 --RemainingLoopCount;
1688 if (Ptr == Opcodes.end()) {
1693 while (More && !Malformed) {
1694 // Parse next opcode and set up next loop.
1695 uint8_t Byte = *Ptr++;
1696 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1697 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1698 int8_t SignExtended;
1699 const uint8_t *SymStart;
1701 case MachO::BIND_OPCODE_DONE:
1702 if (TableKind == Kind::Lazy) {
1703 // Lazying bindings have a DONE opcode between entries. Need to ignore
1704 // it to advance to next entry. But need not if this is last entry.
1705 bool NotLastEntry = false;
1706 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1708 NotLastEntry = true;
1717 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1719 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1723 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1724 << "Ordinal=" << Ordinal << "\n");
1726 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1727 Ordinal = readULEB128();
1730 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1731 << "Ordinal=" << Ordinal << "\n");
1733 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1735 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1736 Ordinal = SignExtended;
1741 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1742 << "Ordinal=" << Ordinal << "\n");
1744 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1750 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1755 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1756 << "SymbolName=" << SymbolName << "\n");
1757 if (TableKind == Kind::Weak) {
1758 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1762 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1763 BindType = ImmValue;
1766 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1767 << "BindType=" << (int)BindType << "\n");
1769 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1770 Addend = readSLEB128();
1771 if (TableKind == Kind::Lazy)
1775 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1776 << "Addend=" << Addend << "\n");
1778 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1779 SegmentIndex = ImmValue;
1780 SegmentOffset = readULEB128();
1783 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1784 << "SegmentIndex=" << SegmentIndex << ", "
1785 << format("SegmentOffset=0x%06X", SegmentOffset)
1788 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1789 SegmentOffset += readULEB128();
1790 DEBUG_WITH_TYPE("mach-o-bind",
1791 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1792 << format("SegmentOffset=0x%06X",
1793 SegmentOffset) << "\n");
1795 case MachO::BIND_OPCODE_DO_BIND:
1796 AdvanceAmount = PointerSize;
1797 RemainingLoopCount = 0;
1798 DEBUG_WITH_TYPE("mach-o-bind",
1799 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1800 << format("SegmentOffset=0x%06X",
1801 SegmentOffset) << "\n");
1803 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1804 AdvanceAmount = readULEB128() + PointerSize;
1805 RemainingLoopCount = 0;
1806 if (TableKind == Kind::Lazy)
1810 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1811 << format("SegmentOffset=0x%06X", SegmentOffset)
1812 << ", AdvanceAmount=" << AdvanceAmount
1813 << ", RemainingLoopCount=" << RemainingLoopCount
1816 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1817 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1818 RemainingLoopCount = 0;
1819 if (TableKind == Kind::Lazy)
1821 DEBUG_WITH_TYPE("mach-o-bind",
1823 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1824 << format("SegmentOffset=0x%06X",
1825 SegmentOffset) << "\n");
1827 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1828 RemainingLoopCount = readULEB128() - 1;
1829 AdvanceAmount = readULEB128() + PointerSize;
1830 if (TableKind == Kind::Lazy)
1834 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1835 << format("SegmentOffset=0x%06X", SegmentOffset)
1836 << ", AdvanceAmount=" << AdvanceAmount
1837 << ", RemainingLoopCount=" << RemainingLoopCount
1846 uint64_t MachOBindEntry::readULEB128() {
1848 uint64_t Result = decodeULEB128(Ptr, &Count);
1850 if (Ptr > Opcodes.end()) {
1851 Ptr = Opcodes.end();
1857 int64_t MachOBindEntry::readSLEB128() {
1859 int64_t Result = decodeSLEB128(Ptr, &Count);
1861 if (Ptr > Opcodes.end()) {
1862 Ptr = Opcodes.end();
1869 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1871 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1873 StringRef MachOBindEntry::typeName() const {
1875 case MachO::BIND_TYPE_POINTER:
1877 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1878 return "text abs32";
1879 case MachO::BIND_TYPE_TEXT_PCREL32:
1880 return "text rel32";
1885 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1887 int64_t MachOBindEntry::addend() const { return Addend; }
1889 uint32_t MachOBindEntry::flags() const { return Flags; }
1891 int MachOBindEntry::ordinal() const { return Ordinal; }
1893 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1894 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1895 return (Ptr == Other.Ptr) &&
1896 (RemainingLoopCount == Other.RemainingLoopCount) &&
1897 (Done == Other.Done);
1900 iterator_range<bind_iterator>
1901 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1902 MachOBindEntry::Kind BKind) {
1903 MachOBindEntry Start(Opcodes, is64, BKind);
1904 Start.moveToFirst();
1906 MachOBindEntry Finish(Opcodes, is64, BKind);
1909 return iterator_range<bind_iterator>(bind_iterator(Start),
1910 bind_iterator(Finish));
1913 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1914 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1915 MachOBindEntry::Kind::Regular);
1918 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1919 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1920 MachOBindEntry::Kind::Lazy);
1923 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1924 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1925 MachOBindEntry::Kind::Weak);
1928 MachOObjectFile::load_command_iterator
1929 MachOObjectFile::begin_load_commands() const {
1930 return LoadCommands.begin();
1933 MachOObjectFile::load_command_iterator
1934 MachOObjectFile::end_load_commands() const {
1935 return LoadCommands.end();
1938 iterator_range<MachOObjectFile::load_command_iterator>
1939 MachOObjectFile::load_commands() const {
1940 return iterator_range<load_command_iterator>(begin_load_commands(),
1941 end_load_commands());
1945 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1946 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1947 return parseSegmentOrSectionName(Raw.data());
1951 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1952 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1953 const section_base *Base =
1954 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1955 return makeArrayRef(Base->sectname);
1959 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1960 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1961 const section_base *Base =
1962 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1963 return makeArrayRef(Base->segname);
1967 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1969 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1971 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1974 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1975 const MachO::any_relocation_info &RE) const {
1976 if (isLittleEndian())
1977 return RE.r_word1 & 0xffffff;
1978 return RE.r_word1 >> 8;
1981 bool MachOObjectFile::getPlainRelocationExternal(
1982 const MachO::any_relocation_info &RE) const {
1983 if (isLittleEndian())
1984 return (RE.r_word1 >> 27) & 1;
1985 return (RE.r_word1 >> 4) & 1;
1988 bool MachOObjectFile::getScatteredRelocationScattered(
1989 const MachO::any_relocation_info &RE) const {
1990 return RE.r_word0 >> 31;
1993 uint32_t MachOObjectFile::getScatteredRelocationValue(
1994 const MachO::any_relocation_info &RE) const {
1998 uint32_t MachOObjectFile::getScatteredRelocationType(
1999 const MachO::any_relocation_info &RE) const {
2000 return (RE.r_word0 >> 24) & 0xf;
2003 unsigned MachOObjectFile::getAnyRelocationAddress(
2004 const MachO::any_relocation_info &RE) const {
2005 if (isRelocationScattered(RE))
2006 return getScatteredRelocationAddress(RE);
2007 return getPlainRelocationAddress(RE);
2010 unsigned MachOObjectFile::getAnyRelocationPCRel(
2011 const MachO::any_relocation_info &RE) const {
2012 if (isRelocationScattered(RE))
2013 return getScatteredRelocationPCRel(this, RE);
2014 return getPlainRelocationPCRel(this, RE);
2017 unsigned MachOObjectFile::getAnyRelocationLength(
2018 const MachO::any_relocation_info &RE) const {
2019 if (isRelocationScattered(RE))
2020 return getScatteredRelocationLength(RE);
2021 return getPlainRelocationLength(this, RE);
2025 MachOObjectFile::getAnyRelocationType(
2026 const MachO::any_relocation_info &RE) const {
2027 if (isRelocationScattered(RE))
2028 return getScatteredRelocationType(RE);
2029 return getPlainRelocationType(this, RE);
2033 MachOObjectFile::getAnyRelocationSection(
2034 const MachO::any_relocation_info &RE) const {
2035 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2036 return *section_end();
2037 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2040 return SectionRef(DRI, this);
2043 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2044 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2045 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2048 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2049 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2050 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2053 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2054 unsigned Index) const {
2055 const char *Sec = getSectionPtr(this, L, Index);
2056 return getStruct<MachO::section>(this, Sec);
2059 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2060 unsigned Index) const {
2061 const char *Sec = getSectionPtr(this, L, Index);
2062 return getStruct<MachO::section_64>(this, Sec);
2066 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2067 const char *P = reinterpret_cast<const char *>(DRI.p);
2068 return getStruct<MachO::nlist>(this, P);
2072 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2073 const char *P = reinterpret_cast<const char *>(DRI.p);
2074 return getStruct<MachO::nlist_64>(this, P);
2077 MachO::linkedit_data_command
2078 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2079 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2082 MachO::segment_command
2083 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2084 return getStruct<MachO::segment_command>(this, L.Ptr);
2087 MachO::segment_command_64
2088 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2089 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2092 MachO::linker_option_command
2093 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2094 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2097 MachO::version_min_command
2098 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2099 return getStruct<MachO::version_min_command>(this, L.Ptr);
2102 MachO::dylib_command
2103 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2104 return getStruct<MachO::dylib_command>(this, L.Ptr);
2107 MachO::dyld_info_command
2108 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2109 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2112 MachO::dylinker_command
2113 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2114 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2118 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2119 return getStruct<MachO::uuid_command>(this, L.Ptr);
2122 MachO::rpath_command
2123 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2124 return getStruct<MachO::rpath_command>(this, L.Ptr);
2127 MachO::source_version_command
2128 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2129 return getStruct<MachO::source_version_command>(this, L.Ptr);
2132 MachO::entry_point_command
2133 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2134 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2137 MachO::encryption_info_command
2138 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2139 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2142 MachO::encryption_info_command_64
2143 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2144 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2147 MachO::sub_framework_command
2148 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2149 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2152 MachO::sub_umbrella_command
2153 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2154 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2157 MachO::sub_library_command
2158 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2159 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2162 MachO::sub_client_command
2163 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2164 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2167 MachO::routines_command
2168 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2169 return getStruct<MachO::routines_command>(this, L.Ptr);
2172 MachO::routines_command_64
2173 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2174 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2177 MachO::thread_command
2178 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2179 return getStruct<MachO::thread_command>(this, L.Ptr);
2182 MachO::any_relocation_info
2183 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2188 MachO::section_64 Sect = getSection64(Sec);
2189 Offset = Sect.reloff;
2191 MachO::section Sect = getSection(Sec);
2192 Offset = Sect.reloff;
2195 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2196 getPtr(this, Offset)) + Rel.d.b;
2197 return getStruct<MachO::any_relocation_info>(
2198 this, reinterpret_cast<const char *>(P));
2201 MachO::data_in_code_entry
2202 MachOObjectFile::getDice(DataRefImpl Rel) const {
2203 const char *P = reinterpret_cast<const char *>(Rel.p);
2204 return getStruct<MachO::data_in_code_entry>(this, P);
2207 const MachO::mach_header &MachOObjectFile::getHeader() const {
2208 // First fields of MachO::mach_header_64 are the same as
2209 // in MachO::mach_header.
2210 return *reinterpret_cast<const MachO::mach_header *>(&this->Header64);
2213 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2218 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2219 const MachO::dysymtab_command &DLC,
2220 unsigned Index) const {
2221 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2222 return getStruct<uint32_t>(this, getPtr(this, Offset));
2225 MachO::data_in_code_entry
2226 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2227 unsigned Index) const {
2228 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2229 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2232 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2234 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2236 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2237 MachO::symtab_command Cmd;
2238 Cmd.cmd = MachO::LC_SYMTAB;
2239 Cmd.cmdsize = sizeof(MachO::symtab_command);
2247 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2248 if (DysymtabLoadCmd)
2249 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2251 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2252 MachO::dysymtab_command Cmd;
2253 Cmd.cmd = MachO::LC_DYSYMTAB;
2254 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2265 Cmd.extrefsymoff = 0;
2266 Cmd.nextrefsyms = 0;
2267 Cmd.indirectsymoff = 0;
2268 Cmd.nindirectsyms = 0;
2276 MachO::linkedit_data_command
2277 MachOObjectFile::getDataInCodeLoadCommand() const {
2278 if (DataInCodeLoadCmd)
2279 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2281 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2282 MachO::linkedit_data_command Cmd;
2283 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2284 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2290 MachO::linkedit_data_command
2291 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2292 if (LinkOptHintsLoadCmd)
2293 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2295 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2297 MachO::linkedit_data_command Cmd;
2298 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2299 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2305 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2306 if (!DyldInfoLoadCmd)
2307 return ArrayRef<uint8_t>();
2309 MachO::dyld_info_command DyldInfo
2310 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2311 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2312 getPtr(this, DyldInfo.rebase_off));
2313 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2316 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2317 if (!DyldInfoLoadCmd)
2318 return ArrayRef<uint8_t>();
2320 MachO::dyld_info_command DyldInfo
2321 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2322 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2323 getPtr(this, DyldInfo.bind_off));
2324 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2327 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2328 if (!DyldInfoLoadCmd)
2329 return ArrayRef<uint8_t>();
2331 MachO::dyld_info_command DyldInfo
2332 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2333 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2334 getPtr(this, DyldInfo.weak_bind_off));
2335 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2338 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2339 if (!DyldInfoLoadCmd)
2340 return ArrayRef<uint8_t>();
2342 MachO::dyld_info_command DyldInfo
2343 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2344 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2345 getPtr(this, DyldInfo.lazy_bind_off));
2346 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2349 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2350 if (!DyldInfoLoadCmd)
2351 return ArrayRef<uint8_t>();
2353 MachO::dyld_info_command DyldInfo
2354 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2355 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2356 getPtr(this, DyldInfo.export_off));
2357 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2360 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2362 return ArrayRef<uint8_t>();
2363 // Returning a pointer is fine as uuid doesn't need endian swapping.
2364 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2365 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2368 StringRef MachOObjectFile::getStringTableData() const {
2369 MachO::symtab_command S = getSymtabLoadCommand();
2370 return getData().substr(S.stroff, S.strsize);
2373 bool MachOObjectFile::is64Bit() const {
2374 return getType() == getMachOType(false, true) ||
2375 getType() == getMachOType(true, true);
2378 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2379 SmallVectorImpl<uint64_t> &Out) const {
2380 DataExtractor extractor(ObjectFile::getData(), true, 0);
2382 uint32_t offset = Index;
2384 while (uint64_t delta = extractor.getULEB128(&offset)) {
2386 Out.push_back(data);
2390 bool MachOObjectFile::isRelocatableObject() const {
2391 return getHeader().filetype == MachO::MH_OBJECT;
2394 ErrorOr<std::unique_ptr<MachOObjectFile>>
2395 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2396 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2398 std::unique_ptr<MachOObjectFile> Ret;
2399 if (Magic == "\xFE\xED\xFA\xCE")
2400 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2401 else if (Magic == "\xCE\xFA\xED\xFE")
2402 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2403 else if (Magic == "\xFE\xED\xFA\xCF")
2404 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2405 else if (Magic == "\xCF\xFA\xED\xFE")
2406 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2408 return object_error::parse_failed;
2412 return std::move(Ret);