1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
42 static T getStruct(const MachOObjectFile *O, const char *P) {
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
46 MachO::swapStruct(Cmd);
51 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
54 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
57 MachO::segment_command S = O->getSegmentLoadCommand(L);
61 static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
73 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
75 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
77 bool Is64 = O->is64Bit();
78 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
84 return reinterpret_cast<const char*>(SectionAddr);
87 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
91 static MachO::nlist_base
92 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
93 const char *P = reinterpret_cast<const char *>(DRI.p);
94 return getStruct<MachO::nlist_base>(O, P);
97 static StringRef parseSegmentOrSectionName(const char *P) {
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
105 // Helper to advance a section or symbol iterator multiple increments at a time.
107 static void advance(T &it, size_t Val) {
112 static unsigned getCPUType(const MachOObjectFile *O) {
113 return O->getHeader().cputype;
116 static void printRelocationTargetName(const MachOObjectFile *O,
117 const MachO::any_relocation_info &RE,
118 raw_string_ostream &fmt) {
119 bool IsScattered = O->isRelocationScattered(RE);
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
128 for (const SymbolRef &Symbol : O->symbols()) {
133 if ((ec = Symbol.getAddress(Addr)))
134 report_fatal_error(ec.message());
137 if ((ec = Symbol.getName(Name)))
138 report_fatal_error(ec.message());
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
145 for (const SectionRef &Section : O->sections()) {
149 uint64_t Addr = Section.getAddress();
152 if ((ec = Section.getName(Name)))
153 report_fatal_error(ec.message());
158 fmt << format("0x%x", Val);
163 bool isExtern = O->getPlainRelocationExternal(RE);
164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
167 symbol_iterator SI = O->symbol_begin();
171 section_iterator SI = O->section_begin();
172 // Adjust for the fact that sections are 1-indexed.
173 advance(SI, Val - 1);
181 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
186 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
190 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
191 const MachO::any_relocation_info &RE) {
192 if (O->isLittleEndian())
193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
198 getScatteredRelocationPCRel(const MachOObjectFile *O,
199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
203 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
211 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
215 static unsigned getPlainRelocationType(const MachOObjectFile *O,
216 const MachO::any_relocation_info &RE) {
217 if (O->isLittleEndian())
218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
222 static uint32_t getSectionFlags(const MachOObjectFile *O,
225 MachO::section_64 Sect = O->getSection64(Sec);
228 MachO::section Sect = O->getSection(Sec);
232 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
236 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 if (LoadCommandCount == 0)
242 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
243 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
245 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
246 for (unsigned I = 0; ; ++I) {
247 if (Load.C.cmd == MachO::LC_SYMTAB) {
248 // Multiple symbol tables
250 EC = object_error::parse_failed;
253 SymtabLoadCmd = Load.Ptr;
254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
255 // Multiple dynamic symbol tables
256 if (DysymtabLoadCmd) {
257 EC = object_error::parse_failed;
260 DysymtabLoadCmd = Load.Ptr;
261 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
262 // Multiple data in code tables
263 if (DataInCodeLoadCmd) {
264 EC = object_error::parse_failed;
267 DataInCodeLoadCmd = Load.Ptr;
268 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
269 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
270 // Multiple dyldinfo load commands
271 if (DyldInfoLoadCmd) {
272 EC = object_error::parse_failed;
275 DyldInfoLoadCmd = Load.Ptr;
276 } else if (Load.C.cmd == MachO::LC_UUID) {
277 // Multiple UUID load commands
279 EC = object_error::parse_failed;
282 UuidLoadCmd = Load.Ptr;
283 } else if (Load.C.cmd == SegmentLoadType) {
284 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
285 for (unsigned J = 0; J < NumSections; ++J) {
286 const char *Sec = getSectionPtr(this, Load, J);
287 Sections.push_back(Sec);
289 if (isPageZeroSegment(this, Load))
290 HasPageZeroSegment = true;
291 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
293 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
294 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
295 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
296 Libraries.push_back(Load.Ptr);
299 if (I == LoadCommandCount - 1)
302 Load = getNextLoadCommandInfo(Load);
306 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
307 unsigned SymbolTableEntrySize = is64Bit() ?
308 sizeof(MachO::nlist_64) :
309 sizeof(MachO::nlist);
310 Symb.p += SymbolTableEntrySize;
313 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
314 StringRef &Res) const {
315 StringRef StringTable = getStringTableData();
316 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
317 const char *Start = &StringTable.data()[Entry.n_strx];
318 Res = StringRef(Start);
319 return object_error::success;
322 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
323 DataRefImpl DRI = Sec.getRawDataRefImpl();
324 uint32_t Flags = getSectionFlags(this, DRI);
325 return Flags & MachO::SECTION_TYPE;
328 // getIndirectName() returns the name of the alias'ed symbol who's string table
329 // index is in the n_value field.
330 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
331 StringRef &Res) const {
332 StringRef StringTable = getStringTableData();
335 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
336 NValue = Entry.n_value;
337 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
338 return object_error::parse_failed;
340 MachO::nlist Entry = getSymbolTableEntry(Symb);
341 NValue = Entry.n_value;
342 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
343 return object_error::parse_failed;
345 if (NValue >= StringTable.size())
346 return object_error::parse_failed;
347 const char *Start = &StringTable.data()[NValue];
348 Res = StringRef(Start);
349 return object_error::success;
352 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
353 uint64_t &Res) const {
355 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
356 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
358 Res = UnknownAddressOrSize;
362 MachO::nlist Entry = getSymbolTableEntry(Symb);
363 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
365 Res = UnknownAddressOrSize;
369 return object_error::success;
372 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
373 uint32_t &Result) const {
374 uint32_t flags = getSymbolFlags(DRI);
375 if (flags & SymbolRef::SF_Common) {
376 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
377 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
381 return object_error::success;
384 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
385 uint64_t &Result) const {
386 uint64_t BeginOffset;
387 uint64_t EndOffset = 0;
388 uint8_t SectionIndex;
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
392 getSymbolAddress(DRI, Value);
393 if (Value == UnknownAddressOrSize) {
394 Result = UnknownAddressOrSize;
395 return object_error::success;
400 SectionIndex = Entry.n_sect;
402 uint32_t flags = getSymbolFlags(DRI);
403 if (flags & SymbolRef::SF_Common)
406 Result = UnknownAddressOrSize;
407 return object_error::success;
409 // Unfortunately symbols are unsorted so we need to touch all
410 // symbols from load command
411 for (const SymbolRef &Symbol : symbols()) {
412 DataRefImpl DRI = Symbol.getRawDataRefImpl();
413 Entry = getSymbolTableEntryBase(this, DRI);
414 getSymbolAddress(DRI, Value);
415 if (Value == UnknownAddressOrSize)
417 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
418 if (!EndOffset || Value < EndOffset)
423 Sec.d.a = SectionIndex-1;
424 uint64_t Size = getSectionSize(Sec);
425 EndOffset = getSectionAddress(Sec);
428 Result = EndOffset - BeginOffset;
429 return object_error::success;
432 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
433 SymbolRef::Type &Res) const {
434 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
435 uint8_t n_type = Entry.n_type;
437 Res = SymbolRef::ST_Other;
439 // If this is a STAB debugging symbol, we can do nothing more.
440 if (n_type & MachO::N_STAB) {
441 Res = SymbolRef::ST_Debug;
442 return object_error::success;
445 switch (n_type & MachO::N_TYPE) {
447 Res = SymbolRef::ST_Unknown;
450 Res = SymbolRef::ST_Function;
453 return object_error::success;
456 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
459 uint8_t MachOType = Entry.n_type;
460 uint16_t MachOFlags = Entry.n_desc;
462 uint32_t Result = SymbolRef::SF_None;
464 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
465 Result |= SymbolRef::SF_Undefined;
467 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
468 Result |= SymbolRef::SF_Indirect;
470 if (MachOType & MachO::N_STAB)
471 Result |= SymbolRef::SF_FormatSpecific;
473 if (MachOType & MachO::N_EXT) {
474 Result |= SymbolRef::SF_Global;
475 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
477 getSymbolAddress(DRI, Value);
478 if (Value && Value != UnknownAddressOrSize)
479 Result |= SymbolRef::SF_Common;
483 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
484 Result |= SymbolRef::SF_Weak;
486 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
487 Result |= SymbolRef::SF_Thumb;
489 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
490 Result |= SymbolRef::SF_Absolute;
495 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
496 section_iterator &Res) const {
497 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
498 uint8_t index = Entry.n_sect;
505 Res = section_iterator(SectionRef(DRI, this));
508 return object_error::success;
511 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
515 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
516 StringRef &Result) const {
517 ArrayRef<char> Raw = getSectionRawName(Sec);
518 Result = parseSegmentOrSectionName(Raw.data());
519 return object_error::success;
522 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
524 return getSection64(Sec).addr;
525 return getSection(Sec).addr;
528 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
530 return getSection64(Sec).size;
531 return getSection(Sec).size;
534 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
535 StringRef &Res) const {
540 MachO::section_64 Sect = getSection64(Sec);
541 Offset = Sect.offset;
544 MachO::section Sect = getSection(Sec);
545 Offset = Sect.offset;
549 Res = this->getData().substr(Offset, Size);
550 return object_error::success;
553 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
556 MachO::section_64 Sect = getSection64(Sec);
559 MachO::section Sect = getSection(Sec);
563 return uint64_t(1) << Align;
566 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
567 uint32_t Flags = getSectionFlags(this, Sec);
568 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
571 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
572 uint32_t Flags = getSectionFlags(this, Sec);
573 unsigned SectionType = Flags & MachO::SECTION_TYPE;
574 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
575 !(SectionType == MachO::S_ZEROFILL ||
576 SectionType == MachO::S_GB_ZEROFILL);
579 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
580 uint32_t Flags = getSectionFlags(this, Sec);
581 unsigned SectionType = Flags & MachO::SECTION_TYPE;
582 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
583 (SectionType == MachO::S_ZEROFILL ||
584 SectionType == MachO::S_GB_ZEROFILL);
587 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
588 // FIXME: Unimplemented.
592 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
593 DataRefImpl Symb) const {
595 this->getSymbolType(Symb, ST);
596 if (ST == SymbolRef::ST_Unknown)
599 uint64_t SectBegin = getSectionAddress(Sec);
600 uint64_t SectEnd = getSectionSize(Sec);
601 SectEnd += SectBegin;
604 getSymbolAddress(Symb, SymAddr);
605 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
608 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
612 return relocation_iterator(RelocationRef(Ret, this));
616 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
619 MachO::section_64 Sect = getSection64(Sec);
622 MachO::section Sect = getSection(Sec);
629 return relocation_iterator(RelocationRef(Ret, this));
632 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
636 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
637 uint64_t &Res) const {
639 getRelocationOffset(Rel, Offset);
643 uint64_t SecAddress = getSectionAddress(Sec);
644 Res = SecAddress + Offset;
645 return object_error::success;
648 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
649 uint64_t &Res) const {
650 assert(getHeader().filetype == MachO::MH_OBJECT &&
651 "Only implemented for MH_OBJECT");
652 MachO::any_relocation_info RE = getRelocation(Rel);
653 Res = getAnyRelocationAddress(RE);
654 return object_error::success;
658 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
659 MachO::any_relocation_info RE = getRelocation(Rel);
660 if (isRelocationScattered(RE))
663 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
664 bool isExtern = getPlainRelocationExternal(RE);
668 MachO::symtab_command S = getSymtabLoadCommand();
669 unsigned SymbolTableEntrySize = is64Bit() ?
670 sizeof(MachO::nlist_64) :
671 sizeof(MachO::nlist);
672 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
674 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
675 return symbol_iterator(SymbolRef(Sym, this));
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;
1002 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1003 // guess on what the short name is. Then name is returned as a substring of the
1004 // StringRef Name passed in. The name of the dynamic library is recognized as
1005 // a framework if it has one of the two following forms:
1006 // Foo.framework/Versions/A/Foo
1007 // Foo.framework/Foo
1008 // Where A and Foo can be any string. And may contain a trailing suffix
1009 // starting with an underbar. If the Name is recognized as a framework then
1010 // isFramework is set to true else it is set to false. If the Name has a
1011 // suffix then Suffix is set to the substring in Name that contains the suffix
1012 // else it is set to a NULL StringRef.
1014 // The Name of the dynamic library is recognized as a library name if it has
1015 // one of the two following forms:
1018 // The library may have a suffix trailing the name Foo of the form:
1019 // libFoo_profile.A.dylib
1020 // libFoo_profile.dylib
1022 // The Name of the dynamic library is also recognized as a library name if it
1023 // has the following form:
1026 // If the Name of the dynamic library is none of the forms above then a NULL
1027 // StringRef is returned.
1029 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1031 StringRef &Suffix) {
1032 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1033 size_t a, b, c, d, Idx;
1035 isFramework = false;
1036 Suffix = StringRef();
1038 // Pull off the last component and make Foo point to it
1039 a = Name.rfind('/');
1040 if (a == Name.npos || a == 0)
1042 Foo = Name.slice(a+1, Name.npos);
1044 // Look for a suffix starting with a '_'
1045 Idx = Foo.rfind('_');
1046 if (Idx != Foo.npos && Foo.size() >= 2) {
1047 Suffix = Foo.slice(Idx, Foo.npos);
1048 Foo = Foo.slice(0, Idx);
1051 // First look for the form Foo.framework/Foo
1052 b = Name.rfind('/', a);
1057 F = Name.slice(Idx, Idx + Foo.size());
1058 DotFramework = Name.slice(Idx + Foo.size(),
1059 Idx + Foo.size() + sizeof(".framework/")-1);
1060 if (F == Foo && DotFramework == ".framework/") {
1065 // Next look for the form Foo.framework/Versions/A/Foo
1068 c = Name.rfind('/', b);
1069 if (c == Name.npos || c == 0)
1071 V = Name.slice(c+1, Name.npos);
1072 if (!V.startswith("Versions/"))
1074 d = Name.rfind('/', c);
1079 F = Name.slice(Idx, Idx + Foo.size());
1080 DotFramework = Name.slice(Idx + Foo.size(),
1081 Idx + Foo.size() + sizeof(".framework/")-1);
1082 if (F == Foo && DotFramework == ".framework/") {
1088 // pull off the suffix after the "." and make a point to it
1089 a = Name.rfind('.');
1090 if (a == Name.npos || a == 0)
1092 Dylib = Name.slice(a, Name.npos);
1093 if (Dylib != ".dylib")
1096 // First pull off the version letter for the form Foo.A.dylib if any.
1098 Dot = Name.slice(a-2, a-1);
1103 b = Name.rfind('/', a);
1108 // ignore any suffix after an underbar like Foo_profile.A.dylib
1109 Idx = Name.find('_', b);
1110 if (Idx != Name.npos && Idx != b) {
1111 Lib = Name.slice(b, Idx);
1112 Suffix = Name.slice(Idx, a);
1115 Lib = Name.slice(b, a);
1116 // There are incorrect library names of the form:
1117 // libATS.A_profile.dylib so check for these.
1118 if (Lib.size() >= 3) {
1119 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1121 Lib = Lib.slice(0, Lib.size()-2);
1126 Qtx = Name.slice(a, Name.npos);
1129 b = Name.rfind('/', a);
1131 Lib = Name.slice(0, a);
1133 Lib = Name.slice(b+1, a);
1134 // There are library names of the form: QT.A.qtx so check for these.
1135 if (Lib.size() >= 3) {
1136 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1138 Lib = Lib.slice(0, Lib.size()-2);
1143 // getLibraryShortNameByIndex() is used to get the short name of the library
1144 // for an undefined symbol in a linked Mach-O binary that was linked with the
1145 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1146 // It is passed the index (0 - based) of the library as translated from
1147 // GET_LIBRARY_ORDINAL (1 - based).
1148 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1149 StringRef &Res) const {
1150 if (Index >= Libraries.size())
1151 return object_error::parse_failed;
1153 // If the cache of LibrariesShortNames is not built up do that first for
1154 // all the Libraries.
1155 if (LibrariesShortNames.size() == 0) {
1156 for (unsigned i = 0; i < Libraries.size(); i++) {
1157 MachO::dylib_command D =
1158 getStruct<MachO::dylib_command>(this, Libraries[i]);
1159 if (D.dylib.name >= D.cmdsize)
1160 return object_error::parse_failed;
1161 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1162 StringRef Name = StringRef(P);
1163 if (D.dylib.name+Name.size() >= D.cmdsize)
1164 return object_error::parse_failed;
1167 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1168 if (shortName.empty())
1169 LibrariesShortNames.push_back(Name);
1171 LibrariesShortNames.push_back(shortName);
1175 Res = LibrariesShortNames[Index];
1176 return object_error::success;
1179 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1180 return getSymbolByIndex(0);
1183 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1186 return basic_symbol_iterator(SymbolRef(DRI, this));
1188 MachO::symtab_command Symtab = getSymtabLoadCommand();
1189 unsigned SymbolTableEntrySize = is64Bit() ?
1190 sizeof(MachO::nlist_64) :
1191 sizeof(MachO::nlist);
1192 unsigned Offset = Symtab.symoff +
1193 Symtab.nsyms * SymbolTableEntrySize;
1194 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1195 return basic_symbol_iterator(SymbolRef(DRI, this));
1198 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1201 return basic_symbol_iterator(SymbolRef(DRI, this));
1203 MachO::symtab_command Symtab = getSymtabLoadCommand();
1204 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1205 unsigned SymbolTableEntrySize =
1206 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1208 DRI.p += Index * SymbolTableEntrySize;
1209 return basic_symbol_iterator(SymbolRef(DRI, this));
1212 section_iterator MachOObjectFile::section_begin() const {
1214 return section_iterator(SectionRef(DRI, this));
1217 section_iterator MachOObjectFile::section_end() const {
1219 DRI.d.a = Sections.size();
1220 return section_iterator(SectionRef(DRI, this));
1223 uint8_t MachOObjectFile::getBytesInAddress() const {
1224 return is64Bit() ? 8 : 4;
1227 StringRef MachOObjectFile::getFileFormatName() const {
1228 unsigned CPUType = getCPUType(this);
1231 case llvm::MachO::CPU_TYPE_I386:
1232 return "Mach-O 32-bit i386";
1233 case llvm::MachO::CPU_TYPE_ARM:
1234 return "Mach-O arm";
1235 case llvm::MachO::CPU_TYPE_POWERPC:
1236 return "Mach-O 32-bit ppc";
1238 return "Mach-O 32-bit unknown";
1243 case llvm::MachO::CPU_TYPE_X86_64:
1244 return "Mach-O 64-bit x86-64";
1245 case llvm::MachO::CPU_TYPE_ARM64:
1246 return "Mach-O arm64";
1247 case llvm::MachO::CPU_TYPE_POWERPC64:
1248 return "Mach-O 64-bit ppc64";
1250 return "Mach-O 64-bit unknown";
1254 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1256 case llvm::MachO::CPU_TYPE_I386:
1258 case llvm::MachO::CPU_TYPE_X86_64:
1259 return Triple::x86_64;
1260 case llvm::MachO::CPU_TYPE_ARM:
1262 case llvm::MachO::CPU_TYPE_ARM64:
1263 return Triple::aarch64;
1264 case llvm::MachO::CPU_TYPE_POWERPC:
1266 case llvm::MachO::CPU_TYPE_POWERPC64:
1267 return Triple::ppc64;
1269 return Triple::UnknownArch;
1273 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1274 const char **McpuDefault) {
1276 *McpuDefault = nullptr;
1279 case MachO::CPU_TYPE_I386:
1280 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1281 case MachO::CPU_SUBTYPE_I386_ALL:
1282 return Triple("i386-apple-darwin");
1286 case MachO::CPU_TYPE_X86_64:
1287 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1288 case MachO::CPU_SUBTYPE_X86_64_ALL:
1289 return Triple("x86_64-apple-darwin");
1290 case MachO::CPU_SUBTYPE_X86_64_H:
1291 return Triple("x86_64h-apple-darwin");
1295 case MachO::CPU_TYPE_ARM:
1296 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1297 case MachO::CPU_SUBTYPE_ARM_V4T:
1298 return Triple("armv4t-apple-darwin");
1299 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1300 return Triple("armv5e-apple-darwin");
1301 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1302 return Triple("xscale-apple-darwin");
1303 case MachO::CPU_SUBTYPE_ARM_V6:
1304 return Triple("armv6-apple-darwin");
1305 case MachO::CPU_SUBTYPE_ARM_V6M:
1307 *McpuDefault = "cortex-m0";
1308 return Triple("armv6m-apple-darwin");
1309 case MachO::CPU_SUBTYPE_ARM_V7:
1310 return Triple("armv7-apple-darwin");
1311 case MachO::CPU_SUBTYPE_ARM_V7EM:
1313 *McpuDefault = "cortex-m4";
1314 return Triple("armv7em-apple-darwin");
1315 case MachO::CPU_SUBTYPE_ARM_V7K:
1316 return Triple("armv7k-apple-darwin");
1317 case MachO::CPU_SUBTYPE_ARM_V7M:
1319 *McpuDefault = "cortex-m3";
1320 return Triple("armv7m-apple-darwin");
1321 case MachO::CPU_SUBTYPE_ARM_V7S:
1322 return Triple("armv7s-apple-darwin");
1326 case MachO::CPU_TYPE_ARM64:
1327 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1328 case MachO::CPU_SUBTYPE_ARM64_ALL:
1329 return Triple("arm64-apple-darwin");
1333 case MachO::CPU_TYPE_POWERPC:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1336 return Triple("ppc-apple-darwin");
1340 case MachO::CPU_TYPE_POWERPC64:
1341 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1342 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1343 return Triple("ppc64-apple-darwin");
1352 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1353 const char **McpuDefault) {
1355 *McpuDefault = nullptr;
1358 case MachO::CPU_TYPE_ARM:
1359 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1360 case MachO::CPU_SUBTYPE_ARM_V4T:
1361 return Triple("thumbv4t-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1363 return Triple("thumbv5e-apple-darwin");
1364 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1365 return Triple("xscale-apple-darwin");
1366 case MachO::CPU_SUBTYPE_ARM_V6:
1367 return Triple("thumbv6-apple-darwin");
1368 case MachO::CPU_SUBTYPE_ARM_V6M:
1370 *McpuDefault = "cortex-m0";
1371 return Triple("thumbv6m-apple-darwin");
1372 case MachO::CPU_SUBTYPE_ARM_V7:
1373 return Triple("thumbv7-apple-darwin");
1374 case MachO::CPU_SUBTYPE_ARM_V7EM:
1376 *McpuDefault = "cortex-m4";
1377 return Triple("thumbv7em-apple-darwin");
1378 case MachO::CPU_SUBTYPE_ARM_V7K:
1379 return Triple("thumbv7k-apple-darwin");
1380 case MachO::CPU_SUBTYPE_ARM_V7M:
1382 *McpuDefault = "cortex-m3";
1383 return Triple("thumbv7m-apple-darwin");
1384 case MachO::CPU_SUBTYPE_ARM_V7S:
1385 return Triple("thumbv7s-apple-darwin");
1394 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1395 const char **McpuDefault,
1396 Triple *ThumbTriple) {
1397 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1398 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1403 Triple MachOObjectFile::getHostArch() {
1404 return Triple(sys::getDefaultTargetTriple());
1407 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1408 return StringSwitch<bool>(ArchFlag)
1410 .Case("x86_64", true)
1411 .Case("x86_64h", true)
1412 .Case("armv4t", true)
1414 .Case("armv5e", true)
1415 .Case("armv6", true)
1416 .Case("armv6m", true)
1417 .Case("armv7em", true)
1418 .Case("armv7k", true)
1419 .Case("armv7m", true)
1420 .Case("armv7s", true)
1421 .Case("arm64", true)
1423 .Case("ppc64", true)
1427 unsigned MachOObjectFile::getArch() const {
1428 return getArch(getCPUType(this));
1431 Triple MachOObjectFile::getArch(const char **McpuDefault,
1432 Triple *ThumbTriple) const {
1435 MachO::mach_header_64 H_64;
1436 H_64 = getHeader64();
1437 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1438 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1441 MachO::mach_header H;
1443 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1450 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1453 return section_rel_begin(DRI);
1456 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1459 return section_rel_end(DRI);
1462 dice_iterator MachOObjectFile::begin_dices() const {
1464 if (!DataInCodeLoadCmd)
1465 return dice_iterator(DiceRef(DRI, this));
1467 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1468 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1469 return dice_iterator(DiceRef(DRI, this));
1472 dice_iterator MachOObjectFile::end_dices() const {
1474 if (!DataInCodeLoadCmd)
1475 return dice_iterator(DiceRef(DRI, this));
1477 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1478 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1479 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1480 return dice_iterator(DiceRef(DRI, this));
1483 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1484 : Trie(T), Malformed(false), Done(false) { }
1486 void ExportEntry::moveToFirst() {
1488 pushDownUntilBottom();
1491 void ExportEntry::moveToEnd() {
1496 bool ExportEntry::operator==(const ExportEntry &Other) const {
1497 // Common case, one at end, other iterating from begin.
1498 if (Done || Other.Done)
1499 return (Done == Other.Done);
1500 // Not equal if different stack sizes.
1501 if (Stack.size() != Other.Stack.size())
1503 // Not equal if different cumulative strings.
1504 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1506 // Equal if all nodes in both stacks match.
1507 for (unsigned i=0; i < Stack.size(); ++i) {
1508 if (Stack[i].Start != Other.Stack[i].Start)
1514 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1516 uint64_t Result = decodeULEB128(Ptr, &Count);
1518 if (Ptr > Trie.end()) {
1525 StringRef ExportEntry::name() const {
1526 return CumulativeString.str();
1529 uint64_t ExportEntry::flags() const {
1530 return Stack.back().Flags;
1533 uint64_t ExportEntry::address() const {
1534 return Stack.back().Address;
1537 uint64_t ExportEntry::other() const {
1538 return Stack.back().Other;
1541 StringRef ExportEntry::otherName() const {
1542 const char* ImportName = Stack.back().ImportName;
1544 return StringRef(ImportName);
1548 uint32_t ExportEntry::nodeOffset() const {
1549 return Stack.back().Start - Trie.begin();
1552 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1553 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1554 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1555 ParentStringLength(0), IsExportNode(false) {
1558 void ExportEntry::pushNode(uint64_t offset) {
1559 const uint8_t *Ptr = Trie.begin() + offset;
1560 NodeState State(Ptr);
1561 uint64_t ExportInfoSize = readULEB128(State.Current);
1562 State.IsExportNode = (ExportInfoSize != 0);
1563 const uint8_t* Children = State.Current + ExportInfoSize;
1564 if (State.IsExportNode) {
1565 State.Flags = readULEB128(State.Current);
1566 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1568 State.Other = readULEB128(State.Current); // dylib ordinal
1569 State.ImportName = reinterpret_cast<const char*>(State.Current);
1571 State.Address = readULEB128(State.Current);
1572 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1573 State.Other = readULEB128(State.Current);
1576 State.ChildCount = *Children;
1577 State.Current = Children + 1;
1578 State.NextChildIndex = 0;
1579 State.ParentStringLength = CumulativeString.size();
1580 Stack.push_back(State);
1583 void ExportEntry::pushDownUntilBottom() {
1584 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1585 NodeState &Top = Stack.back();
1586 CumulativeString.resize(Top.ParentStringLength);
1587 for (;*Top.Current != 0; Top.Current++) {
1588 char C = *Top.Current;
1589 CumulativeString.push_back(C);
1592 uint64_t childNodeIndex = readULEB128(Top.Current);
1593 Top.NextChildIndex += 1;
1594 pushNode(childNodeIndex);
1596 if (!Stack.back().IsExportNode) {
1602 // We have a trie data structure and need a way to walk it that is compatible
1603 // with the C++ iterator model. The solution is a non-recursive depth first
1604 // traversal where the iterator contains a stack of parent nodes along with a
1605 // string that is the accumulation of all edge strings along the parent chain
1608 // There is one "export" node for each exported symbol. But because some
1609 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1610 // node may have child nodes too.
1612 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1613 // child until hitting a node with no children (which is an export node or
1614 // else the trie is malformed). On the way down, each node is pushed on the
1615 // stack ivar. If there is no more ways down, it pops up one and tries to go
1616 // down a sibling path until a childless node is reached.
1617 void ExportEntry::moveNext() {
1618 if (Stack.empty() || !Stack.back().IsExportNode) {
1625 while (!Stack.empty()) {
1626 NodeState &Top = Stack.back();
1627 if (Top.NextChildIndex < Top.ChildCount) {
1628 pushDownUntilBottom();
1629 // Now at the next export node.
1632 if (Top.IsExportNode) {
1633 // This node has no children but is itself an export node.
1634 CumulativeString.resize(Top.ParentStringLength);
1643 iterator_range<export_iterator>
1644 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1645 ExportEntry Start(Trie);
1646 if (Trie.size() == 0)
1649 Start.moveToFirst();
1651 ExportEntry Finish(Trie);
1654 return iterator_range<export_iterator>(export_iterator(Start),
1655 export_iterator(Finish));
1658 iterator_range<export_iterator> MachOObjectFile::exports() const {
1659 return exports(getDyldInfoExportsTrie());
1663 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1664 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1665 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1666 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1668 void MachORebaseEntry::moveToFirst() {
1669 Ptr = Opcodes.begin();
1673 void MachORebaseEntry::moveToEnd() {
1674 Ptr = Opcodes.end();
1675 RemainingLoopCount = 0;
1679 void MachORebaseEntry::moveNext() {
1680 // If in the middle of some loop, move to next rebasing in loop.
1681 SegmentOffset += AdvanceAmount;
1682 if (RemainingLoopCount) {
1683 --RemainingLoopCount;
1686 if (Ptr == Opcodes.end()) {
1691 while (More && !Malformed) {
1692 // Parse next opcode and set up next loop.
1693 uint8_t Byte = *Ptr++;
1694 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1695 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1697 case MachO::REBASE_OPCODE_DONE:
1701 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1703 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1704 RebaseType = ImmValue;
1707 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1708 << "RebaseType=" << (int) RebaseType << "\n");
1710 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1711 SegmentIndex = ImmValue;
1712 SegmentOffset = readULEB128();
1715 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1716 << "SegmentIndex=" << SegmentIndex << ", "
1717 << format("SegmentOffset=0x%06X", SegmentOffset)
1720 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1721 SegmentOffset += readULEB128();
1722 DEBUG_WITH_TYPE("mach-o-rebase",
1723 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1724 << format("SegmentOffset=0x%06X",
1725 SegmentOffset) << "\n");
1727 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1728 SegmentOffset += ImmValue * PointerSize;
1729 DEBUG_WITH_TYPE("mach-o-rebase",
1730 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1731 << format("SegmentOffset=0x%06X",
1732 SegmentOffset) << "\n");
1734 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1735 AdvanceAmount = PointerSize;
1736 RemainingLoopCount = ImmValue - 1;
1739 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1740 << format("SegmentOffset=0x%06X", SegmentOffset)
1741 << ", AdvanceAmount=" << AdvanceAmount
1742 << ", RemainingLoopCount=" << RemainingLoopCount
1745 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1746 AdvanceAmount = PointerSize;
1747 RemainingLoopCount = readULEB128() - 1;
1750 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1751 << format("SegmentOffset=0x%06X", SegmentOffset)
1752 << ", AdvanceAmount=" << AdvanceAmount
1753 << ", RemainingLoopCount=" << RemainingLoopCount
1756 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1757 AdvanceAmount = readULEB128() + PointerSize;
1758 RemainingLoopCount = 0;
1761 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X", SegmentOffset)
1763 << ", AdvanceAmount=" << AdvanceAmount
1764 << ", RemainingLoopCount=" << RemainingLoopCount
1767 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1768 RemainingLoopCount = readULEB128() - 1;
1769 AdvanceAmount = readULEB128() + PointerSize;
1772 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1773 << format("SegmentOffset=0x%06X", SegmentOffset)
1774 << ", AdvanceAmount=" << AdvanceAmount
1775 << ", RemainingLoopCount=" << RemainingLoopCount
1784 uint64_t MachORebaseEntry::readULEB128() {
1786 uint64_t Result = decodeULEB128(Ptr, &Count);
1788 if (Ptr > Opcodes.end()) {
1789 Ptr = Opcodes.end();
1795 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1797 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1799 StringRef MachORebaseEntry::typeName() const {
1800 switch (RebaseType) {
1801 case MachO::REBASE_TYPE_POINTER:
1803 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1804 return "text abs32";
1805 case MachO::REBASE_TYPE_TEXT_PCREL32:
1806 return "text rel32";
1811 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1812 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1813 return (Ptr == Other.Ptr) &&
1814 (RemainingLoopCount == Other.RemainingLoopCount) &&
1815 (Done == Other.Done);
1818 iterator_range<rebase_iterator>
1819 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1820 MachORebaseEntry Start(Opcodes, is64);
1821 Start.moveToFirst();
1823 MachORebaseEntry Finish(Opcodes, is64);
1826 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1827 rebase_iterator(Finish));
1830 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1831 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1835 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1837 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1838 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1839 BindType(0), PointerSize(is64Bit ? 8 : 4),
1840 TableKind(BK), Malformed(false), Done(false) {}
1842 void MachOBindEntry::moveToFirst() {
1843 Ptr = Opcodes.begin();
1847 void MachOBindEntry::moveToEnd() {
1848 Ptr = Opcodes.end();
1849 RemainingLoopCount = 0;
1853 void MachOBindEntry::moveNext() {
1854 // If in the middle of some loop, move to next binding in loop.
1855 SegmentOffset += AdvanceAmount;
1856 if (RemainingLoopCount) {
1857 --RemainingLoopCount;
1860 if (Ptr == Opcodes.end()) {
1865 while (More && !Malformed) {
1866 // Parse next opcode and set up next loop.
1867 uint8_t Byte = *Ptr++;
1868 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1869 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1870 int8_t SignExtended;
1871 const uint8_t *SymStart;
1873 case MachO::BIND_OPCODE_DONE:
1874 if (TableKind == Kind::Lazy) {
1875 // Lazying bindings have a DONE opcode between entries. Need to ignore
1876 // it to advance to next entry. But need not if this is last entry.
1877 bool NotLastEntry = false;
1878 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1880 NotLastEntry = true;
1889 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1891 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1895 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1896 << "Ordinal=" << Ordinal << "\n");
1898 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1899 Ordinal = readULEB128();
1902 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1903 << "Ordinal=" << Ordinal << "\n");
1905 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1907 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1908 Ordinal = SignExtended;
1913 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1914 << "Ordinal=" << Ordinal << "\n");
1916 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1922 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1927 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1928 << "SymbolName=" << SymbolName << "\n");
1929 if (TableKind == Kind::Weak) {
1930 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1934 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1935 BindType = ImmValue;
1938 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1939 << "BindType=" << (int)BindType << "\n");
1941 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1942 Addend = readSLEB128();
1943 if (TableKind == Kind::Lazy)
1947 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1948 << "Addend=" << Addend << "\n");
1950 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1951 SegmentIndex = ImmValue;
1952 SegmentOffset = readULEB128();
1955 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1956 << "SegmentIndex=" << SegmentIndex << ", "
1957 << format("SegmentOffset=0x%06X", SegmentOffset)
1960 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1961 SegmentOffset += readULEB128();
1962 DEBUG_WITH_TYPE("mach-o-bind",
1963 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1964 << format("SegmentOffset=0x%06X",
1965 SegmentOffset) << "\n");
1967 case MachO::BIND_OPCODE_DO_BIND:
1968 AdvanceAmount = PointerSize;
1969 RemainingLoopCount = 0;
1970 DEBUG_WITH_TYPE("mach-o-bind",
1971 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1972 << format("SegmentOffset=0x%06X",
1973 SegmentOffset) << "\n");
1975 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1976 AdvanceAmount = readULEB128() + PointerSize;
1977 RemainingLoopCount = 0;
1978 if (TableKind == Kind::Lazy)
1982 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1983 << format("SegmentOffset=0x%06X", SegmentOffset)
1984 << ", AdvanceAmount=" << AdvanceAmount
1985 << ", RemainingLoopCount=" << RemainingLoopCount
1988 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1989 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1990 RemainingLoopCount = 0;
1991 if (TableKind == Kind::Lazy)
1993 DEBUG_WITH_TYPE("mach-o-bind",
1995 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1996 << format("SegmentOffset=0x%06X",
1997 SegmentOffset) << "\n");
1999 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2000 RemainingLoopCount = readULEB128() - 1;
2001 AdvanceAmount = readULEB128() + PointerSize;
2002 if (TableKind == Kind::Lazy)
2006 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2007 << format("SegmentOffset=0x%06X", SegmentOffset)
2008 << ", AdvanceAmount=" << AdvanceAmount
2009 << ", RemainingLoopCount=" << RemainingLoopCount
2018 uint64_t MachOBindEntry::readULEB128() {
2020 uint64_t Result = decodeULEB128(Ptr, &Count);
2022 if (Ptr > Opcodes.end()) {
2023 Ptr = Opcodes.end();
2029 int64_t MachOBindEntry::readSLEB128() {
2031 int64_t Result = decodeSLEB128(Ptr, &Count);
2033 if (Ptr > Opcodes.end()) {
2034 Ptr = Opcodes.end();
2041 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2043 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2045 StringRef MachOBindEntry::typeName() const {
2047 case MachO::BIND_TYPE_POINTER:
2049 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2050 return "text abs32";
2051 case MachO::BIND_TYPE_TEXT_PCREL32:
2052 return "text rel32";
2057 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2059 int64_t MachOBindEntry::addend() const { return Addend; }
2061 uint32_t MachOBindEntry::flags() const { return Flags; }
2063 int MachOBindEntry::ordinal() const { return Ordinal; }
2065 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2066 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2067 return (Ptr == Other.Ptr) &&
2068 (RemainingLoopCount == Other.RemainingLoopCount) &&
2069 (Done == Other.Done);
2072 iterator_range<bind_iterator>
2073 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2074 MachOBindEntry::Kind BKind) {
2075 MachOBindEntry Start(Opcodes, is64, BKind);
2076 Start.moveToFirst();
2078 MachOBindEntry Finish(Opcodes, is64, BKind);
2081 return iterator_range<bind_iterator>(bind_iterator(Start),
2082 bind_iterator(Finish));
2085 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2086 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2087 MachOBindEntry::Kind::Regular);
2090 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2091 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2092 MachOBindEntry::Kind::Lazy);
2095 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2096 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2097 MachOBindEntry::Kind::Weak);
2101 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2102 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2103 return parseSegmentOrSectionName(Raw.data());
2107 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2108 const section_base *Base =
2109 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2110 return makeArrayRef(Base->sectname);
2114 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2115 const section_base *Base =
2116 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2117 return makeArrayRef(Base->segname);
2121 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2123 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2125 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2128 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2129 const MachO::any_relocation_info &RE) const {
2130 if (isLittleEndian())
2131 return RE.r_word1 & 0xffffff;
2132 return RE.r_word1 >> 8;
2135 bool MachOObjectFile::getPlainRelocationExternal(
2136 const MachO::any_relocation_info &RE) const {
2137 if (isLittleEndian())
2138 return (RE.r_word1 >> 27) & 1;
2139 return (RE.r_word1 >> 4) & 1;
2142 bool MachOObjectFile::getScatteredRelocationScattered(
2143 const MachO::any_relocation_info &RE) const {
2144 return RE.r_word0 >> 31;
2147 uint32_t MachOObjectFile::getScatteredRelocationValue(
2148 const MachO::any_relocation_info &RE) const {
2152 uint32_t MachOObjectFile::getScatteredRelocationType(
2153 const MachO::any_relocation_info &RE) const {
2154 return (RE.r_word0 >> 24) & 0xf;
2157 unsigned MachOObjectFile::getAnyRelocationAddress(
2158 const MachO::any_relocation_info &RE) const {
2159 if (isRelocationScattered(RE))
2160 return getScatteredRelocationAddress(RE);
2161 return getPlainRelocationAddress(RE);
2164 unsigned MachOObjectFile::getAnyRelocationPCRel(
2165 const MachO::any_relocation_info &RE) const {
2166 if (isRelocationScattered(RE))
2167 return getScatteredRelocationPCRel(this, RE);
2168 return getPlainRelocationPCRel(this, RE);
2171 unsigned MachOObjectFile::getAnyRelocationLength(
2172 const MachO::any_relocation_info &RE) const {
2173 if (isRelocationScattered(RE))
2174 return getScatteredRelocationLength(RE);
2175 return getPlainRelocationLength(this, RE);
2179 MachOObjectFile::getAnyRelocationType(
2180 const MachO::any_relocation_info &RE) const {
2181 if (isRelocationScattered(RE))
2182 return getScatteredRelocationType(RE);
2183 return getPlainRelocationType(this, RE);
2187 MachOObjectFile::getRelocationSection(
2188 const MachO::any_relocation_info &RE) const {
2189 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2190 return *section_end();
2191 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2194 return SectionRef(DRI, this);
2197 MachOObjectFile::LoadCommandInfo
2198 MachOObjectFile::getFirstLoadCommandInfo() const {
2199 MachOObjectFile::LoadCommandInfo Load;
2201 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2202 sizeof(MachO::mach_header);
2203 Load.Ptr = getPtr(this, HeaderSize);
2204 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2208 MachOObjectFile::LoadCommandInfo
2209 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2210 MachOObjectFile::LoadCommandInfo Next;
2211 Next.Ptr = L.Ptr + L.C.cmdsize;
2212 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2216 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2217 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2220 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2221 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2224 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2225 unsigned Index) const {
2226 const char *Sec = getSectionPtr(this, L, Index);
2227 return getStruct<MachO::section>(this, Sec);
2230 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2231 unsigned Index) const {
2232 const char *Sec = getSectionPtr(this, L, Index);
2233 return getStruct<MachO::section_64>(this, Sec);
2237 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2238 const char *P = reinterpret_cast<const char *>(DRI.p);
2239 return getStruct<MachO::nlist>(this, P);
2243 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2244 const char *P = reinterpret_cast<const char *>(DRI.p);
2245 return getStruct<MachO::nlist_64>(this, P);
2248 MachO::linkedit_data_command
2249 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2250 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2253 MachO::segment_command
2254 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2255 return getStruct<MachO::segment_command>(this, L.Ptr);
2258 MachO::segment_command_64
2259 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2260 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2263 MachO::linker_option_command
2264 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2265 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2268 MachO::version_min_command
2269 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2270 return getStruct<MachO::version_min_command>(this, L.Ptr);
2273 MachO::dylib_command
2274 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2275 return getStruct<MachO::dylib_command>(this, L.Ptr);
2278 MachO::dyld_info_command
2279 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2280 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2283 MachO::dylinker_command
2284 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2285 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2289 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2290 return getStruct<MachO::uuid_command>(this, L.Ptr);
2293 MachO::rpath_command
2294 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2295 return getStruct<MachO::rpath_command>(this, L.Ptr);
2298 MachO::source_version_command
2299 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::source_version_command>(this, L.Ptr);
2303 MachO::entry_point_command
2304 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2308 MachO::encryption_info_command
2309 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2313 MachO::encryption_info_command_64
2314 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2318 MachO::sub_framework_command
2319 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2323 MachO::sub_umbrella_command
2324 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2328 MachO::sub_library_command
2329 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2333 MachO::sub_client_command
2334 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2338 MachO::routines_command
2339 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::routines_command>(this, L.Ptr);
2343 MachO::routines_command_64
2344 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2348 MachO::thread_command
2349 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::thread_command>(this, L.Ptr);
2353 MachO::any_relocation_info
2354 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2359 MachO::section_64 Sect = getSection64(Sec);
2360 Offset = Sect.reloff;
2362 MachO::section Sect = getSection(Sec);
2363 Offset = Sect.reloff;
2366 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2367 getPtr(this, Offset)) + Rel.d.b;
2368 return getStruct<MachO::any_relocation_info>(
2369 this, reinterpret_cast<const char *>(P));
2372 MachO::data_in_code_entry
2373 MachOObjectFile::getDice(DataRefImpl Rel) const {
2374 const char *P = reinterpret_cast<const char *>(Rel.p);
2375 return getStruct<MachO::data_in_code_entry>(this, P);
2378 MachO::mach_header MachOObjectFile::getHeader() const {
2379 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2382 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2383 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2386 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2387 const MachO::dysymtab_command &DLC,
2388 unsigned Index) const {
2389 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2390 return getStruct<uint32_t>(this, getPtr(this, Offset));
2393 MachO::data_in_code_entry
2394 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2395 unsigned Index) const {
2396 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2397 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2400 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2402 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2404 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2405 MachO::symtab_command Cmd;
2406 Cmd.cmd = MachO::LC_SYMTAB;
2407 Cmd.cmdsize = sizeof(MachO::symtab_command);
2415 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2416 if (DysymtabLoadCmd)
2417 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2419 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2420 MachO::dysymtab_command Cmd;
2421 Cmd.cmd = MachO::LC_DYSYMTAB;
2422 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2433 Cmd.extrefsymoff = 0;
2434 Cmd.nextrefsyms = 0;
2435 Cmd.indirectsymoff = 0;
2436 Cmd.nindirectsyms = 0;
2444 MachO::linkedit_data_command
2445 MachOObjectFile::getDataInCodeLoadCommand() const {
2446 if (DataInCodeLoadCmd)
2447 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2449 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2450 MachO::linkedit_data_command Cmd;
2451 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2452 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2458 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2459 if (!DyldInfoLoadCmd)
2460 return ArrayRef<uint8_t>();
2462 MachO::dyld_info_command DyldInfo
2463 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2464 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2465 getPtr(this, DyldInfo.rebase_off));
2466 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2469 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2470 if (!DyldInfoLoadCmd)
2471 return ArrayRef<uint8_t>();
2473 MachO::dyld_info_command DyldInfo
2474 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2475 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2476 getPtr(this, DyldInfo.bind_off));
2477 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2480 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2481 if (!DyldInfoLoadCmd)
2482 return ArrayRef<uint8_t>();
2484 MachO::dyld_info_command DyldInfo
2485 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2486 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2487 getPtr(this, DyldInfo.weak_bind_off));
2488 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2491 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2492 if (!DyldInfoLoadCmd)
2493 return ArrayRef<uint8_t>();
2495 MachO::dyld_info_command DyldInfo
2496 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2497 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2498 getPtr(this, DyldInfo.lazy_bind_off));
2499 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2502 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2503 if (!DyldInfoLoadCmd)
2504 return ArrayRef<uint8_t>();
2506 MachO::dyld_info_command DyldInfo
2507 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2508 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2509 getPtr(this, DyldInfo.export_off));
2510 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2513 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2515 return ArrayRef<uint8_t>();
2516 // Returning a pointer is fine as uuid doesn't need endian swapping.
2517 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2518 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2521 StringRef MachOObjectFile::getStringTableData() const {
2522 MachO::symtab_command S = getSymtabLoadCommand();
2523 return getData().substr(S.stroff, S.strsize);
2526 bool MachOObjectFile::is64Bit() const {
2527 return getType() == getMachOType(false, true) ||
2528 getType() == getMachOType(true, true);
2531 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2532 SmallVectorImpl<uint64_t> &Out) const {
2533 DataExtractor extractor(ObjectFile::getData(), true, 0);
2535 uint32_t offset = Index;
2537 while (uint64_t delta = extractor.getULEB128(&offset)) {
2539 Out.push_back(data);
2543 bool MachOObjectFile::isRelocatableObject() const {
2544 return getHeader().filetype == MachO::MH_OBJECT;
2547 ErrorOr<std::unique_ptr<MachOObjectFile>>
2548 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2549 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2551 std::unique_ptr<MachOObjectFile> Ret;
2552 if (Magic == "\xFE\xED\xFA\xCE")
2553 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2554 else if (Magic == "\xCE\xFA\xED\xFE")
2555 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2556 else if (Magic == "\xFE\xED\xFA\xCF")
2557 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2558 else if (Magic == "\xCF\xFA\xED\xFE")
2559 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2561 return object_error::parse_failed;
2565 return std::move(Ret);