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 assert(!SymtabLoadCmd && "Multiple symbol tables");
246 SymtabLoadCmd = Load.Ptr;
247 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
248 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
249 DysymtabLoadCmd = Load.Ptr;
250 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
251 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
252 DataInCodeLoadCmd = Load.Ptr;
253 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
254 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
255 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");
256 DyldInfoLoadCmd = Load.Ptr;
257 } else if (Load.C.cmd == MachO::LC_UUID) {
258 assert(!UuidLoadCmd && "Multiple UUID load commands");
259 UuidLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == SegmentLoadType) {
261 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
262 for (unsigned J = 0; J < NumSections; ++J) {
263 const char *Sec = getSectionPtr(this, Load, J);
264 Sections.push_back(Sec);
266 if (isPageZeroSegment(this, Load))
267 HasPageZeroSegment = true;
268 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
269 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
270 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
271 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
272 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
273 Libraries.push_back(Load.Ptr);
276 if (I == LoadCommandCount - 1)
279 Load = getNextLoadCommandInfo(Load);
283 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
284 unsigned SymbolTableEntrySize = is64Bit() ?
285 sizeof(MachO::nlist_64) :
286 sizeof(MachO::nlist);
287 Symb.p += SymbolTableEntrySize;
290 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
291 StringRef &Res) const {
292 StringRef StringTable = getStringTableData();
293 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
294 const char *Start = &StringTable.data()[Entry.n_strx];
295 Res = StringRef(Start);
296 return object_error::success;
299 // getIndirectName() returns the name of the alias'ed symbol who's string table
300 // index is in the n_value field.
301 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
302 StringRef &Res) const {
303 StringRef StringTable = getStringTableData();
306 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
307 NValue = Entry.n_value;
308 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
309 return object_error::parse_failed;
311 MachO::nlist Entry = getSymbolTableEntry(Symb);
312 NValue = Entry.n_value;
313 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
314 return object_error::parse_failed;
316 if (NValue >= StringTable.size())
317 return object_error::parse_failed;
318 const char *Start = &StringTable.data()[NValue];
319 Res = StringRef(Start);
320 return object_error::success;
323 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
324 uint64_t &Res) const {
326 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
327 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
329 Res = UnknownAddressOrSize;
333 MachO::nlist Entry = getSymbolTableEntry(Symb);
334 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
336 Res = UnknownAddressOrSize;
340 return object_error::success;
343 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
344 uint32_t &Result) const {
345 uint32_t flags = getSymbolFlags(DRI);
346 if (flags & SymbolRef::SF_Common) {
347 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
348 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
352 return object_error::success;
355 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
356 uint64_t &Result) const {
357 uint64_t BeginOffset;
358 uint64_t EndOffset = 0;
359 uint8_t SectionIndex;
361 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
363 getSymbolAddress(DRI, Value);
364 if (Value == UnknownAddressOrSize) {
365 Result = UnknownAddressOrSize;
366 return object_error::success;
371 SectionIndex = Entry.n_sect;
373 uint32_t flags = getSymbolFlags(DRI);
374 if (flags & SymbolRef::SF_Common)
377 Result = UnknownAddressOrSize;
378 return object_error::success;
380 // Unfortunately symbols are unsorted so we need to touch all
381 // symbols from load command
382 for (const SymbolRef &Symbol : symbols()) {
383 DataRefImpl DRI = Symbol.getRawDataRefImpl();
384 Entry = getSymbolTableEntryBase(this, DRI);
385 getSymbolAddress(DRI, Value);
386 if (Value == UnknownAddressOrSize)
388 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
389 if (!EndOffset || Value < EndOffset)
394 Sec.d.a = SectionIndex-1;
395 uint64_t Size = getSectionSize(Sec);
396 EndOffset = getSectionAddress(Sec);
399 Result = EndOffset - BeginOffset;
400 return object_error::success;
403 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
404 SymbolRef::Type &Res) const {
405 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
406 uint8_t n_type = Entry.n_type;
408 Res = SymbolRef::ST_Other;
410 // If this is a STAB debugging symbol, we can do nothing more.
411 if (n_type & MachO::N_STAB) {
412 Res = SymbolRef::ST_Debug;
413 return object_error::success;
416 switch (n_type & MachO::N_TYPE) {
418 Res = SymbolRef::ST_Unknown;
421 Res = SymbolRef::ST_Function;
424 return object_error::success;
427 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
428 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
430 uint8_t MachOType = Entry.n_type;
431 uint16_t MachOFlags = Entry.n_desc;
433 uint32_t Result = SymbolRef::SF_None;
435 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
436 Result |= SymbolRef::SF_Undefined;
438 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
439 Result |= SymbolRef::SF_Indirect;
441 if (MachOType & MachO::N_STAB)
442 Result |= SymbolRef::SF_FormatSpecific;
444 if (MachOType & MachO::N_EXT) {
445 Result |= SymbolRef::SF_Global;
446 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
448 getSymbolAddress(DRI, Value);
449 if (Value && Value != UnknownAddressOrSize)
450 Result |= SymbolRef::SF_Common;
454 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
455 Result |= SymbolRef::SF_Weak;
457 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
458 Result |= SymbolRef::SF_Thumb;
460 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
461 Result |= SymbolRef::SF_Absolute;
466 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
467 section_iterator &Res) const {
468 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
469 uint8_t index = Entry.n_sect;
476 Res = section_iterator(SectionRef(DRI, this));
479 return object_error::success;
482 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
486 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
487 StringRef &Result) const {
488 ArrayRef<char> Raw = getSectionRawName(Sec);
489 Result = parseSegmentOrSectionName(Raw.data());
490 return object_error::success;
493 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
495 return getSection64(Sec).addr;
496 return getSection(Sec).addr;
499 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
501 return getSection64(Sec).size;
502 return getSection(Sec).size;
505 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
506 StringRef &Res) const {
511 MachO::section_64 Sect = getSection64(Sec);
512 Offset = Sect.offset;
515 MachO::section Sect = getSection(Sec);
516 Offset = Sect.offset;
520 Res = this->getData().substr(Offset, Size);
521 return object_error::success;
524 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
527 MachO::section_64 Sect = getSection64(Sec);
530 MachO::section Sect = getSection(Sec);
534 return uint64_t(1) << Align;
537 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
538 uint32_t Flags = getSectionFlags(this, Sec);
539 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
542 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
543 uint32_t Flags = getSectionFlags(this, Sec);
544 unsigned SectionType = Flags & MachO::SECTION_TYPE;
545 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
546 !(SectionType == MachO::S_ZEROFILL ||
547 SectionType == MachO::S_GB_ZEROFILL);
550 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
551 uint32_t Flags = getSectionFlags(this, Sec);
552 unsigned SectionType = Flags & MachO::SECTION_TYPE;
553 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
554 (SectionType == MachO::S_ZEROFILL ||
555 SectionType == MachO::S_GB_ZEROFILL);
558 bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
559 // FIXME: Unimplemented.
563 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
564 // FIXME: Unimplemented.
568 bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
569 uint32_t Flags = getSectionFlags(this, Sec);
570 unsigned SectionType = Flags & MachO::SECTION_TYPE;
571 return SectionType == MachO::S_ZEROFILL ||
572 SectionType == MachO::S_GB_ZEROFILL;
575 bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
576 // Consider using the code from isSectionText to look for __const sections.
577 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
578 // to use section attributes to distinguish code from data.
580 // FIXME: Unimplemented.
584 bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
585 DataRefImpl Symb) const {
587 this->getSymbolType(Symb, ST);
588 if (ST == SymbolRef::ST_Unknown)
591 uint64_t SectBegin = getSectionAddress(Sec);
592 uint64_t SectEnd = getSectionSize(Sec);
593 SectEnd += SectBegin;
596 getSymbolAddress(Symb, SymAddr);
597 return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
600 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
604 return relocation_iterator(RelocationRef(Ret, this));
608 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
611 MachO::section_64 Sect = getSection64(Sec);
614 MachO::section Sect = getSection(Sec);
621 return relocation_iterator(RelocationRef(Ret, this));
624 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
628 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
629 uint64_t &Res) const {
631 getRelocationOffset(Rel, Offset);
635 uint64_t SecAddress = getSectionAddress(Sec);
636 Res = SecAddress + Offset;
637 return object_error::success;
640 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
641 uint64_t &Res) const {
642 assert(getHeader().filetype == MachO::MH_OBJECT &&
643 "Only implemented for MH_OBJECT");
644 MachO::any_relocation_info RE = getRelocation(Rel);
645 Res = getAnyRelocationAddress(RE);
646 return object_error::success;
650 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
651 MachO::any_relocation_info RE = getRelocation(Rel);
652 if (isRelocationScattered(RE))
655 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
656 bool isExtern = getPlainRelocationExternal(RE);
660 MachO::symtab_command S = getSymtabLoadCommand();
661 unsigned SymbolTableEntrySize = is64Bit() ?
662 sizeof(MachO::nlist_64) :
663 sizeof(MachO::nlist);
664 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
666 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
667 return symbol_iterator(SymbolRef(Sym, this));
670 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
671 uint64_t &Res) const {
672 MachO::any_relocation_info RE = getRelocation(Rel);
673 Res = getAnyRelocationType(RE);
674 return object_error::success;
678 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
679 SmallVectorImpl<char> &Result) const {
682 getRelocationType(Rel, RType);
684 unsigned Arch = this->getArch();
688 static const char *const Table[] = {
689 "GENERIC_RELOC_VANILLA",
690 "GENERIC_RELOC_PAIR",
691 "GENERIC_RELOC_SECTDIFF",
692 "GENERIC_RELOC_PB_LA_PTR",
693 "GENERIC_RELOC_LOCAL_SECTDIFF",
694 "GENERIC_RELOC_TLV" };
702 case Triple::x86_64: {
703 static const char *const Table[] = {
704 "X86_64_RELOC_UNSIGNED",
705 "X86_64_RELOC_SIGNED",
706 "X86_64_RELOC_BRANCH",
707 "X86_64_RELOC_GOT_LOAD",
709 "X86_64_RELOC_SUBTRACTOR",
710 "X86_64_RELOC_SIGNED_1",
711 "X86_64_RELOC_SIGNED_2",
712 "X86_64_RELOC_SIGNED_4",
713 "X86_64_RELOC_TLV" };
722 static const char *const Table[] = {
725 "ARM_RELOC_SECTDIFF",
726 "ARM_RELOC_LOCAL_SECTDIFF",
727 "ARM_RELOC_PB_LA_PTR",
729 "ARM_THUMB_RELOC_BR22",
730 "ARM_THUMB_32BIT_BRANCH",
732 "ARM_RELOC_HALF_SECTDIFF" };
740 case Triple::aarch64: {
741 static const char *const Table[] = {
742 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
743 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
744 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
745 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
746 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
750 if (RType >= array_lengthof(Table))
757 static const char *const Table[] = {
766 "PPC_RELOC_SECTDIFF",
767 "PPC_RELOC_PB_LA_PTR",
768 "PPC_RELOC_HI16_SECTDIFF",
769 "PPC_RELOC_LO16_SECTDIFF",
770 "PPC_RELOC_HA16_SECTDIFF",
772 "PPC_RELOC_LO14_SECTDIFF",
773 "PPC_RELOC_LOCAL_SECTDIFF" };
781 case Triple::UnknownArch:
785 Result.append(res.begin(), res.end());
786 return object_error::success;
790 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
791 SmallVectorImpl<char> &Result) const {
792 MachO::any_relocation_info RE = getRelocation(Rel);
794 unsigned Arch = this->getArch();
797 raw_string_ostream fmt(fmtbuf);
798 unsigned Type = this->getAnyRelocationType(RE);
799 bool IsPCRel = this->getAnyRelocationPCRel(RE);
801 // Determine any addends that should be displayed with the relocation.
802 // These require decoding the relocation type, which is triple-specific.
804 // X86_64 has entirely custom relocation types.
805 if (Arch == Triple::x86_64) {
806 bool isPCRel = getAnyRelocationPCRel(RE);
809 case MachO::X86_64_RELOC_GOT_LOAD:
810 case MachO::X86_64_RELOC_GOT: {
811 printRelocationTargetName(this, RE, fmt);
813 if (isPCRel) fmt << "PCREL";
816 case MachO::X86_64_RELOC_SUBTRACTOR: {
817 DataRefImpl RelNext = Rel;
818 moveRelocationNext(RelNext);
819 MachO::any_relocation_info RENext = getRelocation(RelNext);
821 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
822 // X86_64_RELOC_UNSIGNED.
823 // NOTE: Scattered relocations don't exist on x86_64.
824 unsigned RType = getAnyRelocationType(RENext);
825 if (RType != MachO::X86_64_RELOC_UNSIGNED)
826 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
827 "X86_64_RELOC_SUBTRACTOR.");
829 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
830 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
831 printRelocationTargetName(this, RENext, fmt);
833 printRelocationTargetName(this, RE, fmt);
836 case MachO::X86_64_RELOC_TLV:
837 printRelocationTargetName(this, RE, fmt);
839 if (isPCRel) fmt << "P";
841 case MachO::X86_64_RELOC_SIGNED_1:
842 printRelocationTargetName(this, RE, fmt);
845 case MachO::X86_64_RELOC_SIGNED_2:
846 printRelocationTargetName(this, RE, fmt);
849 case MachO::X86_64_RELOC_SIGNED_4:
850 printRelocationTargetName(this, RE, fmt);
854 printRelocationTargetName(this, RE, fmt);
857 // X86 and ARM share some relocation types in common.
858 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
859 Arch == Triple::ppc) {
860 // Generic relocation types...
862 case MachO::GENERIC_RELOC_PAIR: // prints no info
863 return object_error::success;
864 case MachO::GENERIC_RELOC_SECTDIFF: {
865 DataRefImpl RelNext = Rel;
866 moveRelocationNext(RelNext);
867 MachO::any_relocation_info RENext = getRelocation(RelNext);
869 // X86 sect diff's must be followed by a relocation of type
870 // GENERIC_RELOC_PAIR.
871 unsigned RType = getAnyRelocationType(RENext);
873 if (RType != MachO::GENERIC_RELOC_PAIR)
874 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
875 "GENERIC_RELOC_SECTDIFF.");
877 printRelocationTargetName(this, RE, fmt);
879 printRelocationTargetName(this, RENext, fmt);
884 if (Arch == Triple::x86 || Arch == Triple::ppc) {
886 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
887 DataRefImpl RelNext = Rel;
888 moveRelocationNext(RelNext);
889 MachO::any_relocation_info RENext = getRelocation(RelNext);
891 // X86 sect diff's must be followed by a relocation of type
892 // GENERIC_RELOC_PAIR.
893 unsigned RType = getAnyRelocationType(RENext);
894 if (RType != MachO::GENERIC_RELOC_PAIR)
895 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
896 "GENERIC_RELOC_LOCAL_SECTDIFF.");
898 printRelocationTargetName(this, RE, fmt);
900 printRelocationTargetName(this, RENext, fmt);
903 case MachO::GENERIC_RELOC_TLV: {
904 printRelocationTargetName(this, RE, fmt);
906 if (IsPCRel) fmt << "P";
910 printRelocationTargetName(this, RE, fmt);
912 } else { // ARM-specific relocations
914 case MachO::ARM_RELOC_HALF:
915 case MachO::ARM_RELOC_HALF_SECTDIFF: {
916 // Half relocations steal a bit from the length field to encode
917 // whether this is an upper16 or a lower16 relocation.
918 bool isUpper = getAnyRelocationLength(RE) >> 1;
924 printRelocationTargetName(this, RE, fmt);
926 DataRefImpl RelNext = Rel;
927 moveRelocationNext(RelNext);
928 MachO::any_relocation_info RENext = getRelocation(RelNext);
930 // ARM half relocs must be followed by a relocation of type
932 unsigned RType = getAnyRelocationType(RENext);
933 if (RType != MachO::ARM_RELOC_PAIR)
934 report_fatal_error("Expected ARM_RELOC_PAIR after "
937 // NOTE: The half of the target virtual address is stashed in the
938 // address field of the secondary relocation, but we can't reverse
939 // engineer the constant offset from it without decoding the movw/movt
940 // instruction to find the other half in its immediate field.
942 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
943 // symbol/section pointer of the follow-on relocation.
944 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
946 printRelocationTargetName(this, RENext, fmt);
953 printRelocationTargetName(this, RE, fmt);
958 printRelocationTargetName(this, RE, fmt);
961 Result.append(fmtbuf.begin(), fmtbuf.end());
962 return object_error::success;
965 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
966 bool &Result) const {
967 unsigned Arch = getArch();
969 getRelocationType(Rel, Type);
973 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
975 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
976 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
977 } else if (Arch == Triple::x86_64) {
978 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
979 // an X86_64_RELOC_SUBTRACTOR.
980 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
981 DataRefImpl RelPrev = Rel;
984 getRelocationType(RelPrev, PrevType);
985 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
990 return object_error::success;
994 // guessLibraryShortName() is passed a name of a dynamic library and returns a
995 // guess on what the short name is. Then name is returned as a substring of the
996 // StringRef Name passed in. The name of the dynamic library is recognized as
997 // a framework if it has one of the two following forms:
998 // Foo.framework/Versions/A/Foo
1000 // Where A and Foo can be any string. And may contain a trailing suffix
1001 // starting with an underbar. If the Name is recognized as a framework then
1002 // isFramework is set to true else it is set to false. If the Name has a
1003 // suffix then Suffix is set to the substring in Name that contains the suffix
1004 // else it is set to a NULL StringRef.
1006 // The Name of the dynamic library is recognized as a library name if it has
1007 // one of the two following forms:
1010 // The library may have a suffix trailing the name Foo of the form:
1011 // libFoo_profile.A.dylib
1012 // libFoo_profile.dylib
1014 // The Name of the dynamic library is also recognized as a library name if it
1015 // has the following form:
1018 // If the Name of the dynamic library is none of the forms above then a NULL
1019 // StringRef is returned.
1021 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1023 StringRef &Suffix) {
1024 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1025 size_t a, b, c, d, Idx;
1027 isFramework = false;
1028 Suffix = StringRef();
1030 // Pull off the last component and make Foo point to it
1031 a = Name.rfind('/');
1032 if (a == Name.npos || a == 0)
1034 Foo = Name.slice(a+1, Name.npos);
1036 // Look for a suffix starting with a '_'
1037 Idx = Foo.rfind('_');
1038 if (Idx != Foo.npos && Foo.size() >= 2) {
1039 Suffix = Foo.slice(Idx, Foo.npos);
1040 Foo = Foo.slice(0, Idx);
1043 // First look for the form Foo.framework/Foo
1044 b = Name.rfind('/', a);
1049 F = Name.slice(Idx, Idx + Foo.size());
1050 DotFramework = Name.slice(Idx + Foo.size(),
1051 Idx + Foo.size() + sizeof(".framework/")-1);
1052 if (F == Foo && DotFramework == ".framework/") {
1057 // Next look for the form Foo.framework/Versions/A/Foo
1060 c = Name.rfind('/', b);
1061 if (c == Name.npos || c == 0)
1063 V = Name.slice(c+1, Name.npos);
1064 if (!V.startswith("Versions/"))
1066 d = Name.rfind('/', c);
1071 F = Name.slice(Idx, Idx + Foo.size());
1072 DotFramework = Name.slice(Idx + Foo.size(),
1073 Idx + Foo.size() + sizeof(".framework/")-1);
1074 if (F == Foo && DotFramework == ".framework/") {
1080 // pull off the suffix after the "." and make a point to it
1081 a = Name.rfind('.');
1082 if (a == Name.npos || a == 0)
1084 Dylib = Name.slice(a, Name.npos);
1085 if (Dylib != ".dylib")
1088 // First pull off the version letter for the form Foo.A.dylib if any.
1090 Dot = Name.slice(a-2, a-1);
1095 b = Name.rfind('/', a);
1100 // ignore any suffix after an underbar like Foo_profile.A.dylib
1101 Idx = Name.find('_', b);
1102 if (Idx != Name.npos && Idx != b) {
1103 Lib = Name.slice(b, Idx);
1104 Suffix = Name.slice(Idx, a);
1107 Lib = Name.slice(b, a);
1108 // There are incorrect library names of the form:
1109 // libATS.A_profile.dylib so check for these.
1110 if (Lib.size() >= 3) {
1111 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1113 Lib = Lib.slice(0, Lib.size()-2);
1118 Qtx = Name.slice(a, Name.npos);
1121 b = Name.rfind('/', a);
1123 Lib = Name.slice(0, a);
1125 Lib = Name.slice(b+1, a);
1126 // There are library names of the form: QT.A.qtx so check for these.
1127 if (Lib.size() >= 3) {
1128 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1130 Lib = Lib.slice(0, Lib.size()-2);
1135 // getLibraryShortNameByIndex() is used to get the short name of the library
1136 // for an undefined symbol in a linked Mach-O binary that was linked with the
1137 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1138 // It is passed the index (0 - based) of the library as translated from
1139 // GET_LIBRARY_ORDINAL (1 - based).
1140 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1141 StringRef &Res) const {
1142 if (Index >= Libraries.size())
1143 return object_error::parse_failed;
1145 // If the cache of LibrariesShortNames is not built up do that first for
1146 // all the Libraries.
1147 if (LibrariesShortNames.size() == 0) {
1148 for (unsigned i = 0; i < Libraries.size(); i++) {
1149 MachO::dylib_command D =
1150 getStruct<MachO::dylib_command>(this, Libraries[i]);
1151 if (D.dylib.name >= D.cmdsize)
1152 return object_error::parse_failed;
1153 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1154 StringRef Name = StringRef(P);
1155 if (D.dylib.name+Name.size() >= D.cmdsize)
1156 return object_error::parse_failed;
1159 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1160 if (shortName.empty())
1161 LibrariesShortNames.push_back(Name);
1163 LibrariesShortNames.push_back(shortName);
1167 Res = LibrariesShortNames[Index];
1168 return object_error::success;
1171 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1172 return getSymbolByIndex(0);
1175 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1178 return basic_symbol_iterator(SymbolRef(DRI, this));
1180 MachO::symtab_command Symtab = getSymtabLoadCommand();
1181 unsigned SymbolTableEntrySize = is64Bit() ?
1182 sizeof(MachO::nlist_64) :
1183 sizeof(MachO::nlist);
1184 unsigned Offset = Symtab.symoff +
1185 Symtab.nsyms * SymbolTableEntrySize;
1186 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1187 return basic_symbol_iterator(SymbolRef(DRI, this));
1190 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1193 return basic_symbol_iterator(SymbolRef(DRI, this));
1195 MachO::symtab_command Symtab = getSymtabLoadCommand();
1196 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1197 unsigned SymbolTableEntrySize =
1198 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1199 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1200 DRI.p += Index * SymbolTableEntrySize;
1201 return basic_symbol_iterator(SymbolRef(DRI, this));
1204 section_iterator MachOObjectFile::section_begin() const {
1206 return section_iterator(SectionRef(DRI, this));
1209 section_iterator MachOObjectFile::section_end() const {
1211 DRI.d.a = Sections.size();
1212 return section_iterator(SectionRef(DRI, this));
1215 uint8_t MachOObjectFile::getBytesInAddress() const {
1216 return is64Bit() ? 8 : 4;
1219 StringRef MachOObjectFile::getFileFormatName() const {
1220 unsigned CPUType = getCPUType(this);
1223 case llvm::MachO::CPU_TYPE_I386:
1224 return "Mach-O 32-bit i386";
1225 case llvm::MachO::CPU_TYPE_ARM:
1226 return "Mach-O arm";
1227 case llvm::MachO::CPU_TYPE_POWERPC:
1228 return "Mach-O 32-bit ppc";
1230 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1231 "64-bit object file when we're not 64-bit?");
1232 return "Mach-O 32-bit unknown";
1236 // Make sure the cpu type has the correct mask.
1237 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1238 == llvm::MachO::CPU_ARCH_ABI64 &&
1239 "32-bit object file when we're 64-bit?");
1242 case llvm::MachO::CPU_TYPE_X86_64:
1243 return "Mach-O 64-bit x86-64";
1244 case llvm::MachO::CPU_TYPE_ARM64:
1245 return "Mach-O arm64";
1246 case llvm::MachO::CPU_TYPE_POWERPC64:
1247 return "Mach-O 64-bit ppc64";
1249 return "Mach-O 64-bit unknown";
1253 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1255 case llvm::MachO::CPU_TYPE_I386:
1257 case llvm::MachO::CPU_TYPE_X86_64:
1258 return Triple::x86_64;
1259 case llvm::MachO::CPU_TYPE_ARM:
1261 case llvm::MachO::CPU_TYPE_ARM64:
1262 return Triple::aarch64;
1263 case llvm::MachO::CPU_TYPE_POWERPC:
1265 case llvm::MachO::CPU_TYPE_POWERPC64:
1266 return Triple::ppc64;
1268 return Triple::UnknownArch;
1272 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1273 const char **McpuDefault) {
1275 *McpuDefault = nullptr;
1278 case MachO::CPU_TYPE_I386:
1279 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1280 case MachO::CPU_SUBTYPE_I386_ALL:
1281 return Triple("i386-apple-darwin");
1285 case MachO::CPU_TYPE_X86_64:
1286 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1287 case MachO::CPU_SUBTYPE_X86_64_ALL:
1288 return Triple("x86_64-apple-darwin");
1289 case MachO::CPU_SUBTYPE_X86_64_H:
1290 return Triple("x86_64h-apple-darwin");
1294 case MachO::CPU_TYPE_ARM:
1295 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1296 case MachO::CPU_SUBTYPE_ARM_V4T:
1297 return Triple("armv4t-apple-darwin");
1298 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1299 return Triple("armv5e-apple-darwin");
1300 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1301 return Triple("xscale-apple-darwin");
1302 case MachO::CPU_SUBTYPE_ARM_V6:
1303 return Triple("armv6-apple-darwin");
1304 case MachO::CPU_SUBTYPE_ARM_V6M:
1306 *McpuDefault = "cortex-m0";
1307 return Triple("armv6m-apple-darwin");
1308 case MachO::CPU_SUBTYPE_ARM_V7:
1309 return Triple("armv7-apple-darwin");
1310 case MachO::CPU_SUBTYPE_ARM_V7EM:
1312 *McpuDefault = "cortex-m4";
1313 return Triple("armv7em-apple-darwin");
1314 case MachO::CPU_SUBTYPE_ARM_V7K:
1315 return Triple("armv7k-apple-darwin");
1316 case MachO::CPU_SUBTYPE_ARM_V7M:
1318 *McpuDefault = "cortex-m3";
1319 return Triple("armv7m-apple-darwin");
1320 case MachO::CPU_SUBTYPE_ARM_V7S:
1321 return Triple("armv7s-apple-darwin");
1325 case MachO::CPU_TYPE_ARM64:
1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1327 case MachO::CPU_SUBTYPE_ARM64_ALL:
1328 return Triple("arm64-apple-darwin");
1332 case MachO::CPU_TYPE_POWERPC:
1333 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1334 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1335 return Triple("ppc-apple-darwin");
1339 case MachO::CPU_TYPE_POWERPC64:
1340 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1341 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1342 return Triple("ppc64-apple-darwin");
1351 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1352 const char **McpuDefault) {
1354 *McpuDefault = nullptr;
1357 case MachO::CPU_TYPE_ARM:
1358 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1359 case MachO::CPU_SUBTYPE_ARM_V4T:
1360 return Triple("thumbv4t-apple-darwin");
1361 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1362 return Triple("thumbv5e-apple-darwin");
1363 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1364 return Triple("xscale-apple-darwin");
1365 case MachO::CPU_SUBTYPE_ARM_V6:
1366 return Triple("thumbv6-apple-darwin");
1367 case MachO::CPU_SUBTYPE_ARM_V6M:
1369 *McpuDefault = "cortex-m0";
1370 return Triple("thumbv6m-apple-darwin");
1371 case MachO::CPU_SUBTYPE_ARM_V7:
1372 return Triple("thumbv7-apple-darwin");
1373 case MachO::CPU_SUBTYPE_ARM_V7EM:
1375 *McpuDefault = "cortex-m4";
1376 return Triple("thumbv7em-apple-darwin");
1377 case MachO::CPU_SUBTYPE_ARM_V7K:
1378 return Triple("thumbv7k-apple-darwin");
1379 case MachO::CPU_SUBTYPE_ARM_V7M:
1381 *McpuDefault = "cortex-m3";
1382 return Triple("thumbv7m-apple-darwin");
1383 case MachO::CPU_SUBTYPE_ARM_V7S:
1384 return Triple("thumbv7s-apple-darwin");
1393 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1394 const char **McpuDefault,
1395 Triple *ThumbTriple) {
1396 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1397 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1402 Triple MachOObjectFile::getHostArch() {
1403 return Triple(sys::getDefaultTargetTriple());
1406 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1407 return StringSwitch<bool>(ArchFlag)
1409 .Case("x86_64", true)
1410 .Case("x86_64h", true)
1411 .Case("armv4t", true)
1413 .Case("armv5e", true)
1414 .Case("armv6", true)
1415 .Case("armv6m", true)
1416 .Case("armv7em", true)
1417 .Case("armv7k", true)
1418 .Case("armv7m", true)
1419 .Case("armv7s", true)
1420 .Case("arm64", true)
1422 .Case("ppc64", true)
1426 unsigned MachOObjectFile::getArch() const {
1427 return getArch(getCPUType(this));
1430 Triple MachOObjectFile::getArch(const char **McpuDefault,
1431 Triple *ThumbTriple) const {
1434 MachO::mach_header_64 H_64;
1435 H_64 = getHeader64();
1436 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
1437 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
1440 MachO::mach_header H;
1442 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
1443 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
1449 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1452 return section_rel_begin(DRI);
1455 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1458 return section_rel_end(DRI);
1461 dice_iterator MachOObjectFile::begin_dices() const {
1463 if (!DataInCodeLoadCmd)
1464 return dice_iterator(DiceRef(DRI, this));
1466 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1467 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1468 return dice_iterator(DiceRef(DRI, this));
1471 dice_iterator MachOObjectFile::end_dices() const {
1473 if (!DataInCodeLoadCmd)
1474 return dice_iterator(DiceRef(DRI, this));
1476 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1477 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1478 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1479 return dice_iterator(DiceRef(DRI, this));
1482 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1483 : Trie(T), Malformed(false), Done(false) { }
1485 void ExportEntry::moveToFirst() {
1487 pushDownUntilBottom();
1490 void ExportEntry::moveToEnd() {
1495 bool ExportEntry::operator==(const ExportEntry &Other) const {
1496 // Common case, one at end, other iterating from begin.
1497 if (Done || Other.Done)
1498 return (Done == Other.Done);
1499 // Not equal if different stack sizes.
1500 if (Stack.size() != Other.Stack.size())
1502 // Not equal if different cumulative strings.
1503 if (!CumulativeString.str().equals(Other.CumulativeString.str()))
1505 // Equal if all nodes in both stacks match.
1506 for (unsigned i=0; i < Stack.size(); ++i) {
1507 if (Stack[i].Start != Other.Stack[i].Start)
1513 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1515 uint64_t Result = decodeULEB128(Ptr, &Count);
1517 if (Ptr > Trie.end()) {
1524 StringRef ExportEntry::name() const {
1525 return CumulativeString.str();
1528 uint64_t ExportEntry::flags() const {
1529 return Stack.back().Flags;
1532 uint64_t ExportEntry::address() const {
1533 return Stack.back().Address;
1536 uint64_t ExportEntry::other() const {
1537 return Stack.back().Other;
1540 StringRef ExportEntry::otherName() const {
1541 const char* ImportName = Stack.back().ImportName;
1543 return StringRef(ImportName);
1547 uint32_t ExportEntry::nodeOffset() const {
1548 return Stack.back().Start - Trie.begin();
1551 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1552 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1553 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1554 ParentStringLength(0), IsExportNode(false) {
1557 void ExportEntry::pushNode(uint64_t offset) {
1558 const uint8_t *Ptr = Trie.begin() + offset;
1559 NodeState State(Ptr);
1560 uint64_t ExportInfoSize = readULEB128(State.Current);
1561 State.IsExportNode = (ExportInfoSize != 0);
1562 const uint8_t* Children = State.Current + ExportInfoSize;
1563 if (State.IsExportNode) {
1564 State.Flags = readULEB128(State.Current);
1565 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1567 State.Other = readULEB128(State.Current); // dylib ordinal
1568 State.ImportName = reinterpret_cast<const char*>(State.Current);
1570 State.Address = readULEB128(State.Current);
1571 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1572 State.Other = readULEB128(State.Current);
1575 State.ChildCount = *Children;
1576 State.Current = Children + 1;
1577 State.NextChildIndex = 0;
1578 State.ParentStringLength = CumulativeString.size();
1579 Stack.push_back(State);
1582 void ExportEntry::pushDownUntilBottom() {
1583 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1584 NodeState &Top = Stack.back();
1585 CumulativeString.resize(Top.ParentStringLength);
1586 for (;*Top.Current != 0; Top.Current++) {
1587 char C = *Top.Current;
1588 CumulativeString.push_back(C);
1591 uint64_t childNodeIndex = readULEB128(Top.Current);
1592 Top.NextChildIndex += 1;
1593 pushNode(childNodeIndex);
1595 if (!Stack.back().IsExportNode) {
1601 // We have a trie data structure and need a way to walk it that is compatible
1602 // with the C++ iterator model. The solution is a non-recursive depth first
1603 // traversal where the iterator contains a stack of parent nodes along with a
1604 // string that is the accumulation of all edge strings along the parent chain
1607 // There is one "export" node for each exported symbol. But because some
1608 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1609 // node may have child nodes too.
1611 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1612 // child until hitting a node with no children (which is an export node or
1613 // else the trie is malformed). On the way down, each node is pushed on the
1614 // stack ivar. If there is no more ways down, it pops up one and tries to go
1615 // down a sibling path until a childless node is reached.
1616 void ExportEntry::moveNext() {
1617 if (Stack.empty() || !Stack.back().IsExportNode) {
1624 while (!Stack.empty()) {
1625 NodeState &Top = Stack.back();
1626 if (Top.NextChildIndex < Top.ChildCount) {
1627 pushDownUntilBottom();
1628 // Now at the next export node.
1631 if (Top.IsExportNode) {
1632 // This node has no children but is itself an export node.
1633 CumulativeString.resize(Top.ParentStringLength);
1642 iterator_range<export_iterator>
1643 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1644 ExportEntry Start(Trie);
1645 Start.moveToFirst();
1647 ExportEntry Finish(Trie);
1650 return iterator_range<export_iterator>(export_iterator(Start),
1651 export_iterator(Finish));
1654 iterator_range<export_iterator> MachOObjectFile::exports() const {
1655 return exports(getDyldInfoExportsTrie());
1659 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1660 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1661 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1662 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1664 void MachORebaseEntry::moveToFirst() {
1665 Ptr = Opcodes.begin();
1669 void MachORebaseEntry::moveToEnd() {
1670 Ptr = Opcodes.end();
1671 RemainingLoopCount = 0;
1675 void MachORebaseEntry::moveNext() {
1676 // If in the middle of some loop, move to next rebasing in loop.
1677 SegmentOffset += AdvanceAmount;
1678 if (RemainingLoopCount) {
1679 --RemainingLoopCount;
1682 if (Ptr == Opcodes.end()) {
1687 while (More && !Malformed) {
1688 // Parse next opcode and set up next loop.
1689 uint8_t Byte = *Ptr++;
1690 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1691 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1693 case MachO::REBASE_OPCODE_DONE:
1697 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1699 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1700 RebaseType = ImmValue;
1703 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1704 << "RebaseType=" << (int) RebaseType << "\n");
1706 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1707 SegmentIndex = ImmValue;
1708 SegmentOffset = readULEB128();
1711 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1712 << "SegmentIndex=" << SegmentIndex << ", "
1713 << format("SegmentOffset=0x%06X", SegmentOffset)
1716 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1717 SegmentOffset += readULEB128();
1718 DEBUG_WITH_TYPE("mach-o-rebase",
1719 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1720 << format("SegmentOffset=0x%06X",
1721 SegmentOffset) << "\n");
1723 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1724 SegmentOffset += ImmValue * PointerSize;
1725 DEBUG_WITH_TYPE("mach-o-rebase",
1726 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1727 << format("SegmentOffset=0x%06X",
1728 SegmentOffset) << "\n");
1730 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1731 AdvanceAmount = PointerSize;
1732 RemainingLoopCount = ImmValue - 1;
1735 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1736 << format("SegmentOffset=0x%06X", SegmentOffset)
1737 << ", AdvanceAmount=" << AdvanceAmount
1738 << ", RemainingLoopCount=" << RemainingLoopCount
1741 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1742 AdvanceAmount = PointerSize;
1743 RemainingLoopCount = readULEB128() - 1;
1746 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1747 << format("SegmentOffset=0x%06X", SegmentOffset)
1748 << ", AdvanceAmount=" << AdvanceAmount
1749 << ", RemainingLoopCount=" << RemainingLoopCount
1752 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1753 AdvanceAmount = readULEB128() + PointerSize;
1754 RemainingLoopCount = 0;
1757 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1758 << format("SegmentOffset=0x%06X", SegmentOffset)
1759 << ", AdvanceAmount=" << AdvanceAmount
1760 << ", RemainingLoopCount=" << RemainingLoopCount
1763 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1764 RemainingLoopCount = readULEB128() - 1;
1765 AdvanceAmount = readULEB128() + PointerSize;
1768 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1769 << format("SegmentOffset=0x%06X", SegmentOffset)
1770 << ", AdvanceAmount=" << AdvanceAmount
1771 << ", RemainingLoopCount=" << RemainingLoopCount
1780 uint64_t MachORebaseEntry::readULEB128() {
1782 uint64_t Result = decodeULEB128(Ptr, &Count);
1784 if (Ptr > Opcodes.end()) {
1785 Ptr = Opcodes.end();
1791 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1793 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1795 StringRef MachORebaseEntry::typeName() const {
1796 switch (RebaseType) {
1797 case MachO::REBASE_TYPE_POINTER:
1799 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1800 return "text abs32";
1801 case MachO::REBASE_TYPE_TEXT_PCREL32:
1802 return "text rel32";
1807 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1808 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1809 return (Ptr == Other.Ptr) &&
1810 (RemainingLoopCount == Other.RemainingLoopCount) &&
1811 (Done == Other.Done);
1814 iterator_range<rebase_iterator>
1815 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1816 MachORebaseEntry Start(Opcodes, is64);
1817 Start.moveToFirst();
1819 MachORebaseEntry Finish(Opcodes, is64);
1822 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1823 rebase_iterator(Finish));
1826 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1827 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1831 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
1833 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1834 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1835 BindType(0), PointerSize(is64Bit ? 8 : 4),
1836 TableKind(BK), Malformed(false), Done(false) {}
1838 void MachOBindEntry::moveToFirst() {
1839 Ptr = Opcodes.begin();
1843 void MachOBindEntry::moveToEnd() {
1844 Ptr = Opcodes.end();
1845 RemainingLoopCount = 0;
1849 void MachOBindEntry::moveNext() {
1850 // If in the middle of some loop, move to next binding in loop.
1851 SegmentOffset += AdvanceAmount;
1852 if (RemainingLoopCount) {
1853 --RemainingLoopCount;
1856 if (Ptr == Opcodes.end()) {
1861 while (More && !Malformed) {
1862 // Parse next opcode and set up next loop.
1863 uint8_t Byte = *Ptr++;
1864 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1865 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1866 int8_t SignExtended;
1867 const uint8_t *SymStart;
1869 case MachO::BIND_OPCODE_DONE:
1870 if (TableKind == Kind::Lazy) {
1871 // Lazying bindings have a DONE opcode between entries. Need to ignore
1872 // it to advance to next entry. But need not if this is last entry.
1873 bool NotLastEntry = false;
1874 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1876 NotLastEntry = true;
1885 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1887 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1891 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1892 << "Ordinal=" << Ordinal << "\n");
1894 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1895 Ordinal = readULEB128();
1898 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1899 << "Ordinal=" << Ordinal << "\n");
1901 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1903 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1904 Ordinal = SignExtended;
1909 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1910 << "Ordinal=" << Ordinal << "\n");
1912 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1918 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1923 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1924 << "SymbolName=" << SymbolName << "\n");
1925 if (TableKind == Kind::Weak) {
1926 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1930 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1931 BindType = ImmValue;
1934 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1935 << "BindType=" << (int)BindType << "\n");
1937 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1938 Addend = readSLEB128();
1939 if (TableKind == Kind::Lazy)
1943 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1944 << "Addend=" << Addend << "\n");
1946 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1947 SegmentIndex = ImmValue;
1948 SegmentOffset = readULEB128();
1951 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1952 << "SegmentIndex=" << SegmentIndex << ", "
1953 << format("SegmentOffset=0x%06X", SegmentOffset)
1956 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1957 SegmentOffset += readULEB128();
1958 DEBUG_WITH_TYPE("mach-o-bind",
1959 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1960 << format("SegmentOffset=0x%06X",
1961 SegmentOffset) << "\n");
1963 case MachO::BIND_OPCODE_DO_BIND:
1964 AdvanceAmount = PointerSize;
1965 RemainingLoopCount = 0;
1966 DEBUG_WITH_TYPE("mach-o-bind",
1967 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1968 << format("SegmentOffset=0x%06X",
1969 SegmentOffset) << "\n");
1971 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1972 AdvanceAmount = readULEB128() + PointerSize;
1973 RemainingLoopCount = 0;
1974 if (TableKind == Kind::Lazy)
1978 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1979 << format("SegmentOffset=0x%06X", SegmentOffset)
1980 << ", AdvanceAmount=" << AdvanceAmount
1981 << ", RemainingLoopCount=" << RemainingLoopCount
1984 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1985 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1986 RemainingLoopCount = 0;
1987 if (TableKind == Kind::Lazy)
1989 DEBUG_WITH_TYPE("mach-o-bind",
1991 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1992 << format("SegmentOffset=0x%06X",
1993 SegmentOffset) << "\n");
1995 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1996 RemainingLoopCount = readULEB128() - 1;
1997 AdvanceAmount = readULEB128() + PointerSize;
1998 if (TableKind == Kind::Lazy)
2002 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
2003 << format("SegmentOffset=0x%06X", SegmentOffset)
2004 << ", AdvanceAmount=" << AdvanceAmount
2005 << ", RemainingLoopCount=" << RemainingLoopCount
2014 uint64_t MachOBindEntry::readULEB128() {
2016 uint64_t Result = decodeULEB128(Ptr, &Count);
2018 if (Ptr > Opcodes.end()) {
2019 Ptr = Opcodes.end();
2025 int64_t MachOBindEntry::readSLEB128() {
2027 int64_t Result = decodeSLEB128(Ptr, &Count);
2029 if (Ptr > Opcodes.end()) {
2030 Ptr = Opcodes.end();
2037 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
2039 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
2041 StringRef MachOBindEntry::typeName() const {
2043 case MachO::BIND_TYPE_POINTER:
2045 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
2046 return "text abs32";
2047 case MachO::BIND_TYPE_TEXT_PCREL32:
2048 return "text rel32";
2053 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
2055 int64_t MachOBindEntry::addend() const { return Addend; }
2057 uint32_t MachOBindEntry::flags() const { return Flags; }
2059 int MachOBindEntry::ordinal() const { return Ordinal; }
2061 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
2062 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
2063 return (Ptr == Other.Ptr) &&
2064 (RemainingLoopCount == Other.RemainingLoopCount) &&
2065 (Done == Other.Done);
2068 iterator_range<bind_iterator>
2069 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
2070 MachOBindEntry::Kind BKind) {
2071 MachOBindEntry Start(Opcodes, is64, BKind);
2072 Start.moveToFirst();
2074 MachOBindEntry Finish(Opcodes, is64, BKind);
2077 return iterator_range<bind_iterator>(bind_iterator(Start),
2078 bind_iterator(Finish));
2081 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
2082 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
2083 MachOBindEntry::Kind::Regular);
2086 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
2087 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
2088 MachOBindEntry::Kind::Lazy);
2091 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
2092 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
2093 MachOBindEntry::Kind::Weak);
2097 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
2098 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
2099 return parseSegmentOrSectionName(Raw.data());
2103 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
2104 const section_base *Base =
2105 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2106 return makeArrayRef(Base->sectname);
2110 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
2111 const section_base *Base =
2112 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
2113 return makeArrayRef(Base->segname);
2117 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
2119 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
2121 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
2124 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
2125 const MachO::any_relocation_info &RE) const {
2126 if (isLittleEndian())
2127 return RE.r_word1 & 0xffffff;
2128 return RE.r_word1 >> 8;
2131 bool MachOObjectFile::getPlainRelocationExternal(
2132 const MachO::any_relocation_info &RE) const {
2133 if (isLittleEndian())
2134 return (RE.r_word1 >> 27) & 1;
2135 return (RE.r_word1 >> 4) & 1;
2138 bool MachOObjectFile::getScatteredRelocationScattered(
2139 const MachO::any_relocation_info &RE) const {
2140 return RE.r_word0 >> 31;
2143 uint32_t MachOObjectFile::getScatteredRelocationValue(
2144 const MachO::any_relocation_info &RE) const {
2148 uint32_t MachOObjectFile::getScatteredRelocationType(
2149 const MachO::any_relocation_info &RE) const {
2150 return (RE.r_word0 >> 24) & 0xf;
2153 unsigned MachOObjectFile::getAnyRelocationAddress(
2154 const MachO::any_relocation_info &RE) const {
2155 if (isRelocationScattered(RE))
2156 return getScatteredRelocationAddress(RE);
2157 return getPlainRelocationAddress(RE);
2160 unsigned MachOObjectFile::getAnyRelocationPCRel(
2161 const MachO::any_relocation_info &RE) const {
2162 if (isRelocationScattered(RE))
2163 return getScatteredRelocationPCRel(this, RE);
2164 return getPlainRelocationPCRel(this, RE);
2167 unsigned MachOObjectFile::getAnyRelocationLength(
2168 const MachO::any_relocation_info &RE) const {
2169 if (isRelocationScattered(RE))
2170 return getScatteredRelocationLength(RE);
2171 return getPlainRelocationLength(this, RE);
2175 MachOObjectFile::getAnyRelocationType(
2176 const MachO::any_relocation_info &RE) const {
2177 if (isRelocationScattered(RE))
2178 return getScatteredRelocationType(RE);
2179 return getPlainRelocationType(this, RE);
2183 MachOObjectFile::getRelocationSection(
2184 const MachO::any_relocation_info &RE) const {
2185 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
2186 return *section_end();
2187 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
2190 return SectionRef(DRI, this);
2193 MachOObjectFile::LoadCommandInfo
2194 MachOObjectFile::getFirstLoadCommandInfo() const {
2195 MachOObjectFile::LoadCommandInfo Load;
2197 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
2198 sizeof(MachO::mach_header);
2199 Load.Ptr = getPtr(this, HeaderSize);
2200 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
2204 MachOObjectFile::LoadCommandInfo
2205 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
2206 MachOObjectFile::LoadCommandInfo Next;
2207 Next.Ptr = L.Ptr + L.C.cmdsize;
2208 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
2212 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
2213 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
2216 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
2217 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
2220 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
2221 unsigned Index) const {
2222 const char *Sec = getSectionPtr(this, L, Index);
2223 return getStruct<MachO::section>(this, Sec);
2226 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
2227 unsigned Index) const {
2228 const char *Sec = getSectionPtr(this, L, Index);
2229 return getStruct<MachO::section_64>(this, Sec);
2233 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
2234 const char *P = reinterpret_cast<const char *>(DRI.p);
2235 return getStruct<MachO::nlist>(this, P);
2239 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
2240 const char *P = reinterpret_cast<const char *>(DRI.p);
2241 return getStruct<MachO::nlist_64>(this, P);
2244 MachO::linkedit_data_command
2245 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
2246 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2249 MachO::segment_command
2250 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2251 return getStruct<MachO::segment_command>(this, L.Ptr);
2254 MachO::segment_command_64
2255 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2256 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2259 MachO::linker_options_command
2260 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
2261 return getStruct<MachO::linker_options_command>(this, L.Ptr);
2264 MachO::version_min_command
2265 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2266 return getStruct<MachO::version_min_command>(this, L.Ptr);
2269 MachO::dylib_command
2270 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2271 return getStruct<MachO::dylib_command>(this, L.Ptr);
2274 MachO::dyld_info_command
2275 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2276 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2279 MachO::dylinker_command
2280 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2281 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2285 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2286 return getStruct<MachO::uuid_command>(this, L.Ptr);
2289 MachO::source_version_command
2290 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2291 return getStruct<MachO::source_version_command>(this, L.Ptr);
2294 MachO::entry_point_command
2295 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2296 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2300 MachO::any_relocation_info
2301 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2306 MachO::section_64 Sect = getSection64(Sec);
2307 Offset = Sect.reloff;
2309 MachO::section Sect = getSection(Sec);
2310 Offset = Sect.reloff;
2313 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2314 getPtr(this, Offset)) + Rel.d.b;
2315 return getStruct<MachO::any_relocation_info>(
2316 this, reinterpret_cast<const char *>(P));
2319 MachO::data_in_code_entry
2320 MachOObjectFile::getDice(DataRefImpl Rel) const {
2321 const char *P = reinterpret_cast<const char *>(Rel.p);
2322 return getStruct<MachO::data_in_code_entry>(this, P);
2325 MachO::mach_header MachOObjectFile::getHeader() const {
2326 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
2329 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
2330 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
2333 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2334 const MachO::dysymtab_command &DLC,
2335 unsigned Index) const {
2336 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2337 return getStruct<uint32_t>(this, getPtr(this, Offset));
2340 MachO::data_in_code_entry
2341 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2342 unsigned Index) const {
2343 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2344 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2347 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2349 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2351 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2352 MachO::symtab_command Cmd;
2353 Cmd.cmd = MachO::LC_SYMTAB;
2354 Cmd.cmdsize = sizeof(MachO::symtab_command);
2362 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2363 if (DysymtabLoadCmd)
2364 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2366 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2367 MachO::dysymtab_command Cmd;
2368 Cmd.cmd = MachO::LC_DYSYMTAB;
2369 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2380 Cmd.extrefsymoff = 0;
2381 Cmd.nextrefsyms = 0;
2382 Cmd.indirectsymoff = 0;
2383 Cmd.nindirectsyms = 0;
2391 MachO::linkedit_data_command
2392 MachOObjectFile::getDataInCodeLoadCommand() const {
2393 if (DataInCodeLoadCmd)
2394 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2396 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2397 MachO::linkedit_data_command Cmd;
2398 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2399 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2405 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2406 if (!DyldInfoLoadCmd)
2407 return ArrayRef<uint8_t>();
2409 MachO::dyld_info_command DyldInfo
2410 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2411 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2412 getPtr(this, DyldInfo.rebase_off));
2413 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);
2416 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2417 if (!DyldInfoLoadCmd)
2418 return ArrayRef<uint8_t>();
2420 MachO::dyld_info_command DyldInfo
2421 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2422 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2423 getPtr(this, DyldInfo.bind_off));
2424 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);
2427 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2428 if (!DyldInfoLoadCmd)
2429 return ArrayRef<uint8_t>();
2431 MachO::dyld_info_command DyldInfo
2432 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2433 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2434 getPtr(this, DyldInfo.weak_bind_off));
2435 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);
2438 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2439 if (!DyldInfoLoadCmd)
2440 return ArrayRef<uint8_t>();
2442 MachO::dyld_info_command DyldInfo
2443 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2444 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2445 getPtr(this, DyldInfo.lazy_bind_off));
2446 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);
2449 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2450 if (!DyldInfoLoadCmd)
2451 return ArrayRef<uint8_t>();
2453 MachO::dyld_info_command DyldInfo
2454 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2455 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(
2456 getPtr(this, DyldInfo.export_off));
2457 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);
2460 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2462 return ArrayRef<uint8_t>();
2463 // Returning a pointer is fine as uuid doesn't need endian swapping.
2464 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2465 return ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), 16);
2468 StringRef MachOObjectFile::getStringTableData() const {
2469 MachO::symtab_command S = getSymtabLoadCommand();
2470 return getData().substr(S.stroff, S.strsize);
2473 bool MachOObjectFile::is64Bit() const {
2474 return getType() == getMachOType(false, true) ||
2475 getType() == getMachOType(true, true);
2478 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2479 SmallVectorImpl<uint64_t> &Out) const {
2480 DataExtractor extractor(ObjectFile::getData(), true, 0);
2482 uint32_t offset = Index;
2484 while (uint64_t delta = extractor.getULEB128(&offset)) {
2486 Out.push_back(data);
2490 bool MachOObjectFile::isRelocatableObject() const {
2491 return getHeader().filetype == MachO::MH_OBJECT;
2494 ErrorOr<std::unique_ptr<MachOObjectFile>>
2495 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2496 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2498 std::unique_ptr<MachOObjectFile> Ret;
2499 if (Magic == "\xFE\xED\xFA\xCE")
2500 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2501 else if (Magic == "\xCE\xFA\xED\xFE")
2502 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2503 else if (Magic == "\xFE\xED\xFA\xCF")
2504 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2505 else if (Magic == "\xCF\xFA\xED\xFE")
2506 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2508 return object_error::parse_failed;
2512 return std::move(Ret);