1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/MachO.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/raw_ostream.h"
32 using namespace object;
42 static T getStruct(const MachOObjectFile *O, const char *P) {
44 memcpy(&Cmd, P, sizeof(T));
45 if (O->isLittleEndian() != sys::IsLittleEndianHost)
46 MachO::swapStruct(Cmd);
51 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
52 const MachOObjectFile::LoadCommandInfo &L) {
54 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
57 MachO::segment_command S = O->getSegmentLoadCommand(L);
61 static bool isPageZeroSegment(const MachOObjectFile *O,
62 const MachOObjectFile::LoadCommandInfo &L) {
64 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
65 return StringRef("__PAGEZERO").equals(S.segname);
67 MachO::segment_command S = O->getSegmentLoadCommand(L);
68 return StringRef("__PAGEZERO").equals(S.segname);
73 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
75 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
77 bool Is64 = O->is64Bit();
78 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
79 sizeof(MachO::segment_command);
80 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
81 sizeof(MachO::section);
83 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
84 return reinterpret_cast<const char*>(SectionAddr);
87 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
88 return O->getData().substr(Offset, 1).data();
91 static MachO::nlist_base
92 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
93 const char *P = reinterpret_cast<const char *>(DRI.p);
94 return getStruct<MachO::nlist_base>(O, P);
97 static StringRef parseSegmentOrSectionName(const char *P) {
101 // Not null terminated, so this is a 16 char string.
102 return StringRef(P, 16);
105 // Helper to advance a section or symbol iterator multiple increments at a time.
107 static void advance(T &it, size_t Val) {
112 static unsigned getCPUType(const MachOObjectFile *O) {
113 return O->getHeader().cputype;
116 static void printRelocationTargetName(const MachOObjectFile *O,
117 const MachO::any_relocation_info &RE,
118 raw_string_ostream &fmt) {
119 bool IsScattered = O->isRelocationScattered(RE);
121 // Target of a scattered relocation is an address. In the interest of
122 // generating pretty output, scan through the symbol table looking for a
123 // symbol that aligns with that address. If we find one, print it.
124 // Otherwise, we just print the hex address of the target.
126 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
128 for (const SymbolRef &Symbol : O->symbols()) {
133 if ((ec = Symbol.getAddress(Addr)))
134 report_fatal_error(ec.message());
137 if ((ec = Symbol.getName(Name)))
138 report_fatal_error(ec.message());
143 // If we couldn't find a symbol that this relocation refers to, try
144 // to find a section beginning instead.
145 for (const SectionRef &Section : O->sections()) {
149 uint64_t Addr = Section.getAddress();
152 if ((ec = Section.getName(Name)))
153 report_fatal_error(ec.message());
158 fmt << format("0x%x", Val);
163 bool isExtern = O->getPlainRelocationExternal(RE);
164 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
167 symbol_iterator SI = O->symbol_begin();
171 section_iterator SI = O->section_begin();
172 // Adjust for the fact that sections are 1-indexed.
173 advance(SI, Val - 1);
181 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
186 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
187 return RE.r_word0 & 0xffffff;
190 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
191 const MachO::any_relocation_info &RE) {
192 if (O->isLittleEndian())
193 return (RE.r_word1 >> 24) & 1;
194 return (RE.r_word1 >> 7) & 1;
198 getScatteredRelocationPCRel(const MachOObjectFile *O,
199 const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 30) & 1;
203 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return (RE.r_word1 >> 25) & 3;
207 return (RE.r_word1 >> 5) & 3;
211 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 28) & 3;
215 static unsigned getPlainRelocationType(const MachOObjectFile *O,
216 const MachO::any_relocation_info &RE) {
217 if (O->isLittleEndian())
218 return RE.r_word1 >> 28;
219 return RE.r_word1 & 0xf;
222 static uint32_t getSectionFlags(const MachOObjectFile *O,
225 MachO::section_64 Sect = O->getSection64(Sec);
228 MachO::section Sect = O->getSection(Sec);
232 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
233 bool Is64bits, std::error_code &EC)
234 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
235 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
236 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
237 UuidLoadCmd(nullptr), HasPageZeroSegment(false) {
238 uint32_t LoadCommandCount = this->getHeader().ncmds;
239 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
240 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
242 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
243 for (unsigned I = 0; ; ++I) {
244 if (Load.C.cmd == MachO::LC_SYMTAB) {
245 // Multiple symbol tables
247 EC = object_error::parse_failed;
250 SymtabLoadCmd = Load.Ptr;
251 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
252 // Multiple dynamic symbol tables
253 if (DysymtabLoadCmd) {
254 EC = object_error::parse_failed;
257 DysymtabLoadCmd = Load.Ptr;
258 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
259 // Multiple data in code tables
260 if (DataInCodeLoadCmd) {
261 EC = object_error::parse_failed;
264 DataInCodeLoadCmd = Load.Ptr;
265 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
266 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
267 // Multiple dyldinfo load commands
268 if (DyldInfoLoadCmd) {
269 EC = object_error::parse_failed;
272 DyldInfoLoadCmd = Load.Ptr;
273 } else if (Load.C.cmd == MachO::LC_UUID) {
274 // Multiple UUID load commands
276 EC = object_error::parse_failed;
279 UuidLoadCmd = Load.Ptr;
280 } else if (Load.C.cmd == SegmentLoadType) {
281 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
282 for (unsigned J = 0; J < NumSections; ++J) {
283 const char *Sec = getSectionPtr(this, Load, J);
284 Sections.push_back(Sec);
286 if (isPageZeroSegment(this, Load))
287 HasPageZeroSegment = true;
288 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
289 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
290 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
291 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
292 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
293 Libraries.push_back(Load.Ptr);
296 if (I == LoadCommandCount - 1)
299 Load = getNextLoadCommandInfo(Load);
303 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
304 unsigned SymbolTableEntrySize = is64Bit() ?
305 sizeof(MachO::nlist_64) :
306 sizeof(MachO::nlist);
307 Symb.p += SymbolTableEntrySize;
310 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
311 StringRef &Res) const {
312 StringRef StringTable = getStringTableData();
313 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
314 const char *Start = &StringTable.data()[Entry.n_strx];
315 Res = StringRef(Start);
316 return object_error::success;
319 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
320 DataRefImpl DRI = Sec.getRawDataRefImpl();
321 uint32_t Flags = getSectionFlags(this, DRI);
322 return Flags & MachO::SECTION_TYPE;
325 // getIndirectName() returns the name of the alias'ed symbol who's string table
326 // index is in the n_value field.
327 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
328 StringRef &Res) const {
329 StringRef StringTable = getStringTableData();
332 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
333 NValue = Entry.n_value;
334 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
335 return object_error::parse_failed;
337 MachO::nlist Entry = getSymbolTableEntry(Symb);
338 NValue = Entry.n_value;
339 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
340 return object_error::parse_failed;
342 if (NValue >= StringTable.size())
343 return object_error::parse_failed;
344 const char *Start = &StringTable.data()[NValue];
345 Res = StringRef(Start);
346 return object_error::success;
349 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
350 uint64_t &Res) const {
352 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
353 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
355 Res = UnknownAddressOrSize;
359 MachO::nlist Entry = getSymbolTableEntry(Symb);
360 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
362 Res = UnknownAddressOrSize;
366 return object_error::success;
369 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
370 uint32_t &Result) const {
371 uint32_t flags = getSymbolFlags(DRI);
372 if (flags & SymbolRef::SF_Common) {
373 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
374 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
378 return object_error::success;
381 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
382 uint64_t &Result) const {
383 uint64_t BeginOffset;
384 uint64_t EndOffset = 0;
385 uint8_t SectionIndex;
387 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
389 getSymbolAddress(DRI, Value);
390 if (Value == UnknownAddressOrSize) {
391 Result = UnknownAddressOrSize;
392 return object_error::success;
397 SectionIndex = Entry.n_sect;
399 uint32_t flags = getSymbolFlags(DRI);
400 if (flags & SymbolRef::SF_Common)
403 Result = UnknownAddressOrSize;
404 return object_error::success;
406 // Unfortunately symbols are unsorted so we need to touch all
407 // symbols from load command
408 for (const SymbolRef &Symbol : symbols()) {
409 DataRefImpl DRI = Symbol.getRawDataRefImpl();
410 Entry = getSymbolTableEntryBase(this, DRI);
411 getSymbolAddress(DRI, Value);
412 if (Value == UnknownAddressOrSize)
414 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
415 if (!EndOffset || Value < EndOffset)
420 Sec.d.a = SectionIndex-1;
421 uint64_t Size = getSectionSize(Sec);
422 EndOffset = getSectionAddress(Sec);
425 Result = EndOffset - BeginOffset;
426 return object_error::success;
429 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
430 SymbolRef::Type &Res) const {
431 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
432 uint8_t n_type = Entry.n_type;
434 Res = SymbolRef::ST_Other;
436 // If this is a STAB debugging symbol, we can do nothing more.
437 if (n_type & MachO::N_STAB) {
438 Res = SymbolRef::ST_Debug;
439 return object_error::success;
442 switch (n_type & MachO::N_TYPE) {
444 Res = SymbolRef::ST_Unknown;
447 Res = SymbolRef::ST_Function;
450 return object_error::success;
453 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
454 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
456 uint8_t MachOType = Entry.n_type;
457 uint16_t MachOFlags = Entry.n_desc;
459 uint32_t Result = SymbolRef::SF_None;
461 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
462 Result |= SymbolRef::SF_Undefined;
464 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
465 Result |= SymbolRef::SF_Indirect;
467 if (MachOType & MachO::N_STAB)
468 Result |= SymbolRef::SF_FormatSpecific;
470 if (MachOType & MachO::N_EXT) {
471 Result |= SymbolRef::SF_Global;
472 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
474 getSymbolAddress(DRI, Value);
475 if (Value && Value != UnknownAddressOrSize)
476 Result |= SymbolRef::SF_Common;
480 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
481 Result |= SymbolRef::SF_Weak;
483 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
484 Result |= SymbolRef::SF_Thumb;
486 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
487 Result |= SymbolRef::SF_Absolute;
492 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
493 section_iterator &Res) const {
494 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
495 uint8_t index = Entry.n_sect;
502 Res = section_iterator(SectionRef(DRI, this));
505 return object_error::success;
508 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
512 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
513 StringRef &Result) const {
514 ArrayRef<char> Raw = getSectionRawName(Sec);
515 Result = parseSegmentOrSectionName(Raw.data());
516 return object_error::success;
519 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
521 return getSection64(Sec).addr;
522 return getSection(Sec).addr;
525 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
527 return getSection64(Sec).size;
528 return getSection(Sec).size;
531 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
532 StringRef &Res) const {
537 MachO::section_64 Sect = getSection64(Sec);
538 Offset = Sect.offset;
541 MachO::section Sect = getSection(Sec);
542 Offset = Sect.offset;
546 Res = this->getData().substr(Offset, Size);
547 return object_error::success;
550 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
553 MachO::section_64 Sect = getSection64(Sec);
556 MachO::section Sect = getSection(Sec);
560 return uint64_t(1) << Align;
563 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
564 uint32_t Flags = getSectionFlags(this, Sec);
565 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
568 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
569 uint32_t Flags = getSectionFlags(this, Sec);
570 unsigned SectionType = Flags & MachO::SECTION_TYPE;
571 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
572 !(SectionType == MachO::S_ZEROFILL ||
573 SectionType == MachO::S_GB_ZEROFILL);
576 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
577 uint32_t Flags = getSectionFlags(this, Sec);
578 unsigned SectionType = Flags & MachO::SECTION_TYPE;
579 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
580 (SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL);
584 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
585 // FIXME: Unimplemented.
589 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
590 DataRefImpl Symb) const {
592 this->getSymbolType(Symb, ST);
593 if (ST == SymbolRef::ST_Unknown)
596 uint64_t SectBegin = getSectionAddress(Sec);
597 uint64_t SectEnd = getSectionSize(Sec);
598 SectEnd += SectBegin;
601 getSymbolAddress(Symb, SymAddr);
602 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
605 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
609 return relocation_iterator(RelocationRef(Ret, this));
613 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
616 MachO::section_64 Sect = getSection64(Sec);
619 MachO::section Sect = getSection(Sec);
626 return relocation_iterator(RelocationRef(Ret, this));
629 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
633 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
634 uint64_t &Res) const {
636 getRelocationOffset(Rel, Offset);
640 uint64_t SecAddress = getSectionAddress(Sec);
641 Res = SecAddress + Offset;
642 return object_error::success;
645 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
646 uint64_t &Res) const {
647 assert(getHeader().filetype == MachO::MH_OBJECT &&
648 "Only implemented for MH_OBJECT");
649 MachO::any_relocation_info RE = getRelocation(Rel);
650 Res = getAnyRelocationAddress(RE);
651 return object_error::success;
655 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
656 MachO::any_relocation_info RE = getRelocation(Rel);
657 if (isRelocationScattered(RE))
660 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
661 bool isExtern = getPlainRelocationExternal(RE);
665 MachO::symtab_command S = getSymtabLoadCommand();
666 unsigned SymbolTableEntrySize = is64Bit() ?
667 sizeof(MachO::nlist_64) :
668 sizeof(MachO::nlist);
669 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
671 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
672 return symbol_iterator(SymbolRef(Sym, this));
675 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
676 uint64_t &Res) const {
677 MachO::any_relocation_info RE = getRelocation(Rel);
678 Res = getAnyRelocationType(RE);
679 return object_error::success;
683 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
684 SmallVectorImpl<char> &Result) const {
687 getRelocationType(Rel, RType);
689 unsigned Arch = this->getArch();
693 static const char *const Table[] = {
694 "GENERIC_RELOC_VANILLA",
695 "GENERIC_RELOC_PAIR",
696 "GENERIC_RELOC_SECTDIFF",
697 "GENERIC_RELOC_PB_LA_PTR",
698 "GENERIC_RELOC_LOCAL_SECTDIFF",
699 "GENERIC_RELOC_TLV" };
707 case Triple::x86_64: {
708 static const char *const Table[] = {
709 "X86_64_RELOC_UNSIGNED",
710 "X86_64_RELOC_SIGNED",
711 "X86_64_RELOC_BRANCH",
712 "X86_64_RELOC_GOT_LOAD",
714 "X86_64_RELOC_SUBTRACTOR",
715 "X86_64_RELOC_SIGNED_1",
716 "X86_64_RELOC_SIGNED_2",
717 "X86_64_RELOC_SIGNED_4",
718 "X86_64_RELOC_TLV" };
727 static const char *const Table[] = {
730 "ARM_RELOC_SECTDIFF",
731 "ARM_RELOC_LOCAL_SECTDIFF",
732 "ARM_RELOC_PB_LA_PTR",
734 "ARM_THUMB_RELOC_BR22",
735 "ARM_THUMB_32BIT_BRANCH",
737 "ARM_RELOC_HALF_SECTDIFF" };
745 case Triple::aarch64: {
746 static const char *const Table[] = {
747 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
748 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
749 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
750 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
751 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
755 if (RType >= array_lengthof(Table))
762 static const char *const Table[] = {
771 "PPC_RELOC_SECTDIFF",
772 "PPC_RELOC_PB_LA_PTR",
773 "PPC_RELOC_HI16_SECTDIFF",
774 "PPC_RELOC_LO16_SECTDIFF",
775 "PPC_RELOC_HA16_SECTDIFF",
777 "PPC_RELOC_LO14_SECTDIFF",
778 "PPC_RELOC_LOCAL_SECTDIFF" };
786 case Triple::UnknownArch:
790 Result.append(res.begin(), res.end());
791 return object_error::success;
795 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
796 SmallVectorImpl<char> &Result) const {
797 MachO::any_relocation_info RE = getRelocation(Rel);
799 unsigned Arch = this->getArch();
802 raw_string_ostream fmt(fmtbuf);
803 unsigned Type = this->getAnyRelocationType(RE);
804 bool IsPCRel = this->getAnyRelocationPCRel(RE);
806 // Determine any addends that should be displayed with the relocation.
807 // These require decoding the relocation type, which is triple-specific.
809 // X86_64 has entirely custom relocation types.
810 if (Arch == Triple::x86_64) {
811 bool isPCRel = getAnyRelocationPCRel(RE);
814 case MachO::X86_64_RELOC_GOT_LOAD:
815 case MachO::X86_64_RELOC_GOT: {
816 printRelocationTargetName(this, RE, fmt);
818 if (isPCRel) fmt << "PCREL";
821 case MachO::X86_64_RELOC_SUBTRACTOR: {
822 DataRefImpl RelNext = Rel;
823 moveRelocationNext(RelNext);
824 MachO::any_relocation_info RENext = getRelocation(RelNext);
826 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
827 // X86_64_RELOC_UNSIGNED.
828 // NOTE: Scattered relocations don't exist on x86_64.
829 unsigned RType = getAnyRelocationType(RENext);
830 if (RType != MachO::X86_64_RELOC_UNSIGNED)
831 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
832 "X86_64_RELOC_SUBTRACTOR.");
834 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
835 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
836 printRelocationTargetName(this, RENext, fmt);
838 printRelocationTargetName(this, RE, fmt);
841 case MachO::X86_64_RELOC_TLV:
842 printRelocationTargetName(this, RE, fmt);
844 if (isPCRel) fmt << "P";
846 case MachO::X86_64_RELOC_SIGNED_1:
847 printRelocationTargetName(this, RE, fmt);
850 case MachO::X86_64_RELOC_SIGNED_2:
851 printRelocationTargetName(this, RE, fmt);
854 case MachO::X86_64_RELOC_SIGNED_4:
855 printRelocationTargetName(this, RE, fmt);
859 printRelocationTargetName(this, RE, fmt);
862 // X86 and ARM share some relocation types in common.
863 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
864 Arch == Triple::ppc) {
865 // Generic relocation types...
867 case MachO::GENERIC_RELOC_PAIR: // prints no info
868 return object_error::success;
869 case MachO::GENERIC_RELOC_SECTDIFF: {
870 DataRefImpl RelNext = Rel;
871 moveRelocationNext(RelNext);
872 MachO::any_relocation_info RENext = getRelocation(RelNext);
874 // X86 sect diff's must be followed by a relocation of type
875 // GENERIC_RELOC_PAIR.
876 unsigned RType = getAnyRelocationType(RENext);
878 if (RType != MachO::GENERIC_RELOC_PAIR)
879 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
880 "GENERIC_RELOC_SECTDIFF.");
882 printRelocationTargetName(this, RE, fmt);
884 printRelocationTargetName(this, RENext, fmt);
889 if (Arch == Triple::x86 || Arch == Triple::ppc) {
891 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
892 DataRefImpl RelNext = Rel;
893 moveRelocationNext(RelNext);
894 MachO::any_relocation_info RENext = getRelocation(RelNext);
896 // X86 sect diff's must be followed by a relocation of type
897 // GENERIC_RELOC_PAIR.
898 unsigned RType = getAnyRelocationType(RENext);
899 if (RType != MachO::GENERIC_RELOC_PAIR)
900 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
901 "GENERIC_RELOC_LOCAL_SECTDIFF.");
903 printRelocationTargetName(this, RE, fmt);
905 printRelocationTargetName(this, RENext, fmt);
908 case MachO::GENERIC_RELOC_TLV: {
909 printRelocationTargetName(this, RE, fmt);
911 if (IsPCRel) fmt << "P";
915 printRelocationTargetName(this, RE, fmt);
917 } else { // ARM-specific relocations
919 case MachO::ARM_RELOC_HALF:
920 case MachO::ARM_RELOC_HALF_SECTDIFF: {
921 // Half relocations steal a bit from the length field to encode
922 // whether this is an upper16 or a lower16 relocation.
923 bool isUpper = getAnyRelocationLength(RE) >> 1;
929 printRelocationTargetName(this, RE, fmt);
931 DataRefImpl RelNext = Rel;
932 moveRelocationNext(RelNext);
933 MachO::any_relocation_info RENext = getRelocation(RelNext);
935 // ARM half relocs must be followed by a relocation of type
937 unsigned RType = getAnyRelocationType(RENext);
938 if (RType != MachO::ARM_RELOC_PAIR)
939 report_fatal_error("Expected ARM_RELOC_PAIR after "
942 // NOTE: The half of the target virtual address is stashed in the
943 // address field of the secondary relocation, but we can't reverse
944 // engineer the constant offset from it without decoding the movw/movt
945 // instruction to find the other half in its immediate field.
947 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
948 // symbol/section pointer of the follow-on relocation.
949 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
951 printRelocationTargetName(this, RENext, fmt);
958 printRelocationTargetName(this, RE, fmt);
963 printRelocationTargetName(this, RE, fmt);
966 Result.append(fmtbuf.begin(), fmtbuf.end());
967 return object_error::success;
970 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
971 bool &Result) const {
972 unsigned Arch = getArch();
974 getRelocationType(Rel, Type);
978 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
980 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
981 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
982 } else if (Arch == Triple::x86_64) {
983 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
984 // an X86_64_RELOC_SUBTRACTOR.
985 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
986 DataRefImpl RelPrev = Rel;
989 getRelocationType(RelPrev, PrevType);
990 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
995 return object_error::success;
999 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1000 // guess on what the short name is. Then name is returned as a substring of the
1001 // StringRef Name passed in. The name of the dynamic library is recognized as
1002 // a framework if it has one of the two following forms:
1003 // Foo.framework/Versions/A/Foo
1004 // Foo.framework/Foo
1005 // Where A and Foo can be any string. And may contain a trailing suffix
1006 // starting with an underbar. If the Name is recognized as a framework then
1007 // isFramework is set to true else it is set to false. If the Name has a
1008 // suffix then Suffix is set to the substring in Name that contains the suffix
1009 // else it is set to a NULL StringRef.
1011 // The Name of the dynamic library is recognized as a library name if it has
1012 // one of the two following forms:
1015 // The library may have a suffix trailing the name Foo of the form:
1016 // libFoo_profile.A.dylib
1017 // libFoo_profile.dylib
1019 // The Name of the dynamic library is also recognized as a library name if it
1020 // has the following form:
1023 // If the Name of the dynamic library is none of the forms above then a NULL
1024 // StringRef is returned.
1026 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1028 StringRef &Suffix) {
1029 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1030 size_t a, b, c, d, Idx;
1032 isFramework = false;
1033 Suffix = StringRef();
1035 // Pull off the last component and make Foo point to it
1036 a = Name.rfind('/');
1037 if (a == Name.npos || a == 0)
1039 Foo = Name.slice(a+1, Name.npos);
1041 // Look for a suffix starting with a '_'
1042 Idx = Foo.rfind('_');
1043 if (Idx != Foo.npos && Foo.size() >= 2) {
1044 Suffix = Foo.slice(Idx, Foo.npos);
1045 Foo = Foo.slice(0, Idx);
1048 // First look for the form Foo.framework/Foo
1049 b = Name.rfind('/', a);
1054 F = Name.slice(Idx, Idx + Foo.size());
1055 DotFramework = Name.slice(Idx + Foo.size(),
1056 Idx + Foo.size() + sizeof(".framework/")-1);
1057 if (F == Foo && DotFramework == ".framework/") {
1062 // Next look for the form Foo.framework/Versions/A/Foo
1065 c = Name.rfind('/', b);
1066 if (c == Name.npos || c == 0)
1068 V = Name.slice(c+1, Name.npos);
1069 if (!V.startswith("Versions/"))
1071 d = Name.rfind('/', c);
1076 F = Name.slice(Idx, Idx + Foo.size());
1077 DotFramework = Name.slice(Idx + Foo.size(),
1078 Idx + Foo.size() + sizeof(".framework/")-1);
1079 if (F == Foo && DotFramework == ".framework/") {
1085 // pull off the suffix after the "." and make a point to it
1086 a = Name.rfind('.');
1087 if (a == Name.npos || a == 0)
1089 Dylib = Name.slice(a, Name.npos);
1090 if (Dylib != ".dylib")
1093 // First pull off the version letter for the form Foo.A.dylib if any.
1095 Dot = Name.slice(a-2, a-1);
1100 b = Name.rfind('/', a);
1105 // ignore any suffix after an underbar like Foo_profile.A.dylib
1106 Idx = Name.find('_', b);
1107 if (Idx != Name.npos && Idx != b) {
1108 Lib = Name.slice(b, Idx);
1109 Suffix = Name.slice(Idx, a);
1112 Lib = Name.slice(b, a);
1113 // There are incorrect library names of the form:
1114 // libATS.A_profile.dylib so check for these.
1115 if (Lib.size() >= 3) {
1116 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1118 Lib = Lib.slice(0, Lib.size()-2);
1123 Qtx = Name.slice(a, Name.npos);
1126 b = Name.rfind('/', a);
1128 Lib = Name.slice(0, a);
1130 Lib = Name.slice(b+1, a);
1131 // There are library names of the form: QT.A.qtx so check for these.
1132 if (Lib.size() >= 3) {
1133 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1135 Lib = Lib.slice(0, Lib.size()-2);
1140 // getLibraryShortNameByIndex() is used to get the short name of the library
1141 // for an undefined symbol in a linked Mach-O binary that was linked with the
1142 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1143 // It is passed the index (0 - based) of the library as translated from
1144 // GET_LIBRARY_ORDINAL (1 - based).
1145 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1146 StringRef &Res) const {
1147 if (Index >= Libraries.size())
1148 return object_error::parse_failed;
1150 // If the cache of LibrariesShortNames is not built up do that first for
1151 // all the Libraries.
1152 if (LibrariesShortNames.size() == 0) {
1153 for (unsigned i = 0; i < Libraries.size(); i++) {
1154 MachO::dylib_command D =
1155 getStruct<MachO::dylib_command>(this, Libraries[i]);
1156 if (D.dylib.name >= D.cmdsize)
1157 return object_error::parse_failed;
1158 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1159 StringRef Name = StringRef(P);
1160 if (D.dylib.name+Name.size() >= D.cmdsize)
1161 return object_error::parse_failed;
1164 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1165 if (shortName.empty())
1166 LibrariesShortNames.push_back(Name);
1168 LibrariesShortNames.push_back(shortName);
1172 Res = LibrariesShortNames[Index];
1173 return object_error::success;
1176 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1177 return getSymbolByIndex(0);
1180 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1183 return basic_symbol_iterator(SymbolRef(DRI, this));
1185 MachO::symtab_command Symtab = getSymtabLoadCommand();
1186 unsigned SymbolTableEntrySize = is64Bit() ?
1187 sizeof(MachO::nlist_64) :
1188 sizeof(MachO::nlist);
1189 unsigned Offset = Symtab.symoff +
1190 Symtab.nsyms * SymbolTableEntrySize;
1191 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1192 return basic_symbol_iterator(SymbolRef(DRI, this));
1195 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1198 return basic_symbol_iterator(SymbolRef(DRI, this));
1200 MachO::symtab_command Symtab = getSymtabLoadCommand();
1201 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1202 unsigned SymbolTableEntrySize =
1203 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1204 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1205 DRI.p += Index * SymbolTableEntrySize;
1206 return basic_symbol_iterator(SymbolRef(DRI, this));
1209 section_iterator MachOObjectFile::section_begin() const {
1211 return section_iterator(SectionRef(DRI, this));
1214 section_iterator MachOObjectFile::section_end() const {
1216 DRI.d.a = Sections.size();
1217 return section_iterator(SectionRef(DRI, this));
1220 uint8_t MachOObjectFile::getBytesInAddress() const {
1221 return is64Bit() ? 8 : 4;
1224 StringRef MachOObjectFile::getFileFormatName() const {
1225 unsigned CPUType = getCPUType(this);
1228 case llvm::MachO::CPU_TYPE_I386:
1229 return "Mach-O 32-bit i386";
1230 case llvm::MachO::CPU_TYPE_ARM:
1231 return "Mach-O arm";
1232 case llvm::MachO::CPU_TYPE_POWERPC:
1233 return "Mach-O 32-bit ppc";
1235 return "Mach-O 32-bit unknown";
1240 case llvm::MachO::CPU_TYPE_X86_64:
1241 return "Mach-O 64-bit x86-64";
1242 case llvm::MachO::CPU_TYPE_ARM64:
1243 return "Mach-O arm64";
1244 case llvm::MachO::CPU_TYPE_POWERPC64:
1245 return "Mach-O 64-bit ppc64";
1247 return "Mach-O 64-bit unknown";
1251 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1253 case llvm::MachO::CPU_TYPE_I386:
1255 case llvm::MachO::CPU_TYPE_X86_64:
1256 return Triple::x86_64;
1257 case llvm::MachO::CPU_TYPE_ARM:
1259 case llvm::MachO::CPU_TYPE_ARM64:
1260 return Triple::aarch64;
1261 case llvm::MachO::CPU_TYPE_POWERPC:
1263 case llvm::MachO::CPU_TYPE_POWERPC64:
1264 return Triple::ppc64;
1266 return Triple::UnknownArch;
1270 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1271 const char **McpuDefault) {
1273 *McpuDefault = nullptr;
1276 case MachO::CPU_TYPE_I386:
1277 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1278 case MachO::CPU_SUBTYPE_I386_ALL:
1279 return Triple("i386-apple-darwin");
1283 case MachO::CPU_TYPE_X86_64:
1284 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1285 case MachO::CPU_SUBTYPE_X86_64_ALL:
1286 return Triple("x86_64-apple-darwin");
1287 case MachO::CPU_SUBTYPE_X86_64_H:
1288 return Triple("x86_64h-apple-darwin");
1292 case MachO::CPU_TYPE_ARM:
1293 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1294 case MachO::CPU_SUBTYPE_ARM_V4T:
1295 return Triple("armv4t-apple-darwin");
1296 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1297 return Triple("armv5e-apple-darwin");
1298 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1299 return Triple("xscale-apple-darwin");
1300 case MachO::CPU_SUBTYPE_ARM_V6:
1301 return Triple("armv6-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_V6M:
1304 *McpuDefault = "cortex-m0";
1305 return Triple("armv6m-apple-darwin");
1306 case MachO::CPU_SUBTYPE_ARM_V7:
1307 return Triple("armv7-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_V7EM:
1310 *McpuDefault = "cortex-m4";
1311 return Triple("armv7em-apple-darwin");
1312 case MachO::CPU_SUBTYPE_ARM_V7K:
1313 return Triple("armv7k-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V7M:
1316 *McpuDefault = "cortex-m3";
1317 return Triple("armv7m-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V7S:
1319 return Triple("armv7s-apple-darwin");
1323 case MachO::CPU_TYPE_ARM64:
1324 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1325 case MachO::CPU_SUBTYPE_ARM64_ALL:
1326 return Triple("arm64-apple-darwin");
1330 case MachO::CPU_TYPE_POWERPC:
1331 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1332 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1333 return Triple("ppc-apple-darwin");
1337 case MachO::CPU_TYPE_POWERPC64:
1338 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1339 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1340 return Triple("ppc64-apple-darwin");
1349 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1350 const char **McpuDefault) {
1352 *McpuDefault = nullptr;
1355 case MachO::CPU_TYPE_ARM:
1356 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1357 case MachO::CPU_SUBTYPE_ARM_V4T:
1358 return Triple("thumbv4t-apple-darwin");
1359 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1360 return Triple("thumbv5e-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1362 return Triple("xscale-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_V6:
1364 return Triple("thumbv6-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_V6M:
1367 *McpuDefault = "cortex-m0";
1368 return Triple("thumbv6m-apple-darwin");
1369 case MachO::CPU_SUBTYPE_ARM_V7:
1370 return Triple("thumbv7-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V7EM:
1373 *McpuDefault = "cortex-m4";
1374 return Triple("thumbv7em-apple-darwin");
1375 case MachO::CPU_SUBTYPE_ARM_V7K:
1376 return Triple("thumbv7k-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V7M:
1379 *McpuDefault = "cortex-m3";
1380 return Triple("thumbv7m-apple-darwin");
1381 case MachO::CPU_SUBTYPE_ARM_V7S:
1382 return Triple("thumbv7s-apple-darwin");
1391 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1392 const char **McpuDefault,
1393 Triple *ThumbTriple) {
1394 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1395 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1400 Triple MachOObjectFile::getHostArch() {
1401 return Triple(sys::getDefaultTargetTriple());
1404 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1405 return StringSwitch<bool>(ArchFlag)
1407 .Case("x86_64", true)
1408 .Case("x86_64h", true)
1409 .Case("armv4t", true)
1411 .Case("armv5e", true)
1412 .Case("armv6", true)
1413 .Case("armv6m", true)
1414 .Case("armv7em", true)
1415 .Case("armv7k", true)
1416 .Case("armv7m", true)
1417 .Case("armv7s", true)
1418 .Case("arm64", true)
1420 .Case("ppc64", true)
1424 unsigned MachOObjectFile::getArch() const {
1425 return getArch(getCPUType(this));
1428 Triple MachOObjectFile::getArch(const char **McpuDefault,
1429 Triple *ThumbTriple) const {
1432 MachO::mach_header_64 H_64;
1433 H_64 = getHeader64();
1434 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1435 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1438 MachO::mach_header H;
1440 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1441 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1447 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1450 return section_rel_begin(DRI);
1453 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1456 return section_rel_end(DRI);
1459 dice_iterator MachOObjectFile::begin_dices() const {
1461 if (!DataInCodeLoadCmd)
1462 return dice_iterator(DiceRef(DRI, this));
1464 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1465 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1466 return dice_iterator(DiceRef(DRI, this));
1469 dice_iterator MachOObjectFile::end_dices() const {
1471 if (!DataInCodeLoadCmd)
1472 return dice_iterator(DiceRef(DRI, this));
1474 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1475 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1476 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1477 return dice_iterator(DiceRef(DRI, this));
1480 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1481 : Trie(T), Malformed(false), Done(false) { }
1483 void ExportEntry::moveToFirst() {
1485 pushDownUntilBottom();
1488 void ExportEntry::moveToEnd() {
1493 bool ExportEntry::operator==(const ExportEntry &Other) const {
1494 // Common case, one at end, other iterating from begin.
1495 if (Done || Other.Done)
1496 return (Done == Other.Done);
1497 // Not equal if different stack sizes.
1498 if (Stack.size() != Other.Stack.size())
1500 // Not equal if different cumulative strings.
1501 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1503 // Equal if all nodes in both stacks match.
1504 for (unsigned i=0; i < Stack.size(); ++i) {
1505 if (Stack[i].Start != Other.Stack[i].Start)
1511 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1513 uint64_t Result = decodeULEB128(Ptr, &Count);
1515 if (Ptr > Trie.end()) {
1522 StringRef ExportEntry::name() const {
1523 return CumulativeString.str();
1526 uint64_t ExportEntry::flags() const {
1527 return Stack.back().Flags;
1530 uint64_t ExportEntry::address() const {
1531 return Stack.back().Address;
1534 uint64_t ExportEntry::other() const {
1535 return Stack.back().Other;
1538 StringRef ExportEntry::otherName() const {
1539 const char* ImportName = Stack.back().ImportName;
1541 return StringRef(ImportName);
1545 uint32_t ExportEntry::nodeOffset() const {
1546 return Stack.back().Start - Trie.begin();
1549 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1550 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1551 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1552 ParentStringLength(0), IsExportNode(false) {
1555 void ExportEntry::pushNode(uint64_t offset) {
1556 const uint8_t *Ptr = Trie.begin() + offset;
1557 NodeState State(Ptr);
1558 uint64_t ExportInfoSize = readULEB128(State.Current);
1559 State.IsExportNode = (ExportInfoSize != 0);
1560 const uint8_t* Children = State.Current + ExportInfoSize;
1561 if (State.IsExportNode) {
1562 State.Flags = readULEB128(State.Current);
1563 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1565 State.Other = readULEB128(State.Current); // dylib ordinal
1566 State.ImportName = reinterpret_cast<const char*>(State.Current);
1568 State.Address = readULEB128(State.Current);
1569 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1570 State.Other = readULEB128(State.Current);
1573 State.ChildCount = *Children;
1574 State.Current = Children + 1;
1575 State.NextChildIndex = 0;
1576 State.ParentStringLength = CumulativeString.size();
1577 Stack.push_back(State);
1580 void ExportEntry::pushDownUntilBottom() {
1581 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1582 NodeState &Top = Stack.back();
1583 CumulativeString.resize(Top.ParentStringLength);
1584 for (;*Top.Current != 0; Top.Current++) {
1585 char C = *Top.Current;
1586 CumulativeString.push_back(C);
1589 uint64_t childNodeIndex = readULEB128(Top.Current);
1590 Top.NextChildIndex += 1;
1591 pushNode(childNodeIndex);
1593 if (!Stack.back().IsExportNode) {
1599 // We have a trie data structure and need a way to walk it that is compatible
1600 // with the C++ iterator model. The solution is a non-recursive depth first
1601 // traversal where the iterator contains a stack of parent nodes along with a
1602 // string that is the accumulation of all edge strings along the parent chain
1605 // There is one "export" node for each exported symbol. But because some
1606 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1607 // node may have child nodes too.
1609 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1610 // child until hitting a node with no children (which is an export node or
1611 // else the trie is malformed). On the way down, each node is pushed on the
1612 // stack ivar. If there is no more ways down, it pops up one and tries to go
1613 // down a sibling path until a childless node is reached.
1614 void ExportEntry::moveNext() {
1615 if (Stack.empty() || !Stack.back().IsExportNode) {
1622 while (!Stack.empty()) {
1623 NodeState &Top = Stack.back();
1624 if (Top.NextChildIndex < Top.ChildCount) {
1625 pushDownUntilBottom();
1626 // Now at the next export node.
1629 if (Top.IsExportNode) {
1630 // This node has no children but is itself an export node.
1631 CumulativeString.resize(Top.ParentStringLength);
1640 iterator_range<export_iterator>
1641 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1642 ExportEntry Start(Trie);
1643 Start.moveToFirst();
1645 ExportEntry Finish(Trie);
1648 return iterator_range<export_iterator>(export_iterator(Start),
1649 export_iterator(Finish));
1652 iterator_range<export_iterator> MachOObjectFile::exports() const {
1653 return exports(getDyldInfoExportsTrie());
1657 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1658 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1659 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1660 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1662 void MachORebaseEntry::moveToFirst() {
1663 Ptr = Opcodes.begin();
1667 void MachORebaseEntry::moveToEnd() {
1668 Ptr = Opcodes.end();
1669 RemainingLoopCount = 0;
1673 void MachORebaseEntry::moveNext() {
1674 // If in the middle of some loop, move to next rebasing in loop.
1675 SegmentOffset += AdvanceAmount;
1676 if (RemainingLoopCount) {
1677 --RemainingLoopCount;
1680 if (Ptr == Opcodes.end()) {
1685 while (More && !Malformed) {
1686 // Parse next opcode and set up next loop.
1687 uint8_t Byte = *Ptr++;
1688 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1689 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1691 case MachO::REBASE_OPCODE_DONE:
1695 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1697 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1698 RebaseType = ImmValue;
1701 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1702 << "RebaseType=" << (int) RebaseType << "\n");
1704 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1705 SegmentIndex = ImmValue;
1706 SegmentOffset = readULEB128();
1709 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1710 << "SegmentIndex=" << SegmentIndex << ", "
1711 << format("SegmentOffset=0x%06X", SegmentOffset)
1714 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1715 SegmentOffset += readULEB128();
1716 DEBUG_WITH_TYPE("mach-o-rebase",
1717 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1718 << format("SegmentOffset=0x%06X",
1719 SegmentOffset) << "\n");
1721 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1722 SegmentOffset += ImmValue * PointerSize;
1723 DEBUG_WITH_TYPE("mach-o-rebase",
1724 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1725 << format("SegmentOffset=0x%06X",
1726 SegmentOffset) << "\n");
1728 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1729 AdvanceAmount = PointerSize;
1730 RemainingLoopCount = ImmValue - 1;
1733 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1734 << format("SegmentOffset=0x%06X", SegmentOffset)
1735 << ", AdvanceAmount=" << AdvanceAmount
1736 << ", RemainingLoopCount=" << RemainingLoopCount
1739 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1740 AdvanceAmount = PointerSize;
1741 RemainingLoopCount = readULEB128() - 1;
1744 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1745 << format("SegmentOffset=0x%06X", SegmentOffset)
1746 << ", AdvanceAmount=" << AdvanceAmount
1747 << ", RemainingLoopCount=" << RemainingLoopCount
1750 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1751 AdvanceAmount = readULEB128() + PointerSize;
1752 RemainingLoopCount = 0;
1755 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1756 << format("SegmentOffset=0x%06X", SegmentOffset)
1757 << ", AdvanceAmount=" << AdvanceAmount
1758 << ", RemainingLoopCount=" << RemainingLoopCount
1761 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1762 RemainingLoopCount = readULEB128() - 1;
1763 AdvanceAmount = readULEB128() + PointerSize;
1766 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1767 << format("SegmentOffset=0x%06X", SegmentOffset)
1768 << ", AdvanceAmount=" << AdvanceAmount
1769 << ", RemainingLoopCount=" << RemainingLoopCount
1778 uint64_t MachORebaseEntry::readULEB128() {
1780 uint64_t Result = decodeULEB128(Ptr, &Count);
1782 if (Ptr > Opcodes.end()) {
1783 Ptr = Opcodes.end();
1789 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1791 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1793 StringRef MachORebaseEntry::typeName() const {
1794 switch (RebaseType) {
1795 case MachO::REBASE_TYPE_POINTER:
1797 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1798 return "text abs32";
1799 case MachO::REBASE_TYPE_TEXT_PCREL32:
1800 return "text rel32";
1805 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1806 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1807 return (Ptr == Other.Ptr) &&
1808 (RemainingLoopCount == Other.RemainingLoopCount) &&
1809 (Done == Other.Done);
1812 iterator_range<rebase_iterator>
1813 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1814 MachORebaseEntry Start(Opcodes, is64);
1815 Start.moveToFirst();
1817 MachORebaseEntry Finish(Opcodes, is64);
1820 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1821 rebase_iterator(Finish));
1824 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1825 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1829 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1831 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1832 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1833 BindType(0), PointerSize(is64Bit ? 8 : 4),
1834 TableKind(BK), Malformed(false), Done(false) {}
1836 void MachOBindEntry::moveToFirst() {
1837 Ptr = Opcodes.begin();
1841 void MachOBindEntry::moveToEnd() {
1842 Ptr = Opcodes.end();
1843 RemainingLoopCount = 0;
1847 void MachOBindEntry::moveNext() {
1848 // If in the middle of some loop, move to next binding in loop.
1849 SegmentOffset += AdvanceAmount;
1850 if (RemainingLoopCount) {
1851 --RemainingLoopCount;
1854 if (Ptr == Opcodes.end()) {
1859 while (More && !Malformed) {
1860 // Parse next opcode and set up next loop.
1861 uint8_t Byte = *Ptr++;
1862 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1863 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1864 int8_t SignExtended;
1865 const uint8_t *SymStart;
1867 case MachO::BIND_OPCODE_DONE:
1868 if (TableKind == Kind::Lazy) {
1869 // Lazying bindings have a DONE opcode between entries. Need to ignore
1870 // it to advance to next entry. But need not if this is last entry.
1871 bool NotLastEntry = false;
1872 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1874 NotLastEntry = true;
1883 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1885 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1889 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1890 << "Ordinal=" << Ordinal << "\n");
1892 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1893 Ordinal = readULEB128();
1896 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1897 << "Ordinal=" << Ordinal << "\n");
1899 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1901 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1902 Ordinal = SignExtended;
1907 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1908 << "Ordinal=" << Ordinal << "\n");
1910 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1916 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1921 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1922 << "SymbolName=" << SymbolName << "\n");
1923 if (TableKind == Kind::Weak) {
1924 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1928 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1929 BindType = ImmValue;
1932 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1933 << "BindType=" << (int)BindType << "\n");
1935 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1936 Addend = readSLEB128();
1937 if (TableKind == Kind::Lazy)
1941 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1942 << "Addend=" << Addend << "\n");
1944 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1945 SegmentIndex = ImmValue;
1946 SegmentOffset = readULEB128();
1949 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1950 << "SegmentIndex=" << SegmentIndex << ", "
1951 << format("SegmentOffset=0x%06X", SegmentOffset)
1954 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1955 SegmentOffset += readULEB128();
1956 DEBUG_WITH_TYPE("mach-o-bind",
1957 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1958 << format("SegmentOffset=0x%06X",
1959 SegmentOffset) << "\n");
1961 case MachO::BIND_OPCODE_DO_BIND:
1962 AdvanceAmount = PointerSize;
1963 RemainingLoopCount = 0;
1964 DEBUG_WITH_TYPE("mach-o-bind",
1965 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1966 << format("SegmentOffset=0x%06X",
1967 SegmentOffset) << "\n");
1969 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1970 AdvanceAmount = readULEB128() + PointerSize;
1971 RemainingLoopCount = 0;
1972 if (TableKind == Kind::Lazy)
1976 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1977 << format("SegmentOffset=0x%06X", SegmentOffset)
1978 << ", AdvanceAmount=" << AdvanceAmount
1979 << ", RemainingLoopCount=" << RemainingLoopCount
1982 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1983 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1984 RemainingLoopCount = 0;
1985 if (TableKind == Kind::Lazy)
1987 DEBUG_WITH_TYPE("mach-o-bind",
1989 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1990 << format("SegmentOffset=0x%06X",
1991 SegmentOffset) << "\n");
1993 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1994 RemainingLoopCount = readULEB128() - 1;
1995 AdvanceAmount = readULEB128() + PointerSize;
1996 if (TableKind == Kind::Lazy)
2000 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2001 << format("SegmentOffset=0x%06X", SegmentOffset)
2002 << ", AdvanceAmount=" << AdvanceAmount
2003 << ", RemainingLoopCount=" << RemainingLoopCount
2012 uint64_t MachOBindEntry::readULEB128() {
2014 uint64_t Result = decodeULEB128(Ptr, &Count);
2016 if (Ptr > Opcodes.end()) {
2017 Ptr = Opcodes.end();
2023 int64_t MachOBindEntry::readSLEB128() {
2025 int64_t Result = decodeSLEB128(Ptr, &Count);
2027 if (Ptr > Opcodes.end()) {
2028 Ptr = Opcodes.end();
2035 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2037 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2039 StringRef MachOBindEntry::typeName() const {
2041 case MachO::BIND_TYPE_POINTER:
2043 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2044 return "text abs32";
2045 case MachO::BIND_TYPE_TEXT_PCREL32:
2046 return "text rel32";
2051 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2053 int64_t MachOBindEntry::addend() const { return Addend; }
2055 uint32_t MachOBindEntry::flags() const { return Flags; }
2057 int MachOBindEntry::ordinal() const { return Ordinal; }
2059 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2060 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2061 return (Ptr == Other.Ptr) &&
2062 (RemainingLoopCount == Other.RemainingLoopCount) &&
2063 (Done == Other.Done);
2066 iterator_range<bind_iterator>
2067 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2068 MachOBindEntry::Kind BKind) {
2069 MachOBindEntry Start(Opcodes, is64, BKind);
2070 Start.moveToFirst();
2072 MachOBindEntry Finish(Opcodes, is64, BKind);
2075 return iterator_range<bind_iterator>(bind_iterator(Start),
2076 bind_iterator(Finish));
2079 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2080 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2081 MachOBindEntry::Kind::Regular);
2084 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2085 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2086 MachOBindEntry::Kind::Lazy);
2089 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2090 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2091 MachOBindEntry::Kind::Weak);
2095 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2096 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2097 return parseSegmentOrSectionName(Raw.data());
2101 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2102 const section_base *Base =
2103 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2104 return makeArrayRef(Base->sectname);
2108 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2109 const section_base *Base =
2110 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2111 return makeArrayRef(Base->segname);
2115 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2117 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2119 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2122 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2123 const MachO::any_relocation_info &RE) const {
2124 if (isLittleEndian())
2125 return RE.r_word1 & 0xffffff;
2126 return RE.r_word1 >> 8;
2129 bool MachOObjectFile::getPlainRelocationExternal(
2130 const MachO::any_relocation_info &RE) const {
2131 if (isLittleEndian())
2132 return (RE.r_word1 >> 27) & 1;
2133 return (RE.r_word1 >> 4) & 1;
2136 bool MachOObjectFile::getScatteredRelocationScattered(
2137 const MachO::any_relocation_info &RE) const {
2138 return RE.r_word0 >> 31;
2141 uint32_t MachOObjectFile::getScatteredRelocationValue(
2142 const MachO::any_relocation_info &RE) const {
2146 uint32_t MachOObjectFile::getScatteredRelocationType(
2147 const MachO::any_relocation_info &RE) const {
2148 return (RE.r_word0 >> 24) & 0xf;
2151 unsigned MachOObjectFile::getAnyRelocationAddress(
2152 const MachO::any_relocation_info &RE) const {
2153 if (isRelocationScattered(RE))
2154 return getScatteredRelocationAddress(RE);
2155 return getPlainRelocationAddress(RE);
2158 unsigned MachOObjectFile::getAnyRelocationPCRel(
2159 const MachO::any_relocation_info &RE) const {
2160 if (isRelocationScattered(RE))
2161 return getScatteredRelocationPCRel(this, RE);
2162 return getPlainRelocationPCRel(this, RE);
2165 unsigned MachOObjectFile::getAnyRelocationLength(
2166 const MachO::any_relocation_info &RE) const {
2167 if (isRelocationScattered(RE))
2168 return getScatteredRelocationLength(RE);
2169 return getPlainRelocationLength(this, RE);
2173 MachOObjectFile::getAnyRelocationType(
2174 const MachO::any_relocation_info &RE) const {
2175 if (isRelocationScattered(RE))
2176 return getScatteredRelocationType(RE);
2177 return getPlainRelocationType(this, RE);
2181 MachOObjectFile::getRelocationSection(
2182 const MachO::any_relocation_info &RE) const {
2183 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2184 return *section_end();
2185 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2188 return SectionRef(DRI, this);
2191 MachOObjectFile::LoadCommandInfo
2192 MachOObjectFile::getFirstLoadCommandInfo() const {
2193 MachOObjectFile::LoadCommandInfo Load;
2195 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2196 sizeof(MachO::mach_header);
2197 Load.Ptr = getPtr(this, HeaderSize);
2198 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2202 MachOObjectFile::LoadCommandInfo
2203 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2204 MachOObjectFile::LoadCommandInfo Next;
2205 Next.Ptr = L.Ptr + L.C.cmdsize;
2206 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2210 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2211 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2214 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2215 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2218 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2219 unsigned Index) const {
2220 const char *Sec = getSectionPtr(this, L, Index);
2221 return getStruct<MachO::section>(this, Sec);
2224 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2225 unsigned Index) const {
2226 const char *Sec = getSectionPtr(this, L, Index);
2227 return getStruct<MachO::section_64>(this, Sec);
2231 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2232 const char *P = reinterpret_cast<const char *>(DRI.p);
2233 return getStruct<MachO::nlist>(this, P);
2237 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2238 const char *P = reinterpret_cast<const char *>(DRI.p);
2239 return getStruct<MachO::nlist_64>(this, P);
2242 MachO::linkedit_data_command
2243 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2244 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2247 MachO::segment_command
2248 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2249 return getStruct<MachO::segment_command>(this, L.Ptr);
2252 MachO::segment_command_64
2253 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2254 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2257 MachO::linker_options_command
2258 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2259 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2262 MachO::version_min_command
2263 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2264 return getStruct<MachO::version_min_command>(this, L.Ptr);
2267 MachO::dylib_command
2268 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2269 return getStruct<MachO::dylib_command>(this, L.Ptr);
2272 MachO::dyld_info_command
2273 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2274 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2277 MachO::dylinker_command
2278 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2279 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2283 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2284 return getStruct<MachO::uuid_command>(this, L.Ptr);
2287 MachO::rpath_command
2288 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2289 return getStruct<MachO::rpath_command>(this, L.Ptr);
2292 MachO::source_version_command
2293 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2294 return getStruct<MachO::source_version_command>(this, L.Ptr);
2297 MachO::entry_point_command
2298 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2299 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2302 MachO::encryption_info_command
2303 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2304 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2308 MachO::any_relocation_info
2309 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2314 MachO::section_64 Sect = getSection64(Sec);
2315 Offset = Sect.reloff;
2317 MachO::section Sect = getSection(Sec);
2318 Offset = Sect.reloff;
2321 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2322 getPtr(this, Offset)) + Rel.d.b;
2323 return getStruct<MachO::any_relocation_info>(
2324 this, reinterpret_cast<const char *>(P));
2327 MachO::data_in_code_entry
2328 MachOObjectFile::getDice(DataRefImpl Rel) const {
2329 const char *P = reinterpret_cast<const char *>(Rel.p);
2330 return getStruct<MachO::data_in_code_entry>(this, P);
2333 MachO::mach_header MachOObjectFile::getHeader() const {
2334 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2337 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2338 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2341 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2342 const MachO::dysymtab_command &DLC,
2343 unsigned Index) const {
2344 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2345 return getStruct<uint32_t>(this, getPtr(this, Offset));
2348 MachO::data_in_code_entry
2349 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2350 unsigned Index) const {
2351 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2352 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2355 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2357 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2359 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2360 MachO::symtab_command Cmd;
2361 Cmd.cmd = MachO::LC_SYMTAB;
2362 Cmd.cmdsize = sizeof(MachO::symtab_command);
2370 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2371 if (DysymtabLoadCmd)
2372 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2374 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2375 MachO::dysymtab_command Cmd;
2376 Cmd.cmd = MachO::LC_DYSYMTAB;
2377 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2388 Cmd.extrefsymoff = 0;
2389 Cmd.nextrefsyms = 0;
2390 Cmd.indirectsymoff = 0;
2391 Cmd.nindirectsyms = 0;
2399 MachO::linkedit_data_command
2400 MachOObjectFile::getDataInCodeLoadCommand() const {
2401 if (DataInCodeLoadCmd)
2402 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2404 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2405 MachO::linkedit_data_command Cmd;
2406 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2407 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2413 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2414 if (!DyldInfoLoadCmd)
2415 return ArrayRef<uint8_t>();
2417 MachO::dyld_info_command DyldInfo
2418 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2419 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2420 getPtr(this, DyldInfo.rebase_off));
2421 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2424 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2425 if (!DyldInfoLoadCmd)
2426 return ArrayRef<uint8_t>();
2428 MachO::dyld_info_command DyldInfo
2429 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2430 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2431 getPtr(this, DyldInfo.bind_off));
2432 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2435 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2436 if (!DyldInfoLoadCmd)
2437 return ArrayRef<uint8_t>();
2439 MachO::dyld_info_command DyldInfo
2440 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2441 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2442 getPtr(this, DyldInfo.weak_bind_off));
2443 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2446 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2447 if (!DyldInfoLoadCmd)
2448 return ArrayRef<uint8_t>();
2450 MachO::dyld_info_command DyldInfo
2451 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2452 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2453 getPtr(this, DyldInfo.lazy_bind_off));
2454 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2457 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2458 if (!DyldInfoLoadCmd)
2459 return ArrayRef<uint8_t>();
2461 MachO::dyld_info_command DyldInfo
2462 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2463 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2464 getPtr(this, DyldInfo.export_off));
2465 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2468 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2470 return ArrayRef<uint8_t>();
2471 // Returning a pointer is fine as uuid doesn't need endian swapping.
2472 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2473 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2476 StringRef MachOObjectFile::getStringTableData() const {
2477 MachO::symtab_command S = getSymtabLoadCommand();
2478 return getData().substr(S.stroff, S.strsize);
2481 bool MachOObjectFile::is64Bit() const {
2482 return getType() == getMachOType(false, true) ||
2483 getType() == getMachOType(true, true);
2486 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2487 SmallVectorImpl<uint64_t> &Out) const {
2488 DataExtractor extractor(ObjectFile::getData(), true, 0);
2490 uint32_t offset = Index;
2492 while (uint64_t delta = extractor.getULEB128(&offset)) {
2494 Out.push_back(data);
2498 bool MachOObjectFile::isRelocatableObject() const {
2499 return getHeader().filetype == MachO::MH_OBJECT;
2502 ErrorOr<std::unique_ptr<MachOObjectFile>>
2503 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2504 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2506 std::unique_ptr<MachOObjectFile> Ret;
2507 if (Magic == "\xFE\xED\xFA\xCE")
2508 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2509 else if (Magic == "\xCE\xFA\xED\xFE")
2510 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2511 else if (Magic == "\xFE\xED\xFA\xCF")
2512 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2513 else if (Magic == "\xCF\xFA\xED\xFE")
2514 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2516 return object_error::parse_failed;
2520 return std::move(Ret);