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 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 == SegmentLoadType) {
263 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
264 for (unsigned J = 0; J < NumSections; ++J) {
265 const char *Sec = getSectionPtr(this, Load, J);
266 Sections.push_back(Sec);
268 if (isPageZeroSegment(this, Load))
269 HasPageZeroSegment = true;
270 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
271 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
272 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
273 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
274 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
275 Libraries.push_back(Load.Ptr);
278 if (I == LoadCommandCount - 1)
281 Load = getNextLoadCommandInfo(Load);
285 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
286 unsigned SymbolTableEntrySize = is64Bit() ?
287 sizeof(MachO::nlist_64) :
288 sizeof(MachO::nlist);
289 Symb.p += SymbolTableEntrySize;
292 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
293 StringRef &Res) const {
294 StringRef StringTable = getStringTableData();
295 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
296 const char *Start = &StringTable.data()[Entry.n_strx];
297 Res = StringRef(Start);
298 return object_error::success;
301 // getIndirectName() returns the name of the alias'ed symbol who's string table
302 // index is in the n_value field.
303 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
304 StringRef &Res) const {
305 StringRef StringTable = getStringTableData();
308 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
309 NValue = Entry.n_value;
310 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
311 return object_error::parse_failed;
313 MachO::nlist Entry = getSymbolTableEntry(Symb);
314 NValue = Entry.n_value;
315 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
316 return object_error::parse_failed;
318 if (NValue >= StringTable.size())
319 return object_error::parse_failed;
320 const char *Start = &StringTable.data()[NValue];
321 Res = StringRef(Start);
322 return object_error::success;
325 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
326 uint64_t &Res) const {
328 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
329 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
331 Res = UnknownAddressOrSize;
335 MachO::nlist Entry = getSymbolTableEntry(Symb);
336 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
338 Res = UnknownAddressOrSize;
342 return object_error::success;
345 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
346 uint32_t &Result) const {
347 uint32_t flags = getSymbolFlags(DRI);
348 if (flags & SymbolRef::SF_Common) {
349 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
350 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
354 return object_error::success;
357 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
358 uint64_t &Result) const {
359 uint64_t BeginOffset;
360 uint64_t EndOffset = 0;
361 uint8_t SectionIndex;
363 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
365 getSymbolAddress(DRI, Value);
366 if (Value == UnknownAddressOrSize) {
367 Result = UnknownAddressOrSize;
368 return object_error::success;
373 SectionIndex = Entry.n_sect;
375 uint32_t flags = getSymbolFlags(DRI);
376 if (flags & SymbolRef::SF_Common)
379 Result = UnknownAddressOrSize;
380 return object_error::success;
382 // Unfortunately symbols are unsorted so we need to touch all
383 // symbols from load command
384 for (const SymbolRef &Symbol : symbols()) {
385 DataRefImpl DRI = Symbol.getRawDataRefImpl();
386 Entry = getSymbolTableEntryBase(this, DRI);
387 getSymbolAddress(DRI, Value);
388 if (Value == UnknownAddressOrSize)
390 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
391 if (!EndOffset || Value < EndOffset)
396 Sec.d.a = SectionIndex-1;
397 uint64_t Size = getSectionSize(Sec);
398 EndOffset = getSectionAddress(Sec);
401 Result = EndOffset - BeginOffset;
402 return object_error::success;
405 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
406 SymbolRef::Type &Res) const {
407 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
408 uint8_t n_type = Entry.n_type;
410 Res = SymbolRef::ST_Other;
412 // If this is a STAB debugging symbol, we can do nothing more.
413 if (n_type & MachO::N_STAB) {
414 Res = SymbolRef::ST_Debug;
415 return object_error::success;
418 switch (n_type & MachO::N_TYPE) {
420 Res = SymbolRef::ST_Unknown;
423 Res = SymbolRef::ST_Function;
426 return object_error::success;
429 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
430 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
432 uint8_t MachOType = Entry.n_type;
433 uint16_t MachOFlags = Entry.n_desc;
435 uint32_t Result = SymbolRef::SF_None;
437 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
438 Result |= SymbolRef::SF_Undefined;
440 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
441 Result |= SymbolRef::SF_Indirect;
443 if (MachOType & MachO::N_STAB)
444 Result |= SymbolRef::SF_FormatSpecific;
446 if (MachOType & MachO::N_EXT) {
447 Result |= SymbolRef::SF_Global;
448 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
450 getSymbolAddress(DRI, Value);
451 if (Value && Value != UnknownAddressOrSize)
452 Result |= SymbolRef::SF_Common;
456 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
457 Result |= SymbolRef::SF_Weak;
459 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
460 Result |= SymbolRef::SF_Thumb;
462 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
463 Result |= SymbolRef::SF_Absolute;
468 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
469 section_iterator &Res) const {
470 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
471 uint8_t index = Entry.n_sect;
478 Res = section_iterator(SectionRef(DRI, this));
481 return object_error::success;
484 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
488 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
489 StringRef &Result) const {
490 ArrayRef<char> Raw = getSectionRawName(Sec);
491 Result = parseSegmentOrSectionName(Raw.data());
492 return object_error::success;
495 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
497 return getSection64(Sec).addr;
498 return getSection(Sec).addr;
501 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
503 return getSection64(Sec).size;
504 return getSection(Sec).size;
507 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
508 StringRef &Res) const {
513 MachO::section_64 Sect = getSection64(Sec);
514 Offset = Sect.offset;
517 MachO::section Sect = getSection(Sec);
518 Offset = Sect.offset;
522 Res = this->getData().substr(Offset, Size);
523 return object_error::success;
526 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
529 MachO::section_64 Sect = getSection64(Sec);
532 MachO::section Sect = getSection(Sec);
536 return uint64_t(1) << Align;
539 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
540 uint32_t Flags = getSectionFlags(this, Sec);
541 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
544 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
545 uint32_t Flags = getSectionFlags(this, Sec);
546 unsigned SectionType = Flags & MachO::SECTION_TYPE;
547 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
548 !(SectionType == MachO::S_ZEROFILL ||
549 SectionType == MachO::S_GB_ZEROFILL);
552 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
553 uint32_t Flags = getSectionFlags(this, Sec);
554 unsigned SectionType = Flags & MachO::SECTION_TYPE;
555 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
556 (SectionType == MachO::S_ZEROFILL ||
557 SectionType == MachO::S_GB_ZEROFILL);
560 bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
561 // FIXME: Unimplemented.
565 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
566 // FIXME: Unimplemented.
570 bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
571 uint32_t Flags = getSectionFlags(this, Sec);
572 unsigned SectionType = Flags & MachO::SECTION_TYPE;
573 return SectionType == MachO::S_ZEROFILL ||
574 SectionType == MachO::S_GB_ZEROFILL;
577 bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
578 // Consider using the code from isSectionText to look for __const sections.
579 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
580 // to use section attributes to distinguish code from data.
582 // FIXME: Unimplemented.
586 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
587 DataRefImpl Symb) const {
589 this->getSymbolType(Symb, ST);
590 if (ST == SymbolRef::ST_Unknown)
593 uint64_t SectBegin = getSectionAddress(Sec);
594 uint64_t SectEnd = getSectionSize(Sec);
595 SectEnd += SectBegin;
598 getSymbolAddress(Symb, SymAddr);
599 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
602 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
606 return relocation_iterator(RelocationRef(Ret, this));
610 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
613 MachO::section_64 Sect = getSection64(Sec);
616 MachO::section Sect = getSection(Sec);
623 return relocation_iterator(RelocationRef(Ret, this));
626 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
630 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
631 uint64_t &Res) const {
633 getRelocationOffset(Rel, Offset);
637 uint64_t SecAddress = getSectionAddress(Sec);
638 Res = SecAddress + Offset;
639 return object_error::success;
642 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
643 uint64_t &Res) const {
644 assert(getHeader().filetype == MachO::MH_OBJECT &&
645 "Only implemented for MH_OBJECT");
646 MachO::any_relocation_info RE = getRelocation(Rel);
647 Res = getAnyRelocationAddress(RE);
648 return object_error::success;
652 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
653 MachO::any_relocation_info RE = getRelocation(Rel);
654 if (isRelocationScattered(RE))
657 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
658 bool isExtern = getPlainRelocationExternal(RE);
662 MachO::symtab_command S = getSymtabLoadCommand();
663 unsigned SymbolTableEntrySize = is64Bit() ?
664 sizeof(MachO::nlist_64) :
665 sizeof(MachO::nlist);
666 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
668 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
669 return symbol_iterator(SymbolRef(Sym, this));
672 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
673 uint64_t &Res) const {
674 MachO::any_relocation_info RE = getRelocation(Rel);
675 Res = getAnyRelocationType(RE);
676 return object_error::success;
680 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
681 SmallVectorImpl<char> &Result) const {
684 getRelocationType(Rel, RType);
686 unsigned Arch = this->getArch();
690 static const char *const Table[] = {
691 "GENERIC_RELOC_VANILLA",
692 "GENERIC_RELOC_PAIR",
693 "GENERIC_RELOC_SECTDIFF",
694 "GENERIC_RELOC_PB_LA_PTR",
695 "GENERIC_RELOC_LOCAL_SECTDIFF",
696 "GENERIC_RELOC_TLV" };
704 case Triple::x86_64: {
705 static const char *const Table[] = {
706 "X86_64_RELOC_UNSIGNED",
707 "X86_64_RELOC_SIGNED",
708 "X86_64_RELOC_BRANCH",
709 "X86_64_RELOC_GOT_LOAD",
711 "X86_64_RELOC_SUBTRACTOR",
712 "X86_64_RELOC_SIGNED_1",
713 "X86_64_RELOC_SIGNED_2",
714 "X86_64_RELOC_SIGNED_4",
715 "X86_64_RELOC_TLV" };
724 static const char *const Table[] = {
727 "ARM_RELOC_SECTDIFF",
728 "ARM_RELOC_LOCAL_SECTDIFF",
729 "ARM_RELOC_PB_LA_PTR",
731 "ARM_THUMB_RELOC_BR22",
732 "ARM_THUMB_32BIT_BRANCH",
734 "ARM_RELOC_HALF_SECTDIFF" };
742 case Triple::aarch64: {
743 static const char *const Table[] = {
744 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
745 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
746 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
747 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
748 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
752 if (RType >= array_lengthof(Table))
759 static const char *const Table[] = {
768 "PPC_RELOC_SECTDIFF",
769 "PPC_RELOC_PB_LA_PTR",
770 "PPC_RELOC_HI16_SECTDIFF",
771 "PPC_RELOC_LO16_SECTDIFF",
772 "PPC_RELOC_HA16_SECTDIFF",
774 "PPC_RELOC_LO14_SECTDIFF",
775 "PPC_RELOC_LOCAL_SECTDIFF" };
783 case Triple::UnknownArch:
787 Result.append(res.begin(), res.end());
788 return object_error::success;
792 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
793 SmallVectorImpl<char> &Result) const {
794 MachO::any_relocation_info RE = getRelocation(Rel);
796 unsigned Arch = this->getArch();
799 raw_string_ostream fmt(fmtbuf);
800 unsigned Type = this->getAnyRelocationType(RE);
801 bool IsPCRel = this->getAnyRelocationPCRel(RE);
803 // Determine any addends that should be displayed with the relocation.
804 // These require decoding the relocation type, which is triple-specific.
806 // X86_64 has entirely custom relocation types.
807 if (Arch == Triple::x86_64) {
808 bool isPCRel = getAnyRelocationPCRel(RE);
811 case MachO::X86_64_RELOC_GOT_LOAD:
812 case MachO::X86_64_RELOC_GOT: {
813 printRelocationTargetName(this, RE, fmt);
815 if (isPCRel) fmt << "PCREL";
818 case MachO::X86_64_RELOC_SUBTRACTOR: {
819 DataRefImpl RelNext = Rel;
820 moveRelocationNext(RelNext);
821 MachO::any_relocation_info RENext = getRelocation(RelNext);
823 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
824 // X86_64_RELOC_UNSIGNED.
825 // NOTE: Scattered relocations don't exist on x86_64.
826 unsigned RType = getAnyRelocationType(RENext);
827 if (RType != MachO::X86_64_RELOC_UNSIGNED)
828 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
829 "X86_64_RELOC_SUBTRACTOR.");
831 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
832 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
833 printRelocationTargetName(this, RENext, fmt);
835 printRelocationTargetName(this, RE, fmt);
838 case MachO::X86_64_RELOC_TLV:
839 printRelocationTargetName(this, RE, fmt);
841 if (isPCRel) fmt << "P";
843 case MachO::X86_64_RELOC_SIGNED_1:
844 printRelocationTargetName(this, RE, fmt);
847 case MachO::X86_64_RELOC_SIGNED_2:
848 printRelocationTargetName(this, RE, fmt);
851 case MachO::X86_64_RELOC_SIGNED_4:
852 printRelocationTargetName(this, RE, fmt);
856 printRelocationTargetName(this, RE, fmt);
859 // X86 and ARM share some relocation types in common.
860 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
861 Arch == Triple::ppc) {
862 // Generic relocation types...
864 case MachO::GENERIC_RELOC_PAIR: // prints no info
865 return object_error::success;
866 case MachO::GENERIC_RELOC_SECTDIFF: {
867 DataRefImpl RelNext = Rel;
868 moveRelocationNext(RelNext);
869 MachO::any_relocation_info RENext = getRelocation(RelNext);
871 // X86 sect diff's must be followed by a relocation of type
872 // GENERIC_RELOC_PAIR.
873 unsigned RType = getAnyRelocationType(RENext);
875 if (RType != MachO::GENERIC_RELOC_PAIR)
876 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
877 "GENERIC_RELOC_SECTDIFF.");
879 printRelocationTargetName(this, RE, fmt);
881 printRelocationTargetName(this, RENext, fmt);
886 if (Arch == Triple::x86 || Arch == Triple::ppc) {
888 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
889 DataRefImpl RelNext = Rel;
890 moveRelocationNext(RelNext);
891 MachO::any_relocation_info RENext = getRelocation(RelNext);
893 // X86 sect diff's must be followed by a relocation of type
894 // GENERIC_RELOC_PAIR.
895 unsigned RType = getAnyRelocationType(RENext);
896 if (RType != MachO::GENERIC_RELOC_PAIR)
897 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
898 "GENERIC_RELOC_LOCAL_SECTDIFF.");
900 printRelocationTargetName(this, RE, fmt);
902 printRelocationTargetName(this, RENext, fmt);
905 case MachO::GENERIC_RELOC_TLV: {
906 printRelocationTargetName(this, RE, fmt);
908 if (IsPCRel) fmt << "P";
912 printRelocationTargetName(this, RE, fmt);
914 } else { // ARM-specific relocations
916 case MachO::ARM_RELOC_HALF:
917 case MachO::ARM_RELOC_HALF_SECTDIFF: {
918 // Half relocations steal a bit from the length field to encode
919 // whether this is an upper16 or a lower16 relocation.
920 bool isUpper = getAnyRelocationLength(RE) >> 1;
926 printRelocationTargetName(this, RE, fmt);
928 DataRefImpl RelNext = Rel;
929 moveRelocationNext(RelNext);
930 MachO::any_relocation_info RENext = getRelocation(RelNext);
932 // ARM half relocs must be followed by a relocation of type
934 unsigned RType = getAnyRelocationType(RENext);
935 if (RType != MachO::ARM_RELOC_PAIR)
936 report_fatal_error("Expected ARM_RELOC_PAIR after "
939 // NOTE: The half of the target virtual address is stashed in the
940 // address field of the secondary relocation, but we can't reverse
941 // engineer the constant offset from it without decoding the movw/movt
942 // instruction to find the other half in its immediate field.
944 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
945 // symbol/section pointer of the follow-on relocation.
946 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
948 printRelocationTargetName(this, RENext, fmt);
955 printRelocationTargetName(this, RE, fmt);
960 printRelocationTargetName(this, RE, fmt);
963 Result.append(fmtbuf.begin(), fmtbuf.end());
964 return object_error::success;
967 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
968 bool &Result) const {
969 unsigned Arch = getArch();
971 getRelocationType(Rel, Type);
975 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
977 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
978 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
979 } else if (Arch == Triple::x86_64) {
980 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
981 // an X86_64_RELOC_SUBTRACTOR.
982 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
983 DataRefImpl RelPrev = Rel;
986 getRelocationType(RelPrev, PrevType);
987 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
992 return object_error::success;
996 // guessLibraryShortName() is passed a name of a dynamic library and returns a
997 // guess on what the short name is. Then name is returned as a substring of the
998 // StringRef Name passed in. The name of the dynamic library is recognized as
999 // a framework if it has one of the two following forms:
1000 // Foo.framework/Versions/A/Foo
1001 // Foo.framework/Foo
1002 // Where A and Foo can be any string. And may contain a trailing suffix
1003 // starting with an underbar. If the Name is recognized as a framework then
1004 // isFramework is set to true else it is set to false. If the Name has a
1005 // suffix then Suffix is set to the substring in Name that contains the suffix
1006 // else it is set to a NULL StringRef.
1008 // The Name of the dynamic library is recognized as a library name if it has
1009 // one of the two following forms:
1012 // The library may have a suffix trailing the name Foo of the form:
1013 // libFoo_profile.A.dylib
1014 // libFoo_profile.dylib
1016 // The Name of the dynamic library is also recognized as a library name if it
1017 // has the following form:
1020 // If the Name of the dynamic library is none of the forms above then a NULL
1021 // StringRef is returned.
1023 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1025 StringRef &Suffix) {
1026 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1027 size_t a, b, c, d, Idx;
1029 isFramework = false;
1030 Suffix = StringRef();
1032 // Pull off the last component and make Foo point to it
1033 a = Name.rfind('/');
1034 if (a == Name.npos || a == 0)
1036 Foo = Name.slice(a+1, Name.npos);
1038 // Look for a suffix starting with a '_'
1039 Idx = Foo.rfind('_');
1040 if (Idx != Foo.npos && Foo.size() >= 2) {
1041 Suffix = Foo.slice(Idx, Foo.npos);
1042 Foo = Foo.slice(0, Idx);
1045 // First look for the form Foo.framework/Foo
1046 b = Name.rfind('/', a);
1051 F = Name.slice(Idx, Idx + Foo.size());
1052 DotFramework = Name.slice(Idx + Foo.size(),
1053 Idx + Foo.size() + sizeof(".framework/")-1);
1054 if (F == Foo && DotFramework == ".framework/") {
1059 // Next look for the form Foo.framework/Versions/A/Foo
1062 c = Name.rfind('/', b);
1063 if (c == Name.npos || c == 0)
1065 V = Name.slice(c+1, Name.npos);
1066 if (!V.startswith("Versions/"))
1068 d = Name.rfind('/', c);
1073 F = Name.slice(Idx, Idx + Foo.size());
1074 DotFramework = Name.slice(Idx + Foo.size(),
1075 Idx + Foo.size() + sizeof(".framework/")-1);
1076 if (F == Foo && DotFramework == ".framework/") {
1082 // pull off the suffix after the "." and make a point to it
1083 a = Name.rfind('.');
1084 if (a == Name.npos || a == 0)
1086 Dylib = Name.slice(a, Name.npos);
1087 if (Dylib != ".dylib")
1090 // First pull off the version letter for the form Foo.A.dylib if any.
1092 Dot = Name.slice(a-2, a-1);
1097 b = Name.rfind('/', a);
1102 // ignore any suffix after an underbar like Foo_profile.A.dylib
1103 Idx = Name.find('_', b);
1104 if (Idx != Name.npos && Idx != b) {
1105 Lib = Name.slice(b, Idx);
1106 Suffix = Name.slice(Idx, a);
1109 Lib = Name.slice(b, a);
1110 // There are incorrect library names of the form:
1111 // libATS.A_profile.dylib so check for these.
1112 if (Lib.size() >= 3) {
1113 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1115 Lib = Lib.slice(0, Lib.size()-2);
1120 Qtx = Name.slice(a, Name.npos);
1123 b = Name.rfind('/', a);
1125 Lib = Name.slice(0, a);
1127 Lib = Name.slice(b+1, a);
1128 // There are library names of the form: QT.A.qtx so check for these.
1129 if (Lib.size() >= 3) {
1130 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1132 Lib = Lib.slice(0, Lib.size()-2);
1137 // getLibraryShortNameByIndex() is used to get the short name of the library
1138 // for an undefined symbol in a linked Mach-O binary that was linked with the
1139 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1140 // It is passed the index (0 - based) of the library as translated from
1141 // GET_LIBRARY_ORDINAL (1 - based).
1142 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1143 StringRef &Res) const {
1144 if (Index >= Libraries.size())
1145 return object_error::parse_failed;
1147 // If the cache of LibrariesShortNames is not built up do that first for
1148 // all the Libraries.
1149 if (LibrariesShortNames.size() == 0) {
1150 for (unsigned i = 0; i < Libraries.size(); i++) {
1151 MachO::dylib_command D =
1152 getStruct<MachO::dylib_command>(this, Libraries[i]);
1153 if (D.dylib.name >= D.cmdsize)
1154 return object_error::parse_failed;
1155 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1156 StringRef Name = StringRef(P);
1157 if (D.dylib.name+Name.size() >= D.cmdsize)
1158 return object_error::parse_failed;
1161 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1162 if (shortName.empty())
1163 LibrariesShortNames.push_back(Name);
1165 LibrariesShortNames.push_back(shortName);
1169 Res = LibrariesShortNames[Index];
1170 return object_error::success;
1173 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1174 return getSymbolByIndex(0);
1177 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1180 return basic_symbol_iterator(SymbolRef(DRI, this));
1182 MachO::symtab_command Symtab = getSymtabLoadCommand();
1183 unsigned SymbolTableEntrySize = is64Bit() ?
1184 sizeof(MachO::nlist_64) :
1185 sizeof(MachO::nlist);
1186 unsigned Offset = Symtab.symoff +
1187 Symtab.nsyms * SymbolTableEntrySize;
1188 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1189 return basic_symbol_iterator(SymbolRef(DRI, this));
1192 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1195 return basic_symbol_iterator(SymbolRef(DRI, this));
1197 MachO::symtab_command Symtab = getSymtabLoadCommand();
1198 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1199 unsigned SymbolTableEntrySize =
1200 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1201 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1202 DRI.p += Index * SymbolTableEntrySize;
1203 return basic_symbol_iterator(SymbolRef(DRI, this));
1206 section_iterator MachOObjectFile::section_begin() const {
1208 return section_iterator(SectionRef(DRI, this));
1211 section_iterator MachOObjectFile::section_end() const {
1213 DRI.d.a = Sections.size();
1214 return section_iterator(SectionRef(DRI, this));
1217 uint8_t MachOObjectFile::getBytesInAddress() const {
1218 return is64Bit() ? 8 : 4;
1221 StringRef MachOObjectFile::getFileFormatName() const {
1222 unsigned CPUType = getCPUType(this);
1225 case llvm::MachO::CPU_TYPE_I386:
1226 return "Mach-O 32-bit i386";
1227 case llvm::MachO::CPU_TYPE_ARM:
1228 return "Mach-O arm";
1229 case llvm::MachO::CPU_TYPE_POWERPC:
1230 return "Mach-O 32-bit ppc";
1232 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1233 "64-bit object file when we're not 64-bit?");
1234 return "Mach-O 32-bit unknown";
1238 // Make sure the cpu type has the correct mask.
1239 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1240 == llvm::MachO::CPU_ARCH_ABI64 &&
1241 "32-bit object file when we're 64-bit?");
1244 case llvm::MachO::CPU_TYPE_X86_64:
1245 return "Mach-O 64-bit x86-64";
1246 case llvm::MachO::CPU_TYPE_ARM64:
1247 return "Mach-O arm64";
1248 case llvm::MachO::CPU_TYPE_POWERPC64:
1249 return "Mach-O 64-bit ppc64";
1251 return "Mach-O 64-bit unknown";
1255 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1257 case llvm::MachO::CPU_TYPE_I386:
1259 case llvm::MachO::CPU_TYPE_X86_64:
1260 return Triple::x86_64;
1261 case llvm::MachO::CPU_TYPE_ARM:
1263 case llvm::MachO::CPU_TYPE_ARM64:
1264 return Triple::aarch64;
1265 case llvm::MachO::CPU_TYPE_POWERPC:
1267 case llvm::MachO::CPU_TYPE_POWERPC64:
1268 return Triple::ppc64;
1270 return Triple::UnknownArch;
1274 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1275 const char **McpuDefault) {
1277 *McpuDefault = nullptr;
1280 case MachO::CPU_TYPE_I386:
1281 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1282 case MachO::CPU_SUBTYPE_I386_ALL:
1283 return Triple("i386-apple-darwin");
1287 case MachO::CPU_TYPE_X86_64:
1288 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1289 case MachO::CPU_SUBTYPE_X86_64_ALL:
1290 return Triple("x86_64-apple-darwin");
1291 case MachO::CPU_SUBTYPE_X86_64_H:
1292 return Triple("x86_64h-apple-darwin");
1296 case MachO::CPU_TYPE_ARM:
1297 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1298 case MachO::CPU_SUBTYPE_ARM_V4T:
1299 return Triple("armv4t-apple-darwin");
1300 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1301 return Triple("armv5e-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1303 return Triple("xscale-apple-darwin");
1304 case MachO::CPU_SUBTYPE_ARM_V6:
1305 return Triple("armv6-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V6M:
1308 *McpuDefault = "cortex-m0";
1309 return Triple("armv6m-apple-darwin");
1310 case MachO::CPU_SUBTYPE_ARM_V7:
1311 return Triple("armv7-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V7EM:
1314 *McpuDefault = "cortex-m4";
1315 return Triple("armv7em-apple-darwin");
1316 case MachO::CPU_SUBTYPE_ARM_V7K:
1317 return Triple("armv7k-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7M:
1320 *McpuDefault = "cortex-m3";
1321 return Triple("armv7m-apple-darwin");
1322 case MachO::CPU_SUBTYPE_ARM_V7S:
1323 return Triple("armv7s-apple-darwin");
1327 case MachO::CPU_TYPE_ARM64:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_ARM64_ALL:
1330 return Triple("arm64-apple-darwin");
1334 case MachO::CPU_TYPE_POWERPC:
1335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1336 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1337 return Triple("ppc-apple-darwin");
1341 case MachO::CPU_TYPE_POWERPC64:
1342 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1343 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1344 return Triple("ppc64-apple-darwin");
1353 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1354 const char **McpuDefault) {
1356 *McpuDefault = nullptr;
1359 case MachO::CPU_TYPE_ARM:
1360 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1361 case MachO::CPU_SUBTYPE_ARM_V4T:
1362 return Triple("thumbv4t-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1364 return Triple("thumbv5e-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1366 return Triple("xscale-apple-darwin");
1367 case MachO::CPU_SUBTYPE_ARM_V6:
1368 return Triple("thumbv6-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V6M:
1371 *McpuDefault = "cortex-m0";
1372 return Triple("thumbv6m-apple-darwin");
1373 case MachO::CPU_SUBTYPE_ARM_V7:
1374 return Triple("thumbv7-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V7EM:
1377 *McpuDefault = "cortex-m4";
1378 return Triple("thumbv7em-apple-darwin");
1379 case MachO::CPU_SUBTYPE_ARM_V7K:
1380 return Triple("thumbv7k-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7M:
1383 *McpuDefault = "cortex-m3";
1384 return Triple("thumbv7m-apple-darwin");
1385 case MachO::CPU_SUBTYPE_ARM_V7S:
1386 return Triple("thumbv7s-apple-darwin");
1395 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1396 const char **McpuDefault,
1397 Triple *ThumbTriple) {
1398 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1399 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1404 Triple MachOObjectFile::getHostArch() {
1405 return Triple(sys::getDefaultTargetTriple());
1408 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1409 return StringSwitch<bool>(ArchFlag)
1411 .Case("x86_64", true)
1412 .Case("x86_64h", true)
1413 .Case("armv4t", true)
1415 .Case("armv5e", true)
1416 .Case("armv6", true)
1417 .Case("armv6m", true)
1418 .Case("armv7em", true)
1419 .Case("armv7k", true)
1420 .Case("armv7m", true)
1421 .Case("armv7s", true)
1422 .Case("arm64", true)
1424 .Case("ppc64", true)
1428 unsigned MachOObjectFile::getArch() const {
1429 return getArch(getCPUType(this));
1432 Triple MachOObjectFile::getArch(const char **McpuDefault,
1433 Triple *ThumbTriple) const {
1436 MachO::mach_header_64 H_64;
1437 H_64 = getHeader64();
1438 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1439 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1442 MachO::mach_header H;
1444 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1445 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1451 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1454 return section_rel_begin(DRI);
1457 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1460 return section_rel_end(DRI);
1463 dice_iterator MachOObjectFile::begin_dices() const {
1465 if (!DataInCodeLoadCmd)
1466 return dice_iterator(DiceRef(DRI, this));
1468 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1469 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1470 return dice_iterator(DiceRef(DRI, this));
1473 dice_iterator MachOObjectFile::end_dices() const {
1475 if (!DataInCodeLoadCmd)
1476 return dice_iterator(DiceRef(DRI, this));
1478 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1479 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1480 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1481 return dice_iterator(DiceRef(DRI, this));
1484 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1485 : Trie(T), Malformed(false), Done(false) { }
1487 void ExportEntry::moveToFirst() {
1489 pushDownUntilBottom();
1492 void ExportEntry::moveToEnd() {
1497 bool ExportEntry::operator==(const ExportEntry &Other) const {
1498 // Common case, one at end, other iterating from begin.
1499 if (Done || Other.Done)
1500 return (Done == Other.Done);
1501 // Not equal if different stack sizes.
1502 if (Stack.size() != Other.Stack.size())
1504 // Not equal if different cumulative strings.
1505 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1507 // Equal if all nodes in both stacks match.
1508 for (unsigned i=0; i < Stack.size(); ++i) {
1509 if (Stack[i].Start != Other.Stack[i].Start)
1515 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1517 uint64_t Result = decodeULEB128(Ptr, &Count);
1519 if (Ptr > Trie.end()) {
1526 StringRef ExportEntry::name() const {
1527 return CumulativeString.str();
1530 uint64_t ExportEntry::flags() const {
1531 return Stack.back().Flags;
1534 uint64_t ExportEntry::address() const {
1535 return Stack.back().Address;
1538 uint64_t ExportEntry::other() const {
1539 return Stack.back().Other;
1542 StringRef ExportEntry::otherName() const {
1543 const char* ImportName = Stack.back().ImportName;
1545 return StringRef(ImportName);
1549 uint32_t ExportEntry::nodeOffset() const {
1550 return Stack.back().Start - Trie.begin();
1553 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1554 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1555 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1556 ParentStringLength(0), IsExportNode(false) {
1559 void ExportEntry::pushNode(uint64_t offset) {
1560 const uint8_t *Ptr = Trie.begin() + offset;
1561 NodeState State(Ptr);
1562 uint64_t ExportInfoSize = readULEB128(State.Current);
1563 State.IsExportNode = (ExportInfoSize != 0);
1564 const uint8_t* Children = State.Current + ExportInfoSize;
1565 if (State.IsExportNode) {
1566 State.Flags = readULEB128(State.Current);
1567 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1569 State.Other = readULEB128(State.Current); // dylib ordinal
1570 State.ImportName = reinterpret_cast<const char*>(State.Current);
1572 State.Address = readULEB128(State.Current);
1573 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1574 State.Other = readULEB128(State.Current);
1577 State.ChildCount = *Children;
1578 State.Current = Children + 1;
1579 State.NextChildIndex = 0;
1580 State.ParentStringLength = CumulativeString.size();
1581 Stack.push_back(State);
1584 void ExportEntry::pushDownUntilBottom() {
1585 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1586 NodeState &Top = Stack.back();
1587 CumulativeString.resize(Top.ParentStringLength);
1588 for (;*Top.Current != 0; Top.Current++) {
1589 char C = *Top.Current;
1590 CumulativeString.push_back(C);
1593 uint64_t childNodeIndex = readULEB128(Top.Current);
1594 Top.NextChildIndex += 1;
1595 pushNode(childNodeIndex);
1597 if (!Stack.back().IsExportNode) {
1603 // We have a trie data structure and need a way to walk it that is compatible
1604 // with the C++ iterator model. The solution is a non-recursive depth first
1605 // traversal where the iterator contains a stack of parent nodes along with a
1606 // string that is the accumulation of all edge strings along the parent chain
1609 // There is one “export” node for each exported symbol. But because some
1610 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1611 // node may have child nodes too.
1613 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1614 // child until hitting a node with no children (which is an export node or
1615 // else the trie is malformed). On the way down, each node is pushed on the
1616 // stack ivar. If there is no more ways down, it pops up one and tries to go
1617 // down a sibling path until a childless node is reached.
1618 void ExportEntry::moveNext() {
1619 if (Stack.empty() || !Stack.back().IsExportNode) {
1626 while (!Stack.empty()) {
1627 NodeState &Top = Stack.back();
1628 if (Top.NextChildIndex < Top.ChildCount) {
1629 pushDownUntilBottom();
1630 // Now at the next export node.
1633 if (Top.IsExportNode) {
1634 // This node has no children but is itself an export node.
1635 CumulativeString.resize(Top.ParentStringLength);
1644 iterator_range<export_iterator>
1645 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1646 ExportEntry Start(Trie);
1647 Start.moveToFirst();
1649 ExportEntry Finish(Trie);
1652 return iterator_range<export_iterator>(export_iterator(Start),
1653 export_iterator(Finish));
1656 iterator_range<export_iterator> MachOObjectFile::exports() const {
1657 return exports(getDyldInfoExportsTrie());
1661 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1662 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1663 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1664 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1666 void MachORebaseEntry::moveToFirst() {
1667 Ptr = Opcodes.begin();
1671 void MachORebaseEntry::moveToEnd() {
1672 Ptr = Opcodes.end();
1673 RemainingLoopCount = 0;
1677 void MachORebaseEntry::moveNext() {
1678 // If in the middle of some loop, move to next rebasing in loop.
1679 SegmentOffset += AdvanceAmount;
1680 if (RemainingLoopCount) {
1681 --RemainingLoopCount;
1684 if (Ptr == Opcodes.end()) {
1689 while (More && !Malformed) {
1690 // Parse next opcode and set up next loop.
1691 uint8_t Byte = *Ptr++;
1692 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1693 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1695 case MachO::REBASE_OPCODE_DONE:
1699 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1701 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1702 RebaseType = ImmValue;
1705 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1706 << "RebaseType=" << (int) RebaseType << "\n");
1708 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1709 SegmentIndex = ImmValue;
1710 SegmentOffset = readULEB128();
1713 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1714 << "SegmentIndex=" << SegmentIndex << ", "
1715 << format("SegmentOffset=0x%06X", SegmentOffset)
1718 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1719 SegmentOffset += readULEB128();
1720 DEBUG_WITH_TYPE("mach-o-rebase",
1721 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1722 << format("SegmentOffset=0x%06X",
1723 SegmentOffset) << "\n");
1725 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1726 SegmentOffset += ImmValue * PointerSize;
1727 DEBUG_WITH_TYPE("mach-o-rebase",
1728 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1729 << format("SegmentOffset=0x%06X",
1730 SegmentOffset) << "\n");
1732 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1733 AdvanceAmount = PointerSize;
1734 RemainingLoopCount = ImmValue - 1;
1737 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1738 << format("SegmentOffset=0x%06X", SegmentOffset)
1739 << ", AdvanceAmount=" << AdvanceAmount
1740 << ", RemainingLoopCount=" << RemainingLoopCount
1743 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1744 AdvanceAmount = PointerSize;
1745 RemainingLoopCount = readULEB128() - 1;
1748 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1749 << format("SegmentOffset=0x%06X", SegmentOffset)
1750 << ", AdvanceAmount=" << AdvanceAmount
1751 << ", RemainingLoopCount=" << RemainingLoopCount
1754 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1755 AdvanceAmount = readULEB128() + PointerSize;
1756 RemainingLoopCount = 0;
1759 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1760 << format("SegmentOffset=0x%06X", SegmentOffset)
1761 << ", AdvanceAmount=" << AdvanceAmount
1762 << ", RemainingLoopCount=" << RemainingLoopCount
1765 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1766 RemainingLoopCount = readULEB128() - 1;
1767 AdvanceAmount = readULEB128() + PointerSize;
1770 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1771 << format("SegmentOffset=0x%06X", SegmentOffset)
1772 << ", AdvanceAmount=" << AdvanceAmount
1773 << ", RemainingLoopCount=" << RemainingLoopCount
1782 uint64_t MachORebaseEntry::readULEB128() {
1784 uint64_t Result = decodeULEB128(Ptr, &Count);
1786 if (Ptr > Opcodes.end()) {
1787 Ptr = Opcodes.end();
1793 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1795 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1797 StringRef MachORebaseEntry::typeName() const {
1798 switch (RebaseType) {
1799 case MachO::REBASE_TYPE_POINTER:
1801 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1802 return "text abs32";
1803 case MachO::REBASE_TYPE_TEXT_PCREL32:
1804 return "text rel32";
1809 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1810 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1811 return (Ptr == Other.Ptr) &&
1812 (RemainingLoopCount == Other.RemainingLoopCount) &&
1813 (Done == Other.Done);
1816 iterator_range<rebase_iterator>
1817 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1818 MachORebaseEntry Start(Opcodes, is64);
1819 Start.moveToFirst();
1821 MachORebaseEntry Finish(Opcodes, is64);
1824 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1825 rebase_iterator(Finish));
1828 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1829 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1833 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1835 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1836 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1837 BindType(0), PointerSize(is64Bit ? 8 : 4),
1838 TableKind(BK), Malformed(false), Done(false) {}
1840 void MachOBindEntry::moveToFirst() {
1841 Ptr = Opcodes.begin();
1845 void MachOBindEntry::moveToEnd() {
1846 Ptr = Opcodes.end();
1847 RemainingLoopCount = 0;
1851 void MachOBindEntry::moveNext() {
1852 // If in the middle of some loop, move to next binding in loop.
1853 SegmentOffset += AdvanceAmount;
1854 if (RemainingLoopCount) {
1855 --RemainingLoopCount;
1858 if (Ptr == Opcodes.end()) {
1863 while (More && !Malformed) {
1864 // Parse next opcode and set up next loop.
1865 uint8_t Byte = *Ptr++;
1866 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1867 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1868 int8_t SignExtended;
1869 const uint8_t *SymStart;
1871 case MachO::BIND_OPCODE_DONE:
1872 if (TableKind == Kind::Lazy) {
1873 // Lazying bindings have a DONE opcode between entries. Need to ignore
1874 // it to advance to next entry. But need not if this is last entry.
1875 bool NotLastEntry = false;
1876 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1878 NotLastEntry = true;
1887 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1889 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1893 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1894 << "Ordinal=" << Ordinal << "\n");
1896 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1897 Ordinal = readULEB128();
1900 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1901 << "Ordinal=" << Ordinal << "\n");
1903 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1905 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1906 Ordinal = SignExtended;
1911 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1912 << "Ordinal=" << Ordinal << "\n");
1914 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1920 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1925 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1926 << "SymbolName=" << SymbolName << "\n");
1927 if (TableKind == Kind::Weak) {
1928 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1932 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1933 BindType = ImmValue;
1936 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1937 << "BindType=" << (int)BindType << "\n");
1939 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1940 Addend = readSLEB128();
1941 if (TableKind == Kind::Lazy)
1945 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1946 << "Addend=" << Addend << "\n");
1948 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1949 SegmentIndex = ImmValue;
1950 SegmentOffset = readULEB128();
1953 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1954 << "SegmentIndex=" << SegmentIndex << ", "
1955 << format("SegmentOffset=0x%06X", SegmentOffset)
1958 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1959 SegmentOffset += readULEB128();
1960 DEBUG_WITH_TYPE("mach-o-bind",
1961 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1962 << format("SegmentOffset=0x%06X",
1963 SegmentOffset) << "\n");
1965 case MachO::BIND_OPCODE_DO_BIND:
1966 AdvanceAmount = PointerSize;
1967 RemainingLoopCount = 0;
1968 DEBUG_WITH_TYPE("mach-o-bind",
1969 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1970 << format("SegmentOffset=0x%06X",
1971 SegmentOffset) << "\n");
1973 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1974 AdvanceAmount = readULEB128();
1975 RemainingLoopCount = 0;
1976 if (TableKind == Kind::Lazy)
1980 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
1981 << format("SegmentOffset=0x%06X", SegmentOffset)
1982 << ", AdvanceAmount=" << AdvanceAmount
1983 << ", RemainingLoopCount=" << RemainingLoopCount
1986 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1987 AdvanceAmount = ImmValue * PointerSize;
1988 RemainingLoopCount = 0;
1989 if (TableKind == Kind::Lazy)
1991 DEBUG_WITH_TYPE("mach-o-bind",
1993 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1994 << format("SegmentOffset=0x%06X",
1995 SegmentOffset) << "\n");
1997 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1998 RemainingLoopCount = readULEB128() - 1;
1999 AdvanceAmount = readULEB128() + PointerSize;
2000 if (TableKind == Kind::Lazy)
2004 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2005 << format("SegmentOffset=0x%06X", SegmentOffset)
2006 << ", AdvanceAmount=" << AdvanceAmount
2007 << ", RemainingLoopCount=" << RemainingLoopCount
2016 uint64_t MachOBindEntry::readULEB128() {
2018 uint64_t Result = decodeULEB128(Ptr, &Count);
2020 if (Ptr > Opcodes.end()) {
2021 Ptr = Opcodes.end();
2027 int64_t MachOBindEntry::readSLEB128() {
2029 int64_t Result = decodeSLEB128(Ptr, &Count);
2031 if (Ptr > Opcodes.end()) {
2032 Ptr = Opcodes.end();
2039 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2041 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2043 StringRef MachOBindEntry::typeName() const {
2045 case MachO::BIND_TYPE_POINTER:
2047 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2048 return "text abs32";
2049 case MachO::BIND_TYPE_TEXT_PCREL32:
2050 return "text rel32";
2055 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2057 int64_t MachOBindEntry::addend() const { return Addend; }
2059 uint32_t MachOBindEntry::flags() const { return Flags; }
2061 int MachOBindEntry::ordinal() const { return Ordinal; }
2063 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2064 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2065 return (Ptr == Other.Ptr) &&
2066 (RemainingLoopCount == Other.RemainingLoopCount) &&
2067 (Done == Other.Done);
2070 iterator_range<bind_iterator>
2071 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2072 MachOBindEntry::Kind BKind) {
2073 MachOBindEntry Start(Opcodes, is64, BKind);
2074 Start.moveToFirst();
2076 MachOBindEntry Finish(Opcodes, is64, BKind);
2079 return iterator_range<bind_iterator>(bind_iterator(Start),
2080 bind_iterator(Finish));
2083 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2084 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2085 MachOBindEntry::Kind::Regular);
2088 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2089 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2090 MachOBindEntry::Kind::Lazy);
2093 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2094 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2095 MachOBindEntry::Kind::Weak);
2099 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2100 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2101 return parseSegmentOrSectionName(Raw.data());
2105 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2106 const section_base *Base =
2107 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2108 return makeArrayRef(Base->sectname);
2112 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2113 const section_base *Base =
2114 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2115 return makeArrayRef(Base->segname);
2119 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2121 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2123 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2126 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2127 const MachO::any_relocation_info &RE) const {
2128 if (isLittleEndian())
2129 return RE.r_word1 & 0xffffff;
2130 return RE.r_word1 >> 8;
2133 bool MachOObjectFile::getPlainRelocationExternal(
2134 const MachO::any_relocation_info &RE) const {
2135 if (isLittleEndian())
2136 return (RE.r_word1 >> 27) & 1;
2137 return (RE.r_word1 >> 4) & 1;
2140 bool MachOObjectFile::getScatteredRelocationScattered(
2141 const MachO::any_relocation_info &RE) const {
2142 return RE.r_word0 >> 31;
2145 uint32_t MachOObjectFile::getScatteredRelocationValue(
2146 const MachO::any_relocation_info &RE) const {
2150 unsigned MachOObjectFile::getAnyRelocationAddress(
2151 const MachO::any_relocation_info &RE) const {
2152 if (isRelocationScattered(RE))
2153 return getScatteredRelocationAddress(RE);
2154 return getPlainRelocationAddress(RE);
2157 unsigned MachOObjectFile::getAnyRelocationPCRel(
2158 const MachO::any_relocation_info &RE) const {
2159 if (isRelocationScattered(RE))
2160 return getScatteredRelocationPCRel(this, RE);
2161 return getPlainRelocationPCRel(this, RE);
2164 unsigned MachOObjectFile::getAnyRelocationLength(
2165 const MachO::any_relocation_info &RE) const {
2166 if (isRelocationScattered(RE))
2167 return getScatteredRelocationLength(RE);
2168 return getPlainRelocationLength(this, RE);
2172 MachOObjectFile::getAnyRelocationType(
2173 const MachO::any_relocation_info &RE) const {
2174 if (isRelocationScattered(RE))
2175 return getScatteredRelocationType(RE);
2176 return getPlainRelocationType(this, RE);
2180 MachOObjectFile::getRelocationSection(
2181 const MachO::any_relocation_info &RE) const {
2182 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2183 return *section_end();
2184 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2187 return SectionRef(DRI, this);
2190 MachOObjectFile::LoadCommandInfo
2191 MachOObjectFile::getFirstLoadCommandInfo() const {
2192 MachOObjectFile::LoadCommandInfo Load;
2194 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2195 sizeof(MachO::mach_header);
2196 Load.Ptr = getPtr(this, HeaderSize);
2197 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2201 MachOObjectFile::LoadCommandInfo
2202 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2203 MachOObjectFile::LoadCommandInfo Next;
2204 Next.Ptr = L.Ptr + L.C.cmdsize;
2205 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2209 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2210 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2213 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2214 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2217 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2218 unsigned Index) const {
2219 const char *Sec = getSectionPtr(this, L, Index);
2220 return getStruct<MachO::section>(this, Sec);
2223 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2224 unsigned Index) const {
2225 const char *Sec = getSectionPtr(this, L, Index);
2226 return getStruct<MachO::section_64>(this, Sec);
2230 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2231 const char *P = reinterpret_cast<const char *>(DRI.p);
2232 return getStruct<MachO::nlist>(this, P);
2236 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2237 const char *P = reinterpret_cast<const char *>(DRI.p);
2238 return getStruct<MachO::nlist_64>(this, P);
2241 MachO::linkedit_data_command
2242 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2243 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2246 MachO::segment_command
2247 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2248 return getStruct<MachO::segment_command>(this, L.Ptr);
2251 MachO::segment_command_64
2252 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2253 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2256 MachO::linker_options_command
2257 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2258 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2261 MachO::version_min_command
2262 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2263 return getStruct<MachO::version_min_command>(this, L.Ptr);
2266 MachO::dylib_command
2267 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2268 return getStruct<MachO::dylib_command>(this, L.Ptr);
2271 MachO::dyld_info_command
2272 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2273 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2276 MachO::dylinker_command
2277 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2278 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2282 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2283 return getStruct<MachO::uuid_command>(this, L.Ptr);
2286 MachO::source_version_command
2287 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2288 return getStruct<MachO::source_version_command>(this, L.Ptr);
2291 MachO::entry_point_command
2292 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2293 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2297 MachO::any_relocation_info
2298 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2303 MachO::section_64 Sect = getSection64(Sec);
2304 Offset = Sect.reloff;
2306 MachO::section Sect = getSection(Sec);
2307 Offset = Sect.reloff;
2310 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2311 getPtr(this, Offset)) + Rel.d.b;
2312 return getStruct<MachO::any_relocation_info>(
2313 this, reinterpret_cast<const char *>(P));
2316 MachO::data_in_code_entry
2317 MachOObjectFile::getDice(DataRefImpl Rel) const {
2318 const char *P = reinterpret_cast<const char *>(Rel.p);
2319 return getStruct<MachO::data_in_code_entry>(this, P);
2322 MachO::mach_header MachOObjectFile::getHeader() const {
2323 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2326 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2327 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2330 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2331 const MachO::dysymtab_command &DLC,
2332 unsigned Index) const {
2333 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2334 return getStruct<uint32_t>(this, getPtr(this, Offset));
2337 MachO::data_in_code_entry
2338 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2339 unsigned Index) const {
2340 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2341 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2344 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2345 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2348 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2349 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2352 MachO::linkedit_data_command
2353 MachOObjectFile::getDataInCodeLoadCommand() const {
2354 if (DataInCodeLoadCmd)
2355 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2357 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2358 MachO::linkedit_data_command Cmd;
2359 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2360 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2366 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2367 if (!DyldInfoLoadCmd)
2368 return ArrayRef<uint8_t>();
2370 MachO::dyld_info_command DyldInfo
2371 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2372 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2373 getPtr(this, DyldInfo.rebase_off));
2374 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2377 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2378 if (!DyldInfoLoadCmd)
2379 return ArrayRef<uint8_t>();
2381 MachO::dyld_info_command DyldInfo
2382 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2383 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2384 getPtr(this, DyldInfo.bind_off));
2385 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2388 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2389 if (!DyldInfoLoadCmd)
2390 return ArrayRef<uint8_t>();
2392 MachO::dyld_info_command DyldInfo
2393 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2394 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2395 getPtr(this, DyldInfo.weak_bind_off));
2396 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2399 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2400 if (!DyldInfoLoadCmd)
2401 return ArrayRef<uint8_t>();
2403 MachO::dyld_info_command DyldInfo
2404 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2405 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2406 getPtr(this, DyldInfo.lazy_bind_off));
2407 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2410 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2411 if (!DyldInfoLoadCmd)
2412 return ArrayRef<uint8_t>();
2414 MachO::dyld_info_command DyldInfo
2415 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2416 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2417 getPtr(this, DyldInfo.export_off));
2418 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2422 StringRef MachOObjectFile::getStringTableData() const {
2423 MachO::symtab_command S = getSymtabLoadCommand();
2424 return getData().substr(S.stroff, S.strsize);
2427 bool MachOObjectFile::is64Bit() const {
2428 return getType() == getMachOType(false, true) ||
2429 getType() == getMachOType(true, true);
2432 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2433 SmallVectorImpl<uint64_t> &Out) const {
2434 DataExtractor extractor(ObjectFile::getData(), true, 0);
2436 uint32_t offset = Index;
2438 while (uint64_t delta = extractor.getULEB128(&offset)) {
2440 Out.push_back(data);
2444 bool MachOObjectFile::isRelocatableObject() const {
2445 return getHeader().filetype == MachO::MH_OBJECT;
2448 ErrorOr<std::unique_ptr<MachOObjectFile>>
2449 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2450 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2452 std::unique_ptr<MachOObjectFile> Ret;
2453 if (Magic == "\xFE\xED\xFA\xCE")
2454 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2455 else if (Magic == "\xCE\xFA\xED\xFE")
2456 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2457 else if (Magic == "\xFE\xED\xFA\xCF")
2458 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2459 else if (Magic == "\xCF\xFA\xED\xFE")
2460 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2462 return object_error::parse_failed;
2466 return std::move(Ret);