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) {
43 // Don't read before the beginning or past the end of the file
44 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
45 report_fatal_error("Malformed MachO file.");
48 memcpy(&Cmd, P, sizeof(T));
49 if (O->isLittleEndian() != sys::IsLittleEndianHost)
50 MachO::swapStruct(Cmd);
54 template <typename SegmentCmd>
55 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
57 const unsigned SectionSize = sizeof(SegmentCmd);
58 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
59 S.nsects * SectionSize > Cmdsize - sizeof(S))
61 "Number of sections too large for size of load command.");
66 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
67 const MachOObjectFile::LoadCommandInfo &L) {
69 return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
72 return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
76 static bool isPageZeroSegment(const MachOObjectFile *O,
77 const MachOObjectFile::LoadCommandInfo &L) {
79 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
80 return StringRef("__PAGEZERO").equals(S.segname);
82 MachO::segment_command S = O->getSegmentLoadCommand(L);
83 return StringRef("__PAGEZERO").equals(S.segname);
88 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
90 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
92 bool Is64 = O->is64Bit();
93 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
94 sizeof(MachO::segment_command);
95 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
96 sizeof(MachO::section);
98 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
99 return reinterpret_cast<const char*>(SectionAddr);
102 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
103 return O->getData().substr(Offset, 1).data();
106 static MachO::nlist_base
107 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
108 const char *P = reinterpret_cast<const char *>(DRI.p);
109 return getStruct<MachO::nlist_base>(O, P);
112 static StringRef parseSegmentOrSectionName(const char *P) {
116 // Not null terminated, so this is a 16 char string.
117 return StringRef(P, 16);
120 // Helper to advance a section or symbol iterator multiple increments at a time.
122 static void advance(T &it, size_t Val) {
127 static unsigned getCPUType(const MachOObjectFile *O) {
128 return O->getHeader().cputype;
131 static void printRelocationTargetName(const MachOObjectFile *O,
132 const MachO::any_relocation_info &RE,
133 raw_string_ostream &fmt) {
134 bool IsScattered = O->isRelocationScattered(RE);
136 // Target of a scattered relocation is an address. In the interest of
137 // generating pretty output, scan through the symbol table looking for a
138 // symbol that aligns with that address. If we find one, print it.
139 // Otherwise, we just print the hex address of the target.
141 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
143 for (const SymbolRef &Symbol : O->symbols()) {
148 if ((ec = Symbol.getAddress(Addr)))
149 report_fatal_error(ec.message());
152 if ((ec = Symbol.getName(Name)))
153 report_fatal_error(ec.message());
158 // If we couldn't find a symbol that this relocation refers to, try
159 // to find a section beginning instead.
160 for (const SectionRef &Section : O->sections()) {
164 uint64_t Addr = Section.getAddress();
167 if ((ec = Section.getName(Name)))
168 report_fatal_error(ec.message());
173 fmt << format("0x%x", Val);
178 bool isExtern = O->getPlainRelocationExternal(RE);
179 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
182 symbol_iterator SI = O->symbol_begin();
186 section_iterator SI = O->section_begin();
187 // Adjust for the fact that sections are 1-indexed.
188 advance(SI, Val - 1);
196 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
201 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
202 return RE.r_word0 & 0xffffff;
205 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
206 const MachO::any_relocation_info &RE) {
207 if (O->isLittleEndian())
208 return (RE.r_word1 >> 24) & 1;
209 return (RE.r_word1 >> 7) & 1;
213 getScatteredRelocationPCRel(const MachOObjectFile *O,
214 const MachO::any_relocation_info &RE) {
215 return (RE.r_word0 >> 30) & 1;
218 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
219 const MachO::any_relocation_info &RE) {
220 if (O->isLittleEndian())
221 return (RE.r_word1 >> 25) & 3;
222 return (RE.r_word1 >> 5) & 3;
226 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
227 return (RE.r_word0 >> 28) & 3;
230 static unsigned getPlainRelocationType(const MachOObjectFile *O,
231 const MachO::any_relocation_info &RE) {
232 if (O->isLittleEndian())
233 return RE.r_word1 >> 28;
234 return RE.r_word1 & 0xf;
237 static uint32_t getSectionFlags(const MachOObjectFile *O,
240 MachO::section_64 Sect = O->getSection64(Sec);
243 MachO::section Sect = O->getSection(Sec);
247 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
248 bool Is64bits, std::error_code &EC)
249 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
250 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
251 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
252 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
253 uint32_t LoadCommandCount = this->getHeader().ncmds;
254 if (LoadCommandCount == 0)
257 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
258 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
260 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
261 for (unsigned I = 0; ; ++I) {
262 if (Load.C.cmd == MachO::LC_SYMTAB) {
263 // Multiple symbol tables
265 EC = object_error::parse_failed;
268 SymtabLoadCmd = Load.Ptr;
269 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
270 // Multiple dynamic symbol tables
271 if (DysymtabLoadCmd) {
272 EC = object_error::parse_failed;
275 DysymtabLoadCmd = Load.Ptr;
276 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
277 // Multiple data in code tables
278 if (DataInCodeLoadCmd) {
279 EC = object_error::parse_failed;
282 DataInCodeLoadCmd = Load.Ptr;
283 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
284 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
285 // Multiple dyldinfo load commands
286 if (DyldInfoLoadCmd) {
287 EC = object_error::parse_failed;
290 DyldInfoLoadCmd = Load.Ptr;
291 } else if (Load.C.cmd == MachO::LC_UUID) {
292 // Multiple UUID load commands
294 EC = object_error::parse_failed;
297 UuidLoadCmd = Load.Ptr;
298 } else if (Load.C.cmd == SegmentLoadType) {
299 const unsigned SegmentLoadSize = this->is64Bit()
300 ? sizeof(MachO::segment_command_64)
301 : sizeof(MachO::segment_command);
302 if (Load.C.cmdsize < SegmentLoadSize)
303 report_fatal_error("Segment load command size is too small.");
305 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
306 for (unsigned J = 0; J < NumSections; ++J) {
307 const char *Sec = getSectionPtr(this, Load, J);
308 Sections.push_back(Sec);
310 if (isPageZeroSegment(this, Load))
311 HasPageZeroSegment = true;
312 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
313 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
314 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
315 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
316 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
317 Libraries.push_back(Load.Ptr);
320 if (I == LoadCommandCount - 1)
323 Load = getNextLoadCommandInfo(Load);
327 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
328 unsigned SymbolTableEntrySize = is64Bit() ?
329 sizeof(MachO::nlist_64) :
330 sizeof(MachO::nlist);
331 Symb.p += SymbolTableEntrySize;
334 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
335 StringRef &Res) const {
336 StringRef StringTable = getStringTableData();
337 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
338 const char *Start = &StringTable.data()[Entry.n_strx];
339 if (Start >= getData().end())
340 report_fatal_error("Symbol name entry points past end of file.");
341 Res = StringRef(Start);
342 return object_error::success;
345 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
346 DataRefImpl DRI = Sec.getRawDataRefImpl();
347 uint32_t Flags = getSectionFlags(this, DRI);
348 return Flags & MachO::SECTION_TYPE;
351 // getIndirectName() returns the name of the alias'ed symbol who's string table
352 // index is in the n_value field.
353 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
354 StringRef &Res) const {
355 StringRef StringTable = getStringTableData();
358 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
359 NValue = Entry.n_value;
360 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
361 return object_error::parse_failed;
363 MachO::nlist Entry = getSymbolTableEntry(Symb);
364 NValue = Entry.n_value;
365 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
366 return object_error::parse_failed;
368 if (NValue >= StringTable.size())
369 return object_error::parse_failed;
370 const char *Start = &StringTable.data()[NValue];
371 Res = StringRef(Start);
372 return object_error::success;
375 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
376 uint64_t &Res) const {
378 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
379 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
381 Res = UnknownAddressOrSize;
385 MachO::nlist Entry = getSymbolTableEntry(Symb);
386 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
388 Res = UnknownAddressOrSize;
392 return object_error::success;
395 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
396 uint32_t &Result) const {
397 uint32_t flags = getSymbolFlags(DRI);
398 if (flags & SymbolRef::SF_Common) {
399 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
400 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
404 return object_error::success;
407 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
408 uint64_t &Result) const {
409 uint64_t BeginOffset;
410 uint64_t EndOffset = 0;
411 uint8_t SectionIndex;
413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
415 getSymbolAddress(DRI, Value);
416 if (Value == UnknownAddressOrSize) {
417 Result = UnknownAddressOrSize;
418 return object_error::success;
423 SectionIndex = Entry.n_sect;
425 uint32_t flags = getSymbolFlags(DRI);
426 if (flags & SymbolRef::SF_Common)
429 Result = UnknownAddressOrSize;
430 return object_error::success;
432 // Unfortunately symbols are unsorted so we need to touch all
433 // symbols from load command
434 for (const SymbolRef &Symbol : symbols()) {
435 DataRefImpl DRI = Symbol.getRawDataRefImpl();
436 Entry = getSymbolTableEntryBase(this, DRI);
437 getSymbolAddress(DRI, Value);
438 if (Value == UnknownAddressOrSize)
440 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
441 if (!EndOffset || Value < EndOffset)
446 Sec.d.a = SectionIndex-1;
447 uint64_t Size = getSectionSize(Sec);
448 EndOffset = getSectionAddress(Sec);
451 Result = EndOffset - BeginOffset;
452 return object_error::success;
455 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
456 SymbolRef::Type &Res) const {
457 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
458 uint8_t n_type = Entry.n_type;
460 Res = SymbolRef::ST_Other;
462 // If this is a STAB debugging symbol, we can do nothing more.
463 if (n_type & MachO::N_STAB) {
464 Res = SymbolRef::ST_Debug;
465 return object_error::success;
468 switch (n_type & MachO::N_TYPE) {
470 Res = SymbolRef::ST_Unknown;
473 Res = SymbolRef::ST_Function;
476 return object_error::success;
479 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
480 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
482 uint8_t MachOType = Entry.n_type;
483 uint16_t MachOFlags = Entry.n_desc;
485 uint32_t Result = SymbolRef::SF_None;
487 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
488 Result |= SymbolRef::SF_Undefined;
490 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
491 Result |= SymbolRef::SF_Indirect;
493 if (MachOType & MachO::N_STAB)
494 Result |= SymbolRef::SF_FormatSpecific;
496 if (MachOType & MachO::N_EXT) {
497 Result |= SymbolRef::SF_Global;
498 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
500 getSymbolAddress(DRI, Value);
501 if (Value && Value != UnknownAddressOrSize)
502 Result |= SymbolRef::SF_Common;
505 if (!(MachOType & MachO::N_PEXT))
506 Result |= SymbolRef::SF_Exported;
509 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
510 Result |= SymbolRef::SF_Weak;
512 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
513 Result |= SymbolRef::SF_Thumb;
515 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
516 Result |= SymbolRef::SF_Absolute;
521 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
522 section_iterator &Res) const {
523 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
524 uint8_t index = Entry.n_sect;
531 Res = section_iterator(SectionRef(DRI, this));
534 return object_error::success;
537 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
541 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
542 StringRef &Result) const {
543 ArrayRef<char> Raw = getSectionRawName(Sec);
544 Result = parseSegmentOrSectionName(Raw.data());
545 return object_error::success;
548 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
550 return getSection64(Sec).addr;
551 return getSection(Sec).addr;
554 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
556 return getSection64(Sec).size;
557 return getSection(Sec).size;
560 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
561 StringRef &Res) const {
566 MachO::section_64 Sect = getSection64(Sec);
567 Offset = Sect.offset;
570 MachO::section Sect = getSection(Sec);
571 Offset = Sect.offset;
575 Res = this->getData().substr(Offset, Size);
576 return object_error::success;
579 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
582 MachO::section_64 Sect = getSection64(Sec);
585 MachO::section Sect = getSection(Sec);
589 return uint64_t(1) << Align;
592 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
593 uint32_t Flags = getSectionFlags(this, Sec);
594 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
597 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
598 uint32_t Flags = getSectionFlags(this, Sec);
599 unsigned SectionType = Flags & MachO::SECTION_TYPE;
600 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
601 !(SectionType == MachO::S_ZEROFILL ||
602 SectionType == MachO::S_GB_ZEROFILL);
605 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
606 uint32_t Flags = getSectionFlags(this, Sec);
607 unsigned SectionType = Flags & MachO::SECTION_TYPE;
608 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
609 (SectionType == MachO::S_ZEROFILL ||
610 SectionType == MachO::S_GB_ZEROFILL);
613 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
614 // FIXME: Unimplemented.
618 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
619 DataRefImpl Symb) const {
621 this->getSymbolType(Symb, ST);
622 if (ST == SymbolRef::ST_Unknown)
625 uint64_t SectBegin = getSectionAddress(Sec);
626 uint64_t SectEnd = getSectionSize(Sec);
627 SectEnd += SectBegin;
630 getSymbolAddress(Symb, SymAddr);
631 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
634 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
638 return relocation_iterator(RelocationRef(Ret, this));
642 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
645 MachO::section_64 Sect = getSection64(Sec);
648 MachO::section Sect = getSection(Sec);
655 return relocation_iterator(RelocationRef(Ret, this));
658 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
662 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
663 uint64_t &Res) const {
665 getRelocationOffset(Rel, Offset);
669 uint64_t SecAddress = getSectionAddress(Sec);
670 Res = SecAddress + Offset;
671 return object_error::success;
674 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
675 uint64_t &Res) const {
676 assert(getHeader().filetype == MachO::MH_OBJECT &&
677 "Only implemented for MH_OBJECT");
678 MachO::any_relocation_info RE = getRelocation(Rel);
679 Res = getAnyRelocationAddress(RE);
680 return object_error::success;
684 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
685 MachO::any_relocation_info RE = getRelocation(Rel);
686 if (isRelocationScattered(RE))
689 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
690 bool isExtern = getPlainRelocationExternal(RE);
694 MachO::symtab_command S = getSymtabLoadCommand();
695 unsigned SymbolTableEntrySize = is64Bit() ?
696 sizeof(MachO::nlist_64) :
697 sizeof(MachO::nlist);
698 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
700 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
701 return symbol_iterator(SymbolRef(Sym, this));
704 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
705 uint64_t &Res) const {
706 MachO::any_relocation_info RE = getRelocation(Rel);
707 Res = getAnyRelocationType(RE);
708 return object_error::success;
712 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
713 SmallVectorImpl<char> &Result) const {
716 getRelocationType(Rel, RType);
718 unsigned Arch = this->getArch();
722 static const char *const Table[] = {
723 "GENERIC_RELOC_VANILLA",
724 "GENERIC_RELOC_PAIR",
725 "GENERIC_RELOC_SECTDIFF",
726 "GENERIC_RELOC_PB_LA_PTR",
727 "GENERIC_RELOC_LOCAL_SECTDIFF",
728 "GENERIC_RELOC_TLV" };
736 case Triple::x86_64: {
737 static const char *const Table[] = {
738 "X86_64_RELOC_UNSIGNED",
739 "X86_64_RELOC_SIGNED",
740 "X86_64_RELOC_BRANCH",
741 "X86_64_RELOC_GOT_LOAD",
743 "X86_64_RELOC_SUBTRACTOR",
744 "X86_64_RELOC_SIGNED_1",
745 "X86_64_RELOC_SIGNED_2",
746 "X86_64_RELOC_SIGNED_4",
747 "X86_64_RELOC_TLV" };
756 static const char *const Table[] = {
759 "ARM_RELOC_SECTDIFF",
760 "ARM_RELOC_LOCAL_SECTDIFF",
761 "ARM_RELOC_PB_LA_PTR",
763 "ARM_THUMB_RELOC_BR22",
764 "ARM_THUMB_32BIT_BRANCH",
766 "ARM_RELOC_HALF_SECTDIFF" };
774 case Triple::aarch64: {
775 static const char *const Table[] = {
776 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
777 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
778 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
779 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
780 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
784 if (RType >= array_lengthof(Table))
791 static const char *const Table[] = {
800 "PPC_RELOC_SECTDIFF",
801 "PPC_RELOC_PB_LA_PTR",
802 "PPC_RELOC_HI16_SECTDIFF",
803 "PPC_RELOC_LO16_SECTDIFF",
804 "PPC_RELOC_HA16_SECTDIFF",
806 "PPC_RELOC_LO14_SECTDIFF",
807 "PPC_RELOC_LOCAL_SECTDIFF" };
815 case Triple::UnknownArch:
819 Result.append(res.begin(), res.end());
820 return object_error::success;
824 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
825 SmallVectorImpl<char> &Result) const {
826 MachO::any_relocation_info RE = getRelocation(Rel);
828 unsigned Arch = this->getArch();
831 raw_string_ostream fmt(fmtbuf);
832 unsigned Type = this->getAnyRelocationType(RE);
833 bool IsPCRel = this->getAnyRelocationPCRel(RE);
835 // Determine any addends that should be displayed with the relocation.
836 // These require decoding the relocation type, which is triple-specific.
838 // X86_64 has entirely custom relocation types.
839 if (Arch == Triple::x86_64) {
840 bool isPCRel = getAnyRelocationPCRel(RE);
843 case MachO::X86_64_RELOC_GOT_LOAD:
844 case MachO::X86_64_RELOC_GOT: {
845 printRelocationTargetName(this, RE, fmt);
847 if (isPCRel) fmt << "PCREL";
850 case MachO::X86_64_RELOC_SUBTRACTOR: {
851 DataRefImpl RelNext = Rel;
852 moveRelocationNext(RelNext);
853 MachO::any_relocation_info RENext = getRelocation(RelNext);
855 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
856 // X86_64_RELOC_UNSIGNED.
857 // NOTE: Scattered relocations don't exist on x86_64.
858 unsigned RType = getAnyRelocationType(RENext);
859 if (RType != MachO::X86_64_RELOC_UNSIGNED)
860 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
861 "X86_64_RELOC_SUBTRACTOR.");
863 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
864 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
865 printRelocationTargetName(this, RENext, fmt);
867 printRelocationTargetName(this, RE, fmt);
870 case MachO::X86_64_RELOC_TLV:
871 printRelocationTargetName(this, RE, fmt);
873 if (isPCRel) fmt << "P";
875 case MachO::X86_64_RELOC_SIGNED_1:
876 printRelocationTargetName(this, RE, fmt);
879 case MachO::X86_64_RELOC_SIGNED_2:
880 printRelocationTargetName(this, RE, fmt);
883 case MachO::X86_64_RELOC_SIGNED_4:
884 printRelocationTargetName(this, RE, fmt);
888 printRelocationTargetName(this, RE, fmt);
891 // X86 and ARM share some relocation types in common.
892 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
893 Arch == Triple::ppc) {
894 // Generic relocation types...
896 case MachO::GENERIC_RELOC_PAIR: // prints no info
897 return object_error::success;
898 case MachO::GENERIC_RELOC_SECTDIFF: {
899 DataRefImpl RelNext = Rel;
900 moveRelocationNext(RelNext);
901 MachO::any_relocation_info RENext = getRelocation(RelNext);
903 // X86 sect diff's must be followed by a relocation of type
904 // GENERIC_RELOC_PAIR.
905 unsigned RType = getAnyRelocationType(RENext);
907 if (RType != MachO::GENERIC_RELOC_PAIR)
908 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
909 "GENERIC_RELOC_SECTDIFF.");
911 printRelocationTargetName(this, RE, fmt);
913 printRelocationTargetName(this, RENext, fmt);
918 if (Arch == Triple::x86 || Arch == Triple::ppc) {
920 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
921 DataRefImpl RelNext = Rel;
922 moveRelocationNext(RelNext);
923 MachO::any_relocation_info RENext = getRelocation(RelNext);
925 // X86 sect diff's must be followed by a relocation of type
926 // GENERIC_RELOC_PAIR.
927 unsigned RType = getAnyRelocationType(RENext);
928 if (RType != MachO::GENERIC_RELOC_PAIR)
929 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
930 "GENERIC_RELOC_LOCAL_SECTDIFF.");
932 printRelocationTargetName(this, RE, fmt);
934 printRelocationTargetName(this, RENext, fmt);
937 case MachO::GENERIC_RELOC_TLV: {
938 printRelocationTargetName(this, RE, fmt);
940 if (IsPCRel) fmt << "P";
944 printRelocationTargetName(this, RE, fmt);
946 } else { // ARM-specific relocations
948 case MachO::ARM_RELOC_HALF:
949 case MachO::ARM_RELOC_HALF_SECTDIFF: {
950 // Half relocations steal a bit from the length field to encode
951 // whether this is an upper16 or a lower16 relocation.
952 bool isUpper = getAnyRelocationLength(RE) >> 1;
958 printRelocationTargetName(this, RE, fmt);
960 DataRefImpl RelNext = Rel;
961 moveRelocationNext(RelNext);
962 MachO::any_relocation_info RENext = getRelocation(RelNext);
964 // ARM half relocs must be followed by a relocation of type
966 unsigned RType = getAnyRelocationType(RENext);
967 if (RType != MachO::ARM_RELOC_PAIR)
968 report_fatal_error("Expected ARM_RELOC_PAIR after "
971 // NOTE: The half of the target virtual address is stashed in the
972 // address field of the secondary relocation, but we can't reverse
973 // engineer the constant offset from it without decoding the movw/movt
974 // instruction to find the other half in its immediate field.
976 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
977 // symbol/section pointer of the follow-on relocation.
978 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
980 printRelocationTargetName(this, RENext, fmt);
987 printRelocationTargetName(this, RE, fmt);
992 printRelocationTargetName(this, RE, fmt);
995 Result.append(fmtbuf.begin(), fmtbuf.end());
996 return object_error::success;
999 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1000 bool &Result) const {
1001 unsigned Arch = getArch();
1003 getRelocationType(Rel, Type);
1007 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1008 // is always hidden.
1009 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1010 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1011 } else if (Arch == Triple::x86_64) {
1012 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1013 // an X86_64_RELOC_SUBTRACTOR.
1014 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1015 DataRefImpl RelPrev = Rel;
1018 getRelocationType(RelPrev, PrevType);
1019 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1024 return object_error::success;
1028 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1029 // guess on what the short name is. Then name is returned as a substring of the
1030 // StringRef Name passed in. The name of the dynamic library is recognized as
1031 // a framework if it has one of the two following forms:
1032 // Foo.framework/Versions/A/Foo
1033 // Foo.framework/Foo
1034 // Where A and Foo can be any string. And may contain a trailing suffix
1035 // starting with an underbar. If the Name is recognized as a framework then
1036 // isFramework is set to true else it is set to false. If the Name has a
1037 // suffix then Suffix is set to the substring in Name that contains the suffix
1038 // else it is set to a NULL StringRef.
1040 // The Name of the dynamic library is recognized as a library name if it has
1041 // one of the two following forms:
1044 // The library may have a suffix trailing the name Foo of the form:
1045 // libFoo_profile.A.dylib
1046 // libFoo_profile.dylib
1048 // The Name of the dynamic library is also recognized as a library name if it
1049 // has the following form:
1052 // If the Name of the dynamic library is none of the forms above then a NULL
1053 // StringRef is returned.
1055 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1057 StringRef &Suffix) {
1058 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1059 size_t a, b, c, d, Idx;
1061 isFramework = false;
1062 Suffix = StringRef();
1064 // Pull off the last component and make Foo point to it
1065 a = Name.rfind('/');
1066 if (a == Name.npos || a == 0)
1068 Foo = Name.slice(a+1, Name.npos);
1070 // Look for a suffix starting with a '_'
1071 Idx = Foo.rfind('_');
1072 if (Idx != Foo.npos && Foo.size() >= 2) {
1073 Suffix = Foo.slice(Idx, Foo.npos);
1074 Foo = Foo.slice(0, Idx);
1077 // First look for the form Foo.framework/Foo
1078 b = Name.rfind('/', a);
1083 F = Name.slice(Idx, Idx + Foo.size());
1084 DotFramework = Name.slice(Idx + Foo.size(),
1085 Idx + Foo.size() + sizeof(".framework/")-1);
1086 if (F == Foo && DotFramework == ".framework/") {
1091 // Next look for the form Foo.framework/Versions/A/Foo
1094 c = Name.rfind('/', b);
1095 if (c == Name.npos || c == 0)
1097 V = Name.slice(c+1, Name.npos);
1098 if (!V.startswith("Versions/"))
1100 d = Name.rfind('/', c);
1105 F = Name.slice(Idx, Idx + Foo.size());
1106 DotFramework = Name.slice(Idx + Foo.size(),
1107 Idx + Foo.size() + sizeof(".framework/")-1);
1108 if (F == Foo && DotFramework == ".framework/") {
1114 // pull off the suffix after the "." and make a point to it
1115 a = Name.rfind('.');
1116 if (a == Name.npos || a == 0)
1118 Dylib = Name.slice(a, Name.npos);
1119 if (Dylib != ".dylib")
1122 // First pull off the version letter for the form Foo.A.dylib if any.
1124 Dot = Name.slice(a-2, a-1);
1129 b = Name.rfind('/', a);
1134 // ignore any suffix after an underbar like Foo_profile.A.dylib
1135 Idx = Name.find('_', b);
1136 if (Idx != Name.npos && Idx != b) {
1137 Lib = Name.slice(b, Idx);
1138 Suffix = Name.slice(Idx, a);
1141 Lib = Name.slice(b, a);
1142 // There are incorrect library names of the form:
1143 // libATS.A_profile.dylib so check for these.
1144 if (Lib.size() >= 3) {
1145 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1147 Lib = Lib.slice(0, Lib.size()-2);
1152 Qtx = Name.slice(a, Name.npos);
1155 b = Name.rfind('/', a);
1157 Lib = Name.slice(0, a);
1159 Lib = Name.slice(b+1, a);
1160 // There are library names of the form: QT.A.qtx so check for these.
1161 if (Lib.size() >= 3) {
1162 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1164 Lib = Lib.slice(0, Lib.size()-2);
1169 // getLibraryShortNameByIndex() is used to get the short name of the library
1170 // for an undefined symbol in a linked Mach-O binary that was linked with the
1171 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1172 // It is passed the index (0 - based) of the library as translated from
1173 // GET_LIBRARY_ORDINAL (1 - based).
1174 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1175 StringRef &Res) const {
1176 if (Index >= Libraries.size())
1177 return object_error::parse_failed;
1179 // If the cache of LibrariesShortNames is not built up do that first for
1180 // all the Libraries.
1181 if (LibrariesShortNames.size() == 0) {
1182 for (unsigned i = 0; i < Libraries.size(); i++) {
1183 MachO::dylib_command D =
1184 getStruct<MachO::dylib_command>(this, Libraries[i]);
1185 if (D.dylib.name >= D.cmdsize)
1186 return object_error::parse_failed;
1187 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1188 StringRef Name = StringRef(P);
1189 if (D.dylib.name+Name.size() >= D.cmdsize)
1190 return object_error::parse_failed;
1193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1194 if (shortName.empty())
1195 LibrariesShortNames.push_back(Name);
1197 LibrariesShortNames.push_back(shortName);
1201 Res = LibrariesShortNames[Index];
1202 return object_error::success;
1205 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1206 return getSymbolByIndex(0);
1209 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1212 return basic_symbol_iterator(SymbolRef(DRI, this));
1214 MachO::symtab_command Symtab = getSymtabLoadCommand();
1215 unsigned SymbolTableEntrySize = is64Bit() ?
1216 sizeof(MachO::nlist_64) :
1217 sizeof(MachO::nlist);
1218 unsigned Offset = Symtab.symoff +
1219 Symtab.nsyms * SymbolTableEntrySize;
1220 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1221 return basic_symbol_iterator(SymbolRef(DRI, this));
1224 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1227 return basic_symbol_iterator(SymbolRef(DRI, this));
1229 MachO::symtab_command Symtab = getSymtabLoadCommand();
1230 if (Index >= Symtab.nsyms)
1231 report_fatal_error("Requested symbol index is out of range.");
1232 unsigned SymbolTableEntrySize =
1233 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1234 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1235 DRI.p += Index * SymbolTableEntrySize;
1236 return basic_symbol_iterator(SymbolRef(DRI, this));
1239 section_iterator MachOObjectFile::section_begin() const {
1241 return section_iterator(SectionRef(DRI, this));
1244 section_iterator MachOObjectFile::section_end() const {
1246 DRI.d.a = Sections.size();
1247 return section_iterator(SectionRef(DRI, this));
1250 uint8_t MachOObjectFile::getBytesInAddress() const {
1251 return is64Bit() ? 8 : 4;
1254 StringRef MachOObjectFile::getFileFormatName() const {
1255 unsigned CPUType = getCPUType(this);
1258 case llvm::MachO::CPU_TYPE_I386:
1259 return "Mach-O 32-bit i386";
1260 case llvm::MachO::CPU_TYPE_ARM:
1261 return "Mach-O arm";
1262 case llvm::MachO::CPU_TYPE_POWERPC:
1263 return "Mach-O 32-bit ppc";
1265 return "Mach-O 32-bit unknown";
1270 case llvm::MachO::CPU_TYPE_X86_64:
1271 return "Mach-O 64-bit x86-64";
1272 case llvm::MachO::CPU_TYPE_ARM64:
1273 return "Mach-O arm64";
1274 case llvm::MachO::CPU_TYPE_POWERPC64:
1275 return "Mach-O 64-bit ppc64";
1277 return "Mach-O 64-bit unknown";
1281 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1283 case llvm::MachO::CPU_TYPE_I386:
1285 case llvm::MachO::CPU_TYPE_X86_64:
1286 return Triple::x86_64;
1287 case llvm::MachO::CPU_TYPE_ARM:
1289 case llvm::MachO::CPU_TYPE_ARM64:
1290 return Triple::aarch64;
1291 case llvm::MachO::CPU_TYPE_POWERPC:
1293 case llvm::MachO::CPU_TYPE_POWERPC64:
1294 return Triple::ppc64;
1296 return Triple::UnknownArch;
1300 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1301 const char **McpuDefault) {
1303 *McpuDefault = nullptr;
1306 case MachO::CPU_TYPE_I386:
1307 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1308 case MachO::CPU_SUBTYPE_I386_ALL:
1309 return Triple("i386-apple-darwin");
1313 case MachO::CPU_TYPE_X86_64:
1314 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1315 case MachO::CPU_SUBTYPE_X86_64_ALL:
1316 return Triple("x86_64-apple-darwin");
1317 case MachO::CPU_SUBTYPE_X86_64_H:
1318 return Triple("x86_64h-apple-darwin");
1322 case MachO::CPU_TYPE_ARM:
1323 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1324 case MachO::CPU_SUBTYPE_ARM_V4T:
1325 return Triple("armv4t-apple-darwin");
1326 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1327 return Triple("armv5e-apple-darwin");
1328 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1329 return Triple("xscale-apple-darwin");
1330 case MachO::CPU_SUBTYPE_ARM_V6:
1331 return Triple("armv6-apple-darwin");
1332 case MachO::CPU_SUBTYPE_ARM_V6M:
1334 *McpuDefault = "cortex-m0";
1335 return Triple("armv6m-apple-darwin");
1336 case MachO::CPU_SUBTYPE_ARM_V7:
1337 return Triple("armv7-apple-darwin");
1338 case MachO::CPU_SUBTYPE_ARM_V7EM:
1340 *McpuDefault = "cortex-m4";
1341 return Triple("armv7em-apple-darwin");
1342 case MachO::CPU_SUBTYPE_ARM_V7K:
1343 return Triple("armv7k-apple-darwin");
1344 case MachO::CPU_SUBTYPE_ARM_V7M:
1346 *McpuDefault = "cortex-m3";
1347 return Triple("armv7m-apple-darwin");
1348 case MachO::CPU_SUBTYPE_ARM_V7S:
1349 return Triple("armv7s-apple-darwin");
1353 case MachO::CPU_TYPE_ARM64:
1354 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1355 case MachO::CPU_SUBTYPE_ARM64_ALL:
1356 return Triple("arm64-apple-darwin");
1360 case MachO::CPU_TYPE_POWERPC:
1361 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1362 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1363 return Triple("ppc-apple-darwin");
1367 case MachO::CPU_TYPE_POWERPC64:
1368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1369 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1370 return Triple("ppc64-apple-darwin");
1379 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1380 const char **McpuDefault) {
1382 *McpuDefault = nullptr;
1385 case MachO::CPU_TYPE_ARM:
1386 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1387 case MachO::CPU_SUBTYPE_ARM_V4T:
1388 return Triple("thumbv4t-apple-darwin");
1389 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1390 return Triple("thumbv5e-apple-darwin");
1391 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1392 return Triple("xscale-apple-darwin");
1393 case MachO::CPU_SUBTYPE_ARM_V6:
1394 return Triple("thumbv6-apple-darwin");
1395 case MachO::CPU_SUBTYPE_ARM_V6M:
1397 *McpuDefault = "cortex-m0";
1398 return Triple("thumbv6m-apple-darwin");
1399 case MachO::CPU_SUBTYPE_ARM_V7:
1400 return Triple("thumbv7-apple-darwin");
1401 case MachO::CPU_SUBTYPE_ARM_V7EM:
1403 *McpuDefault = "cortex-m4";
1404 return Triple("thumbv7em-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_V7K:
1406 return Triple("thumbv7k-apple-darwin");
1407 case MachO::CPU_SUBTYPE_ARM_V7M:
1409 *McpuDefault = "cortex-m3";
1410 return Triple("thumbv7m-apple-darwin");
1411 case MachO::CPU_SUBTYPE_ARM_V7S:
1412 return Triple("thumbv7s-apple-darwin");
1421 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1422 const char **McpuDefault,
1423 Triple *ThumbTriple) {
1424 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1425 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1430 Triple MachOObjectFile::getHostArch() {
1431 return Triple(sys::getDefaultTargetTriple());
1434 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1435 return StringSwitch<bool>(ArchFlag)
1437 .Case("x86_64", true)
1438 .Case("x86_64h", true)
1439 .Case("armv4t", true)
1441 .Case("armv5e", true)
1442 .Case("armv6", true)
1443 .Case("armv6m", true)
1444 .Case("armv7em", true)
1445 .Case("armv7k", true)
1446 .Case("armv7m", true)
1447 .Case("armv7s", true)
1448 .Case("arm64", true)
1450 .Case("ppc64", true)
1454 unsigned MachOObjectFile::getArch() const {
1455 return getArch(getCPUType(this));
1458 Triple MachOObjectFile::getArch(const char **McpuDefault,
1459 Triple *ThumbTriple) const {
1462 MachO::mach_header_64 H_64;
1463 H_64 = getHeader64();
1464 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1465 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1468 MachO::mach_header H;
1470 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1471 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1477 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1480 return section_rel_begin(DRI);
1483 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1486 return section_rel_end(DRI);
1489 dice_iterator MachOObjectFile::begin_dices() const {
1491 if (!DataInCodeLoadCmd)
1492 return dice_iterator(DiceRef(DRI, this));
1494 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1495 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1496 return dice_iterator(DiceRef(DRI, this));
1499 dice_iterator MachOObjectFile::end_dices() const {
1501 if (!DataInCodeLoadCmd)
1502 return dice_iterator(DiceRef(DRI, this));
1504 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1505 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1506 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1507 return dice_iterator(DiceRef(DRI, this));
1510 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1511 : Trie(T), Malformed(false), Done(false) { }
1513 void ExportEntry::moveToFirst() {
1515 pushDownUntilBottom();
1518 void ExportEntry::moveToEnd() {
1523 bool ExportEntry::operator==(const ExportEntry &Other) const {
1524 // Common case, one at end, other iterating from begin.
1525 if (Done || Other.Done)
1526 return (Done == Other.Done);
1527 // Not equal if different stack sizes.
1528 if (Stack.size() != Other.Stack.size())
1530 // Not equal if different cumulative strings.
1531 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1533 // Equal if all nodes in both stacks match.
1534 for (unsigned i=0; i < Stack.size(); ++i) {
1535 if (Stack[i].Start != Other.Stack[i].Start)
1541 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1543 uint64_t Result = decodeULEB128(Ptr, &Count);
1545 if (Ptr > Trie.end()) {
1552 StringRef ExportEntry::name() const {
1553 return CumulativeString.str();
1556 uint64_t ExportEntry::flags() const {
1557 return Stack.back().Flags;
1560 uint64_t ExportEntry::address() const {
1561 return Stack.back().Address;
1564 uint64_t ExportEntry::other() const {
1565 return Stack.back().Other;
1568 StringRef ExportEntry::otherName() const {
1569 const char* ImportName = Stack.back().ImportName;
1571 return StringRef(ImportName);
1575 uint32_t ExportEntry::nodeOffset() const {
1576 return Stack.back().Start - Trie.begin();
1579 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1580 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1581 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1582 ParentStringLength(0), IsExportNode(false) {
1585 void ExportEntry::pushNode(uint64_t offset) {
1586 const uint8_t *Ptr = Trie.begin() + offset;
1587 NodeState State(Ptr);
1588 uint64_t ExportInfoSize = readULEB128(State.Current);
1589 State.IsExportNode = (ExportInfoSize != 0);
1590 const uint8_t* Children = State.Current + ExportInfoSize;
1591 if (State.IsExportNode) {
1592 State.Flags = readULEB128(State.Current);
1593 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1595 State.Other = readULEB128(State.Current); // dylib ordinal
1596 State.ImportName = reinterpret_cast<const char*>(State.Current);
1598 State.Address = readULEB128(State.Current);
1599 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1600 State.Other = readULEB128(State.Current);
1603 State.ChildCount = *Children;
1604 State.Current = Children + 1;
1605 State.NextChildIndex = 0;
1606 State.ParentStringLength = CumulativeString.size();
1607 Stack.push_back(State);
1610 void ExportEntry::pushDownUntilBottom() {
1611 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1612 NodeState &Top = Stack.back();
1613 CumulativeString.resize(Top.ParentStringLength);
1614 for (;*Top.Current != 0; Top.Current++) {
1615 char C = *Top.Current;
1616 CumulativeString.push_back(C);
1619 uint64_t childNodeIndex = readULEB128(Top.Current);
1620 Top.NextChildIndex += 1;
1621 pushNode(childNodeIndex);
1623 if (!Stack.back().IsExportNode) {
1629 // We have a trie data structure and need a way to walk it that is compatible
1630 // with the C++ iterator model. The solution is a non-recursive depth first
1631 // traversal where the iterator contains a stack of parent nodes along with a
1632 // string that is the accumulation of all edge strings along the parent chain
1635 // There is one "export" node for each exported symbol. But because some
1636 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1637 // node may have child nodes too.
1639 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1640 // child until hitting a node with no children (which is an export node or
1641 // else the trie is malformed). On the way down, each node is pushed on the
1642 // stack ivar. If there is no more ways down, it pops up one and tries to go
1643 // down a sibling path until a childless node is reached.
1644 void ExportEntry::moveNext() {
1645 if (Stack.empty() || !Stack.back().IsExportNode) {
1652 while (!Stack.empty()) {
1653 NodeState &Top = Stack.back();
1654 if (Top.NextChildIndex < Top.ChildCount) {
1655 pushDownUntilBottom();
1656 // Now at the next export node.
1659 if (Top.IsExportNode) {
1660 // This node has no children but is itself an export node.
1661 CumulativeString.resize(Top.ParentStringLength);
1670 iterator_range<export_iterator>
1671 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1672 ExportEntry Start(Trie);
1673 if (Trie.size() == 0)
1676 Start.moveToFirst();
1678 ExportEntry Finish(Trie);
1681 return iterator_range<export_iterator>(export_iterator(Start),
1682 export_iterator(Finish));
1685 iterator_range<export_iterator> MachOObjectFile::exports() const {
1686 return exports(getDyldInfoExportsTrie());
1690 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1691 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1692 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1693 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1695 void MachORebaseEntry::moveToFirst() {
1696 Ptr = Opcodes.begin();
1700 void MachORebaseEntry::moveToEnd() {
1701 Ptr = Opcodes.end();
1702 RemainingLoopCount = 0;
1706 void MachORebaseEntry::moveNext() {
1707 // If in the middle of some loop, move to next rebasing in loop.
1708 SegmentOffset += AdvanceAmount;
1709 if (RemainingLoopCount) {
1710 --RemainingLoopCount;
1713 if (Ptr == Opcodes.end()) {
1718 while (More && !Malformed) {
1719 // Parse next opcode and set up next loop.
1720 uint8_t Byte = *Ptr++;
1721 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1722 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1724 case MachO::REBASE_OPCODE_DONE:
1728 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1730 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1731 RebaseType = ImmValue;
1734 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1735 << "RebaseType=" << (int) RebaseType << "\n");
1737 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1738 SegmentIndex = ImmValue;
1739 SegmentOffset = readULEB128();
1742 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1743 << "SegmentIndex=" << SegmentIndex << ", "
1744 << format("SegmentOffset=0x%06X", SegmentOffset)
1747 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1748 SegmentOffset += readULEB128();
1749 DEBUG_WITH_TYPE("mach-o-rebase",
1750 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1751 << format("SegmentOffset=0x%06X",
1752 SegmentOffset) << "\n");
1754 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1755 SegmentOffset += ImmValue * PointerSize;
1756 DEBUG_WITH_TYPE("mach-o-rebase",
1757 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1758 << format("SegmentOffset=0x%06X",
1759 SegmentOffset) << "\n");
1761 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1762 AdvanceAmount = PointerSize;
1763 RemainingLoopCount = ImmValue - 1;
1766 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1767 << format("SegmentOffset=0x%06X", SegmentOffset)
1768 << ", AdvanceAmount=" << AdvanceAmount
1769 << ", RemainingLoopCount=" << RemainingLoopCount
1772 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1773 AdvanceAmount = PointerSize;
1774 RemainingLoopCount = readULEB128() - 1;
1777 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1778 << format("SegmentOffset=0x%06X", SegmentOffset)
1779 << ", AdvanceAmount=" << AdvanceAmount
1780 << ", RemainingLoopCount=" << RemainingLoopCount
1783 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1784 AdvanceAmount = readULEB128() + PointerSize;
1785 RemainingLoopCount = 0;
1788 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1789 << format("SegmentOffset=0x%06X", SegmentOffset)
1790 << ", AdvanceAmount=" << AdvanceAmount
1791 << ", RemainingLoopCount=" << RemainingLoopCount
1794 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1795 RemainingLoopCount = readULEB128() - 1;
1796 AdvanceAmount = readULEB128() + PointerSize;
1799 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1800 << format("SegmentOffset=0x%06X", SegmentOffset)
1801 << ", AdvanceAmount=" << AdvanceAmount
1802 << ", RemainingLoopCount=" << RemainingLoopCount
1811 uint64_t MachORebaseEntry::readULEB128() {
1813 uint64_t Result = decodeULEB128(Ptr, &Count);
1815 if (Ptr > Opcodes.end()) {
1816 Ptr = Opcodes.end();
1822 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1824 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1826 StringRef MachORebaseEntry::typeName() const {
1827 switch (RebaseType) {
1828 case MachO::REBASE_TYPE_POINTER:
1830 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1831 return "text abs32";
1832 case MachO::REBASE_TYPE_TEXT_PCREL32:
1833 return "text rel32";
1838 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1839 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1840 return (Ptr == Other.Ptr) &&
1841 (RemainingLoopCount == Other.RemainingLoopCount) &&
1842 (Done == Other.Done);
1845 iterator_range<rebase_iterator>
1846 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1847 MachORebaseEntry Start(Opcodes, is64);
1848 Start.moveToFirst();
1850 MachORebaseEntry Finish(Opcodes, is64);
1853 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1854 rebase_iterator(Finish));
1857 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1858 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1862 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1864 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1865 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1866 BindType(0), PointerSize(is64Bit ? 8 : 4),
1867 TableKind(BK), Malformed(false), Done(false) {}
1869 void MachOBindEntry::moveToFirst() {
1870 Ptr = Opcodes.begin();
1874 void MachOBindEntry::moveToEnd() {
1875 Ptr = Opcodes.end();
1876 RemainingLoopCount = 0;
1880 void MachOBindEntry::moveNext() {
1881 // If in the middle of some loop, move to next binding in loop.
1882 SegmentOffset += AdvanceAmount;
1883 if (RemainingLoopCount) {
1884 --RemainingLoopCount;
1887 if (Ptr == Opcodes.end()) {
1892 while (More && !Malformed) {
1893 // Parse next opcode and set up next loop.
1894 uint8_t Byte = *Ptr++;
1895 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1896 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1897 int8_t SignExtended;
1898 const uint8_t *SymStart;
1900 case MachO::BIND_OPCODE_DONE:
1901 if (TableKind == Kind::Lazy) {
1902 // Lazying bindings have a DONE opcode between entries. Need to ignore
1903 // it to advance to next entry. But need not if this is last entry.
1904 bool NotLastEntry = false;
1905 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1907 NotLastEntry = true;
1916 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1918 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1922 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1923 << "Ordinal=" << Ordinal << "\n");
1925 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1926 Ordinal = readULEB128();
1929 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1930 << "Ordinal=" << Ordinal << "\n");
1932 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1934 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1935 Ordinal = SignExtended;
1940 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1941 << "Ordinal=" << Ordinal << "\n");
1943 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1949 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1954 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1955 << "SymbolName=" << SymbolName << "\n");
1956 if (TableKind == Kind::Weak) {
1957 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1961 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1962 BindType = ImmValue;
1965 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1966 << "BindType=" << (int)BindType << "\n");
1968 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1969 Addend = readSLEB128();
1970 if (TableKind == Kind::Lazy)
1974 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1975 << "Addend=" << Addend << "\n");
1977 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1978 SegmentIndex = ImmValue;
1979 SegmentOffset = readULEB128();
1982 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1983 << "SegmentIndex=" << SegmentIndex << ", "
1984 << format("SegmentOffset=0x%06X", SegmentOffset)
1987 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1988 SegmentOffset += readULEB128();
1989 DEBUG_WITH_TYPE("mach-o-bind",
1990 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1991 << format("SegmentOffset=0x%06X",
1992 SegmentOffset) << "\n");
1994 case MachO::BIND_OPCODE_DO_BIND:
1995 AdvanceAmount = PointerSize;
1996 RemainingLoopCount = 0;
1997 DEBUG_WITH_TYPE("mach-o-bind",
1998 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1999 << format("SegmentOffset=0x%06X",
2000 SegmentOffset) << "\n");
2002 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2003 AdvanceAmount = readULEB128() + PointerSize;
2004 RemainingLoopCount = 0;
2005 if (TableKind == Kind::Lazy)
2009 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2010 << format("SegmentOffset=0x%06X", SegmentOffset)
2011 << ", AdvanceAmount=" << AdvanceAmount
2012 << ", RemainingLoopCount=" << RemainingLoopCount
2015 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2016 AdvanceAmount = ImmValue * PointerSize + PointerSize;
2017 RemainingLoopCount = 0;
2018 if (TableKind == Kind::Lazy)
2020 DEBUG_WITH_TYPE("mach-o-bind",
2022 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2023 << format("SegmentOffset=0x%06X",
2024 SegmentOffset) << "\n");
2026 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2027 RemainingLoopCount = readULEB128() - 1;
2028 AdvanceAmount = readULEB128() + PointerSize;
2029 if (TableKind == Kind::Lazy)
2033 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2034 << format("SegmentOffset=0x%06X", SegmentOffset)
2035 << ", AdvanceAmount=" << AdvanceAmount
2036 << ", RemainingLoopCount=" << RemainingLoopCount
2045 uint64_t MachOBindEntry::readULEB128() {
2047 uint64_t Result = decodeULEB128(Ptr, &Count);
2049 if (Ptr > Opcodes.end()) {
2050 Ptr = Opcodes.end();
2056 int64_t MachOBindEntry::readSLEB128() {
2058 int64_t Result = decodeSLEB128(Ptr, &Count);
2060 if (Ptr > Opcodes.end()) {
2061 Ptr = Opcodes.end();
2068 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2070 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2072 StringRef MachOBindEntry::typeName() const {
2074 case MachO::BIND_TYPE_POINTER:
2076 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2077 return "text abs32";
2078 case MachO::BIND_TYPE_TEXT_PCREL32:
2079 return "text rel32";
2084 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2086 int64_t MachOBindEntry::addend() const { return Addend; }
2088 uint32_t MachOBindEntry::flags() const { return Flags; }
2090 int MachOBindEntry::ordinal() const { return Ordinal; }
2092 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2093 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2094 return (Ptr == Other.Ptr) &&
2095 (RemainingLoopCount == Other.RemainingLoopCount) &&
2096 (Done == Other.Done);
2099 iterator_range<bind_iterator>
2100 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2101 MachOBindEntry::Kind BKind) {
2102 MachOBindEntry Start(Opcodes, is64, BKind);
2103 Start.moveToFirst();
2105 MachOBindEntry Finish(Opcodes, is64, BKind);
2108 return iterator_range<bind_iterator>(bind_iterator(Start),
2109 bind_iterator(Finish));
2112 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2113 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2114 MachOBindEntry::Kind::Regular);
2117 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2118 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2119 MachOBindEntry::Kind::Lazy);
2122 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2123 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2124 MachOBindEntry::Kind::Weak);
2128 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2129 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2130 return parseSegmentOrSectionName(Raw.data());
2134 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2135 if (Sec.d.a >= Sections.size())
2136 report_fatal_error("getSectionRawName: Invalid section index");
2137 const section_base *Base =
2138 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2139 return makeArrayRef(Base->sectname);
2143 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2144 if (Sec.d.a >= Sections.size())
2145 report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
2146 const section_base *Base =
2147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2148 return makeArrayRef(Base->segname);
2152 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2154 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2156 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2159 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2160 const MachO::any_relocation_info &RE) const {
2161 if (isLittleEndian())
2162 return RE.r_word1 & 0xffffff;
2163 return RE.r_word1 >> 8;
2166 bool MachOObjectFile::getPlainRelocationExternal(
2167 const MachO::any_relocation_info &RE) const {
2168 if (isLittleEndian())
2169 return (RE.r_word1 >> 27) & 1;
2170 return (RE.r_word1 >> 4) & 1;
2173 bool MachOObjectFile::getScatteredRelocationScattered(
2174 const MachO::any_relocation_info &RE) const {
2175 return RE.r_word0 >> 31;
2178 uint32_t MachOObjectFile::getScatteredRelocationValue(
2179 const MachO::any_relocation_info &RE) const {
2183 uint32_t MachOObjectFile::getScatteredRelocationType(
2184 const MachO::any_relocation_info &RE) const {
2185 return (RE.r_word0 >> 24) & 0xf;
2188 unsigned MachOObjectFile::getAnyRelocationAddress(
2189 const MachO::any_relocation_info &RE) const {
2190 if (isRelocationScattered(RE))
2191 return getScatteredRelocationAddress(RE);
2192 return getPlainRelocationAddress(RE);
2195 unsigned MachOObjectFile::getAnyRelocationPCRel(
2196 const MachO::any_relocation_info &RE) const {
2197 if (isRelocationScattered(RE))
2198 return getScatteredRelocationPCRel(this, RE);
2199 return getPlainRelocationPCRel(this, RE);
2202 unsigned MachOObjectFile::getAnyRelocationLength(
2203 const MachO::any_relocation_info &RE) const {
2204 if (isRelocationScattered(RE))
2205 return getScatteredRelocationLength(RE);
2206 return getPlainRelocationLength(this, RE);
2210 MachOObjectFile::getAnyRelocationType(
2211 const MachO::any_relocation_info &RE) const {
2212 if (isRelocationScattered(RE))
2213 return getScatteredRelocationType(RE);
2214 return getPlainRelocationType(this, RE);
2218 MachOObjectFile::getRelocationSection(
2219 const MachO::any_relocation_info &RE) const {
2220 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2221 return *section_end();
2222 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2225 return SectionRef(DRI, this);
2228 MachOObjectFile::LoadCommandInfo
2229 MachOObjectFile::getFirstLoadCommandInfo() const {
2230 MachOObjectFile::LoadCommandInfo Load;
2232 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2233 sizeof(MachO::mach_header);
2234 Load.Ptr = getPtr(this, HeaderSize);
2235 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2236 if (Load.C.cmdsize < 8)
2237 report_fatal_error("Load command with size < 8 bytes.");
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);
2246 if (Next.C.cmdsize < 8)
2247 report_fatal_error("Load command with size < 8 bytes.");
2251 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2252 // TODO: What if Sections.size() == 0?
2253 if (DRI.d.a >= Sections.size())
2254 report_fatal_error("getSection: Invalid section index.");
2255 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2258 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2259 // TODO: What if Sections.size() == 0?
2260 if (DRI.d.a >= Sections.size())
2261 report_fatal_error("getSection64: Invalid section index.");
2262 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2265 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2266 unsigned Index) const {
2267 const char *Sec = getSectionPtr(this, L, Index);
2268 return getStruct<MachO::section>(this, Sec);
2271 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2272 unsigned Index) const {
2273 const char *Sec = getSectionPtr(this, L, Index);
2274 return getStruct<MachO::section_64>(this, Sec);
2278 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2279 const char *P = reinterpret_cast<const char *>(DRI.p);
2280 return getStruct<MachO::nlist>(this, P);
2284 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2285 const char *P = reinterpret_cast<const char *>(DRI.p);
2286 return getStruct<MachO::nlist_64>(this, P);
2289 MachO::linkedit_data_command
2290 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2291 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2294 MachO::segment_command
2295 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2296 return getStruct<MachO::segment_command>(this, L.Ptr);
2299 MachO::segment_command_64
2300 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2301 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2304 MachO::linker_option_command
2305 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2306 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2309 MachO::version_min_command
2310 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2311 return getStruct<MachO::version_min_command>(this, L.Ptr);
2314 MachO::dylib_command
2315 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2316 return getStruct<MachO::dylib_command>(this, L.Ptr);
2319 MachO::dyld_info_command
2320 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2321 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2324 MachO::dylinker_command
2325 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2326 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2330 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2331 return getStruct<MachO::uuid_command>(this, L.Ptr);
2334 MachO::rpath_command
2335 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2336 return getStruct<MachO::rpath_command>(this, L.Ptr);
2339 MachO::source_version_command
2340 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2341 return getStruct<MachO::source_version_command>(this, L.Ptr);
2344 MachO::entry_point_command
2345 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2346 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2349 MachO::encryption_info_command
2350 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2351 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2354 MachO::encryption_info_command_64
2355 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2356 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2359 MachO::sub_framework_command
2360 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2361 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2364 MachO::sub_umbrella_command
2365 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2366 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2369 MachO::sub_library_command
2370 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2371 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2374 MachO::sub_client_command
2375 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2376 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2379 MachO::routines_command
2380 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2381 return getStruct<MachO::routines_command>(this, L.Ptr);
2384 MachO::routines_command_64
2385 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2386 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2389 MachO::thread_command
2390 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2391 return getStruct<MachO::thread_command>(this, L.Ptr);
2394 MachO::any_relocation_info
2395 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2400 MachO::section_64 Sect = getSection64(Sec);
2401 Offset = Sect.reloff;
2403 MachO::section Sect = getSection(Sec);
2404 Offset = Sect.reloff;
2407 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2408 getPtr(this, Offset)) + Rel.d.b;
2409 return getStruct<MachO::any_relocation_info>(
2410 this, reinterpret_cast<const char *>(P));
2413 MachO::data_in_code_entry
2414 MachOObjectFile::getDice(DataRefImpl Rel) const {
2415 const char *P = reinterpret_cast<const char *>(Rel.p);
2416 return getStruct<MachO::data_in_code_entry>(this, P);
2419 MachO::mach_header MachOObjectFile::getHeader() const {
2420 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2423 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2424 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2427 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2428 const MachO::dysymtab_command &DLC,
2429 unsigned Index) const {
2430 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2431 return getStruct<uint32_t>(this, getPtr(this, Offset));
2434 MachO::data_in_code_entry
2435 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2436 unsigned Index) const {
2437 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2438 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2441 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2443 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2445 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2446 MachO::symtab_command Cmd;
2447 Cmd.cmd = MachO::LC_SYMTAB;
2448 Cmd.cmdsize = sizeof(MachO::symtab_command);
2456 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2457 if (DysymtabLoadCmd)
2458 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2460 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2461 MachO::dysymtab_command Cmd;
2462 Cmd.cmd = MachO::LC_DYSYMTAB;
2463 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2474 Cmd.extrefsymoff = 0;
2475 Cmd.nextrefsyms = 0;
2476 Cmd.indirectsymoff = 0;
2477 Cmd.nindirectsyms = 0;
2485 MachO::linkedit_data_command
2486 MachOObjectFile::getDataInCodeLoadCommand() const {
2487 if (DataInCodeLoadCmd)
2488 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2490 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2491 MachO::linkedit_data_command Cmd;
2492 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2493 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2499 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2500 if (!DyldInfoLoadCmd)
2501 return ArrayRef<uint8_t>();
2503 MachO::dyld_info_command DyldInfo
2504 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2505 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2506 getPtr(this, DyldInfo.rebase_off));
2507 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2510 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2511 if (!DyldInfoLoadCmd)
2512 return ArrayRef<uint8_t>();
2514 MachO::dyld_info_command DyldInfo
2515 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2516 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2517 getPtr(this, DyldInfo.bind_off));
2518 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2521 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2522 if (!DyldInfoLoadCmd)
2523 return ArrayRef<uint8_t>();
2525 MachO::dyld_info_command DyldInfo
2526 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2527 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2528 getPtr(this, DyldInfo.weak_bind_off));
2529 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2532 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2533 if (!DyldInfoLoadCmd)
2534 return ArrayRef<uint8_t>();
2536 MachO::dyld_info_command DyldInfo
2537 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2538 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2539 getPtr(this, DyldInfo.lazy_bind_off));
2540 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2543 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2544 if (!DyldInfoLoadCmd)
2545 return ArrayRef<uint8_t>();
2547 MachO::dyld_info_command DyldInfo
2548 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2549 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2550 getPtr(this, DyldInfo.export_off));
2551 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2554 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2556 return ArrayRef<uint8_t>();
2557 // Returning a pointer is fine as uuid doesn't need endian swapping.
2558 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2559 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2562 StringRef MachOObjectFile::getStringTableData() const {
2563 MachO::symtab_command S = getSymtabLoadCommand();
2564 return getData().substr(S.stroff, S.strsize);
2567 bool MachOObjectFile::is64Bit() const {
2568 return getType() == getMachOType(false, true) ||
2569 getType() == getMachOType(true, true);
2572 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2573 SmallVectorImpl<uint64_t> &Out) const {
2574 DataExtractor extractor(ObjectFile::getData(), true, 0);
2576 uint32_t offset = Index;
2578 while (uint64_t delta = extractor.getULEB128(&offset)) {
2580 Out.push_back(data);
2584 bool MachOObjectFile::isRelocatableObject() const {
2585 return getHeader().filetype == MachO::MH_OBJECT;
2588 ErrorOr<std::unique_ptr<MachOObjectFile>>
2589 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2590 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2592 std::unique_ptr<MachOObjectFile> Ret;
2593 if (Magic == "\xFE\xED\xFA\xCE")
2594 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2595 else if (Magic == "\xCE\xFA\xED\xFE")
2596 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2597 else if (Magic == "\xFE\xED\xFA\xCF")
2598 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2599 else if (Magic == "\xCF\xFA\xED\xFE")
2600 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2602 return object_error::parse_failed;
2606 return std::move(Ret);