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 uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
415 getSymbolAddress(DRI, Value);
416 uint32_t flags = getSymbolFlags(DRI);
417 if (flags & SymbolRef::SF_Common)
419 return UnknownAddressOrSize;
422 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
423 SymbolRef::Type &Res) const {
424 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
425 uint8_t n_type = Entry.n_type;
427 Res = SymbolRef::ST_Other;
429 // If this is a STAB debugging symbol, we can do nothing more.
430 if (n_type & MachO::N_STAB) {
431 Res = SymbolRef::ST_Debug;
432 return object_error::success;
435 switch (n_type & MachO::N_TYPE) {
437 Res = SymbolRef::ST_Unknown;
440 Res = SymbolRef::ST_Function;
443 return object_error::success;
446 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
447 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
449 uint8_t MachOType = Entry.n_type;
450 uint16_t MachOFlags = Entry.n_desc;
452 uint32_t Result = SymbolRef::SF_None;
454 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
455 Result |= SymbolRef::SF_Undefined;
457 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
458 Result |= SymbolRef::SF_Indirect;
460 if (MachOType & MachO::N_STAB)
461 Result |= SymbolRef::SF_FormatSpecific;
463 if (MachOType & MachO::N_EXT) {
464 Result |= SymbolRef::SF_Global;
465 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
467 getSymbolAddress(DRI, Value);
468 if (Value && Value != UnknownAddressOrSize)
469 Result |= SymbolRef::SF_Common;
472 if (!(MachOType & MachO::N_PEXT))
473 Result |= SymbolRef::SF_Exported;
476 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
477 Result |= SymbolRef::SF_Weak;
479 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
480 Result |= SymbolRef::SF_Thumb;
482 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
483 Result |= SymbolRef::SF_Absolute;
488 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
489 section_iterator &Res) const {
490 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
491 uint8_t index = Entry.n_sect;
498 if (DRI.d.a >= Sections.size())
499 report_fatal_error("getSymbolSection: Invalid section index.");
500 Res = section_iterator(SectionRef(DRI, this));
503 return object_error::success;
506 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
510 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
511 StringRef &Result) const {
512 ArrayRef<char> Raw = getSectionRawName(Sec);
513 Result = parseSegmentOrSectionName(Raw.data());
514 return object_error::success;
517 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
519 return getSection64(Sec).addr;
520 return getSection(Sec).addr;
523 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
525 return getSection64(Sec).size;
526 return getSection(Sec).size;
529 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
530 StringRef &Res) const {
535 MachO::section_64 Sect = getSection64(Sec);
536 Offset = Sect.offset;
539 MachO::section Sect = getSection(Sec);
540 Offset = Sect.offset;
544 Res = this->getData().substr(Offset, Size);
545 return object_error::success;
548 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
551 MachO::section_64 Sect = getSection64(Sec);
554 MachO::section Sect = getSection(Sec);
558 return uint64_t(1) << Align;
561 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
562 uint32_t Flags = getSectionFlags(this, Sec);
563 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
566 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
567 uint32_t Flags = getSectionFlags(this, Sec);
568 unsigned SectionType = Flags & MachO::SECTION_TYPE;
569 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
570 !(SectionType == MachO::S_ZEROFILL ||
571 SectionType == MachO::S_GB_ZEROFILL);
574 bool MachOObjectFile::isSectionBSS(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::isSectionVirtual(DataRefImpl Sec) const {
583 // FIXME: Unimplemented.
587 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
588 DataRefImpl Symb) const {
590 this->getSymbolType(Symb, ST);
591 if (ST == SymbolRef::ST_Unknown)
594 uint64_t SectBegin = getSectionAddress(Sec);
595 uint64_t SectEnd = getSectionSize(Sec);
596 SectEnd += SectBegin;
599 getSymbolAddress(Symb, SymAddr);
600 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
603 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
607 return relocation_iterator(RelocationRef(Ret, this));
611 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
614 MachO::section_64 Sect = getSection64(Sec);
617 MachO::section Sect = getSection(Sec);
624 return relocation_iterator(RelocationRef(Ret, this));
627 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
631 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
632 uint64_t &Res) const {
634 getRelocationOffset(Rel, Offset);
638 uint64_t SecAddress = getSectionAddress(Sec);
639 Res = SecAddress + Offset;
640 return object_error::success;
643 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
644 uint64_t &Res) const {
645 assert(getHeader().filetype == MachO::MH_OBJECT &&
646 "Only implemented for MH_OBJECT");
647 MachO::any_relocation_info RE = getRelocation(Rel);
648 Res = getAnyRelocationAddress(RE);
649 return object_error::success;
653 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
654 MachO::any_relocation_info RE = getRelocation(Rel);
655 if (isRelocationScattered(RE))
658 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
659 bool isExtern = getPlainRelocationExternal(RE);
663 MachO::symtab_command S = getSymtabLoadCommand();
664 unsigned SymbolTableEntrySize = is64Bit() ?
665 sizeof(MachO::nlist_64) :
666 sizeof(MachO::nlist);
667 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
669 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
670 return symbol_iterator(SymbolRef(Sym, this));
674 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
675 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
678 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
679 uint64_t &Res) const {
680 MachO::any_relocation_info RE = getRelocation(Rel);
681 Res = getAnyRelocationType(RE);
682 return object_error::success;
686 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
687 SmallVectorImpl<char> &Result) const {
690 getRelocationType(Rel, RType);
692 unsigned Arch = this->getArch();
696 static const char *const Table[] = {
697 "GENERIC_RELOC_VANILLA",
698 "GENERIC_RELOC_PAIR",
699 "GENERIC_RELOC_SECTDIFF",
700 "GENERIC_RELOC_PB_LA_PTR",
701 "GENERIC_RELOC_LOCAL_SECTDIFF",
702 "GENERIC_RELOC_TLV" };
710 case Triple::x86_64: {
711 static const char *const Table[] = {
712 "X86_64_RELOC_UNSIGNED",
713 "X86_64_RELOC_SIGNED",
714 "X86_64_RELOC_BRANCH",
715 "X86_64_RELOC_GOT_LOAD",
717 "X86_64_RELOC_SUBTRACTOR",
718 "X86_64_RELOC_SIGNED_1",
719 "X86_64_RELOC_SIGNED_2",
720 "X86_64_RELOC_SIGNED_4",
721 "X86_64_RELOC_TLV" };
730 static const char *const Table[] = {
733 "ARM_RELOC_SECTDIFF",
734 "ARM_RELOC_LOCAL_SECTDIFF",
735 "ARM_RELOC_PB_LA_PTR",
737 "ARM_THUMB_RELOC_BR22",
738 "ARM_THUMB_32BIT_BRANCH",
740 "ARM_RELOC_HALF_SECTDIFF" };
748 case Triple::aarch64: {
749 static const char *const Table[] = {
750 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
751 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
752 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
753 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
754 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
758 if (RType >= array_lengthof(Table))
765 static const char *const Table[] = {
774 "PPC_RELOC_SECTDIFF",
775 "PPC_RELOC_PB_LA_PTR",
776 "PPC_RELOC_HI16_SECTDIFF",
777 "PPC_RELOC_LO16_SECTDIFF",
778 "PPC_RELOC_HA16_SECTDIFF",
780 "PPC_RELOC_LO14_SECTDIFF",
781 "PPC_RELOC_LOCAL_SECTDIFF" };
789 case Triple::UnknownArch:
793 Result.append(res.begin(), res.end());
794 return object_error::success;
798 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
799 SmallVectorImpl<char> &Result) const {
800 MachO::any_relocation_info RE = getRelocation(Rel);
802 unsigned Arch = this->getArch();
805 raw_string_ostream fmt(fmtbuf);
806 unsigned Type = this->getAnyRelocationType(RE);
807 bool IsPCRel = this->getAnyRelocationPCRel(RE);
809 // Determine any addends that should be displayed with the relocation.
810 // These require decoding the relocation type, which is triple-specific.
812 // X86_64 has entirely custom relocation types.
813 if (Arch == Triple::x86_64) {
814 bool isPCRel = getAnyRelocationPCRel(RE);
817 case MachO::X86_64_RELOC_GOT_LOAD:
818 case MachO::X86_64_RELOC_GOT: {
819 printRelocationTargetName(this, RE, fmt);
821 if (isPCRel) fmt << "PCREL";
824 case MachO::X86_64_RELOC_SUBTRACTOR: {
825 DataRefImpl RelNext = Rel;
826 moveRelocationNext(RelNext);
827 MachO::any_relocation_info RENext = getRelocation(RelNext);
829 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
830 // X86_64_RELOC_UNSIGNED.
831 // NOTE: Scattered relocations don't exist on x86_64.
832 unsigned RType = getAnyRelocationType(RENext);
833 if (RType != MachO::X86_64_RELOC_UNSIGNED)
834 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
835 "X86_64_RELOC_SUBTRACTOR.");
837 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
838 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
839 printRelocationTargetName(this, RENext, fmt);
841 printRelocationTargetName(this, RE, fmt);
844 case MachO::X86_64_RELOC_TLV:
845 printRelocationTargetName(this, RE, fmt);
847 if (isPCRel) fmt << "P";
849 case MachO::X86_64_RELOC_SIGNED_1:
850 printRelocationTargetName(this, RE, fmt);
853 case MachO::X86_64_RELOC_SIGNED_2:
854 printRelocationTargetName(this, RE, fmt);
857 case MachO::X86_64_RELOC_SIGNED_4:
858 printRelocationTargetName(this, RE, fmt);
862 printRelocationTargetName(this, RE, fmt);
865 // X86 and ARM share some relocation types in common.
866 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
867 Arch == Triple::ppc) {
868 // Generic relocation types...
870 case MachO::GENERIC_RELOC_PAIR: // prints no info
871 return object_error::success;
872 case MachO::GENERIC_RELOC_SECTDIFF: {
873 DataRefImpl RelNext = Rel;
874 moveRelocationNext(RelNext);
875 MachO::any_relocation_info RENext = getRelocation(RelNext);
877 // X86 sect diff's must be followed by a relocation of type
878 // GENERIC_RELOC_PAIR.
879 unsigned RType = getAnyRelocationType(RENext);
881 if (RType != MachO::GENERIC_RELOC_PAIR)
882 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
883 "GENERIC_RELOC_SECTDIFF.");
885 printRelocationTargetName(this, RE, fmt);
887 printRelocationTargetName(this, RENext, fmt);
892 if (Arch == Triple::x86 || Arch == Triple::ppc) {
894 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
895 DataRefImpl RelNext = Rel;
896 moveRelocationNext(RelNext);
897 MachO::any_relocation_info RENext = getRelocation(RelNext);
899 // X86 sect diff's must be followed by a relocation of type
900 // GENERIC_RELOC_PAIR.
901 unsigned RType = getAnyRelocationType(RENext);
902 if (RType != MachO::GENERIC_RELOC_PAIR)
903 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
904 "GENERIC_RELOC_LOCAL_SECTDIFF.");
906 printRelocationTargetName(this, RE, fmt);
908 printRelocationTargetName(this, RENext, fmt);
911 case MachO::GENERIC_RELOC_TLV: {
912 printRelocationTargetName(this, RE, fmt);
914 if (IsPCRel) fmt << "P";
918 printRelocationTargetName(this, RE, fmt);
920 } else { // ARM-specific relocations
922 case MachO::ARM_RELOC_HALF:
923 case MachO::ARM_RELOC_HALF_SECTDIFF: {
924 // Half relocations steal a bit from the length field to encode
925 // whether this is an upper16 or a lower16 relocation.
926 bool isUpper = getAnyRelocationLength(RE) >> 1;
932 printRelocationTargetName(this, RE, fmt);
934 DataRefImpl RelNext = Rel;
935 moveRelocationNext(RelNext);
936 MachO::any_relocation_info RENext = getRelocation(RelNext);
938 // ARM half relocs must be followed by a relocation of type
940 unsigned RType = getAnyRelocationType(RENext);
941 if (RType != MachO::ARM_RELOC_PAIR)
942 report_fatal_error("Expected ARM_RELOC_PAIR after "
945 // NOTE: The half of the target virtual address is stashed in the
946 // address field of the secondary relocation, but we can't reverse
947 // engineer the constant offset from it without decoding the movw/movt
948 // instruction to find the other half in its immediate field.
950 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
951 // symbol/section pointer of the follow-on relocation.
952 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
954 printRelocationTargetName(this, RENext, fmt);
961 printRelocationTargetName(this, RE, fmt);
966 printRelocationTargetName(this, RE, fmt);
969 Result.append(fmtbuf.begin(), fmtbuf.end());
970 return object_error::success;
973 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
974 bool &Result) const {
975 unsigned Arch = getArch();
977 getRelocationType(Rel, Type);
981 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
983 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
984 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
985 } else if (Arch == Triple::x86_64) {
986 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
987 // an X86_64_RELOC_SUBTRACTOR.
988 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
989 DataRefImpl RelPrev = Rel;
992 getRelocationType(RelPrev, PrevType);
993 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
998 return object_error::success;
1001 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
1002 MachO::any_relocation_info RE = getRelocation(Rel);
1003 return getAnyRelocationLength(RE);
1007 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1008 // guess on what the short name is. Then name is returned as a substring of the
1009 // StringRef Name passed in. The name of the dynamic library is recognized as
1010 // a framework if it has one of the two following forms:
1011 // Foo.framework/Versions/A/Foo
1012 // Foo.framework/Foo
1013 // Where A and Foo can be any string. And may contain a trailing suffix
1014 // starting with an underbar. If the Name is recognized as a framework then
1015 // isFramework is set to true else it is set to false. If the Name has a
1016 // suffix then Suffix is set to the substring in Name that contains the suffix
1017 // else it is set to a NULL StringRef.
1019 // The Name of the dynamic library is recognized as a library name if it has
1020 // one of the two following forms:
1023 // The library may have a suffix trailing the name Foo of the form:
1024 // libFoo_profile.A.dylib
1025 // libFoo_profile.dylib
1027 // The Name of the dynamic library is also recognized as a library name if it
1028 // has the following form:
1031 // If the Name of the dynamic library is none of the forms above then a NULL
1032 // StringRef is returned.
1034 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1036 StringRef &Suffix) {
1037 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1038 size_t a, b, c, d, Idx;
1040 isFramework = false;
1041 Suffix = StringRef();
1043 // Pull off the last component and make Foo point to it
1044 a = Name.rfind('/');
1045 if (a == Name.npos || a == 0)
1047 Foo = Name.slice(a+1, Name.npos);
1049 // Look for a suffix starting with a '_'
1050 Idx = Foo.rfind('_');
1051 if (Idx != Foo.npos && Foo.size() >= 2) {
1052 Suffix = Foo.slice(Idx, Foo.npos);
1053 Foo = Foo.slice(0, Idx);
1056 // First look for the form Foo.framework/Foo
1057 b = Name.rfind('/', a);
1062 F = Name.slice(Idx, Idx + Foo.size());
1063 DotFramework = Name.slice(Idx + Foo.size(),
1064 Idx + Foo.size() + sizeof(".framework/")-1);
1065 if (F == Foo && DotFramework == ".framework/") {
1070 // Next look for the form Foo.framework/Versions/A/Foo
1073 c = Name.rfind('/', b);
1074 if (c == Name.npos || c == 0)
1076 V = Name.slice(c+1, Name.npos);
1077 if (!V.startswith("Versions/"))
1079 d = Name.rfind('/', c);
1084 F = Name.slice(Idx, Idx + Foo.size());
1085 DotFramework = Name.slice(Idx + Foo.size(),
1086 Idx + Foo.size() + sizeof(".framework/")-1);
1087 if (F == Foo && DotFramework == ".framework/") {
1093 // pull off the suffix after the "." and make a point to it
1094 a = Name.rfind('.');
1095 if (a == Name.npos || a == 0)
1097 Dylib = Name.slice(a, Name.npos);
1098 if (Dylib != ".dylib")
1101 // First pull off the version letter for the form Foo.A.dylib if any.
1103 Dot = Name.slice(a-2, a-1);
1108 b = Name.rfind('/', a);
1113 // ignore any suffix after an underbar like Foo_profile.A.dylib
1114 Idx = Name.find('_', b);
1115 if (Idx != Name.npos && Idx != b) {
1116 Lib = Name.slice(b, Idx);
1117 Suffix = Name.slice(Idx, a);
1120 Lib = Name.slice(b, a);
1121 // There are incorrect library names of the form:
1122 // libATS.A_profile.dylib so check for these.
1123 if (Lib.size() >= 3) {
1124 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1126 Lib = Lib.slice(0, Lib.size()-2);
1131 Qtx = Name.slice(a, Name.npos);
1134 b = Name.rfind('/', a);
1136 Lib = Name.slice(0, a);
1138 Lib = Name.slice(b+1, a);
1139 // There are library names of the form: QT.A.qtx so check for these.
1140 if (Lib.size() >= 3) {
1141 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1143 Lib = Lib.slice(0, Lib.size()-2);
1148 // getLibraryShortNameByIndex() is used to get the short name of the library
1149 // for an undefined symbol in a linked Mach-O binary that was linked with the
1150 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1151 // It is passed the index (0 - based) of the library as translated from
1152 // GET_LIBRARY_ORDINAL (1 - based).
1153 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1154 StringRef &Res) const {
1155 if (Index >= Libraries.size())
1156 return object_error::parse_failed;
1158 // If the cache of LibrariesShortNames is not built up do that first for
1159 // all the Libraries.
1160 if (LibrariesShortNames.size() == 0) {
1161 for (unsigned i = 0; i < Libraries.size(); i++) {
1162 MachO::dylib_command D =
1163 getStruct<MachO::dylib_command>(this, Libraries[i]);
1164 if (D.dylib.name >= D.cmdsize)
1165 return object_error::parse_failed;
1166 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1167 StringRef Name = StringRef(P);
1168 if (D.dylib.name+Name.size() >= D.cmdsize)
1169 return object_error::parse_failed;
1172 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1173 if (shortName.empty())
1174 LibrariesShortNames.push_back(Name);
1176 LibrariesShortNames.push_back(shortName);
1180 Res = LibrariesShortNames[Index];
1181 return object_error::success;
1184 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1185 return getSymbolByIndex(0);
1188 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1191 return basic_symbol_iterator(SymbolRef(DRI, this));
1193 MachO::symtab_command Symtab = getSymtabLoadCommand();
1194 unsigned SymbolTableEntrySize = is64Bit() ?
1195 sizeof(MachO::nlist_64) :
1196 sizeof(MachO::nlist);
1197 unsigned Offset = Symtab.symoff +
1198 Symtab.nsyms * SymbolTableEntrySize;
1199 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1200 return basic_symbol_iterator(SymbolRef(DRI, this));
1203 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1208 MachO::symtab_command Symtab = getSymtabLoadCommand();
1209 if (Index >= Symtab.nsyms)
1210 report_fatal_error("Requested symbol index is out of range.");
1211 unsigned SymbolTableEntrySize =
1212 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1213 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1214 DRI.p += Index * SymbolTableEntrySize;
1215 return basic_symbol_iterator(SymbolRef(DRI, this));
1218 section_iterator MachOObjectFile::section_begin() const {
1220 return section_iterator(SectionRef(DRI, this));
1223 section_iterator MachOObjectFile::section_end() const {
1225 DRI.d.a = Sections.size();
1226 return section_iterator(SectionRef(DRI, this));
1229 uint8_t MachOObjectFile::getBytesInAddress() const {
1230 return is64Bit() ? 8 : 4;
1233 StringRef MachOObjectFile::getFileFormatName() const {
1234 unsigned CPUType = getCPUType(this);
1237 case llvm::MachO::CPU_TYPE_I386:
1238 return "Mach-O 32-bit i386";
1239 case llvm::MachO::CPU_TYPE_ARM:
1240 return "Mach-O arm";
1241 case llvm::MachO::CPU_TYPE_POWERPC:
1242 return "Mach-O 32-bit ppc";
1244 return "Mach-O 32-bit unknown";
1249 case llvm::MachO::CPU_TYPE_X86_64:
1250 return "Mach-O 64-bit x86-64";
1251 case llvm::MachO::CPU_TYPE_ARM64:
1252 return "Mach-O arm64";
1253 case llvm::MachO::CPU_TYPE_POWERPC64:
1254 return "Mach-O 64-bit ppc64";
1256 return "Mach-O 64-bit unknown";
1260 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1262 case llvm::MachO::CPU_TYPE_I386:
1264 case llvm::MachO::CPU_TYPE_X86_64:
1265 return Triple::x86_64;
1266 case llvm::MachO::CPU_TYPE_ARM:
1268 case llvm::MachO::CPU_TYPE_ARM64:
1269 return Triple::aarch64;
1270 case llvm::MachO::CPU_TYPE_POWERPC:
1272 case llvm::MachO::CPU_TYPE_POWERPC64:
1273 return Triple::ppc64;
1275 return Triple::UnknownArch;
1279 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1280 const char **McpuDefault) {
1282 *McpuDefault = nullptr;
1285 case MachO::CPU_TYPE_I386:
1286 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1287 case MachO::CPU_SUBTYPE_I386_ALL:
1288 return Triple("i386-apple-darwin");
1292 case MachO::CPU_TYPE_X86_64:
1293 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1294 case MachO::CPU_SUBTYPE_X86_64_ALL:
1295 return Triple("x86_64-apple-darwin");
1296 case MachO::CPU_SUBTYPE_X86_64_H:
1297 return Triple("x86_64h-apple-darwin");
1301 case MachO::CPU_TYPE_ARM:
1302 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1303 case MachO::CPU_SUBTYPE_ARM_V4T:
1304 return Triple("armv4t-apple-darwin");
1305 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1306 return Triple("armv5e-apple-darwin");
1307 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1308 return Triple("xscale-apple-darwin");
1309 case MachO::CPU_SUBTYPE_ARM_V6:
1310 return Triple("armv6-apple-darwin");
1311 case MachO::CPU_SUBTYPE_ARM_V6M:
1313 *McpuDefault = "cortex-m0";
1314 return Triple("armv6m-apple-darwin");
1315 case MachO::CPU_SUBTYPE_ARM_V7:
1316 return Triple("armv7-apple-darwin");
1317 case MachO::CPU_SUBTYPE_ARM_V7EM:
1319 *McpuDefault = "cortex-m4";
1320 return Triple("armv7em-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7K:
1322 return Triple("armv7k-apple-darwin");
1323 case MachO::CPU_SUBTYPE_ARM_V7M:
1325 *McpuDefault = "cortex-m3";
1326 return Triple("armv7m-apple-darwin");
1327 case MachO::CPU_SUBTYPE_ARM_V7S:
1328 return Triple("armv7s-apple-darwin");
1332 case MachO::CPU_TYPE_ARM64:
1333 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1334 case MachO::CPU_SUBTYPE_ARM64_ALL:
1335 return Triple("arm64-apple-darwin");
1339 case MachO::CPU_TYPE_POWERPC:
1340 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1341 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1342 return Triple("ppc-apple-darwin");
1346 case MachO::CPU_TYPE_POWERPC64:
1347 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1348 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1349 return Triple("ppc64-apple-darwin");
1358 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1359 const char **McpuDefault) {
1361 *McpuDefault = nullptr;
1364 case MachO::CPU_TYPE_ARM:
1365 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1366 case MachO::CPU_SUBTYPE_ARM_V4T:
1367 return Triple("thumbv4t-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1369 return Triple("thumbv5e-apple-darwin");
1370 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1371 return Triple("xscale-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V6:
1373 return Triple("thumbv6-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V6M:
1376 *McpuDefault = "cortex-m0";
1377 return Triple("thumbv6m-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7:
1379 return Triple("thumbv7-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V7EM:
1382 *McpuDefault = "cortex-m4";
1383 return Triple("thumbv7em-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7K:
1385 return Triple("thumbv7k-apple-darwin");
1386 case MachO::CPU_SUBTYPE_ARM_V7M:
1388 *McpuDefault = "cortex-m3";
1389 return Triple("thumbv7m-apple-darwin");
1390 case MachO::CPU_SUBTYPE_ARM_V7S:
1391 return Triple("thumbv7s-apple-darwin");
1400 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1401 const char **McpuDefault,
1402 Triple *ThumbTriple) {
1403 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1404 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1409 Triple MachOObjectFile::getHostArch() {
1410 return Triple(sys::getDefaultTargetTriple());
1413 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1414 return StringSwitch<bool>(ArchFlag)
1416 .Case("x86_64", true)
1417 .Case("x86_64h", true)
1418 .Case("armv4t", true)
1420 .Case("armv5e", true)
1421 .Case("armv6", true)
1422 .Case("armv6m", true)
1423 .Case("armv7em", true)
1424 .Case("armv7k", true)
1425 .Case("armv7m", true)
1426 .Case("armv7s", true)
1427 .Case("arm64", true)
1429 .Case("ppc64", true)
1433 unsigned MachOObjectFile::getArch() const {
1434 return getArch(getCPUType(this));
1437 Triple MachOObjectFile::getArch(const char **McpuDefault,
1438 Triple *ThumbTriple) const {
1441 MachO::mach_header_64 H_64;
1442 H_64 = getHeader64();
1443 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1447 MachO::mach_header H;
1449 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1450 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1456 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1459 return section_rel_begin(DRI);
1462 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1465 return section_rel_end(DRI);
1468 dice_iterator MachOObjectFile::begin_dices() const {
1470 if (!DataInCodeLoadCmd)
1471 return dice_iterator(DiceRef(DRI, this));
1473 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1474 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1475 return dice_iterator(DiceRef(DRI, this));
1478 dice_iterator MachOObjectFile::end_dices() const {
1480 if (!DataInCodeLoadCmd)
1481 return dice_iterator(DiceRef(DRI, this));
1483 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1484 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1485 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1486 return dice_iterator(DiceRef(DRI, this));
1489 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1490 : Trie(T), Malformed(false), Done(false) { }
1492 void ExportEntry::moveToFirst() {
1494 pushDownUntilBottom();
1497 void ExportEntry::moveToEnd() {
1502 bool ExportEntry::operator==(const ExportEntry &Other) const {
1503 // Common case, one at end, other iterating from begin.
1504 if (Done || Other.Done)
1505 return (Done == Other.Done);
1506 // Not equal if different stack sizes.
1507 if (Stack.size() != Other.Stack.size())
1509 // Not equal if different cumulative strings.
1510 if (!CumulativeString.equals(Other.CumulativeString))
1512 // Equal if all nodes in both stacks match.
1513 for (unsigned i=0; i < Stack.size(); ++i) {
1514 if (Stack[i].Start != Other.Stack[i].Start)
1520 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1522 uint64_t Result = decodeULEB128(Ptr, &Count);
1524 if (Ptr > Trie.end()) {
1531 StringRef ExportEntry::name() const {
1532 return CumulativeString;
1535 uint64_t ExportEntry::flags() const {
1536 return Stack.back().Flags;
1539 uint64_t ExportEntry::address() const {
1540 return Stack.back().Address;
1543 uint64_t ExportEntry::other() const {
1544 return Stack.back().Other;
1547 StringRef ExportEntry::otherName() const {
1548 const char* ImportName = Stack.back().ImportName;
1550 return StringRef(ImportName);
1554 uint32_t ExportEntry::nodeOffset() const {
1555 return Stack.back().Start - Trie.begin();
1558 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1559 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1560 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1561 ParentStringLength(0), IsExportNode(false) {
1564 void ExportEntry::pushNode(uint64_t offset) {
1565 const uint8_t *Ptr = Trie.begin() + offset;
1566 NodeState State(Ptr);
1567 uint64_t ExportInfoSize = readULEB128(State.Current);
1568 State.IsExportNode = (ExportInfoSize != 0);
1569 const uint8_t* Children = State.Current + ExportInfoSize;
1570 if (State.IsExportNode) {
1571 State.Flags = readULEB128(State.Current);
1572 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1574 State.Other = readULEB128(State.Current); // dylib ordinal
1575 State.ImportName = reinterpret_cast<const char*>(State.Current);
1577 State.Address = readULEB128(State.Current);
1578 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1579 State.Other = readULEB128(State.Current);
1582 State.ChildCount = *Children;
1583 State.Current = Children + 1;
1584 State.NextChildIndex = 0;
1585 State.ParentStringLength = CumulativeString.size();
1586 Stack.push_back(State);
1589 void ExportEntry::pushDownUntilBottom() {
1590 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1591 NodeState &Top = Stack.back();
1592 CumulativeString.resize(Top.ParentStringLength);
1593 for (;*Top.Current != 0; Top.Current++) {
1594 char C = *Top.Current;
1595 CumulativeString.push_back(C);
1598 uint64_t childNodeIndex = readULEB128(Top.Current);
1599 Top.NextChildIndex += 1;
1600 pushNode(childNodeIndex);
1602 if (!Stack.back().IsExportNode) {
1608 // We have a trie data structure and need a way to walk it that is compatible
1609 // with the C++ iterator model. The solution is a non-recursive depth first
1610 // traversal where the iterator contains a stack of parent nodes along with a
1611 // string that is the accumulation of all edge strings along the parent chain
1614 // There is one "export" node for each exported symbol. But because some
1615 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1616 // node may have child nodes too.
1618 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1619 // child until hitting a node with no children (which is an export node or
1620 // else the trie is malformed). On the way down, each node is pushed on the
1621 // stack ivar. If there is no more ways down, it pops up one and tries to go
1622 // down a sibling path until a childless node is reached.
1623 void ExportEntry::moveNext() {
1624 if (Stack.empty() || !Stack.back().IsExportNode) {
1631 while (!Stack.empty()) {
1632 NodeState &Top = Stack.back();
1633 if (Top.NextChildIndex < Top.ChildCount) {
1634 pushDownUntilBottom();
1635 // Now at the next export node.
1638 if (Top.IsExportNode) {
1639 // This node has no children but is itself an export node.
1640 CumulativeString.resize(Top.ParentStringLength);
1649 iterator_range<export_iterator>
1650 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1651 ExportEntry Start(Trie);
1652 if (Trie.size() == 0)
1655 Start.moveToFirst();
1657 ExportEntry Finish(Trie);
1660 return iterator_range<export_iterator>(export_iterator(Start),
1661 export_iterator(Finish));
1664 iterator_range<export_iterator> MachOObjectFile::exports() const {
1665 return exports(getDyldInfoExportsTrie());
1669 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1670 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1671 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1672 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1674 void MachORebaseEntry::moveToFirst() {
1675 Ptr = Opcodes.begin();
1679 void MachORebaseEntry::moveToEnd() {
1680 Ptr = Opcodes.end();
1681 RemainingLoopCount = 0;
1685 void MachORebaseEntry::moveNext() {
1686 // If in the middle of some loop, move to next rebasing in loop.
1687 SegmentOffset += AdvanceAmount;
1688 if (RemainingLoopCount) {
1689 --RemainingLoopCount;
1692 if (Ptr == Opcodes.end()) {
1697 while (More && !Malformed) {
1698 // Parse next opcode and set up next loop.
1699 uint8_t Byte = *Ptr++;
1700 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1701 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1703 case MachO::REBASE_OPCODE_DONE:
1707 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1709 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1710 RebaseType = ImmValue;
1713 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1714 << "RebaseType=" << (int) RebaseType << "\n");
1716 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1717 SegmentIndex = ImmValue;
1718 SegmentOffset = readULEB128();
1721 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1722 << "SegmentIndex=" << SegmentIndex << ", "
1723 << format("SegmentOffset=0x%06X", SegmentOffset)
1726 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1727 SegmentOffset += readULEB128();
1728 DEBUG_WITH_TYPE("mach-o-rebase",
1729 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1730 << format("SegmentOffset=0x%06X",
1731 SegmentOffset) << "\n");
1733 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1734 SegmentOffset += ImmValue * PointerSize;
1735 DEBUG_WITH_TYPE("mach-o-rebase",
1736 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1737 << format("SegmentOffset=0x%06X",
1738 SegmentOffset) << "\n");
1740 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1741 AdvanceAmount = PointerSize;
1742 RemainingLoopCount = ImmValue - 1;
1745 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1746 << format("SegmentOffset=0x%06X", SegmentOffset)
1747 << ", AdvanceAmount=" << AdvanceAmount
1748 << ", RemainingLoopCount=" << RemainingLoopCount
1751 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1752 AdvanceAmount = PointerSize;
1753 RemainingLoopCount = readULEB128() - 1;
1756 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1757 << format("SegmentOffset=0x%06X", SegmentOffset)
1758 << ", AdvanceAmount=" << AdvanceAmount
1759 << ", RemainingLoopCount=" << RemainingLoopCount
1762 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1763 AdvanceAmount = readULEB128() + PointerSize;
1764 RemainingLoopCount = 0;
1767 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1768 << format("SegmentOffset=0x%06X", SegmentOffset)
1769 << ", AdvanceAmount=" << AdvanceAmount
1770 << ", RemainingLoopCount=" << RemainingLoopCount
1773 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1774 RemainingLoopCount = readULEB128() - 1;
1775 AdvanceAmount = readULEB128() + PointerSize;
1778 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1779 << format("SegmentOffset=0x%06X", SegmentOffset)
1780 << ", AdvanceAmount=" << AdvanceAmount
1781 << ", RemainingLoopCount=" << RemainingLoopCount
1790 uint64_t MachORebaseEntry::readULEB128() {
1792 uint64_t Result = decodeULEB128(Ptr, &Count);
1794 if (Ptr > Opcodes.end()) {
1795 Ptr = Opcodes.end();
1801 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1803 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1805 StringRef MachORebaseEntry::typeName() const {
1806 switch (RebaseType) {
1807 case MachO::REBASE_TYPE_POINTER:
1809 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1810 return "text abs32";
1811 case MachO::REBASE_TYPE_TEXT_PCREL32:
1812 return "text rel32";
1817 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1818 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1819 return (Ptr == Other.Ptr) &&
1820 (RemainingLoopCount == Other.RemainingLoopCount) &&
1821 (Done == Other.Done);
1824 iterator_range<rebase_iterator>
1825 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1826 MachORebaseEntry Start(Opcodes, is64);
1827 Start.moveToFirst();
1829 MachORebaseEntry Finish(Opcodes, is64);
1832 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1833 rebase_iterator(Finish));
1836 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1837 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1841 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1843 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1844 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1845 BindType(0), PointerSize(is64Bit ? 8 : 4),
1846 TableKind(BK), Malformed(false), Done(false) {}
1848 void MachOBindEntry::moveToFirst() {
1849 Ptr = Opcodes.begin();
1853 void MachOBindEntry::moveToEnd() {
1854 Ptr = Opcodes.end();
1855 RemainingLoopCount = 0;
1859 void MachOBindEntry::moveNext() {
1860 // If in the middle of some loop, move to next binding in loop.
1861 SegmentOffset += AdvanceAmount;
1862 if (RemainingLoopCount) {
1863 --RemainingLoopCount;
1866 if (Ptr == Opcodes.end()) {
1871 while (More && !Malformed) {
1872 // Parse next opcode and set up next loop.
1873 uint8_t Byte = *Ptr++;
1874 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1875 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1876 int8_t SignExtended;
1877 const uint8_t *SymStart;
1879 case MachO::BIND_OPCODE_DONE:
1880 if (TableKind == Kind::Lazy) {
1881 // Lazying bindings have a DONE opcode between entries. Need to ignore
1882 // it to advance to next entry. But need not if this is last entry.
1883 bool NotLastEntry = false;
1884 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1886 NotLastEntry = true;
1895 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1897 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1901 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1902 << "Ordinal=" << Ordinal << "\n");
1904 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1905 Ordinal = readULEB128();
1908 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1909 << "Ordinal=" << Ordinal << "\n");
1911 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1913 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1914 Ordinal = SignExtended;
1919 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1920 << "Ordinal=" << Ordinal << "\n");
1922 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1928 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1933 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1934 << "SymbolName=" << SymbolName << "\n");
1935 if (TableKind == Kind::Weak) {
1936 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1940 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1941 BindType = ImmValue;
1944 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1945 << "BindType=" << (int)BindType << "\n");
1947 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1948 Addend = readSLEB128();
1949 if (TableKind == Kind::Lazy)
1953 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1954 << "Addend=" << Addend << "\n");
1956 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1957 SegmentIndex = ImmValue;
1958 SegmentOffset = readULEB128();
1961 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1962 << "SegmentIndex=" << SegmentIndex << ", "
1963 << format("SegmentOffset=0x%06X", SegmentOffset)
1966 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1967 SegmentOffset += readULEB128();
1968 DEBUG_WITH_TYPE("mach-o-bind",
1969 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1970 << format("SegmentOffset=0x%06X",
1971 SegmentOffset) << "\n");
1973 case MachO::BIND_OPCODE_DO_BIND:
1974 AdvanceAmount = PointerSize;
1975 RemainingLoopCount = 0;
1976 DEBUG_WITH_TYPE("mach-o-bind",
1977 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1978 << format("SegmentOffset=0x%06X",
1979 SegmentOffset) << "\n");
1981 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1982 AdvanceAmount = readULEB128() + PointerSize;
1983 RemainingLoopCount = 0;
1984 if (TableKind == Kind::Lazy)
1988 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1989 << format("SegmentOffset=0x%06X", SegmentOffset)
1990 << ", AdvanceAmount=" << AdvanceAmount
1991 << ", RemainingLoopCount=" << RemainingLoopCount
1994 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1995 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1996 RemainingLoopCount = 0;
1997 if (TableKind == Kind::Lazy)
1999 DEBUG_WITH_TYPE("mach-o-bind",
2001 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2002 << format("SegmentOffset=0x%06X",
2003 SegmentOffset) << "\n");
2005 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2006 RemainingLoopCount = readULEB128() - 1;
2007 AdvanceAmount = readULEB128() + PointerSize;
2008 if (TableKind == Kind::Lazy)
2012 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2013 << format("SegmentOffset=0x%06X", SegmentOffset)
2014 << ", AdvanceAmount=" << AdvanceAmount
2015 << ", RemainingLoopCount=" << RemainingLoopCount
2024 uint64_t MachOBindEntry::readULEB128() {
2026 uint64_t Result = decodeULEB128(Ptr, &Count);
2028 if (Ptr > Opcodes.end()) {
2029 Ptr = Opcodes.end();
2035 int64_t MachOBindEntry::readSLEB128() {
2037 int64_t Result = decodeSLEB128(Ptr, &Count);
2039 if (Ptr > Opcodes.end()) {
2040 Ptr = Opcodes.end();
2047 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2049 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2051 StringRef MachOBindEntry::typeName() const {
2053 case MachO::BIND_TYPE_POINTER:
2055 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2056 return "text abs32";
2057 case MachO::BIND_TYPE_TEXT_PCREL32:
2058 return "text rel32";
2063 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2065 int64_t MachOBindEntry::addend() const { return Addend; }
2067 uint32_t MachOBindEntry::flags() const { return Flags; }
2069 int MachOBindEntry::ordinal() const { return Ordinal; }
2071 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2072 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2073 return (Ptr == Other.Ptr) &&
2074 (RemainingLoopCount == Other.RemainingLoopCount) &&
2075 (Done == Other.Done);
2078 iterator_range<bind_iterator>
2079 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2080 MachOBindEntry::Kind BKind) {
2081 MachOBindEntry Start(Opcodes, is64, BKind);
2082 Start.moveToFirst();
2084 MachOBindEntry Finish(Opcodes, is64, BKind);
2087 return iterator_range<bind_iterator>(bind_iterator(Start),
2088 bind_iterator(Finish));
2091 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2092 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2093 MachOBindEntry::Kind::Regular);
2096 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2097 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2098 MachOBindEntry::Kind::Lazy);
2101 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2102 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2103 MachOBindEntry::Kind::Weak);
2107 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2108 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2109 return parseSegmentOrSectionName(Raw.data());
2113 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2114 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
2115 const section_base *Base =
2116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2117 return makeArrayRef(Base->sectname);
2121 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2122 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
2123 const section_base *Base =
2124 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2125 return makeArrayRef(Base->segname);
2129 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2131 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2133 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2136 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2137 const MachO::any_relocation_info &RE) const {
2138 if (isLittleEndian())
2139 return RE.r_word1 & 0xffffff;
2140 return RE.r_word1 >> 8;
2143 bool MachOObjectFile::getPlainRelocationExternal(
2144 const MachO::any_relocation_info &RE) const {
2145 if (isLittleEndian())
2146 return (RE.r_word1 >> 27) & 1;
2147 return (RE.r_word1 >> 4) & 1;
2150 bool MachOObjectFile::getScatteredRelocationScattered(
2151 const MachO::any_relocation_info &RE) const {
2152 return RE.r_word0 >> 31;
2155 uint32_t MachOObjectFile::getScatteredRelocationValue(
2156 const MachO::any_relocation_info &RE) const {
2160 uint32_t MachOObjectFile::getScatteredRelocationType(
2161 const MachO::any_relocation_info &RE) const {
2162 return (RE.r_word0 >> 24) & 0xf;
2165 unsigned MachOObjectFile::getAnyRelocationAddress(
2166 const MachO::any_relocation_info &RE) const {
2167 if (isRelocationScattered(RE))
2168 return getScatteredRelocationAddress(RE);
2169 return getPlainRelocationAddress(RE);
2172 unsigned MachOObjectFile::getAnyRelocationPCRel(
2173 const MachO::any_relocation_info &RE) const {
2174 if (isRelocationScattered(RE))
2175 return getScatteredRelocationPCRel(this, RE);
2176 return getPlainRelocationPCRel(this, RE);
2179 unsigned MachOObjectFile::getAnyRelocationLength(
2180 const MachO::any_relocation_info &RE) const {
2181 if (isRelocationScattered(RE))
2182 return getScatteredRelocationLength(RE);
2183 return getPlainRelocationLength(this, RE);
2187 MachOObjectFile::getAnyRelocationType(
2188 const MachO::any_relocation_info &RE) const {
2189 if (isRelocationScattered(RE))
2190 return getScatteredRelocationType(RE);
2191 return getPlainRelocationType(this, RE);
2195 MachOObjectFile::getAnyRelocationSection(
2196 const MachO::any_relocation_info &RE) const {
2197 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2198 return *section_end();
2199 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2202 return SectionRef(DRI, this);
2205 MachOObjectFile::LoadCommandInfo
2206 MachOObjectFile::getFirstLoadCommandInfo() const {
2207 MachOObjectFile::LoadCommandInfo Load;
2209 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2210 sizeof(MachO::mach_header);
2211 Load.Ptr = getPtr(this, HeaderSize);
2212 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2213 if (Load.C.cmdsize < 8)
2214 report_fatal_error("Load command with size < 8 bytes.");
2218 MachOObjectFile::LoadCommandInfo
2219 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2220 MachOObjectFile::LoadCommandInfo Next;
2221 Next.Ptr = L.Ptr + L.C.cmdsize;
2222 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2223 if (Next.C.cmdsize < 8)
2224 report_fatal_error("Load command with size < 8 bytes.");
2228 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2229 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2230 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2233 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2234 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
2235 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2238 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2239 unsigned Index) const {
2240 const char *Sec = getSectionPtr(this, L, Index);
2241 return getStruct<MachO::section>(this, Sec);
2244 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2245 unsigned Index) const {
2246 const char *Sec = getSectionPtr(this, L, Index);
2247 return getStruct<MachO::section_64>(this, Sec);
2251 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2252 const char *P = reinterpret_cast<const char *>(DRI.p);
2253 return getStruct<MachO::nlist>(this, P);
2257 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2258 const char *P = reinterpret_cast<const char *>(DRI.p);
2259 return getStruct<MachO::nlist_64>(this, P);
2262 MachO::linkedit_data_command
2263 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2264 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2267 MachO::segment_command
2268 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2269 return getStruct<MachO::segment_command>(this, L.Ptr);
2272 MachO::segment_command_64
2273 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2274 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2277 MachO::linker_option_command
2278 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2282 MachO::version_min_command
2283 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::version_min_command>(this, L.Ptr);
2287 MachO::dylib_command
2288 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::dylib_command>(this, L.Ptr);
2292 MachO::dyld_info_command
2293 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2297 MachO::dylinker_command
2298 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2303 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2304 return getStruct<MachO::uuid_command>(this, L.Ptr);
2307 MachO::rpath_command
2308 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2309 return getStruct<MachO::rpath_command>(this, L.Ptr);
2312 MachO::source_version_command
2313 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2314 return getStruct<MachO::source_version_command>(this, L.Ptr);
2317 MachO::entry_point_command
2318 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2319 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2322 MachO::encryption_info_command
2323 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2324 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2327 MachO::encryption_info_command_64
2328 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2329 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2332 MachO::sub_framework_command
2333 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2334 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2337 MachO::sub_umbrella_command
2338 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2339 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2342 MachO::sub_library_command
2343 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2344 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2347 MachO::sub_client_command
2348 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2349 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2352 MachO::routines_command
2353 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2354 return getStruct<MachO::routines_command>(this, L.Ptr);
2357 MachO::routines_command_64
2358 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2359 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2362 MachO::thread_command
2363 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2364 return getStruct<MachO::thread_command>(this, L.Ptr);
2367 MachO::any_relocation_info
2368 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2373 MachO::section_64 Sect = getSection64(Sec);
2374 Offset = Sect.reloff;
2376 MachO::section Sect = getSection(Sec);
2377 Offset = Sect.reloff;
2380 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2381 getPtr(this, Offset)) + Rel.d.b;
2382 return getStruct<MachO::any_relocation_info>(
2383 this, reinterpret_cast<const char *>(P));
2386 MachO::data_in_code_entry
2387 MachOObjectFile::getDice(DataRefImpl Rel) const {
2388 const char *P = reinterpret_cast<const char *>(Rel.p);
2389 return getStruct<MachO::data_in_code_entry>(this, P);
2392 MachO::mach_header MachOObjectFile::getHeader() const {
2393 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2396 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2397 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2400 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2401 const MachO::dysymtab_command &DLC,
2402 unsigned Index) const {
2403 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2404 return getStruct<uint32_t>(this, getPtr(this, Offset));
2407 MachO::data_in_code_entry
2408 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2409 unsigned Index) const {
2410 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2411 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2414 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2416 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2418 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2419 MachO::symtab_command Cmd;
2420 Cmd.cmd = MachO::LC_SYMTAB;
2421 Cmd.cmdsize = sizeof(MachO::symtab_command);
2429 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2430 if (DysymtabLoadCmd)
2431 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2433 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2434 MachO::dysymtab_command Cmd;
2435 Cmd.cmd = MachO::LC_DYSYMTAB;
2436 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2447 Cmd.extrefsymoff = 0;
2448 Cmd.nextrefsyms = 0;
2449 Cmd.indirectsymoff = 0;
2450 Cmd.nindirectsyms = 0;
2458 MachO::linkedit_data_command
2459 MachOObjectFile::getDataInCodeLoadCommand() const {
2460 if (DataInCodeLoadCmd)
2461 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2463 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2464 MachO::linkedit_data_command Cmd;
2465 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2466 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2472 MachO::linkedit_data_command
2473 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2474 if (LinkOptHintsLoadCmd)
2475 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2477 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2479 MachO::linkedit_data_command Cmd;
2480 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2481 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2487 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2488 if (!DyldInfoLoadCmd)
2489 return ArrayRef<uint8_t>();
2491 MachO::dyld_info_command DyldInfo
2492 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2493 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2494 getPtr(this, DyldInfo.rebase_off));
2495 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2498 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2499 if (!DyldInfoLoadCmd)
2500 return ArrayRef<uint8_t>();
2502 MachO::dyld_info_command DyldInfo
2503 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2504 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2505 getPtr(this, DyldInfo.bind_off));
2506 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2509 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2510 if (!DyldInfoLoadCmd)
2511 return ArrayRef<uint8_t>();
2513 MachO::dyld_info_command DyldInfo
2514 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2515 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2516 getPtr(this, DyldInfo.weak_bind_off));
2517 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2520 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2521 if (!DyldInfoLoadCmd)
2522 return ArrayRef<uint8_t>();
2524 MachO::dyld_info_command DyldInfo
2525 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2526 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2527 getPtr(this, DyldInfo.lazy_bind_off));
2528 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2531 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2532 if (!DyldInfoLoadCmd)
2533 return ArrayRef<uint8_t>();
2535 MachO::dyld_info_command DyldInfo
2536 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2537 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2538 getPtr(this, DyldInfo.export_off));
2539 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2542 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2544 return ArrayRef<uint8_t>();
2545 // Returning a pointer is fine as uuid doesn't need endian swapping.
2546 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2547 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2550 StringRef MachOObjectFile::getStringTableData() const {
2551 MachO::symtab_command S = getSymtabLoadCommand();
2552 return getData().substr(S.stroff, S.strsize);
2555 bool MachOObjectFile::is64Bit() const {
2556 return getType() == getMachOType(false, true) ||
2557 getType() == getMachOType(true, true);
2560 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2561 SmallVectorImpl<uint64_t> &Out) const {
2562 DataExtractor extractor(ObjectFile::getData(), true, 0);
2564 uint32_t offset = Index;
2566 while (uint64_t delta = extractor.getULEB128(&offset)) {
2568 Out.push_back(data);
2572 bool MachOObjectFile::isRelocatableObject() const {
2573 return getHeader().filetype == MachO::MH_OBJECT;
2576 ErrorOr<std::unique_ptr<MachOObjectFile>>
2577 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2578 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2580 std::unique_ptr<MachOObjectFile> Ret;
2581 if (Magic == "\xFE\xED\xFA\xCE")
2582 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2583 else if (Magic == "\xCE\xFA\xED\xFE")
2584 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2585 else if (Magic == "\xFE\xED\xFA\xCF")
2586 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2587 else if (Magic == "\xCF\xFA\xED\xFE")
2588 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2590 return object_error::parse_failed;
2594 return std::move(Ret);