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 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
240 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
242 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
243 for (unsigned I = 0; ; ++I) {
244 if (Load.C.cmd == MachO::LC_SYMTAB) {
245 // Multiple symbol tables
247 EC = object_error::parse_failed;
250 SymtabLoadCmd = Load.Ptr;
251 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
252 // Multiple dynamic symbol tables
253 if (DysymtabLoadCmd) {
254 EC = object_error::parse_failed;
257 DysymtabLoadCmd = Load.Ptr;
258 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
259 // Multiple data in code tables
260 if (DataInCodeLoadCmd) {
261 EC = object_error::parse_failed;
264 DataInCodeLoadCmd = Load.Ptr;
265 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
266 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
267 // Multiple dyldinfo load commands
268 if (DyldInfoLoadCmd) {
269 EC = object_error::parse_failed;
272 DyldInfoLoadCmd = Load.Ptr;
273 } else if (Load.C.cmd == MachO::LC_UUID) {
274 // Multiple UUID load commands
276 EC = object_error::parse_failed;
279 UuidLoadCmd = Load.Ptr;
280 } else if (Load.C.cmd == SegmentLoadType) {
281 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
282 for (unsigned J = 0; J < NumSections; ++J) {
283 const char *Sec = getSectionPtr(this, Load, J);
284 Sections.push_back(Sec);
286 if (isPageZeroSegment(this, Load))
287 HasPageZeroSegment = true;
288 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
289 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
290 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
291 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
293 Libraries.push_back(Load.Ptr);
296 if (I == LoadCommandCount - 1)
299 Load = getNextLoadCommandInfo(Load);
303 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
304 unsigned SymbolTableEntrySize = is64Bit() ?
305 sizeof(MachO::nlist_64) :
306 sizeof(MachO::nlist);
307 Symb.p += SymbolTableEntrySize;
310 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
311 StringRef &Res) const {
312 StringRef StringTable = getStringTableData();
313 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
314 const char *Start = &StringTable.data()[Entry.n_strx];
315 Res = StringRef(Start);
316 return object_error::success;
319 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
320 DataRefImpl DRI = Sec.getRawDataRefImpl();
321 uint32_t Flags = getSectionFlags(this, DRI);
322 return Flags & MachO::SECTION_TYPE;
325 // getIndirectName() returns the name of the alias'ed symbol who's string table
326 // index is in the n_value field.
327 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
328 StringRef &Res) const {
329 StringRef StringTable = getStringTableData();
332 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
333 NValue = Entry.n_value;
334 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
335 return object_error::parse_failed;
337 MachO::nlist Entry = getSymbolTableEntry(Symb);
338 NValue = Entry.n_value;
339 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
340 return object_error::parse_failed;
342 if (NValue >= StringTable.size())
343 return object_error::parse_failed;
344 const char *Start = &StringTable.data()[NValue];
345 Res = StringRef(Start);
346 return object_error::success;
349 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
350 uint64_t &Res) const {
352 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
353 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
355 Res = UnknownAddressOrSize;
359 MachO::nlist Entry = getSymbolTableEntry(Symb);
360 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
362 Res = UnknownAddressOrSize;
366 return object_error::success;
369 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
370 uint32_t &Result) const {
371 uint32_t flags = getSymbolFlags(DRI);
372 if (flags & SymbolRef::SF_Common) {
373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
374 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
378 return object_error::success;
381 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
382 uint64_t &Result) const {
383 uint64_t BeginOffset;
384 uint64_t EndOffset = 0;
385 uint8_t SectionIndex;
387 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
389 getSymbolAddress(DRI, Value);
390 if (Value == UnknownAddressOrSize) {
391 Result = UnknownAddressOrSize;
392 return object_error::success;
397 SectionIndex = Entry.n_sect;
399 uint32_t flags = getSymbolFlags(DRI);
400 if (flags & SymbolRef::SF_Common)
403 Result = UnknownAddressOrSize;
404 return object_error::success;
406 // Unfortunately symbols are unsorted so we need to touch all
407 // symbols from load command
408 for (const SymbolRef &Symbol : symbols()) {
409 DataRefImpl DRI = Symbol.getRawDataRefImpl();
410 Entry = getSymbolTableEntryBase(this, DRI);
411 getSymbolAddress(DRI, Value);
412 if (Value == UnknownAddressOrSize)
414 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
415 if (!EndOffset || Value < EndOffset)
420 Sec.d.a = SectionIndex-1;
421 uint64_t Size = getSectionSize(Sec);
422 EndOffset = getSectionAddress(Sec);
425 Result = EndOffset - BeginOffset;
426 return object_error::success;
429 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
430 SymbolRef::Type &Res) const {
431 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
432 uint8_t n_type = Entry.n_type;
434 Res = SymbolRef::ST_Other;
436 // If this is a STAB debugging symbol, we can do nothing more.
437 if (n_type & MachO::N_STAB) {
438 Res = SymbolRef::ST_Debug;
439 return object_error::success;
442 switch (n_type & MachO::N_TYPE) {
444 Res = SymbolRef::ST_Unknown;
447 Res = SymbolRef::ST_Function;
450 return object_error::success;
453 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
454 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
456 uint8_t MachOType = Entry.n_type;
457 uint16_t MachOFlags = Entry.n_desc;
459 uint32_t Result = SymbolRef::SF_None;
461 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
462 Result |= SymbolRef::SF_Undefined;
464 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
465 Result |= SymbolRef::SF_Indirect;
467 if (MachOType & MachO::N_STAB)
468 Result |= SymbolRef::SF_FormatSpecific;
470 if (MachOType & MachO::N_EXT) {
471 Result |= SymbolRef::SF_Global;
472 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
474 getSymbolAddress(DRI, Value);
475 if (Value && Value != UnknownAddressOrSize)
476 Result |= SymbolRef::SF_Common;
480 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
481 Result |= SymbolRef::SF_Weak;
483 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
484 Result |= SymbolRef::SF_Thumb;
486 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
487 Result |= SymbolRef::SF_Absolute;
492 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
493 section_iterator &Res) const {
494 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
495 uint8_t index = Entry.n_sect;
502 Res = section_iterator(SectionRef(DRI, this));
505 return object_error::success;
508 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
512 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
513 StringRef &Result) const {
514 ArrayRef<char> Raw = getSectionRawName(Sec);
515 Result = parseSegmentOrSectionName(Raw.data());
516 return object_error::success;
519 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
521 return getSection64(Sec).addr;
522 return getSection(Sec).addr;
525 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
527 return getSection64(Sec).size;
528 return getSection(Sec).size;
531 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
532 StringRef &Res) const {
537 MachO::section_64 Sect = getSection64(Sec);
538 Offset = Sect.offset;
541 MachO::section Sect = getSection(Sec);
542 Offset = Sect.offset;
546 Res = this->getData().substr(Offset, Size);
547 return object_error::success;
550 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
553 MachO::section_64 Sect = getSection64(Sec);
556 MachO::section Sect = getSection(Sec);
560 return uint64_t(1) << Align;
563 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
564 uint32_t Flags = getSectionFlags(this, Sec);
565 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
568 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
569 uint32_t Flags = getSectionFlags(this, Sec);
570 unsigned SectionType = Flags & MachO::SECTION_TYPE;
571 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
572 !(SectionType == MachO::S_ZEROFILL ||
573 SectionType == MachO::S_GB_ZEROFILL);
576 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
577 uint32_t Flags = getSectionFlags(this, Sec);
578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
579 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
580 (SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL);
584 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
585 // FIXME: Unimplemented.
589 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
590 DataRefImpl Symb) const {
592 this->getSymbolType(Symb, ST);
593 if (ST == SymbolRef::ST_Unknown)
596 uint64_t SectBegin = getSectionAddress(Sec);
597 uint64_t SectEnd = getSectionSize(Sec);
598 SectEnd += SectBegin;
601 getSymbolAddress(Symb, SymAddr);
602 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
605 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
609 return relocation_iterator(RelocationRef(Ret, this));
613 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
616 MachO::section_64 Sect = getSection64(Sec);
619 MachO::section Sect = getSection(Sec);
626 return relocation_iterator(RelocationRef(Ret, this));
629 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
633 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
634 uint64_t &Res) const {
636 getRelocationOffset(Rel, Offset);
640 uint64_t SecAddress = getSectionAddress(Sec);
641 Res = SecAddress + Offset;
642 return object_error::success;
645 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
646 uint64_t &Res) const {
647 assert(getHeader().filetype == MachO::MH_OBJECT &&
648 "Only implemented for MH_OBJECT");
649 MachO::any_relocation_info RE = getRelocation(Rel);
650 Res = getAnyRelocationAddress(RE);
651 return object_error::success;
655 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
656 MachO::any_relocation_info RE = getRelocation(Rel);
657 if (isRelocationScattered(RE))
660 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
661 bool isExtern = getPlainRelocationExternal(RE);
665 MachO::symtab_command S = getSymtabLoadCommand();
666 unsigned SymbolTableEntrySize = is64Bit() ?
667 sizeof(MachO::nlist_64) :
668 sizeof(MachO::nlist);
669 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
671 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
672 return symbol_iterator(SymbolRef(Sym, this));
675 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
676 uint64_t &Res) const {
677 MachO::any_relocation_info RE = getRelocation(Rel);
678 Res = getAnyRelocationType(RE);
679 return object_error::success;
683 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
684 SmallVectorImpl<char> &Result) const {
687 getRelocationType(Rel, RType);
689 unsigned Arch = this->getArch();
693 static const char *const Table[] = {
694 "GENERIC_RELOC_VANILLA",
695 "GENERIC_RELOC_PAIR",
696 "GENERIC_RELOC_SECTDIFF",
697 "GENERIC_RELOC_PB_LA_PTR",
698 "GENERIC_RELOC_LOCAL_SECTDIFF",
699 "GENERIC_RELOC_TLV" };
707 case Triple::x86_64: {
708 static const char *const Table[] = {
709 "X86_64_RELOC_UNSIGNED",
710 "X86_64_RELOC_SIGNED",
711 "X86_64_RELOC_BRANCH",
712 "X86_64_RELOC_GOT_LOAD",
714 "X86_64_RELOC_SUBTRACTOR",
715 "X86_64_RELOC_SIGNED_1",
716 "X86_64_RELOC_SIGNED_2",
717 "X86_64_RELOC_SIGNED_4",
718 "X86_64_RELOC_TLV" };
727 static const char *const Table[] = {
730 "ARM_RELOC_SECTDIFF",
731 "ARM_RELOC_LOCAL_SECTDIFF",
732 "ARM_RELOC_PB_LA_PTR",
734 "ARM_THUMB_RELOC_BR22",
735 "ARM_THUMB_32BIT_BRANCH",
737 "ARM_RELOC_HALF_SECTDIFF" };
745 case Triple::aarch64: {
746 static const char *const Table[] = {
747 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
748 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
749 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
750 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
751 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
755 if (RType >= array_lengthof(Table))
762 static const char *const Table[] = {
771 "PPC_RELOC_SECTDIFF",
772 "PPC_RELOC_PB_LA_PTR",
773 "PPC_RELOC_HI16_SECTDIFF",
774 "PPC_RELOC_LO16_SECTDIFF",
775 "PPC_RELOC_HA16_SECTDIFF",
777 "PPC_RELOC_LO14_SECTDIFF",
778 "PPC_RELOC_LOCAL_SECTDIFF" };
786 case Triple::UnknownArch:
790 Result.append(res.begin(), res.end());
791 return object_error::success;
795 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
796 SmallVectorImpl<char> &Result) const {
797 MachO::any_relocation_info RE = getRelocation(Rel);
799 unsigned Arch = this->getArch();
802 raw_string_ostream fmt(fmtbuf);
803 unsigned Type = this->getAnyRelocationType(RE);
804 bool IsPCRel = this->getAnyRelocationPCRel(RE);
806 // Determine any addends that should be displayed with the relocation.
807 // These require decoding the relocation type, which is triple-specific.
809 // X86_64 has entirely custom relocation types.
810 if (Arch == Triple::x86_64) {
811 bool isPCRel = getAnyRelocationPCRel(RE);
814 case MachO::X86_64_RELOC_GOT_LOAD:
815 case MachO::X86_64_RELOC_GOT: {
816 printRelocationTargetName(this, RE, fmt);
818 if (isPCRel) fmt << "PCREL";
821 case MachO::X86_64_RELOC_SUBTRACTOR: {
822 DataRefImpl RelNext = Rel;
823 moveRelocationNext(RelNext);
824 MachO::any_relocation_info RENext = getRelocation(RelNext);
826 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
827 // X86_64_RELOC_UNSIGNED.
828 // NOTE: Scattered relocations don't exist on x86_64.
829 unsigned RType = getAnyRelocationType(RENext);
830 if (RType != MachO::X86_64_RELOC_UNSIGNED)
831 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
832 "X86_64_RELOC_SUBTRACTOR.");
834 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
835 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
836 printRelocationTargetName(this, RENext, fmt);
838 printRelocationTargetName(this, RE, fmt);
841 case MachO::X86_64_RELOC_TLV:
842 printRelocationTargetName(this, RE, fmt);
844 if (isPCRel) fmt << "P";
846 case MachO::X86_64_RELOC_SIGNED_1:
847 printRelocationTargetName(this, RE, fmt);
850 case MachO::X86_64_RELOC_SIGNED_2:
851 printRelocationTargetName(this, RE, fmt);
854 case MachO::X86_64_RELOC_SIGNED_4:
855 printRelocationTargetName(this, RE, fmt);
859 printRelocationTargetName(this, RE, fmt);
862 // X86 and ARM share some relocation types in common.
863 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
864 Arch == Triple::ppc) {
865 // Generic relocation types...
867 case MachO::GENERIC_RELOC_PAIR: // prints no info
868 return object_error::success;
869 case MachO::GENERIC_RELOC_SECTDIFF: {
870 DataRefImpl RelNext = Rel;
871 moveRelocationNext(RelNext);
872 MachO::any_relocation_info RENext = getRelocation(RelNext);
874 // X86 sect diff's must be followed by a relocation of type
875 // GENERIC_RELOC_PAIR.
876 unsigned RType = getAnyRelocationType(RENext);
878 if (RType != MachO::GENERIC_RELOC_PAIR)
879 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
880 "GENERIC_RELOC_SECTDIFF.");
882 printRelocationTargetName(this, RE, fmt);
884 printRelocationTargetName(this, RENext, fmt);
889 if (Arch == Triple::x86 || Arch == Triple::ppc) {
891 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
892 DataRefImpl RelNext = Rel;
893 moveRelocationNext(RelNext);
894 MachO::any_relocation_info RENext = getRelocation(RelNext);
896 // X86 sect diff's must be followed by a relocation of type
897 // GENERIC_RELOC_PAIR.
898 unsigned RType = getAnyRelocationType(RENext);
899 if (RType != MachO::GENERIC_RELOC_PAIR)
900 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
901 "GENERIC_RELOC_LOCAL_SECTDIFF.");
903 printRelocationTargetName(this, RE, fmt);
905 printRelocationTargetName(this, RENext, fmt);
908 case MachO::GENERIC_RELOC_TLV: {
909 printRelocationTargetName(this, RE, fmt);
911 if (IsPCRel) fmt << "P";
915 printRelocationTargetName(this, RE, fmt);
917 } else { // ARM-specific relocations
919 case MachO::ARM_RELOC_HALF:
920 case MachO::ARM_RELOC_HALF_SECTDIFF: {
921 // Half relocations steal a bit from the length field to encode
922 // whether this is an upper16 or a lower16 relocation.
923 bool isUpper = getAnyRelocationLength(RE) >> 1;
929 printRelocationTargetName(this, RE, fmt);
931 DataRefImpl RelNext = Rel;
932 moveRelocationNext(RelNext);
933 MachO::any_relocation_info RENext = getRelocation(RelNext);
935 // ARM half relocs must be followed by a relocation of type
937 unsigned RType = getAnyRelocationType(RENext);
938 if (RType != MachO::ARM_RELOC_PAIR)
939 report_fatal_error("Expected ARM_RELOC_PAIR after "
942 // NOTE: The half of the target virtual address is stashed in the
943 // address field of the secondary relocation, but we can't reverse
944 // engineer the constant offset from it without decoding the movw/movt
945 // instruction to find the other half in its immediate field.
947 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
948 // symbol/section pointer of the follow-on relocation.
949 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
951 printRelocationTargetName(this, RENext, fmt);
958 printRelocationTargetName(this, RE, fmt);
963 printRelocationTargetName(this, RE, fmt);
966 Result.append(fmtbuf.begin(), fmtbuf.end());
967 return object_error::success;
970 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
971 bool &Result) const {
972 unsigned Arch = getArch();
974 getRelocationType(Rel, Type);
978 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
980 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
981 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
982 } else if (Arch == Triple::x86_64) {
983 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
984 // an X86_64_RELOC_SUBTRACTOR.
985 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
986 DataRefImpl RelPrev = Rel;
989 getRelocationType(RelPrev, PrevType);
990 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
995 return object_error::success;
999 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1000 // guess on what the short name is. Then name is returned as a substring of the
1001 // StringRef Name passed in. The name of the dynamic library is recognized as
1002 // a framework if it has one of the two following forms:
1003 // Foo.framework/Versions/A/Foo
1004 // Foo.framework/Foo
1005 // Where A and Foo can be any string. And may contain a trailing suffix
1006 // starting with an underbar. If the Name is recognized as a framework then
1007 // isFramework is set to true else it is set to false. If the Name has a
1008 // suffix then Suffix is set to the substring in Name that contains the suffix
1009 // else it is set to a NULL StringRef.
1011 // The Name of the dynamic library is recognized as a library name if it has
1012 // one of the two following forms:
1015 // The library may have a suffix trailing the name Foo of the form:
1016 // libFoo_profile.A.dylib
1017 // libFoo_profile.dylib
1019 // The Name of the dynamic library is also recognized as a library name if it
1020 // has the following form:
1023 // If the Name of the dynamic library is none of the forms above then a NULL
1024 // StringRef is returned.
1026 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1028 StringRef &Suffix) {
1029 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1030 size_t a, b, c, d, Idx;
1032 isFramework = false;
1033 Suffix = StringRef();
1035 // Pull off the last component and make Foo point to it
1036 a = Name.rfind('/');
1037 if (a == Name.npos || a == 0)
1039 Foo = Name.slice(a+1, Name.npos);
1041 // Look for a suffix starting with a '_'
1042 Idx = Foo.rfind('_');
1043 if (Idx != Foo.npos && Foo.size() >= 2) {
1044 Suffix = Foo.slice(Idx, Foo.npos);
1045 Foo = Foo.slice(0, Idx);
1048 // First look for the form Foo.framework/Foo
1049 b = Name.rfind('/', a);
1054 F = Name.slice(Idx, Idx + Foo.size());
1055 DotFramework = Name.slice(Idx + Foo.size(),
1056 Idx + Foo.size() + sizeof(".framework/")-1);
1057 if (F == Foo && DotFramework == ".framework/") {
1062 // Next look for the form Foo.framework/Versions/A/Foo
1065 c = Name.rfind('/', b);
1066 if (c == Name.npos || c == 0)
1068 V = Name.slice(c+1, Name.npos);
1069 if (!V.startswith("Versions/"))
1071 d = Name.rfind('/', c);
1076 F = Name.slice(Idx, Idx + Foo.size());
1077 DotFramework = Name.slice(Idx + Foo.size(),
1078 Idx + Foo.size() + sizeof(".framework/")-1);
1079 if (F == Foo && DotFramework == ".framework/") {
1085 // pull off the suffix after the "." and make a point to it
1086 a = Name.rfind('.');
1087 if (a == Name.npos || a == 0)
1089 Dylib = Name.slice(a, Name.npos);
1090 if (Dylib != ".dylib")
1093 // First pull off the version letter for the form Foo.A.dylib if any.
1095 Dot = Name.slice(a-2, a-1);
1100 b = Name.rfind('/', a);
1105 // ignore any suffix after an underbar like Foo_profile.A.dylib
1106 Idx = Name.find('_', b);
1107 if (Idx != Name.npos && Idx != b) {
1108 Lib = Name.slice(b, Idx);
1109 Suffix = Name.slice(Idx, a);
1112 Lib = Name.slice(b, a);
1113 // There are incorrect library names of the form:
1114 // libATS.A_profile.dylib so check for these.
1115 if (Lib.size() >= 3) {
1116 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1118 Lib = Lib.slice(0, Lib.size()-2);
1123 Qtx = Name.slice(a, Name.npos);
1126 b = Name.rfind('/', a);
1128 Lib = Name.slice(0, a);
1130 Lib = Name.slice(b+1, a);
1131 // There are library names of the form: QT.A.qtx so check for these.
1132 if (Lib.size() >= 3) {
1133 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1135 Lib = Lib.slice(0, Lib.size()-2);
1140 // getLibraryShortNameByIndex() is used to get the short name of the library
1141 // for an undefined symbol in a linked Mach-O binary that was linked with the
1142 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1143 // It is passed the index (0 - based) of the library as translated from
1144 // GET_LIBRARY_ORDINAL (1 - based).
1145 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1146 StringRef &Res) const {
1147 if (Index >= Libraries.size())
1148 return object_error::parse_failed;
1150 // If the cache of LibrariesShortNames is not built up do that first for
1151 // all the Libraries.
1152 if (LibrariesShortNames.size() == 0) {
1153 for (unsigned i = 0; i < Libraries.size(); i++) {
1154 MachO::dylib_command D =
1155 getStruct<MachO::dylib_command>(this, Libraries[i]);
1156 if (D.dylib.name >= D.cmdsize)
1157 return object_error::parse_failed;
1158 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1159 StringRef Name = StringRef(P);
1160 if (D.dylib.name+Name.size() >= D.cmdsize)
1161 return object_error::parse_failed;
1164 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1165 if (shortName.empty())
1166 LibrariesShortNames.push_back(Name);
1168 LibrariesShortNames.push_back(shortName);
1172 Res = LibrariesShortNames[Index];
1173 return object_error::success;
1176 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1177 return getSymbolByIndex(0);
1180 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1183 return basic_symbol_iterator(SymbolRef(DRI, this));
1185 MachO::symtab_command Symtab = getSymtabLoadCommand();
1186 unsigned SymbolTableEntrySize = is64Bit() ?
1187 sizeof(MachO::nlist_64) :
1188 sizeof(MachO::nlist);
1189 unsigned Offset = Symtab.symoff +
1190 Symtab.nsyms * SymbolTableEntrySize;
1191 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1192 return basic_symbol_iterator(SymbolRef(DRI, this));
1195 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1200 MachO::symtab_command Symtab = getSymtabLoadCommand();
1201 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1202 unsigned SymbolTableEntrySize =
1203 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1204 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1205 DRI.p += Index * SymbolTableEntrySize;
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1209 section_iterator MachOObjectFile::section_begin() const {
1211 return section_iterator(SectionRef(DRI, this));
1214 section_iterator MachOObjectFile::section_end() const {
1216 DRI.d.a = Sections.size();
1217 return section_iterator(SectionRef(DRI, this));
1220 uint8_t MachOObjectFile::getBytesInAddress() const {
1221 return is64Bit() ? 8 : 4;
1224 StringRef MachOObjectFile::getFileFormatName() const {
1225 unsigned CPUType = getCPUType(this);
1228 case llvm::MachO::CPU_TYPE_I386:
1229 return "Mach-O 32-bit i386";
1230 case llvm::MachO::CPU_TYPE_ARM:
1231 return "Mach-O arm";
1232 case llvm::MachO::CPU_TYPE_POWERPC:
1233 return "Mach-O 32-bit ppc";
1235 return "Mach-O 32-bit unknown";
1240 case llvm::MachO::CPU_TYPE_X86_64:
1241 return "Mach-O 64-bit x86-64";
1242 case llvm::MachO::CPU_TYPE_ARM64:
1243 return "Mach-O arm64";
1244 case llvm::MachO::CPU_TYPE_POWERPC64:
1245 return "Mach-O 64-bit ppc64";
1247 return "Mach-O 64-bit unknown";
1251 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1253 case llvm::MachO::CPU_TYPE_I386:
1255 case llvm::MachO::CPU_TYPE_X86_64:
1256 return Triple::x86_64;
1257 case llvm::MachO::CPU_TYPE_ARM:
1259 case llvm::MachO::CPU_TYPE_ARM64:
1260 return Triple::aarch64;
1261 case llvm::MachO::CPU_TYPE_POWERPC:
1263 case llvm::MachO::CPU_TYPE_POWERPC64:
1264 return Triple::ppc64;
1266 return Triple::UnknownArch;
1270 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1271 const char **McpuDefault) {
1273 *McpuDefault = nullptr;
1276 case MachO::CPU_TYPE_I386:
1277 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1278 case MachO::CPU_SUBTYPE_I386_ALL:
1279 return Triple("i386-apple-darwin");
1283 case MachO::CPU_TYPE_X86_64:
1284 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1285 case MachO::CPU_SUBTYPE_X86_64_ALL:
1286 return Triple("x86_64-apple-darwin");
1287 case MachO::CPU_SUBTYPE_X86_64_H:
1288 return Triple("x86_64h-apple-darwin");
1292 case MachO::CPU_TYPE_ARM:
1293 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1294 case MachO::CPU_SUBTYPE_ARM_V4T:
1295 return Triple("armv4t-apple-darwin");
1296 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1297 return Triple("armv5e-apple-darwin");
1298 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1299 return Triple("xscale-apple-darwin");
1300 case MachO::CPU_SUBTYPE_ARM_V6:
1301 return Triple("armv6-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_V6M:
1304 *McpuDefault = "cortex-m0";
1305 return Triple("armv6m-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V7:
1307 return Triple("armv7-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_V7EM:
1310 *McpuDefault = "cortex-m4";
1311 return Triple("armv7em-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V7K:
1313 return Triple("armv7k-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V7M:
1316 *McpuDefault = "cortex-m3";
1317 return Triple("armv7m-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7S:
1319 return Triple("armv7s-apple-darwin");
1323 case MachO::CPU_TYPE_ARM64:
1324 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1325 case MachO::CPU_SUBTYPE_ARM64_ALL:
1326 return Triple("arm64-apple-darwin");
1330 case MachO::CPU_TYPE_POWERPC:
1331 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1332 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1333 return Triple("ppc-apple-darwin");
1337 case MachO::CPU_TYPE_POWERPC64:
1338 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1339 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1340 return Triple("ppc64-apple-darwin");
1349 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1350 const char **McpuDefault) {
1352 *McpuDefault = nullptr;
1355 case MachO::CPU_TYPE_ARM:
1356 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1357 case MachO::CPU_SUBTYPE_ARM_V4T:
1358 return Triple("thumbv4t-apple-darwin");
1359 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1360 return Triple("thumbv5e-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1362 return Triple("xscale-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V6:
1364 return Triple("thumbv6-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_V6M:
1367 *McpuDefault = "cortex-m0";
1368 return Triple("thumbv6m-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V7:
1370 return Triple("thumbv7-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V7EM:
1373 *McpuDefault = "cortex-m4";
1374 return Triple("thumbv7em-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V7K:
1376 return Triple("thumbv7k-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V7M:
1379 *McpuDefault = "cortex-m3";
1380 return Triple("thumbv7m-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7S:
1382 return Triple("thumbv7s-apple-darwin");
1391 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1392 const char **McpuDefault,
1393 Triple *ThumbTriple) {
1394 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1395 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1400 Triple MachOObjectFile::getHostArch() {
1401 return Triple(sys::getDefaultTargetTriple());
1404 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1405 return StringSwitch<bool>(ArchFlag)
1407 .Case("x86_64", true)
1408 .Case("x86_64h", true)
1409 .Case("armv4t", true)
1411 .Case("armv5e", true)
1412 .Case("armv6", true)
1413 .Case("armv6m", true)
1414 .Case("armv7em", true)
1415 .Case("armv7k", true)
1416 .Case("armv7m", true)
1417 .Case("armv7s", true)
1418 .Case("arm64", true)
1420 .Case("ppc64", true)
1424 unsigned MachOObjectFile::getArch() const {
1425 return getArch(getCPUType(this));
1428 Triple MachOObjectFile::getArch(const char **McpuDefault,
1429 Triple *ThumbTriple) const {
1432 MachO::mach_header_64 H_64;
1433 H_64 = getHeader64();
1434 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1435 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1438 MachO::mach_header H;
1440 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1441 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1447 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1450 return section_rel_begin(DRI);
1453 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1456 return section_rel_end(DRI);
1459 dice_iterator MachOObjectFile::begin_dices() const {
1461 if (!DataInCodeLoadCmd)
1462 return dice_iterator(DiceRef(DRI, this));
1464 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1465 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1466 return dice_iterator(DiceRef(DRI, this));
1469 dice_iterator MachOObjectFile::end_dices() const {
1471 if (!DataInCodeLoadCmd)
1472 return dice_iterator(DiceRef(DRI, this));
1474 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1475 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1476 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1477 return dice_iterator(DiceRef(DRI, this));
1480 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1481 : Trie(T), Malformed(false), Done(false) { }
1483 void ExportEntry::moveToFirst() {
1485 pushDownUntilBottom();
1488 void ExportEntry::moveToEnd() {
1493 bool ExportEntry::operator==(const ExportEntry &Other) const {
1494 // Common case, one at end, other iterating from begin.
1495 if (Done || Other.Done)
1496 return (Done == Other.Done);
1497 // Not equal if different stack sizes.
1498 if (Stack.size() != Other.Stack.size())
1500 // Not equal if different cumulative strings.
1501 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1503 // Equal if all nodes in both stacks match.
1504 for (unsigned i=0; i < Stack.size(); ++i) {
1505 if (Stack[i].Start != Other.Stack[i].Start)
1511 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1513 uint64_t Result = decodeULEB128(Ptr, &Count);
1515 if (Ptr > Trie.end()) {
1522 StringRef ExportEntry::name() const {
1523 return CumulativeString.str();
1526 uint64_t ExportEntry::flags() const {
1527 return Stack.back().Flags;
1530 uint64_t ExportEntry::address() const {
1531 return Stack.back().Address;
1534 uint64_t ExportEntry::other() const {
1535 return Stack.back().Other;
1538 StringRef ExportEntry::otherName() const {
1539 const char* ImportName = Stack.back().ImportName;
1541 return StringRef(ImportName);
1545 uint32_t ExportEntry::nodeOffset() const {
1546 return Stack.back().Start - Trie.begin();
1549 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1550 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1551 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1552 ParentStringLength(0), IsExportNode(false) {
1555 void ExportEntry::pushNode(uint64_t offset) {
1556 const uint8_t *Ptr = Trie.begin() + offset;
1557 NodeState State(Ptr);
1558 uint64_t ExportInfoSize = readULEB128(State.Current);
1559 State.IsExportNode = (ExportInfoSize != 0);
1560 const uint8_t* Children = State.Current + ExportInfoSize;
1561 if (State.IsExportNode) {
1562 State.Flags = readULEB128(State.Current);
1563 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1565 State.Other = readULEB128(State.Current); // dylib ordinal
1566 State.ImportName = reinterpret_cast<const char*>(State.Current);
1568 State.Address = readULEB128(State.Current);
1569 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1570 State.Other = readULEB128(State.Current);
1573 State.ChildCount = *Children;
1574 State.Current = Children + 1;
1575 State.NextChildIndex = 0;
1576 State.ParentStringLength = CumulativeString.size();
1577 Stack.push_back(State);
1580 void ExportEntry::pushDownUntilBottom() {
1581 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1582 NodeState &Top = Stack.back();
1583 CumulativeString.resize(Top.ParentStringLength);
1584 for (;*Top.Current != 0; Top.Current++) {
1585 char C = *Top.Current;
1586 CumulativeString.push_back(C);
1589 uint64_t childNodeIndex = readULEB128(Top.Current);
1590 Top.NextChildIndex += 1;
1591 pushNode(childNodeIndex);
1593 if (!Stack.back().IsExportNode) {
1599 // We have a trie data structure and need a way to walk it that is compatible
1600 // with the C++ iterator model. The solution is a non-recursive depth first
1601 // traversal where the iterator contains a stack of parent nodes along with a
1602 // string that is the accumulation of all edge strings along the parent chain
1605 // There is one "export" node for each exported symbol. But because some
1606 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1607 // node may have child nodes too.
1609 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1610 // child until hitting a node with no children (which is an export node or
1611 // else the trie is malformed). On the way down, each node is pushed on the
1612 // stack ivar. If there is no more ways down, it pops up one and tries to go
1613 // down a sibling path until a childless node is reached.
1614 void ExportEntry::moveNext() {
1615 if (Stack.empty() || !Stack.back().IsExportNode) {
1622 while (!Stack.empty()) {
1623 NodeState &Top = Stack.back();
1624 if (Top.NextChildIndex < Top.ChildCount) {
1625 pushDownUntilBottom();
1626 // Now at the next export node.
1629 if (Top.IsExportNode) {
1630 // This node has no children but is itself an export node.
1631 CumulativeString.resize(Top.ParentStringLength);
1640 iterator_range<export_iterator>
1641 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1642 ExportEntry Start(Trie);
1643 if (Trie.size() == 0)
1646 Start.moveToFirst();
1648 ExportEntry Finish(Trie);
1651 return iterator_range<export_iterator>(export_iterator(Start),
1652 export_iterator(Finish));
1655 iterator_range<export_iterator> MachOObjectFile::exports() const {
1656 return exports(getDyldInfoExportsTrie());
1660 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1661 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1662 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1663 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1665 void MachORebaseEntry::moveToFirst() {
1666 Ptr = Opcodes.begin();
1670 void MachORebaseEntry::moveToEnd() {
1671 Ptr = Opcodes.end();
1672 RemainingLoopCount = 0;
1676 void MachORebaseEntry::moveNext() {
1677 // If in the middle of some loop, move to next rebasing in loop.
1678 SegmentOffset += AdvanceAmount;
1679 if (RemainingLoopCount) {
1680 --RemainingLoopCount;
1683 if (Ptr == Opcodes.end()) {
1688 while (More && !Malformed) {
1689 // Parse next opcode and set up next loop.
1690 uint8_t Byte = *Ptr++;
1691 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1692 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1694 case MachO::REBASE_OPCODE_DONE:
1698 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1700 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1701 RebaseType = ImmValue;
1704 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1705 << "RebaseType=" << (int) RebaseType << "\n");
1707 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1708 SegmentIndex = ImmValue;
1709 SegmentOffset = readULEB128();
1712 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1713 << "SegmentIndex=" << SegmentIndex << ", "
1714 << format("SegmentOffset=0x%06X", SegmentOffset)
1717 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1718 SegmentOffset += readULEB128();
1719 DEBUG_WITH_TYPE("mach-o-rebase",
1720 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1721 << format("SegmentOffset=0x%06X",
1722 SegmentOffset) << "\n");
1724 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1725 SegmentOffset += ImmValue * PointerSize;
1726 DEBUG_WITH_TYPE("mach-o-rebase",
1727 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1728 << format("SegmentOffset=0x%06X",
1729 SegmentOffset) << "\n");
1731 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1732 AdvanceAmount = PointerSize;
1733 RemainingLoopCount = ImmValue - 1;
1736 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1737 << format("SegmentOffset=0x%06X", SegmentOffset)
1738 << ", AdvanceAmount=" << AdvanceAmount
1739 << ", RemainingLoopCount=" << RemainingLoopCount
1742 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1743 AdvanceAmount = PointerSize;
1744 RemainingLoopCount = readULEB128() - 1;
1747 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1748 << format("SegmentOffset=0x%06X", SegmentOffset)
1749 << ", AdvanceAmount=" << AdvanceAmount
1750 << ", RemainingLoopCount=" << RemainingLoopCount
1753 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1754 AdvanceAmount = readULEB128() + PointerSize;
1755 RemainingLoopCount = 0;
1758 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1759 << format("SegmentOffset=0x%06X", SegmentOffset)
1760 << ", AdvanceAmount=" << AdvanceAmount
1761 << ", RemainingLoopCount=" << RemainingLoopCount
1764 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1765 RemainingLoopCount = readULEB128() - 1;
1766 AdvanceAmount = readULEB128() + PointerSize;
1769 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1770 << format("SegmentOffset=0x%06X", SegmentOffset)
1771 << ", AdvanceAmount=" << AdvanceAmount
1772 << ", RemainingLoopCount=" << RemainingLoopCount
1781 uint64_t MachORebaseEntry::readULEB128() {
1783 uint64_t Result = decodeULEB128(Ptr, &Count);
1785 if (Ptr > Opcodes.end()) {
1786 Ptr = Opcodes.end();
1792 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1794 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1796 StringRef MachORebaseEntry::typeName() const {
1797 switch (RebaseType) {
1798 case MachO::REBASE_TYPE_POINTER:
1800 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1801 return "text abs32";
1802 case MachO::REBASE_TYPE_TEXT_PCREL32:
1803 return "text rel32";
1808 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1809 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1810 return (Ptr == Other.Ptr) &&
1811 (RemainingLoopCount == Other.RemainingLoopCount) &&
1812 (Done == Other.Done);
1815 iterator_range<rebase_iterator>
1816 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1817 MachORebaseEntry Start(Opcodes, is64);
1818 Start.moveToFirst();
1820 MachORebaseEntry Finish(Opcodes, is64);
1823 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1824 rebase_iterator(Finish));
1827 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1828 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1832 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1834 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1835 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1836 BindType(0), PointerSize(is64Bit ? 8 : 4),
1837 TableKind(BK), Malformed(false), Done(false) {}
1839 void MachOBindEntry::moveToFirst() {
1840 Ptr = Opcodes.begin();
1844 void MachOBindEntry::moveToEnd() {
1845 Ptr = Opcodes.end();
1846 RemainingLoopCount = 0;
1850 void MachOBindEntry::moveNext() {
1851 // If in the middle of some loop, move to next binding in loop.
1852 SegmentOffset += AdvanceAmount;
1853 if (RemainingLoopCount) {
1854 --RemainingLoopCount;
1857 if (Ptr == Opcodes.end()) {
1862 while (More && !Malformed) {
1863 // Parse next opcode and set up next loop.
1864 uint8_t Byte = *Ptr++;
1865 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1866 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1867 int8_t SignExtended;
1868 const uint8_t *SymStart;
1870 case MachO::BIND_OPCODE_DONE:
1871 if (TableKind == Kind::Lazy) {
1872 // Lazying bindings have a DONE opcode between entries. Need to ignore
1873 // it to advance to next entry. But need not if this is last entry.
1874 bool NotLastEntry = false;
1875 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1877 NotLastEntry = true;
1886 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1888 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1892 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1893 << "Ordinal=" << Ordinal << "\n");
1895 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1896 Ordinal = readULEB128();
1899 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1900 << "Ordinal=" << Ordinal << "\n");
1902 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1904 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1905 Ordinal = SignExtended;
1910 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1911 << "Ordinal=" << Ordinal << "\n");
1913 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1919 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1924 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1925 << "SymbolName=" << SymbolName << "\n");
1926 if (TableKind == Kind::Weak) {
1927 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1931 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1932 BindType = ImmValue;
1935 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1936 << "BindType=" << (int)BindType << "\n");
1938 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1939 Addend = readSLEB128();
1940 if (TableKind == Kind::Lazy)
1944 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1945 << "Addend=" << Addend << "\n");
1947 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1948 SegmentIndex = ImmValue;
1949 SegmentOffset = readULEB128();
1952 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1953 << "SegmentIndex=" << SegmentIndex << ", "
1954 << format("SegmentOffset=0x%06X", SegmentOffset)
1957 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1958 SegmentOffset += readULEB128();
1959 DEBUG_WITH_TYPE("mach-o-bind",
1960 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1961 << format("SegmentOffset=0x%06X",
1962 SegmentOffset) << "\n");
1964 case MachO::BIND_OPCODE_DO_BIND:
1965 AdvanceAmount = PointerSize;
1966 RemainingLoopCount = 0;
1967 DEBUG_WITH_TYPE("mach-o-bind",
1968 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1969 << format("SegmentOffset=0x%06X",
1970 SegmentOffset) << "\n");
1972 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1973 AdvanceAmount = readULEB128() + PointerSize;
1974 RemainingLoopCount = 0;
1975 if (TableKind == Kind::Lazy)
1979 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1980 << format("SegmentOffset=0x%06X", SegmentOffset)
1981 << ", AdvanceAmount=" << AdvanceAmount
1982 << ", RemainingLoopCount=" << RemainingLoopCount
1985 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1986 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1987 RemainingLoopCount = 0;
1988 if (TableKind == Kind::Lazy)
1990 DEBUG_WITH_TYPE("mach-o-bind",
1992 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1993 << format("SegmentOffset=0x%06X",
1994 SegmentOffset) << "\n");
1996 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1997 RemainingLoopCount = readULEB128() - 1;
1998 AdvanceAmount = readULEB128() + PointerSize;
1999 if (TableKind == Kind::Lazy)
2003 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2004 << format("SegmentOffset=0x%06X", SegmentOffset)
2005 << ", AdvanceAmount=" << AdvanceAmount
2006 << ", RemainingLoopCount=" << RemainingLoopCount
2015 uint64_t MachOBindEntry::readULEB128() {
2017 uint64_t Result = decodeULEB128(Ptr, &Count);
2019 if (Ptr > Opcodes.end()) {
2020 Ptr = Opcodes.end();
2026 int64_t MachOBindEntry::readSLEB128() {
2028 int64_t Result = decodeSLEB128(Ptr, &Count);
2030 if (Ptr > Opcodes.end()) {
2031 Ptr = Opcodes.end();
2038 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2040 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2042 StringRef MachOBindEntry::typeName() const {
2044 case MachO::BIND_TYPE_POINTER:
2046 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2047 return "text abs32";
2048 case MachO::BIND_TYPE_TEXT_PCREL32:
2049 return "text rel32";
2054 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2056 int64_t MachOBindEntry::addend() const { return Addend; }
2058 uint32_t MachOBindEntry::flags() const { return Flags; }
2060 int MachOBindEntry::ordinal() const { return Ordinal; }
2062 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2063 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2064 return (Ptr == Other.Ptr) &&
2065 (RemainingLoopCount == Other.RemainingLoopCount) &&
2066 (Done == Other.Done);
2069 iterator_range<bind_iterator>
2070 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2071 MachOBindEntry::Kind BKind) {
2072 MachOBindEntry Start(Opcodes, is64, BKind);
2073 Start.moveToFirst();
2075 MachOBindEntry Finish(Opcodes, is64, BKind);
2078 return iterator_range<bind_iterator>(bind_iterator(Start),
2079 bind_iterator(Finish));
2082 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2083 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2084 MachOBindEntry::Kind::Regular);
2087 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2088 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2089 MachOBindEntry::Kind::Lazy);
2092 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2093 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2094 MachOBindEntry::Kind::Weak);
2098 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2099 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2100 return parseSegmentOrSectionName(Raw.data());
2104 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2105 const section_base *Base =
2106 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2107 return makeArrayRef(Base->sectname);
2111 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2112 const section_base *Base =
2113 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2114 return makeArrayRef(Base->segname);
2118 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2120 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2122 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2125 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2126 const MachO::any_relocation_info &RE) const {
2127 if (isLittleEndian())
2128 return RE.r_word1 & 0xffffff;
2129 return RE.r_word1 >> 8;
2132 bool MachOObjectFile::getPlainRelocationExternal(
2133 const MachO::any_relocation_info &RE) const {
2134 if (isLittleEndian())
2135 return (RE.r_word1 >> 27) & 1;
2136 return (RE.r_word1 >> 4) & 1;
2139 bool MachOObjectFile::getScatteredRelocationScattered(
2140 const MachO::any_relocation_info &RE) const {
2141 return RE.r_word0 >> 31;
2144 uint32_t MachOObjectFile::getScatteredRelocationValue(
2145 const MachO::any_relocation_info &RE) const {
2149 uint32_t MachOObjectFile::getScatteredRelocationType(
2150 const MachO::any_relocation_info &RE) const {
2151 return (RE.r_word0 >> 24) & 0xf;
2154 unsigned MachOObjectFile::getAnyRelocationAddress(
2155 const MachO::any_relocation_info &RE) const {
2156 if (isRelocationScattered(RE))
2157 return getScatteredRelocationAddress(RE);
2158 return getPlainRelocationAddress(RE);
2161 unsigned MachOObjectFile::getAnyRelocationPCRel(
2162 const MachO::any_relocation_info &RE) const {
2163 if (isRelocationScattered(RE))
2164 return getScatteredRelocationPCRel(this, RE);
2165 return getPlainRelocationPCRel(this, RE);
2168 unsigned MachOObjectFile::getAnyRelocationLength(
2169 const MachO::any_relocation_info &RE) const {
2170 if (isRelocationScattered(RE))
2171 return getScatteredRelocationLength(RE);
2172 return getPlainRelocationLength(this, RE);
2176 MachOObjectFile::getAnyRelocationType(
2177 const MachO::any_relocation_info &RE) const {
2178 if (isRelocationScattered(RE))
2179 return getScatteredRelocationType(RE);
2180 return getPlainRelocationType(this, RE);
2184 MachOObjectFile::getRelocationSection(
2185 const MachO::any_relocation_info &RE) const {
2186 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2187 return *section_end();
2188 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2191 return SectionRef(DRI, this);
2194 MachOObjectFile::LoadCommandInfo
2195 MachOObjectFile::getFirstLoadCommandInfo() const {
2196 MachOObjectFile::LoadCommandInfo Load;
2198 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2199 sizeof(MachO::mach_header);
2200 Load.Ptr = getPtr(this, HeaderSize);
2201 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2205 MachOObjectFile::LoadCommandInfo
2206 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2207 MachOObjectFile::LoadCommandInfo Next;
2208 Next.Ptr = L.Ptr + L.C.cmdsize;
2209 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2213 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2214 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2217 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2218 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2221 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2222 unsigned Index) const {
2223 const char *Sec = getSectionPtr(this, L, Index);
2224 return getStruct<MachO::section>(this, Sec);
2227 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2228 unsigned Index) const {
2229 const char *Sec = getSectionPtr(this, L, Index);
2230 return getStruct<MachO::section_64>(this, Sec);
2234 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2235 const char *P = reinterpret_cast<const char *>(DRI.p);
2236 return getStruct<MachO::nlist>(this, P);
2240 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2241 const char *P = reinterpret_cast<const char *>(DRI.p);
2242 return getStruct<MachO::nlist_64>(this, P);
2245 MachO::linkedit_data_command
2246 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2247 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2250 MachO::segment_command
2251 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2252 return getStruct<MachO::segment_command>(this, L.Ptr);
2255 MachO::segment_command_64
2256 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2257 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2260 MachO::linker_option_command
2261 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2262 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2265 MachO::version_min_command
2266 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2267 return getStruct<MachO::version_min_command>(this, L.Ptr);
2270 MachO::dylib_command
2271 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2272 return getStruct<MachO::dylib_command>(this, L.Ptr);
2275 MachO::dyld_info_command
2276 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2277 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2280 MachO::dylinker_command
2281 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2282 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2286 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2287 return getStruct<MachO::uuid_command>(this, L.Ptr);
2290 MachO::rpath_command
2291 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2292 return getStruct<MachO::rpath_command>(this, L.Ptr);
2295 MachO::source_version_command
2296 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2297 return getStruct<MachO::source_version_command>(this, L.Ptr);
2300 MachO::entry_point_command
2301 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2302 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2305 MachO::encryption_info_command
2306 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2307 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2310 MachO::encryption_info_command_64
2311 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2312 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2315 MachO::sub_framework_command
2316 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2317 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2320 MachO::sub_umbrella_command
2321 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2322 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2325 MachO::sub_library_command
2326 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2327 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2330 MachO::sub_client_command
2331 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2332 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2335 MachO::any_relocation_info
2336 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2341 MachO::section_64 Sect = getSection64(Sec);
2342 Offset = Sect.reloff;
2344 MachO::section Sect = getSection(Sec);
2345 Offset = Sect.reloff;
2348 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2349 getPtr(this, Offset)) + Rel.d.b;
2350 return getStruct<MachO::any_relocation_info>(
2351 this, reinterpret_cast<const char *>(P));
2354 MachO::data_in_code_entry
2355 MachOObjectFile::getDice(DataRefImpl Rel) const {
2356 const char *P = reinterpret_cast<const char *>(Rel.p);
2357 return getStruct<MachO::data_in_code_entry>(this, P);
2360 MachO::mach_header MachOObjectFile::getHeader() const {
2361 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2364 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2365 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2368 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2369 const MachO::dysymtab_command &DLC,
2370 unsigned Index) const {
2371 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2372 return getStruct<uint32_t>(this, getPtr(this, Offset));
2375 MachO::data_in_code_entry
2376 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2377 unsigned Index) const {
2378 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2379 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2382 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2384 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2386 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2387 MachO::symtab_command Cmd;
2388 Cmd.cmd = MachO::LC_SYMTAB;
2389 Cmd.cmdsize = sizeof(MachO::symtab_command);
2397 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2398 if (DysymtabLoadCmd)
2399 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2401 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2402 MachO::dysymtab_command Cmd;
2403 Cmd.cmd = MachO::LC_DYSYMTAB;
2404 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2415 Cmd.extrefsymoff = 0;
2416 Cmd.nextrefsyms = 0;
2417 Cmd.indirectsymoff = 0;
2418 Cmd.nindirectsyms = 0;
2426 MachO::linkedit_data_command
2427 MachOObjectFile::getDataInCodeLoadCommand() const {
2428 if (DataInCodeLoadCmd)
2429 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2431 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2432 MachO::linkedit_data_command Cmd;
2433 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2434 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2440 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2441 if (!DyldInfoLoadCmd)
2442 return ArrayRef<uint8_t>();
2444 MachO::dyld_info_command DyldInfo
2445 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2446 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2447 getPtr(this, DyldInfo.rebase_off));
2448 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2451 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2452 if (!DyldInfoLoadCmd)
2453 return ArrayRef<uint8_t>();
2455 MachO::dyld_info_command DyldInfo
2456 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2457 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2458 getPtr(this, DyldInfo.bind_off));
2459 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2462 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2463 if (!DyldInfoLoadCmd)
2464 return ArrayRef<uint8_t>();
2466 MachO::dyld_info_command DyldInfo
2467 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2468 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2469 getPtr(this, DyldInfo.weak_bind_off));
2470 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2473 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2474 if (!DyldInfoLoadCmd)
2475 return ArrayRef<uint8_t>();
2477 MachO::dyld_info_command DyldInfo
2478 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2479 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2480 getPtr(this, DyldInfo.lazy_bind_off));
2481 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2484 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2485 if (!DyldInfoLoadCmd)
2486 return ArrayRef<uint8_t>();
2488 MachO::dyld_info_command DyldInfo
2489 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2490 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2491 getPtr(this, DyldInfo.export_off));
2492 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2495 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2497 return ArrayRef<uint8_t>();
2498 // Returning a pointer is fine as uuid doesn't need endian swapping.
2499 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2500 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2503 StringRef MachOObjectFile::getStringTableData() const {
2504 MachO::symtab_command S = getSymtabLoadCommand();
2505 return getData().substr(S.stroff, S.strsize);
2508 bool MachOObjectFile::is64Bit() const {
2509 return getType() == getMachOType(false, true) ||
2510 getType() == getMachOType(true, true);
2513 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2514 SmallVectorImpl<uint64_t> &Out) const {
2515 DataExtractor extractor(ObjectFile::getData(), true, 0);
2517 uint32_t offset = Index;
2519 while (uint64_t delta = extractor.getULEB128(&offset)) {
2521 Out.push_back(data);
2525 bool MachOObjectFile::isRelocatableObject() const {
2526 return getHeader().filetype == MachO::MH_OBJECT;
2529 ErrorOr<std::unique_ptr<MachOObjectFile>>
2530 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2531 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2533 std::unique_ptr<MachOObjectFile> Ret;
2534 if (Magic == "\xFE\xED\xFA\xCE")
2535 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2536 else if (Magic == "\xCE\xFA\xED\xFE")
2537 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2538 else if (Magic == "\xFE\xED\xFA\xCF")
2539 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2540 else if (Magic == "\xCF\xFA\xED\xFE")
2541 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2543 return object_error::parse_failed;
2547 return std::move(Ret);