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()) {
150 if ((ec = Section.getAddress(Addr)))
151 report_fatal_error(ec.message());
154 if ((ec = Section.getName(Name)))
155 report_fatal_error(ec.message());
160 fmt << format("0x%x", Val);
165 bool isExtern = O->getPlainRelocationExternal(RE);
166 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
169 symbol_iterator SI = O->symbol_begin();
173 section_iterator SI = O->section_begin();
174 // Adjust for the fact that sections are 1-indexed.
175 advance(SI, Val - 1);
183 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
188 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
189 return RE.r_word0 & 0xffffff;
192 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
193 const MachO::any_relocation_info &RE) {
194 if (O->isLittleEndian())
195 return (RE.r_word1 >> 24) & 1;
196 return (RE.r_word1 >> 7) & 1;
200 getScatteredRelocationPCRel(const MachOObjectFile *O,
201 const MachO::any_relocation_info &RE) {
202 return (RE.r_word0 >> 30) & 1;
205 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
206 const MachO::any_relocation_info &RE) {
207 if (O->isLittleEndian())
208 return (RE.r_word1 >> 25) & 3;
209 return (RE.r_word1 >> 5) & 3;
213 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
214 return (RE.r_word0 >> 28) & 3;
217 static unsigned getPlainRelocationType(const MachOObjectFile *O,
218 const MachO::any_relocation_info &RE) {
219 if (O->isLittleEndian())
220 return RE.r_word1 >> 28;
221 return RE.r_word1 & 0xf;
225 getScatteredRelocationType(const MachO::any_relocation_info &RE) {
226 return (RE.r_word0 >> 24) & 0xf;
229 static uint32_t getSectionFlags(const MachOObjectFile *O,
232 MachO::section_64 Sect = O->getSection64(Sec);
235 MachO::section Sect = O->getSection(Sec);
239 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
240 bool Is64bits, std::error_code &EC)
241 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
242 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
243 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
244 HasPageZeroSegment(false) {
245 uint32_t LoadCommandCount = this->getHeader().ncmds;
246 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
247 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
249 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
250 for (unsigned I = 0; ; ++I) {
251 if (Load.C.cmd == MachO::LC_SYMTAB) {
252 assert(!SymtabLoadCmd && "Multiple symbol tables");
253 SymtabLoadCmd = Load.Ptr;
254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
255 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
256 DysymtabLoadCmd = Load.Ptr;
257 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
258 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
259 DataInCodeLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
261 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
262 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
263 DyldInfoLoadCmd = Load.Ptr;
264 } else if (Load.C.cmd == SegmentLoadType) {
265 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
266 for (unsigned J = 0; J < NumSections; ++J) {
267 const char *Sec = getSectionPtr(this, Load, J);
268 Sections.push_back(Sec);
270 if (isPageZeroSegment(this, Load))
271 HasPageZeroSegment = true;
272 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
273 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
274 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
275 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
276 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
277 Libraries.push_back(Load.Ptr);
280 if (I == LoadCommandCount - 1)
283 Load = getNextLoadCommandInfo(Load);
287 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
288 unsigned SymbolTableEntrySize = is64Bit() ?
289 sizeof(MachO::nlist_64) :
290 sizeof(MachO::nlist);
291 Symb.p += SymbolTableEntrySize;
294 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
295 StringRef &Res) const {
296 StringRef StringTable = getStringTableData();
297 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
298 const char *Start = &StringTable.data()[Entry.n_strx];
299 Res = StringRef(Start);
300 return object_error::success;
303 // getIndirectName() returns the name of the alias'ed symbol who's string table
304 // index is in the n_value field.
305 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
306 StringRef &Res) const {
307 StringRef StringTable = getStringTableData();
310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
311 NValue = Entry.n_value;
312 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
313 return object_error::parse_failed;
315 MachO::nlist Entry = getSymbolTableEntry(Symb);
316 NValue = Entry.n_value;
317 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
318 return object_error::parse_failed;
320 if (NValue >= StringTable.size())
321 return object_error::parse_failed;
322 const char *Start = &StringTable.data()[NValue];
323 Res = StringRef(Start);
324 return object_error::success;
327 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
328 uint64_t &Res) const {
330 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
331 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
333 Res = UnknownAddressOrSize;
337 MachO::nlist Entry = getSymbolTableEntry(Symb);
338 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
340 Res = UnknownAddressOrSize;
344 return object_error::success;
347 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
348 uint32_t &Result) const {
349 uint32_t flags = getSymbolFlags(DRI);
350 if (flags & SymbolRef::SF_Common) {
351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
352 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
356 return object_error::success;
359 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
360 uint64_t &Result) const {
361 uint64_t BeginOffset;
362 uint64_t EndOffset = 0;
363 uint8_t SectionIndex;
365 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
367 getSymbolAddress(DRI, Value);
368 if (Value == UnknownAddressOrSize) {
369 Result = UnknownAddressOrSize;
370 return object_error::success;
375 SectionIndex = Entry.n_sect;
377 uint32_t flags = getSymbolFlags(DRI);
378 if (flags & SymbolRef::SF_Common)
381 Result = UnknownAddressOrSize;
382 return object_error::success;
384 // Unfortunately symbols are unsorted so we need to touch all
385 // symbols from load command
386 for (const SymbolRef &Symbol : symbols()) {
387 DataRefImpl DRI = Symbol.getRawDataRefImpl();
388 Entry = getSymbolTableEntryBase(this, DRI);
389 getSymbolAddress(DRI, Value);
390 if (Value == UnknownAddressOrSize)
392 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
393 if (!EndOffset || Value < EndOffset)
399 Sec.d.a = SectionIndex-1;
400 getSectionSize(Sec, Size);
401 getSectionAddress(Sec, EndOffset);
404 Result = EndOffset - BeginOffset;
405 return object_error::success;
408 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
409 SymbolRef::Type &Res) const {
410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
411 uint8_t n_type = Entry.n_type;
413 Res = SymbolRef::ST_Other;
415 // If this is a STAB debugging symbol, we can do nothing more.
416 if (n_type & MachO::N_STAB) {
417 Res = SymbolRef::ST_Debug;
418 return object_error::success;
421 switch (n_type & MachO::N_TYPE) {
423 Res = SymbolRef::ST_Unknown;
426 Res = SymbolRef::ST_Function;
429 return object_error::success;
432 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
433 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
435 uint8_t MachOType = Entry.n_type;
436 uint16_t MachOFlags = Entry.n_desc;
438 uint32_t Result = SymbolRef::SF_None;
440 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
441 Result |= SymbolRef::SF_Undefined;
443 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
444 Result |= SymbolRef::SF_Indirect;
446 if (MachOType & MachO::N_STAB)
447 Result |= SymbolRef::SF_FormatSpecific;
449 if (MachOType & MachO::N_EXT) {
450 Result |= SymbolRef::SF_Global;
451 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
453 getSymbolAddress(DRI, Value);
454 if (Value && Value != UnknownAddressOrSize)
455 Result |= SymbolRef::SF_Common;
459 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
460 Result |= SymbolRef::SF_Weak;
462 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
463 Result |= SymbolRef::SF_Thumb;
465 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
466 Result |= SymbolRef::SF_Absolute;
471 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
472 section_iterator &Res) const {
473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
474 uint8_t index = Entry.n_sect;
481 Res = section_iterator(SectionRef(DRI, this));
484 return object_error::success;
487 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
491 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
492 StringRef &Result) const {
493 ArrayRef<char> Raw = getSectionRawName(Sec);
494 Result = parseSegmentOrSectionName(Raw.data());
495 return object_error::success;
498 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
499 uint64_t &Res) const {
501 MachO::section_64 Sect = getSection64(Sec);
504 MachO::section Sect = getSection(Sec);
507 return object_error::success;
510 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
511 uint64_t &Res) const {
513 MachO::section_64 Sect = getSection64(Sec);
516 MachO::section Sect = getSection(Sec);
520 return object_error::success;
523 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
524 StringRef &Res) const {
529 MachO::section_64 Sect = getSection64(Sec);
530 Offset = Sect.offset;
533 MachO::section Sect = getSection(Sec);
534 Offset = Sect.offset;
538 Res = this->getData().substr(Offset, Size);
539 return object_error::success;
542 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
543 uint64_t &Res) const {
546 MachO::section_64 Sect = getSection64(Sec);
549 MachO::section Sect = getSection(Sec);
553 Res = uint64_t(1) << Align;
554 return object_error::success;
557 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
559 uint32_t Flags = getSectionFlags(this, Sec);
560 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
561 return object_error::success;
564 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
565 bool &Result) const {
566 uint32_t Flags = getSectionFlags(this, Sec);
567 unsigned SectionType = Flags & MachO::SECTION_TYPE;
568 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
569 !(SectionType == MachO::S_ZEROFILL ||
570 SectionType == MachO::S_GB_ZEROFILL);
571 return object_error::success;
574 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
575 bool &Result) const {
576 uint32_t Flags = getSectionFlags(this, Sec);
577 unsigned SectionType = Flags & MachO::SECTION_TYPE;
578 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
579 (SectionType == MachO::S_ZEROFILL ||
580 SectionType == MachO::S_GB_ZEROFILL);
581 return object_error::success;
585 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
586 bool &Result) const {
587 // FIXME: Unimplemented.
589 return object_error::success;
592 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
593 bool &Result) const {
594 // FIXME: Unimplemented.
596 return object_error::success;
599 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
601 uint32_t Flags = getSectionFlags(this, Sec);
602 unsigned SectionType = Flags & MachO::SECTION_TYPE;
603 Res = SectionType == MachO::S_ZEROFILL ||
604 SectionType == MachO::S_GB_ZEROFILL;
605 return object_error::success;
608 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
609 bool &Result) const {
610 // Consider using the code from isSectionText to look for __const sections.
611 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
612 // to use section attributes to distinguish code from data.
614 // FIXME: Unimplemented.
616 return object_error::success;
619 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
621 bool &Result) const {
623 this->getSymbolType(Symb, ST);
624 if (ST == SymbolRef::ST_Unknown) {
626 return object_error::success;
629 uint64_t SectBegin, SectEnd;
630 getSectionAddress(Sec, SectBegin);
631 getSectionSize(Sec, SectEnd);
632 SectEnd += SectBegin;
635 getSymbolAddress(Symb, SymAddr);
636 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
638 return object_error::success;
641 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
645 return relocation_iterator(RelocationRef(Ret, this));
649 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
652 MachO::section_64 Sect = getSection64(Sec);
655 MachO::section Sect = getSection(Sec);
662 return relocation_iterator(RelocationRef(Ret, this));
665 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
669 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
670 uint64_t &Res) const {
672 getRelocationOffset(Rel, Offset);
677 getSectionAddress(Sec, SecAddress);
678 Res = SecAddress + Offset;
679 return object_error::success;
682 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
683 uint64_t &Res) const {
684 assert(getHeader().filetype == MachO::MH_OBJECT &&
685 "Only implemented for MH_OBJECT");
686 MachO::any_relocation_info RE = getRelocation(Rel);
687 Res = getAnyRelocationAddress(RE);
688 return object_error::success;
692 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
693 MachO::any_relocation_info RE = getRelocation(Rel);
694 if (isRelocationScattered(RE))
697 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
698 bool isExtern = getPlainRelocationExternal(RE);
702 MachO::symtab_command S = getSymtabLoadCommand();
703 unsigned SymbolTableEntrySize = is64Bit() ?
704 sizeof(MachO::nlist_64) :
705 sizeof(MachO::nlist);
706 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
708 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
709 return symbol_iterator(SymbolRef(Sym, this));
712 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
713 uint64_t &Res) const {
714 MachO::any_relocation_info RE = getRelocation(Rel);
715 Res = getAnyRelocationType(RE);
716 return object_error::success;
720 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
721 SmallVectorImpl<char> &Result) const {
724 getRelocationType(Rel, RType);
726 unsigned Arch = this->getArch();
730 static const char *const Table[] = {
731 "GENERIC_RELOC_VANILLA",
732 "GENERIC_RELOC_PAIR",
733 "GENERIC_RELOC_SECTDIFF",
734 "GENERIC_RELOC_PB_LA_PTR",
735 "GENERIC_RELOC_LOCAL_SECTDIFF",
736 "GENERIC_RELOC_TLV" };
744 case Triple::x86_64: {
745 static const char *const Table[] = {
746 "X86_64_RELOC_UNSIGNED",
747 "X86_64_RELOC_SIGNED",
748 "X86_64_RELOC_BRANCH",
749 "X86_64_RELOC_GOT_LOAD",
751 "X86_64_RELOC_SUBTRACTOR",
752 "X86_64_RELOC_SIGNED_1",
753 "X86_64_RELOC_SIGNED_2",
754 "X86_64_RELOC_SIGNED_4",
755 "X86_64_RELOC_TLV" };
764 static const char *const Table[] = {
767 "ARM_RELOC_SECTDIFF",
768 "ARM_RELOC_LOCAL_SECTDIFF",
769 "ARM_RELOC_PB_LA_PTR",
771 "ARM_THUMB_RELOC_BR22",
772 "ARM_THUMB_32BIT_BRANCH",
774 "ARM_RELOC_HALF_SECTDIFF" };
782 case Triple::aarch64: {
783 static const char *const Table[] = {
784 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
785 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
786 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
787 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
788 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
792 if (RType >= array_lengthof(Table))
799 static const char *const Table[] = {
808 "PPC_RELOC_SECTDIFF",
809 "PPC_RELOC_PB_LA_PTR",
810 "PPC_RELOC_HI16_SECTDIFF",
811 "PPC_RELOC_LO16_SECTDIFF",
812 "PPC_RELOC_HA16_SECTDIFF",
814 "PPC_RELOC_LO14_SECTDIFF",
815 "PPC_RELOC_LOCAL_SECTDIFF" };
823 case Triple::UnknownArch:
827 Result.append(res.begin(), res.end());
828 return object_error::success;
832 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
833 SmallVectorImpl<char> &Result) const {
834 MachO::any_relocation_info RE = getRelocation(Rel);
836 unsigned Arch = this->getArch();
839 raw_string_ostream fmt(fmtbuf);
840 unsigned Type = this->getAnyRelocationType(RE);
841 bool IsPCRel = this->getAnyRelocationPCRel(RE);
843 // Determine any addends that should be displayed with the relocation.
844 // These require decoding the relocation type, which is triple-specific.
846 // X86_64 has entirely custom relocation types.
847 if (Arch == Triple::x86_64) {
848 bool isPCRel = getAnyRelocationPCRel(RE);
851 case MachO::X86_64_RELOC_GOT_LOAD:
852 case MachO::X86_64_RELOC_GOT: {
853 printRelocationTargetName(this, RE, fmt);
855 if (isPCRel) fmt << "PCREL";
858 case MachO::X86_64_RELOC_SUBTRACTOR: {
859 DataRefImpl RelNext = Rel;
860 moveRelocationNext(RelNext);
861 MachO::any_relocation_info RENext = getRelocation(RelNext);
863 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
864 // X86_64_RELOC_UNSIGNED.
865 // NOTE: Scattered relocations don't exist on x86_64.
866 unsigned RType = getAnyRelocationType(RENext);
867 if (RType != MachO::X86_64_RELOC_UNSIGNED)
868 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
869 "X86_64_RELOC_SUBTRACTOR.");
871 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
872 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
873 printRelocationTargetName(this, RENext, fmt);
875 printRelocationTargetName(this, RE, fmt);
878 case MachO::X86_64_RELOC_TLV:
879 printRelocationTargetName(this, RE, fmt);
881 if (isPCRel) fmt << "P";
883 case MachO::X86_64_RELOC_SIGNED_1:
884 printRelocationTargetName(this, RE, fmt);
887 case MachO::X86_64_RELOC_SIGNED_2:
888 printRelocationTargetName(this, RE, fmt);
891 case MachO::X86_64_RELOC_SIGNED_4:
892 printRelocationTargetName(this, RE, fmt);
896 printRelocationTargetName(this, RE, fmt);
899 // X86 and ARM share some relocation types in common.
900 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
901 Arch == Triple::ppc) {
902 // Generic relocation types...
904 case MachO::GENERIC_RELOC_PAIR: // prints no info
905 return object_error::success;
906 case MachO::GENERIC_RELOC_SECTDIFF: {
907 DataRefImpl RelNext = Rel;
908 moveRelocationNext(RelNext);
909 MachO::any_relocation_info RENext = getRelocation(RelNext);
911 // X86 sect diff's must be followed by a relocation of type
912 // GENERIC_RELOC_PAIR.
913 unsigned RType = getAnyRelocationType(RENext);
915 if (RType != MachO::GENERIC_RELOC_PAIR)
916 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
917 "GENERIC_RELOC_SECTDIFF.");
919 printRelocationTargetName(this, RE, fmt);
921 printRelocationTargetName(this, RENext, fmt);
926 if (Arch == Triple::x86 || Arch == Triple::ppc) {
928 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
929 DataRefImpl RelNext = Rel;
930 moveRelocationNext(RelNext);
931 MachO::any_relocation_info RENext = getRelocation(RelNext);
933 // X86 sect diff's must be followed by a relocation of type
934 // GENERIC_RELOC_PAIR.
935 unsigned RType = getAnyRelocationType(RENext);
936 if (RType != MachO::GENERIC_RELOC_PAIR)
937 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
938 "GENERIC_RELOC_LOCAL_SECTDIFF.");
940 printRelocationTargetName(this, RE, fmt);
942 printRelocationTargetName(this, RENext, fmt);
945 case MachO::GENERIC_RELOC_TLV: {
946 printRelocationTargetName(this, RE, fmt);
948 if (IsPCRel) fmt << "P";
952 printRelocationTargetName(this, RE, fmt);
954 } else { // ARM-specific relocations
956 case MachO::ARM_RELOC_HALF:
957 case MachO::ARM_RELOC_HALF_SECTDIFF: {
958 // Half relocations steal a bit from the length field to encode
959 // whether this is an upper16 or a lower16 relocation.
960 bool isUpper = getAnyRelocationLength(RE) >> 1;
966 printRelocationTargetName(this, RE, fmt);
968 DataRefImpl RelNext = Rel;
969 moveRelocationNext(RelNext);
970 MachO::any_relocation_info RENext = getRelocation(RelNext);
972 // ARM half relocs must be followed by a relocation of type
974 unsigned RType = getAnyRelocationType(RENext);
975 if (RType != MachO::ARM_RELOC_PAIR)
976 report_fatal_error("Expected ARM_RELOC_PAIR after "
979 // NOTE: The half of the target virtual address is stashed in the
980 // address field of the secondary relocation, but we can't reverse
981 // engineer the constant offset from it without decoding the movw/movt
982 // instruction to find the other half in its immediate field.
984 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
985 // symbol/section pointer of the follow-on relocation.
986 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
988 printRelocationTargetName(this, RENext, fmt);
995 printRelocationTargetName(this, RE, fmt);
1000 printRelocationTargetName(this, RE, fmt);
1003 Result.append(fmtbuf.begin(), fmtbuf.end());
1004 return object_error::success;
1007 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1008 bool &Result) const {
1009 unsigned Arch = getArch();
1011 getRelocationType(Rel, Type);
1015 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1016 // is always hidden.
1017 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1018 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1019 } else if (Arch == Triple::x86_64) {
1020 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1021 // an X86_64_RELOC_SUBTRACTOR.
1022 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1023 DataRefImpl RelPrev = Rel;
1026 getRelocationType(RelPrev, PrevType);
1027 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1032 return object_error::success;
1036 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1037 // guess on what the short name is. Then name is returned as a substring of the
1038 // StringRef Name passed in. The name of the dynamic library is recognized as
1039 // a framework if it has one of the two following forms:
1040 // Foo.framework/Versions/A/Foo
1041 // Foo.framework/Foo
1042 // Where A and Foo can be any string. And may contain a trailing suffix
1043 // starting with an underbar. If the Name is recognized as a framework then
1044 // isFramework is set to true else it is set to false. If the Name has a
1045 // suffix then Suffix is set to the substring in Name that contains the suffix
1046 // else it is set to a NULL StringRef.
1048 // The Name of the dynamic library is recognized as a library name if it has
1049 // one of the two following forms:
1052 // The library may have a suffix trailing the name Foo of the form:
1053 // libFoo_profile.A.dylib
1054 // libFoo_profile.dylib
1056 // The Name of the dynamic library is also recognized as a library name if it
1057 // has the following form:
1060 // If the Name of the dynamic library is none of the forms above then a NULL
1061 // StringRef is returned.
1063 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1065 StringRef &Suffix) {
1066 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1067 size_t a, b, c, d, Idx;
1069 isFramework = false;
1070 Suffix = StringRef();
1072 // Pull off the last component and make Foo point to it
1073 a = Name.rfind('/');
1074 if (a == Name.npos || a == 0)
1076 Foo = Name.slice(a+1, Name.npos);
1078 // Look for a suffix starting with a '_'
1079 Idx = Foo.rfind('_');
1080 if (Idx != Foo.npos && Foo.size() >= 2) {
1081 Suffix = Foo.slice(Idx, Foo.npos);
1082 Foo = Foo.slice(0, Idx);
1085 // First look for the form Foo.framework/Foo
1086 b = Name.rfind('/', a);
1091 F = Name.slice(Idx, Idx + Foo.size());
1092 DotFramework = Name.slice(Idx + Foo.size(),
1093 Idx + Foo.size() + sizeof(".framework/")-1);
1094 if (F == Foo && DotFramework == ".framework/") {
1099 // Next look for the form Foo.framework/Versions/A/Foo
1102 c = Name.rfind('/', b);
1103 if (c == Name.npos || c == 0)
1105 V = Name.slice(c+1, Name.npos);
1106 if (!V.startswith("Versions/"))
1108 d = Name.rfind('/', c);
1113 F = Name.slice(Idx, Idx + Foo.size());
1114 DotFramework = Name.slice(Idx + Foo.size(),
1115 Idx + Foo.size() + sizeof(".framework/")-1);
1116 if (F == Foo && DotFramework == ".framework/") {
1122 // pull off the suffix after the "." and make a point to it
1123 a = Name.rfind('.');
1124 if (a == Name.npos || a == 0)
1126 Dylib = Name.slice(a, Name.npos);
1127 if (Dylib != ".dylib")
1130 // First pull off the version letter for the form Foo.A.dylib if any.
1132 Dot = Name.slice(a-2, a-1);
1137 b = Name.rfind('/', a);
1142 // ignore any suffix after an underbar like Foo_profile.A.dylib
1143 Idx = Name.find('_', b);
1144 if (Idx != Name.npos && Idx != b) {
1145 Lib = Name.slice(b, Idx);
1146 Suffix = Name.slice(Idx, a);
1149 Lib = Name.slice(b, a);
1150 // There are incorrect library names of the form:
1151 // libATS.A_profile.dylib so check for these.
1152 if (Lib.size() >= 3) {
1153 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1155 Lib = Lib.slice(0, Lib.size()-2);
1160 Qtx = Name.slice(a, Name.npos);
1163 b = Name.rfind('/', a);
1165 Lib = Name.slice(0, a);
1167 Lib = Name.slice(b+1, a);
1168 // There are library names of the form: QT.A.qtx so check for these.
1169 if (Lib.size() >= 3) {
1170 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1172 Lib = Lib.slice(0, Lib.size()-2);
1177 // getLibraryShortNameByIndex() is used to get the short name of the library
1178 // for an undefined symbol in a linked Mach-O binary that was linked with the
1179 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1180 // It is passed the index (0 - based) of the library as translated from
1181 // GET_LIBRARY_ORDINAL (1 - based).
1182 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1183 StringRef &Res) const {
1184 if (Index >= Libraries.size())
1185 return object_error::parse_failed;
1187 // If the cache of LibrariesShortNames is not built up do that first for
1188 // all the Libraries.
1189 if (LibrariesShortNames.size() == 0) {
1190 for (unsigned i = 0; i < Libraries.size(); i++) {
1191 MachO::dylib_command D =
1192 getStruct<MachO::dylib_command>(this, Libraries[i]);
1193 if (D.dylib.name >= D.cmdsize)
1194 return object_error::parse_failed;
1195 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1196 StringRef Name = StringRef(P);
1197 if (D.dylib.name+Name.size() >= D.cmdsize)
1198 return object_error::parse_failed;
1201 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1202 if (shortName.empty())
1203 LibrariesShortNames.push_back(Name);
1205 LibrariesShortNames.push_back(shortName);
1209 Res = LibrariesShortNames[Index];
1210 return object_error::success;
1213 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1214 return getSymbolByIndex(0);
1217 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1220 return basic_symbol_iterator(SymbolRef(DRI, this));
1222 MachO::symtab_command Symtab = getSymtabLoadCommand();
1223 unsigned SymbolTableEntrySize = is64Bit() ?
1224 sizeof(MachO::nlist_64) :
1225 sizeof(MachO::nlist);
1226 unsigned Offset = Symtab.symoff +
1227 Symtab.nsyms * SymbolTableEntrySize;
1228 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1229 return basic_symbol_iterator(SymbolRef(DRI, this));
1232 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1235 return basic_symbol_iterator(SymbolRef(DRI, this));
1237 MachO::symtab_command Symtab = getSymtabLoadCommand();
1238 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1239 unsigned SymbolTableEntrySize =
1240 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1241 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1242 DRI.p += Index * SymbolTableEntrySize;
1243 return basic_symbol_iterator(SymbolRef(DRI, this));
1246 section_iterator MachOObjectFile::section_begin() const {
1248 return section_iterator(SectionRef(DRI, this));
1251 section_iterator MachOObjectFile::section_end() const {
1253 DRI.d.a = Sections.size();
1254 return section_iterator(SectionRef(DRI, this));
1257 uint8_t MachOObjectFile::getBytesInAddress() const {
1258 return is64Bit() ? 8 : 4;
1261 StringRef MachOObjectFile::getFileFormatName() const {
1262 unsigned CPUType = getCPUType(this);
1265 case llvm::MachO::CPU_TYPE_I386:
1266 return "Mach-O 32-bit i386";
1267 case llvm::MachO::CPU_TYPE_ARM:
1268 return "Mach-O arm";
1269 case llvm::MachO::CPU_TYPE_POWERPC:
1270 return "Mach-O 32-bit ppc";
1272 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1273 "64-bit object file when we're not 64-bit?");
1274 return "Mach-O 32-bit unknown";
1278 // Make sure the cpu type has the correct mask.
1279 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1280 == llvm::MachO::CPU_ARCH_ABI64 &&
1281 "32-bit object file when we're 64-bit?");
1284 case llvm::MachO::CPU_TYPE_X86_64:
1285 return "Mach-O 64-bit x86-64";
1286 case llvm::MachO::CPU_TYPE_ARM64:
1287 return "Mach-O arm64";
1288 case llvm::MachO::CPU_TYPE_POWERPC64:
1289 return "Mach-O 64-bit ppc64";
1291 return "Mach-O 64-bit unknown";
1295 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1297 case llvm::MachO::CPU_TYPE_I386:
1299 case llvm::MachO::CPU_TYPE_X86_64:
1300 return Triple::x86_64;
1301 case llvm::MachO::CPU_TYPE_ARM:
1303 case llvm::MachO::CPU_TYPE_ARM64:
1304 return Triple::aarch64;
1305 case llvm::MachO::CPU_TYPE_POWERPC:
1307 case llvm::MachO::CPU_TYPE_POWERPC64:
1308 return Triple::ppc64;
1310 return Triple::UnknownArch;
1314 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1315 const char **McpuDefault) {
1317 *McpuDefault = nullptr;
1320 case MachO::CPU_TYPE_I386:
1321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1322 case MachO::CPU_SUBTYPE_I386_ALL:
1323 return Triple("i386-apple-darwin");
1327 case MachO::CPU_TYPE_X86_64:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_X86_64_ALL:
1330 return Triple("x86_64-apple-darwin");
1331 case MachO::CPU_SUBTYPE_X86_64_H:
1332 return Triple("x86_64h-apple-darwin");
1336 case MachO::CPU_TYPE_ARM:
1337 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1338 case MachO::CPU_SUBTYPE_ARM_V4T:
1339 return Triple("armv4t-apple-darwin");
1340 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1341 return Triple("armv5e-apple-darwin");
1342 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1343 return Triple("xscale-apple-darwin");
1344 case MachO::CPU_SUBTYPE_ARM_V6:
1345 return Triple("armv6-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V6M:
1348 *McpuDefault = "cortex-m0";
1349 return Triple("armv6m-apple-darwin");
1350 case MachO::CPU_SUBTYPE_ARM_V7:
1351 return Triple("armv7-apple-darwin");
1352 case MachO::CPU_SUBTYPE_ARM_V7EM:
1354 *McpuDefault = "cortex-m4";
1355 return Triple("armv7em-apple-darwin");
1356 case MachO::CPU_SUBTYPE_ARM_V7K:
1357 return Triple("armv7k-apple-darwin");
1358 case MachO::CPU_SUBTYPE_ARM_V7M:
1360 *McpuDefault = "cortex-m3";
1361 return Triple("armv7m-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V7S:
1363 return Triple("armv7s-apple-darwin");
1367 case MachO::CPU_TYPE_ARM64:
1368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1369 case MachO::CPU_SUBTYPE_ARM64_ALL:
1370 return Triple("arm64-apple-darwin");
1374 case MachO::CPU_TYPE_POWERPC:
1375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1376 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1377 return Triple("ppc-apple-darwin");
1381 case MachO::CPU_TYPE_POWERPC64:
1382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1383 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1384 return Triple("ppc64-apple-darwin");
1393 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1394 const char **McpuDefault) {
1396 *McpuDefault = nullptr;
1399 case MachO::CPU_TYPE_ARM:
1400 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1401 case MachO::CPU_SUBTYPE_ARM_V4T:
1402 return Triple("thumbv4t-apple-darwin");
1403 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1404 return Triple("thumbv5e-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1406 return Triple("xscale-apple-darwin");
1407 case MachO::CPU_SUBTYPE_ARM_V6:
1408 return Triple("thumbv6-apple-darwin");
1409 case MachO::CPU_SUBTYPE_ARM_V6M:
1411 *McpuDefault = "cortex-m0";
1412 return Triple("thumbv6m-apple-darwin");
1413 case MachO::CPU_SUBTYPE_ARM_V7:
1414 return Triple("thumbv7-apple-darwin");
1415 case MachO::CPU_SUBTYPE_ARM_V7EM:
1417 *McpuDefault = "cortex-m4";
1418 return Triple("thumbv7em-apple-darwin");
1419 case MachO::CPU_SUBTYPE_ARM_V7K:
1420 return Triple("thumbv7k-apple-darwin");
1421 case MachO::CPU_SUBTYPE_ARM_V7M:
1423 *McpuDefault = "cortex-m3";
1424 return Triple("thumbv7m-apple-darwin");
1425 case MachO::CPU_SUBTYPE_ARM_V7S:
1426 return Triple("thumbv7s-apple-darwin");
1435 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1436 const char **McpuDefault,
1437 Triple *ThumbTriple) {
1438 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1439 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1444 Triple MachOObjectFile::getHostArch() {
1445 return Triple(sys::getDefaultTargetTriple());
1448 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1449 return StringSwitch<bool>(ArchFlag)
1451 .Case("x86_64", true)
1452 .Case("x86_64h", true)
1453 .Case("armv4t", true)
1455 .Case("armv5e", true)
1456 .Case("armv6", true)
1457 .Case("armv6m", true)
1458 .Case("armv7em", true)
1459 .Case("armv7k", true)
1460 .Case("armv7m", true)
1461 .Case("armv7s", true)
1462 .Case("arm64", true)
1464 .Case("ppc64", true)
1468 unsigned MachOObjectFile::getArch() const {
1469 return getArch(getCPUType(this));
1472 Triple MachOObjectFile::getArch(const char **McpuDefault,
1473 Triple *ThumbTriple) const {
1476 MachO::mach_header_64 H_64;
1477 H_64 = getHeader64();
1478 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1479 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1482 MachO::mach_header H;
1484 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1485 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1491 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1494 return section_rel_begin(DRI);
1497 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1500 return section_rel_end(DRI);
1503 dice_iterator MachOObjectFile::begin_dices() const {
1505 if (!DataInCodeLoadCmd)
1506 return dice_iterator(DiceRef(DRI, this));
1508 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1509 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1510 return dice_iterator(DiceRef(DRI, this));
1513 dice_iterator MachOObjectFile::end_dices() const {
1515 if (!DataInCodeLoadCmd)
1516 return dice_iterator(DiceRef(DRI, this));
1518 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1519 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1520 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1521 return dice_iterator(DiceRef(DRI, this));
1524 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1525 : Trie(T), Malformed(false), Done(false) { }
1527 void ExportEntry::moveToFirst() {
1529 pushDownUntilBottom();
1532 void ExportEntry::moveToEnd() {
1537 bool ExportEntry::operator==(const ExportEntry &Other) const {
1538 // Common case, one at end, other iterating from begin.
1539 if (Done || Other.Done)
1540 return (Done == Other.Done);
1541 // Not equal if different stack sizes.
1542 if (Stack.size() != Other.Stack.size())
1544 // Not equal if different cumulative strings.
1545 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1547 // Equal if all nodes in both stacks match.
1548 for (unsigned i=0; i < Stack.size(); ++i) {
1549 if (Stack[i].Start != Other.Stack[i].Start)
1555 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1557 uint64_t Result = decodeULEB128(Ptr, &Count);
1559 if (Ptr > Trie.end()) {
1566 StringRef ExportEntry::name() const {
1567 return CumulativeString.str();
1570 uint64_t ExportEntry::flags() const {
1571 return Stack.back().Flags;
1574 uint64_t ExportEntry::address() const {
1575 return Stack.back().Address;
1578 uint64_t ExportEntry::other() const {
1579 return Stack.back().Other;
1582 StringRef ExportEntry::otherName() const {
1583 const char* ImportName = Stack.back().ImportName;
1585 return StringRef(ImportName);
1589 uint32_t ExportEntry::nodeOffset() const {
1590 return Stack.back().Start - Trie.begin();
1593 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1594 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1595 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1596 ParentStringLength(0), IsExportNode(false) {
1599 void ExportEntry::pushNode(uint64_t offset) {
1600 const uint8_t *Ptr = Trie.begin() + offset;
1601 NodeState State(Ptr);
1602 uint64_t ExportInfoSize = readULEB128(State.Current);
1603 State.IsExportNode = (ExportInfoSize != 0);
1604 const uint8_t* Children = State.Current + ExportInfoSize;
1605 if (State.IsExportNode) {
1606 State.Flags = readULEB128(State.Current);
1607 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1609 State.Other = readULEB128(State.Current); // dylib ordinal
1610 State.ImportName = reinterpret_cast<const char*>(State.Current);
1612 State.Address = readULEB128(State.Current);
1613 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1614 State.Other = readULEB128(State.Current);
1617 State.ChildCount = *Children;
1618 State.Current = Children + 1;
1619 State.NextChildIndex = 0;
1620 State.ParentStringLength = CumulativeString.size();
1621 Stack.push_back(State);
1624 void ExportEntry::pushDownUntilBottom() {
1625 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1626 NodeState &Top = Stack.back();
1627 CumulativeString.resize(Top.ParentStringLength);
1628 for (;*Top.Current != 0; Top.Current++) {
1629 char C = *Top.Current;
1630 CumulativeString.push_back(C);
1633 uint64_t childNodeIndex = readULEB128(Top.Current);
1634 Top.NextChildIndex += 1;
1635 pushNode(childNodeIndex);
1637 if (!Stack.back().IsExportNode) {
1643 // We have a trie data structure and need a way to walk it that is compatible
1644 // with the C++ iterator model. The solution is a non-recursive depth first
1645 // traversal where the iterator contains a stack of parent nodes along with a
1646 // string that is the accumulation of all edge strings along the parent chain
1649 // There is one “export” node for each exported symbol. But because some
1650 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1651 // node may have child nodes too.
1653 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1654 // child until hitting a node with no children (which is an export node or
1655 // else the trie is malformed). On the way down, each node is pushed on the
1656 // stack ivar. If there is no more ways down, it pops up one and tries to go
1657 // down a sibling path until a childless node is reached.
1658 void ExportEntry::moveNext() {
1659 if (Stack.empty() || !Stack.back().IsExportNode) {
1666 while (!Stack.empty()) {
1667 NodeState &Top = Stack.back();
1668 if (Top.NextChildIndex < Top.ChildCount) {
1669 pushDownUntilBottom();
1670 // Now at the next export node.
1673 if (Top.IsExportNode) {
1674 // This node has no children but is itself an export node.
1675 CumulativeString.resize(Top.ParentStringLength);
1684 iterator_range<export_iterator>
1685 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1686 ExportEntry Start(Trie);
1687 Start.moveToFirst();
1689 ExportEntry Finish(Trie);
1692 return iterator_range<export_iterator>(export_iterator(Start),
1693 export_iterator(Finish));
1696 iterator_range<export_iterator> MachOObjectFile::exports() const {
1697 return exports(getDyldInfoExportsTrie());
1701 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1702 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1703 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1704 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1706 void MachORebaseEntry::moveToFirst() {
1707 Ptr = Opcodes.begin();
1711 void MachORebaseEntry::moveToEnd() {
1712 Ptr = Opcodes.end();
1713 RemainingLoopCount = 0;
1717 void MachORebaseEntry::moveNext() {
1718 // If in the middle of some loop, move to next rebasing in loop.
1719 SegmentOffset += AdvanceAmount;
1720 if (RemainingLoopCount) {
1721 --RemainingLoopCount;
1724 if (Ptr == Opcodes.end()) {
1729 while (More && !Malformed) {
1730 // Parse next opcode and set up next loop.
1731 uint8_t Byte = *Ptr++;
1732 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1733 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1735 case MachO::REBASE_OPCODE_DONE:
1739 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1741 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1742 RebaseType = ImmValue;
1745 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1746 << "RebaseType=" << (int) RebaseType << "\n");
1748 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1749 SegmentIndex = ImmValue;
1750 SegmentOffset = readULEB128();
1753 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1754 << "SegmentIndex=" << SegmentIndex << ", "
1755 << format("SegmentOffset=0x%06X", SegmentOffset)
1758 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1759 SegmentOffset += readULEB128();
1760 DEBUG_WITH_TYPE("mach-o-rebase",
1761 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1762 << format("SegmentOffset=0x%06X",
1763 SegmentOffset) << "\n");
1765 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1766 SegmentOffset += ImmValue * PointerSize;
1767 DEBUG_WITH_TYPE("mach-o-rebase",
1768 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1769 << format("SegmentOffset=0x%06X",
1770 SegmentOffset) << "\n");
1772 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1773 AdvanceAmount = PointerSize;
1774 RemainingLoopCount = ImmValue - 1;
1777 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1778 << format("SegmentOffset=0x%06X", SegmentOffset)
1779 << ", AdvanceAmount=" << AdvanceAmount
1780 << ", RemainingLoopCount=" << RemainingLoopCount
1783 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1784 AdvanceAmount = PointerSize;
1785 RemainingLoopCount = readULEB128() - 1;
1788 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1789 << format("SegmentOffset=0x%06X", SegmentOffset)
1790 << ", AdvanceAmount=" << AdvanceAmount
1791 << ", RemainingLoopCount=" << RemainingLoopCount
1794 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1795 AdvanceAmount = readULEB128() + PointerSize;
1796 RemainingLoopCount = 0;
1799 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1800 << format("SegmentOffset=0x%06X", SegmentOffset)
1801 << ", AdvanceAmount=" << AdvanceAmount
1802 << ", RemainingLoopCount=" << RemainingLoopCount
1805 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1806 RemainingLoopCount = readULEB128() - 1;
1807 AdvanceAmount = readULEB128() + PointerSize;
1810 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1811 << format("SegmentOffset=0x%06X", SegmentOffset)
1812 << ", AdvanceAmount=" << AdvanceAmount
1813 << ", RemainingLoopCount=" << RemainingLoopCount
1822 uint64_t MachORebaseEntry::readULEB128() {
1824 uint64_t Result = decodeULEB128(Ptr, &Count);
1826 if (Ptr > Opcodes.end()) {
1827 Ptr = Opcodes.end();
1833 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1835 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1837 StringRef MachORebaseEntry::typeName() const {
1838 switch (RebaseType) {
1839 case MachO::REBASE_TYPE_POINTER:
1841 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1842 return "text abs32";
1843 case MachO::REBASE_TYPE_TEXT_PCREL32:
1844 return "text rel32";
1849 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1850 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1851 return (Ptr == Other.Ptr) &&
1852 (RemainingLoopCount == Other.RemainingLoopCount) &&
1853 (Done == Other.Done);
1856 iterator_range<rebase_iterator>
1857 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1858 MachORebaseEntry Start(Opcodes, is64);
1859 Start.moveToFirst();
1861 MachORebaseEntry Finish(Opcodes, is64);
1864 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1865 rebase_iterator(Finish));
1868 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1869 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1873 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1875 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1876 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1877 BindType(0), PointerSize(is64Bit ? 8 : 4),
1878 TableKind(BK), Malformed(false), Done(false) {}
1880 void MachOBindEntry::moveToFirst() {
1881 Ptr = Opcodes.begin();
1885 void MachOBindEntry::moveToEnd() {
1886 Ptr = Opcodes.end();
1887 RemainingLoopCount = 0;
1891 void MachOBindEntry::moveNext() {
1892 // If in the middle of some loop, move to next binding in loop.
1893 SegmentOffset += AdvanceAmount;
1894 if (RemainingLoopCount) {
1895 --RemainingLoopCount;
1898 if (Ptr == Opcodes.end()) {
1903 while (More && !Malformed) {
1904 // Parse next opcode and set up next loop.
1905 uint8_t Byte = *Ptr++;
1906 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1907 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1908 int8_t SignExtended;
1909 const uint8_t *SymStart;
1911 case MachO::BIND_OPCODE_DONE:
1912 if (TableKind == Kind::Lazy) {
1913 // Lazying bindings have a DONE opcode between entries. Need to ignore
1914 // it to advance to next entry. But need not if this is last entry.
1915 bool NotLastEntry = false;
1916 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1918 NotLastEntry = true;
1927 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1929 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1933 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1934 << "Ordinal=" << Ordinal << "\n");
1936 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1937 Ordinal = readULEB128();
1940 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1941 << "Ordinal=" << Ordinal << "\n");
1943 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1945 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1946 Ordinal = SignExtended;
1951 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1952 << "Ordinal=" << Ordinal << "\n");
1954 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1960 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1965 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1966 << "SymbolName=" << SymbolName << "\n");
1967 if (TableKind == Kind::Weak) {
1968 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1972 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1973 BindType = ImmValue;
1976 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1977 << "BindType=" << (int)BindType << "\n");
1979 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1980 Addend = readSLEB128();
1981 if (TableKind == Kind::Lazy)
1985 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1986 << "Addend=" << Addend << "\n");
1988 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1989 SegmentIndex = ImmValue;
1990 SegmentOffset = readULEB128();
1993 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1994 << "SegmentIndex=" << SegmentIndex << ", "
1995 << format("SegmentOffset=0x%06X", SegmentOffset)
1998 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1999 SegmentOffset += readULEB128();
2000 DEBUG_WITH_TYPE("mach-o-bind",
2001 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2002 << format("SegmentOffset=0x%06X",
2003 SegmentOffset) << "\n");
2005 case MachO::BIND_OPCODE_DO_BIND:
2006 AdvanceAmount = PointerSize;
2007 RemainingLoopCount = 0;
2008 DEBUG_WITH_TYPE("mach-o-bind",
2009 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2010 << format("SegmentOffset=0x%06X",
2011 SegmentOffset) << "\n");
2013 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2014 AdvanceAmount = readULEB128();
2015 RemainingLoopCount = 0;
2016 if (TableKind == Kind::Lazy)
2020 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
2021 << format("SegmentOffset=0x%06X", SegmentOffset)
2022 << ", AdvanceAmount=" << AdvanceAmount
2023 << ", RemainingLoopCount=" << RemainingLoopCount
2026 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2027 AdvanceAmount = ImmValue * PointerSize;
2028 RemainingLoopCount = 0;
2029 if (TableKind == Kind::Lazy)
2031 DEBUG_WITH_TYPE("mach-o-bind",
2033 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2034 << format("SegmentOffset=0x%06X",
2035 SegmentOffset) << "\n");
2037 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2038 RemainingLoopCount = readULEB128() - 1;
2039 AdvanceAmount = readULEB128() + PointerSize;
2040 if (TableKind == Kind::Lazy)
2044 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2045 << format("SegmentOffset=0x%06X", SegmentOffset)
2046 << ", AdvanceAmount=" << AdvanceAmount
2047 << ", RemainingLoopCount=" << RemainingLoopCount
2056 uint64_t MachOBindEntry::readULEB128() {
2058 uint64_t Result = decodeULEB128(Ptr, &Count);
2060 if (Ptr > Opcodes.end()) {
2061 Ptr = Opcodes.end();
2067 int64_t MachOBindEntry::readSLEB128() {
2069 int64_t Result = decodeSLEB128(Ptr, &Count);
2071 if (Ptr > Opcodes.end()) {
2072 Ptr = Opcodes.end();
2079 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2081 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2083 StringRef MachOBindEntry::typeName() const {
2085 case MachO::BIND_TYPE_POINTER:
2087 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2088 return "text abs32";
2089 case MachO::BIND_TYPE_TEXT_PCREL32:
2090 return "text rel32";
2095 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2097 int64_t MachOBindEntry::addend() const { return Addend; }
2099 uint32_t MachOBindEntry::flags() const { return Flags; }
2101 int MachOBindEntry::ordinal() const { return Ordinal; }
2103 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2104 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2105 return (Ptr == Other.Ptr) &&
2106 (RemainingLoopCount == Other.RemainingLoopCount) &&
2107 (Done == Other.Done);
2110 iterator_range<bind_iterator>
2111 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2112 MachOBindEntry::Kind BKind) {
2113 MachOBindEntry Start(Opcodes, is64, BKind);
2114 Start.moveToFirst();
2116 MachOBindEntry Finish(Opcodes, is64, BKind);
2119 return iterator_range<bind_iterator>(bind_iterator(Start),
2120 bind_iterator(Finish));
2123 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2124 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2125 MachOBindEntry::Kind::Regular);
2128 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2129 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2130 MachOBindEntry::Kind::Lazy);
2133 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2134 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2135 MachOBindEntry::Kind::Weak);
2139 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2140 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2141 return parseSegmentOrSectionName(Raw.data());
2145 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2146 const section_base *Base =
2147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2148 return makeArrayRef(Base->sectname);
2152 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2153 const section_base *Base =
2154 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2155 return makeArrayRef(Base->segname);
2159 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2161 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2163 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2166 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2167 const MachO::any_relocation_info &RE) const {
2168 if (isLittleEndian())
2169 return RE.r_word1 & 0xffffff;
2170 return RE.r_word1 >> 8;
2173 bool MachOObjectFile::getPlainRelocationExternal(
2174 const MachO::any_relocation_info &RE) const {
2175 if (isLittleEndian())
2176 return (RE.r_word1 >> 27) & 1;
2177 return (RE.r_word1 >> 4) & 1;
2180 bool MachOObjectFile::getScatteredRelocationScattered(
2181 const MachO::any_relocation_info &RE) const {
2182 return RE.r_word0 >> 31;
2185 uint32_t MachOObjectFile::getScatteredRelocationValue(
2186 const MachO::any_relocation_info &RE) const {
2190 unsigned MachOObjectFile::getAnyRelocationAddress(
2191 const MachO::any_relocation_info &RE) const {
2192 if (isRelocationScattered(RE))
2193 return getScatteredRelocationAddress(RE);
2194 return getPlainRelocationAddress(RE);
2197 unsigned MachOObjectFile::getAnyRelocationPCRel(
2198 const MachO::any_relocation_info &RE) const {
2199 if (isRelocationScattered(RE))
2200 return getScatteredRelocationPCRel(this, RE);
2201 return getPlainRelocationPCRel(this, RE);
2204 unsigned MachOObjectFile::getAnyRelocationLength(
2205 const MachO::any_relocation_info &RE) const {
2206 if (isRelocationScattered(RE))
2207 return getScatteredRelocationLength(RE);
2208 return getPlainRelocationLength(this, RE);
2212 MachOObjectFile::getAnyRelocationType(
2213 const MachO::any_relocation_info &RE) const {
2214 if (isRelocationScattered(RE))
2215 return getScatteredRelocationType(RE);
2216 return getPlainRelocationType(this, RE);
2220 MachOObjectFile::getRelocationSection(
2221 const MachO::any_relocation_info &RE) const {
2222 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2223 return *section_end();
2224 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2227 return SectionRef(DRI, this);
2230 MachOObjectFile::LoadCommandInfo
2231 MachOObjectFile::getFirstLoadCommandInfo() const {
2232 MachOObjectFile::LoadCommandInfo Load;
2234 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2235 sizeof(MachO::mach_header);
2236 Load.Ptr = getPtr(this, HeaderSize);
2237 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2241 MachOObjectFile::LoadCommandInfo
2242 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2243 MachOObjectFile::LoadCommandInfo Next;
2244 Next.Ptr = L.Ptr + L.C.cmdsize;
2245 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2249 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2250 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2253 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2254 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2257 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2258 unsigned Index) const {
2259 const char *Sec = getSectionPtr(this, L, Index);
2260 return getStruct<MachO::section>(this, Sec);
2263 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2264 unsigned Index) const {
2265 const char *Sec = getSectionPtr(this, L, Index);
2266 return getStruct<MachO::section_64>(this, Sec);
2270 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2271 const char *P = reinterpret_cast<const char *>(DRI.p);
2272 return getStruct<MachO::nlist>(this, P);
2276 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2277 const char *P = reinterpret_cast<const char *>(DRI.p);
2278 return getStruct<MachO::nlist_64>(this, P);
2281 MachO::linkedit_data_command
2282 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2283 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2286 MachO::segment_command
2287 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2288 return getStruct<MachO::segment_command>(this, L.Ptr);
2291 MachO::segment_command_64
2292 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2293 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2296 MachO::linker_options_command
2297 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2298 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2301 MachO::version_min_command
2302 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2303 return getStruct<MachO::version_min_command>(this, L.Ptr);
2306 MachO::dylib_command
2307 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2308 return getStruct<MachO::dylib_command>(this, L.Ptr);
2311 MachO::dyld_info_command
2312 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2313 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2316 MachO::dylinker_command
2317 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2318 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2322 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2323 return getStruct<MachO::uuid_command>(this, L.Ptr);
2326 MachO::source_version_command
2327 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2328 return getStruct<MachO::source_version_command>(this, L.Ptr);
2331 MachO::entry_point_command
2332 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2333 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2337 MachO::any_relocation_info
2338 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2343 MachO::section_64 Sect = getSection64(Sec);
2344 Offset = Sect.reloff;
2346 MachO::section Sect = getSection(Sec);
2347 Offset = Sect.reloff;
2350 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2351 getPtr(this, Offset)) + Rel.d.b;
2352 return getStruct<MachO::any_relocation_info>(
2353 this, reinterpret_cast<const char *>(P));
2356 MachO::data_in_code_entry
2357 MachOObjectFile::getDice(DataRefImpl Rel) const {
2358 const char *P = reinterpret_cast<const char *>(Rel.p);
2359 return getStruct<MachO::data_in_code_entry>(this, P);
2362 MachO::mach_header MachOObjectFile::getHeader() const {
2363 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2366 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2367 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2370 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2371 const MachO::dysymtab_command &DLC,
2372 unsigned Index) const {
2373 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2374 return getStruct<uint32_t>(this, getPtr(this, Offset));
2377 MachO::data_in_code_entry
2378 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2379 unsigned Index) const {
2380 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2381 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2384 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2385 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2388 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2389 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2392 MachO::linkedit_data_command
2393 MachOObjectFile::getDataInCodeLoadCommand() const {
2394 if (DataInCodeLoadCmd)
2395 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2397 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2398 MachO::linkedit_data_command Cmd;
2399 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2400 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2406 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2407 if (!DyldInfoLoadCmd)
2408 return ArrayRef<uint8_t>();
2410 MachO::dyld_info_command DyldInfo
2411 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2412 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2413 getPtr(this, DyldInfo.rebase_off));
2414 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2417 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2418 if (!DyldInfoLoadCmd)
2419 return ArrayRef<uint8_t>();
2421 MachO::dyld_info_command DyldInfo
2422 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2423 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2424 getPtr(this, DyldInfo.bind_off));
2425 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2428 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2429 if (!DyldInfoLoadCmd)
2430 return ArrayRef<uint8_t>();
2432 MachO::dyld_info_command DyldInfo
2433 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2434 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2435 getPtr(this, DyldInfo.weak_bind_off));
2436 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2439 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2440 if (!DyldInfoLoadCmd)
2441 return ArrayRef<uint8_t>();
2443 MachO::dyld_info_command DyldInfo
2444 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2445 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2446 getPtr(this, DyldInfo.lazy_bind_off));
2447 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2450 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2451 if (!DyldInfoLoadCmd)
2452 return ArrayRef<uint8_t>();
2454 MachO::dyld_info_command DyldInfo
2455 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2456 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2457 getPtr(this, DyldInfo.export_off));
2458 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2462 StringRef MachOObjectFile::getStringTableData() const {
2463 MachO::symtab_command S = getSymtabLoadCommand();
2464 return getData().substr(S.stroff, S.strsize);
2467 bool MachOObjectFile::is64Bit() const {
2468 return getType() == getMachOType(false, true) ||
2469 getType() == getMachOType(true, true);
2472 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2473 SmallVectorImpl<uint64_t> &Out) const {
2474 DataExtractor extractor(ObjectFile::getData(), true, 0);
2476 uint32_t offset = Index;
2478 while (uint64_t delta = extractor.getULEB128(&offset)) {
2480 Out.push_back(data);
2484 bool MachOObjectFile::isRelocatableObject() const {
2485 return getHeader().filetype == MachO::MH_OBJECT;
2488 ErrorOr<std::unique_ptr<MachOObjectFile>>
2489 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2490 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2492 std::unique_ptr<MachOObjectFile> Ret;
2493 if (Magic == "\xFE\xED\xFA\xCE")
2494 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2495 else if (Magic == "\xCE\xFA\xED\xFE")
2496 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2497 else if (Magic == "\xFE\xED\xFA\xCF")
2498 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2499 else if (Magic == "\xCF\xFA\xED\xFE")
2500 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2502 return object_error::parse_failed;
2506 return std::move(Ret);