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;
223 getScatteredRelocationType(const MachO::any_relocation_info &RE) {
224 return (RE.r_word0 >> 24) & 0xf;
227 static uint32_t getSectionFlags(const MachOObjectFile *O,
230 MachO::section_64 Sect = O->getSection64(Sec);
233 MachO::section Sect = O->getSection(Sec);
237 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
238 bool Is64bits, std::error_code &EC)
239 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
240 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
241 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
242 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
243 uint32_t LoadCommandCount = this->getHeader().ncmds;
244 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
245 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
247 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
248 for (unsigned I = 0; ; ++I) {
249 if (Load.C.cmd == MachO::LC_SYMTAB) {
250 assert(!SymtabLoadCmd && "Multiple symbol tables");
251 SymtabLoadCmd = Load.Ptr;
252 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
253 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
254 DysymtabLoadCmd = Load.Ptr;
255 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
256 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
257 DataInCodeLoadCmd = Load.Ptr;
258 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
259 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
260 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
261 DyldInfoLoadCmd = Load.Ptr;
262 } else if (Load.C.cmd == MachO::LC_UUID) {
263 assert(!UuidLoadCmd && "Multiple UUID load commands");
264 UuidLoadCmd = Load.Ptr;
265 } else if (Load.C.cmd == SegmentLoadType) {
266 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
267 for (unsigned J = 0; J < NumSections; ++J) {
268 const char *Sec = getSectionPtr(this, Load, J);
269 Sections.push_back(Sec);
271 if (isPageZeroSegment(this, Load))
272 HasPageZeroSegment = true;
273 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
274 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
275 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
276 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
277 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
278 Libraries.push_back(Load.Ptr);
281 if (I == LoadCommandCount - 1)
284 Load = getNextLoadCommandInfo(Load);
288 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
289 unsigned SymbolTableEntrySize = is64Bit() ?
290 sizeof(MachO::nlist_64) :
291 sizeof(MachO::nlist);
292 Symb.p += SymbolTableEntrySize;
295 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
296 StringRef &Res) const {
297 StringRef StringTable = getStringTableData();
298 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
299 const char *Start = &StringTable.data()[Entry.n_strx];
300 Res = StringRef(Start);
301 return object_error::success;
304 // getIndirectName() returns the name of the alias'ed symbol who's string table
305 // index is in the n_value field.
306 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
307 StringRef &Res) const {
308 StringRef StringTable = getStringTableData();
311 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
312 NValue = Entry.n_value;
313 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
314 return object_error::parse_failed;
316 MachO::nlist Entry = getSymbolTableEntry(Symb);
317 NValue = Entry.n_value;
318 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
319 return object_error::parse_failed;
321 if (NValue >= StringTable.size())
322 return object_error::parse_failed;
323 const char *Start = &StringTable.data()[NValue];
324 Res = StringRef(Start);
325 return object_error::success;
328 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
329 uint64_t &Res) const {
331 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
332 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
334 Res = UnknownAddressOrSize;
338 MachO::nlist Entry = getSymbolTableEntry(Symb);
339 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
341 Res = UnknownAddressOrSize;
345 return object_error::success;
348 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
349 uint32_t &Result) const {
350 uint32_t flags = getSymbolFlags(DRI);
351 if (flags & SymbolRef::SF_Common) {
352 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
353 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
357 return object_error::success;
360 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
361 uint64_t &Result) const {
362 uint64_t BeginOffset;
363 uint64_t EndOffset = 0;
364 uint8_t SectionIndex;
366 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
368 getSymbolAddress(DRI, Value);
369 if (Value == UnknownAddressOrSize) {
370 Result = UnknownAddressOrSize;
371 return object_error::success;
376 SectionIndex = Entry.n_sect;
378 uint32_t flags = getSymbolFlags(DRI);
379 if (flags & SymbolRef::SF_Common)
382 Result = UnknownAddressOrSize;
383 return object_error::success;
385 // Unfortunately symbols are unsorted so we need to touch all
386 // symbols from load command
387 for (const SymbolRef &Symbol : symbols()) {
388 DataRefImpl DRI = Symbol.getRawDataRefImpl();
389 Entry = getSymbolTableEntryBase(this, DRI);
390 getSymbolAddress(DRI, Value);
391 if (Value == UnknownAddressOrSize)
393 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
394 if (!EndOffset || Value < EndOffset)
399 Sec.d.a = SectionIndex-1;
400 uint64_t Size = getSectionSize(Sec);
401 EndOffset = getSectionAddress(Sec);
404 Result = EndOffset - BeginOffset;
405 return object_error::success;
408 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
409 SymbolRef::Type &Res) const {
410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
411 uint8_t n_type = Entry.n_type;
413 Res = SymbolRef::ST_Other;
415 // If this is a STAB debugging symbol, we can do nothing more.
416 if (n_type & MachO::N_STAB) {
417 Res = SymbolRef::ST_Debug;
418 return object_error::success;
421 switch (n_type & MachO::N_TYPE) {
423 Res = SymbolRef::ST_Unknown;
426 Res = SymbolRef::ST_Function;
429 return object_error::success;
432 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
433 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
435 uint8_t MachOType = Entry.n_type;
436 uint16_t MachOFlags = Entry.n_desc;
438 uint32_t Result = SymbolRef::SF_None;
440 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
441 Result |= SymbolRef::SF_Undefined;
443 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
444 Result |= SymbolRef::SF_Indirect;
446 if (MachOType & MachO::N_STAB)
447 Result |= SymbolRef::SF_FormatSpecific;
449 if (MachOType & MachO::N_EXT) {
450 Result |= SymbolRef::SF_Global;
451 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
453 getSymbolAddress(DRI, Value);
454 if (Value && Value != UnknownAddressOrSize)
455 Result |= SymbolRef::SF_Common;
458 if (!(MachOType & MachO::N_PEXT))
459 Result |= SymbolRef::SF_Exported;
462 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
463 Result |= SymbolRef::SF_Weak;
465 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
466 Result |= SymbolRef::SF_Thumb;
468 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
469 Result |= SymbolRef::SF_Absolute;
474 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
475 section_iterator &Res) const {
476 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
477 uint8_t index = Entry.n_sect;
484 Res = section_iterator(SectionRef(DRI, this));
487 return object_error::success;
490 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
494 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
495 StringRef &Result) const {
496 ArrayRef<char> Raw = getSectionRawName(Sec);
497 Result = parseSegmentOrSectionName(Raw.data());
498 return object_error::success;
501 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
503 return getSection64(Sec).addr;
504 return getSection(Sec).addr;
507 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
509 return getSection64(Sec).size;
510 return getSection(Sec).size;
513 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
514 StringRef &Res) const {
519 MachO::section_64 Sect = getSection64(Sec);
520 Offset = Sect.offset;
523 MachO::section Sect = getSection(Sec);
524 Offset = Sect.offset;
528 Res = this->getData().substr(Offset, Size);
529 return object_error::success;
532 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
535 MachO::section_64 Sect = getSection64(Sec);
538 MachO::section Sect = getSection(Sec);
542 return uint64_t(1) << Align;
545 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
546 uint32_t Flags = getSectionFlags(this, Sec);
547 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
550 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
551 uint32_t Flags = getSectionFlags(this, Sec);
552 unsigned SectionType = Flags & MachO::SECTION_TYPE;
553 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
554 !(SectionType == MachO::S_ZEROFILL ||
555 SectionType == MachO::S_GB_ZEROFILL);
558 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
559 uint32_t Flags = getSectionFlags(this, Sec);
560 unsigned SectionType = Flags & MachO::SECTION_TYPE;
561 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
562 (SectionType == MachO::S_ZEROFILL ||
563 SectionType == MachO::S_GB_ZEROFILL);
566 bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
567 // FIXME: Unimplemented.
571 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
572 // FIXME: Unimplemented.
576 bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
577 uint32_t Flags = getSectionFlags(this, Sec);
578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
579 return SectionType == MachO::S_ZEROFILL ||
580 SectionType == MachO::S_GB_ZEROFILL;
583 bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
584 // Consider using the code from isSectionText to look for __const sections.
585 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
586 // to use section attributes to distinguish code from data.
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 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1239 "64-bit object file when we're not 64-bit?");
1240 return "Mach-O 32-bit unknown";
1244 // Make sure the cpu type has the correct mask.
1245 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1246 == llvm::MachO::CPU_ARCH_ABI64 &&
1247 "32-bit object file when we're 64-bit?");
1250 case llvm::MachO::CPU_TYPE_X86_64:
1251 return "Mach-O 64-bit x86-64";
1252 case llvm::MachO::CPU_TYPE_ARM64:
1253 return "Mach-O arm64";
1254 case llvm::MachO::CPU_TYPE_POWERPC64:
1255 return "Mach-O 64-bit ppc64";
1257 return "Mach-O 64-bit unknown";
1261 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1263 case llvm::MachO::CPU_TYPE_I386:
1265 case llvm::MachO::CPU_TYPE_X86_64:
1266 return Triple::x86_64;
1267 case llvm::MachO::CPU_TYPE_ARM:
1269 case llvm::MachO::CPU_TYPE_ARM64:
1270 return Triple::aarch64;
1271 case llvm::MachO::CPU_TYPE_POWERPC:
1273 case llvm::MachO::CPU_TYPE_POWERPC64:
1274 return Triple::ppc64;
1276 return Triple::UnknownArch;
1280 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1281 const char **McpuDefault) {
1283 *McpuDefault = nullptr;
1286 case MachO::CPU_TYPE_I386:
1287 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1288 case MachO::CPU_SUBTYPE_I386_ALL:
1289 return Triple("i386-apple-darwin");
1293 case MachO::CPU_TYPE_X86_64:
1294 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1295 case MachO::CPU_SUBTYPE_X86_64_ALL:
1296 return Triple("x86_64-apple-darwin");
1297 case MachO::CPU_SUBTYPE_X86_64_H:
1298 return Triple("x86_64h-apple-darwin");
1302 case MachO::CPU_TYPE_ARM:
1303 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1304 case MachO::CPU_SUBTYPE_ARM_V4T:
1305 return Triple("armv4t-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1307 return Triple("armv5e-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1309 return Triple("xscale-apple-darwin");
1310 case MachO::CPU_SUBTYPE_ARM_V6:
1311 return Triple("armv6-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V6M:
1314 *McpuDefault = "cortex-m0";
1315 return Triple("armv6m-apple-darwin");
1316 case MachO::CPU_SUBTYPE_ARM_V7:
1317 return Triple("armv7-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7EM:
1320 *McpuDefault = "cortex-m4";
1321 return Triple("armv7em-apple-darwin");
1322 case MachO::CPU_SUBTYPE_ARM_V7K:
1323 return Triple("armv7k-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V7M:
1326 *McpuDefault = "cortex-m3";
1327 return Triple("armv7m-apple-darwin");
1328 case MachO::CPU_SUBTYPE_ARM_V7S:
1329 return Triple("armv7s-apple-darwin");
1333 case MachO::CPU_TYPE_ARM64:
1334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1335 case MachO::CPU_SUBTYPE_ARM64_ALL:
1336 return Triple("arm64-apple-darwin");
1340 case MachO::CPU_TYPE_POWERPC:
1341 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1342 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1343 return Triple("ppc-apple-darwin");
1347 case MachO::CPU_TYPE_POWERPC64:
1348 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1349 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1350 return Triple("ppc64-apple-darwin");
1359 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1360 const char **McpuDefault) {
1362 *McpuDefault = nullptr;
1365 case MachO::CPU_TYPE_ARM:
1366 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1367 case MachO::CPU_SUBTYPE_ARM_V4T:
1368 return Triple("thumbv4t-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1370 return Triple("thumbv5e-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1372 return Triple("xscale-apple-darwin");
1373 case MachO::CPU_SUBTYPE_ARM_V6:
1374 return Triple("thumbv6-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V6M:
1377 *McpuDefault = "cortex-m0";
1378 return Triple("thumbv6m-apple-darwin");
1379 case MachO::CPU_SUBTYPE_ARM_V7:
1380 return Triple("thumbv7-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7EM:
1383 *McpuDefault = "cortex-m4";
1384 return Triple("thumbv7em-apple-darwin");
1385 case MachO::CPU_SUBTYPE_ARM_V7K:
1386 return Triple("thumbv7k-apple-darwin");
1387 case MachO::CPU_SUBTYPE_ARM_V7M:
1389 *McpuDefault = "cortex-m3";
1390 return Triple("thumbv7m-apple-darwin");
1391 case MachO::CPU_SUBTYPE_ARM_V7S:
1392 return Triple("thumbv7s-apple-darwin");
1401 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1402 const char **McpuDefault,
1403 Triple *ThumbTriple) {
1404 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1405 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1410 Triple MachOObjectFile::getHostArch() {
1411 return Triple(sys::getDefaultTargetTriple());
1414 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1415 return StringSwitch<bool>(ArchFlag)
1417 .Case("x86_64", true)
1418 .Case("x86_64h", true)
1419 .Case("armv4t", true)
1421 .Case("armv5e", true)
1422 .Case("armv6", true)
1423 .Case("armv6m", true)
1424 .Case("armv7em", true)
1425 .Case("armv7k", true)
1426 .Case("armv7m", true)
1427 .Case("armv7s", true)
1428 .Case("arm64", true)
1430 .Case("ppc64", true)
1434 unsigned MachOObjectFile::getArch() const {
1435 return getArch(getCPUType(this));
1438 Triple MachOObjectFile::getArch(const char **McpuDefault,
1439 Triple *ThumbTriple) const {
1442 MachO::mach_header_64 H_64;
1443 H_64 = getHeader64();
1444 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1445 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1448 MachO::mach_header H;
1450 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1451 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1457 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1460 return section_rel_begin(DRI);
1463 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1466 return section_rel_end(DRI);
1469 dice_iterator MachOObjectFile::begin_dices() const {
1471 if (!DataInCodeLoadCmd)
1472 return dice_iterator(DiceRef(DRI, this));
1474 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1475 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1476 return dice_iterator(DiceRef(DRI, this));
1479 dice_iterator MachOObjectFile::end_dices() const {
1481 if (!DataInCodeLoadCmd)
1482 return dice_iterator(DiceRef(DRI, this));
1484 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1485 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1486 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1487 return dice_iterator(DiceRef(DRI, this));
1490 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1491 : Trie(T), Malformed(false), Done(false) { }
1493 void ExportEntry::moveToFirst() {
1495 pushDownUntilBottom();
1498 void ExportEntry::moveToEnd() {
1503 bool ExportEntry::operator==(const ExportEntry &Other) const {
1504 // Common case, one at end, other iterating from begin.
1505 if (Done || Other.Done)
1506 return (Done == Other.Done);
1507 // Not equal if different stack sizes.
1508 if (Stack.size() != Other.Stack.size())
1510 // Not equal if different cumulative strings.
1511 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1513 // Equal if all nodes in both stacks match.
1514 for (unsigned i=0; i < Stack.size(); ++i) {
1515 if (Stack[i].Start != Other.Stack[i].Start)
1521 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1523 uint64_t Result = decodeULEB128(Ptr, &Count);
1525 if (Ptr > Trie.end()) {
1532 StringRef ExportEntry::name() const {
1533 return CumulativeString.str();
1536 uint64_t ExportEntry::flags() const {
1537 return Stack.back().Flags;
1540 uint64_t ExportEntry::address() const {
1541 return Stack.back().Address;
1544 uint64_t ExportEntry::other() const {
1545 return Stack.back().Other;
1548 StringRef ExportEntry::otherName() const {
1549 const char* ImportName = Stack.back().ImportName;
1551 return StringRef(ImportName);
1555 uint32_t ExportEntry::nodeOffset() const {
1556 return Stack.back().Start - Trie.begin();
1559 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1560 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1561 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1562 ParentStringLength(0), IsExportNode(false) {
1565 void ExportEntry::pushNode(uint64_t offset) {
1566 const uint8_t *Ptr = Trie.begin() + offset;
1567 NodeState State(Ptr);
1568 uint64_t ExportInfoSize = readULEB128(State.Current);
1569 State.IsExportNode = (ExportInfoSize != 0);
1570 const uint8_t* Children = State.Current + ExportInfoSize;
1571 if (State.IsExportNode) {
1572 State.Flags = readULEB128(State.Current);
1573 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1575 State.Other = readULEB128(State.Current); // dylib ordinal
1576 State.ImportName = reinterpret_cast<const char*>(State.Current);
1578 State.Address = readULEB128(State.Current);
1579 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1580 State.Other = readULEB128(State.Current);
1583 State.ChildCount = *Children;
1584 State.Current = Children + 1;
1585 State.NextChildIndex = 0;
1586 State.ParentStringLength = CumulativeString.size();
1587 Stack.push_back(State);
1590 void ExportEntry::pushDownUntilBottom() {
1591 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1592 NodeState &Top = Stack.back();
1593 CumulativeString.resize(Top.ParentStringLength);
1594 for (;*Top.Current != 0; Top.Current++) {
1595 char C = *Top.Current;
1596 CumulativeString.push_back(C);
1599 uint64_t childNodeIndex = readULEB128(Top.Current);
1600 Top.NextChildIndex += 1;
1601 pushNode(childNodeIndex);
1603 if (!Stack.back().IsExportNode) {
1609 // We have a trie data structure and need a way to walk it that is compatible
1610 // with the C++ iterator model. The solution is a non-recursive depth first
1611 // traversal where the iterator contains a stack of parent nodes along with a
1612 // string that is the accumulation of all edge strings along the parent chain
1615 // There is one “export” node for each exported symbol. But because some
1616 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1617 // node may have child nodes too.
1619 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1620 // child until hitting a node with no children (which is an export node or
1621 // else the trie is malformed). On the way down, each node is pushed on the
1622 // stack ivar. If there is no more ways down, it pops up one and tries to go
1623 // down a sibling path until a childless node is reached.
1624 void ExportEntry::moveNext() {
1625 if (Stack.empty() || !Stack.back().IsExportNode) {
1632 while (!Stack.empty()) {
1633 NodeState &Top = Stack.back();
1634 if (Top.NextChildIndex < Top.ChildCount) {
1635 pushDownUntilBottom();
1636 // Now at the next export node.
1639 if (Top.IsExportNode) {
1640 // This node has no children but is itself an export node.
1641 CumulativeString.resize(Top.ParentStringLength);
1650 iterator_range<export_iterator>
1651 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1652 ExportEntry Start(Trie);
1653 Start.moveToFirst();
1655 ExportEntry Finish(Trie);
1658 return iterator_range<export_iterator>(export_iterator(Start),
1659 export_iterator(Finish));
1662 iterator_range<export_iterator> MachOObjectFile::exports() const {
1663 return exports(getDyldInfoExportsTrie());
1667 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1668 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1669 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1670 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1672 void MachORebaseEntry::moveToFirst() {
1673 Ptr = Opcodes.begin();
1677 void MachORebaseEntry::moveToEnd() {
1678 Ptr = Opcodes.end();
1679 RemainingLoopCount = 0;
1683 void MachORebaseEntry::moveNext() {
1684 // If in the middle of some loop, move to next rebasing in loop.
1685 SegmentOffset += AdvanceAmount;
1686 if (RemainingLoopCount) {
1687 --RemainingLoopCount;
1690 if (Ptr == Opcodes.end()) {
1695 while (More && !Malformed) {
1696 // Parse next opcode and set up next loop.
1697 uint8_t Byte = *Ptr++;
1698 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1699 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1701 case MachO::REBASE_OPCODE_DONE:
1705 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1707 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1708 RebaseType = ImmValue;
1711 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1712 << "RebaseType=" << (int) RebaseType << "\n");
1714 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1715 SegmentIndex = ImmValue;
1716 SegmentOffset = readULEB128();
1719 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1720 << "SegmentIndex=" << SegmentIndex << ", "
1721 << format("SegmentOffset=0x%06X", SegmentOffset)
1724 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1725 SegmentOffset += readULEB128();
1726 DEBUG_WITH_TYPE("mach-o-rebase",
1727 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1728 << format("SegmentOffset=0x%06X",
1729 SegmentOffset) << "\n");
1731 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1732 SegmentOffset += ImmValue * PointerSize;
1733 DEBUG_WITH_TYPE("mach-o-rebase",
1734 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1735 << format("SegmentOffset=0x%06X",
1736 SegmentOffset) << "\n");
1738 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1739 AdvanceAmount = PointerSize;
1740 RemainingLoopCount = ImmValue - 1;
1743 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1744 << format("SegmentOffset=0x%06X", SegmentOffset)
1745 << ", AdvanceAmount=" << AdvanceAmount
1746 << ", RemainingLoopCount=" << RemainingLoopCount
1749 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1750 AdvanceAmount = PointerSize;
1751 RemainingLoopCount = readULEB128() - 1;
1754 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1755 << format("SegmentOffset=0x%06X", SegmentOffset)
1756 << ", AdvanceAmount=" << AdvanceAmount
1757 << ", RemainingLoopCount=" << RemainingLoopCount
1760 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1761 AdvanceAmount = readULEB128() + PointerSize;
1762 RemainingLoopCount = 0;
1765 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1766 << format("SegmentOffset=0x%06X", SegmentOffset)
1767 << ", AdvanceAmount=" << AdvanceAmount
1768 << ", RemainingLoopCount=" << RemainingLoopCount
1771 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1772 RemainingLoopCount = readULEB128() - 1;
1773 AdvanceAmount = readULEB128() + PointerSize;
1776 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1777 << format("SegmentOffset=0x%06X", SegmentOffset)
1778 << ", AdvanceAmount=" << AdvanceAmount
1779 << ", RemainingLoopCount=" << RemainingLoopCount
1788 uint64_t MachORebaseEntry::readULEB128() {
1790 uint64_t Result = decodeULEB128(Ptr, &Count);
1792 if (Ptr > Opcodes.end()) {
1793 Ptr = Opcodes.end();
1799 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1801 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1803 StringRef MachORebaseEntry::typeName() const {
1804 switch (RebaseType) {
1805 case MachO::REBASE_TYPE_POINTER:
1807 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1808 return "text abs32";
1809 case MachO::REBASE_TYPE_TEXT_PCREL32:
1810 return "text rel32";
1815 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1816 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1817 return (Ptr == Other.Ptr) &&
1818 (RemainingLoopCount == Other.RemainingLoopCount) &&
1819 (Done == Other.Done);
1822 iterator_range<rebase_iterator>
1823 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1824 MachORebaseEntry Start(Opcodes, is64);
1825 Start.moveToFirst();
1827 MachORebaseEntry Finish(Opcodes, is64);
1830 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1831 rebase_iterator(Finish));
1834 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1835 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1839 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1841 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1842 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1843 BindType(0), PointerSize(is64Bit ? 8 : 4),
1844 TableKind(BK), Malformed(false), Done(false) {}
1846 void MachOBindEntry::moveToFirst() {
1847 Ptr = Opcodes.begin();
1851 void MachOBindEntry::moveToEnd() {
1852 Ptr = Opcodes.end();
1853 RemainingLoopCount = 0;
1857 void MachOBindEntry::moveNext() {
1858 // If in the middle of some loop, move to next binding in loop.
1859 SegmentOffset += AdvanceAmount;
1860 if (RemainingLoopCount) {
1861 --RemainingLoopCount;
1864 if (Ptr == Opcodes.end()) {
1869 while (More && !Malformed) {
1870 // Parse next opcode and set up next loop.
1871 uint8_t Byte = *Ptr++;
1872 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1873 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1874 int8_t SignExtended;
1875 const uint8_t *SymStart;
1877 case MachO::BIND_OPCODE_DONE:
1878 if (TableKind == Kind::Lazy) {
1879 // Lazying bindings have a DONE opcode between entries. Need to ignore
1880 // it to advance to next entry. But need not if this is last entry.
1881 bool NotLastEntry = false;
1882 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1884 NotLastEntry = true;
1893 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1895 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1899 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1900 << "Ordinal=" << Ordinal << "\n");
1902 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1903 Ordinal = readULEB128();
1906 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1907 << "Ordinal=" << Ordinal << "\n");
1909 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1911 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1912 Ordinal = SignExtended;
1917 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1918 << "Ordinal=" << Ordinal << "\n");
1920 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1926 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1931 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1932 << "SymbolName=" << SymbolName << "\n");
1933 if (TableKind == Kind::Weak) {
1934 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1938 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1939 BindType = ImmValue;
1942 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1943 << "BindType=" << (int)BindType << "\n");
1945 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1946 Addend = readSLEB128();
1947 if (TableKind == Kind::Lazy)
1951 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1952 << "Addend=" << Addend << "\n");
1954 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1955 SegmentIndex = ImmValue;
1956 SegmentOffset = readULEB128();
1959 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1960 << "SegmentIndex=" << SegmentIndex << ", "
1961 << format("SegmentOffset=0x%06X", SegmentOffset)
1964 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1965 SegmentOffset += readULEB128();
1966 DEBUG_WITH_TYPE("mach-o-bind",
1967 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1968 << format("SegmentOffset=0x%06X",
1969 SegmentOffset) << "\n");
1971 case MachO::BIND_OPCODE_DO_BIND:
1972 AdvanceAmount = PointerSize;
1973 RemainingLoopCount = 0;
1974 DEBUG_WITH_TYPE("mach-o-bind",
1975 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1976 << format("SegmentOffset=0x%06X",
1977 SegmentOffset) << "\n");
1979 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1980 AdvanceAmount = readULEB128() + PointerSize;
1981 RemainingLoopCount = 0;
1982 if (TableKind == Kind::Lazy)
1986 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1987 << format("SegmentOffset=0x%06X", SegmentOffset)
1988 << ", AdvanceAmount=" << AdvanceAmount
1989 << ", RemainingLoopCount=" << RemainingLoopCount
1992 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1993 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1994 RemainingLoopCount = 0;
1995 if (TableKind == Kind::Lazy)
1997 DEBUG_WITH_TYPE("mach-o-bind",
1999 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2000 << format("SegmentOffset=0x%06X",
2001 SegmentOffset) << "\n");
2003 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2004 RemainingLoopCount = readULEB128() - 1;
2005 AdvanceAmount = readULEB128() + PointerSize;
2006 if (TableKind == Kind::Lazy)
2010 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2011 << format("SegmentOffset=0x%06X", SegmentOffset)
2012 << ", AdvanceAmount=" << AdvanceAmount
2013 << ", RemainingLoopCount=" << RemainingLoopCount
2022 uint64_t MachOBindEntry::readULEB128() {
2024 uint64_t Result = decodeULEB128(Ptr, &Count);
2026 if (Ptr > Opcodes.end()) {
2027 Ptr = Opcodes.end();
2033 int64_t MachOBindEntry::readSLEB128() {
2035 int64_t Result = decodeSLEB128(Ptr, &Count);
2037 if (Ptr > Opcodes.end()) {
2038 Ptr = Opcodes.end();
2045 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2047 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2049 StringRef MachOBindEntry::typeName() const {
2051 case MachO::BIND_TYPE_POINTER:
2053 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2054 return "text abs32";
2055 case MachO::BIND_TYPE_TEXT_PCREL32:
2056 return "text rel32";
2061 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2063 int64_t MachOBindEntry::addend() const { return Addend; }
2065 uint32_t MachOBindEntry::flags() const { return Flags; }
2067 int MachOBindEntry::ordinal() const { return Ordinal; }
2069 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2070 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2071 return (Ptr == Other.Ptr) &&
2072 (RemainingLoopCount == Other.RemainingLoopCount) &&
2073 (Done == Other.Done);
2076 iterator_range<bind_iterator>
2077 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2078 MachOBindEntry::Kind BKind) {
2079 MachOBindEntry Start(Opcodes, is64, BKind);
2080 Start.moveToFirst();
2082 MachOBindEntry Finish(Opcodes, is64, BKind);
2085 return iterator_range<bind_iterator>(bind_iterator(Start),
2086 bind_iterator(Finish));
2089 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2090 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2091 MachOBindEntry::Kind::Regular);
2094 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2095 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2096 MachOBindEntry::Kind::Lazy);
2099 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2100 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2101 MachOBindEntry::Kind::Weak);
2105 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2106 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2107 return parseSegmentOrSectionName(Raw.data());
2111 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2112 const section_base *Base =
2113 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2114 return makeArrayRef(Base->sectname);
2118 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2119 const section_base *Base =
2120 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2121 return makeArrayRef(Base->segname);
2125 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2127 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2129 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2132 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2133 const MachO::any_relocation_info &RE) const {
2134 if (isLittleEndian())
2135 return RE.r_word1 & 0xffffff;
2136 return RE.r_word1 >> 8;
2139 bool MachOObjectFile::getPlainRelocationExternal(
2140 const MachO::any_relocation_info &RE) const {
2141 if (isLittleEndian())
2142 return (RE.r_word1 >> 27) & 1;
2143 return (RE.r_word1 >> 4) & 1;
2146 bool MachOObjectFile::getScatteredRelocationScattered(
2147 const MachO::any_relocation_info &RE) const {
2148 return RE.r_word0 >> 31;
2151 uint32_t MachOObjectFile::getScatteredRelocationValue(
2152 const MachO::any_relocation_info &RE) const {
2156 unsigned MachOObjectFile::getAnyRelocationAddress(
2157 const MachO::any_relocation_info &RE) const {
2158 if (isRelocationScattered(RE))
2159 return getScatteredRelocationAddress(RE);
2160 return getPlainRelocationAddress(RE);
2163 unsigned MachOObjectFile::getAnyRelocationPCRel(
2164 const MachO::any_relocation_info &RE) const {
2165 if (isRelocationScattered(RE))
2166 return getScatteredRelocationPCRel(this, RE);
2167 return getPlainRelocationPCRel(this, RE);
2170 unsigned MachOObjectFile::getAnyRelocationLength(
2171 const MachO::any_relocation_info &RE) const {
2172 if (isRelocationScattered(RE))
2173 return getScatteredRelocationLength(RE);
2174 return getPlainRelocationLength(this, RE);
2178 MachOObjectFile::getAnyRelocationType(
2179 const MachO::any_relocation_info &RE) const {
2180 if (isRelocationScattered(RE))
2181 return getScatteredRelocationType(RE);
2182 return getPlainRelocationType(this, RE);
2186 MachOObjectFile::getRelocationSection(
2187 const MachO::any_relocation_info &RE) const {
2188 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2189 return *section_end();
2190 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2193 return SectionRef(DRI, this);
2196 MachOObjectFile::LoadCommandInfo
2197 MachOObjectFile::getFirstLoadCommandInfo() const {
2198 MachOObjectFile::LoadCommandInfo Load;
2200 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2201 sizeof(MachO::mach_header);
2202 Load.Ptr = getPtr(this, HeaderSize);
2203 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2207 MachOObjectFile::LoadCommandInfo
2208 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2209 MachOObjectFile::LoadCommandInfo Next;
2210 Next.Ptr = L.Ptr + L.C.cmdsize;
2211 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2215 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2216 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2219 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2220 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2223 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2224 unsigned Index) const {
2225 const char *Sec = getSectionPtr(this, L, Index);
2226 return getStruct<MachO::section>(this, Sec);
2229 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2230 unsigned Index) const {
2231 const char *Sec = getSectionPtr(this, L, Index);
2232 return getStruct<MachO::section_64>(this, Sec);
2236 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2237 const char *P = reinterpret_cast<const char *>(DRI.p);
2238 return getStruct<MachO::nlist>(this, P);
2242 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2243 const char *P = reinterpret_cast<const char *>(DRI.p);
2244 return getStruct<MachO::nlist_64>(this, P);
2247 MachO::linkedit_data_command
2248 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2249 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2252 MachO::segment_command
2253 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2254 return getStruct<MachO::segment_command>(this, L.Ptr);
2257 MachO::segment_command_64
2258 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2259 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2262 MachO::linker_options_command
2263 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2264 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2267 MachO::version_min_command
2268 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2269 return getStruct<MachO::version_min_command>(this, L.Ptr);
2272 MachO::dylib_command
2273 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2274 return getStruct<MachO::dylib_command>(this, L.Ptr);
2277 MachO::dyld_info_command
2278 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2282 MachO::dylinker_command
2283 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2288 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::uuid_command>(this, L.Ptr);
2292 MachO::source_version_command
2293 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::source_version_command>(this, L.Ptr);
2297 MachO::entry_point_command
2298 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2303 MachO::any_relocation_info
2304 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2309 MachO::section_64 Sect = getSection64(Sec);
2310 Offset = Sect.reloff;
2312 MachO::section Sect = getSection(Sec);
2313 Offset = Sect.reloff;
2316 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2317 getPtr(this, Offset)) + Rel.d.b;
2318 return getStruct<MachO::any_relocation_info>(
2319 this, reinterpret_cast<const char *>(P));
2322 MachO::data_in_code_entry
2323 MachOObjectFile::getDice(DataRefImpl Rel) const {
2324 const char *P = reinterpret_cast<const char *>(Rel.p);
2325 return getStruct<MachO::data_in_code_entry>(this, P);
2328 MachO::mach_header MachOObjectFile::getHeader() const {
2329 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2332 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2333 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2336 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2337 const MachO::dysymtab_command &DLC,
2338 unsigned Index) const {
2339 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2340 return getStruct<uint32_t>(this, getPtr(this, Offset));
2343 MachO::data_in_code_entry
2344 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2345 unsigned Index) const {
2346 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2347 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2350 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2351 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2354 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2355 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2358 MachO::linkedit_data_command
2359 MachOObjectFile::getDataInCodeLoadCommand() const {
2360 if (DataInCodeLoadCmd)
2361 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2363 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2364 MachO::linkedit_data_command Cmd;
2365 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2366 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2372 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2373 if (!DyldInfoLoadCmd)
2374 return ArrayRef<uint8_t>();
2376 MachO::dyld_info_command DyldInfo
2377 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2378 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2379 getPtr(this, DyldInfo.rebase_off));
2380 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2383 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2384 if (!DyldInfoLoadCmd)
2385 return ArrayRef<uint8_t>();
2387 MachO::dyld_info_command DyldInfo
2388 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2389 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2390 getPtr(this, DyldInfo.bind_off));
2391 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2394 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2395 if (!DyldInfoLoadCmd)
2396 return ArrayRef<uint8_t>();
2398 MachO::dyld_info_command DyldInfo
2399 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2400 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2401 getPtr(this, DyldInfo.weak_bind_off));
2402 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2405 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2406 if (!DyldInfoLoadCmd)
2407 return ArrayRef<uint8_t>();
2409 MachO::dyld_info_command DyldInfo
2410 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2411 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2412 getPtr(this, DyldInfo.lazy_bind_off));
2413 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2416 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2417 if (!DyldInfoLoadCmd)
2418 return ArrayRef<uint8_t>();
2420 MachO::dyld_info_command DyldInfo
2421 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2422 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2423 getPtr(this, DyldInfo.export_off));
2424 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2427 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2429 return ArrayRef<uint8_t>();
2430 MachO::uuid_command Uuid = getStruct<MachO::uuid_command>(this, UuidLoadCmd);
2431 return ArrayRef<uint8_t>(Uuid.uuid, 16);
2434 StringRef MachOObjectFile::getStringTableData() const {
2435 MachO::symtab_command S = getSymtabLoadCommand();
2436 return getData().substr(S.stroff, S.strsize);
2439 bool MachOObjectFile::is64Bit() const {
2440 return getType() == getMachOType(false, true) ||
2441 getType() == getMachOType(true, true);
2444 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2445 SmallVectorImpl<uint64_t> &Out) const {
2446 DataExtractor extractor(ObjectFile::getData(), true, 0);
2448 uint32_t offset = Index;
2450 while (uint64_t delta = extractor.getULEB128(&offset)) {
2452 Out.push_back(data);
2456 bool MachOObjectFile::isRelocatableObject() const {
2457 return getHeader().filetype == MachO::MH_OBJECT;
2460 ErrorOr<std::unique_ptr<MachOObjectFile>>
2461 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2462 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2464 std::unique_ptr<MachOObjectFile> Ret;
2465 if (Magic == "\xFE\xED\xFA\xCE")
2466 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2467 else if (Magic == "\xCE\xFA\xED\xFE")
2468 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2469 else if (Magic == "\xFE\xED\xFA\xCF")
2470 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2471 else if (Magic == "\xCF\xFA\xED\xFE")
2472 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2474 return object_error::parse_failed;
2478 return std::move(Ret);