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;
41 // FIXME: Replace all uses of this function with getStructOrErr.
43 static T getStruct(const MachOObjectFile *O, const char *P) {
44 // Don't read before the beginning or past the end of the file
45 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
46 report_fatal_error("Malformed MachO file.");
49 memcpy(&Cmd, P, sizeof(T));
50 if (O->isLittleEndian() != sys::IsLittleEndianHost)
51 MachO::swapStruct(Cmd);
56 static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
57 // Don't read before the beginning or past the end of the file
58 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
59 return object_error::parse_failed;
62 memcpy(&Cmd, P, sizeof(T));
63 if (O->isLittleEndian() != sys::IsLittleEndianHost)
64 MachO::swapStruct(Cmd);
69 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
71 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
73 bool Is64 = O->is64Bit();
74 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
75 sizeof(MachO::segment_command);
76 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
77 sizeof(MachO::section);
79 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
80 return reinterpret_cast<const char*>(SectionAddr);
83 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
84 return O->getData().substr(Offset, 1).data();
87 static MachO::nlist_base
88 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
89 const char *P = reinterpret_cast<const char *>(DRI.p);
90 return getStruct<MachO::nlist_base>(O, P);
93 static StringRef parseSegmentOrSectionName(const char *P) {
97 // Not null terminated, so this is a 16 char string.
98 return StringRef(P, 16);
101 // Helper to advance a section or symbol iterator multiple increments at a time.
103 static void advance(T &it, size_t Val) {
108 static unsigned getCPUType(const MachOObjectFile *O) {
109 return O->getHeader().cputype;
113 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
118 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
119 return RE.r_word0 & 0xffffff;
122 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
123 const MachO::any_relocation_info &RE) {
124 if (O->isLittleEndian())
125 return (RE.r_word1 >> 24) & 1;
126 return (RE.r_word1 >> 7) & 1;
130 getScatteredRelocationPCRel(const MachOObjectFile *O,
131 const MachO::any_relocation_info &RE) {
132 return (RE.r_word0 >> 30) & 1;
135 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
136 const MachO::any_relocation_info &RE) {
137 if (O->isLittleEndian())
138 return (RE.r_word1 >> 25) & 3;
139 return (RE.r_word1 >> 5) & 3;
143 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
144 return (RE.r_word0 >> 28) & 3;
147 static unsigned getPlainRelocationType(const MachOObjectFile *O,
148 const MachO::any_relocation_info &RE) {
149 if (O->isLittleEndian())
150 return RE.r_word1 >> 28;
151 return RE.r_word1 & 0xf;
154 static uint32_t getSectionFlags(const MachOObjectFile *O,
157 MachO::section_64 Sect = O->getSection64(Sec);
160 MachO::section Sect = O->getSection(Sec);
164 static ErrorOr<MachOObjectFile::LoadCommandInfo>
165 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
166 auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
168 return CmdOrErr.getError();
169 if (CmdOrErr->cmdsize < 8)
170 return object_error::macho_small_load_command;
171 MachOObjectFile::LoadCommandInfo Load;
173 Load.C = CmdOrErr.get();
177 static ErrorOr<MachOObjectFile::LoadCommandInfo>
178 getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
179 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
180 : sizeof(MachO::mach_header);
181 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
184 static ErrorOr<MachOObjectFile::LoadCommandInfo>
185 getNextLoadCommandInfo(const MachOObjectFile *Obj,
186 const MachOObjectFile::LoadCommandInfo &L) {
187 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
190 template <typename T>
191 static void parseHeader(const MachOObjectFile *Obj, T &Header,
192 std::error_code &EC) {
193 auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
195 Header = HeaderOrErr.get();
197 EC = HeaderOrErr.getError();
200 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
201 // sections to \param Sections, and optionally sets
202 // \param IsPageZeroSegment to true.
203 template <typename SegmentCmd>
204 static std::error_code parseSegmentLoadCommand(
205 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load,
206 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) {
207 const unsigned SegmentLoadSize = sizeof(SegmentCmd);
208 if (Load.C.cmdsize < SegmentLoadSize)
209 return object_error::macho_load_segment_too_small;
210 auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr);
212 return SegOrErr.getError();
213 SegmentCmd S = SegOrErr.get();
214 const unsigned SectionSize =
215 Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section);
216 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
217 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
218 return object_error::macho_load_segment_too_many_sections;
219 for (unsigned J = 0; J < S.nsects; ++J) {
220 const char *Sec = getSectionPtr(Obj, Load, J);
221 Sections.push_back(Sec);
223 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
224 return std::error_code();
227 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
228 bool Is64bits, std::error_code &EC)
229 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
230 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
231 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
232 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
233 HasPageZeroSegment(false) {
235 parseHeader(this, Header64, EC);
237 parseHeader(this, Header, EC);
241 uint32_t LoadCommandCount = getHeader().ncmds;
242 if (LoadCommandCount == 0)
245 auto LoadOrErr = getFirstLoadCommandInfo(this);
247 EC = LoadOrErr.getError();
250 LoadCommandInfo Load = LoadOrErr.get();
251 for (unsigned I = 0; I < LoadCommandCount; ++I) {
252 LoadCommands.push_back(Load);
253 if (Load.C.cmd == MachO::LC_SYMTAB) {
254 // Multiple symbol tables
256 EC = object_error::parse_failed;
259 SymtabLoadCmd = Load.Ptr;
260 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
261 // Multiple dynamic symbol tables
262 if (DysymtabLoadCmd) {
263 EC = object_error::parse_failed;
266 DysymtabLoadCmd = Load.Ptr;
267 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
268 // Multiple data in code tables
269 if (DataInCodeLoadCmd) {
270 EC = object_error::parse_failed;
273 DataInCodeLoadCmd = Load.Ptr;
274 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
275 // Multiple linker optimization hint tables
276 if (LinkOptHintsLoadCmd) {
277 EC = object_error::parse_failed;
280 LinkOptHintsLoadCmd = Load.Ptr;
281 } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
282 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
283 // Multiple dyldinfo load commands
284 if (DyldInfoLoadCmd) {
285 EC = object_error::parse_failed;
288 DyldInfoLoadCmd = Load.Ptr;
289 } else if (Load.C.cmd == MachO::LC_UUID) {
290 // Multiple UUID load commands
292 EC = object_error::parse_failed;
295 UuidLoadCmd = Load.Ptr;
296 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
297 if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>(
298 this, Load, Sections, HasPageZeroSegment)))
300 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
301 if ((EC = parseSegmentLoadCommand<MachO::segment_command>(
302 this, Load, Sections, HasPageZeroSegment)))
304 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
305 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
306 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
307 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
308 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
309 Libraries.push_back(Load.Ptr);
311 if (I < LoadCommandCount - 1) {
312 auto LoadOrErr = getNextLoadCommandInfo(this, Load);
314 EC = LoadOrErr.getError();
317 Load = LoadOrErr.get();
320 assert(LoadCommands.size() == LoadCommandCount);
323 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
324 unsigned SymbolTableEntrySize = is64Bit() ?
325 sizeof(MachO::nlist_64) :
326 sizeof(MachO::nlist);
327 Symb.p += SymbolTableEntrySize;
330 ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
331 StringRef StringTable = getStringTableData();
332 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
333 const char *Start = &StringTable.data()[Entry.n_strx];
334 if (Start < getData().begin() || Start >= getData().end())
336 "Symbol name entry points before beginning or past end of file.");
337 return StringRef(Start);
340 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
341 DataRefImpl DRI = Sec.getRawDataRefImpl();
342 uint32_t Flags = getSectionFlags(this, DRI);
343 return Flags & MachO::SECTION_TYPE;
346 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
348 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
349 return Entry.n_value;
351 MachO::nlist Entry = getSymbolTableEntry(Sym);
352 return Entry.n_value;
355 // getIndirectName() returns the name of the alias'ed symbol who's string table
356 // index is in the n_value field.
357 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
358 StringRef &Res) const {
359 StringRef StringTable = getStringTableData();
360 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
361 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
362 return object_error::parse_failed;
363 uint64_t NValue = getNValue(Symb);
364 if (NValue >= StringTable.size())
365 return object_error::parse_failed;
366 const char *Start = &StringTable.data()[NValue];
367 Res = StringRef(Start);
368 return std::error_code();
371 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
372 return getNValue(Sym);
375 ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
376 return getSymbolValue(Sym);
379 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
380 uint32_t flags = getSymbolFlags(DRI);
381 if (flags & SymbolRef::SF_Common) {
382 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
383 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
388 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
389 return getNValue(DRI);
392 SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
393 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
394 uint8_t n_type = Entry.n_type;
396 // If this is a STAB debugging symbol, we can do nothing more.
397 if (n_type & MachO::N_STAB)
398 return SymbolRef::ST_Debug;
400 switch (n_type & MachO::N_TYPE) {
402 return SymbolRef::ST_Unknown;
404 return SymbolRef::ST_Function;
406 return SymbolRef::ST_Other;
409 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
412 uint8_t MachOType = Entry.n_type;
413 uint16_t MachOFlags = Entry.n_desc;
415 uint32_t Result = SymbolRef::SF_None;
417 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
418 Result |= SymbolRef::SF_Indirect;
420 if (MachOType & MachO::N_STAB)
421 Result |= SymbolRef::SF_FormatSpecific;
423 if (MachOType & MachO::N_EXT) {
424 Result |= SymbolRef::SF_Global;
425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
427 Result |= SymbolRef::SF_Common;
429 Result |= SymbolRef::SF_Undefined;
432 if (!(MachOType & MachO::N_PEXT))
433 Result |= SymbolRef::SF_Exported;
436 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
437 Result |= SymbolRef::SF_Weak;
439 if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
440 Result |= SymbolRef::SF_Thumb;
442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
443 Result |= SymbolRef::SF_Absolute;
448 ErrorOr<section_iterator>
449 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
451 uint8_t index = Entry.n_sect;
454 return section_end();
457 if (DRI.d.a >= Sections.size())
458 report_fatal_error("getSymbolSection: Invalid section index.");
459 return section_iterator(SectionRef(DRI, this));
462 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
463 MachO::nlist_base Entry =
464 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl());
465 return Entry.n_sect - 1;
468 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
472 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
473 StringRef &Result) const {
474 ArrayRef<char> Raw = getSectionRawName(Sec);
475 Result = parseSegmentOrSectionName(Raw.data());
476 return std::error_code();
479 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
481 return getSection64(Sec).addr;
482 return getSection(Sec).addr;
485 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
487 return getSection64(Sec).size;
488 return getSection(Sec).size;
491 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
492 StringRef &Res) const {
497 MachO::section_64 Sect = getSection64(Sec);
498 Offset = Sect.offset;
501 MachO::section Sect = getSection(Sec);
502 Offset = Sect.offset;
506 Res = this->getData().substr(Offset, Size);
507 return std::error_code();
510 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
513 MachO::section_64 Sect = getSection64(Sec);
516 MachO::section Sect = getSection(Sec);
520 return uint64_t(1) << Align;
523 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
524 uint32_t Flags = getSectionFlags(this, Sec);
525 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
528 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
529 uint32_t Flags = getSectionFlags(this, Sec);
530 unsigned SectionType = Flags & MachO::SECTION_TYPE;
531 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
532 !(SectionType == MachO::S_ZEROFILL ||
533 SectionType == MachO::S_GB_ZEROFILL);
536 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
537 uint32_t Flags = getSectionFlags(this, Sec);
538 unsigned SectionType = Flags & MachO::SECTION_TYPE;
539 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
540 (SectionType == MachO::S_ZEROFILL ||
541 SectionType == MachO::S_GB_ZEROFILL);
544 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
545 return Sec.getRawDataRefImpl().d.a;
548 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
549 // FIXME: Unimplemented.
553 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
557 return relocation_iterator(RelocationRef(Ret, this));
561 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
564 MachO::section_64 Sect = getSection64(Sec);
567 MachO::section Sect = getSection(Sec);
574 return relocation_iterator(RelocationRef(Ret, this));
577 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
581 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
582 assert(getHeader().filetype == MachO::MH_OBJECT &&
583 "Only implemented for MH_OBJECT");
584 MachO::any_relocation_info RE = getRelocation(Rel);
585 return getAnyRelocationAddress(RE);
589 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
590 MachO::any_relocation_info RE = getRelocation(Rel);
591 if (isRelocationScattered(RE))
594 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
595 bool isExtern = getPlainRelocationExternal(RE);
599 MachO::symtab_command S = getSymtabLoadCommand();
600 unsigned SymbolTableEntrySize = is64Bit() ?
601 sizeof(MachO::nlist_64) :
602 sizeof(MachO::nlist);
603 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
605 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
606 return symbol_iterator(SymbolRef(Sym, this));
610 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
611 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
614 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
615 MachO::any_relocation_info RE = getRelocation(Rel);
616 return getAnyRelocationType(RE);
619 void MachOObjectFile::getRelocationTypeName(
620 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
622 uint64_t RType = getRelocationType(Rel);
624 unsigned Arch = this->getArch();
628 static const char *const Table[] = {
629 "GENERIC_RELOC_VANILLA",
630 "GENERIC_RELOC_PAIR",
631 "GENERIC_RELOC_SECTDIFF",
632 "GENERIC_RELOC_PB_LA_PTR",
633 "GENERIC_RELOC_LOCAL_SECTDIFF",
634 "GENERIC_RELOC_TLV" };
642 case Triple::x86_64: {
643 static const char *const Table[] = {
644 "X86_64_RELOC_UNSIGNED",
645 "X86_64_RELOC_SIGNED",
646 "X86_64_RELOC_BRANCH",
647 "X86_64_RELOC_GOT_LOAD",
649 "X86_64_RELOC_SUBTRACTOR",
650 "X86_64_RELOC_SIGNED_1",
651 "X86_64_RELOC_SIGNED_2",
652 "X86_64_RELOC_SIGNED_4",
653 "X86_64_RELOC_TLV" };
662 static const char *const Table[] = {
665 "ARM_RELOC_SECTDIFF",
666 "ARM_RELOC_LOCAL_SECTDIFF",
667 "ARM_RELOC_PB_LA_PTR",
669 "ARM_THUMB_RELOC_BR22",
670 "ARM_THUMB_32BIT_BRANCH",
672 "ARM_RELOC_HALF_SECTDIFF" };
680 case Triple::aarch64: {
681 static const char *const Table[] = {
682 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
683 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
684 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
685 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
686 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
690 if (RType >= array_lengthof(Table))
697 static const char *const Table[] = {
706 "PPC_RELOC_SECTDIFF",
707 "PPC_RELOC_PB_LA_PTR",
708 "PPC_RELOC_HI16_SECTDIFF",
709 "PPC_RELOC_LO16_SECTDIFF",
710 "PPC_RELOC_HA16_SECTDIFF",
712 "PPC_RELOC_LO14_SECTDIFF",
713 "PPC_RELOC_LOCAL_SECTDIFF" };
721 case Triple::UnknownArch:
725 Result.append(res.begin(), res.end());
728 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
729 MachO::any_relocation_info RE = getRelocation(Rel);
730 return getAnyRelocationLength(RE);
734 // guessLibraryShortName() is passed a name of a dynamic library and returns a
735 // guess on what the short name is. Then name is returned as a substring of the
736 // StringRef Name passed in. The name of the dynamic library is recognized as
737 // a framework if it has one of the two following forms:
738 // Foo.framework/Versions/A/Foo
740 // Where A and Foo can be any string. And may contain a trailing suffix
741 // starting with an underbar. If the Name is recognized as a framework then
742 // isFramework is set to true else it is set to false. If the Name has a
743 // suffix then Suffix is set to the substring in Name that contains the suffix
744 // else it is set to a NULL StringRef.
746 // The Name of the dynamic library is recognized as a library name if it has
747 // one of the two following forms:
750 // The library may have a suffix trailing the name Foo of the form:
751 // libFoo_profile.A.dylib
752 // libFoo_profile.dylib
754 // The Name of the dynamic library is also recognized as a library name if it
755 // has the following form:
758 // If the Name of the dynamic library is none of the forms above then a NULL
759 // StringRef is returned.
761 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
764 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
765 size_t a, b, c, d, Idx;
768 Suffix = StringRef();
770 // Pull off the last component and make Foo point to it
772 if (a == Name.npos || a == 0)
774 Foo = Name.slice(a+1, Name.npos);
776 // Look for a suffix starting with a '_'
777 Idx = Foo.rfind('_');
778 if (Idx != Foo.npos && Foo.size() >= 2) {
779 Suffix = Foo.slice(Idx, Foo.npos);
780 Foo = Foo.slice(0, Idx);
783 // First look for the form Foo.framework/Foo
784 b = Name.rfind('/', a);
789 F = Name.slice(Idx, Idx + Foo.size());
790 DotFramework = Name.slice(Idx + Foo.size(),
791 Idx + Foo.size() + sizeof(".framework/")-1);
792 if (F == Foo && DotFramework == ".framework/") {
797 // Next look for the form Foo.framework/Versions/A/Foo
800 c = Name.rfind('/', b);
801 if (c == Name.npos || c == 0)
803 V = Name.slice(c+1, Name.npos);
804 if (!V.startswith("Versions/"))
806 d = Name.rfind('/', c);
811 F = Name.slice(Idx, Idx + Foo.size());
812 DotFramework = Name.slice(Idx + Foo.size(),
813 Idx + Foo.size() + sizeof(".framework/")-1);
814 if (F == Foo && DotFramework == ".framework/") {
820 // pull off the suffix after the "." and make a point to it
822 if (a == Name.npos || a == 0)
824 Dylib = Name.slice(a, Name.npos);
825 if (Dylib != ".dylib")
828 // First pull off the version letter for the form Foo.A.dylib if any.
830 Dot = Name.slice(a-2, a-1);
835 b = Name.rfind('/', a);
840 // ignore any suffix after an underbar like Foo_profile.A.dylib
841 Idx = Name.find('_', b);
842 if (Idx != Name.npos && Idx != b) {
843 Lib = Name.slice(b, Idx);
844 Suffix = Name.slice(Idx, a);
847 Lib = Name.slice(b, a);
848 // There are incorrect library names of the form:
849 // libATS.A_profile.dylib so check for these.
850 if (Lib.size() >= 3) {
851 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
853 Lib = Lib.slice(0, Lib.size()-2);
858 Qtx = Name.slice(a, Name.npos);
861 b = Name.rfind('/', a);
863 Lib = Name.slice(0, a);
865 Lib = Name.slice(b+1, a);
866 // There are library names of the form: QT.A.qtx so check for these.
867 if (Lib.size() >= 3) {
868 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
870 Lib = Lib.slice(0, Lib.size()-2);
875 // getLibraryShortNameByIndex() is used to get the short name of the library
876 // for an undefined symbol in a linked Mach-O binary that was linked with the
877 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
878 // It is passed the index (0 - based) of the library as translated from
879 // GET_LIBRARY_ORDINAL (1 - based).
880 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
881 StringRef &Res) const {
882 if (Index >= Libraries.size())
883 return object_error::parse_failed;
885 // If the cache of LibrariesShortNames is not built up do that first for
886 // all the Libraries.
887 if (LibrariesShortNames.size() == 0) {
888 for (unsigned i = 0; i < Libraries.size(); i++) {
889 MachO::dylib_command D =
890 getStruct<MachO::dylib_command>(this, Libraries[i]);
891 if (D.dylib.name >= D.cmdsize)
892 return object_error::parse_failed;
893 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
894 StringRef Name = StringRef(P);
895 if (D.dylib.name+Name.size() >= D.cmdsize)
896 return object_error::parse_failed;
899 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
900 if (shortName.empty())
901 LibrariesShortNames.push_back(Name);
903 LibrariesShortNames.push_back(shortName);
907 Res = LibrariesShortNames[Index];
908 return std::error_code();
912 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
914 Sec.d.a = Rel->getRawDataRefImpl().d.a;
915 return section_iterator(SectionRef(Sec, this));
918 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
919 return getSymbolByIndex(0);
922 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
925 return basic_symbol_iterator(SymbolRef(DRI, this));
927 MachO::symtab_command Symtab = getSymtabLoadCommand();
928 unsigned SymbolTableEntrySize = is64Bit() ?
929 sizeof(MachO::nlist_64) :
930 sizeof(MachO::nlist);
931 unsigned Offset = Symtab.symoff +
932 Symtab.nsyms * SymbolTableEntrySize;
933 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
934 return basic_symbol_iterator(SymbolRef(DRI, this));
937 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
940 return basic_symbol_iterator(SymbolRef(DRI, this));
942 MachO::symtab_command Symtab = getSymtabLoadCommand();
943 if (Index >= Symtab.nsyms)
944 report_fatal_error("Requested symbol index is out of range.");
945 unsigned SymbolTableEntrySize =
946 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
947 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
948 DRI.p += Index * SymbolTableEntrySize;
949 return basic_symbol_iterator(SymbolRef(DRI, this));
952 section_iterator MachOObjectFile::section_begin() const {
954 return section_iterator(SectionRef(DRI, this));
957 section_iterator MachOObjectFile::section_end() const {
959 DRI.d.a = Sections.size();
960 return section_iterator(SectionRef(DRI, this));
963 uint8_t MachOObjectFile::getBytesInAddress() const {
964 return is64Bit() ? 8 : 4;
967 StringRef MachOObjectFile::getFileFormatName() const {
968 unsigned CPUType = getCPUType(this);
971 case llvm::MachO::CPU_TYPE_I386:
972 return "Mach-O 32-bit i386";
973 case llvm::MachO::CPU_TYPE_ARM:
975 case llvm::MachO::CPU_TYPE_POWERPC:
976 return "Mach-O 32-bit ppc";
978 return "Mach-O 32-bit unknown";
983 case llvm::MachO::CPU_TYPE_X86_64:
984 return "Mach-O 64-bit x86-64";
985 case llvm::MachO::CPU_TYPE_ARM64:
986 return "Mach-O arm64";
987 case llvm::MachO::CPU_TYPE_POWERPC64:
988 return "Mach-O 64-bit ppc64";
990 return "Mach-O 64-bit unknown";
994 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
996 case llvm::MachO::CPU_TYPE_I386:
998 case llvm::MachO::CPU_TYPE_X86_64:
999 return Triple::x86_64;
1000 case llvm::MachO::CPU_TYPE_ARM:
1002 case llvm::MachO::CPU_TYPE_ARM64:
1003 return Triple::aarch64;
1004 case llvm::MachO::CPU_TYPE_POWERPC:
1006 case llvm::MachO::CPU_TYPE_POWERPC64:
1007 return Triple::ppc64;
1009 return Triple::UnknownArch;
1013 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1014 const char **McpuDefault) {
1016 *McpuDefault = nullptr;
1019 case MachO::CPU_TYPE_I386:
1020 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1021 case MachO::CPU_SUBTYPE_I386_ALL:
1022 return Triple("i386-apple-darwin");
1026 case MachO::CPU_TYPE_X86_64:
1027 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1028 case MachO::CPU_SUBTYPE_X86_64_ALL:
1029 return Triple("x86_64-apple-darwin");
1030 case MachO::CPU_SUBTYPE_X86_64_H:
1031 return Triple("x86_64h-apple-darwin");
1035 case MachO::CPU_TYPE_ARM:
1036 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1037 case MachO::CPU_SUBTYPE_ARM_V4T:
1038 return Triple("armv4t-apple-darwin");
1039 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1040 return Triple("armv5e-apple-darwin");
1041 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1042 return Triple("xscale-apple-darwin");
1043 case MachO::CPU_SUBTYPE_ARM_V6:
1044 return Triple("armv6-apple-darwin");
1045 case MachO::CPU_SUBTYPE_ARM_V6M:
1047 *McpuDefault = "cortex-m0";
1048 return Triple("armv6m-apple-darwin");
1049 case MachO::CPU_SUBTYPE_ARM_V7:
1050 return Triple("armv7-apple-darwin");
1051 case MachO::CPU_SUBTYPE_ARM_V7EM:
1053 *McpuDefault = "cortex-m4";
1054 return Triple("armv7em-apple-darwin");
1055 case MachO::CPU_SUBTYPE_ARM_V7K:
1056 return Triple("armv7k-apple-darwin");
1057 case MachO::CPU_SUBTYPE_ARM_V7M:
1059 *McpuDefault = "cortex-m3";
1060 return Triple("armv7m-apple-darwin");
1061 case MachO::CPU_SUBTYPE_ARM_V7S:
1062 return Triple("armv7s-apple-darwin");
1066 case MachO::CPU_TYPE_ARM64:
1067 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1068 case MachO::CPU_SUBTYPE_ARM64_ALL:
1069 return Triple("arm64-apple-darwin");
1073 case MachO::CPU_TYPE_POWERPC:
1074 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1075 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1076 return Triple("ppc-apple-darwin");
1080 case MachO::CPU_TYPE_POWERPC64:
1081 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1082 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1083 return Triple("ppc64-apple-darwin");
1092 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1093 const char **McpuDefault) {
1095 *McpuDefault = nullptr;
1098 case MachO::CPU_TYPE_ARM:
1099 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1100 case MachO::CPU_SUBTYPE_ARM_V4T:
1101 return Triple("thumbv4t-apple-darwin");
1102 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1103 return Triple("thumbv5e-apple-darwin");
1104 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1105 return Triple("xscale-apple-darwin");
1106 case MachO::CPU_SUBTYPE_ARM_V6:
1107 return Triple("thumbv6-apple-darwin");
1108 case MachO::CPU_SUBTYPE_ARM_V6M:
1110 *McpuDefault = "cortex-m0";
1111 return Triple("thumbv6m-apple-darwin");
1112 case MachO::CPU_SUBTYPE_ARM_V7:
1113 return Triple("thumbv7-apple-darwin");
1114 case MachO::CPU_SUBTYPE_ARM_V7EM:
1116 *McpuDefault = "cortex-m4";
1117 return Triple("thumbv7em-apple-darwin");
1118 case MachO::CPU_SUBTYPE_ARM_V7K:
1119 return Triple("thumbv7k-apple-darwin");
1120 case MachO::CPU_SUBTYPE_ARM_V7M:
1122 *McpuDefault = "cortex-m3";
1123 return Triple("thumbv7m-apple-darwin");
1124 case MachO::CPU_SUBTYPE_ARM_V7S:
1125 return Triple("thumbv7s-apple-darwin");
1134 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1135 const char **McpuDefault,
1136 Triple *ThumbTriple) {
1137 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1138 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1143 Triple MachOObjectFile::getHostArch() {
1144 return Triple(sys::getDefaultTargetTriple());
1147 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1148 return StringSwitch<bool>(ArchFlag)
1150 .Case("x86_64", true)
1151 .Case("x86_64h", true)
1152 .Case("armv4t", true)
1154 .Case("armv5e", true)
1155 .Case("armv6", true)
1156 .Case("armv6m", true)
1157 .Case("armv7", true)
1158 .Case("armv7em", true)
1159 .Case("armv7k", true)
1160 .Case("armv7m", true)
1161 .Case("armv7s", true)
1162 .Case("arm64", true)
1164 .Case("ppc64", true)
1168 unsigned MachOObjectFile::getArch() const {
1169 return getArch(getCPUType(this));
1172 Triple MachOObjectFile::getArch(const char **McpuDefault,
1173 Triple *ThumbTriple) const {
1174 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1175 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1178 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1181 return section_rel_begin(DRI);
1184 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1187 return section_rel_end(DRI);
1190 dice_iterator MachOObjectFile::begin_dices() const {
1192 if (!DataInCodeLoadCmd)
1193 return dice_iterator(DiceRef(DRI, this));
1195 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1196 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1197 return dice_iterator(DiceRef(DRI, this));
1200 dice_iterator MachOObjectFile::end_dices() const {
1202 if (!DataInCodeLoadCmd)
1203 return dice_iterator(DiceRef(DRI, this));
1205 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1206 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1208 return dice_iterator(DiceRef(DRI, this));
1211 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1212 : Trie(T), Malformed(false), Done(false) {}
1214 void ExportEntry::moveToFirst() {
1216 pushDownUntilBottom();
1219 void ExportEntry::moveToEnd() {
1224 bool ExportEntry::operator==(const ExportEntry &Other) const {
1225 // Common case, one at end, other iterating from begin.
1226 if (Done || Other.Done)
1227 return (Done == Other.Done);
1228 // Not equal if different stack sizes.
1229 if (Stack.size() != Other.Stack.size())
1231 // Not equal if different cumulative strings.
1232 if (!CumulativeString.equals(Other.CumulativeString))
1234 // Equal if all nodes in both stacks match.
1235 for (unsigned i=0; i < Stack.size(); ++i) {
1236 if (Stack[i].Start != Other.Stack[i].Start)
1242 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1244 uint64_t Result = decodeULEB128(Ptr, &Count);
1246 if (Ptr > Trie.end()) {
1253 StringRef ExportEntry::name() const {
1254 return CumulativeString;
1257 uint64_t ExportEntry::flags() const {
1258 return Stack.back().Flags;
1261 uint64_t ExportEntry::address() const {
1262 return Stack.back().Address;
1265 uint64_t ExportEntry::other() const {
1266 return Stack.back().Other;
1269 StringRef ExportEntry::otherName() const {
1270 const char* ImportName = Stack.back().ImportName;
1272 return StringRef(ImportName);
1276 uint32_t ExportEntry::nodeOffset() const {
1277 return Stack.back().Start - Trie.begin();
1280 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1281 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1282 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1283 ParentStringLength(0), IsExportNode(false) {}
1285 void ExportEntry::pushNode(uint64_t offset) {
1286 const uint8_t *Ptr = Trie.begin() + offset;
1287 NodeState State(Ptr);
1288 uint64_t ExportInfoSize = readULEB128(State.Current);
1289 State.IsExportNode = (ExportInfoSize != 0);
1290 const uint8_t* Children = State.Current + ExportInfoSize;
1291 if (State.IsExportNode) {
1292 State.Flags = readULEB128(State.Current);
1293 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1295 State.Other = readULEB128(State.Current); // dylib ordinal
1296 State.ImportName = reinterpret_cast<const char*>(State.Current);
1298 State.Address = readULEB128(State.Current);
1299 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1300 State.Other = readULEB128(State.Current);
1303 State.ChildCount = *Children;
1304 State.Current = Children + 1;
1305 State.NextChildIndex = 0;
1306 State.ParentStringLength = CumulativeString.size();
1307 Stack.push_back(State);
1310 void ExportEntry::pushDownUntilBottom() {
1311 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1312 NodeState &Top = Stack.back();
1313 CumulativeString.resize(Top.ParentStringLength);
1314 for (;*Top.Current != 0; Top.Current++) {
1315 char C = *Top.Current;
1316 CumulativeString.push_back(C);
1319 uint64_t childNodeIndex = readULEB128(Top.Current);
1320 Top.NextChildIndex += 1;
1321 pushNode(childNodeIndex);
1323 if (!Stack.back().IsExportNode) {
1329 // We have a trie data structure and need a way to walk it that is compatible
1330 // with the C++ iterator model. The solution is a non-recursive depth first
1331 // traversal where the iterator contains a stack of parent nodes along with a
1332 // string that is the accumulation of all edge strings along the parent chain
1335 // There is one "export" node for each exported symbol. But because some
1336 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1337 // node may have child nodes too.
1339 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1340 // child until hitting a node with no children (which is an export node or
1341 // else the trie is malformed). On the way down, each node is pushed on the
1342 // stack ivar. If there is no more ways down, it pops up one and tries to go
1343 // down a sibling path until a childless node is reached.
1344 void ExportEntry::moveNext() {
1345 if (Stack.empty() || !Stack.back().IsExportNode) {
1352 while (!Stack.empty()) {
1353 NodeState &Top = Stack.back();
1354 if (Top.NextChildIndex < Top.ChildCount) {
1355 pushDownUntilBottom();
1356 // Now at the next export node.
1359 if (Top.IsExportNode) {
1360 // This node has no children but is itself an export node.
1361 CumulativeString.resize(Top.ParentStringLength);
1370 iterator_range<export_iterator>
1371 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1372 ExportEntry Start(Trie);
1373 if (Trie.size() == 0)
1376 Start.moveToFirst();
1378 ExportEntry Finish(Trie);
1381 return iterator_range<export_iterator>(export_iterator(Start),
1382 export_iterator(Finish));
1385 iterator_range<export_iterator> MachOObjectFile::exports() const {
1386 return exports(getDyldInfoExportsTrie());
1390 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1391 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1392 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1393 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1395 void MachORebaseEntry::moveToFirst() {
1396 Ptr = Opcodes.begin();
1400 void MachORebaseEntry::moveToEnd() {
1401 Ptr = Opcodes.end();
1402 RemainingLoopCount = 0;
1406 void MachORebaseEntry::moveNext() {
1407 // If in the middle of some loop, move to next rebasing in loop.
1408 SegmentOffset += AdvanceAmount;
1409 if (RemainingLoopCount) {
1410 --RemainingLoopCount;
1413 if (Ptr == Opcodes.end()) {
1418 while (More && !Malformed) {
1419 // Parse next opcode and set up next loop.
1420 uint8_t Byte = *Ptr++;
1421 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1422 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1424 case MachO::REBASE_OPCODE_DONE:
1428 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1430 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1431 RebaseType = ImmValue;
1434 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1435 << "RebaseType=" << (int) RebaseType << "\n");
1437 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1438 SegmentIndex = ImmValue;
1439 SegmentOffset = readULEB128();
1442 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1443 << "SegmentIndex=" << SegmentIndex << ", "
1444 << format("SegmentOffset=0x%06X", SegmentOffset)
1447 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1448 SegmentOffset += readULEB128();
1449 DEBUG_WITH_TYPE("mach-o-rebase",
1450 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1451 << format("SegmentOffset=0x%06X",
1452 SegmentOffset) << "\n");
1454 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1455 SegmentOffset += ImmValue * PointerSize;
1456 DEBUG_WITH_TYPE("mach-o-rebase",
1457 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1458 << format("SegmentOffset=0x%06X",
1459 SegmentOffset) << "\n");
1461 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1462 AdvanceAmount = PointerSize;
1463 RemainingLoopCount = ImmValue - 1;
1466 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1467 << format("SegmentOffset=0x%06X", SegmentOffset)
1468 << ", AdvanceAmount=" << AdvanceAmount
1469 << ", RemainingLoopCount=" << RemainingLoopCount
1472 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1473 AdvanceAmount = PointerSize;
1474 RemainingLoopCount = readULEB128() - 1;
1477 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1478 << format("SegmentOffset=0x%06X", SegmentOffset)
1479 << ", AdvanceAmount=" << AdvanceAmount
1480 << ", RemainingLoopCount=" << RemainingLoopCount
1483 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1484 AdvanceAmount = readULEB128() + PointerSize;
1485 RemainingLoopCount = 0;
1488 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1489 << format("SegmentOffset=0x%06X", SegmentOffset)
1490 << ", AdvanceAmount=" << AdvanceAmount
1491 << ", RemainingLoopCount=" << RemainingLoopCount
1494 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1495 RemainingLoopCount = readULEB128() - 1;
1496 AdvanceAmount = readULEB128() + PointerSize;
1499 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1500 << format("SegmentOffset=0x%06X", SegmentOffset)
1501 << ", AdvanceAmount=" << AdvanceAmount
1502 << ", RemainingLoopCount=" << RemainingLoopCount
1511 uint64_t MachORebaseEntry::readULEB128() {
1513 uint64_t Result = decodeULEB128(Ptr, &Count);
1515 if (Ptr > Opcodes.end()) {
1516 Ptr = Opcodes.end();
1522 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1524 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1526 StringRef MachORebaseEntry::typeName() const {
1527 switch (RebaseType) {
1528 case MachO::REBASE_TYPE_POINTER:
1530 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1531 return "text abs32";
1532 case MachO::REBASE_TYPE_TEXT_PCREL32:
1533 return "text rel32";
1538 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1539 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1540 return (Ptr == Other.Ptr) &&
1541 (RemainingLoopCount == Other.RemainingLoopCount) &&
1542 (Done == Other.Done);
1545 iterator_range<rebase_iterator>
1546 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1547 MachORebaseEntry Start(Opcodes, is64);
1548 Start.moveToFirst();
1550 MachORebaseEntry Finish(Opcodes, is64);
1553 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1554 rebase_iterator(Finish));
1557 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1558 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1561 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
1562 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1563 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1564 BindType(0), PointerSize(is64Bit ? 8 : 4),
1565 TableKind(BK), Malformed(false), Done(false) {}
1567 void MachOBindEntry::moveToFirst() {
1568 Ptr = Opcodes.begin();
1572 void MachOBindEntry::moveToEnd() {
1573 Ptr = Opcodes.end();
1574 RemainingLoopCount = 0;
1578 void MachOBindEntry::moveNext() {
1579 // If in the middle of some loop, move to next binding in loop.
1580 SegmentOffset += AdvanceAmount;
1581 if (RemainingLoopCount) {
1582 --RemainingLoopCount;
1585 if (Ptr == Opcodes.end()) {
1590 while (More && !Malformed) {
1591 // Parse next opcode and set up next loop.
1592 uint8_t Byte = *Ptr++;
1593 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1594 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1595 int8_t SignExtended;
1596 const uint8_t *SymStart;
1598 case MachO::BIND_OPCODE_DONE:
1599 if (TableKind == Kind::Lazy) {
1600 // Lazying bindings have a DONE opcode between entries. Need to ignore
1601 // it to advance to next entry. But need not if this is last entry.
1602 bool NotLastEntry = false;
1603 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1605 NotLastEntry = true;
1614 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1616 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1620 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1621 << "Ordinal=" << Ordinal << "\n");
1623 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1624 Ordinal = readULEB128();
1627 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1628 << "Ordinal=" << Ordinal << "\n");
1630 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1632 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1633 Ordinal = SignExtended;
1638 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1639 << "Ordinal=" << Ordinal << "\n");
1641 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1647 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1652 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1653 << "SymbolName=" << SymbolName << "\n");
1654 if (TableKind == Kind::Weak) {
1655 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1659 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1660 BindType = ImmValue;
1663 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1664 << "BindType=" << (int)BindType << "\n");
1666 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1667 Addend = readSLEB128();
1668 if (TableKind == Kind::Lazy)
1672 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1673 << "Addend=" << Addend << "\n");
1675 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1676 SegmentIndex = ImmValue;
1677 SegmentOffset = readULEB128();
1680 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1681 << "SegmentIndex=" << SegmentIndex << ", "
1682 << format("SegmentOffset=0x%06X", SegmentOffset)
1685 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1686 SegmentOffset += readULEB128();
1687 DEBUG_WITH_TYPE("mach-o-bind",
1688 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1689 << format("SegmentOffset=0x%06X",
1690 SegmentOffset) << "\n");
1692 case MachO::BIND_OPCODE_DO_BIND:
1693 AdvanceAmount = PointerSize;
1694 RemainingLoopCount = 0;
1695 DEBUG_WITH_TYPE("mach-o-bind",
1696 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1697 << format("SegmentOffset=0x%06X",
1698 SegmentOffset) << "\n");
1700 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1701 AdvanceAmount = readULEB128() + PointerSize;
1702 RemainingLoopCount = 0;
1703 if (TableKind == Kind::Lazy)
1707 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1708 << format("SegmentOffset=0x%06X", SegmentOffset)
1709 << ", AdvanceAmount=" << AdvanceAmount
1710 << ", RemainingLoopCount=" << RemainingLoopCount
1713 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1714 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1715 RemainingLoopCount = 0;
1716 if (TableKind == Kind::Lazy)
1718 DEBUG_WITH_TYPE("mach-o-bind",
1720 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1721 << format("SegmentOffset=0x%06X",
1722 SegmentOffset) << "\n");
1724 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1725 RemainingLoopCount = readULEB128() - 1;
1726 AdvanceAmount = readULEB128() + PointerSize;
1727 if (TableKind == Kind::Lazy)
1731 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1732 << format("SegmentOffset=0x%06X", SegmentOffset)
1733 << ", AdvanceAmount=" << AdvanceAmount
1734 << ", RemainingLoopCount=" << RemainingLoopCount
1743 uint64_t MachOBindEntry::readULEB128() {
1745 uint64_t Result = decodeULEB128(Ptr, &Count);
1747 if (Ptr > Opcodes.end()) {
1748 Ptr = Opcodes.end();
1754 int64_t MachOBindEntry::readSLEB128() {
1756 int64_t Result = decodeSLEB128(Ptr, &Count);
1758 if (Ptr > Opcodes.end()) {
1759 Ptr = Opcodes.end();
1766 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1768 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1770 StringRef MachOBindEntry::typeName() const {
1772 case MachO::BIND_TYPE_POINTER:
1774 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1775 return "text abs32";
1776 case MachO::BIND_TYPE_TEXT_PCREL32:
1777 return "text rel32";
1782 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1784 int64_t MachOBindEntry::addend() const { return Addend; }
1786 uint32_t MachOBindEntry::flags() const { return Flags; }
1788 int MachOBindEntry::ordinal() const { return Ordinal; }
1790 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1791 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1792 return (Ptr == Other.Ptr) &&
1793 (RemainingLoopCount == Other.RemainingLoopCount) &&
1794 (Done == Other.Done);
1797 iterator_range<bind_iterator>
1798 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1799 MachOBindEntry::Kind BKind) {
1800 MachOBindEntry Start(Opcodes, is64, BKind);
1801 Start.moveToFirst();
1803 MachOBindEntry Finish(Opcodes, is64, BKind);
1806 return iterator_range<bind_iterator>(bind_iterator(Start),
1807 bind_iterator(Finish));
1810 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1811 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1812 MachOBindEntry::Kind::Regular);
1815 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1816 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1817 MachOBindEntry::Kind::Lazy);
1820 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1821 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1822 MachOBindEntry::Kind::Weak);
1825 MachOObjectFile::load_command_iterator
1826 MachOObjectFile::begin_load_commands() const {
1827 return LoadCommands.begin();
1830 MachOObjectFile::load_command_iterator
1831 MachOObjectFile::end_load_commands() const {
1832 return LoadCommands.end();
1835 iterator_range<MachOObjectFile::load_command_iterator>
1836 MachOObjectFile::load_commands() const {
1837 return iterator_range<load_command_iterator>(begin_load_commands(),
1838 end_load_commands());
1842 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1843 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1844 return parseSegmentOrSectionName(Raw.data());
1848 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1849 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1850 const section_base *Base =
1851 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1852 return makeArrayRef(Base->sectname);
1856 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1857 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1858 const section_base *Base =
1859 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1860 return makeArrayRef(Base->segname);
1864 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1866 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1868 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1871 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1872 const MachO::any_relocation_info &RE) const {
1873 if (isLittleEndian())
1874 return RE.r_word1 & 0xffffff;
1875 return RE.r_word1 >> 8;
1878 bool MachOObjectFile::getPlainRelocationExternal(
1879 const MachO::any_relocation_info &RE) const {
1880 if (isLittleEndian())
1881 return (RE.r_word1 >> 27) & 1;
1882 return (RE.r_word1 >> 4) & 1;
1885 bool MachOObjectFile::getScatteredRelocationScattered(
1886 const MachO::any_relocation_info &RE) const {
1887 return RE.r_word0 >> 31;
1890 uint32_t MachOObjectFile::getScatteredRelocationValue(
1891 const MachO::any_relocation_info &RE) const {
1895 uint32_t MachOObjectFile::getScatteredRelocationType(
1896 const MachO::any_relocation_info &RE) const {
1897 return (RE.r_word0 >> 24) & 0xf;
1900 unsigned MachOObjectFile::getAnyRelocationAddress(
1901 const MachO::any_relocation_info &RE) const {
1902 if (isRelocationScattered(RE))
1903 return getScatteredRelocationAddress(RE);
1904 return getPlainRelocationAddress(RE);
1907 unsigned MachOObjectFile::getAnyRelocationPCRel(
1908 const MachO::any_relocation_info &RE) const {
1909 if (isRelocationScattered(RE))
1910 return getScatteredRelocationPCRel(this, RE);
1911 return getPlainRelocationPCRel(this, RE);
1914 unsigned MachOObjectFile::getAnyRelocationLength(
1915 const MachO::any_relocation_info &RE) const {
1916 if (isRelocationScattered(RE))
1917 return getScatteredRelocationLength(RE);
1918 return getPlainRelocationLength(this, RE);
1922 MachOObjectFile::getAnyRelocationType(
1923 const MachO::any_relocation_info &RE) const {
1924 if (isRelocationScattered(RE))
1925 return getScatteredRelocationType(RE);
1926 return getPlainRelocationType(this, RE);
1930 MachOObjectFile::getAnyRelocationSection(
1931 const MachO::any_relocation_info &RE) const {
1932 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1933 return *section_end();
1934 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1935 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1936 return *section_end();
1938 DRI.d.a = SecNum - 1;
1939 return SectionRef(DRI, this);
1942 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1943 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1944 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1947 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1948 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1949 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1952 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1953 unsigned Index) const {
1954 const char *Sec = getSectionPtr(this, L, Index);
1955 return getStruct<MachO::section>(this, Sec);
1958 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1959 unsigned Index) const {
1960 const char *Sec = getSectionPtr(this, L, Index);
1961 return getStruct<MachO::section_64>(this, Sec);
1965 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1966 const char *P = reinterpret_cast<const char *>(DRI.p);
1967 return getStruct<MachO::nlist>(this, P);
1971 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1972 const char *P = reinterpret_cast<const char *>(DRI.p);
1973 return getStruct<MachO::nlist_64>(this, P);
1976 MachO::linkedit_data_command
1977 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1978 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1981 MachO::segment_command
1982 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1983 return getStruct<MachO::segment_command>(this, L.Ptr);
1986 MachO::segment_command_64
1987 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1988 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1991 MachO::linker_option_command
1992 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
1993 return getStruct<MachO::linker_option_command>(this, L.Ptr);
1996 MachO::version_min_command
1997 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1998 return getStruct<MachO::version_min_command>(this, L.Ptr);
2001 MachO::dylib_command
2002 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2003 return getStruct<MachO::dylib_command>(this, L.Ptr);
2006 MachO::dyld_info_command
2007 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2008 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2011 MachO::dylinker_command
2012 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2013 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2017 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2018 return getStruct<MachO::uuid_command>(this, L.Ptr);
2021 MachO::rpath_command
2022 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2023 return getStruct<MachO::rpath_command>(this, L.Ptr);
2026 MachO::source_version_command
2027 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2028 return getStruct<MachO::source_version_command>(this, L.Ptr);
2031 MachO::entry_point_command
2032 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2033 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2036 MachO::encryption_info_command
2037 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2038 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2041 MachO::encryption_info_command_64
2042 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2043 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2046 MachO::sub_framework_command
2047 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2048 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2051 MachO::sub_umbrella_command
2052 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2056 MachO::sub_library_command
2057 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2061 MachO::sub_client_command
2062 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2063 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2066 MachO::routines_command
2067 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::routines_command>(this, L.Ptr);
2071 MachO::routines_command_64
2072 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2073 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2076 MachO::thread_command
2077 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2078 return getStruct<MachO::thread_command>(this, L.Ptr);
2081 MachO::any_relocation_info
2082 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2087 MachO::section_64 Sect = getSection64(Sec);
2088 Offset = Sect.reloff;
2090 MachO::section Sect = getSection(Sec);
2091 Offset = Sect.reloff;
2094 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2095 getPtr(this, Offset)) + Rel.d.b;
2096 return getStruct<MachO::any_relocation_info>(
2097 this, reinterpret_cast<const char *>(P));
2100 MachO::data_in_code_entry
2101 MachOObjectFile::getDice(DataRefImpl Rel) const {
2102 const char *P = reinterpret_cast<const char *>(Rel.p);
2103 return getStruct<MachO::data_in_code_entry>(this, P);
2106 const MachO::mach_header &MachOObjectFile::getHeader() const {
2110 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2115 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2116 const MachO::dysymtab_command &DLC,
2117 unsigned Index) const {
2118 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2119 return getStruct<uint32_t>(this, getPtr(this, Offset));
2122 MachO::data_in_code_entry
2123 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2124 unsigned Index) const {
2125 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2126 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2129 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2131 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2133 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2134 MachO::symtab_command Cmd;
2135 Cmd.cmd = MachO::LC_SYMTAB;
2136 Cmd.cmdsize = sizeof(MachO::symtab_command);
2144 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2145 if (DysymtabLoadCmd)
2146 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2148 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2149 MachO::dysymtab_command Cmd;
2150 Cmd.cmd = MachO::LC_DYSYMTAB;
2151 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2162 Cmd.extrefsymoff = 0;
2163 Cmd.nextrefsyms = 0;
2164 Cmd.indirectsymoff = 0;
2165 Cmd.nindirectsyms = 0;
2173 MachO::linkedit_data_command
2174 MachOObjectFile::getDataInCodeLoadCommand() const {
2175 if (DataInCodeLoadCmd)
2176 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2178 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2179 MachO::linkedit_data_command Cmd;
2180 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2181 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2187 MachO::linkedit_data_command
2188 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2189 if (LinkOptHintsLoadCmd)
2190 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2192 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2194 MachO::linkedit_data_command Cmd;
2195 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2196 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2202 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2203 if (!DyldInfoLoadCmd)
2206 MachO::dyld_info_command DyldInfo =
2207 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2208 const uint8_t *Ptr =
2209 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
2210 return makeArrayRef(Ptr, DyldInfo.rebase_size);
2213 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2214 if (!DyldInfoLoadCmd)
2217 MachO::dyld_info_command DyldInfo =
2218 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2219 const uint8_t *Ptr =
2220 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
2221 return makeArrayRef(Ptr, DyldInfo.bind_size);
2224 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2225 if (!DyldInfoLoadCmd)
2228 MachO::dyld_info_command DyldInfo =
2229 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2230 const uint8_t *Ptr =
2231 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
2232 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
2235 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2236 if (!DyldInfoLoadCmd)
2239 MachO::dyld_info_command DyldInfo =
2240 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2241 const uint8_t *Ptr =
2242 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
2243 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
2246 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2247 if (!DyldInfoLoadCmd)
2250 MachO::dyld_info_command DyldInfo =
2251 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2252 const uint8_t *Ptr =
2253 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
2254 return makeArrayRef(Ptr, DyldInfo.export_size);
2257 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2260 // Returning a pointer is fine as uuid doesn't need endian swapping.
2261 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2262 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
2265 StringRef MachOObjectFile::getStringTableData() const {
2266 MachO::symtab_command S = getSymtabLoadCommand();
2267 return getData().substr(S.stroff, S.strsize);
2270 bool MachOObjectFile::is64Bit() const {
2271 return getType() == getMachOType(false, true) ||
2272 getType() == getMachOType(true, true);
2275 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2276 SmallVectorImpl<uint64_t> &Out) const {
2277 DataExtractor extractor(ObjectFile::getData(), true, 0);
2279 uint32_t offset = Index;
2281 while (uint64_t delta = extractor.getULEB128(&offset)) {
2283 Out.push_back(data);
2287 bool MachOObjectFile::isRelocatableObject() const {
2288 return getHeader().filetype == MachO::MH_OBJECT;
2291 ErrorOr<std::unique_ptr<MachOObjectFile>>
2292 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2293 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2295 std::unique_ptr<MachOObjectFile> Ret;
2296 if (Magic == "\xFE\xED\xFA\xCE")
2297 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2298 else if (Magic == "\xCE\xFA\xED\xFE")
2299 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2300 else if (Magic == "\xFE\xED\xFA\xCF")
2301 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2302 else if (Magic == "\xCF\xFA\xED\xFE")
2303 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2305 return object_error::parse_failed;
2309 return std::move(Ret);