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 MachO::dylib_command D =
1188 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1189 if (D.dylib.name >= D.cmdsize)
1190 return object_error::parse_failed;
1192 // If the cache of LibrariesShortNames is not built up do that first for
1193 // all the Libraries.
1194 if (LibrariesShortNames.size() == 0) {
1195 for (unsigned i = 0; i < Libraries.size(); i++) {
1196 MachO::dylib_command D =
1197 getStruct<MachO::dylib_command>(this, Libraries[i]);
1198 if (D.dylib.name >= D.cmdsize) {
1199 LibrariesShortNames.push_back(StringRef());
1202 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1203 StringRef Name = StringRef(P);
1206 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1207 if (shortName == StringRef())
1208 LibrariesShortNames.push_back(Name);
1210 LibrariesShortNames.push_back(shortName);
1214 Res = LibrariesShortNames[Index];
1215 return object_error::success;
1218 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1219 return getSymbolByIndex(0);
1222 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1225 return basic_symbol_iterator(SymbolRef(DRI, this));
1227 MachO::symtab_command Symtab = getSymtabLoadCommand();
1228 unsigned SymbolTableEntrySize = is64Bit() ?
1229 sizeof(MachO::nlist_64) :
1230 sizeof(MachO::nlist);
1231 unsigned Offset = Symtab.symoff +
1232 Symtab.nsyms * SymbolTableEntrySize;
1233 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1234 return basic_symbol_iterator(SymbolRef(DRI, this));
1237 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1240 return basic_symbol_iterator(SymbolRef(DRI, this));
1242 MachO::symtab_command Symtab = getSymtabLoadCommand();
1243 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1244 unsigned SymbolTableEntrySize =
1245 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1246 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1247 DRI.p += Index * SymbolTableEntrySize;
1248 return basic_symbol_iterator(SymbolRef(DRI, this));
1251 section_iterator MachOObjectFile::section_begin() const {
1253 return section_iterator(SectionRef(DRI, this));
1256 section_iterator MachOObjectFile::section_end() const {
1258 DRI.d.a = Sections.size();
1259 return section_iterator(SectionRef(DRI, this));
1262 uint8_t MachOObjectFile::getBytesInAddress() const {
1263 return is64Bit() ? 8 : 4;
1266 StringRef MachOObjectFile::getFileFormatName() const {
1267 unsigned CPUType = getCPUType(this);
1270 case llvm::MachO::CPU_TYPE_I386:
1271 return "Mach-O 32-bit i386";
1272 case llvm::MachO::CPU_TYPE_ARM:
1273 return "Mach-O arm";
1274 case llvm::MachO::CPU_TYPE_POWERPC:
1275 return "Mach-O 32-bit ppc";
1277 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1278 "64-bit object file when we're not 64-bit?");
1279 return "Mach-O 32-bit unknown";
1283 // Make sure the cpu type has the correct mask.
1284 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1285 == llvm::MachO::CPU_ARCH_ABI64 &&
1286 "32-bit object file when we're 64-bit?");
1289 case llvm::MachO::CPU_TYPE_X86_64:
1290 return "Mach-O 64-bit x86-64";
1291 case llvm::MachO::CPU_TYPE_ARM64:
1292 return "Mach-O arm64";
1293 case llvm::MachO::CPU_TYPE_POWERPC64:
1294 return "Mach-O 64-bit ppc64";
1296 return "Mach-O 64-bit unknown";
1300 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1302 case llvm::MachO::CPU_TYPE_I386:
1304 case llvm::MachO::CPU_TYPE_X86_64:
1305 return Triple::x86_64;
1306 case llvm::MachO::CPU_TYPE_ARM:
1308 case llvm::MachO::CPU_TYPE_ARM64:
1309 return Triple::aarch64;
1310 case llvm::MachO::CPU_TYPE_POWERPC:
1312 case llvm::MachO::CPU_TYPE_POWERPC64:
1313 return Triple::ppc64;
1315 return Triple::UnknownArch;
1319 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1320 const char **McpuDefault) {
1322 *McpuDefault = nullptr;
1325 case MachO::CPU_TYPE_I386:
1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1327 case MachO::CPU_SUBTYPE_I386_ALL:
1328 return Triple("i386-apple-darwin");
1332 case MachO::CPU_TYPE_X86_64:
1333 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1334 case MachO::CPU_SUBTYPE_X86_64_ALL:
1335 return Triple("x86_64-apple-darwin");
1336 case MachO::CPU_SUBTYPE_X86_64_H:
1337 return Triple("x86_64h-apple-darwin");
1341 case MachO::CPU_TYPE_ARM:
1342 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1343 case MachO::CPU_SUBTYPE_ARM_V4T:
1344 return Triple("armv4t-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1346 return Triple("armv5e-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1348 return Triple("xscale-apple-darwin");
1349 case MachO::CPU_SUBTYPE_ARM_V6:
1350 return Triple("armv6-apple-darwin");
1351 case MachO::CPU_SUBTYPE_ARM_V6M:
1353 *McpuDefault = "cortex-m0";
1354 return Triple("armv6m-apple-darwin");
1355 case MachO::CPU_SUBTYPE_ARM_V7:
1356 return Triple("armv7-apple-darwin");
1357 case MachO::CPU_SUBTYPE_ARM_V7EM:
1359 *McpuDefault = "cortex-m4";
1360 return Triple("armv7em-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_V7K:
1362 return Triple("armv7k-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V7M:
1365 *McpuDefault = "cortex-m3";
1366 return Triple("armv7m-apple-darwin");
1367 case MachO::CPU_SUBTYPE_ARM_V7S:
1368 return Triple("armv7s-apple-darwin");
1372 case MachO::CPU_TYPE_ARM64:
1373 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1374 case MachO::CPU_SUBTYPE_ARM64_ALL:
1375 return Triple("arm64-apple-darwin");
1379 case MachO::CPU_TYPE_POWERPC:
1380 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1381 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1382 return Triple("ppc-apple-darwin");
1386 case MachO::CPU_TYPE_POWERPC64:
1387 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1388 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1389 return Triple("ppc64-apple-darwin");
1398 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1399 const char **McpuDefault) {
1401 *McpuDefault = nullptr;
1404 case MachO::CPU_TYPE_ARM:
1405 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1406 case MachO::CPU_SUBTYPE_ARM_V4T:
1407 return Triple("thumbv4t-apple-darwin");
1408 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1409 return Triple("thumbv5e-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1411 return Triple("xscale-apple-darwin");
1412 case MachO::CPU_SUBTYPE_ARM_V6:
1413 return Triple("thumbv6-apple-darwin");
1414 case MachO::CPU_SUBTYPE_ARM_V6M:
1416 *McpuDefault = "cortex-m0";
1417 return Triple("thumbv6m-apple-darwin");
1418 case MachO::CPU_SUBTYPE_ARM_V7:
1419 return Triple("thumbv7-apple-darwin");
1420 case MachO::CPU_SUBTYPE_ARM_V7EM:
1422 *McpuDefault = "cortex-m4";
1423 return Triple("thumbv7em-apple-darwin");
1424 case MachO::CPU_SUBTYPE_ARM_V7K:
1425 return Triple("thumbv7k-apple-darwin");
1426 case MachO::CPU_SUBTYPE_ARM_V7M:
1428 *McpuDefault = "cortex-m3";
1429 return Triple("thumbv7m-apple-darwin");
1430 case MachO::CPU_SUBTYPE_ARM_V7S:
1431 return Triple("thumbv7s-apple-darwin");
1440 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1441 const char **McpuDefault,
1442 Triple *ThumbTriple) {
1443 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1444 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1449 Triple MachOObjectFile::getHostArch() {
1450 return Triple(sys::getDefaultTargetTriple());
1453 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1454 return StringSwitch<bool>(ArchFlag)
1456 .Case("x86_64", true)
1457 .Case("x86_64h", true)
1458 .Case("armv4t", true)
1460 .Case("armv5e", true)
1461 .Case("armv6", true)
1462 .Case("armv6m", true)
1463 .Case("armv7em", true)
1464 .Case("armv7k", true)
1465 .Case("armv7m", true)
1466 .Case("armv7s", true)
1467 .Case("arm64", true)
1469 .Case("ppc64", true)
1473 unsigned MachOObjectFile::getArch() const {
1474 return getArch(getCPUType(this));
1477 Triple MachOObjectFile::getArch(const char **McpuDefault,
1478 Triple *ThumbTriple) const {
1481 MachO::mach_header_64 H_64;
1482 H_64 = getHeader64();
1483 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1484 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1487 MachO::mach_header H;
1489 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1490 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1496 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1499 return section_rel_begin(DRI);
1502 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1505 return section_rel_end(DRI);
1508 dice_iterator MachOObjectFile::begin_dices() const {
1510 if (!DataInCodeLoadCmd)
1511 return dice_iterator(DiceRef(DRI, this));
1513 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1514 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1515 return dice_iterator(DiceRef(DRI, this));
1518 dice_iterator MachOObjectFile::end_dices() const {
1520 if (!DataInCodeLoadCmd)
1521 return dice_iterator(DiceRef(DRI, this));
1523 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1524 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1525 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1526 return dice_iterator(DiceRef(DRI, this));
1529 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1530 : Trie(T), Malformed(false), Done(false) { }
1532 void ExportEntry::moveToFirst() {
1534 pushDownUntilBottom();
1537 void ExportEntry::moveToEnd() {
1542 bool ExportEntry::operator==(const ExportEntry &Other) const {
1543 // Common case, one at end, other iterating from begin.
1544 if (Done || Other.Done)
1545 return (Done == Other.Done);
1546 // Not equal if different stack sizes.
1547 if (Stack.size() != Other.Stack.size())
1549 // Not equal if different cumulative strings.
1550 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1552 // Equal if all nodes in both stacks match.
1553 for (unsigned i=0; i < Stack.size(); ++i) {
1554 if (Stack[i].Start != Other.Stack[i].Start)
1560 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1562 uint64_t Result = decodeULEB128(Ptr, &Count);
1564 if (Ptr > Trie.end()) {
1571 StringRef ExportEntry::name() const {
1572 return CumulativeString.str();
1575 uint64_t ExportEntry::flags() const {
1576 return Stack.back().Flags;
1579 uint64_t ExportEntry::address() const {
1580 return Stack.back().Address;
1583 uint64_t ExportEntry::other() const {
1584 return Stack.back().Other;
1587 StringRef ExportEntry::otherName() const {
1588 const char* ImportName = Stack.back().ImportName;
1590 return StringRef(ImportName);
1594 uint32_t ExportEntry::nodeOffset() const {
1595 return Stack.back().Start - Trie.begin();
1598 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1599 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1600 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1601 ParentStringLength(0), IsExportNode(false) {
1604 void ExportEntry::pushNode(uint64_t offset) {
1605 const uint8_t *Ptr = Trie.begin() + offset;
1606 NodeState State(Ptr);
1607 uint64_t ExportInfoSize = readULEB128(State.Current);
1608 State.IsExportNode = (ExportInfoSize != 0);
1609 const uint8_t* Children = State.Current + ExportInfoSize;
1610 if (State.IsExportNode) {
1611 State.Flags = readULEB128(State.Current);
1612 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1614 State.Other = readULEB128(State.Current); // dylib ordinal
1615 State.ImportName = reinterpret_cast<const char*>(State.Current);
1617 State.Address = readULEB128(State.Current);
1618 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1619 State.Other = readULEB128(State.Current);
1622 State.ChildCount = *Children;
1623 State.Current = Children + 1;
1624 State.NextChildIndex = 0;
1625 State.ParentStringLength = CumulativeString.size();
1626 Stack.push_back(State);
1629 void ExportEntry::pushDownUntilBottom() {
1630 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1631 NodeState &Top = Stack.back();
1632 CumulativeString.resize(Top.ParentStringLength);
1633 for (;*Top.Current != 0; Top.Current++) {
1634 char C = *Top.Current;
1635 CumulativeString.push_back(C);
1638 uint64_t childNodeIndex = readULEB128(Top.Current);
1639 Top.NextChildIndex += 1;
1640 pushNode(childNodeIndex);
1642 if (!Stack.back().IsExportNode) {
1648 // We have a trie data structure and need a way to walk it that is compatible
1649 // with the C++ iterator model. The solution is a non-recursive depth first
1650 // traversal where the iterator contains a stack of parent nodes along with a
1651 // string that is the accumulation of all edge strings along the parent chain
1654 // There is one “export” node for each exported symbol. But because some
1655 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1656 // node may have child nodes too.
1658 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1659 // child until hitting a node with no children (which is an export node or
1660 // else the trie is malformed). On the way down, each node is pushed on the
1661 // stack ivar. If there is no more ways down, it pops up one and tries to go
1662 // down a sibling path until a childless node is reached.
1663 void ExportEntry::moveNext() {
1664 if (Stack.empty() || !Stack.back().IsExportNode) {
1671 while (!Stack.empty()) {
1672 NodeState &Top = Stack.back();
1673 if (Top.NextChildIndex < Top.ChildCount) {
1674 pushDownUntilBottom();
1675 // Now at the next export node.
1678 if (Top.IsExportNode) {
1679 // This node has no children but is itself an export node.
1680 CumulativeString.resize(Top.ParentStringLength);
1689 iterator_range<export_iterator>
1690 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1691 ExportEntry Start(Trie);
1692 Start.moveToFirst();
1694 ExportEntry Finish(Trie);
1697 return iterator_range<export_iterator>(export_iterator(Start),
1698 export_iterator(Finish));
1701 iterator_range<export_iterator> MachOObjectFile::exports() const {
1702 return exports(getDyldInfoExportsTrie());
1706 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1707 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1708 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1709 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1711 void MachORebaseEntry::moveToFirst() {
1712 Ptr = Opcodes.begin();
1716 void MachORebaseEntry::moveToEnd() {
1717 Ptr = Opcodes.end();
1718 RemainingLoopCount = 0;
1722 void MachORebaseEntry::moveNext() {
1723 // If in the middle of some loop, move to next rebasing in loop.
1724 SegmentOffset += AdvanceAmount;
1725 if (RemainingLoopCount) {
1726 --RemainingLoopCount;
1729 if (Ptr == Opcodes.end()) {
1734 while (More && !Malformed) {
1735 // Parse next opcode and set up next loop.
1736 uint8_t Byte = *Ptr++;
1737 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1738 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1740 case MachO::REBASE_OPCODE_DONE:
1744 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1746 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1747 RebaseType = ImmValue;
1750 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1751 << "RebaseType=" << (int) RebaseType << "\n");
1753 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1754 SegmentIndex = ImmValue;
1755 SegmentOffset = readULEB128();
1758 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1759 << "SegmentIndex=" << SegmentIndex << ", "
1760 << format("SegmentOffset=0x%06X", SegmentOffset)
1763 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1764 SegmentOffset += readULEB128();
1765 DEBUG_WITH_TYPE("mach-o-rebase",
1766 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1767 << format("SegmentOffset=0x%06X",
1768 SegmentOffset) << "\n");
1770 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1771 SegmentOffset += ImmValue * PointerSize;
1772 DEBUG_WITH_TYPE("mach-o-rebase",
1773 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1774 << format("SegmentOffset=0x%06X",
1775 SegmentOffset) << "\n");
1777 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1778 AdvanceAmount = PointerSize;
1779 RemainingLoopCount = ImmValue - 1;
1782 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1783 << format("SegmentOffset=0x%06X", SegmentOffset)
1784 << ", AdvanceAmount=" << AdvanceAmount
1785 << ", RemainingLoopCount=" << RemainingLoopCount
1788 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1789 AdvanceAmount = PointerSize;
1790 RemainingLoopCount = readULEB128() - 1;
1793 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1794 << format("SegmentOffset=0x%06X", SegmentOffset)
1795 << ", AdvanceAmount=" << AdvanceAmount
1796 << ", RemainingLoopCount=" << RemainingLoopCount
1799 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1800 AdvanceAmount = readULEB128() + PointerSize;
1801 RemainingLoopCount = 0;
1804 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1805 << format("SegmentOffset=0x%06X", SegmentOffset)
1806 << ", AdvanceAmount=" << AdvanceAmount
1807 << ", RemainingLoopCount=" << RemainingLoopCount
1810 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1811 RemainingLoopCount = readULEB128() - 1;
1812 AdvanceAmount = readULEB128() + PointerSize;
1815 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1816 << format("SegmentOffset=0x%06X", SegmentOffset)
1817 << ", AdvanceAmount=" << AdvanceAmount
1818 << ", RemainingLoopCount=" << RemainingLoopCount
1827 uint64_t MachORebaseEntry::readULEB128() {
1829 uint64_t Result = decodeULEB128(Ptr, &Count);
1831 if (Ptr > Opcodes.end()) {
1832 Ptr = Opcodes.end();
1838 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1840 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1842 StringRef MachORebaseEntry::typeName() const {
1843 switch (RebaseType) {
1844 case MachO::REBASE_TYPE_POINTER:
1846 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1847 return "text abs32";
1848 case MachO::REBASE_TYPE_TEXT_PCREL32:
1849 return "text rel32";
1854 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1855 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1856 return (Ptr == Other.Ptr) &&
1857 (RemainingLoopCount == Other.RemainingLoopCount) &&
1858 (Done == Other.Done);
1861 iterator_range<rebase_iterator>
1862 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1863 MachORebaseEntry Start(Opcodes, is64);
1864 Start.moveToFirst();
1866 MachORebaseEntry Finish(Opcodes, is64);
1869 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1870 rebase_iterator(Finish));
1873 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1874 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1878 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1880 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1881 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1882 BindType(0), PointerSize(is64Bit ? 8 : 4),
1883 TableKind(BK), Malformed(false), Done(false) {}
1885 void MachOBindEntry::moveToFirst() {
1886 Ptr = Opcodes.begin();
1890 void MachOBindEntry::moveToEnd() {
1891 Ptr = Opcodes.end();
1892 RemainingLoopCount = 0;
1896 void MachOBindEntry::moveNext() {
1897 // If in the middle of some loop, move to next binding in loop.
1898 SegmentOffset += AdvanceAmount;
1899 if (RemainingLoopCount) {
1900 --RemainingLoopCount;
1903 if (Ptr == Opcodes.end()) {
1908 while (More && !Malformed) {
1909 // Parse next opcode and set up next loop.
1910 uint8_t Byte = *Ptr++;
1911 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1912 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1913 int8_t SignExtended;
1914 const uint8_t *SymStart;
1916 case MachO::BIND_OPCODE_DONE:
1917 if (TableKind == Kind::Lazy) {
1918 // Lazying bindings have a DONE opcode between entries. Need to ignore
1919 // it to advance to next entry. But need not if this is last entry.
1920 bool NotLastEntry = false;
1921 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1923 NotLastEntry = true;
1932 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1934 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1938 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1939 << "Ordinal=" << Ordinal << "\n");
1941 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1942 Ordinal = readULEB128();
1945 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1946 << "Ordinal=" << Ordinal << "\n");
1948 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1950 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1951 Ordinal = SignExtended;
1956 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1957 << "Ordinal=" << Ordinal << "\n");
1959 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1966 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1970 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1971 << "SymbolName=" << SymbolName << "\n");
1972 if (TableKind == Kind::Weak) {
1973 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1977 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1978 BindType = ImmValue;
1981 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1982 << "BindType=" << (int)BindType << "\n");
1984 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1985 Addend = readSLEB128();
1986 if (TableKind == Kind::Lazy)
1990 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1991 << "Addend=" << Addend << "\n");
1993 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1994 SegmentIndex = ImmValue;
1995 SegmentOffset = readULEB128();
1998 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1999 << "SegmentIndex=" << SegmentIndex << ", "
2000 << format("SegmentOffset=0x%06X", SegmentOffset)
2003 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2004 SegmentOffset += readULEB128();
2005 DEBUG_WITH_TYPE("mach-o-bind",
2006 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2007 << format("SegmentOffset=0x%06X",
2008 SegmentOffset) << "\n");
2010 case MachO::BIND_OPCODE_DO_BIND:
2011 AdvanceAmount = PointerSize;
2012 RemainingLoopCount = 0;
2013 DEBUG_WITH_TYPE("mach-o-bind",
2014 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2015 << format("SegmentOffset=0x%06X",
2016 SegmentOffset) << "\n");
2018 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2019 AdvanceAmount = readULEB128();
2020 RemainingLoopCount = 0;
2021 if (TableKind == Kind::Lazy)
2025 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
2026 << format("SegmentOffset=0x%06X", SegmentOffset)
2027 << ", AdvanceAmount=" << AdvanceAmount
2028 << ", RemainingLoopCount=" << RemainingLoopCount
2031 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2032 AdvanceAmount = ImmValue * PointerSize;
2033 RemainingLoopCount = 0;
2034 if (TableKind == Kind::Lazy)
2036 DEBUG_WITH_TYPE("mach-o-bind",
2038 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2039 << format("SegmentOffset=0x%06X",
2040 SegmentOffset) << "\n");
2042 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2043 RemainingLoopCount = readULEB128() - 1;
2044 AdvanceAmount = readULEB128() + PointerSize;
2045 if (TableKind == Kind::Lazy)
2049 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2050 << format("SegmentOffset=0x%06X", SegmentOffset)
2051 << ", AdvanceAmount=" << AdvanceAmount
2052 << ", RemainingLoopCount=" << RemainingLoopCount
2061 uint64_t MachOBindEntry::readULEB128() {
2063 uint64_t Result = decodeULEB128(Ptr, &Count);
2065 if (Ptr > Opcodes.end()) {
2066 Ptr = Opcodes.end();
2072 int64_t MachOBindEntry::readSLEB128() {
2074 int64_t Result = decodeSLEB128(Ptr, &Count);
2076 if (Ptr > Opcodes.end()) {
2077 Ptr = Opcodes.end();
2084 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2086 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2088 StringRef MachOBindEntry::typeName() const {
2090 case MachO::BIND_TYPE_POINTER:
2092 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2093 return "text abs32";
2094 case MachO::BIND_TYPE_TEXT_PCREL32:
2095 return "text rel32";
2100 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2102 int64_t MachOBindEntry::addend() const { return Addend; }
2104 uint32_t MachOBindEntry::flags() const { return Flags; }
2106 int MachOBindEntry::ordinal() const { return Ordinal; }
2108 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2109 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2110 return (Ptr == Other.Ptr) &&
2111 (RemainingLoopCount == Other.RemainingLoopCount) &&
2112 (Done == Other.Done);
2115 iterator_range<bind_iterator>
2116 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2117 MachOBindEntry::Kind BKind) {
2118 MachOBindEntry Start(Opcodes, is64, BKind);
2119 Start.moveToFirst();
2121 MachOBindEntry Finish(Opcodes, is64, BKind);
2124 return iterator_range<bind_iterator>(bind_iterator(Start),
2125 bind_iterator(Finish));
2128 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2129 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2130 MachOBindEntry::Kind::Regular);
2133 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2134 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2135 MachOBindEntry::Kind::Lazy);
2138 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2139 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2140 MachOBindEntry::Kind::Weak);
2144 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2145 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2146 return parseSegmentOrSectionName(Raw.data());
2150 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2151 const section_base *Base =
2152 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2153 return makeArrayRef(Base->sectname);
2157 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2158 const section_base *Base =
2159 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2160 return makeArrayRef(Base->segname);
2164 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2166 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2168 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2171 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2172 const MachO::any_relocation_info &RE) const {
2173 if (isLittleEndian())
2174 return RE.r_word1 & 0xffffff;
2175 return RE.r_word1 >> 8;
2178 bool MachOObjectFile::getPlainRelocationExternal(
2179 const MachO::any_relocation_info &RE) const {
2180 if (isLittleEndian())
2181 return (RE.r_word1 >> 27) & 1;
2182 return (RE.r_word1 >> 4) & 1;
2185 bool MachOObjectFile::getScatteredRelocationScattered(
2186 const MachO::any_relocation_info &RE) const {
2187 return RE.r_word0 >> 31;
2190 uint32_t MachOObjectFile::getScatteredRelocationValue(
2191 const MachO::any_relocation_info &RE) const {
2195 unsigned MachOObjectFile::getAnyRelocationAddress(
2196 const MachO::any_relocation_info &RE) const {
2197 if (isRelocationScattered(RE))
2198 return getScatteredRelocationAddress(RE);
2199 return getPlainRelocationAddress(RE);
2202 unsigned MachOObjectFile::getAnyRelocationPCRel(
2203 const MachO::any_relocation_info &RE) const {
2204 if (isRelocationScattered(RE))
2205 return getScatteredRelocationPCRel(this, RE);
2206 return getPlainRelocationPCRel(this, RE);
2209 unsigned MachOObjectFile::getAnyRelocationLength(
2210 const MachO::any_relocation_info &RE) const {
2211 if (isRelocationScattered(RE))
2212 return getScatteredRelocationLength(RE);
2213 return getPlainRelocationLength(this, RE);
2217 MachOObjectFile::getAnyRelocationType(
2218 const MachO::any_relocation_info &RE) const {
2219 if (isRelocationScattered(RE))
2220 return getScatteredRelocationType(RE);
2221 return getPlainRelocationType(this, RE);
2225 MachOObjectFile::getRelocationSection(
2226 const MachO::any_relocation_info &RE) const {
2227 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2228 return *section_end();
2229 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2232 return SectionRef(DRI, this);
2235 MachOObjectFile::LoadCommandInfo
2236 MachOObjectFile::getFirstLoadCommandInfo() const {
2237 MachOObjectFile::LoadCommandInfo Load;
2239 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2240 sizeof(MachO::mach_header);
2241 Load.Ptr = getPtr(this, HeaderSize);
2242 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2246 MachOObjectFile::LoadCommandInfo
2247 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2248 MachOObjectFile::LoadCommandInfo Next;
2249 Next.Ptr = L.Ptr + L.C.cmdsize;
2250 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2254 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2255 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2258 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2259 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2262 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2263 unsigned Index) const {
2264 const char *Sec = getSectionPtr(this, L, Index);
2265 return getStruct<MachO::section>(this, Sec);
2268 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2269 unsigned Index) const {
2270 const char *Sec = getSectionPtr(this, L, Index);
2271 return getStruct<MachO::section_64>(this, Sec);
2275 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2276 const char *P = reinterpret_cast<const char *>(DRI.p);
2277 return getStruct<MachO::nlist>(this, P);
2281 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2282 const char *P = reinterpret_cast<const char *>(DRI.p);
2283 return getStruct<MachO::nlist_64>(this, P);
2286 MachO::linkedit_data_command
2287 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2288 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2291 MachO::segment_command
2292 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2293 return getStruct<MachO::segment_command>(this, L.Ptr);
2296 MachO::segment_command_64
2297 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2298 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2301 MachO::linker_options_command
2302 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2303 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2306 MachO::version_min_command
2307 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2308 return getStruct<MachO::version_min_command>(this, L.Ptr);
2311 MachO::dylib_command
2312 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2313 return getStruct<MachO::dylib_command>(this, L.Ptr);
2316 MachO::dyld_info_command
2317 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2318 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2321 MachO::dylinker_command
2322 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2323 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2327 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2328 return getStruct<MachO::uuid_command>(this, L.Ptr);
2331 MachO::source_version_command
2332 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2333 return getStruct<MachO::source_version_command>(this, L.Ptr);
2336 MachO::entry_point_command
2337 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2338 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2342 MachO::any_relocation_info
2343 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2348 MachO::section_64 Sect = getSection64(Sec);
2349 Offset = Sect.reloff;
2351 MachO::section Sect = getSection(Sec);
2352 Offset = Sect.reloff;
2355 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2356 getPtr(this, Offset)) + Rel.d.b;
2357 return getStruct<MachO::any_relocation_info>(
2358 this, reinterpret_cast<const char *>(P));
2361 MachO::data_in_code_entry
2362 MachOObjectFile::getDice(DataRefImpl Rel) const {
2363 const char *P = reinterpret_cast<const char *>(Rel.p);
2364 return getStruct<MachO::data_in_code_entry>(this, P);
2367 MachO::mach_header MachOObjectFile::getHeader() const {
2368 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2371 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2372 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2375 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2376 const MachO::dysymtab_command &DLC,
2377 unsigned Index) const {
2378 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2379 return getStruct<uint32_t>(this, getPtr(this, Offset));
2382 MachO::data_in_code_entry
2383 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2384 unsigned Index) const {
2385 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2386 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2389 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2390 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2393 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2394 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2397 MachO::linkedit_data_command
2398 MachOObjectFile::getDataInCodeLoadCommand() const {
2399 if (DataInCodeLoadCmd)
2400 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2402 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2403 MachO::linkedit_data_command Cmd;
2404 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2405 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2411 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2412 if (!DyldInfoLoadCmd)
2413 return ArrayRef<uint8_t>();
2415 MachO::dyld_info_command DyldInfo
2416 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2417 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2418 getPtr(this, DyldInfo.rebase_off));
2419 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2422 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2423 if (!DyldInfoLoadCmd)
2424 return ArrayRef<uint8_t>();
2426 MachO::dyld_info_command DyldInfo
2427 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2428 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2429 getPtr(this, DyldInfo.bind_off));
2430 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2433 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2434 if (!DyldInfoLoadCmd)
2435 return ArrayRef<uint8_t>();
2437 MachO::dyld_info_command DyldInfo
2438 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2439 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2440 getPtr(this, DyldInfo.weak_bind_off));
2441 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2444 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2445 if (!DyldInfoLoadCmd)
2446 return ArrayRef<uint8_t>();
2448 MachO::dyld_info_command DyldInfo
2449 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2450 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2451 getPtr(this, DyldInfo.lazy_bind_off));
2452 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2455 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2456 if (!DyldInfoLoadCmd)
2457 return ArrayRef<uint8_t>();
2459 MachO::dyld_info_command DyldInfo
2460 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2461 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2462 getPtr(this, DyldInfo.export_off));
2463 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2467 StringRef MachOObjectFile::getStringTableData() const {
2468 MachO::symtab_command S = getSymtabLoadCommand();
2469 return getData().substr(S.stroff, S.strsize);
2472 bool MachOObjectFile::is64Bit() const {
2473 return getType() == getMachOType(false, true) ||
2474 getType() == getMachOType(true, true);
2477 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2478 SmallVectorImpl<uint64_t> &Out) const {
2479 DataExtractor extractor(ObjectFile::getData(), true, 0);
2481 uint32_t offset = Index;
2483 while (uint64_t delta = extractor.getULEB128(&offset)) {
2485 Out.push_back(data);
2489 bool MachOObjectFile::isRelocatableObject() const {
2490 return getHeader().filetype == MachO::MH_OBJECT;
2493 ErrorOr<std::unique_ptr<MachOObjectFile>>
2494 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2495 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2497 std::unique_ptr<MachOObjectFile> Ret;
2498 if (Magic == "\xFE\xED\xFA\xCE")
2499 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2500 else if (Magic == "\xCE\xFA\xED\xFE")
2501 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2502 else if (Magic == "\xFE\xED\xFA\xCF")
2503 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2504 else if (Magic == "\xCF\xFA\xED\xFE")
2505 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2507 return object_error::parse_failed;
2511 return std::move(Ret);