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;
42 static T getStruct(const MachOObjectFile *O, const char *P) {
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
46 MachO::swapStruct(Cmd);
51 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
54 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
57 MachO::segment_command S = O->getSegmentLoadCommand(L);
61 static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
73 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
75 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
77 bool Is64 = O->is64Bit();
78 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
84 return reinterpret_cast<const char*>(SectionAddr);
87 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
91 static MachO::nlist_base
92 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
93 const char *P = reinterpret_cast<const char *>(DRI.p);
94 return getStruct<MachO::nlist_base>(O, P);
97 static StringRef parseSegmentOrSectionName(const char *P) {
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
105 // Helper to advance a section or symbol iterator multiple increments at a time.
107 static void advance(T &it, size_t Val) {
112 static unsigned getCPUType(const MachOObjectFile *O) {
113 return O->getHeader().cputype;
116 static void printRelocationTargetName(const MachOObjectFile *O,
117 const MachO::any_relocation_info &RE,
118 raw_string_ostream &fmt) {
119 bool IsScattered = O->isRelocationScattered(RE);
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
128 for (const SymbolRef &Symbol : O->symbols()) {
133 if ((ec = Symbol.getAddress(Addr)))
134 report_fatal_error(ec.message());
137 if ((ec = Symbol.getName(Name)))
138 report_fatal_error(ec.message());
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
145 for (const SectionRef &Section : O->sections()) {
149 uint64_t Addr = Section.getAddress();
152 if ((ec = Section.getName(Name)))
153 report_fatal_error(ec.message());
158 fmt << format("0x%x", Val);
163 bool isExtern = O->getPlainRelocationExternal(RE);
164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
167 symbol_iterator SI = O->symbol_begin();
171 section_iterator SI = O->section_begin();
172 // Adjust for the fact that sections are 1-indexed.
173 advance(SI, Val - 1);
181 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
186 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
190 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
191 const MachO::any_relocation_info &RE) {
192 if (O->isLittleEndian())
193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
198 getScatteredRelocationPCRel(const MachOObjectFile *O,
199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
203 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
211 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
215 static unsigned getPlainRelocationType(const MachOObjectFile *O,
216 const MachO::any_relocation_info &RE) {
217 if (O->isLittleEndian())
218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
222 static uint32_t getSectionFlags(const MachOObjectFile *O,
225 MachO::section_64 Sect = O->getSection64(Sec);
228 MachO::section Sect = O->getSection(Sec);
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), DyldInfoLoadCmd(nullptr),
237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 if (LoadCommandCount == 0)
242 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
243 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
245 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
246 for (unsigned I = 0; ; ++I) {
247 if (Load.C.cmd == MachO::LC_SYMTAB) {
248 // Multiple symbol tables
250 EC = object_error::parse_failed;
253 SymtabLoadCmd = Load.Ptr;
254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
255 // Multiple dynamic symbol tables
256 if (DysymtabLoadCmd) {
257 EC = object_error::parse_failed;
260 DysymtabLoadCmd = Load.Ptr;
261 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
262 // Multiple data in code tables
263 if (DataInCodeLoadCmd) {
264 EC = object_error::parse_failed;
267 DataInCodeLoadCmd = Load.Ptr;
268 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
269 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
270 // Multiple dyldinfo load commands
271 if (DyldInfoLoadCmd) {
272 EC = object_error::parse_failed;
275 DyldInfoLoadCmd = Load.Ptr;
276 } else if (Load.C.cmd == MachO::LC_UUID) {
277 // Multiple UUID load commands
279 EC = object_error::parse_failed;
282 UuidLoadCmd = Load.Ptr;
283 } else if (Load.C.cmd == SegmentLoadType) {
284 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
285 for (unsigned J = 0; J < NumSections; ++J) {
286 const char *Sec = getSectionPtr(this, Load, J);
287 Sections.push_back(Sec);
289 if (isPageZeroSegment(this, Load))
290 HasPageZeroSegment = true;
291 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
293 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
294 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
295 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
296 Libraries.push_back(Load.Ptr);
299 if (I == LoadCommandCount - 1)
302 Load = getNextLoadCommandInfo(Load);
306 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
307 unsigned SymbolTableEntrySize = is64Bit() ?
308 sizeof(MachO::nlist_64) :
309 sizeof(MachO::nlist);
310 Symb.p += SymbolTableEntrySize;
313 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
314 StringRef &Res) const {
315 StringRef StringTable = getStringTableData();
316 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
317 const char *Start = &StringTable.data()[Entry.n_strx];
318 Res = StringRef(Start);
319 return object_error::success;
322 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
323 DataRefImpl DRI = Sec.getRawDataRefImpl();
324 uint32_t Flags = getSectionFlags(this, DRI);
325 return Flags & MachO::SECTION_TYPE;
328 // getIndirectName() returns the name of the alias'ed symbol who's string table
329 // index is in the n_value field.
330 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
335 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
336 NValue = Entry.n_value;
337 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
338 return object_error::parse_failed;
340 MachO::nlist Entry = getSymbolTableEntry(Symb);
341 NValue = Entry.n_value;
342 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
343 return object_error::parse_failed;
345 if (NValue >= StringTable.size())
346 return object_error::parse_failed;
347 const char *Start = &StringTable.data()[NValue];
348 Res = StringRef(Start);
349 return object_error::success;
352 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
353 uint64_t &Res) const {
355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
356 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
358 Res = UnknownAddressOrSize;
362 MachO::nlist Entry = getSymbolTableEntry(Symb);
363 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
365 Res = UnknownAddressOrSize;
369 return object_error::success;
372 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
373 uint32_t &Result) const {
374 uint32_t flags = getSymbolFlags(DRI);
375 if (flags & SymbolRef::SF_Common) {
376 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
377 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
381 return object_error::success;
384 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
385 uint64_t &Result) const {
386 uint64_t BeginOffset;
387 uint64_t EndOffset = 0;
388 uint8_t SectionIndex;
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
392 getSymbolAddress(DRI, Value);
393 if (Value == UnknownAddressOrSize) {
394 Result = UnknownAddressOrSize;
395 return object_error::success;
400 SectionIndex = Entry.n_sect;
402 uint32_t flags = getSymbolFlags(DRI);
403 if (flags & SymbolRef::SF_Common)
406 Result = UnknownAddressOrSize;
407 return object_error::success;
409 // Unfortunately symbols are unsorted so we need to touch all
410 // symbols from load command
411 for (const SymbolRef &Symbol : symbols()) {
412 DataRefImpl DRI = Symbol.getRawDataRefImpl();
413 Entry = getSymbolTableEntryBase(this, DRI);
414 getSymbolAddress(DRI, Value);
415 if (Value == UnknownAddressOrSize)
417 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
418 if (!EndOffset || Value < EndOffset)
423 Sec.d.a = SectionIndex-1;
424 uint64_t Size = getSectionSize(Sec);
425 EndOffset = getSectionAddress(Sec);
428 Result = EndOffset - BeginOffset;
429 return object_error::success;
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 Res = section_iterator(SectionRef(DRI, this));
511 return object_error::success;
514 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
518 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
519 StringRef &Result) const {
520 ArrayRef<char> Raw = getSectionRawName(Sec);
521 Result = parseSegmentOrSectionName(Raw.data());
522 return object_error::success;
525 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
527 return getSection64(Sec).addr;
528 return getSection(Sec).addr;
531 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
533 return getSection64(Sec).size;
534 return getSection(Sec).size;
537 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
538 StringRef &Res) const {
543 MachO::section_64 Sect = getSection64(Sec);
544 Offset = Sect.offset;
547 MachO::section Sect = getSection(Sec);
548 Offset = Sect.offset;
552 Res = this->getData().substr(Offset, Size);
553 return object_error::success;
556 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
559 MachO::section_64 Sect = getSection64(Sec);
562 MachO::section Sect = getSection(Sec);
566 return uint64_t(1) << Align;
569 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
570 uint32_t Flags = getSectionFlags(this, Sec);
571 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
574 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
575 uint32_t Flags = getSectionFlags(this, Sec);
576 unsigned SectionType = Flags & MachO::SECTION_TYPE;
577 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
578 !(SectionType == MachO::S_ZEROFILL ||
579 SectionType == MachO::S_GB_ZEROFILL);
582 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
583 uint32_t Flags = getSectionFlags(this, Sec);
584 unsigned SectionType = Flags & MachO::SECTION_TYPE;
585 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
586 (SectionType == MachO::S_ZEROFILL ||
587 SectionType == MachO::S_GB_ZEROFILL);
590 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
591 // FIXME: Unimplemented.
595 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
596 DataRefImpl Symb) const {
598 this->getSymbolType(Symb, ST);
599 if (ST == SymbolRef::ST_Unknown)
602 uint64_t SectBegin = getSectionAddress(Sec);
603 uint64_t SectEnd = getSectionSize(Sec);
604 SectEnd += SectBegin;
607 getSymbolAddress(Symb, SymAddr);
608 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
611 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
615 return relocation_iterator(RelocationRef(Ret, this));
619 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
622 MachO::section_64 Sect = getSection64(Sec);
625 MachO::section Sect = getSection(Sec);
632 return relocation_iterator(RelocationRef(Ret, this));
635 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
639 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
640 uint64_t &Res) const {
642 getRelocationOffset(Rel, Offset);
646 uint64_t SecAddress = getSectionAddress(Sec);
647 Res = SecAddress + Offset;
648 return object_error::success;
651 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
652 uint64_t &Res) const {
653 assert(getHeader().filetype == MachO::MH_OBJECT &&
654 "Only implemented for MH_OBJECT");
655 MachO::any_relocation_info RE = getRelocation(Rel);
656 Res = getAnyRelocationAddress(RE);
657 return object_error::success;
661 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
662 MachO::any_relocation_info RE = getRelocation(Rel);
663 if (isRelocationScattered(RE))
666 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
667 bool isExtern = getPlainRelocationExternal(RE);
671 MachO::symtab_command S = getSymtabLoadCommand();
672 unsigned SymbolTableEntrySize = is64Bit() ?
673 sizeof(MachO::nlist_64) :
674 sizeof(MachO::nlist);
675 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
677 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
678 return symbol_iterator(SymbolRef(Sym, this));
681 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
682 uint64_t &Res) const {
683 MachO::any_relocation_info RE = getRelocation(Rel);
684 Res = getAnyRelocationType(RE);
685 return object_error::success;
689 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
690 SmallVectorImpl<char> &Result) const {
693 getRelocationType(Rel, RType);
695 unsigned Arch = this->getArch();
699 static const char *const Table[] = {
700 "GENERIC_RELOC_VANILLA",
701 "GENERIC_RELOC_PAIR",
702 "GENERIC_RELOC_SECTDIFF",
703 "GENERIC_RELOC_PB_LA_PTR",
704 "GENERIC_RELOC_LOCAL_SECTDIFF",
705 "GENERIC_RELOC_TLV" };
713 case Triple::x86_64: {
714 static const char *const Table[] = {
715 "X86_64_RELOC_UNSIGNED",
716 "X86_64_RELOC_SIGNED",
717 "X86_64_RELOC_BRANCH",
718 "X86_64_RELOC_GOT_LOAD",
720 "X86_64_RELOC_SUBTRACTOR",
721 "X86_64_RELOC_SIGNED_1",
722 "X86_64_RELOC_SIGNED_2",
723 "X86_64_RELOC_SIGNED_4",
724 "X86_64_RELOC_TLV" };
733 static const char *const Table[] = {
736 "ARM_RELOC_SECTDIFF",
737 "ARM_RELOC_LOCAL_SECTDIFF",
738 "ARM_RELOC_PB_LA_PTR",
740 "ARM_THUMB_RELOC_BR22",
741 "ARM_THUMB_32BIT_BRANCH",
743 "ARM_RELOC_HALF_SECTDIFF" };
751 case Triple::aarch64: {
752 static const char *const Table[] = {
753 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
754 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
755 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
756 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
757 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
761 if (RType >= array_lengthof(Table))
768 static const char *const Table[] = {
777 "PPC_RELOC_SECTDIFF",
778 "PPC_RELOC_PB_LA_PTR",
779 "PPC_RELOC_HI16_SECTDIFF",
780 "PPC_RELOC_LO16_SECTDIFF",
781 "PPC_RELOC_HA16_SECTDIFF",
783 "PPC_RELOC_LO14_SECTDIFF",
784 "PPC_RELOC_LOCAL_SECTDIFF" };
792 case Triple::UnknownArch:
796 Result.append(res.begin(), res.end());
797 return object_error::success;
801 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
802 SmallVectorImpl<char> &Result) const {
803 MachO::any_relocation_info RE = getRelocation(Rel);
805 unsigned Arch = this->getArch();
808 raw_string_ostream fmt(fmtbuf);
809 unsigned Type = this->getAnyRelocationType(RE);
810 bool IsPCRel = this->getAnyRelocationPCRel(RE);
812 // Determine any addends that should be displayed with the relocation.
813 // These require decoding the relocation type, which is triple-specific.
815 // X86_64 has entirely custom relocation types.
816 if (Arch == Triple::x86_64) {
817 bool isPCRel = getAnyRelocationPCRel(RE);
820 case MachO::X86_64_RELOC_GOT_LOAD:
821 case MachO::X86_64_RELOC_GOT: {
822 printRelocationTargetName(this, RE, fmt);
824 if (isPCRel) fmt << "PCREL";
827 case MachO::X86_64_RELOC_SUBTRACTOR: {
828 DataRefImpl RelNext = Rel;
829 moveRelocationNext(RelNext);
830 MachO::any_relocation_info RENext = getRelocation(RelNext);
832 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
833 // X86_64_RELOC_UNSIGNED.
834 // NOTE: Scattered relocations don't exist on x86_64.
835 unsigned RType = getAnyRelocationType(RENext);
836 if (RType != MachO::X86_64_RELOC_UNSIGNED)
837 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
838 "X86_64_RELOC_SUBTRACTOR.");
840 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
841 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
842 printRelocationTargetName(this, RENext, fmt);
844 printRelocationTargetName(this, RE, fmt);
847 case MachO::X86_64_RELOC_TLV:
848 printRelocationTargetName(this, RE, fmt);
850 if (isPCRel) fmt << "P";
852 case MachO::X86_64_RELOC_SIGNED_1:
853 printRelocationTargetName(this, RE, fmt);
856 case MachO::X86_64_RELOC_SIGNED_2:
857 printRelocationTargetName(this, RE, fmt);
860 case MachO::X86_64_RELOC_SIGNED_4:
861 printRelocationTargetName(this, RE, fmt);
865 printRelocationTargetName(this, RE, fmt);
868 // X86 and ARM share some relocation types in common.
869 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
870 Arch == Triple::ppc) {
871 // Generic relocation types...
873 case MachO::GENERIC_RELOC_PAIR: // prints no info
874 return object_error::success;
875 case MachO::GENERIC_RELOC_SECTDIFF: {
876 DataRefImpl RelNext = Rel;
877 moveRelocationNext(RelNext);
878 MachO::any_relocation_info RENext = getRelocation(RelNext);
880 // X86 sect diff's must be followed by a relocation of type
881 // GENERIC_RELOC_PAIR.
882 unsigned RType = getAnyRelocationType(RENext);
884 if (RType != MachO::GENERIC_RELOC_PAIR)
885 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
886 "GENERIC_RELOC_SECTDIFF.");
888 printRelocationTargetName(this, RE, fmt);
890 printRelocationTargetName(this, RENext, fmt);
895 if (Arch == Triple::x86 || Arch == Triple::ppc) {
897 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
898 DataRefImpl RelNext = Rel;
899 moveRelocationNext(RelNext);
900 MachO::any_relocation_info RENext = getRelocation(RelNext);
902 // X86 sect diff's must be followed by a relocation of type
903 // GENERIC_RELOC_PAIR.
904 unsigned RType = getAnyRelocationType(RENext);
905 if (RType != MachO::GENERIC_RELOC_PAIR)
906 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
907 "GENERIC_RELOC_LOCAL_SECTDIFF.");
909 printRelocationTargetName(this, RE, fmt);
911 printRelocationTargetName(this, RENext, fmt);
914 case MachO::GENERIC_RELOC_TLV: {
915 printRelocationTargetName(this, RE, fmt);
917 if (IsPCRel) fmt << "P";
921 printRelocationTargetName(this, RE, fmt);
923 } else { // ARM-specific relocations
925 case MachO::ARM_RELOC_HALF:
926 case MachO::ARM_RELOC_HALF_SECTDIFF: {
927 // Half relocations steal a bit from the length field to encode
928 // whether this is an upper16 or a lower16 relocation.
929 bool isUpper = getAnyRelocationLength(RE) >> 1;
935 printRelocationTargetName(this, RE, fmt);
937 DataRefImpl RelNext = Rel;
938 moveRelocationNext(RelNext);
939 MachO::any_relocation_info RENext = getRelocation(RelNext);
941 // ARM half relocs must be followed by a relocation of type
943 unsigned RType = getAnyRelocationType(RENext);
944 if (RType != MachO::ARM_RELOC_PAIR)
945 report_fatal_error("Expected ARM_RELOC_PAIR after "
948 // NOTE: The half of the target virtual address is stashed in the
949 // address field of the secondary relocation, but we can't reverse
950 // engineer the constant offset from it without decoding the movw/movt
951 // instruction to find the other half in its immediate field.
953 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
954 // symbol/section pointer of the follow-on relocation.
955 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
957 printRelocationTargetName(this, RENext, fmt);
964 printRelocationTargetName(this, RE, fmt);
969 printRelocationTargetName(this, RE, fmt);
972 Result.append(fmtbuf.begin(), fmtbuf.end());
973 return object_error::success;
976 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
977 bool &Result) const {
978 unsigned Arch = getArch();
980 getRelocationType(Rel, Type);
984 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
986 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
987 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
988 } else if (Arch == Triple::x86_64) {
989 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
990 // an X86_64_RELOC_SUBTRACTOR.
991 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
992 DataRefImpl RelPrev = Rel;
995 getRelocationType(RelPrev, PrevType);
996 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1001 return object_error::success;
1005 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1006 // guess on what the short name is. Then name is returned as a substring of the
1007 // StringRef Name passed in. The name of the dynamic library is recognized as
1008 // a framework if it has one of the two following forms:
1009 // Foo.framework/Versions/A/Foo
1010 // Foo.framework/Foo
1011 // Where A and Foo can be any string. And may contain a trailing suffix
1012 // starting with an underbar. If the Name is recognized as a framework then
1013 // isFramework is set to true else it is set to false. If the Name has a
1014 // suffix then Suffix is set to the substring in Name that contains the suffix
1015 // else it is set to a NULL StringRef.
1017 // The Name of the dynamic library is recognized as a library name if it has
1018 // one of the two following forms:
1021 // The library may have a suffix trailing the name Foo of the form:
1022 // libFoo_profile.A.dylib
1023 // libFoo_profile.dylib
1025 // The Name of the dynamic library is also recognized as a library name if it
1026 // has the following form:
1029 // If the Name of the dynamic library is none of the forms above then a NULL
1030 // StringRef is returned.
1032 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1034 StringRef &Suffix) {
1035 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1036 size_t a, b, c, d, Idx;
1038 isFramework = false;
1039 Suffix = StringRef();
1041 // Pull off the last component and make Foo point to it
1042 a = Name.rfind('/');
1043 if (a == Name.npos || a == 0)
1045 Foo = Name.slice(a+1, Name.npos);
1047 // Look for a suffix starting with a '_'
1048 Idx = Foo.rfind('_');
1049 if (Idx != Foo.npos && Foo.size() >= 2) {
1050 Suffix = Foo.slice(Idx, Foo.npos);
1051 Foo = Foo.slice(0, Idx);
1054 // First look for the form Foo.framework/Foo
1055 b = Name.rfind('/', a);
1060 F = Name.slice(Idx, Idx + Foo.size());
1061 DotFramework = Name.slice(Idx + Foo.size(),
1062 Idx + Foo.size() + sizeof(".framework/")-1);
1063 if (F == Foo && DotFramework == ".framework/") {
1068 // Next look for the form Foo.framework/Versions/A/Foo
1071 c = Name.rfind('/', b);
1072 if (c == Name.npos || c == 0)
1074 V = Name.slice(c+1, Name.npos);
1075 if (!V.startswith("Versions/"))
1077 d = Name.rfind('/', c);
1082 F = Name.slice(Idx, Idx + Foo.size());
1083 DotFramework = Name.slice(Idx + Foo.size(),
1084 Idx + Foo.size() + sizeof(".framework/")-1);
1085 if (F == Foo && DotFramework == ".framework/") {
1091 // pull off the suffix after the "." and make a point to it
1092 a = Name.rfind('.');
1093 if (a == Name.npos || a == 0)
1095 Dylib = Name.slice(a, Name.npos);
1096 if (Dylib != ".dylib")
1099 // First pull off the version letter for the form Foo.A.dylib if any.
1101 Dot = Name.slice(a-2, a-1);
1106 b = Name.rfind('/', a);
1111 // ignore any suffix after an underbar like Foo_profile.A.dylib
1112 Idx = Name.find('_', b);
1113 if (Idx != Name.npos && Idx != b) {
1114 Lib = Name.slice(b, Idx);
1115 Suffix = Name.slice(Idx, a);
1118 Lib = Name.slice(b, a);
1119 // There are incorrect library names of the form:
1120 // libATS.A_profile.dylib so check for these.
1121 if (Lib.size() >= 3) {
1122 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1124 Lib = Lib.slice(0, Lib.size()-2);
1129 Qtx = Name.slice(a, Name.npos);
1132 b = Name.rfind('/', a);
1134 Lib = Name.slice(0, a);
1136 Lib = Name.slice(b+1, a);
1137 // There are library names of the form: QT.A.qtx so check for these.
1138 if (Lib.size() >= 3) {
1139 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1141 Lib = Lib.slice(0, Lib.size()-2);
1146 // getLibraryShortNameByIndex() is used to get the short name of the library
1147 // for an undefined symbol in a linked Mach-O binary that was linked with the
1148 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1149 // It is passed the index (0 - based) of the library as translated from
1150 // GET_LIBRARY_ORDINAL (1 - based).
1151 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1152 StringRef &Res) const {
1153 if (Index >= Libraries.size())
1154 return object_error::parse_failed;
1156 // If the cache of LibrariesShortNames is not built up do that first for
1157 // all the Libraries.
1158 if (LibrariesShortNames.size() == 0) {
1159 for (unsigned i = 0; i < Libraries.size(); i++) {
1160 MachO::dylib_command D =
1161 getStruct<MachO::dylib_command>(this, Libraries[i]);
1162 if (D.dylib.name >= D.cmdsize)
1163 return object_error::parse_failed;
1164 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1165 StringRef Name = StringRef(P);
1166 if (D.dylib.name+Name.size() >= D.cmdsize)
1167 return object_error::parse_failed;
1170 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1171 if (shortName.empty())
1172 LibrariesShortNames.push_back(Name);
1174 LibrariesShortNames.push_back(shortName);
1178 Res = LibrariesShortNames[Index];
1179 return object_error::success;
1182 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1183 return getSymbolByIndex(0);
1186 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1189 return basic_symbol_iterator(SymbolRef(DRI, this));
1191 MachO::symtab_command Symtab = getSymtabLoadCommand();
1192 unsigned SymbolTableEntrySize = is64Bit() ?
1193 sizeof(MachO::nlist_64) :
1194 sizeof(MachO::nlist);
1195 unsigned Offset = Symtab.symoff +
1196 Symtab.nsyms * SymbolTableEntrySize;
1197 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1201 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1204 return basic_symbol_iterator(SymbolRef(DRI, this));
1206 MachO::symtab_command Symtab = getSymtabLoadCommand();
1207 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1208 unsigned SymbolTableEntrySize =
1209 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1210 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1211 DRI.p += Index * SymbolTableEntrySize;
1212 return basic_symbol_iterator(SymbolRef(DRI, this));
1215 section_iterator MachOObjectFile::section_begin() const {
1217 return section_iterator(SectionRef(DRI, this));
1220 section_iterator MachOObjectFile::section_end() const {
1222 DRI.d.a = Sections.size();
1223 return section_iterator(SectionRef(DRI, this));
1226 uint8_t MachOObjectFile::getBytesInAddress() const {
1227 return is64Bit() ? 8 : 4;
1230 StringRef MachOObjectFile::getFileFormatName() const {
1231 unsigned CPUType = getCPUType(this);
1234 case llvm::MachO::CPU_TYPE_I386:
1235 return "Mach-O 32-bit i386";
1236 case llvm::MachO::CPU_TYPE_ARM:
1237 return "Mach-O arm";
1238 case llvm::MachO::CPU_TYPE_POWERPC:
1239 return "Mach-O 32-bit ppc";
1241 return "Mach-O 32-bit unknown";
1246 case llvm::MachO::CPU_TYPE_X86_64:
1247 return "Mach-O 64-bit x86-64";
1248 case llvm::MachO::CPU_TYPE_ARM64:
1249 return "Mach-O arm64";
1250 case llvm::MachO::CPU_TYPE_POWERPC64:
1251 return "Mach-O 64-bit ppc64";
1253 return "Mach-O 64-bit unknown";
1257 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1259 case llvm::MachO::CPU_TYPE_I386:
1261 case llvm::MachO::CPU_TYPE_X86_64:
1262 return Triple::x86_64;
1263 case llvm::MachO::CPU_TYPE_ARM:
1265 case llvm::MachO::CPU_TYPE_ARM64:
1266 return Triple::aarch64;
1267 case llvm::MachO::CPU_TYPE_POWERPC:
1269 case llvm::MachO::CPU_TYPE_POWERPC64:
1270 return Triple::ppc64;
1272 return Triple::UnknownArch;
1276 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1277 const char **McpuDefault) {
1279 *McpuDefault = nullptr;
1282 case MachO::CPU_TYPE_I386:
1283 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1284 case MachO::CPU_SUBTYPE_I386_ALL:
1285 return Triple("i386-apple-darwin");
1289 case MachO::CPU_TYPE_X86_64:
1290 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1291 case MachO::CPU_SUBTYPE_X86_64_ALL:
1292 return Triple("x86_64-apple-darwin");
1293 case MachO::CPU_SUBTYPE_X86_64_H:
1294 return Triple("x86_64h-apple-darwin");
1298 case MachO::CPU_TYPE_ARM:
1299 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1300 case MachO::CPU_SUBTYPE_ARM_V4T:
1301 return Triple("armv4t-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1303 return Triple("armv5e-apple-darwin");
1304 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1305 return Triple("xscale-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V6:
1307 return Triple("armv6-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_V6M:
1310 *McpuDefault = "cortex-m0";
1311 return Triple("armv6m-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V7:
1313 return Triple("armv7-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V7EM:
1316 *McpuDefault = "cortex-m4";
1317 return Triple("armv7em-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7K:
1319 return Triple("armv7k-apple-darwin");
1320 case MachO::CPU_SUBTYPE_ARM_V7M:
1322 *McpuDefault = "cortex-m3";
1323 return Triple("armv7m-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V7S:
1325 return Triple("armv7s-apple-darwin");
1329 case MachO::CPU_TYPE_ARM64:
1330 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1331 case MachO::CPU_SUBTYPE_ARM64_ALL:
1332 return Triple("arm64-apple-darwin");
1336 case MachO::CPU_TYPE_POWERPC:
1337 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1338 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1339 return Triple("ppc-apple-darwin");
1343 case MachO::CPU_TYPE_POWERPC64:
1344 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1345 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1346 return Triple("ppc64-apple-darwin");
1355 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1356 const char **McpuDefault) {
1358 *McpuDefault = nullptr;
1361 case MachO::CPU_TYPE_ARM:
1362 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1363 case MachO::CPU_SUBTYPE_ARM_V4T:
1364 return Triple("thumbv4t-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1366 return Triple("thumbv5e-apple-darwin");
1367 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1368 return Triple("xscale-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V6:
1370 return Triple("thumbv6-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V6M:
1373 *McpuDefault = "cortex-m0";
1374 return Triple("thumbv6m-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V7:
1376 return Triple("thumbv7-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V7EM:
1379 *McpuDefault = "cortex-m4";
1380 return Triple("thumbv7em-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7K:
1382 return Triple("thumbv7k-apple-darwin");
1383 case MachO::CPU_SUBTYPE_ARM_V7M:
1385 *McpuDefault = "cortex-m3";
1386 return Triple("thumbv7m-apple-darwin");
1387 case MachO::CPU_SUBTYPE_ARM_V7S:
1388 return Triple("thumbv7s-apple-darwin");
1397 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1398 const char **McpuDefault,
1399 Triple *ThumbTriple) {
1400 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1401 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1406 Triple MachOObjectFile::getHostArch() {
1407 return Triple(sys::getDefaultTargetTriple());
1410 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1411 return StringSwitch<bool>(ArchFlag)
1413 .Case("x86_64", true)
1414 .Case("x86_64h", true)
1415 .Case("armv4t", true)
1417 .Case("armv5e", true)
1418 .Case("armv6", true)
1419 .Case("armv6m", true)
1420 .Case("armv7em", true)
1421 .Case("armv7k", true)
1422 .Case("armv7m", true)
1423 .Case("armv7s", true)
1424 .Case("arm64", true)
1426 .Case("ppc64", true)
1430 unsigned MachOObjectFile::getArch() const {
1431 return getArch(getCPUType(this));
1434 Triple MachOObjectFile::getArch(const char **McpuDefault,
1435 Triple *ThumbTriple) const {
1438 MachO::mach_header_64 H_64;
1439 H_64 = getHeader64();
1440 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1441 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1444 MachO::mach_header H;
1446 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1447 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1453 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1456 return section_rel_begin(DRI);
1459 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1462 return section_rel_end(DRI);
1465 dice_iterator MachOObjectFile::begin_dices() const {
1467 if (!DataInCodeLoadCmd)
1468 return dice_iterator(DiceRef(DRI, this));
1470 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1471 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1472 return dice_iterator(DiceRef(DRI, this));
1475 dice_iterator MachOObjectFile::end_dices() const {
1477 if (!DataInCodeLoadCmd)
1478 return dice_iterator(DiceRef(DRI, this));
1480 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1481 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1482 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1483 return dice_iterator(DiceRef(DRI, this));
1486 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1487 : Trie(T), Malformed(false), Done(false) { }
1489 void ExportEntry::moveToFirst() {
1491 pushDownUntilBottom();
1494 void ExportEntry::moveToEnd() {
1499 bool ExportEntry::operator==(const ExportEntry &Other) const {
1500 // Common case, one at end, other iterating from begin.
1501 if (Done || Other.Done)
1502 return (Done == Other.Done);
1503 // Not equal if different stack sizes.
1504 if (Stack.size() != Other.Stack.size())
1506 // Not equal if different cumulative strings.
1507 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1509 // Equal if all nodes in both stacks match.
1510 for (unsigned i=0; i < Stack.size(); ++i) {
1511 if (Stack[i].Start != Other.Stack[i].Start)
1517 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1519 uint64_t Result = decodeULEB128(Ptr, &Count);
1521 if (Ptr > Trie.end()) {
1528 StringRef ExportEntry::name() const {
1529 return CumulativeString.str();
1532 uint64_t ExportEntry::flags() const {
1533 return Stack.back().Flags;
1536 uint64_t ExportEntry::address() const {
1537 return Stack.back().Address;
1540 uint64_t ExportEntry::other() const {
1541 return Stack.back().Other;
1544 StringRef ExportEntry::otherName() const {
1545 const char* ImportName = Stack.back().ImportName;
1547 return StringRef(ImportName);
1551 uint32_t ExportEntry::nodeOffset() const {
1552 return Stack.back().Start - Trie.begin();
1555 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1556 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1557 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1558 ParentStringLength(0), IsExportNode(false) {
1561 void ExportEntry::pushNode(uint64_t offset) {
1562 const uint8_t *Ptr = Trie.begin() + offset;
1563 NodeState State(Ptr);
1564 uint64_t ExportInfoSize = readULEB128(State.Current);
1565 State.IsExportNode = (ExportInfoSize != 0);
1566 const uint8_t* Children = State.Current + ExportInfoSize;
1567 if (State.IsExportNode) {
1568 State.Flags = readULEB128(State.Current);
1569 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1571 State.Other = readULEB128(State.Current); // dylib ordinal
1572 State.ImportName = reinterpret_cast<const char*>(State.Current);
1574 State.Address = readULEB128(State.Current);
1575 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1576 State.Other = readULEB128(State.Current);
1579 State.ChildCount = *Children;
1580 State.Current = Children + 1;
1581 State.NextChildIndex = 0;
1582 State.ParentStringLength = CumulativeString.size();
1583 Stack.push_back(State);
1586 void ExportEntry::pushDownUntilBottom() {
1587 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1588 NodeState &Top = Stack.back();
1589 CumulativeString.resize(Top.ParentStringLength);
1590 for (;*Top.Current != 0; Top.Current++) {
1591 char C = *Top.Current;
1592 CumulativeString.push_back(C);
1595 uint64_t childNodeIndex = readULEB128(Top.Current);
1596 Top.NextChildIndex += 1;
1597 pushNode(childNodeIndex);
1599 if (!Stack.back().IsExportNode) {
1605 // We have a trie data structure and need a way to walk it that is compatible
1606 // with the C++ iterator model. The solution is a non-recursive depth first
1607 // traversal where the iterator contains a stack of parent nodes along with a
1608 // string that is the accumulation of all edge strings along the parent chain
1611 // There is one "export" node for each exported symbol. But because some
1612 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1613 // node may have child nodes too.
1615 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1616 // child until hitting a node with no children (which is an export node or
1617 // else the trie is malformed). On the way down, each node is pushed on the
1618 // stack ivar. If there is no more ways down, it pops up one and tries to go
1619 // down a sibling path until a childless node is reached.
1620 void ExportEntry::moveNext() {
1621 if (Stack.empty() || !Stack.back().IsExportNode) {
1628 while (!Stack.empty()) {
1629 NodeState &Top = Stack.back();
1630 if (Top.NextChildIndex < Top.ChildCount) {
1631 pushDownUntilBottom();
1632 // Now at the next export node.
1635 if (Top.IsExportNode) {
1636 // This node has no children but is itself an export node.
1637 CumulativeString.resize(Top.ParentStringLength);
1646 iterator_range<export_iterator>
1647 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1648 ExportEntry Start(Trie);
1649 if (Trie.size() == 0)
1652 Start.moveToFirst();
1654 ExportEntry Finish(Trie);
1657 return iterator_range<export_iterator>(export_iterator(Start),
1658 export_iterator(Finish));
1661 iterator_range<export_iterator> MachOObjectFile::exports() const {
1662 return exports(getDyldInfoExportsTrie());
1666 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1667 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1668 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1669 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1671 void MachORebaseEntry::moveToFirst() {
1672 Ptr = Opcodes.begin();
1676 void MachORebaseEntry::moveToEnd() {
1677 Ptr = Opcodes.end();
1678 RemainingLoopCount = 0;
1682 void MachORebaseEntry::moveNext() {
1683 // If in the middle of some loop, move to next rebasing in loop.
1684 SegmentOffset += AdvanceAmount;
1685 if (RemainingLoopCount) {
1686 --RemainingLoopCount;
1689 if (Ptr == Opcodes.end()) {
1694 while (More && !Malformed) {
1695 // Parse next opcode and set up next loop.
1696 uint8_t Byte = *Ptr++;
1697 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1698 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1700 case MachO::REBASE_OPCODE_DONE:
1704 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1706 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1707 RebaseType = ImmValue;
1710 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1711 << "RebaseType=" << (int) RebaseType << "\n");
1713 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1714 SegmentIndex = ImmValue;
1715 SegmentOffset = readULEB128();
1718 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1719 << "SegmentIndex=" << SegmentIndex << ", "
1720 << format("SegmentOffset=0x%06X", SegmentOffset)
1723 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1724 SegmentOffset += readULEB128();
1725 DEBUG_WITH_TYPE("mach-o-rebase",
1726 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1727 << format("SegmentOffset=0x%06X",
1728 SegmentOffset) << "\n");
1730 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1731 SegmentOffset += ImmValue * PointerSize;
1732 DEBUG_WITH_TYPE("mach-o-rebase",
1733 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1734 << format("SegmentOffset=0x%06X",
1735 SegmentOffset) << "\n");
1737 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1738 AdvanceAmount = PointerSize;
1739 RemainingLoopCount = ImmValue - 1;
1742 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1743 << format("SegmentOffset=0x%06X", SegmentOffset)
1744 << ", AdvanceAmount=" << AdvanceAmount
1745 << ", RemainingLoopCount=" << RemainingLoopCount
1748 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1749 AdvanceAmount = PointerSize;
1750 RemainingLoopCount = readULEB128() - 1;
1753 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1754 << format("SegmentOffset=0x%06X", SegmentOffset)
1755 << ", AdvanceAmount=" << AdvanceAmount
1756 << ", RemainingLoopCount=" << RemainingLoopCount
1759 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1760 AdvanceAmount = readULEB128() + PointerSize;
1761 RemainingLoopCount = 0;
1764 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1765 << format("SegmentOffset=0x%06X", SegmentOffset)
1766 << ", AdvanceAmount=" << AdvanceAmount
1767 << ", RemainingLoopCount=" << RemainingLoopCount
1770 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1771 RemainingLoopCount = readULEB128() - 1;
1772 AdvanceAmount = readULEB128() + PointerSize;
1775 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1776 << format("SegmentOffset=0x%06X", SegmentOffset)
1777 << ", AdvanceAmount=" << AdvanceAmount
1778 << ", RemainingLoopCount=" << RemainingLoopCount
1787 uint64_t MachORebaseEntry::readULEB128() {
1789 uint64_t Result = decodeULEB128(Ptr, &Count);
1791 if (Ptr > Opcodes.end()) {
1792 Ptr = Opcodes.end();
1798 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1800 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1802 StringRef MachORebaseEntry::typeName() const {
1803 switch (RebaseType) {
1804 case MachO::REBASE_TYPE_POINTER:
1806 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1807 return "text abs32";
1808 case MachO::REBASE_TYPE_TEXT_PCREL32:
1809 return "text rel32";
1814 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1815 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1816 return (Ptr == Other.Ptr) &&
1817 (RemainingLoopCount == Other.RemainingLoopCount) &&
1818 (Done == Other.Done);
1821 iterator_range<rebase_iterator>
1822 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1823 MachORebaseEntry Start(Opcodes, is64);
1824 Start.moveToFirst();
1826 MachORebaseEntry Finish(Opcodes, is64);
1829 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1830 rebase_iterator(Finish));
1833 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1834 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1838 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1840 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1841 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1842 BindType(0), PointerSize(is64Bit ? 8 : 4),
1843 TableKind(BK), Malformed(false), Done(false) {}
1845 void MachOBindEntry::moveToFirst() {
1846 Ptr = Opcodes.begin();
1850 void MachOBindEntry::moveToEnd() {
1851 Ptr = Opcodes.end();
1852 RemainingLoopCount = 0;
1856 void MachOBindEntry::moveNext() {
1857 // If in the middle of some loop, move to next binding in loop.
1858 SegmentOffset += AdvanceAmount;
1859 if (RemainingLoopCount) {
1860 --RemainingLoopCount;
1863 if (Ptr == Opcodes.end()) {
1868 while (More && !Malformed) {
1869 // Parse next opcode and set up next loop.
1870 uint8_t Byte = *Ptr++;
1871 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1872 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1873 int8_t SignExtended;
1874 const uint8_t *SymStart;
1876 case MachO::BIND_OPCODE_DONE:
1877 if (TableKind == Kind::Lazy) {
1878 // Lazying bindings have a DONE opcode between entries. Need to ignore
1879 // it to advance to next entry. But need not if this is last entry.
1880 bool NotLastEntry = false;
1881 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1883 NotLastEntry = true;
1892 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1894 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1898 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1899 << "Ordinal=" << Ordinal << "\n");
1901 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1902 Ordinal = readULEB128();
1905 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1906 << "Ordinal=" << Ordinal << "\n");
1908 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1910 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1911 Ordinal = SignExtended;
1916 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1917 << "Ordinal=" << Ordinal << "\n");
1919 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1925 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1930 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1931 << "SymbolName=" << SymbolName << "\n");
1932 if (TableKind == Kind::Weak) {
1933 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1937 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1938 BindType = ImmValue;
1941 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1942 << "BindType=" << (int)BindType << "\n");
1944 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1945 Addend = readSLEB128();
1946 if (TableKind == Kind::Lazy)
1950 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1951 << "Addend=" << Addend << "\n");
1953 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1954 SegmentIndex = ImmValue;
1955 SegmentOffset = readULEB128();
1958 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1959 << "SegmentIndex=" << SegmentIndex << ", "
1960 << format("SegmentOffset=0x%06X", SegmentOffset)
1963 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1964 SegmentOffset += readULEB128();
1965 DEBUG_WITH_TYPE("mach-o-bind",
1966 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1967 << format("SegmentOffset=0x%06X",
1968 SegmentOffset) << "\n");
1970 case MachO::BIND_OPCODE_DO_BIND:
1971 AdvanceAmount = PointerSize;
1972 RemainingLoopCount = 0;
1973 DEBUG_WITH_TYPE("mach-o-bind",
1974 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1975 << format("SegmentOffset=0x%06X",
1976 SegmentOffset) << "\n");
1978 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1979 AdvanceAmount = readULEB128() + PointerSize;
1980 RemainingLoopCount = 0;
1981 if (TableKind == Kind::Lazy)
1985 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1986 << format("SegmentOffset=0x%06X", SegmentOffset)
1987 << ", AdvanceAmount=" << AdvanceAmount
1988 << ", RemainingLoopCount=" << RemainingLoopCount
1991 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1992 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1993 RemainingLoopCount = 0;
1994 if (TableKind == Kind::Lazy)
1996 DEBUG_WITH_TYPE("mach-o-bind",
1998 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1999 << format("SegmentOffset=0x%06X",
2000 SegmentOffset) << "\n");
2002 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2003 RemainingLoopCount = readULEB128() - 1;
2004 AdvanceAmount = readULEB128() + PointerSize;
2005 if (TableKind == Kind::Lazy)
2009 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2010 << format("SegmentOffset=0x%06X", SegmentOffset)
2011 << ", AdvanceAmount=" << AdvanceAmount
2012 << ", RemainingLoopCount=" << RemainingLoopCount
2021 uint64_t MachOBindEntry::readULEB128() {
2023 uint64_t Result = decodeULEB128(Ptr, &Count);
2025 if (Ptr > Opcodes.end()) {
2026 Ptr = Opcodes.end();
2032 int64_t MachOBindEntry::readSLEB128() {
2034 int64_t Result = decodeSLEB128(Ptr, &Count);
2036 if (Ptr > Opcodes.end()) {
2037 Ptr = Opcodes.end();
2044 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2046 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2048 StringRef MachOBindEntry::typeName() const {
2050 case MachO::BIND_TYPE_POINTER:
2052 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2053 return "text abs32";
2054 case MachO::BIND_TYPE_TEXT_PCREL32:
2055 return "text rel32";
2060 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2062 int64_t MachOBindEntry::addend() const { return Addend; }
2064 uint32_t MachOBindEntry::flags() const { return Flags; }
2066 int MachOBindEntry::ordinal() const { return Ordinal; }
2068 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2069 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2070 return (Ptr == Other.Ptr) &&
2071 (RemainingLoopCount == Other.RemainingLoopCount) &&
2072 (Done == Other.Done);
2075 iterator_range<bind_iterator>
2076 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2077 MachOBindEntry::Kind BKind) {
2078 MachOBindEntry Start(Opcodes, is64, BKind);
2079 Start.moveToFirst();
2081 MachOBindEntry Finish(Opcodes, is64, BKind);
2084 return iterator_range<bind_iterator>(bind_iterator(Start),
2085 bind_iterator(Finish));
2088 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2089 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2090 MachOBindEntry::Kind::Regular);
2093 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2094 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2095 MachOBindEntry::Kind::Lazy);
2098 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2099 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2100 MachOBindEntry::Kind::Weak);
2104 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2105 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2106 return parseSegmentOrSectionName(Raw.data());
2110 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2111 const section_base *Base =
2112 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2113 return makeArrayRef(Base->sectname);
2117 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2118 const section_base *Base =
2119 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2120 return makeArrayRef(Base->segname);
2124 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2126 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2128 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2131 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2132 const MachO::any_relocation_info &RE) const {
2133 if (isLittleEndian())
2134 return RE.r_word1 & 0xffffff;
2135 return RE.r_word1 >> 8;
2138 bool MachOObjectFile::getPlainRelocationExternal(
2139 const MachO::any_relocation_info &RE) const {
2140 if (isLittleEndian())
2141 return (RE.r_word1 >> 27) & 1;
2142 return (RE.r_word1 >> 4) & 1;
2145 bool MachOObjectFile::getScatteredRelocationScattered(
2146 const MachO::any_relocation_info &RE) const {
2147 return RE.r_word0 >> 31;
2150 uint32_t MachOObjectFile::getScatteredRelocationValue(
2151 const MachO::any_relocation_info &RE) const {
2155 uint32_t MachOObjectFile::getScatteredRelocationType(
2156 const MachO::any_relocation_info &RE) const {
2157 return (RE.r_word0 >> 24) & 0xf;
2160 unsigned MachOObjectFile::getAnyRelocationAddress(
2161 const MachO::any_relocation_info &RE) const {
2162 if (isRelocationScattered(RE))
2163 return getScatteredRelocationAddress(RE);
2164 return getPlainRelocationAddress(RE);
2167 unsigned MachOObjectFile::getAnyRelocationPCRel(
2168 const MachO::any_relocation_info &RE) const {
2169 if (isRelocationScattered(RE))
2170 return getScatteredRelocationPCRel(this, RE);
2171 return getPlainRelocationPCRel(this, RE);
2174 unsigned MachOObjectFile::getAnyRelocationLength(
2175 const MachO::any_relocation_info &RE) const {
2176 if (isRelocationScattered(RE))
2177 return getScatteredRelocationLength(RE);
2178 return getPlainRelocationLength(this, RE);
2182 MachOObjectFile::getAnyRelocationType(
2183 const MachO::any_relocation_info &RE) const {
2184 if (isRelocationScattered(RE))
2185 return getScatteredRelocationType(RE);
2186 return getPlainRelocationType(this, RE);
2190 MachOObjectFile::getRelocationSection(
2191 const MachO::any_relocation_info &RE) const {
2192 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2193 return *section_end();
2194 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2197 return SectionRef(DRI, this);
2200 MachOObjectFile::LoadCommandInfo
2201 MachOObjectFile::getFirstLoadCommandInfo() const {
2202 MachOObjectFile::LoadCommandInfo Load;
2204 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2205 sizeof(MachO::mach_header);
2206 Load.Ptr = getPtr(this, HeaderSize);
2207 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2211 MachOObjectFile::LoadCommandInfo
2212 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2213 MachOObjectFile::LoadCommandInfo Next;
2214 Next.Ptr = L.Ptr + L.C.cmdsize;
2215 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2219 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2220 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2223 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2224 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2227 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2228 unsigned Index) const {
2229 const char *Sec = getSectionPtr(this, L, Index);
2230 return getStruct<MachO::section>(this, Sec);
2233 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2234 unsigned Index) const {
2235 const char *Sec = getSectionPtr(this, L, Index);
2236 return getStruct<MachO::section_64>(this, Sec);
2240 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2241 const char *P = reinterpret_cast<const char *>(DRI.p);
2242 return getStruct<MachO::nlist>(this, P);
2246 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2247 const char *P = reinterpret_cast<const char *>(DRI.p);
2248 return getStruct<MachO::nlist_64>(this, P);
2251 MachO::linkedit_data_command
2252 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2253 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2256 MachO::segment_command
2257 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2258 return getStruct<MachO::segment_command>(this, L.Ptr);
2261 MachO::segment_command_64
2262 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2263 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2266 MachO::linker_option_command
2267 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2268 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2271 MachO::version_min_command
2272 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2273 return getStruct<MachO::version_min_command>(this, L.Ptr);
2276 MachO::dylib_command
2277 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2278 return getStruct<MachO::dylib_command>(this, L.Ptr);
2281 MachO::dyld_info_command
2282 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2283 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2286 MachO::dylinker_command
2287 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2288 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2292 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2293 return getStruct<MachO::uuid_command>(this, L.Ptr);
2296 MachO::rpath_command
2297 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2298 return getStruct<MachO::rpath_command>(this, L.Ptr);
2301 MachO::source_version_command
2302 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2303 return getStruct<MachO::source_version_command>(this, L.Ptr);
2306 MachO::entry_point_command
2307 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2308 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2311 MachO::encryption_info_command
2312 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2313 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2316 MachO::encryption_info_command_64
2317 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2318 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2321 MachO::sub_framework_command
2322 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2323 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2326 MachO::sub_umbrella_command
2327 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2328 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2331 MachO::sub_library_command
2332 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2333 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2336 MachO::sub_client_command
2337 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2338 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2341 MachO::routines_command
2342 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2343 return getStruct<MachO::routines_command>(this, L.Ptr);
2346 MachO::routines_command_64
2347 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2348 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2351 MachO::thread_command
2352 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2353 return getStruct<MachO::thread_command>(this, L.Ptr);
2356 MachO::any_relocation_info
2357 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2362 MachO::section_64 Sect = getSection64(Sec);
2363 Offset = Sect.reloff;
2365 MachO::section Sect = getSection(Sec);
2366 Offset = Sect.reloff;
2369 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2370 getPtr(this, Offset)) + Rel.d.b;
2371 return getStruct<MachO::any_relocation_info>(
2372 this, reinterpret_cast<const char *>(P));
2375 MachO::data_in_code_entry
2376 MachOObjectFile::getDice(DataRefImpl Rel) const {
2377 const char *P = reinterpret_cast<const char *>(Rel.p);
2378 return getStruct<MachO::data_in_code_entry>(this, P);
2381 MachO::mach_header MachOObjectFile::getHeader() const {
2382 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2385 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2386 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2389 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2390 const MachO::dysymtab_command &DLC,
2391 unsigned Index) const {
2392 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2393 return getStruct<uint32_t>(this, getPtr(this, Offset));
2396 MachO::data_in_code_entry
2397 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2398 unsigned Index) const {
2399 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2400 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2403 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2405 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2407 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2408 MachO::symtab_command Cmd;
2409 Cmd.cmd = MachO::LC_SYMTAB;
2410 Cmd.cmdsize = sizeof(MachO::symtab_command);
2418 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2419 if (DysymtabLoadCmd)
2420 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2422 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2423 MachO::dysymtab_command Cmd;
2424 Cmd.cmd = MachO::LC_DYSYMTAB;
2425 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2436 Cmd.extrefsymoff = 0;
2437 Cmd.nextrefsyms = 0;
2438 Cmd.indirectsymoff = 0;
2439 Cmd.nindirectsyms = 0;
2447 MachO::linkedit_data_command
2448 MachOObjectFile::getDataInCodeLoadCommand() const {
2449 if (DataInCodeLoadCmd)
2450 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2452 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2453 MachO::linkedit_data_command Cmd;
2454 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2455 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2461 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2462 if (!DyldInfoLoadCmd)
2463 return ArrayRef<uint8_t>();
2465 MachO::dyld_info_command DyldInfo
2466 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2467 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2468 getPtr(this, DyldInfo.rebase_off));
2469 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2472 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2473 if (!DyldInfoLoadCmd)
2474 return ArrayRef<uint8_t>();
2476 MachO::dyld_info_command DyldInfo
2477 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2478 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2479 getPtr(this, DyldInfo.bind_off));
2480 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2483 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2484 if (!DyldInfoLoadCmd)
2485 return ArrayRef<uint8_t>();
2487 MachO::dyld_info_command DyldInfo
2488 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2489 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2490 getPtr(this, DyldInfo.weak_bind_off));
2491 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2494 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2495 if (!DyldInfoLoadCmd)
2496 return ArrayRef<uint8_t>();
2498 MachO::dyld_info_command DyldInfo
2499 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2500 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2501 getPtr(this, DyldInfo.lazy_bind_off));
2502 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2505 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2506 if (!DyldInfoLoadCmd)
2507 return ArrayRef<uint8_t>();
2509 MachO::dyld_info_command DyldInfo
2510 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2511 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2512 getPtr(this, DyldInfo.export_off));
2513 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2516 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2518 return ArrayRef<uint8_t>();
2519 // Returning a pointer is fine as uuid doesn't need endian swapping.
2520 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2521 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2524 StringRef MachOObjectFile::getStringTableData() const {
2525 MachO::symtab_command S = getSymtabLoadCommand();
2526 return getData().substr(S.stroff, S.strsize);
2529 bool MachOObjectFile::is64Bit() const {
2530 return getType() == getMachOType(false, true) ||
2531 getType() == getMachOType(true, true);
2534 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2535 SmallVectorImpl<uint64_t> &Out) const {
2536 DataExtractor extractor(ObjectFile::getData(), true, 0);
2538 uint32_t offset = Index;
2540 while (uint64_t delta = extractor.getULEB128(&offset)) {
2542 Out.push_back(data);
2546 bool MachOObjectFile::isRelocatableObject() const {
2547 return getHeader().filetype == MachO::MH_OBJECT;
2550 ErrorOr<std::unique_ptr<MachOObjectFile>>
2551 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2552 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2554 std::unique_ptr<MachOObjectFile> Ret;
2555 if (Magic == "\xFE\xED\xFA\xCE")
2556 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2557 else if (Magic == "\xCE\xFA\xED\xFE")
2558 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2559 else if (Magic == "\xFE\xED\xFA\xCF")
2560 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2561 else if (Magic == "\xCF\xFA\xED\xFE")
2562 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2564 return object_error::parse_failed;
2568 return std::move(Ret);