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) {
43 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
50 MachO::swapStruct(Cmd);
54 template <typename SegmentCmd>
55 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
61 "Number of sections too large for size of load command.");
66 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
76 static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
88 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
90 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
92 bool Is64 = O->is64Bit();
93 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
99 return reinterpret_cast<const char*>(SectionAddr);
102 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
106 static MachO::nlist_base
107 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
108 const char *P = reinterpret_cast<const char *>(DRI.p);
109 return getStruct<MachO::nlist_base>(O, P);
112 static StringRef parseSegmentOrSectionName(const char *P) {
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
120 // Helper to advance a section or symbol iterator multiple increments at a time.
122 static void advance(T &it, size_t Val) {
127 static unsigned getCPUType(const MachOObjectFile *O) {
128 return O->getHeader().cputype;
131 static void printRelocationTargetName(const MachOObjectFile *O,
132 const MachO::any_relocation_info &RE,
133 raw_string_ostream &fmt) {
134 bool IsScattered = O->isRelocationScattered(RE);
136 // Target of a scattered relocation is an address. In the interest of
137 // generating pretty output, scan through the symbol table looking for a
138 // symbol that aligns with that address. If we find one, print it.
139 // Otherwise, we just print the hex address of the target.
141 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
143 for (const SymbolRef &Symbol : O->symbols()) {
148 if ((ec = Symbol.getAddress(Addr)))
149 report_fatal_error(ec.message());
152 if ((ec = Symbol.getName(Name)))
153 report_fatal_error(ec.message());
158 // If we couldn't find a symbol that this relocation refers to, try
159 // to find a section beginning instead.
160 for (const SectionRef &Section : O->sections()) {
164 uint64_t Addr = Section.getAddress();
167 if ((ec = Section.getName(Name)))
168 report_fatal_error(ec.message());
173 fmt << format("0x%x", Val);
178 bool isExtern = O->getPlainRelocationExternal(RE);
179 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
182 symbol_iterator SI = O->symbol_begin();
186 section_iterator SI = O->section_begin();
187 // Adjust for the fact that sections are 1-indexed.
188 advance(SI, Val - 1);
196 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
201 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
202 return RE.r_word0 & 0xffffff;
205 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
206 const MachO::any_relocation_info &RE) {
207 if (O->isLittleEndian())
208 return (RE.r_word1 >> 24) & 1;
209 return (RE.r_word1 >> 7) & 1;
213 getScatteredRelocationPCRel(const MachOObjectFile *O,
214 const MachO::any_relocation_info &RE) {
215 return (RE.r_word0 >> 30) & 1;
218 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
219 const MachO::any_relocation_info &RE) {
220 if (O->isLittleEndian())
221 return (RE.r_word1 >> 25) & 3;
222 return (RE.r_word1 >> 5) & 3;
226 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
227 return (RE.r_word0 >> 28) & 3;
230 static unsigned getPlainRelocationType(const MachOObjectFile *O,
231 const MachO::any_relocation_info &RE) {
232 if (O->isLittleEndian())
233 return RE.r_word1 >> 28;
234 return RE.r_word1 & 0xf;
237 static uint32_t getSectionFlags(const MachOObjectFile *O,
240 MachO::section_64 Sect = O->getSection64(Sec);
243 MachO::section Sect = O->getSection(Sec);
247 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
248 bool Is64bits, std::error_code &EC)
249 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
250 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
251 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
252 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
253 HasPageZeroSegment(false) {
254 uint32_t LoadCommandCount = this->getHeader().ncmds;
255 if (LoadCommandCount == 0)
258 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
259 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
261 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
262 for (unsigned I = 0; ; ++I) {
263 if (Load.C.cmd == MachO::LC_SYMTAB) {
264 // Multiple symbol tables
266 EC = object_error::parse_failed;
269 SymtabLoadCmd = Load.Ptr;
270 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
271 // Multiple dynamic symbol tables
272 if (DysymtabLoadCmd) {
273 EC = object_error::parse_failed;
276 DysymtabLoadCmd = Load.Ptr;
277 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
278 // Multiple data in code tables
279 if (DataInCodeLoadCmd) {
280 EC = object_error::parse_failed;
283 DataInCodeLoadCmd = Load.Ptr;
284 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
285 // Multiple linker optimization hint tables
286 if (LinkOptHintsLoadCmd) {
287 EC = object_error::parse_failed;
290 LinkOptHintsLoadCmd = Load.Ptr;
291 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
292 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
293 // Multiple dyldinfo load commands
294 if (DyldInfoLoadCmd) {
295 EC = object_error::parse_failed;
298 DyldInfoLoadCmd = Load.Ptr;
299 } else if (Load.C.cmd == MachO::LC_UUID) {
300 // Multiple UUID load commands
302 EC = object_error::parse_failed;
305 UuidLoadCmd = Load.Ptr;
306 } else if (Load.C.cmd == SegmentLoadType) {
307 const unsigned SegmentLoadSize = this->is64Bit()
308 ? sizeof(MachO::segment_command_64)
309 : sizeof(MachO::segment_command);
310 if (Load.C.cmdsize < SegmentLoadSize)
311 report_fatal_error("Segment load command size is too small.");
313 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
314 for (unsigned J = 0; J < NumSections; ++J) {
315 const char *Sec = getSectionPtr(this, Load, J);
316 Sections.push_back(Sec);
318 if (isPageZeroSegment(this, Load))
319 HasPageZeroSegment = true;
320 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
321 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
322 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
324 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
325 Libraries.push_back(Load.Ptr);
328 if (I == LoadCommandCount - 1)
331 Load = getNextLoadCommandInfo(Load);
335 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
336 unsigned SymbolTableEntrySize = is64Bit() ?
337 sizeof(MachO::nlist_64) :
338 sizeof(MachO::nlist);
339 Symb.p += SymbolTableEntrySize;
342 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
343 StringRef &Res) const {
344 StringRef StringTable = getStringTableData();
345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
346 const char *Start = &StringTable.data()[Entry.n_strx];
347 if (Start < getData().begin() || Start >= getData().end())
349 "Symbol name entry points before beginning or past end of file.");
350 Res = StringRef(Start);
351 return object_error::success;
354 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
355 DataRefImpl DRI = Sec.getRawDataRefImpl();
356 uint32_t Flags = getSectionFlags(this, DRI);
357 return Flags & MachO::SECTION_TYPE;
360 // getIndirectName() returns the name of the alias'ed symbol who's string table
361 // index is in the n_value field.
362 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
363 StringRef &Res) const {
364 StringRef StringTable = getStringTableData();
367 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
368 NValue = Entry.n_value;
369 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
370 return object_error::parse_failed;
372 MachO::nlist Entry = getSymbolTableEntry(Symb);
373 NValue = Entry.n_value;
374 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
375 return object_error::parse_failed;
377 if (NValue >= StringTable.size())
378 return object_error::parse_failed;
379 const char *Start = &StringTable.data()[NValue];
380 Res = StringRef(Start);
381 return object_error::success;
384 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
385 uint64_t &Res) const {
387 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
388 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
390 Res = UnknownAddressOrSize;
394 MachO::nlist Entry = getSymbolTableEntry(Symb);
395 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
397 Res = UnknownAddressOrSize;
401 return object_error::success;
404 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
405 uint32_t flags = getSymbolFlags(DRI);
406 if (flags & SymbolRef::SF_Common) {
407 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
408 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
413 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
414 uint64_t &Result) const {
416 getSymbolAddress(DRI, Value);
417 uint32_t flags = getSymbolFlags(DRI);
418 if (flags & SymbolRef::SF_Common)
421 Result = UnknownAddressOrSize;
422 return object_error::success;
425 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
426 SymbolRef::Type &Res) const {
427 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
428 uint8_t n_type = Entry.n_type;
430 Res = SymbolRef::ST_Other;
432 // If this is a STAB debugging symbol, we can do nothing more.
433 if (n_type & MachO::N_STAB) {
434 Res = SymbolRef::ST_Debug;
435 return object_error::success;
438 switch (n_type & MachO::N_TYPE) {
440 Res = SymbolRef::ST_Unknown;
443 Res = SymbolRef::ST_Function;
446 return object_error::success;
449 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
452 uint8_t MachOType = Entry.n_type;
453 uint16_t MachOFlags = Entry.n_desc;
455 uint32_t Result = SymbolRef::SF_None;
457 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
458 Result |= SymbolRef::SF_Undefined;
460 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
461 Result |= SymbolRef::SF_Indirect;
463 if (MachOType & MachO::N_STAB)
464 Result |= SymbolRef::SF_FormatSpecific;
466 if (MachOType & MachO::N_EXT) {
467 Result |= SymbolRef::SF_Global;
468 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
470 getSymbolAddress(DRI, Value);
471 if (Value && Value != UnknownAddressOrSize)
472 Result |= SymbolRef::SF_Common;
475 if (!(MachOType & MachO::N_PEXT))
476 Result |= SymbolRef::SF_Exported;
479 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
480 Result |= SymbolRef::SF_Weak;
482 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
483 Result |= SymbolRef::SF_Thumb;
485 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
486 Result |= SymbolRef::SF_Absolute;
491 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
492 section_iterator &Res) const {
493 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
494 uint8_t index = Entry.n_sect;
501 if (DRI.d.a >= Sections.size())
502 report_fatal_error("getSymbolSection: Invalid section index.");
503 Res = section_iterator(SectionRef(DRI, this));
506 return object_error::success;
509 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
513 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
514 StringRef &Result) const {
515 ArrayRef<char> Raw = getSectionRawName(Sec);
516 Result = parseSegmentOrSectionName(Raw.data());
517 return object_error::success;
520 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
522 return getSection64(Sec).addr;
523 return getSection(Sec).addr;
526 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
528 return getSection64(Sec).size;
529 return getSection(Sec).size;
532 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
533 StringRef &Res) const {
538 MachO::section_64 Sect = getSection64(Sec);
539 Offset = Sect.offset;
542 MachO::section Sect = getSection(Sec);
543 Offset = Sect.offset;
547 Res = this->getData().substr(Offset, Size);
548 return object_error::success;
551 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
554 MachO::section_64 Sect = getSection64(Sec);
557 MachO::section Sect = getSection(Sec);
561 return uint64_t(1) << Align;
564 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
565 uint32_t Flags = getSectionFlags(this, Sec);
566 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
569 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
570 uint32_t Flags = getSectionFlags(this, Sec);
571 unsigned SectionType = Flags & MachO::SECTION_TYPE;
572 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
573 !(SectionType == MachO::S_ZEROFILL ||
574 SectionType == MachO::S_GB_ZEROFILL);
577 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
578 uint32_t Flags = getSectionFlags(this, Sec);
579 unsigned SectionType = Flags & MachO::SECTION_TYPE;
580 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
581 (SectionType == MachO::S_ZEROFILL ||
582 SectionType == MachO::S_GB_ZEROFILL);
585 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
586 // FIXME: Unimplemented.
590 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
591 DataRefImpl Symb) const {
593 this->getSymbolType(Symb, ST);
594 if (ST == SymbolRef::ST_Unknown)
597 uint64_t SectBegin = getSectionAddress(Sec);
598 uint64_t SectEnd = getSectionSize(Sec);
599 SectEnd += SectBegin;
602 getSymbolAddress(Symb, SymAddr);
603 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
606 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
610 return relocation_iterator(RelocationRef(Ret, this));
614 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
617 MachO::section_64 Sect = getSection64(Sec);
620 MachO::section Sect = getSection(Sec);
627 return relocation_iterator(RelocationRef(Ret, this));
630 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
634 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
635 uint64_t &Res) const {
637 getRelocationOffset(Rel, Offset);
641 uint64_t SecAddress = getSectionAddress(Sec);
642 Res = SecAddress + Offset;
643 return object_error::success;
646 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
647 uint64_t &Res) const {
648 assert(getHeader().filetype == MachO::MH_OBJECT &&
649 "Only implemented for MH_OBJECT");
650 MachO::any_relocation_info RE = getRelocation(Rel);
651 Res = getAnyRelocationAddress(RE);
652 return object_error::success;
656 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
657 MachO::any_relocation_info RE = getRelocation(Rel);
658 if (isRelocationScattered(RE))
661 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
662 bool isExtern = getPlainRelocationExternal(RE);
666 MachO::symtab_command S = getSymtabLoadCommand();
667 unsigned SymbolTableEntrySize = is64Bit() ?
668 sizeof(MachO::nlist_64) :
669 sizeof(MachO::nlist);
670 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
672 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
673 return symbol_iterator(SymbolRef(Sym, this));
677 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
678 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
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;
1004 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1005 MachO::any_relocation_info RE = getRelocation(Rel);
1006 return getAnyRelocationLength(RE);
1010 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1011 // guess on what the short name is. Then name is returned as a substring of the
1012 // StringRef Name passed in. The name of the dynamic library is recognized as
1013 // a framework if it has one of the two following forms:
1014 // Foo.framework/Versions/A/Foo
1015 // Foo.framework/Foo
1016 // Where A and Foo can be any string. And may contain a trailing suffix
1017 // starting with an underbar. If the Name is recognized as a framework then
1018 // isFramework is set to true else it is set to false. If the Name has a
1019 // suffix then Suffix is set to the substring in Name that contains the suffix
1020 // else it is set to a NULL StringRef.
1022 // The Name of the dynamic library is recognized as a library name if it has
1023 // one of the two following forms:
1026 // The library may have a suffix trailing the name Foo of the form:
1027 // libFoo_profile.A.dylib
1028 // libFoo_profile.dylib
1030 // The Name of the dynamic library is also recognized as a library name if it
1031 // has the following form:
1034 // If the Name of the dynamic library is none of the forms above then a NULL
1035 // StringRef is returned.
1037 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1039 StringRef &Suffix) {
1040 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1041 size_t a, b, c, d, Idx;
1043 isFramework = false;
1044 Suffix = StringRef();
1046 // Pull off the last component and make Foo point to it
1047 a = Name.rfind('/');
1048 if (a == Name.npos || a == 0)
1050 Foo = Name.slice(a+1, Name.npos);
1052 // Look for a suffix starting with a '_'
1053 Idx = Foo.rfind('_');
1054 if (Idx != Foo.npos && Foo.size() >= 2) {
1055 Suffix = Foo.slice(Idx, Foo.npos);
1056 Foo = Foo.slice(0, Idx);
1059 // First look for the form Foo.framework/Foo
1060 b = Name.rfind('/', a);
1065 F = Name.slice(Idx, Idx + Foo.size());
1066 DotFramework = Name.slice(Idx + Foo.size(),
1067 Idx + Foo.size() + sizeof(".framework/")-1);
1068 if (F == Foo && DotFramework == ".framework/") {
1073 // Next look for the form Foo.framework/Versions/A/Foo
1076 c = Name.rfind('/', b);
1077 if (c == Name.npos || c == 0)
1079 V = Name.slice(c+1, Name.npos);
1080 if (!V.startswith("Versions/"))
1082 d = Name.rfind('/', c);
1087 F = Name.slice(Idx, Idx + Foo.size());
1088 DotFramework = Name.slice(Idx + Foo.size(),
1089 Idx + Foo.size() + sizeof(".framework/")-1);
1090 if (F == Foo && DotFramework == ".framework/") {
1096 // pull off the suffix after the "." and make a point to it
1097 a = Name.rfind('.');
1098 if (a == Name.npos || a == 0)
1100 Dylib = Name.slice(a, Name.npos);
1101 if (Dylib != ".dylib")
1104 // First pull off the version letter for the form Foo.A.dylib if any.
1106 Dot = Name.slice(a-2, a-1);
1111 b = Name.rfind('/', a);
1116 // ignore any suffix after an underbar like Foo_profile.A.dylib
1117 Idx = Name.find('_', b);
1118 if (Idx != Name.npos && Idx != b) {
1119 Lib = Name.slice(b, Idx);
1120 Suffix = Name.slice(Idx, a);
1123 Lib = Name.slice(b, a);
1124 // There are incorrect library names of the form:
1125 // libATS.A_profile.dylib so check for these.
1126 if (Lib.size() >= 3) {
1127 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1129 Lib = Lib.slice(0, Lib.size()-2);
1134 Qtx = Name.slice(a, Name.npos);
1137 b = Name.rfind('/', a);
1139 Lib = Name.slice(0, a);
1141 Lib = Name.slice(b+1, a);
1142 // There are library names of the form: QT.A.qtx so check for these.
1143 if (Lib.size() >= 3) {
1144 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1146 Lib = Lib.slice(0, Lib.size()-2);
1151 // getLibraryShortNameByIndex() is used to get the short name of the library
1152 // for an undefined symbol in a linked Mach-O binary that was linked with the
1153 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1154 // It is passed the index (0 - based) of the library as translated from
1155 // GET_LIBRARY_ORDINAL (1 - based).
1156 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1157 StringRef &Res) const {
1158 if (Index >= Libraries.size())
1159 return object_error::parse_failed;
1161 // If the cache of LibrariesShortNames is not built up do that first for
1162 // all the Libraries.
1163 if (LibrariesShortNames.size() == 0) {
1164 for (unsigned i = 0; i < Libraries.size(); i++) {
1165 MachO::dylib_command D =
1166 getStruct<MachO::dylib_command>(this, Libraries[i]);
1167 if (D.dylib.name >= D.cmdsize)
1168 return object_error::parse_failed;
1169 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1170 StringRef Name = StringRef(P);
1171 if (D.dylib.name+Name.size() >= D.cmdsize)
1172 return object_error::parse_failed;
1175 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1176 if (shortName.empty())
1177 LibrariesShortNames.push_back(Name);
1179 LibrariesShortNames.push_back(shortName);
1183 Res = LibrariesShortNames[Index];
1184 return object_error::success;
1187 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1188 return getSymbolByIndex(0);
1191 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1194 return basic_symbol_iterator(SymbolRef(DRI, this));
1196 MachO::symtab_command Symtab = getSymtabLoadCommand();
1197 unsigned SymbolTableEntrySize = is64Bit() ?
1198 sizeof(MachO::nlist_64) :
1199 sizeof(MachO::nlist);
1200 unsigned Offset = Symtab.symoff +
1201 Symtab.nsyms * SymbolTableEntrySize;
1202 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1203 return basic_symbol_iterator(SymbolRef(DRI, this));
1206 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1209 return basic_symbol_iterator(SymbolRef(DRI, this));
1211 MachO::symtab_command Symtab = getSymtabLoadCommand();
1212 if (Index >= Symtab.nsyms)
1213 report_fatal_error("Requested symbol index is out of range.");
1214 unsigned SymbolTableEntrySize =
1215 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1216 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1217 DRI.p += Index * SymbolTableEntrySize;
1218 return basic_symbol_iterator(SymbolRef(DRI, this));
1221 section_iterator MachOObjectFile::section_begin() const {
1223 return section_iterator(SectionRef(DRI, this));
1226 section_iterator MachOObjectFile::section_end() const {
1228 DRI.d.a = Sections.size();
1229 return section_iterator(SectionRef(DRI, this));
1232 uint8_t MachOObjectFile::getBytesInAddress() const {
1233 return is64Bit() ? 8 : 4;
1236 StringRef MachOObjectFile::getFileFormatName() const {
1237 unsigned CPUType = getCPUType(this);
1240 case llvm::MachO::CPU_TYPE_I386:
1241 return "Mach-O 32-bit i386";
1242 case llvm::MachO::CPU_TYPE_ARM:
1243 return "Mach-O arm";
1244 case llvm::MachO::CPU_TYPE_POWERPC:
1245 return "Mach-O 32-bit ppc";
1247 return "Mach-O 32-bit unknown";
1252 case llvm::MachO::CPU_TYPE_X86_64:
1253 return "Mach-O 64-bit x86-64";
1254 case llvm::MachO::CPU_TYPE_ARM64:
1255 return "Mach-O arm64";
1256 case llvm::MachO::CPU_TYPE_POWERPC64:
1257 return "Mach-O 64-bit ppc64";
1259 return "Mach-O 64-bit unknown";
1263 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1265 case llvm::MachO::CPU_TYPE_I386:
1267 case llvm::MachO::CPU_TYPE_X86_64:
1268 return Triple::x86_64;
1269 case llvm::MachO::CPU_TYPE_ARM:
1271 case llvm::MachO::CPU_TYPE_ARM64:
1272 return Triple::aarch64;
1273 case llvm::MachO::CPU_TYPE_POWERPC:
1275 case llvm::MachO::CPU_TYPE_POWERPC64:
1276 return Triple::ppc64;
1278 return Triple::UnknownArch;
1282 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1283 const char **McpuDefault) {
1285 *McpuDefault = nullptr;
1288 case MachO::CPU_TYPE_I386:
1289 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1290 case MachO::CPU_SUBTYPE_I386_ALL:
1291 return Triple("i386-apple-darwin");
1295 case MachO::CPU_TYPE_X86_64:
1296 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1297 case MachO::CPU_SUBTYPE_X86_64_ALL:
1298 return Triple("x86_64-apple-darwin");
1299 case MachO::CPU_SUBTYPE_X86_64_H:
1300 return Triple("x86_64h-apple-darwin");
1304 case MachO::CPU_TYPE_ARM:
1305 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1306 case MachO::CPU_SUBTYPE_ARM_V4T:
1307 return Triple("armv4t-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1309 return Triple("armv5e-apple-darwin");
1310 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1311 return Triple("xscale-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V6:
1313 return Triple("armv6-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V6M:
1316 *McpuDefault = "cortex-m0";
1317 return Triple("armv6m-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7:
1319 return Triple("armv7-apple-darwin");
1320 case MachO::CPU_SUBTYPE_ARM_V7EM:
1322 *McpuDefault = "cortex-m4";
1323 return Triple("armv7em-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V7K:
1325 return Triple("armv7k-apple-darwin");
1326 case MachO::CPU_SUBTYPE_ARM_V7M:
1328 *McpuDefault = "cortex-m3";
1329 return Triple("armv7m-apple-darwin");
1330 case MachO::CPU_SUBTYPE_ARM_V7S:
1331 return Triple("armv7s-apple-darwin");
1335 case MachO::CPU_TYPE_ARM64:
1336 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1337 case MachO::CPU_SUBTYPE_ARM64_ALL:
1338 return Triple("arm64-apple-darwin");
1342 case MachO::CPU_TYPE_POWERPC:
1343 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1344 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1345 return Triple("ppc-apple-darwin");
1349 case MachO::CPU_TYPE_POWERPC64:
1350 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1351 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1352 return Triple("ppc64-apple-darwin");
1361 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1362 const char **McpuDefault) {
1364 *McpuDefault = nullptr;
1367 case MachO::CPU_TYPE_ARM:
1368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1369 case MachO::CPU_SUBTYPE_ARM_V4T:
1370 return Triple("thumbv4t-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1372 return Triple("thumbv5e-apple-darwin");
1373 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1374 return Triple("xscale-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V6:
1376 return Triple("thumbv6-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V6M:
1379 *McpuDefault = "cortex-m0";
1380 return Triple("thumbv6m-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7:
1382 return Triple("thumbv7-apple-darwin");
1383 case MachO::CPU_SUBTYPE_ARM_V7EM:
1385 *McpuDefault = "cortex-m4";
1386 return Triple("thumbv7em-apple-darwin");
1387 case MachO::CPU_SUBTYPE_ARM_V7K:
1388 return Triple("thumbv7k-apple-darwin");
1389 case MachO::CPU_SUBTYPE_ARM_V7M:
1391 *McpuDefault = "cortex-m3";
1392 return Triple("thumbv7m-apple-darwin");
1393 case MachO::CPU_SUBTYPE_ARM_V7S:
1394 return Triple("thumbv7s-apple-darwin");
1403 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1404 const char **McpuDefault,
1405 Triple *ThumbTriple) {
1406 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1407 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1412 Triple MachOObjectFile::getHostArch() {
1413 return Triple(sys::getDefaultTargetTriple());
1416 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1417 return StringSwitch<bool>(ArchFlag)
1419 .Case("x86_64", true)
1420 .Case("x86_64h", true)
1421 .Case("armv4t", true)
1423 .Case("armv5e", true)
1424 .Case("armv6", true)
1425 .Case("armv6m", true)
1426 .Case("armv7em", true)
1427 .Case("armv7k", true)
1428 .Case("armv7m", true)
1429 .Case("armv7s", true)
1430 .Case("arm64", true)
1432 .Case("ppc64", true)
1436 unsigned MachOObjectFile::getArch() const {
1437 return getArch(getCPUType(this));
1440 Triple MachOObjectFile::getArch(const char **McpuDefault,
1441 Triple *ThumbTriple) const {
1444 MachO::mach_header_64 H_64;
1445 H_64 = getHeader64();
1446 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1447 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1450 MachO::mach_header H;
1452 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1453 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1459 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1462 return section_rel_begin(DRI);
1465 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1468 return section_rel_end(DRI);
1471 dice_iterator MachOObjectFile::begin_dices() const {
1473 if (!DataInCodeLoadCmd)
1474 return dice_iterator(DiceRef(DRI, this));
1476 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1477 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1478 return dice_iterator(DiceRef(DRI, this));
1481 dice_iterator MachOObjectFile::end_dices() const {
1483 if (!DataInCodeLoadCmd)
1484 return dice_iterator(DiceRef(DRI, this));
1486 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1487 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1488 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1489 return dice_iterator(DiceRef(DRI, this));
1492 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1493 : Trie(T), Malformed(false), Done(false) { }
1495 void ExportEntry::moveToFirst() {
1497 pushDownUntilBottom();
1500 void ExportEntry::moveToEnd() {
1505 bool ExportEntry::operator==(const ExportEntry &Other) const {
1506 // Common case, one at end, other iterating from begin.
1507 if (Done || Other.Done)
1508 return (Done == Other.Done);
1509 // Not equal if different stack sizes.
1510 if (Stack.size() != Other.Stack.size())
1512 // Not equal if different cumulative strings.
1513 if (!CumulativeString.equals(Other.CumulativeString))
1515 // Equal if all nodes in both stacks match.
1516 for (unsigned i=0; i < Stack.size(); ++i) {
1517 if (Stack[i].Start != Other.Stack[i].Start)
1523 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1525 uint64_t Result = decodeULEB128(Ptr, &Count);
1527 if (Ptr > Trie.end()) {
1534 StringRef ExportEntry::name() const {
1535 return CumulativeString;
1538 uint64_t ExportEntry::flags() const {
1539 return Stack.back().Flags;
1542 uint64_t ExportEntry::address() const {
1543 return Stack.back().Address;
1546 uint64_t ExportEntry::other() const {
1547 return Stack.back().Other;
1550 StringRef ExportEntry::otherName() const {
1551 const char* ImportName = Stack.back().ImportName;
1553 return StringRef(ImportName);
1557 uint32_t ExportEntry::nodeOffset() const {
1558 return Stack.back().Start - Trie.begin();
1561 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1562 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1563 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1564 ParentStringLength(0), IsExportNode(false) {
1567 void ExportEntry::pushNode(uint64_t offset) {
1568 const uint8_t *Ptr = Trie.begin() + offset;
1569 NodeState State(Ptr);
1570 uint64_t ExportInfoSize = readULEB128(State.Current);
1571 State.IsExportNode = (ExportInfoSize != 0);
1572 const uint8_t* Children = State.Current + ExportInfoSize;
1573 if (State.IsExportNode) {
1574 State.Flags = readULEB128(State.Current);
1575 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1577 State.Other = readULEB128(State.Current); // dylib ordinal
1578 State.ImportName = reinterpret_cast<const char*>(State.Current);
1580 State.Address = readULEB128(State.Current);
1581 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1582 State.Other = readULEB128(State.Current);
1585 State.ChildCount = *Children;
1586 State.Current = Children + 1;
1587 State.NextChildIndex = 0;
1588 State.ParentStringLength = CumulativeString.size();
1589 Stack.push_back(State);
1592 void ExportEntry::pushDownUntilBottom() {
1593 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1594 NodeState &Top = Stack.back();
1595 CumulativeString.resize(Top.ParentStringLength);
1596 for (;*Top.Current != 0; Top.Current++) {
1597 char C = *Top.Current;
1598 CumulativeString.push_back(C);
1601 uint64_t childNodeIndex = readULEB128(Top.Current);
1602 Top.NextChildIndex += 1;
1603 pushNode(childNodeIndex);
1605 if (!Stack.back().IsExportNode) {
1611 // We have a trie data structure and need a way to walk it that is compatible
1612 // with the C++ iterator model. The solution is a non-recursive depth first
1613 // traversal where the iterator contains a stack of parent nodes along with a
1614 // string that is the accumulation of all edge strings along the parent chain
1617 // There is one "export" node for each exported symbol. But because some
1618 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1619 // node may have child nodes too.
1621 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1622 // child until hitting a node with no children (which is an export node or
1623 // else the trie is malformed). On the way down, each node is pushed on the
1624 // stack ivar. If there is no more ways down, it pops up one and tries to go
1625 // down a sibling path until a childless node is reached.
1626 void ExportEntry::moveNext() {
1627 if (Stack.empty() || !Stack.back().IsExportNode) {
1634 while (!Stack.empty()) {
1635 NodeState &Top = Stack.back();
1636 if (Top.NextChildIndex < Top.ChildCount) {
1637 pushDownUntilBottom();
1638 // Now at the next export node.
1641 if (Top.IsExportNode) {
1642 // This node has no children but is itself an export node.
1643 CumulativeString.resize(Top.ParentStringLength);
1652 iterator_range<export_iterator>
1653 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1654 ExportEntry Start(Trie);
1655 if (Trie.size() == 0)
1658 Start.moveToFirst();
1660 ExportEntry Finish(Trie);
1663 return iterator_range<export_iterator>(export_iterator(Start),
1664 export_iterator(Finish));
1667 iterator_range<export_iterator> MachOObjectFile::exports() const {
1668 return exports(getDyldInfoExportsTrie());
1672 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1673 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1674 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1675 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1677 void MachORebaseEntry::moveToFirst() {
1678 Ptr = Opcodes.begin();
1682 void MachORebaseEntry::moveToEnd() {
1683 Ptr = Opcodes.end();
1684 RemainingLoopCount = 0;
1688 void MachORebaseEntry::moveNext() {
1689 // If in the middle of some loop, move to next rebasing in loop.
1690 SegmentOffset += AdvanceAmount;
1691 if (RemainingLoopCount) {
1692 --RemainingLoopCount;
1695 if (Ptr == Opcodes.end()) {
1700 while (More && !Malformed) {
1701 // Parse next opcode and set up next loop.
1702 uint8_t Byte = *Ptr++;
1703 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1704 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1706 case MachO::REBASE_OPCODE_DONE:
1710 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1712 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1713 RebaseType = ImmValue;
1716 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1717 << "RebaseType=" << (int) RebaseType << "\n");
1719 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1720 SegmentIndex = ImmValue;
1721 SegmentOffset = readULEB128();
1724 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1725 << "SegmentIndex=" << SegmentIndex << ", "
1726 << format("SegmentOffset=0x%06X", SegmentOffset)
1729 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1730 SegmentOffset += readULEB128();
1731 DEBUG_WITH_TYPE("mach-o-rebase",
1732 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1733 << format("SegmentOffset=0x%06X",
1734 SegmentOffset) << "\n");
1736 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1737 SegmentOffset += ImmValue * PointerSize;
1738 DEBUG_WITH_TYPE("mach-o-rebase",
1739 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1740 << format("SegmentOffset=0x%06X",
1741 SegmentOffset) << "\n");
1743 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1744 AdvanceAmount = PointerSize;
1745 RemainingLoopCount = ImmValue - 1;
1748 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1754 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1755 AdvanceAmount = PointerSize;
1756 RemainingLoopCount = readULEB128() - 1;
1759 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1760 << format("SegmentOffset=0x%06X", SegmentOffset)
1761 << ", AdvanceAmount=" << AdvanceAmount
1762 << ", RemainingLoopCount=" << RemainingLoopCount
1765 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1766 AdvanceAmount = readULEB128() + PointerSize;
1767 RemainingLoopCount = 0;
1770 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1771 << format("SegmentOffset=0x%06X", SegmentOffset)
1772 << ", AdvanceAmount=" << AdvanceAmount
1773 << ", RemainingLoopCount=" << RemainingLoopCount
1776 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1777 RemainingLoopCount = readULEB128() - 1;
1778 AdvanceAmount = readULEB128() + PointerSize;
1781 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1782 << format("SegmentOffset=0x%06X", SegmentOffset)
1783 << ", AdvanceAmount=" << AdvanceAmount
1784 << ", RemainingLoopCount=" << RemainingLoopCount
1793 uint64_t MachORebaseEntry::readULEB128() {
1795 uint64_t Result = decodeULEB128(Ptr, &Count);
1797 if (Ptr > Opcodes.end()) {
1798 Ptr = Opcodes.end();
1804 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1806 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1808 StringRef MachORebaseEntry::typeName() const {
1809 switch (RebaseType) {
1810 case MachO::REBASE_TYPE_POINTER:
1812 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1813 return "text abs32";
1814 case MachO::REBASE_TYPE_TEXT_PCREL32:
1815 return "text rel32";
1820 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1821 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1822 return (Ptr == Other.Ptr) &&
1823 (RemainingLoopCount == Other.RemainingLoopCount) &&
1824 (Done == Other.Done);
1827 iterator_range<rebase_iterator>
1828 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1829 MachORebaseEntry Start(Opcodes, is64);
1830 Start.moveToFirst();
1832 MachORebaseEntry Finish(Opcodes, is64);
1835 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1836 rebase_iterator(Finish));
1839 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1840 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1844 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1846 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1847 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1848 BindType(0), PointerSize(is64Bit ? 8 : 4),
1849 TableKind(BK), Malformed(false), Done(false) {}
1851 void MachOBindEntry::moveToFirst() {
1852 Ptr = Opcodes.begin();
1856 void MachOBindEntry::moveToEnd() {
1857 Ptr = Opcodes.end();
1858 RemainingLoopCount = 0;
1862 void MachOBindEntry::moveNext() {
1863 // If in the middle of some loop, move to next binding in loop.
1864 SegmentOffset += AdvanceAmount;
1865 if (RemainingLoopCount) {
1866 --RemainingLoopCount;
1869 if (Ptr == Opcodes.end()) {
1874 while (More && !Malformed) {
1875 // Parse next opcode and set up next loop.
1876 uint8_t Byte = *Ptr++;
1877 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1878 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1879 int8_t SignExtended;
1880 const uint8_t *SymStart;
1882 case MachO::BIND_OPCODE_DONE:
1883 if (TableKind == Kind::Lazy) {
1884 // Lazying bindings have a DONE opcode between entries. Need to ignore
1885 // it to advance to next entry. But need not if this is last entry.
1886 bool NotLastEntry = false;
1887 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1889 NotLastEntry = true;
1898 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1900 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1904 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1905 << "Ordinal=" << Ordinal << "\n");
1907 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1908 Ordinal = readULEB128();
1911 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1912 << "Ordinal=" << Ordinal << "\n");
1914 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1916 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1917 Ordinal = SignExtended;
1922 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1923 << "Ordinal=" << Ordinal << "\n");
1925 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1931 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1936 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1937 << "SymbolName=" << SymbolName << "\n");
1938 if (TableKind == Kind::Weak) {
1939 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1943 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1944 BindType = ImmValue;
1947 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1948 << "BindType=" << (int)BindType << "\n");
1950 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1951 Addend = readSLEB128();
1952 if (TableKind == Kind::Lazy)
1956 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1957 << "Addend=" << Addend << "\n");
1959 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1960 SegmentIndex = ImmValue;
1961 SegmentOffset = readULEB128();
1964 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1965 << "SegmentIndex=" << SegmentIndex << ", "
1966 << format("SegmentOffset=0x%06X", SegmentOffset)
1969 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1970 SegmentOffset += readULEB128();
1971 DEBUG_WITH_TYPE("mach-o-bind",
1972 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1973 << format("SegmentOffset=0x%06X",
1974 SegmentOffset) << "\n");
1976 case MachO::BIND_OPCODE_DO_BIND:
1977 AdvanceAmount = PointerSize;
1978 RemainingLoopCount = 0;
1979 DEBUG_WITH_TYPE("mach-o-bind",
1980 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1981 << format("SegmentOffset=0x%06X",
1982 SegmentOffset) << "\n");
1984 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1985 AdvanceAmount = readULEB128() + PointerSize;
1986 RemainingLoopCount = 0;
1987 if (TableKind == Kind::Lazy)
1991 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1992 << format("SegmentOffset=0x%06X", SegmentOffset)
1993 << ", AdvanceAmount=" << AdvanceAmount
1994 << ", RemainingLoopCount=" << RemainingLoopCount
1997 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1998 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1999 RemainingLoopCount = 0;
2000 if (TableKind == Kind::Lazy)
2002 DEBUG_WITH_TYPE("mach-o-bind",
2004 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2005 << format("SegmentOffset=0x%06X",
2006 SegmentOffset) << "\n");
2008 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2009 RemainingLoopCount = readULEB128() - 1;
2010 AdvanceAmount = readULEB128() + PointerSize;
2011 if (TableKind == Kind::Lazy)
2015 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2016 << format("SegmentOffset=0x%06X", SegmentOffset)
2017 << ", AdvanceAmount=" << AdvanceAmount
2018 << ", RemainingLoopCount=" << RemainingLoopCount
2027 uint64_t MachOBindEntry::readULEB128() {
2029 uint64_t Result = decodeULEB128(Ptr, &Count);
2031 if (Ptr > Opcodes.end()) {
2032 Ptr = Opcodes.end();
2038 int64_t MachOBindEntry::readSLEB128() {
2040 int64_t Result = decodeSLEB128(Ptr, &Count);
2042 if (Ptr > Opcodes.end()) {
2043 Ptr = Opcodes.end();
2050 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2052 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2054 StringRef MachOBindEntry::typeName() const {
2056 case MachO::BIND_TYPE_POINTER:
2058 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2059 return "text abs32";
2060 case MachO::BIND_TYPE_TEXT_PCREL32:
2061 return "text rel32";
2066 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2068 int64_t MachOBindEntry::addend() const { return Addend; }
2070 uint32_t MachOBindEntry::flags() const { return Flags; }
2072 int MachOBindEntry::ordinal() const { return Ordinal; }
2074 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2075 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2076 return (Ptr == Other.Ptr) &&
2077 (RemainingLoopCount == Other.RemainingLoopCount) &&
2078 (Done == Other.Done);
2081 iterator_range<bind_iterator>
2082 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2083 MachOBindEntry::Kind BKind) {
2084 MachOBindEntry Start(Opcodes, is64, BKind);
2085 Start.moveToFirst();
2087 MachOBindEntry Finish(Opcodes, is64, BKind);
2090 return iterator_range<bind_iterator>(bind_iterator(Start),
2091 bind_iterator(Finish));
2094 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2095 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2096 MachOBindEntry::Kind::Regular);
2099 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2100 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2101 MachOBindEntry::Kind::Lazy);
2104 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2105 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2106 MachOBindEntry::Kind::Weak);
2110 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2111 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2112 return parseSegmentOrSectionName(Raw.data());
2116 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2117 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
2118 const section_base *Base =
2119 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2120 return makeArrayRef(Base->sectname);
2124 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2125 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
2126 const section_base *Base =
2127 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2128 return makeArrayRef(Base->segname);
2132 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2134 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2136 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2139 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2140 const MachO::any_relocation_info &RE) const {
2141 if (isLittleEndian())
2142 return RE.r_word1 & 0xffffff;
2143 return RE.r_word1 >> 8;
2146 bool MachOObjectFile::getPlainRelocationExternal(
2147 const MachO::any_relocation_info &RE) const {
2148 if (isLittleEndian())
2149 return (RE.r_word1 >> 27) & 1;
2150 return (RE.r_word1 >> 4) & 1;
2153 bool MachOObjectFile::getScatteredRelocationScattered(
2154 const MachO::any_relocation_info &RE) const {
2155 return RE.r_word0 >> 31;
2158 uint32_t MachOObjectFile::getScatteredRelocationValue(
2159 const MachO::any_relocation_info &RE) const {
2163 uint32_t MachOObjectFile::getScatteredRelocationType(
2164 const MachO::any_relocation_info &RE) const {
2165 return (RE.r_word0 >> 24) & 0xf;
2168 unsigned MachOObjectFile::getAnyRelocationAddress(
2169 const MachO::any_relocation_info &RE) const {
2170 if (isRelocationScattered(RE))
2171 return getScatteredRelocationAddress(RE);
2172 return getPlainRelocationAddress(RE);
2175 unsigned MachOObjectFile::getAnyRelocationPCRel(
2176 const MachO::any_relocation_info &RE) const {
2177 if (isRelocationScattered(RE))
2178 return getScatteredRelocationPCRel(this, RE);
2179 return getPlainRelocationPCRel(this, RE);
2182 unsigned MachOObjectFile::getAnyRelocationLength(
2183 const MachO::any_relocation_info &RE) const {
2184 if (isRelocationScattered(RE))
2185 return getScatteredRelocationLength(RE);
2186 return getPlainRelocationLength(this, RE);
2190 MachOObjectFile::getAnyRelocationType(
2191 const MachO::any_relocation_info &RE) const {
2192 if (isRelocationScattered(RE))
2193 return getScatteredRelocationType(RE);
2194 return getPlainRelocationType(this, RE);
2198 MachOObjectFile::getAnyRelocationSection(
2199 const MachO::any_relocation_info &RE) const {
2200 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2201 return *section_end();
2202 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2205 return SectionRef(DRI, this);
2208 MachOObjectFile::LoadCommandInfo
2209 MachOObjectFile::getFirstLoadCommandInfo() const {
2210 MachOObjectFile::LoadCommandInfo Load;
2212 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2213 sizeof(MachO::mach_header);
2214 Load.Ptr = getPtr(this, HeaderSize);
2215 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2216 if (Load.C.cmdsize < 8)
2217 report_fatal_error("Load command with size < 8 bytes.");
2221 MachOObjectFile::LoadCommandInfo
2222 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2223 MachOObjectFile::LoadCommandInfo Next;
2224 Next.Ptr = L.Ptr + L.C.cmdsize;
2225 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2226 if (Next.C.cmdsize < 8)
2227 report_fatal_error("Load command with size < 8 bytes.");
2231 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2232 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2233 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2236 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2237 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2238 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2241 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2242 unsigned Index) const {
2243 const char *Sec = getSectionPtr(this, L, Index);
2244 return getStruct<MachO::section>(this, Sec);
2247 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2248 unsigned Index) const {
2249 const char *Sec = getSectionPtr(this, L, Index);
2250 return getStruct<MachO::section_64>(this, Sec);
2254 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2255 const char *P = reinterpret_cast<const char *>(DRI.p);
2256 return getStruct<MachO::nlist>(this, P);
2260 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2261 const char *P = reinterpret_cast<const char *>(DRI.p);
2262 return getStruct<MachO::nlist_64>(this, P);
2265 MachO::linkedit_data_command
2266 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2267 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2270 MachO::segment_command
2271 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2272 return getStruct<MachO::segment_command>(this, L.Ptr);
2275 MachO::segment_command_64
2276 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2277 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2280 MachO::linker_option_command
2281 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2282 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2285 MachO::version_min_command
2286 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2287 return getStruct<MachO::version_min_command>(this, L.Ptr);
2290 MachO::dylib_command
2291 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2292 return getStruct<MachO::dylib_command>(this, L.Ptr);
2295 MachO::dyld_info_command
2296 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2297 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2300 MachO::dylinker_command
2301 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2302 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2306 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2307 return getStruct<MachO::uuid_command>(this, L.Ptr);
2310 MachO::rpath_command
2311 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2312 return getStruct<MachO::rpath_command>(this, L.Ptr);
2315 MachO::source_version_command
2316 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2317 return getStruct<MachO::source_version_command>(this, L.Ptr);
2320 MachO::entry_point_command
2321 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2322 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2325 MachO::encryption_info_command
2326 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2327 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2330 MachO::encryption_info_command_64
2331 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2332 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2335 MachO::sub_framework_command
2336 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2337 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2340 MachO::sub_umbrella_command
2341 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2342 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2345 MachO::sub_library_command
2346 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2347 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2350 MachO::sub_client_command
2351 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2352 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2355 MachO::routines_command
2356 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2357 return getStruct<MachO::routines_command>(this, L.Ptr);
2360 MachO::routines_command_64
2361 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2362 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2365 MachO::thread_command
2366 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2367 return getStruct<MachO::thread_command>(this, L.Ptr);
2370 MachO::any_relocation_info
2371 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2376 MachO::section_64 Sect = getSection64(Sec);
2377 Offset = Sect.reloff;
2379 MachO::section Sect = getSection(Sec);
2380 Offset = Sect.reloff;
2383 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2384 getPtr(this, Offset)) + Rel.d.b;
2385 return getStruct<MachO::any_relocation_info>(
2386 this, reinterpret_cast<const char *>(P));
2389 MachO::data_in_code_entry
2390 MachOObjectFile::getDice(DataRefImpl Rel) const {
2391 const char *P = reinterpret_cast<const char *>(Rel.p);
2392 return getStruct<MachO::data_in_code_entry>(this, P);
2395 MachO::mach_header MachOObjectFile::getHeader() const {
2396 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2399 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2400 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2403 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2404 const MachO::dysymtab_command &DLC,
2405 unsigned Index) const {
2406 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2407 return getStruct<uint32_t>(this, getPtr(this, Offset));
2410 MachO::data_in_code_entry
2411 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2412 unsigned Index) const {
2413 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2414 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2417 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2419 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2421 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2422 MachO::symtab_command Cmd;
2423 Cmd.cmd = MachO::LC_SYMTAB;
2424 Cmd.cmdsize = sizeof(MachO::symtab_command);
2432 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2433 if (DysymtabLoadCmd)
2434 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2436 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2437 MachO::dysymtab_command Cmd;
2438 Cmd.cmd = MachO::LC_DYSYMTAB;
2439 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2450 Cmd.extrefsymoff = 0;
2451 Cmd.nextrefsyms = 0;
2452 Cmd.indirectsymoff = 0;
2453 Cmd.nindirectsyms = 0;
2461 MachO::linkedit_data_command
2462 MachOObjectFile::getDataInCodeLoadCommand() const {
2463 if (DataInCodeLoadCmd)
2464 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2466 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2467 MachO::linkedit_data_command Cmd;
2468 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2469 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2475 MachO::linkedit_data_command
2476 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2477 if (LinkOptHintsLoadCmd)
2478 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2480 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2482 MachO::linkedit_data_command Cmd;
2483 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2484 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2490 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2491 if (!DyldInfoLoadCmd)
2492 return ArrayRef<uint8_t>();
2494 MachO::dyld_info_command DyldInfo
2495 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2496 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2497 getPtr(this, DyldInfo.rebase_off));
2498 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2501 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2502 if (!DyldInfoLoadCmd)
2503 return ArrayRef<uint8_t>();
2505 MachO::dyld_info_command DyldInfo
2506 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2507 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2508 getPtr(this, DyldInfo.bind_off));
2509 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2512 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2513 if (!DyldInfoLoadCmd)
2514 return ArrayRef<uint8_t>();
2516 MachO::dyld_info_command DyldInfo
2517 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2518 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2519 getPtr(this, DyldInfo.weak_bind_off));
2520 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2523 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2524 if (!DyldInfoLoadCmd)
2525 return ArrayRef<uint8_t>();
2527 MachO::dyld_info_command DyldInfo
2528 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2529 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2530 getPtr(this, DyldInfo.lazy_bind_off));
2531 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2534 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2535 if (!DyldInfoLoadCmd)
2536 return ArrayRef<uint8_t>();
2538 MachO::dyld_info_command DyldInfo
2539 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2540 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2541 getPtr(this, DyldInfo.export_off));
2542 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2545 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2547 return ArrayRef<uint8_t>();
2548 // Returning a pointer is fine as uuid doesn't need endian swapping.
2549 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2550 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2553 StringRef MachOObjectFile::getStringTableData() const {
2554 MachO::symtab_command S = getSymtabLoadCommand();
2555 return getData().substr(S.stroff, S.strsize);
2558 bool MachOObjectFile::is64Bit() const {
2559 return getType() == getMachOType(false, true) ||
2560 getType() == getMachOType(true, true);
2563 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2564 SmallVectorImpl<uint64_t> &Out) const {
2565 DataExtractor extractor(ObjectFile::getData(), true, 0);
2567 uint32_t offset = Index;
2569 while (uint64_t delta = extractor.getULEB128(&offset)) {
2571 Out.push_back(data);
2575 bool MachOObjectFile::isRelocatableObject() const {
2576 return getHeader().filetype == MachO::MH_OBJECT;
2579 ErrorOr<std::unique_ptr<MachOObjectFile>>
2580 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2581 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2583 std::unique_ptr<MachOObjectFile> Ret;
2584 if (Magic == "\xFE\xED\xFA\xCE")
2585 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2586 else if (Magic == "\xCE\xFA\xED\xFE")
2587 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2588 else if (Magic == "\xFE\xED\xFA\xCF")
2589 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2590 else if (Magic == "\xCF\xFA\xED\xFE")
2591 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2593 return object_error::parse_failed;
2597 return std::move(Ret);