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));
713 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
714 uint64_t &Res) const {
715 MachO::any_relocation_info RE = getRelocation(Rel);
716 Res = getAnyRelocationType(RE);
717 return object_error::success;
721 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
722 SmallVectorImpl<char> &Result) const {
725 getRelocationType(Rel, RType);
727 unsigned Arch = this->getArch();
731 static const char *const Table[] = {
732 "GENERIC_RELOC_VANILLA",
733 "GENERIC_RELOC_PAIR",
734 "GENERIC_RELOC_SECTDIFF",
735 "GENERIC_RELOC_PB_LA_PTR",
736 "GENERIC_RELOC_LOCAL_SECTDIFF",
737 "GENERIC_RELOC_TLV" };
745 case Triple::x86_64: {
746 static const char *const Table[] = {
747 "X86_64_RELOC_UNSIGNED",
748 "X86_64_RELOC_SIGNED",
749 "X86_64_RELOC_BRANCH",
750 "X86_64_RELOC_GOT_LOAD",
752 "X86_64_RELOC_SUBTRACTOR",
753 "X86_64_RELOC_SIGNED_1",
754 "X86_64_RELOC_SIGNED_2",
755 "X86_64_RELOC_SIGNED_4",
756 "X86_64_RELOC_TLV" };
765 static const char *const Table[] = {
768 "ARM_RELOC_SECTDIFF",
769 "ARM_RELOC_LOCAL_SECTDIFF",
770 "ARM_RELOC_PB_LA_PTR",
772 "ARM_THUMB_RELOC_BR22",
773 "ARM_THUMB_32BIT_BRANCH",
775 "ARM_RELOC_HALF_SECTDIFF" };
783 case Triple::aarch64: {
784 static const char *const Table[] = {
785 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
786 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
787 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
788 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
789 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
793 if (RType >= array_lengthof(Table))
800 static const char *const Table[] = {
809 "PPC_RELOC_SECTDIFF",
810 "PPC_RELOC_PB_LA_PTR",
811 "PPC_RELOC_HI16_SECTDIFF",
812 "PPC_RELOC_LO16_SECTDIFF",
813 "PPC_RELOC_HA16_SECTDIFF",
815 "PPC_RELOC_LO14_SECTDIFF",
816 "PPC_RELOC_LOCAL_SECTDIFF" };
824 case Triple::UnknownArch:
828 Result.append(res.begin(), res.end());
829 return object_error::success;
833 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
834 SmallVectorImpl<char> &Result) const {
835 MachO::any_relocation_info RE = getRelocation(Rel);
837 unsigned Arch = this->getArch();
840 raw_string_ostream fmt(fmtbuf);
841 unsigned Type = this->getAnyRelocationType(RE);
842 bool IsPCRel = this->getAnyRelocationPCRel(RE);
844 // Determine any addends that should be displayed with the relocation.
845 // These require decoding the relocation type, which is triple-specific.
847 // X86_64 has entirely custom relocation types.
848 if (Arch == Triple::x86_64) {
849 bool isPCRel = getAnyRelocationPCRel(RE);
852 case MachO::X86_64_RELOC_GOT_LOAD:
853 case MachO::X86_64_RELOC_GOT: {
854 printRelocationTargetName(this, RE, fmt);
856 if (isPCRel) fmt << "PCREL";
859 case MachO::X86_64_RELOC_SUBTRACTOR: {
860 DataRefImpl RelNext = Rel;
861 moveRelocationNext(RelNext);
862 MachO::any_relocation_info RENext = getRelocation(RelNext);
864 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
865 // X86_64_RELOC_UNSIGNED.
866 // NOTE: Scattered relocations don't exist on x86_64.
867 unsigned RType = getAnyRelocationType(RENext);
868 if (RType != MachO::X86_64_RELOC_UNSIGNED)
869 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
870 "X86_64_RELOC_SUBTRACTOR.");
872 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
873 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
874 printRelocationTargetName(this, RENext, fmt);
876 printRelocationTargetName(this, RE, fmt);
879 case MachO::X86_64_RELOC_TLV:
880 printRelocationTargetName(this, RE, fmt);
882 if (isPCRel) fmt << "P";
884 case MachO::X86_64_RELOC_SIGNED_1:
885 printRelocationTargetName(this, RE, fmt);
888 case MachO::X86_64_RELOC_SIGNED_2:
889 printRelocationTargetName(this, RE, fmt);
892 case MachO::X86_64_RELOC_SIGNED_4:
893 printRelocationTargetName(this, RE, fmt);
897 printRelocationTargetName(this, RE, fmt);
900 // X86 and ARM share some relocation types in common.
901 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
902 Arch == Triple::ppc) {
903 // Generic relocation types...
905 case MachO::GENERIC_RELOC_PAIR: // prints no info
906 return object_error::success;
907 case MachO::GENERIC_RELOC_SECTDIFF: {
908 DataRefImpl RelNext = Rel;
909 moveRelocationNext(RelNext);
910 MachO::any_relocation_info RENext = getRelocation(RelNext);
912 // X86 sect diff's must be followed by a relocation of type
913 // GENERIC_RELOC_PAIR.
914 unsigned RType = getAnyRelocationType(RENext);
916 if (RType != MachO::GENERIC_RELOC_PAIR)
917 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
918 "GENERIC_RELOC_SECTDIFF.");
920 printRelocationTargetName(this, RE, fmt);
922 printRelocationTargetName(this, RENext, fmt);
927 if (Arch == Triple::x86 || Arch == Triple::ppc) {
929 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
930 DataRefImpl RelNext = Rel;
931 moveRelocationNext(RelNext);
932 MachO::any_relocation_info RENext = getRelocation(RelNext);
934 // X86 sect diff's must be followed by a relocation of type
935 // GENERIC_RELOC_PAIR.
936 unsigned RType = getAnyRelocationType(RENext);
937 if (RType != MachO::GENERIC_RELOC_PAIR)
938 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
939 "GENERIC_RELOC_LOCAL_SECTDIFF.");
941 printRelocationTargetName(this, RE, fmt);
943 printRelocationTargetName(this, RENext, fmt);
946 case MachO::GENERIC_RELOC_TLV: {
947 printRelocationTargetName(this, RE, fmt);
949 if (IsPCRel) fmt << "P";
953 printRelocationTargetName(this, RE, fmt);
955 } else { // ARM-specific relocations
957 case MachO::ARM_RELOC_HALF:
958 case MachO::ARM_RELOC_HALF_SECTDIFF: {
959 // Half relocations steal a bit from the length field to encode
960 // whether this is an upper16 or a lower16 relocation.
961 bool isUpper = getAnyRelocationLength(RE) >> 1;
967 printRelocationTargetName(this, RE, fmt);
969 DataRefImpl RelNext = Rel;
970 moveRelocationNext(RelNext);
971 MachO::any_relocation_info RENext = getRelocation(RelNext);
973 // ARM half relocs must be followed by a relocation of type
975 unsigned RType = getAnyRelocationType(RENext);
976 if (RType != MachO::ARM_RELOC_PAIR)
977 report_fatal_error("Expected ARM_RELOC_PAIR after "
980 // NOTE: The half of the target virtual address is stashed in the
981 // address field of the secondary relocation, but we can't reverse
982 // engineer the constant offset from it without decoding the movw/movt
983 // instruction to find the other half in its immediate field.
985 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
986 // symbol/section pointer of the follow-on relocation.
987 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
989 printRelocationTargetName(this, RENext, fmt);
996 printRelocationTargetName(this, RE, fmt);
1001 printRelocationTargetName(this, RE, fmt);
1004 Result.append(fmtbuf.begin(), fmtbuf.end());
1005 return object_error::success;
1008 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1009 bool &Result) const {
1010 unsigned Arch = getArch();
1012 getRelocationType(Rel, Type);
1016 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1017 // is always hidden.
1018 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
1019 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
1020 } else if (Arch == Triple::x86_64) {
1021 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1022 // an X86_64_RELOC_SUBTRACTOR.
1023 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1024 DataRefImpl RelPrev = Rel;
1027 getRelocationType(RelPrev, PrevType);
1028 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1033 return object_error::success;
1037 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1038 // guess on what the short name is. Then name is returned as a substring of the
1039 // StringRef Name passed in. The name of the dynamic library is recognized as
1040 // a framework if it has one of the two following forms:
1041 // Foo.framework/Versions/A/Foo
1042 // Foo.framework/Foo
1043 // Where A and Foo can be any string. And may contain a trailing suffix
1044 // starting with an underbar. If the Name is recognized as a framework then
1045 // isFramework is set to true else it is set to false. If the Name has a
1046 // suffix then Suffix is set to the substring in Name that contains the suffix
1047 // else it is set to a NULL StringRef.
1049 // The Name of the dynamic library is recognized as a library name if it has
1050 // one of the two following forms:
1053 // The library may have a suffix trailing the name Foo of the form:
1054 // libFoo_profile.A.dylib
1055 // libFoo_profile.dylib
1057 // The Name of the dynamic library is also recognized as a library name if it
1058 // has the following form:
1061 // If the Name of the dynamic library is none of the forms above then a NULL
1062 // StringRef is returned.
1064 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1066 StringRef &Suffix) {
1067 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1068 size_t a, b, c, d, Idx;
1070 isFramework = false;
1071 Suffix = StringRef();
1073 // Pull off the last component and make Foo point to it
1074 a = Name.rfind('/');
1075 if (a == Name.npos || a == 0)
1077 Foo = Name.slice(a+1, Name.npos);
1079 // Look for a suffix starting with a '_'
1080 Idx = Foo.rfind('_');
1081 if (Idx != Foo.npos && Foo.size() >= 2) {
1082 Suffix = Foo.slice(Idx, Foo.npos);
1083 Foo = Foo.slice(0, Idx);
1086 // First look for the form Foo.framework/Foo
1087 b = Name.rfind('/', a);
1092 F = Name.slice(Idx, Idx + Foo.size());
1093 DotFramework = Name.slice(Idx + Foo.size(),
1094 Idx + Foo.size() + sizeof(".framework/")-1);
1095 if (F == Foo && DotFramework == ".framework/") {
1100 // Next look for the form Foo.framework/Versions/A/Foo
1103 c = Name.rfind('/', b);
1104 if (c == Name.npos || c == 0)
1106 V = Name.slice(c+1, Name.npos);
1107 if (!V.startswith("Versions/"))
1109 d = Name.rfind('/', c);
1114 F = Name.slice(Idx, Idx + Foo.size());
1115 DotFramework = Name.slice(Idx + Foo.size(),
1116 Idx + Foo.size() + sizeof(".framework/")-1);
1117 if (F == Foo && DotFramework == ".framework/") {
1123 // pull off the suffix after the "." and make a point to it
1124 a = Name.rfind('.');
1125 if (a == Name.npos || a == 0)
1127 Dylib = Name.slice(a, Name.npos);
1128 if (Dylib != ".dylib")
1131 // First pull off the version letter for the form Foo.A.dylib if any.
1133 Dot = Name.slice(a-2, a-1);
1138 b = Name.rfind('/', a);
1143 // ignore any suffix after an underbar like Foo_profile.A.dylib
1144 Idx = Name.find('_', b);
1145 if (Idx != Name.npos && Idx != b) {
1146 Lib = Name.slice(b, Idx);
1147 Suffix = Name.slice(Idx, a);
1150 Lib = Name.slice(b, a);
1151 // There are incorrect library names of the form:
1152 // libATS.A_profile.dylib so check for these.
1153 if (Lib.size() >= 3) {
1154 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1156 Lib = Lib.slice(0, Lib.size()-2);
1161 Qtx = Name.slice(a, Name.npos);
1164 b = Name.rfind('/', a);
1166 Lib = Name.slice(0, a);
1168 Lib = Name.slice(b+1, a);
1169 // There are library names of the form: QT.A.qtx so check for these.
1170 if (Lib.size() >= 3) {
1171 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1173 Lib = Lib.slice(0, Lib.size()-2);
1178 // getLibraryShortNameByIndex() is used to get the short name of the library
1179 // for an undefined symbol in a linked Mach-O binary that was linked with the
1180 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1181 // It is passed the index (0 - based) of the library as translated from
1182 // GET_LIBRARY_ORDINAL (1 - based).
1183 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1184 StringRef &Res) const {
1185 if (Index >= Libraries.size())
1186 return object_error::parse_failed;
1188 // If the cache of LibrariesShortNames is not built up do that first for
1189 // all the Libraries.
1190 if (LibrariesShortNames.size() == 0) {
1191 for (unsigned i = 0; i < Libraries.size(); i++) {
1192 MachO::dylib_command D =
1193 getStruct<MachO::dylib_command>(this, Libraries[i]);
1194 if (D.dylib.name >= D.cmdsize)
1195 return object_error::parse_failed;
1196 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1197 StringRef Name = StringRef(P);
1198 if (D.dylib.name+Name.size() >= D.cmdsize)
1199 return object_error::parse_failed;
1202 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1203 if (shortName.empty())
1204 LibrariesShortNames.push_back(Name);
1206 LibrariesShortNames.push_back(shortName);
1210 Res = LibrariesShortNames[Index];
1211 return object_error::success;
1214 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1215 return getSymbolByIndex(0);
1218 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1221 return basic_symbol_iterator(SymbolRef(DRI, this));
1223 MachO::symtab_command Symtab = getSymtabLoadCommand();
1224 unsigned SymbolTableEntrySize = is64Bit() ?
1225 sizeof(MachO::nlist_64) :
1226 sizeof(MachO::nlist);
1227 unsigned Offset = Symtab.symoff +
1228 Symtab.nsyms * SymbolTableEntrySize;
1229 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1230 return basic_symbol_iterator(SymbolRef(DRI, this));
1233 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1236 return basic_symbol_iterator(SymbolRef(DRI, this));
1238 MachO::symtab_command Symtab = getSymtabLoadCommand();
1239 if (Index >= Symtab.nsyms)
1240 report_fatal_error("Requested symbol index is out of range.");
1241 unsigned SymbolTableEntrySize =
1242 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1243 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1244 DRI.p += Index * SymbolTableEntrySize;
1245 return basic_symbol_iterator(SymbolRef(DRI, this));
1248 section_iterator MachOObjectFile::section_begin() const {
1250 return section_iterator(SectionRef(DRI, this));
1253 section_iterator MachOObjectFile::section_end() const {
1255 DRI.d.a = Sections.size();
1256 return section_iterator(SectionRef(DRI, this));
1259 uint8_t MachOObjectFile::getBytesInAddress() const {
1260 return is64Bit() ? 8 : 4;
1263 StringRef MachOObjectFile::getFileFormatName() const {
1264 unsigned CPUType = getCPUType(this);
1267 case llvm::MachO::CPU_TYPE_I386:
1268 return "Mach-O 32-bit i386";
1269 case llvm::MachO::CPU_TYPE_ARM:
1270 return "Mach-O arm";
1271 case llvm::MachO::CPU_TYPE_POWERPC:
1272 return "Mach-O 32-bit ppc";
1274 return "Mach-O 32-bit unknown";
1279 case llvm::MachO::CPU_TYPE_X86_64:
1280 return "Mach-O 64-bit x86-64";
1281 case llvm::MachO::CPU_TYPE_ARM64:
1282 return "Mach-O arm64";
1283 case llvm::MachO::CPU_TYPE_POWERPC64:
1284 return "Mach-O 64-bit ppc64";
1286 return "Mach-O 64-bit unknown";
1290 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1292 case llvm::MachO::CPU_TYPE_I386:
1294 case llvm::MachO::CPU_TYPE_X86_64:
1295 return Triple::x86_64;
1296 case llvm::MachO::CPU_TYPE_ARM:
1298 case llvm::MachO::CPU_TYPE_ARM64:
1299 return Triple::aarch64;
1300 case llvm::MachO::CPU_TYPE_POWERPC:
1302 case llvm::MachO::CPU_TYPE_POWERPC64:
1303 return Triple::ppc64;
1305 return Triple::UnknownArch;
1309 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1310 const char **McpuDefault) {
1312 *McpuDefault = nullptr;
1315 case MachO::CPU_TYPE_I386:
1316 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1317 case MachO::CPU_SUBTYPE_I386_ALL:
1318 return Triple("i386-apple-darwin");
1322 case MachO::CPU_TYPE_X86_64:
1323 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1324 case MachO::CPU_SUBTYPE_X86_64_ALL:
1325 return Triple("x86_64-apple-darwin");
1326 case MachO::CPU_SUBTYPE_X86_64_H:
1327 return Triple("x86_64h-apple-darwin");
1331 case MachO::CPU_TYPE_ARM:
1332 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1333 case MachO::CPU_SUBTYPE_ARM_V4T:
1334 return Triple("armv4t-apple-darwin");
1335 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1336 return Triple("armv5e-apple-darwin");
1337 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1338 return Triple("xscale-apple-darwin");
1339 case MachO::CPU_SUBTYPE_ARM_V6:
1340 return Triple("armv6-apple-darwin");
1341 case MachO::CPU_SUBTYPE_ARM_V6M:
1343 *McpuDefault = "cortex-m0";
1344 return Triple("armv6m-apple-darwin");
1345 case MachO::CPU_SUBTYPE_ARM_V7:
1346 return Triple("armv7-apple-darwin");
1347 case MachO::CPU_SUBTYPE_ARM_V7EM:
1349 *McpuDefault = "cortex-m4";
1350 return Triple("armv7em-apple-darwin");
1351 case MachO::CPU_SUBTYPE_ARM_V7K:
1352 return Triple("armv7k-apple-darwin");
1353 case MachO::CPU_SUBTYPE_ARM_V7M:
1355 *McpuDefault = "cortex-m3";
1356 return Triple("armv7m-apple-darwin");
1357 case MachO::CPU_SUBTYPE_ARM_V7S:
1358 return Triple("armv7s-apple-darwin");
1362 case MachO::CPU_TYPE_ARM64:
1363 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1364 case MachO::CPU_SUBTYPE_ARM64_ALL:
1365 return Triple("arm64-apple-darwin");
1369 case MachO::CPU_TYPE_POWERPC:
1370 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1371 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1372 return Triple("ppc-apple-darwin");
1376 case MachO::CPU_TYPE_POWERPC64:
1377 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1378 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1379 return Triple("ppc64-apple-darwin");
1388 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1389 const char **McpuDefault) {
1391 *McpuDefault = nullptr;
1394 case MachO::CPU_TYPE_ARM:
1395 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1396 case MachO::CPU_SUBTYPE_ARM_V4T:
1397 return Triple("thumbv4t-apple-darwin");
1398 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1399 return Triple("thumbv5e-apple-darwin");
1400 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1401 return Triple("xscale-apple-darwin");
1402 case MachO::CPU_SUBTYPE_ARM_V6:
1403 return Triple("thumbv6-apple-darwin");
1404 case MachO::CPU_SUBTYPE_ARM_V6M:
1406 *McpuDefault = "cortex-m0";
1407 return Triple("thumbv6m-apple-darwin");
1408 case MachO::CPU_SUBTYPE_ARM_V7:
1409 return Triple("thumbv7-apple-darwin");
1410 case MachO::CPU_SUBTYPE_ARM_V7EM:
1412 *McpuDefault = "cortex-m4";
1413 return Triple("thumbv7em-apple-darwin");
1414 case MachO::CPU_SUBTYPE_ARM_V7K:
1415 return Triple("thumbv7k-apple-darwin");
1416 case MachO::CPU_SUBTYPE_ARM_V7M:
1418 *McpuDefault = "cortex-m3";
1419 return Triple("thumbv7m-apple-darwin");
1420 case MachO::CPU_SUBTYPE_ARM_V7S:
1421 return Triple("thumbv7s-apple-darwin");
1430 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1431 const char **McpuDefault,
1432 Triple *ThumbTriple) {
1433 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1434 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1439 Triple MachOObjectFile::getHostArch() {
1440 return Triple(sys::getDefaultTargetTriple());
1443 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1444 return StringSwitch<bool>(ArchFlag)
1446 .Case("x86_64", true)
1447 .Case("x86_64h", true)
1448 .Case("armv4t", true)
1450 .Case("armv5e", true)
1451 .Case("armv6", true)
1452 .Case("armv6m", true)
1453 .Case("armv7em", true)
1454 .Case("armv7k", true)
1455 .Case("armv7m", true)
1456 .Case("armv7s", true)
1457 .Case("arm64", true)
1459 .Case("ppc64", true)
1463 unsigned MachOObjectFile::getArch() const {
1464 return getArch(getCPUType(this));
1467 Triple MachOObjectFile::getArch(const char **McpuDefault,
1468 Triple *ThumbTriple) const {
1471 MachO::mach_header_64 H_64;
1472 H_64 = getHeader64();
1473 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1474 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1477 MachO::mach_header H;
1479 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1480 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1486 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1489 return section_rel_begin(DRI);
1492 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1495 return section_rel_end(DRI);
1498 dice_iterator MachOObjectFile::begin_dices() const {
1500 if (!DataInCodeLoadCmd)
1501 return dice_iterator(DiceRef(DRI, this));
1503 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1504 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1505 return dice_iterator(DiceRef(DRI, this));
1508 dice_iterator MachOObjectFile::end_dices() const {
1510 if (!DataInCodeLoadCmd)
1511 return dice_iterator(DiceRef(DRI, this));
1513 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1514 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1515 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1516 return dice_iterator(DiceRef(DRI, this));
1519 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1520 : Trie(T), Malformed(false), Done(false) { }
1522 void ExportEntry::moveToFirst() {
1524 pushDownUntilBottom();
1527 void ExportEntry::moveToEnd() {
1532 bool ExportEntry::operator==(const ExportEntry &Other) const {
1533 // Common case, one at end, other iterating from begin.
1534 if (Done || Other.Done)
1535 return (Done == Other.Done);
1536 // Not equal if different stack sizes.
1537 if (Stack.size() != Other.Stack.size())
1539 // Not equal if different cumulative strings.
1540 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1542 // Equal if all nodes in both stacks match.
1543 for (unsigned i=0; i < Stack.size(); ++i) {
1544 if (Stack[i].Start != Other.Stack[i].Start)
1550 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1552 uint64_t Result = decodeULEB128(Ptr, &Count);
1554 if (Ptr > Trie.end()) {
1561 StringRef ExportEntry::name() const {
1562 return CumulativeString.str();
1565 uint64_t ExportEntry::flags() const {
1566 return Stack.back().Flags;
1569 uint64_t ExportEntry::address() const {
1570 return Stack.back().Address;
1573 uint64_t ExportEntry::other() const {
1574 return Stack.back().Other;
1577 StringRef ExportEntry::otherName() const {
1578 const char* ImportName = Stack.back().ImportName;
1580 return StringRef(ImportName);
1584 uint32_t ExportEntry::nodeOffset() const {
1585 return Stack.back().Start - Trie.begin();
1588 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1589 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1590 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1591 ParentStringLength(0), IsExportNode(false) {
1594 void ExportEntry::pushNode(uint64_t offset) {
1595 const uint8_t *Ptr = Trie.begin() + offset;
1596 NodeState State(Ptr);
1597 uint64_t ExportInfoSize = readULEB128(State.Current);
1598 State.IsExportNode = (ExportInfoSize != 0);
1599 const uint8_t* Children = State.Current + ExportInfoSize;
1600 if (State.IsExportNode) {
1601 State.Flags = readULEB128(State.Current);
1602 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1604 State.Other = readULEB128(State.Current); // dylib ordinal
1605 State.ImportName = reinterpret_cast<const char*>(State.Current);
1607 State.Address = readULEB128(State.Current);
1608 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1609 State.Other = readULEB128(State.Current);
1612 State.ChildCount = *Children;
1613 State.Current = Children + 1;
1614 State.NextChildIndex = 0;
1615 State.ParentStringLength = CumulativeString.size();
1616 Stack.push_back(State);
1619 void ExportEntry::pushDownUntilBottom() {
1620 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1621 NodeState &Top = Stack.back();
1622 CumulativeString.resize(Top.ParentStringLength);
1623 for (;*Top.Current != 0; Top.Current++) {
1624 char C = *Top.Current;
1625 CumulativeString.push_back(C);
1628 uint64_t childNodeIndex = readULEB128(Top.Current);
1629 Top.NextChildIndex += 1;
1630 pushNode(childNodeIndex);
1632 if (!Stack.back().IsExportNode) {
1638 // We have a trie data structure and need a way to walk it that is compatible
1639 // with the C++ iterator model. The solution is a non-recursive depth first
1640 // traversal where the iterator contains a stack of parent nodes along with a
1641 // string that is the accumulation of all edge strings along the parent chain
1644 // There is one "export" node for each exported symbol. But because some
1645 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1646 // node may have child nodes too.
1648 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1649 // child until hitting a node with no children (which is an export node or
1650 // else the trie is malformed). On the way down, each node is pushed on the
1651 // stack ivar. If there is no more ways down, it pops up one and tries to go
1652 // down a sibling path until a childless node is reached.
1653 void ExportEntry::moveNext() {
1654 if (Stack.empty() || !Stack.back().IsExportNode) {
1661 while (!Stack.empty()) {
1662 NodeState &Top = Stack.back();
1663 if (Top.NextChildIndex < Top.ChildCount) {
1664 pushDownUntilBottom();
1665 // Now at the next export node.
1668 if (Top.IsExportNode) {
1669 // This node has no children but is itself an export node.
1670 CumulativeString.resize(Top.ParentStringLength);
1679 iterator_range<export_iterator>
1680 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1681 ExportEntry Start(Trie);
1682 if (Trie.size() == 0)
1685 Start.moveToFirst();
1687 ExportEntry Finish(Trie);
1690 return iterator_range<export_iterator>(export_iterator(Start),
1691 export_iterator(Finish));
1694 iterator_range<export_iterator> MachOObjectFile::exports() const {
1695 return exports(getDyldInfoExportsTrie());
1699 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1700 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1701 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1702 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1704 void MachORebaseEntry::moveToFirst() {
1705 Ptr = Opcodes.begin();
1709 void MachORebaseEntry::moveToEnd() {
1710 Ptr = Opcodes.end();
1711 RemainingLoopCount = 0;
1715 void MachORebaseEntry::moveNext() {
1716 // If in the middle of some loop, move to next rebasing in loop.
1717 SegmentOffset += AdvanceAmount;
1718 if (RemainingLoopCount) {
1719 --RemainingLoopCount;
1722 if (Ptr == Opcodes.end()) {
1727 while (More && !Malformed) {
1728 // Parse next opcode and set up next loop.
1729 uint8_t Byte = *Ptr++;
1730 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1731 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1733 case MachO::REBASE_OPCODE_DONE:
1737 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1739 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1740 RebaseType = ImmValue;
1743 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1744 << "RebaseType=" << (int) RebaseType << "\n");
1746 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1747 SegmentIndex = ImmValue;
1748 SegmentOffset = readULEB128();
1751 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1752 << "SegmentIndex=" << SegmentIndex << ", "
1753 << format("SegmentOffset=0x%06X", SegmentOffset)
1756 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1757 SegmentOffset += readULEB128();
1758 DEBUG_WITH_TYPE("mach-o-rebase",
1759 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1760 << format("SegmentOffset=0x%06X",
1761 SegmentOffset) << "\n");
1763 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1764 SegmentOffset += ImmValue * PointerSize;
1765 DEBUG_WITH_TYPE("mach-o-rebase",
1766 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1767 << format("SegmentOffset=0x%06X",
1768 SegmentOffset) << "\n");
1770 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1771 AdvanceAmount = PointerSize;
1772 RemainingLoopCount = ImmValue - 1;
1775 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1776 << format("SegmentOffset=0x%06X", SegmentOffset)
1777 << ", AdvanceAmount=" << AdvanceAmount
1778 << ", RemainingLoopCount=" << RemainingLoopCount
1781 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1782 AdvanceAmount = PointerSize;
1783 RemainingLoopCount = readULEB128() - 1;
1786 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1787 << format("SegmentOffset=0x%06X", SegmentOffset)
1788 << ", AdvanceAmount=" << AdvanceAmount
1789 << ", RemainingLoopCount=" << RemainingLoopCount
1792 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1793 AdvanceAmount = readULEB128() + PointerSize;
1794 RemainingLoopCount = 0;
1797 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1798 << format("SegmentOffset=0x%06X", SegmentOffset)
1799 << ", AdvanceAmount=" << AdvanceAmount
1800 << ", RemainingLoopCount=" << RemainingLoopCount
1803 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1804 RemainingLoopCount = readULEB128() - 1;
1805 AdvanceAmount = readULEB128() + PointerSize;
1808 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1809 << format("SegmentOffset=0x%06X", SegmentOffset)
1810 << ", AdvanceAmount=" << AdvanceAmount
1811 << ", RemainingLoopCount=" << RemainingLoopCount
1820 uint64_t MachORebaseEntry::readULEB128() {
1822 uint64_t Result = decodeULEB128(Ptr, &Count);
1824 if (Ptr > Opcodes.end()) {
1825 Ptr = Opcodes.end();
1831 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1833 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1835 StringRef MachORebaseEntry::typeName() const {
1836 switch (RebaseType) {
1837 case MachO::REBASE_TYPE_POINTER:
1839 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1840 return "text abs32";
1841 case MachO::REBASE_TYPE_TEXT_PCREL32:
1842 return "text rel32";
1847 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1848 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1849 return (Ptr == Other.Ptr) &&
1850 (RemainingLoopCount == Other.RemainingLoopCount) &&
1851 (Done == Other.Done);
1854 iterator_range<rebase_iterator>
1855 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1856 MachORebaseEntry Start(Opcodes, is64);
1857 Start.moveToFirst();
1859 MachORebaseEntry Finish(Opcodes, is64);
1862 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1863 rebase_iterator(Finish));
1866 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1867 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1871 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1873 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1874 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1875 BindType(0), PointerSize(is64Bit ? 8 : 4),
1876 TableKind(BK), Malformed(false), Done(false) {}
1878 void MachOBindEntry::moveToFirst() {
1879 Ptr = Opcodes.begin();
1883 void MachOBindEntry::moveToEnd() {
1884 Ptr = Opcodes.end();
1885 RemainingLoopCount = 0;
1889 void MachOBindEntry::moveNext() {
1890 // If in the middle of some loop, move to next binding in loop.
1891 SegmentOffset += AdvanceAmount;
1892 if (RemainingLoopCount) {
1893 --RemainingLoopCount;
1896 if (Ptr == Opcodes.end()) {
1901 while (More && !Malformed) {
1902 // Parse next opcode and set up next loop.
1903 uint8_t Byte = *Ptr++;
1904 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1905 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1906 int8_t SignExtended;
1907 const uint8_t *SymStart;
1909 case MachO::BIND_OPCODE_DONE:
1910 if (TableKind == Kind::Lazy) {
1911 // Lazying bindings have a DONE opcode between entries. Need to ignore
1912 // it to advance to next entry. But need not if this is last entry.
1913 bool NotLastEntry = false;
1914 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1916 NotLastEntry = true;
1925 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1927 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1931 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1932 << "Ordinal=" << Ordinal << "\n");
1934 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1935 Ordinal = readULEB128();
1938 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1939 << "Ordinal=" << Ordinal << "\n");
1941 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1943 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1944 Ordinal = SignExtended;
1949 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1950 << "Ordinal=" << Ordinal << "\n");
1952 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1958 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1963 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1964 << "SymbolName=" << SymbolName << "\n");
1965 if (TableKind == Kind::Weak) {
1966 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1970 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1971 BindType = ImmValue;
1974 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1975 << "BindType=" << (int)BindType << "\n");
1977 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1978 Addend = readSLEB128();
1979 if (TableKind == Kind::Lazy)
1983 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1984 << "Addend=" << Addend << "\n");
1986 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1987 SegmentIndex = ImmValue;
1988 SegmentOffset = readULEB128();
1991 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1992 << "SegmentIndex=" << SegmentIndex << ", "
1993 << format("SegmentOffset=0x%06X", SegmentOffset)
1996 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1997 SegmentOffset += readULEB128();
1998 DEBUG_WITH_TYPE("mach-o-bind",
1999 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
2000 << format("SegmentOffset=0x%06X",
2001 SegmentOffset) << "\n");
2003 case MachO::BIND_OPCODE_DO_BIND:
2004 AdvanceAmount = PointerSize;
2005 RemainingLoopCount = 0;
2006 DEBUG_WITH_TYPE("mach-o-bind",
2007 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
2008 << format("SegmentOffset=0x%06X",
2009 SegmentOffset) << "\n");
2011 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
2012 AdvanceAmount = readULEB128() + PointerSize;
2013 RemainingLoopCount = 0;
2014 if (TableKind == Kind::Lazy)
2018 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
2019 << format("SegmentOffset=0x%06X", SegmentOffset)
2020 << ", AdvanceAmount=" << AdvanceAmount
2021 << ", RemainingLoopCount=" << RemainingLoopCount
2024 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
2025 AdvanceAmount = ImmValue * PointerSize + PointerSize;
2026 RemainingLoopCount = 0;
2027 if (TableKind == Kind::Lazy)
2029 DEBUG_WITH_TYPE("mach-o-bind",
2031 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
2032 << format("SegmentOffset=0x%06X",
2033 SegmentOffset) << "\n");
2035 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
2036 RemainingLoopCount = readULEB128() - 1;
2037 AdvanceAmount = readULEB128() + PointerSize;
2038 if (TableKind == Kind::Lazy)
2042 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2043 << format("SegmentOffset=0x%06X", SegmentOffset)
2044 << ", AdvanceAmount=" << AdvanceAmount
2045 << ", RemainingLoopCount=" << RemainingLoopCount
2054 uint64_t MachOBindEntry::readULEB128() {
2056 uint64_t Result = decodeULEB128(Ptr, &Count);
2058 if (Ptr > Opcodes.end()) {
2059 Ptr = Opcodes.end();
2065 int64_t MachOBindEntry::readSLEB128() {
2067 int64_t Result = decodeSLEB128(Ptr, &Count);
2069 if (Ptr > Opcodes.end()) {
2070 Ptr = Opcodes.end();
2077 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2079 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2081 StringRef MachOBindEntry::typeName() const {
2083 case MachO::BIND_TYPE_POINTER:
2085 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2086 return "text abs32";
2087 case MachO::BIND_TYPE_TEXT_PCREL32:
2088 return "text rel32";
2093 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2095 int64_t MachOBindEntry::addend() const { return Addend; }
2097 uint32_t MachOBindEntry::flags() const { return Flags; }
2099 int MachOBindEntry::ordinal() const { return Ordinal; }
2101 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2102 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2103 return (Ptr == Other.Ptr) &&
2104 (RemainingLoopCount == Other.RemainingLoopCount) &&
2105 (Done == Other.Done);
2108 iterator_range<bind_iterator>
2109 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2110 MachOBindEntry::Kind BKind) {
2111 MachOBindEntry Start(Opcodes, is64, BKind);
2112 Start.moveToFirst();
2114 MachOBindEntry Finish(Opcodes, is64, BKind);
2117 return iterator_range<bind_iterator>(bind_iterator(Start),
2118 bind_iterator(Finish));
2121 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2122 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2123 MachOBindEntry::Kind::Regular);
2126 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2127 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2128 MachOBindEntry::Kind::Lazy);
2131 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2132 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2133 MachOBindEntry::Kind::Weak);
2137 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2138 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2139 return parseSegmentOrSectionName(Raw.data());
2143 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2144 if (Sec.d.a >= Sections.size())
2145 report_fatal_error("getSectionRawName: Invalid section index");
2146 const section_base *Base =
2147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2148 return makeArrayRef(Base->sectname);
2152 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2153 if (Sec.d.a >= Sections.size())
2154 report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
2155 const section_base *Base =
2156 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2157 return makeArrayRef(Base->segname);
2161 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2163 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2165 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2168 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2169 const MachO::any_relocation_info &RE) const {
2170 if (isLittleEndian())
2171 return RE.r_word1 & 0xffffff;
2172 return RE.r_word1 >> 8;
2175 bool MachOObjectFile::getPlainRelocationExternal(
2176 const MachO::any_relocation_info &RE) const {
2177 if (isLittleEndian())
2178 return (RE.r_word1 >> 27) & 1;
2179 return (RE.r_word1 >> 4) & 1;
2182 bool MachOObjectFile::getScatteredRelocationScattered(
2183 const MachO::any_relocation_info &RE) const {
2184 return RE.r_word0 >> 31;
2187 uint32_t MachOObjectFile::getScatteredRelocationValue(
2188 const MachO::any_relocation_info &RE) const {
2192 uint32_t MachOObjectFile::getScatteredRelocationType(
2193 const MachO::any_relocation_info &RE) const {
2194 return (RE.r_word0 >> 24) & 0xf;
2197 unsigned MachOObjectFile::getAnyRelocationAddress(
2198 const MachO::any_relocation_info &RE) const {
2199 if (isRelocationScattered(RE))
2200 return getScatteredRelocationAddress(RE);
2201 return getPlainRelocationAddress(RE);
2204 unsigned MachOObjectFile::getAnyRelocationPCRel(
2205 const MachO::any_relocation_info &RE) const {
2206 if (isRelocationScattered(RE))
2207 return getScatteredRelocationPCRel(this, RE);
2208 return getPlainRelocationPCRel(this, RE);
2211 unsigned MachOObjectFile::getAnyRelocationLength(
2212 const MachO::any_relocation_info &RE) const {
2213 if (isRelocationScattered(RE))
2214 return getScatteredRelocationLength(RE);
2215 return getPlainRelocationLength(this, RE);
2219 MachOObjectFile::getAnyRelocationType(
2220 const MachO::any_relocation_info &RE) const {
2221 if (isRelocationScattered(RE))
2222 return getScatteredRelocationType(RE);
2223 return getPlainRelocationType(this, RE);
2227 MachOObjectFile::getRelocationSection(
2228 const MachO::any_relocation_info &RE) const {
2229 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2230 return *section_end();
2231 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2234 return SectionRef(DRI, this);
2237 MachOObjectFile::LoadCommandInfo
2238 MachOObjectFile::getFirstLoadCommandInfo() const {
2239 MachOObjectFile::LoadCommandInfo Load;
2241 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2242 sizeof(MachO::mach_header);
2243 Load.Ptr = getPtr(this, HeaderSize);
2244 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2245 if (Load.C.cmdsize < 8)
2246 report_fatal_error("Load command with size < 8 bytes.");
2250 MachOObjectFile::LoadCommandInfo
2251 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2252 MachOObjectFile::LoadCommandInfo Next;
2253 Next.Ptr = L.Ptr + L.C.cmdsize;
2254 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2255 if (Next.C.cmdsize < 8)
2256 report_fatal_error("Load command with size < 8 bytes.");
2260 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2261 // TODO: What if Sections.size() == 0?
2262 if (DRI.d.a >= Sections.size())
2263 report_fatal_error("getSection: Invalid section index.");
2264 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2267 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2268 // TODO: What if Sections.size() == 0?
2269 if (DRI.d.a >= Sections.size())
2270 report_fatal_error("getSection64: Invalid section index.");
2271 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2274 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2275 unsigned Index) const {
2276 const char *Sec = getSectionPtr(this, L, Index);
2277 return getStruct<MachO::section>(this, Sec);
2280 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2281 unsigned Index) const {
2282 const char *Sec = getSectionPtr(this, L, Index);
2283 return getStruct<MachO::section_64>(this, Sec);
2287 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2288 const char *P = reinterpret_cast<const char *>(DRI.p);
2289 return getStruct<MachO::nlist>(this, P);
2293 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2294 const char *P = reinterpret_cast<const char *>(DRI.p);
2295 return getStruct<MachO::nlist_64>(this, P);
2298 MachO::linkedit_data_command
2299 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2300 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2303 MachO::segment_command
2304 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2305 return getStruct<MachO::segment_command>(this, L.Ptr);
2308 MachO::segment_command_64
2309 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2310 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2313 MachO::linker_option_command
2314 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2315 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2318 MachO::version_min_command
2319 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2320 return getStruct<MachO::version_min_command>(this, L.Ptr);
2323 MachO::dylib_command
2324 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2325 return getStruct<MachO::dylib_command>(this, L.Ptr);
2328 MachO::dyld_info_command
2329 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2330 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2333 MachO::dylinker_command
2334 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2335 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2339 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2340 return getStruct<MachO::uuid_command>(this, L.Ptr);
2343 MachO::rpath_command
2344 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2345 return getStruct<MachO::rpath_command>(this, L.Ptr);
2348 MachO::source_version_command
2349 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2350 return getStruct<MachO::source_version_command>(this, L.Ptr);
2353 MachO::entry_point_command
2354 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2355 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2358 MachO::encryption_info_command
2359 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2360 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2363 MachO::encryption_info_command_64
2364 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2365 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2368 MachO::sub_framework_command
2369 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2370 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2373 MachO::sub_umbrella_command
2374 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2375 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2378 MachO::sub_library_command
2379 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2380 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2383 MachO::sub_client_command
2384 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2385 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2388 MachO::routines_command
2389 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2390 return getStruct<MachO::routines_command>(this, L.Ptr);
2393 MachO::routines_command_64
2394 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2395 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2398 MachO::thread_command
2399 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2400 return getStruct<MachO::thread_command>(this, L.Ptr);
2403 MachO::any_relocation_info
2404 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2409 MachO::section_64 Sect = getSection64(Sec);
2410 Offset = Sect.reloff;
2412 MachO::section Sect = getSection(Sec);
2413 Offset = Sect.reloff;
2416 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2417 getPtr(this, Offset)) + Rel.d.b;
2418 return getStruct<MachO::any_relocation_info>(
2419 this, reinterpret_cast<const char *>(P));
2422 MachO::data_in_code_entry
2423 MachOObjectFile::getDice(DataRefImpl Rel) const {
2424 const char *P = reinterpret_cast<const char *>(Rel.p);
2425 return getStruct<MachO::data_in_code_entry>(this, P);
2428 MachO::mach_header MachOObjectFile::getHeader() const {
2429 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2432 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2433 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2436 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2437 const MachO::dysymtab_command &DLC,
2438 unsigned Index) const {
2439 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2440 return getStruct<uint32_t>(this, getPtr(this, Offset));
2443 MachO::data_in_code_entry
2444 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2445 unsigned Index) const {
2446 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2447 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2450 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2452 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2454 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2455 MachO::symtab_command Cmd;
2456 Cmd.cmd = MachO::LC_SYMTAB;
2457 Cmd.cmdsize = sizeof(MachO::symtab_command);
2465 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2466 if (DysymtabLoadCmd)
2467 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2469 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2470 MachO::dysymtab_command Cmd;
2471 Cmd.cmd = MachO::LC_DYSYMTAB;
2472 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2483 Cmd.extrefsymoff = 0;
2484 Cmd.nextrefsyms = 0;
2485 Cmd.indirectsymoff = 0;
2486 Cmd.nindirectsyms = 0;
2494 MachO::linkedit_data_command
2495 MachOObjectFile::getDataInCodeLoadCommand() const {
2496 if (DataInCodeLoadCmd)
2497 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2499 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2500 MachO::linkedit_data_command Cmd;
2501 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2502 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2508 MachO::linkedit_data_command
2509 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2510 if (LinkOptHintsLoadCmd)
2511 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2513 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2515 MachO::linkedit_data_command Cmd;
2516 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2517 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2523 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2524 if (!DyldInfoLoadCmd)
2525 return ArrayRef<uint8_t>();
2527 MachO::dyld_info_command DyldInfo
2528 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2529 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2530 getPtr(this, DyldInfo.rebase_off));
2531 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2534 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2535 if (!DyldInfoLoadCmd)
2536 return ArrayRef<uint8_t>();
2538 MachO::dyld_info_command DyldInfo
2539 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2540 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2541 getPtr(this, DyldInfo.bind_off));
2542 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2545 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2546 if (!DyldInfoLoadCmd)
2547 return ArrayRef<uint8_t>();
2549 MachO::dyld_info_command DyldInfo
2550 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2551 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2552 getPtr(this, DyldInfo.weak_bind_off));
2553 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2556 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2557 if (!DyldInfoLoadCmd)
2558 return ArrayRef<uint8_t>();
2560 MachO::dyld_info_command DyldInfo
2561 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2562 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2563 getPtr(this, DyldInfo.lazy_bind_off));
2564 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2567 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2568 if (!DyldInfoLoadCmd)
2569 return ArrayRef<uint8_t>();
2571 MachO::dyld_info_command DyldInfo
2572 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2573 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2574 getPtr(this, DyldInfo.export_off));
2575 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2578 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2580 return ArrayRef<uint8_t>();
2581 // Returning a pointer is fine as uuid doesn't need endian swapping.
2582 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2583 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2586 StringRef MachOObjectFile::getStringTableData() const {
2587 MachO::symtab_command S = getSymtabLoadCommand();
2588 return getData().substr(S.stroff, S.strsize);
2591 bool MachOObjectFile::is64Bit() const {
2592 return getType() == getMachOType(false, true) ||
2593 getType() == getMachOType(true, true);
2596 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2597 SmallVectorImpl<uint64_t> &Out) const {
2598 DataExtractor extractor(ObjectFile::getData(), true, 0);
2600 uint32_t offset = Index;
2602 while (uint64_t delta = extractor.getULEB128(&offset)) {
2604 Out.push_back(data);
2608 bool MachOObjectFile::isRelocatableObject() const {
2609 return getHeader().filetype == MachO::MH_OBJECT;
2612 ErrorOr<std::unique_ptr<MachOObjectFile>>
2613 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2614 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2616 std::unique_ptr<MachOObjectFile> Ret;
2617 if (Magic == "\xFE\xED\xFA\xCE")
2618 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2619 else if (Magic == "\xCE\xFA\xED\xFE")
2620 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2621 else if (Magic == "\xFE\xED\xFA\xCF")
2622 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2623 else if (Magic == "\xCF\xFA\xED\xFE")
2624 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2626 return object_error::parse_failed;
2630 return std::move(Ret);