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), LinkOptHintsLoadCmd(nullptr),
252 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
253 HasPageZeroSegment(false) {
254 uint32_t LoadCommandCount = this->getHeader().ncmds;
255 if (LoadCommandCount == 0)
258 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
259 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
261 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
262 for (unsigned I = 0; ; ++I) {
263 if (Load.C.cmd == MachO::LC_SYMTAB) {
264 // Multiple symbol tables
266 EC = object_error::parse_failed;
269 SymtabLoadCmd = Load.Ptr;
270 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
271 // Multiple dynamic symbol tables
272 if (DysymtabLoadCmd) {
273 EC = object_error::parse_failed;
276 DysymtabLoadCmd = Load.Ptr;
277 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
278 // Multiple data in code tables
279 if (DataInCodeLoadCmd) {
280 EC = object_error::parse_failed;
283 DataInCodeLoadCmd = Load.Ptr;
284 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
285 // Multiple linker optimization hint tables
286 if (LinkOptHintsLoadCmd) {
287 EC = object_error::parse_failed;
290 LinkOptHintsLoadCmd = Load.Ptr;
291 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
292 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
293 // Multiple dyldinfo load commands
294 if (DyldInfoLoadCmd) {
295 EC = object_error::parse_failed;
298 DyldInfoLoadCmd = Load.Ptr;
299 } else if (Load.C.cmd == MachO::LC_UUID) {
300 // Multiple UUID load commands
302 EC = object_error::parse_failed;
305 UuidLoadCmd = Load.Ptr;
306 } else if (Load.C.cmd == SegmentLoadType) {
307 const unsigned SegmentLoadSize = this->is64Bit()
308 ? sizeof(MachO::segment_command_64)
309 : sizeof(MachO::segment_command);
310 if (Load.C.cmdsize < SegmentLoadSize)
311 report_fatal_error("Segment load command size is too small.");
313 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
314 for (unsigned J = 0; J < NumSections; ++J) {
315 const char *Sec = getSectionPtr(this, Load, J);
316 Sections.push_back(Sec);
318 if (isPageZeroSegment(this, Load))
319 HasPageZeroSegment = true;
320 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
321 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
322 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
323 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
324 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
325 Libraries.push_back(Load.Ptr);
328 if (I == LoadCommandCount - 1)
331 Load = getNextLoadCommandInfo(Load);
335 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
336 unsigned SymbolTableEntrySize = is64Bit() ?
337 sizeof(MachO::nlist_64) :
338 sizeof(MachO::nlist);
339 Symb.p += SymbolTableEntrySize;
342 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
343 StringRef &Res) const {
344 StringRef StringTable = getStringTableData();
345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
346 const char *Start = &StringTable.data()[Entry.n_strx];
347 if (Start < getData().begin() || Start >= getData().end())
349 "Symbol name entry points before beginning or past end of file.");
350 Res = StringRef(Start);
351 return object_error::success;
354 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
355 DataRefImpl DRI = Sec.getRawDataRefImpl();
356 uint32_t Flags = getSectionFlags(this, DRI);
357 return Flags & MachO::SECTION_TYPE;
360 // getIndirectName() returns the name of the alias'ed symbol who's string table
361 // index is in the n_value field.
362 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
363 StringRef &Res) const {
364 StringRef StringTable = getStringTableData();
367 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
368 NValue = Entry.n_value;
369 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
370 return object_error::parse_failed;
372 MachO::nlist Entry = getSymbolTableEntry(Symb);
373 NValue = Entry.n_value;
374 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
375 return object_error::parse_failed;
377 if (NValue >= StringTable.size())
378 return object_error::parse_failed;
379 const char *Start = &StringTable.data()[NValue];
380 Res = StringRef(Start);
381 return object_error::success;
384 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
385 uint64_t &Res) const {
387 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
388 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
390 Res = UnknownAddressOrSize;
394 MachO::nlist Entry = getSymbolTableEntry(Symb);
395 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
397 Res = UnknownAddressOrSize;
401 return object_error::success;
404 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
405 uint32_t &Result) const {
406 uint32_t flags = getSymbolFlags(DRI);
407 if (flags & SymbolRef::SF_Common) {
408 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
409 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
413 return object_error::success;
416 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
417 uint64_t &Result) const {
418 uint64_t BeginOffset;
419 uint64_t EndOffset = 0;
420 uint8_t SectionIndex;
422 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
424 getSymbolAddress(DRI, Value);
425 if (Value == UnknownAddressOrSize) {
426 Result = UnknownAddressOrSize;
427 return object_error::success;
432 SectionIndex = Entry.n_sect;
434 uint32_t flags = getSymbolFlags(DRI);
435 if (flags & SymbolRef::SF_Common)
438 Result = UnknownAddressOrSize;
439 return object_error::success;
441 // Unfortunately symbols are unsorted so we need to touch all
442 // symbols from load command
443 for (const SymbolRef &Symbol : symbols()) {
444 DataRefImpl DRI = Symbol.getRawDataRefImpl();
445 Entry = getSymbolTableEntryBase(this, DRI);
446 getSymbolAddress(DRI, Value);
447 if (Value == UnknownAddressOrSize)
449 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
450 if (!EndOffset || Value < EndOffset)
455 Sec.d.a = SectionIndex-1;
456 uint64_t Size = getSectionSize(Sec);
457 EndOffset = getSectionAddress(Sec);
460 Result = EndOffset - BeginOffset;
461 return object_error::success;
464 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
465 SymbolRef::Type &Res) const {
466 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
467 uint8_t n_type = Entry.n_type;
469 Res = SymbolRef::ST_Other;
471 // If this is a STAB debugging symbol, we can do nothing more.
472 if (n_type & MachO::N_STAB) {
473 Res = SymbolRef::ST_Debug;
474 return object_error::success;
477 switch (n_type & MachO::N_TYPE) {
479 Res = SymbolRef::ST_Unknown;
482 Res = SymbolRef::ST_Function;
485 return object_error::success;
488 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
489 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
491 uint8_t MachOType = Entry.n_type;
492 uint16_t MachOFlags = Entry.n_desc;
494 uint32_t Result = SymbolRef::SF_None;
496 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
497 Result |= SymbolRef::SF_Undefined;
499 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
500 Result |= SymbolRef::SF_Indirect;
502 if (MachOType & MachO::N_STAB)
503 Result |= SymbolRef::SF_FormatSpecific;
505 if (MachOType & MachO::N_EXT) {
506 Result |= SymbolRef::SF_Global;
507 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
509 getSymbolAddress(DRI, Value);
510 if (Value && Value != UnknownAddressOrSize)
511 Result |= SymbolRef::SF_Common;
514 if (!(MachOType & MachO::N_PEXT))
515 Result |= SymbolRef::SF_Exported;
518 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
519 Result |= SymbolRef::SF_Weak;
521 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
522 Result |= SymbolRef::SF_Thumb;
524 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
525 Result |= SymbolRef::SF_Absolute;
530 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
531 section_iterator &Res) const {
532 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
533 uint8_t index = Entry.n_sect;
540 Res = section_iterator(SectionRef(DRI, this));
543 return object_error::success;
546 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
550 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
551 StringRef &Result) const {
552 ArrayRef<char> Raw = getSectionRawName(Sec);
553 Result = parseSegmentOrSectionName(Raw.data());
554 return object_error::success;
557 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
559 return getSection64(Sec).addr;
560 return getSection(Sec).addr;
563 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
565 return getSection64(Sec).size;
566 return getSection(Sec).size;
569 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
570 StringRef &Res) const {
575 MachO::section_64 Sect = getSection64(Sec);
576 Offset = Sect.offset;
579 MachO::section Sect = getSection(Sec);
580 Offset = Sect.offset;
584 Res = this->getData().substr(Offset, Size);
585 return object_error::success;
588 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
591 MachO::section_64 Sect = getSection64(Sec);
594 MachO::section Sect = getSection(Sec);
598 return uint64_t(1) << Align;
601 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
602 uint32_t Flags = getSectionFlags(this, Sec);
603 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
606 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
607 uint32_t Flags = getSectionFlags(this, Sec);
608 unsigned SectionType = Flags & MachO::SECTION_TYPE;
609 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
610 !(SectionType == MachO::S_ZEROFILL ||
611 SectionType == MachO::S_GB_ZEROFILL);
614 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
615 uint32_t Flags = getSectionFlags(this, Sec);
616 unsigned SectionType = Flags & MachO::SECTION_TYPE;
617 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
618 (SectionType == MachO::S_ZEROFILL ||
619 SectionType == MachO::S_GB_ZEROFILL);
622 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
623 // FIXME: Unimplemented.
627 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
628 DataRefImpl Symb) const {
630 this->getSymbolType(Symb, ST);
631 if (ST == SymbolRef::ST_Unknown)
634 uint64_t SectBegin = getSectionAddress(Sec);
635 uint64_t SectEnd = getSectionSize(Sec);
636 SectEnd += SectBegin;
639 getSymbolAddress(Symb, SymAddr);
640 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
643 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
647 return relocation_iterator(RelocationRef(Ret, this));
651 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
654 MachO::section_64 Sect = getSection64(Sec);
657 MachO::section Sect = getSection(Sec);
664 return relocation_iterator(RelocationRef(Ret, this));
667 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
671 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
672 uint64_t &Res) const {
674 getRelocationOffset(Rel, Offset);
678 uint64_t SecAddress = getSectionAddress(Sec);
679 Res = SecAddress + Offset;
680 return object_error::success;
683 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
684 uint64_t &Res) const {
685 assert(getHeader().filetype == MachO::MH_OBJECT &&
686 "Only implemented for MH_OBJECT");
687 MachO::any_relocation_info RE = getRelocation(Rel);
688 Res = getAnyRelocationAddress(RE);
689 return object_error::success;
693 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
694 MachO::any_relocation_info RE = getRelocation(Rel);
695 if (isRelocationScattered(RE))
698 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
699 bool isExtern = getPlainRelocationExternal(RE);
703 MachO::symtab_command S = getSymtabLoadCommand();
704 unsigned SymbolTableEntrySize = is64Bit() ?
705 sizeof(MachO::nlist_64) :
706 sizeof(MachO::nlist);
707 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
709 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
710 return symbol_iterator(SymbolRef(Sym, this));
714 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
715 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
718 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
719 uint64_t &Res) const {
720 MachO::any_relocation_info RE = getRelocation(Rel);
721 Res = getAnyRelocationType(RE);
722 return object_error::success;
726 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
727 SmallVectorImpl<char> &Result) const {
730 getRelocationType(Rel, RType);
732 unsigned Arch = this->getArch();
736 static const char *const Table[] = {
737 "GENERIC_RELOC_VANILLA",
738 "GENERIC_RELOC_PAIR",
739 "GENERIC_RELOC_SECTDIFF",
740 "GENERIC_RELOC_PB_LA_PTR",
741 "GENERIC_RELOC_LOCAL_SECTDIFF",
742 "GENERIC_RELOC_TLV" };
750 case Triple::x86_64: {
751 static const char *const Table[] = {
752 "X86_64_RELOC_UNSIGNED",
753 "X86_64_RELOC_SIGNED",
754 "X86_64_RELOC_BRANCH",
755 "X86_64_RELOC_GOT_LOAD",
757 "X86_64_RELOC_SUBTRACTOR",
758 "X86_64_RELOC_SIGNED_1",
759 "X86_64_RELOC_SIGNED_2",
760 "X86_64_RELOC_SIGNED_4",
761 "X86_64_RELOC_TLV" };
770 static const char *const Table[] = {
773 "ARM_RELOC_SECTDIFF",
774 "ARM_RELOC_LOCAL_SECTDIFF",
775 "ARM_RELOC_PB_LA_PTR",
777 "ARM_THUMB_RELOC_BR22",
778 "ARM_THUMB_32BIT_BRANCH",
780 "ARM_RELOC_HALF_SECTDIFF" };
788 case Triple::aarch64: {
789 static const char *const Table[] = {
790 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
791 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
792 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
793 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
794 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
798 if (RType >= array_lengthof(Table))
805 static const char *const Table[] = {
814 "PPC_RELOC_SECTDIFF",
815 "PPC_RELOC_PB_LA_PTR",
816 "PPC_RELOC_HI16_SECTDIFF",
817 "PPC_RELOC_LO16_SECTDIFF",
818 "PPC_RELOC_HA16_SECTDIFF",
820 "PPC_RELOC_LO14_SECTDIFF",
821 "PPC_RELOC_LOCAL_SECTDIFF" };
829 case Triple::UnknownArch:
833 Result.append(res.begin(), res.end());
834 return object_error::success;
838 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
839 SmallVectorImpl<char> &Result) const {
840 MachO::any_relocation_info RE = getRelocation(Rel);
842 unsigned Arch = this->getArch();
845 raw_string_ostream fmt(fmtbuf);
846 unsigned Type = this->getAnyRelocationType(RE);
847 bool IsPCRel = this->getAnyRelocationPCRel(RE);
849 // Determine any addends that should be displayed with the relocation.
850 // These require decoding the relocation type, which is triple-specific.
852 // X86_64 has entirely custom relocation types.
853 if (Arch == Triple::x86_64) {
854 bool isPCRel = getAnyRelocationPCRel(RE);
857 case MachO::X86_64_RELOC_GOT_LOAD:
858 case MachO::X86_64_RELOC_GOT: {
859 printRelocationTargetName(this, RE, fmt);
861 if (isPCRel) fmt << "PCREL";
864 case MachO::X86_64_RELOC_SUBTRACTOR: {
865 DataRefImpl RelNext = Rel;
866 moveRelocationNext(RelNext);
867 MachO::any_relocation_info RENext = getRelocation(RelNext);
869 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
870 // X86_64_RELOC_UNSIGNED.
871 // NOTE: Scattered relocations don't exist on x86_64.
872 unsigned RType = getAnyRelocationType(RENext);
873 if (RType != MachO::X86_64_RELOC_UNSIGNED)
874 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
875 "X86_64_RELOC_SUBTRACTOR.");
877 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
878 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
879 printRelocationTargetName(this, RENext, fmt);
881 printRelocationTargetName(this, RE, fmt);
884 case MachO::X86_64_RELOC_TLV:
885 printRelocationTargetName(this, RE, fmt);
887 if (isPCRel) fmt << "P";
889 case MachO::X86_64_RELOC_SIGNED_1:
890 printRelocationTargetName(this, RE, fmt);
893 case MachO::X86_64_RELOC_SIGNED_2:
894 printRelocationTargetName(this, RE, fmt);
897 case MachO::X86_64_RELOC_SIGNED_4:
898 printRelocationTargetName(this, RE, fmt);
902 printRelocationTargetName(this, RE, fmt);
905 // X86 and ARM share some relocation types in common.
906 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
907 Arch == Triple::ppc) {
908 // Generic relocation types...
910 case MachO::GENERIC_RELOC_PAIR: // prints no info
911 return object_error::success;
912 case MachO::GENERIC_RELOC_SECTDIFF: {
913 DataRefImpl RelNext = Rel;
914 moveRelocationNext(RelNext);
915 MachO::any_relocation_info RENext = getRelocation(RelNext);
917 // X86 sect diff's must be followed by a relocation of type
918 // GENERIC_RELOC_PAIR.
919 unsigned RType = getAnyRelocationType(RENext);
921 if (RType != MachO::GENERIC_RELOC_PAIR)
922 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
923 "GENERIC_RELOC_SECTDIFF.");
925 printRelocationTargetName(this, RE, fmt);
927 printRelocationTargetName(this, RENext, fmt);
932 if (Arch == Triple::x86 || Arch == Triple::ppc) {
934 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
935 DataRefImpl RelNext = Rel;
936 moveRelocationNext(RelNext);
937 MachO::any_relocation_info RENext = getRelocation(RelNext);
939 // X86 sect diff's must be followed by a relocation of type
940 // GENERIC_RELOC_PAIR.
941 unsigned RType = getAnyRelocationType(RENext);
942 if (RType != MachO::GENERIC_RELOC_PAIR)
943 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
944 "GENERIC_RELOC_LOCAL_SECTDIFF.");
946 printRelocationTargetName(this, RE, fmt);
948 printRelocationTargetName(this, RENext, fmt);
951 case MachO::GENERIC_RELOC_TLV: {
952 printRelocationTargetName(this, RE, fmt);
954 if (IsPCRel) fmt << "P";
958 printRelocationTargetName(this, RE, fmt);
960 } else { // ARM-specific relocations
962 case MachO::ARM_RELOC_HALF:
963 case MachO::ARM_RELOC_HALF_SECTDIFF: {
964 // Half relocations steal a bit from the length field to encode
965 // whether this is an upper16 or a lower16 relocation.
966 bool isUpper = getAnyRelocationLength(RE) >> 1;
972 printRelocationTargetName(this, RE, fmt);
974 DataRefImpl RelNext = Rel;
975 moveRelocationNext(RelNext);
976 MachO::any_relocation_info RENext = getRelocation(RelNext);
978 // ARM half relocs must be followed by a relocation of type
980 unsigned RType = getAnyRelocationType(RENext);
981 if (RType != MachO::ARM_RELOC_PAIR)
982 report_fatal_error("Expected ARM_RELOC_PAIR after "
985 // NOTE: The half of the target virtual address is stashed in the
986 // address field of the secondary relocation, but we can't reverse
987 // engineer the constant offset from it without decoding the movw/movt
988 // instruction to find the other half in its immediate field.
990 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
991 // symbol/section pointer of the follow-on relocation.
992 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
994 printRelocationTargetName(this, RENext, fmt);
1001 printRelocationTargetName(this, RE, fmt);
1006 printRelocationTargetName(this, RE, fmt);
1009 Result.append(fmtbuf.begin(), fmtbuf.end());
1010 return object_error::success;
1013 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1014 bool &Result) const {
1015 unsigned Arch = getArch();
1017 getRelocationType(Rel, Type);
1021 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1022 // is always hidden.
1023 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1024 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1025 } else if (Arch == Triple::x86_64) {
1026 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1027 // an X86_64_RELOC_SUBTRACTOR.
1028 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1029 DataRefImpl RelPrev = Rel;
1032 getRelocationType(RelPrev, PrevType);
1033 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1038 return object_error::success;
1042 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1043 // guess on what the short name is. Then name is returned as a substring of the
1044 // StringRef Name passed in. The name of the dynamic library is recognized as
1045 // a framework if it has one of the two following forms:
1046 // Foo.framework/Versions/A/Foo
1047 // Foo.framework/Foo
1048 // Where A and Foo can be any string. And may contain a trailing suffix
1049 // starting with an underbar. If the Name is recognized as a framework then
1050 // isFramework is set to true else it is set to false. If the Name has a
1051 // suffix then Suffix is set to the substring in Name that contains the suffix
1052 // else it is set to a NULL StringRef.
1054 // The Name of the dynamic library is recognized as a library name if it has
1055 // one of the two following forms:
1058 // The library may have a suffix trailing the name Foo of the form:
1059 // libFoo_profile.A.dylib
1060 // libFoo_profile.dylib
1062 // The Name of the dynamic library is also recognized as a library name if it
1063 // has the following form:
1066 // If the Name of the dynamic library is none of the forms above then a NULL
1067 // StringRef is returned.
1069 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1071 StringRef &Suffix) {
1072 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1073 size_t a, b, c, d, Idx;
1075 isFramework = false;
1076 Suffix = StringRef();
1078 // Pull off the last component and make Foo point to it
1079 a = Name.rfind('/');
1080 if (a == Name.npos || a == 0)
1082 Foo = Name.slice(a+1, Name.npos);
1084 // Look for a suffix starting with a '_'
1085 Idx = Foo.rfind('_');
1086 if (Idx != Foo.npos && Foo.size() >= 2) {
1087 Suffix = Foo.slice(Idx, Foo.npos);
1088 Foo = Foo.slice(0, Idx);
1091 // First look for the form Foo.framework/Foo
1092 b = Name.rfind('/', a);
1097 F = Name.slice(Idx, Idx + Foo.size());
1098 DotFramework = Name.slice(Idx + Foo.size(),
1099 Idx + Foo.size() + sizeof(".framework/")-1);
1100 if (F == Foo && DotFramework == ".framework/") {
1105 // Next look for the form Foo.framework/Versions/A/Foo
1108 c = Name.rfind('/', b);
1109 if (c == Name.npos || c == 0)
1111 V = Name.slice(c+1, Name.npos);
1112 if (!V.startswith("Versions/"))
1114 d = Name.rfind('/', c);
1119 F = Name.slice(Idx, Idx + Foo.size());
1120 DotFramework = Name.slice(Idx + Foo.size(),
1121 Idx + Foo.size() + sizeof(".framework/")-1);
1122 if (F == Foo && DotFramework == ".framework/") {
1128 // pull off the suffix after the "." and make a point to it
1129 a = Name.rfind('.');
1130 if (a == Name.npos || a == 0)
1132 Dylib = Name.slice(a, Name.npos);
1133 if (Dylib != ".dylib")
1136 // First pull off the version letter for the form Foo.A.dylib if any.
1138 Dot = Name.slice(a-2, a-1);
1143 b = Name.rfind('/', a);
1148 // ignore any suffix after an underbar like Foo_profile.A.dylib
1149 Idx = Name.find('_', b);
1150 if (Idx != Name.npos && Idx != b) {
1151 Lib = Name.slice(b, Idx);
1152 Suffix = Name.slice(Idx, a);
1155 Lib = Name.slice(b, a);
1156 // There are incorrect library names of the form:
1157 // libATS.A_profile.dylib so check for these.
1158 if (Lib.size() >= 3) {
1159 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1161 Lib = Lib.slice(0, Lib.size()-2);
1166 Qtx = Name.slice(a, Name.npos);
1169 b = Name.rfind('/', a);
1171 Lib = Name.slice(0, a);
1173 Lib = Name.slice(b+1, a);
1174 // There are library names of the form: QT.A.qtx so check for these.
1175 if (Lib.size() >= 3) {
1176 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1178 Lib = Lib.slice(0, Lib.size()-2);
1183 // getLibraryShortNameByIndex() is used to get the short name of the library
1184 // for an undefined symbol in a linked Mach-O binary that was linked with the
1185 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1186 // It is passed the index (0 - based) of the library as translated from
1187 // GET_LIBRARY_ORDINAL (1 - based).
1188 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1189 StringRef &Res) const {
1190 if (Index >= Libraries.size())
1191 return object_error::parse_failed;
1193 // If the cache of LibrariesShortNames is not built up do that first for
1194 // all the Libraries.
1195 if (LibrariesShortNames.size() == 0) {
1196 for (unsigned i = 0; i < Libraries.size(); i++) {
1197 MachO::dylib_command D =
1198 getStruct<MachO::dylib_command>(this, Libraries[i]);
1199 if (D.dylib.name >= D.cmdsize)
1200 return object_error::parse_failed;
1201 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1202 StringRef Name = StringRef(P);
1203 if (D.dylib.name+Name.size() >= D.cmdsize)
1204 return object_error::parse_failed;
1207 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1208 if (shortName.empty())
1209 LibrariesShortNames.push_back(Name);
1211 LibrariesShortNames.push_back(shortName);
1215 Res = LibrariesShortNames[Index];
1216 return object_error::success;
1219 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1220 return getSymbolByIndex(0);
1223 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1226 return basic_symbol_iterator(SymbolRef(DRI, this));
1228 MachO::symtab_command Symtab = getSymtabLoadCommand();
1229 unsigned SymbolTableEntrySize = is64Bit() ?
1230 sizeof(MachO::nlist_64) :
1231 sizeof(MachO::nlist);
1232 unsigned Offset = Symtab.symoff +
1233 Symtab.nsyms * SymbolTableEntrySize;
1234 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1235 return basic_symbol_iterator(SymbolRef(DRI, this));
1238 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1241 return basic_symbol_iterator(SymbolRef(DRI, this));
1243 MachO::symtab_command Symtab = getSymtabLoadCommand();
1244 if (Index >= Symtab.nsyms)
1245 report_fatal_error("Requested symbol index is out of range.");
1246 unsigned SymbolTableEntrySize =
1247 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1248 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1249 DRI.p += Index * SymbolTableEntrySize;
1250 return basic_symbol_iterator(SymbolRef(DRI, this));
1253 section_iterator MachOObjectFile::section_begin() const {
1255 return section_iterator(SectionRef(DRI, this));
1258 section_iterator MachOObjectFile::section_end() const {
1260 DRI.d.a = Sections.size();
1261 return section_iterator(SectionRef(DRI, this));
1264 uint8_t MachOObjectFile::getBytesInAddress() const {
1265 return is64Bit() ? 8 : 4;
1268 StringRef MachOObjectFile::getFileFormatName() const {
1269 unsigned CPUType = getCPUType(this);
1272 case llvm::MachO::CPU_TYPE_I386:
1273 return "Mach-O 32-bit i386";
1274 case llvm::MachO::CPU_TYPE_ARM:
1275 return "Mach-O arm";
1276 case llvm::MachO::CPU_TYPE_POWERPC:
1277 return "Mach-O 32-bit ppc";
1279 return "Mach-O 32-bit unknown";
1284 case llvm::MachO::CPU_TYPE_X86_64:
1285 return "Mach-O 64-bit x86-64";
1286 case llvm::MachO::CPU_TYPE_ARM64:
1287 return "Mach-O arm64";
1288 case llvm::MachO::CPU_TYPE_POWERPC64:
1289 return "Mach-O 64-bit ppc64";
1291 return "Mach-O 64-bit unknown";
1295 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1297 case llvm::MachO::CPU_TYPE_I386:
1299 case llvm::MachO::CPU_TYPE_X86_64:
1300 return Triple::x86_64;
1301 case llvm::MachO::CPU_TYPE_ARM:
1303 case llvm::MachO::CPU_TYPE_ARM64:
1304 return Triple::aarch64;
1305 case llvm::MachO::CPU_TYPE_POWERPC:
1307 case llvm::MachO::CPU_TYPE_POWERPC64:
1308 return Triple::ppc64;
1310 return Triple::UnknownArch;
1314 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1315 const char **McpuDefault) {
1317 *McpuDefault = nullptr;
1320 case MachO::CPU_TYPE_I386:
1321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1322 case MachO::CPU_SUBTYPE_I386_ALL:
1323 return Triple("i386-apple-darwin");
1327 case MachO::CPU_TYPE_X86_64:
1328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1329 case MachO::CPU_SUBTYPE_X86_64_ALL:
1330 return Triple("x86_64-apple-darwin");
1331 case MachO::CPU_SUBTYPE_X86_64_H:
1332 return Triple("x86_64h-apple-darwin");
1336 case MachO::CPU_TYPE_ARM:
1337 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1338 case MachO::CPU_SUBTYPE_ARM_V4T:
1339 return Triple("armv4t-apple-darwin");
1340 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1341 return Triple("armv5e-apple-darwin");
1342 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1343 return Triple("xscale-apple-darwin");
1344 case MachO::CPU_SUBTYPE_ARM_V6:
1345 return Triple("armv6-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V6M:
1348 *McpuDefault = "cortex-m0";
1349 return Triple("armv6m-apple-darwin");
1350 case MachO::CPU_SUBTYPE_ARM_V7:
1351 return Triple("armv7-apple-darwin");
1352 case MachO::CPU_SUBTYPE_ARM_V7EM:
1354 *McpuDefault = "cortex-m4";
1355 return Triple("armv7em-apple-darwin");
1356 case MachO::CPU_SUBTYPE_ARM_V7K:
1357 return Triple("armv7k-apple-darwin");
1358 case MachO::CPU_SUBTYPE_ARM_V7M:
1360 *McpuDefault = "cortex-m3";
1361 return Triple("armv7m-apple-darwin");
1362 case MachO::CPU_SUBTYPE_ARM_V7S:
1363 return Triple("armv7s-apple-darwin");
1367 case MachO::CPU_TYPE_ARM64:
1368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1369 case MachO::CPU_SUBTYPE_ARM64_ALL:
1370 return Triple("arm64-apple-darwin");
1374 case MachO::CPU_TYPE_POWERPC:
1375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1376 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1377 return Triple("ppc-apple-darwin");
1381 case MachO::CPU_TYPE_POWERPC64:
1382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1383 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1384 return Triple("ppc64-apple-darwin");
1393 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1394 const char **McpuDefault) {
1396 *McpuDefault = nullptr;
1399 case MachO::CPU_TYPE_ARM:
1400 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1401 case MachO::CPU_SUBTYPE_ARM_V4T:
1402 return Triple("thumbv4t-apple-darwin");
1403 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1404 return Triple("thumbv5e-apple-darwin");
1405 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1406 return Triple("xscale-apple-darwin");
1407 case MachO::CPU_SUBTYPE_ARM_V6:
1408 return Triple("thumbv6-apple-darwin");
1409 case MachO::CPU_SUBTYPE_ARM_V6M:
1411 *McpuDefault = "cortex-m0";
1412 return Triple("thumbv6m-apple-darwin");
1413 case MachO::CPU_SUBTYPE_ARM_V7:
1414 return Triple("thumbv7-apple-darwin");
1415 case MachO::CPU_SUBTYPE_ARM_V7EM:
1417 *McpuDefault = "cortex-m4";
1418 return Triple("thumbv7em-apple-darwin");
1419 case MachO::CPU_SUBTYPE_ARM_V7K:
1420 return Triple("thumbv7k-apple-darwin");
1421 case MachO::CPU_SUBTYPE_ARM_V7M:
1423 *McpuDefault = "cortex-m3";
1424 return Triple("thumbv7m-apple-darwin");
1425 case MachO::CPU_SUBTYPE_ARM_V7S:
1426 return Triple("thumbv7s-apple-darwin");
1435 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1436 const char **McpuDefault,
1437 Triple *ThumbTriple) {
1438 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1439 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1444 Triple MachOObjectFile::getHostArch() {
1445 return Triple(sys::getDefaultTargetTriple());
1448 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1449 return StringSwitch<bool>(ArchFlag)
1451 .Case("x86_64", true)
1452 .Case("x86_64h", true)
1453 .Case("armv4t", true)
1455 .Case("armv5e", true)
1456 .Case("armv6", true)
1457 .Case("armv6m", true)
1458 .Case("armv7em", true)
1459 .Case("armv7k", true)
1460 .Case("armv7m", true)
1461 .Case("armv7s", true)
1462 .Case("arm64", true)
1464 .Case("ppc64", true)
1468 unsigned MachOObjectFile::getArch() const {
1469 return getArch(getCPUType(this));
1472 Triple MachOObjectFile::getArch(const char **McpuDefault,
1473 Triple *ThumbTriple) const {
1476 MachO::mach_header_64 H_64;
1477 H_64 = getHeader64();
1478 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1479 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1482 MachO::mach_header H;
1484 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1485 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1491 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1494 return section_rel_begin(DRI);
1497 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1500 return section_rel_end(DRI);
1503 dice_iterator MachOObjectFile::begin_dices() const {
1505 if (!DataInCodeLoadCmd)
1506 return dice_iterator(DiceRef(DRI, this));
1508 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1509 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1510 return dice_iterator(DiceRef(DRI, this));
1513 dice_iterator MachOObjectFile::end_dices() const {
1515 if (!DataInCodeLoadCmd)
1516 return dice_iterator(DiceRef(DRI, this));
1518 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1519 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1520 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1521 return dice_iterator(DiceRef(DRI, this));
1524 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1525 : Trie(T), Malformed(false), Done(false) { }
1527 void ExportEntry::moveToFirst() {
1529 pushDownUntilBottom();
1532 void ExportEntry::moveToEnd() {
1537 bool ExportEntry::operator==(const ExportEntry &Other) const {
1538 // Common case, one at end, other iterating from begin.
1539 if (Done || Other.Done)
1540 return (Done == Other.Done);
1541 // Not equal if different stack sizes.
1542 if (Stack.size() != Other.Stack.size())
1544 // Not equal if different cumulative strings.
1545 if (!CumulativeString.equals(Other.CumulativeString))
1547 // Equal if all nodes in both stacks match.
1548 for (unsigned i=0; i < Stack.size(); ++i) {
1549 if (Stack[i].Start != Other.Stack[i].Start)
1555 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1557 uint64_t Result = decodeULEB128(Ptr, &Count);
1559 if (Ptr > Trie.end()) {
1566 StringRef ExportEntry::name() const {
1567 return CumulativeString;
1570 uint64_t ExportEntry::flags() const {
1571 return Stack.back().Flags;
1574 uint64_t ExportEntry::address() const {
1575 return Stack.back().Address;
1578 uint64_t ExportEntry::other() const {
1579 return Stack.back().Other;
1582 StringRef ExportEntry::otherName() const {
1583 const char* ImportName = Stack.back().ImportName;
1585 return StringRef(ImportName);
1589 uint32_t ExportEntry::nodeOffset() const {
1590 return Stack.back().Start - Trie.begin();
1593 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1594 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1595 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1596 ParentStringLength(0), IsExportNode(false) {
1599 void ExportEntry::pushNode(uint64_t offset) {
1600 const uint8_t *Ptr = Trie.begin() + offset;
1601 NodeState State(Ptr);
1602 uint64_t ExportInfoSize = readULEB128(State.Current);
1603 State.IsExportNode = (ExportInfoSize != 0);
1604 const uint8_t* Children = State.Current + ExportInfoSize;
1605 if (State.IsExportNode) {
1606 State.Flags = readULEB128(State.Current);
1607 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1609 State.Other = readULEB128(State.Current); // dylib ordinal
1610 State.ImportName = reinterpret_cast<const char*>(State.Current);
1612 State.Address = readULEB128(State.Current);
1613 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1614 State.Other = readULEB128(State.Current);
1617 State.ChildCount = *Children;
1618 State.Current = Children + 1;
1619 State.NextChildIndex = 0;
1620 State.ParentStringLength = CumulativeString.size();
1621 Stack.push_back(State);
1624 void ExportEntry::pushDownUntilBottom() {
1625 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1626 NodeState &Top = Stack.back();
1627 CumulativeString.resize(Top.ParentStringLength);
1628 for (;*Top.Current != 0; Top.Current++) {
1629 char C = *Top.Current;
1630 CumulativeString.push_back(C);
1633 uint64_t childNodeIndex = readULEB128(Top.Current);
1634 Top.NextChildIndex += 1;
1635 pushNode(childNodeIndex);
1637 if (!Stack.back().IsExportNode) {
1643 // We have a trie data structure and need a way to walk it that is compatible
1644 // with the C++ iterator model. The solution is a non-recursive depth first
1645 // traversal where the iterator contains a stack of parent nodes along with a
1646 // string that is the accumulation of all edge strings along the parent chain
1649 // There is one "export" node for each exported symbol. But because some
1650 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1651 // node may have child nodes too.
1653 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1654 // child until hitting a node with no children (which is an export node or
1655 // else the trie is malformed). On the way down, each node is pushed on the
1656 // stack ivar. If there is no more ways down, it pops up one and tries to go
1657 // down a sibling path until a childless node is reached.
1658 void ExportEntry::moveNext() {
1659 if (Stack.empty() || !Stack.back().IsExportNode) {
1666 while (!Stack.empty()) {
1667 NodeState &Top = Stack.back();
1668 if (Top.NextChildIndex < Top.ChildCount) {
1669 pushDownUntilBottom();
1670 // Now at the next export node.
1673 if (Top.IsExportNode) {
1674 // This node has no children but is itself an export node.
1675 CumulativeString.resize(Top.ParentStringLength);
1684 iterator_range<export_iterator>
1685 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1686 ExportEntry Start(Trie);
1687 if (Trie.size() == 0)
1690 Start.moveToFirst();
1692 ExportEntry Finish(Trie);
1695 return iterator_range<export_iterator>(export_iterator(Start),
1696 export_iterator(Finish));
1699 iterator_range<export_iterator> MachOObjectFile::exports() const {
1700 return exports(getDyldInfoExportsTrie());
1704 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1705 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1706 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1707 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1709 void MachORebaseEntry::moveToFirst() {
1710 Ptr = Opcodes.begin();
1714 void MachORebaseEntry::moveToEnd() {
1715 Ptr = Opcodes.end();
1716 RemainingLoopCount = 0;
1720 void MachORebaseEntry::moveNext() {
1721 // If in the middle of some loop, move to next rebasing in loop.
1722 SegmentOffset += AdvanceAmount;
1723 if (RemainingLoopCount) {
1724 --RemainingLoopCount;
1727 if (Ptr == Opcodes.end()) {
1732 while (More && !Malformed) {
1733 // Parse next opcode and set up next loop.
1734 uint8_t Byte = *Ptr++;
1735 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1736 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1738 case MachO::REBASE_OPCODE_DONE:
1742 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1744 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1745 RebaseType = ImmValue;
1748 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1749 << "RebaseType=" << (int) RebaseType << "\n");
1751 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1752 SegmentIndex = ImmValue;
1753 SegmentOffset = readULEB128();
1756 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1757 << "SegmentIndex=" << SegmentIndex << ", "
1758 << format("SegmentOffset=0x%06X", SegmentOffset)
1761 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1762 SegmentOffset += readULEB128();
1763 DEBUG_WITH_TYPE("mach-o-rebase",
1764 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1765 << format("SegmentOffset=0x%06X",
1766 SegmentOffset) << "\n");
1768 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1769 SegmentOffset += ImmValue * PointerSize;
1770 DEBUG_WITH_TYPE("mach-o-rebase",
1771 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1772 << format("SegmentOffset=0x%06X",
1773 SegmentOffset) << "\n");
1775 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1776 AdvanceAmount = PointerSize;
1777 RemainingLoopCount = ImmValue - 1;
1780 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1781 << format("SegmentOffset=0x%06X", SegmentOffset)
1782 << ", AdvanceAmount=" << AdvanceAmount
1783 << ", RemainingLoopCount=" << RemainingLoopCount
1786 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1787 AdvanceAmount = PointerSize;
1788 RemainingLoopCount = readULEB128() - 1;
1791 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1792 << format("SegmentOffset=0x%06X", SegmentOffset)
1793 << ", AdvanceAmount=" << AdvanceAmount
1794 << ", RemainingLoopCount=" << RemainingLoopCount
1797 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1798 AdvanceAmount = readULEB128() + PointerSize;
1799 RemainingLoopCount = 0;
1802 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1803 << format("SegmentOffset=0x%06X", SegmentOffset)
1804 << ", AdvanceAmount=" << AdvanceAmount
1805 << ", RemainingLoopCount=" << RemainingLoopCount
1808 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1809 RemainingLoopCount = readULEB128() - 1;
1810 AdvanceAmount = readULEB128() + PointerSize;
1813 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1814 << format("SegmentOffset=0x%06X", SegmentOffset)
1815 << ", AdvanceAmount=" << AdvanceAmount
1816 << ", RemainingLoopCount=" << RemainingLoopCount
1825 uint64_t MachORebaseEntry::readULEB128() {
1827 uint64_t Result = decodeULEB128(Ptr, &Count);
1829 if (Ptr > Opcodes.end()) {
1830 Ptr = Opcodes.end();
1836 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1838 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1840 StringRef MachORebaseEntry::typeName() const {
1841 switch (RebaseType) {
1842 case MachO::REBASE_TYPE_POINTER:
1844 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1845 return "text abs32";
1846 case MachO::REBASE_TYPE_TEXT_PCREL32:
1847 return "text rel32";
1852 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1853 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1854 return (Ptr == Other.Ptr) &&
1855 (RemainingLoopCount == Other.RemainingLoopCount) &&
1856 (Done == Other.Done);
1859 iterator_range<rebase_iterator>
1860 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1861 MachORebaseEntry Start(Opcodes, is64);
1862 Start.moveToFirst();
1864 MachORebaseEntry Finish(Opcodes, is64);
1867 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1868 rebase_iterator(Finish));
1871 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1872 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1876 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1878 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1879 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1880 BindType(0), PointerSize(is64Bit ? 8 : 4),
1881 TableKind(BK), Malformed(false), Done(false) {}
1883 void MachOBindEntry::moveToFirst() {
1884 Ptr = Opcodes.begin();
1888 void MachOBindEntry::moveToEnd() {
1889 Ptr = Opcodes.end();
1890 RemainingLoopCount = 0;
1894 void MachOBindEntry::moveNext() {
1895 // If in the middle of some loop, move to next binding in loop.
1896 SegmentOffset += AdvanceAmount;
1897 if (RemainingLoopCount) {
1898 --RemainingLoopCount;
1901 if (Ptr == Opcodes.end()) {
1906 while (More && !Malformed) {
1907 // Parse next opcode and set up next loop.
1908 uint8_t Byte = *Ptr++;
1909 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1910 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1911 int8_t SignExtended;
1912 const uint8_t *SymStart;
1914 case MachO::BIND_OPCODE_DONE:
1915 if (TableKind == Kind::Lazy) {
1916 // Lazying bindings have a DONE opcode between entries. Need to ignore
1917 // it to advance to next entry. But need not if this is last entry.
1918 bool NotLastEntry = false;
1919 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1921 NotLastEntry = true;
1930 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1932 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1936 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1937 << "Ordinal=" << Ordinal << "\n");
1939 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1940 Ordinal = readULEB128();
1943 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1944 << "Ordinal=" << Ordinal << "\n");
1946 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1948 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1949 Ordinal = SignExtended;
1954 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1955 << "Ordinal=" << Ordinal << "\n");
1957 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1963 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1968 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1969 << "SymbolName=" << SymbolName << "\n");
1970 if (TableKind == Kind::Weak) {
1971 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1975 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1976 BindType = ImmValue;
1979 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1980 << "BindType=" << (int)BindType << "\n");
1982 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1983 Addend = readSLEB128();
1984 if (TableKind == Kind::Lazy)
1988 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1989 << "Addend=" << Addend << "\n");
1991 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1992 SegmentIndex = ImmValue;
1993 SegmentOffset = readULEB128();
1996 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1997 << "SegmentIndex=" << SegmentIndex << ", "
1998 << format("SegmentOffset=0x%06X", SegmentOffset)
2001 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
2002 SegmentOffset += readULEB128();
2003 DEBUG_WITH_TYPE("mach-o-bind",
2004 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2005 << format("SegmentOffset=0x%06X",
2006 SegmentOffset) << "\n");
2008 case MachO::BIND_OPCODE_DO_BIND:
2009 AdvanceAmount = PointerSize;
2010 RemainingLoopCount = 0;
2011 DEBUG_WITH_TYPE("mach-o-bind",
2012 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2013 << format("SegmentOffset=0x%06X",
2014 SegmentOffset) << "\n");
2016 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2017 AdvanceAmount = readULEB128() + PointerSize;
2018 RemainingLoopCount = 0;
2019 if (TableKind == Kind::Lazy)
2023 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2024 << format("SegmentOffset=0x%06X", SegmentOffset)
2025 << ", AdvanceAmount=" << AdvanceAmount
2026 << ", RemainingLoopCount=" << RemainingLoopCount
2029 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2030 AdvanceAmount = ImmValue * PointerSize + PointerSize;
2031 RemainingLoopCount = 0;
2032 if (TableKind == Kind::Lazy)
2034 DEBUG_WITH_TYPE("mach-o-bind",
2036 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2037 << format("SegmentOffset=0x%06X",
2038 SegmentOffset) << "\n");
2040 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2041 RemainingLoopCount = readULEB128() - 1;
2042 AdvanceAmount = readULEB128() + PointerSize;
2043 if (TableKind == Kind::Lazy)
2047 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2048 << format("SegmentOffset=0x%06X", SegmentOffset)
2049 << ", AdvanceAmount=" << AdvanceAmount
2050 << ", RemainingLoopCount=" << RemainingLoopCount
2059 uint64_t MachOBindEntry::readULEB128() {
2061 uint64_t Result = decodeULEB128(Ptr, &Count);
2063 if (Ptr > Opcodes.end()) {
2064 Ptr = Opcodes.end();
2070 int64_t MachOBindEntry::readSLEB128() {
2072 int64_t Result = decodeSLEB128(Ptr, &Count);
2074 if (Ptr > Opcodes.end()) {
2075 Ptr = Opcodes.end();
2082 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2084 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2086 StringRef MachOBindEntry::typeName() const {
2088 case MachO::BIND_TYPE_POINTER:
2090 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2091 return "text abs32";
2092 case MachO::BIND_TYPE_TEXT_PCREL32:
2093 return "text rel32";
2098 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2100 int64_t MachOBindEntry::addend() const { return Addend; }
2102 uint32_t MachOBindEntry::flags() const { return Flags; }
2104 int MachOBindEntry::ordinal() const { return Ordinal; }
2106 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2107 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2108 return (Ptr == Other.Ptr) &&
2109 (RemainingLoopCount == Other.RemainingLoopCount) &&
2110 (Done == Other.Done);
2113 iterator_range<bind_iterator>
2114 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2115 MachOBindEntry::Kind BKind) {
2116 MachOBindEntry Start(Opcodes, is64, BKind);
2117 Start.moveToFirst();
2119 MachOBindEntry Finish(Opcodes, is64, BKind);
2122 return iterator_range<bind_iterator>(bind_iterator(Start),
2123 bind_iterator(Finish));
2126 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2127 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2128 MachOBindEntry::Kind::Regular);
2131 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2132 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2133 MachOBindEntry::Kind::Lazy);
2136 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2137 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2138 MachOBindEntry::Kind::Weak);
2142 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2143 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2144 return parseSegmentOrSectionName(Raw.data());
2148 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2149 if (Sec.d.a >= Sections.size())
2150 report_fatal_error("getSectionRawName: Invalid section index");
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 if (Sec.d.a >= Sections.size())
2159 report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
2160 const section_base *Base =
2161 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2162 return makeArrayRef(Base->segname);
2166 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2168 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2170 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2173 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2174 const MachO::any_relocation_info &RE) const {
2175 if (isLittleEndian())
2176 return RE.r_word1 & 0xffffff;
2177 return RE.r_word1 >> 8;
2180 bool MachOObjectFile::getPlainRelocationExternal(
2181 const MachO::any_relocation_info &RE) const {
2182 if (isLittleEndian())
2183 return (RE.r_word1 >> 27) & 1;
2184 return (RE.r_word1 >> 4) & 1;
2187 bool MachOObjectFile::getScatteredRelocationScattered(
2188 const MachO::any_relocation_info &RE) const {
2189 return RE.r_word0 >> 31;
2192 uint32_t MachOObjectFile::getScatteredRelocationValue(
2193 const MachO::any_relocation_info &RE) const {
2197 uint32_t MachOObjectFile::getScatteredRelocationType(
2198 const MachO::any_relocation_info &RE) const {
2199 return (RE.r_word0 >> 24) & 0xf;
2202 unsigned MachOObjectFile::getAnyRelocationAddress(
2203 const MachO::any_relocation_info &RE) const {
2204 if (isRelocationScattered(RE))
2205 return getScatteredRelocationAddress(RE);
2206 return getPlainRelocationAddress(RE);
2209 unsigned MachOObjectFile::getAnyRelocationPCRel(
2210 const MachO::any_relocation_info &RE) const {
2211 if (isRelocationScattered(RE))
2212 return getScatteredRelocationPCRel(this, RE);
2213 return getPlainRelocationPCRel(this, RE);
2216 unsigned MachOObjectFile::getAnyRelocationLength(
2217 const MachO::any_relocation_info &RE) const {
2218 if (isRelocationScattered(RE))
2219 return getScatteredRelocationLength(RE);
2220 return getPlainRelocationLength(this, RE);
2224 MachOObjectFile::getAnyRelocationType(
2225 const MachO::any_relocation_info &RE) const {
2226 if (isRelocationScattered(RE))
2227 return getScatteredRelocationType(RE);
2228 return getPlainRelocationType(this, RE);
2232 MachOObjectFile::getAnyRelocationSection(
2233 const MachO::any_relocation_info &RE) const {
2234 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2235 return *section_end();
2236 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2239 return SectionRef(DRI, this);
2242 MachOObjectFile::LoadCommandInfo
2243 MachOObjectFile::getFirstLoadCommandInfo() const {
2244 MachOObjectFile::LoadCommandInfo Load;
2246 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2247 sizeof(MachO::mach_header);
2248 Load.Ptr = getPtr(this, HeaderSize);
2249 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2250 if (Load.C.cmdsize < 8)
2251 report_fatal_error("Load command with size < 8 bytes.");
2255 MachOObjectFile::LoadCommandInfo
2256 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2257 MachOObjectFile::LoadCommandInfo Next;
2258 Next.Ptr = L.Ptr + L.C.cmdsize;
2259 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2260 if (Next.C.cmdsize < 8)
2261 report_fatal_error("Load command with size < 8 bytes.");
2265 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2266 // TODO: What if Sections.size() == 0?
2267 if (DRI.d.a >= Sections.size())
2268 report_fatal_error("getSection: Invalid section index.");
2269 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2272 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2273 // TODO: What if Sections.size() == 0?
2274 if (DRI.d.a >= Sections.size())
2275 report_fatal_error("getSection64: Invalid section index.");
2276 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2279 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2280 unsigned Index) const {
2281 const char *Sec = getSectionPtr(this, L, Index);
2282 return getStruct<MachO::section>(this, Sec);
2285 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2286 unsigned Index) const {
2287 const char *Sec = getSectionPtr(this, L, Index);
2288 return getStruct<MachO::section_64>(this, Sec);
2292 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2293 const char *P = reinterpret_cast<const char *>(DRI.p);
2294 return getStruct<MachO::nlist>(this, P);
2298 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2299 const char *P = reinterpret_cast<const char *>(DRI.p);
2300 return getStruct<MachO::nlist_64>(this, P);
2303 MachO::linkedit_data_command
2304 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2308 MachO::segment_command
2309 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::segment_command>(this, L.Ptr);
2313 MachO::segment_command_64
2314 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2318 MachO::linker_option_command
2319 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2323 MachO::version_min_command
2324 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::version_min_command>(this, L.Ptr);
2328 MachO::dylib_command
2329 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::dylib_command>(this, L.Ptr);
2333 MachO::dyld_info_command
2334 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2338 MachO::dylinker_command
2339 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2344 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::uuid_command>(this, L.Ptr);
2348 MachO::rpath_command
2349 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::rpath_command>(this, L.Ptr);
2353 MachO::source_version_command
2354 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2355 return getStruct<MachO::source_version_command>(this, L.Ptr);
2358 MachO::entry_point_command
2359 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2360 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2363 MachO::encryption_info_command
2364 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2365 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2368 MachO::encryption_info_command_64
2369 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2370 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2373 MachO::sub_framework_command
2374 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2375 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2378 MachO::sub_umbrella_command
2379 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2380 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2383 MachO::sub_library_command
2384 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2385 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2388 MachO::sub_client_command
2389 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2390 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2393 MachO::routines_command
2394 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2395 return getStruct<MachO::routines_command>(this, L.Ptr);
2398 MachO::routines_command_64
2399 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2400 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2403 MachO::thread_command
2404 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2405 return getStruct<MachO::thread_command>(this, L.Ptr);
2408 MachO::any_relocation_info
2409 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2414 MachO::section_64 Sect = getSection64(Sec);
2415 Offset = Sect.reloff;
2417 MachO::section Sect = getSection(Sec);
2418 Offset = Sect.reloff;
2421 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2422 getPtr(this, Offset)) + Rel.d.b;
2423 return getStruct<MachO::any_relocation_info>(
2424 this, reinterpret_cast<const char *>(P));
2427 MachO::data_in_code_entry
2428 MachOObjectFile::getDice(DataRefImpl Rel) const {
2429 const char *P = reinterpret_cast<const char *>(Rel.p);
2430 return getStruct<MachO::data_in_code_entry>(this, P);
2433 MachO::mach_header MachOObjectFile::getHeader() const {
2434 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2437 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2438 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2441 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2442 const MachO::dysymtab_command &DLC,
2443 unsigned Index) const {
2444 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2445 return getStruct<uint32_t>(this, getPtr(this, Offset));
2448 MachO::data_in_code_entry
2449 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2450 unsigned Index) const {
2451 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2452 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2455 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2457 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2459 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2460 MachO::symtab_command Cmd;
2461 Cmd.cmd = MachO::LC_SYMTAB;
2462 Cmd.cmdsize = sizeof(MachO::symtab_command);
2470 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2471 if (DysymtabLoadCmd)
2472 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2474 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2475 MachO::dysymtab_command Cmd;
2476 Cmd.cmd = MachO::LC_DYSYMTAB;
2477 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2488 Cmd.extrefsymoff = 0;
2489 Cmd.nextrefsyms = 0;
2490 Cmd.indirectsymoff = 0;
2491 Cmd.nindirectsyms = 0;
2499 MachO::linkedit_data_command
2500 MachOObjectFile::getDataInCodeLoadCommand() const {
2501 if (DataInCodeLoadCmd)
2502 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2504 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2505 MachO::linkedit_data_command Cmd;
2506 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2507 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2513 MachO::linkedit_data_command
2514 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2515 if (LinkOptHintsLoadCmd)
2516 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2518 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2520 MachO::linkedit_data_command Cmd;
2521 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2522 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2528 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2529 if (!DyldInfoLoadCmd)
2530 return ArrayRef<uint8_t>();
2532 MachO::dyld_info_command DyldInfo
2533 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2534 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2535 getPtr(this, DyldInfo.rebase_off));
2536 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2539 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2540 if (!DyldInfoLoadCmd)
2541 return ArrayRef<uint8_t>();
2543 MachO::dyld_info_command DyldInfo
2544 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2545 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2546 getPtr(this, DyldInfo.bind_off));
2547 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2550 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2551 if (!DyldInfoLoadCmd)
2552 return ArrayRef<uint8_t>();
2554 MachO::dyld_info_command DyldInfo
2555 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2556 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2557 getPtr(this, DyldInfo.weak_bind_off));
2558 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2561 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2562 if (!DyldInfoLoadCmd)
2563 return ArrayRef<uint8_t>();
2565 MachO::dyld_info_command DyldInfo
2566 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2567 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2568 getPtr(this, DyldInfo.lazy_bind_off));
2569 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2572 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2573 if (!DyldInfoLoadCmd)
2574 return ArrayRef<uint8_t>();
2576 MachO::dyld_info_command DyldInfo
2577 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2578 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2579 getPtr(this, DyldInfo.export_off));
2580 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2583 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2585 return ArrayRef<uint8_t>();
2586 // Returning a pointer is fine as uuid doesn't need endian swapping.
2587 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2588 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2591 StringRef MachOObjectFile::getStringTableData() const {
2592 MachO::symtab_command S = getSymtabLoadCommand();
2593 return getData().substr(S.stroff, S.strsize);
2596 bool MachOObjectFile::is64Bit() const {
2597 return getType() == getMachOType(false, true) ||
2598 getType() == getMachOType(true, true);
2601 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2602 SmallVectorImpl<uint64_t> &Out) const {
2603 DataExtractor extractor(ObjectFile::getData(), true, 0);
2605 uint32_t offset = Index;
2607 while (uint64_t delta = extractor.getULEB128(&offset)) {
2609 Out.push_back(data);
2613 bool MachOObjectFile::isRelocatableObject() const {
2614 return getHeader().filetype == MachO::MH_OBJECT;
2617 ErrorOr<std::unique_ptr<MachOObjectFile>>
2618 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2619 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2621 std::unique_ptr<MachOObjectFile> Ret;
2622 if (Magic == "\xFE\xED\xFA\xCE")
2623 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2624 else if (Magic == "\xCE\xFA\xED\xFE")
2625 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2626 else if (Magic == "\xFE\xED\xFA\xCF")
2627 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2628 else if (Magic == "\xCF\xFA\xED\xFE")
2629 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2631 return object_error::parse_failed;
2635 return std::move(Ret);