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 {
486 // In the case if a malformed Mach-O file where the section offset is past
487 // the end of the file or some part of the section size is past the end of
488 // the file return a size of zero or a size that covers the rest of the file
489 // but does not extend past the end of the file.
490 uint32_t SectOffset, SectType;
494 MachO::section_64 Sect = getSection64(Sec);
495 SectOffset = Sect.offset;
496 SectSize = Sect.size;
497 SectType = Sect.flags & MachO::SECTION_TYPE;
499 MachO::section Sect = getSection(Sec);
500 SectOffset = Sect.offset;
501 SectSize = Sect.size;
502 SectType = Sect.flags & MachO::SECTION_TYPE;
504 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
506 uint64_t FileSize = getData().size();
507 if (SectOffset > FileSize)
509 if (FileSize - SectOffset < SectSize)
510 return FileSize - SectOffset;
514 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
515 StringRef &Res) const {
520 MachO::section_64 Sect = getSection64(Sec);
521 Offset = Sect.offset;
524 MachO::section Sect = getSection(Sec);
525 Offset = Sect.offset;
529 Res = this->getData().substr(Offset, Size);
530 return std::error_code();
533 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
536 MachO::section_64 Sect = getSection64(Sec);
539 MachO::section Sect = getSection(Sec);
543 return uint64_t(1) << Align;
546 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
547 uint32_t Flags = getSectionFlags(this, Sec);
548 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
551 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
552 uint32_t Flags = getSectionFlags(this, Sec);
553 unsigned SectionType = Flags & MachO::SECTION_TYPE;
554 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
555 !(SectionType == MachO::S_ZEROFILL ||
556 SectionType == MachO::S_GB_ZEROFILL);
559 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
560 uint32_t Flags = getSectionFlags(this, Sec);
561 unsigned SectionType = Flags & MachO::SECTION_TYPE;
562 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
563 (SectionType == MachO::S_ZEROFILL ||
564 SectionType == MachO::S_GB_ZEROFILL);
567 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
568 return Sec.getRawDataRefImpl().d.a;
571 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
572 // FIXME: Unimplemented.
576 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
580 return relocation_iterator(RelocationRef(Ret, this));
584 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
587 MachO::section_64 Sect = getSection64(Sec);
590 MachO::section Sect = getSection(Sec);
597 return relocation_iterator(RelocationRef(Ret, this));
600 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
604 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
605 assert(getHeader().filetype == MachO::MH_OBJECT &&
606 "Only implemented for MH_OBJECT");
607 MachO::any_relocation_info RE = getRelocation(Rel);
608 return getAnyRelocationAddress(RE);
612 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
613 MachO::any_relocation_info RE = getRelocation(Rel);
614 if (isRelocationScattered(RE))
617 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
618 bool isExtern = getPlainRelocationExternal(RE);
622 MachO::symtab_command S = getSymtabLoadCommand();
623 unsigned SymbolTableEntrySize = is64Bit() ?
624 sizeof(MachO::nlist_64) :
625 sizeof(MachO::nlist);
626 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
628 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
629 return symbol_iterator(SymbolRef(Sym, this));
633 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
634 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
637 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
638 MachO::any_relocation_info RE = getRelocation(Rel);
639 return getAnyRelocationType(RE);
642 void MachOObjectFile::getRelocationTypeName(
643 DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
645 uint64_t RType = getRelocationType(Rel);
647 unsigned Arch = this->getArch();
651 static const char *const Table[] = {
652 "GENERIC_RELOC_VANILLA",
653 "GENERIC_RELOC_PAIR",
654 "GENERIC_RELOC_SECTDIFF",
655 "GENERIC_RELOC_PB_LA_PTR",
656 "GENERIC_RELOC_LOCAL_SECTDIFF",
657 "GENERIC_RELOC_TLV" };
665 case Triple::x86_64: {
666 static const char *const Table[] = {
667 "X86_64_RELOC_UNSIGNED",
668 "X86_64_RELOC_SIGNED",
669 "X86_64_RELOC_BRANCH",
670 "X86_64_RELOC_GOT_LOAD",
672 "X86_64_RELOC_SUBTRACTOR",
673 "X86_64_RELOC_SIGNED_1",
674 "X86_64_RELOC_SIGNED_2",
675 "X86_64_RELOC_SIGNED_4",
676 "X86_64_RELOC_TLV" };
685 static const char *const Table[] = {
688 "ARM_RELOC_SECTDIFF",
689 "ARM_RELOC_LOCAL_SECTDIFF",
690 "ARM_RELOC_PB_LA_PTR",
692 "ARM_THUMB_RELOC_BR22",
693 "ARM_THUMB_32BIT_BRANCH",
695 "ARM_RELOC_HALF_SECTDIFF" };
703 case Triple::aarch64: {
704 static const char *const Table[] = {
705 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
706 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
707 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
708 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
709 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
713 if (RType >= array_lengthof(Table))
720 static const char *const Table[] = {
729 "PPC_RELOC_SECTDIFF",
730 "PPC_RELOC_PB_LA_PTR",
731 "PPC_RELOC_HI16_SECTDIFF",
732 "PPC_RELOC_LO16_SECTDIFF",
733 "PPC_RELOC_HA16_SECTDIFF",
735 "PPC_RELOC_LO14_SECTDIFF",
736 "PPC_RELOC_LOCAL_SECTDIFF" };
744 case Triple::UnknownArch:
748 Result.append(res.begin(), res.end());
751 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
752 MachO::any_relocation_info RE = getRelocation(Rel);
753 return getAnyRelocationLength(RE);
757 // guessLibraryShortName() is passed a name of a dynamic library and returns a
758 // guess on what the short name is. Then name is returned as a substring of the
759 // StringRef Name passed in. The name of the dynamic library is recognized as
760 // a framework if it has one of the two following forms:
761 // Foo.framework/Versions/A/Foo
763 // Where A and Foo can be any string. And may contain a trailing suffix
764 // starting with an underbar. If the Name is recognized as a framework then
765 // isFramework is set to true else it is set to false. If the Name has a
766 // suffix then Suffix is set to the substring in Name that contains the suffix
767 // else it is set to a NULL StringRef.
769 // The Name of the dynamic library is recognized as a library name if it has
770 // one of the two following forms:
773 // The library may have a suffix trailing the name Foo of the form:
774 // libFoo_profile.A.dylib
775 // libFoo_profile.dylib
777 // The Name of the dynamic library is also recognized as a library name if it
778 // has the following form:
781 // If the Name of the dynamic library is none of the forms above then a NULL
782 // StringRef is returned.
784 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
787 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
788 size_t a, b, c, d, Idx;
791 Suffix = StringRef();
793 // Pull off the last component and make Foo point to it
795 if (a == Name.npos || a == 0)
797 Foo = Name.slice(a+1, Name.npos);
799 // Look for a suffix starting with a '_'
800 Idx = Foo.rfind('_');
801 if (Idx != Foo.npos && Foo.size() >= 2) {
802 Suffix = Foo.slice(Idx, Foo.npos);
803 Foo = Foo.slice(0, Idx);
806 // First look for the form Foo.framework/Foo
807 b = Name.rfind('/', a);
812 F = Name.slice(Idx, Idx + Foo.size());
813 DotFramework = Name.slice(Idx + Foo.size(),
814 Idx + Foo.size() + sizeof(".framework/")-1);
815 if (F == Foo && DotFramework == ".framework/") {
820 // Next look for the form Foo.framework/Versions/A/Foo
823 c = Name.rfind('/', b);
824 if (c == Name.npos || c == 0)
826 V = Name.slice(c+1, Name.npos);
827 if (!V.startswith("Versions/"))
829 d = Name.rfind('/', c);
834 F = Name.slice(Idx, Idx + Foo.size());
835 DotFramework = Name.slice(Idx + Foo.size(),
836 Idx + Foo.size() + sizeof(".framework/")-1);
837 if (F == Foo && DotFramework == ".framework/") {
843 // pull off the suffix after the "." and make a point to it
845 if (a == Name.npos || a == 0)
847 Dylib = Name.slice(a, Name.npos);
848 if (Dylib != ".dylib")
851 // First pull off the version letter for the form Foo.A.dylib if any.
853 Dot = Name.slice(a-2, a-1);
858 b = Name.rfind('/', a);
863 // ignore any suffix after an underbar like Foo_profile.A.dylib
864 Idx = Name.find('_', b);
865 if (Idx != Name.npos && Idx != b) {
866 Lib = Name.slice(b, Idx);
867 Suffix = Name.slice(Idx, a);
870 Lib = Name.slice(b, a);
871 // There are incorrect library names of the form:
872 // libATS.A_profile.dylib so check for these.
873 if (Lib.size() >= 3) {
874 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
876 Lib = Lib.slice(0, Lib.size()-2);
881 Qtx = Name.slice(a, Name.npos);
884 b = Name.rfind('/', a);
886 Lib = Name.slice(0, a);
888 Lib = Name.slice(b+1, a);
889 // There are library names of the form: QT.A.qtx so check for these.
890 if (Lib.size() >= 3) {
891 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
893 Lib = Lib.slice(0, Lib.size()-2);
898 // getLibraryShortNameByIndex() is used to get the short name of the library
899 // for an undefined symbol in a linked Mach-O binary that was linked with the
900 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
901 // It is passed the index (0 - based) of the library as translated from
902 // GET_LIBRARY_ORDINAL (1 - based).
903 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
904 StringRef &Res) const {
905 if (Index >= Libraries.size())
906 return object_error::parse_failed;
908 // If the cache of LibrariesShortNames is not built up do that first for
909 // all the Libraries.
910 if (LibrariesShortNames.size() == 0) {
911 for (unsigned i = 0; i < Libraries.size(); i++) {
912 MachO::dylib_command D =
913 getStruct<MachO::dylib_command>(this, Libraries[i]);
914 if (D.dylib.name >= D.cmdsize)
915 return object_error::parse_failed;
916 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
917 StringRef Name = StringRef(P);
918 if (D.dylib.name+Name.size() >= D.cmdsize)
919 return object_error::parse_failed;
922 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
923 if (shortName.empty())
924 LibrariesShortNames.push_back(Name);
926 LibrariesShortNames.push_back(shortName);
930 Res = LibrariesShortNames[Index];
931 return std::error_code();
935 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
937 Sec.d.a = Rel->getRawDataRefImpl().d.a;
938 return section_iterator(SectionRef(Sec, this));
941 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
942 return getSymbolByIndex(0);
945 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
948 return basic_symbol_iterator(SymbolRef(DRI, this));
950 MachO::symtab_command Symtab = getSymtabLoadCommand();
951 unsigned SymbolTableEntrySize = is64Bit() ?
952 sizeof(MachO::nlist_64) :
953 sizeof(MachO::nlist);
954 unsigned Offset = Symtab.symoff +
955 Symtab.nsyms * SymbolTableEntrySize;
956 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
957 return basic_symbol_iterator(SymbolRef(DRI, this));
960 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
963 return basic_symbol_iterator(SymbolRef(DRI, this));
965 MachO::symtab_command Symtab = getSymtabLoadCommand();
966 if (Index >= Symtab.nsyms)
967 report_fatal_error("Requested symbol index is out of range.");
968 unsigned SymbolTableEntrySize =
969 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
970 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
971 DRI.p += Index * SymbolTableEntrySize;
972 return basic_symbol_iterator(SymbolRef(DRI, this));
975 section_iterator MachOObjectFile::section_begin() const {
977 return section_iterator(SectionRef(DRI, this));
980 section_iterator MachOObjectFile::section_end() const {
982 DRI.d.a = Sections.size();
983 return section_iterator(SectionRef(DRI, this));
986 uint8_t MachOObjectFile::getBytesInAddress() const {
987 return is64Bit() ? 8 : 4;
990 StringRef MachOObjectFile::getFileFormatName() const {
991 unsigned CPUType = getCPUType(this);
994 case llvm::MachO::CPU_TYPE_I386:
995 return "Mach-O 32-bit i386";
996 case llvm::MachO::CPU_TYPE_ARM:
998 case llvm::MachO::CPU_TYPE_POWERPC:
999 return "Mach-O 32-bit ppc";
1001 return "Mach-O 32-bit unknown";
1006 case llvm::MachO::CPU_TYPE_X86_64:
1007 return "Mach-O 64-bit x86-64";
1008 case llvm::MachO::CPU_TYPE_ARM64:
1009 return "Mach-O arm64";
1010 case llvm::MachO::CPU_TYPE_POWERPC64:
1011 return "Mach-O 64-bit ppc64";
1013 return "Mach-O 64-bit unknown";
1017 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1019 case llvm::MachO::CPU_TYPE_I386:
1021 case llvm::MachO::CPU_TYPE_X86_64:
1022 return Triple::x86_64;
1023 case llvm::MachO::CPU_TYPE_ARM:
1025 case llvm::MachO::CPU_TYPE_ARM64:
1026 return Triple::aarch64;
1027 case llvm::MachO::CPU_TYPE_POWERPC:
1029 case llvm::MachO::CPU_TYPE_POWERPC64:
1030 return Triple::ppc64;
1032 return Triple::UnknownArch;
1036 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1037 const char **McpuDefault) {
1039 *McpuDefault = nullptr;
1042 case MachO::CPU_TYPE_I386:
1043 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1044 case MachO::CPU_SUBTYPE_I386_ALL:
1045 return Triple("i386-apple-darwin");
1049 case MachO::CPU_TYPE_X86_64:
1050 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1051 case MachO::CPU_SUBTYPE_X86_64_ALL:
1052 return Triple("x86_64-apple-darwin");
1053 case MachO::CPU_SUBTYPE_X86_64_H:
1054 return Triple("x86_64h-apple-darwin");
1058 case MachO::CPU_TYPE_ARM:
1059 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1060 case MachO::CPU_SUBTYPE_ARM_V4T:
1061 return Triple("armv4t-apple-darwin");
1062 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1063 return Triple("armv5e-apple-darwin");
1064 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1065 return Triple("xscale-apple-darwin");
1066 case MachO::CPU_SUBTYPE_ARM_V6:
1067 return Triple("armv6-apple-darwin");
1068 case MachO::CPU_SUBTYPE_ARM_V6M:
1070 *McpuDefault = "cortex-m0";
1071 return Triple("armv6m-apple-darwin");
1072 case MachO::CPU_SUBTYPE_ARM_V7:
1073 return Triple("armv7-apple-darwin");
1074 case MachO::CPU_SUBTYPE_ARM_V7EM:
1076 *McpuDefault = "cortex-m4";
1077 return Triple("armv7em-apple-darwin");
1078 case MachO::CPU_SUBTYPE_ARM_V7K:
1079 return Triple("armv7k-apple-darwin");
1080 case MachO::CPU_SUBTYPE_ARM_V7M:
1082 *McpuDefault = "cortex-m3";
1083 return Triple("armv7m-apple-darwin");
1084 case MachO::CPU_SUBTYPE_ARM_V7S:
1085 return Triple("armv7s-apple-darwin");
1089 case MachO::CPU_TYPE_ARM64:
1090 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1091 case MachO::CPU_SUBTYPE_ARM64_ALL:
1092 return Triple("arm64-apple-darwin");
1096 case MachO::CPU_TYPE_POWERPC:
1097 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1098 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1099 return Triple("ppc-apple-darwin");
1103 case MachO::CPU_TYPE_POWERPC64:
1104 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1105 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1106 return Triple("ppc64-apple-darwin");
1115 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
1116 const char **McpuDefault) {
1118 *McpuDefault = nullptr;
1121 case MachO::CPU_TYPE_ARM:
1122 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1123 case MachO::CPU_SUBTYPE_ARM_V4T:
1124 return Triple("thumbv4t-apple-darwin");
1125 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1126 return Triple("thumbv5e-apple-darwin");
1127 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1128 return Triple("xscale-apple-darwin");
1129 case MachO::CPU_SUBTYPE_ARM_V6:
1130 return Triple("thumbv6-apple-darwin");
1131 case MachO::CPU_SUBTYPE_ARM_V6M:
1133 *McpuDefault = "cortex-m0";
1134 return Triple("thumbv6m-apple-darwin");
1135 case MachO::CPU_SUBTYPE_ARM_V7:
1136 return Triple("thumbv7-apple-darwin");
1137 case MachO::CPU_SUBTYPE_ARM_V7EM:
1139 *McpuDefault = "cortex-m4";
1140 return Triple("thumbv7em-apple-darwin");
1141 case MachO::CPU_SUBTYPE_ARM_V7K:
1142 return Triple("thumbv7k-apple-darwin");
1143 case MachO::CPU_SUBTYPE_ARM_V7M:
1145 *McpuDefault = "cortex-m3";
1146 return Triple("thumbv7m-apple-darwin");
1147 case MachO::CPU_SUBTYPE_ARM_V7S:
1148 return Triple("thumbv7s-apple-darwin");
1157 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
1158 const char **McpuDefault, Triple *ThumbTriple) {
1159 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
1160 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
1165 Triple MachOObjectFile::getHostArch() {
1166 return Triple(sys::getDefaultTargetTriple());
1169 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1170 return StringSwitch<bool>(ArchFlag)
1172 .Case("x86_64", true)
1173 .Case("x86_64h", true)
1174 .Case("armv4t", true)
1176 .Case("armv5e", true)
1177 .Case("armv6", true)
1178 .Case("armv6m", true)
1179 .Case("armv7", true)
1180 .Case("armv7em", true)
1181 .Case("armv7k", true)
1182 .Case("armv7m", true)
1183 .Case("armv7s", true)
1184 .Case("arm64", true)
1186 .Case("ppc64", true)
1190 unsigned MachOObjectFile::getArch() const {
1191 return getArch(getCPUType(this));
1194 Triple MachOObjectFile::getArch(const char **McpuDefault,
1195 Triple *ThumbTriple) const {
1196 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault);
1197 return getArch(Header.cputype, Header.cpusubtype, McpuDefault);
1200 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1203 return section_rel_begin(DRI);
1206 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1209 return section_rel_end(DRI);
1212 dice_iterator MachOObjectFile::begin_dices() const {
1214 if (!DataInCodeLoadCmd)
1215 return dice_iterator(DiceRef(DRI, this));
1217 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1218 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1219 return dice_iterator(DiceRef(DRI, this));
1222 dice_iterator MachOObjectFile::end_dices() const {
1224 if (!DataInCodeLoadCmd)
1225 return dice_iterator(DiceRef(DRI, this));
1227 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1228 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1229 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1230 return dice_iterator(DiceRef(DRI, this));
1233 ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
1234 : Trie(T), Malformed(false), Done(false) {}
1236 void ExportEntry::moveToFirst() {
1238 pushDownUntilBottom();
1241 void ExportEntry::moveToEnd() {
1246 bool ExportEntry::operator==(const ExportEntry &Other) const {
1247 // Common case, one at end, other iterating from begin.
1248 if (Done || Other.Done)
1249 return (Done == Other.Done);
1250 // Not equal if different stack sizes.
1251 if (Stack.size() != Other.Stack.size())
1253 // Not equal if different cumulative strings.
1254 if (!CumulativeString.equals(Other.CumulativeString))
1256 // Equal if all nodes in both stacks match.
1257 for (unsigned i=0; i < Stack.size(); ++i) {
1258 if (Stack[i].Start != Other.Stack[i].Start)
1264 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
1266 uint64_t Result = decodeULEB128(Ptr, &Count);
1268 if (Ptr > Trie.end()) {
1275 StringRef ExportEntry::name() const {
1276 return CumulativeString;
1279 uint64_t ExportEntry::flags() const {
1280 return Stack.back().Flags;
1283 uint64_t ExportEntry::address() const {
1284 return Stack.back().Address;
1287 uint64_t ExportEntry::other() const {
1288 return Stack.back().Other;
1291 StringRef ExportEntry::otherName() const {
1292 const char* ImportName = Stack.back().ImportName;
1294 return StringRef(ImportName);
1298 uint32_t ExportEntry::nodeOffset() const {
1299 return Stack.back().Start - Trie.begin();
1302 ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
1303 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
1304 ImportName(nullptr), ChildCount(0), NextChildIndex(0),
1305 ParentStringLength(0), IsExportNode(false) {}
1307 void ExportEntry::pushNode(uint64_t offset) {
1308 const uint8_t *Ptr = Trie.begin() + offset;
1309 NodeState State(Ptr);
1310 uint64_t ExportInfoSize = readULEB128(State.Current);
1311 State.IsExportNode = (ExportInfoSize != 0);
1312 const uint8_t* Children = State.Current + ExportInfoSize;
1313 if (State.IsExportNode) {
1314 State.Flags = readULEB128(State.Current);
1315 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
1317 State.Other = readULEB128(State.Current); // dylib ordinal
1318 State.ImportName = reinterpret_cast<const char*>(State.Current);
1320 State.Address = readULEB128(State.Current);
1321 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
1322 State.Other = readULEB128(State.Current);
1325 State.ChildCount = *Children;
1326 State.Current = Children + 1;
1327 State.NextChildIndex = 0;
1328 State.ParentStringLength = CumulativeString.size();
1329 Stack.push_back(State);
1332 void ExportEntry::pushDownUntilBottom() {
1333 while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
1334 NodeState &Top = Stack.back();
1335 CumulativeString.resize(Top.ParentStringLength);
1336 for (;*Top.Current != 0; Top.Current++) {
1337 char C = *Top.Current;
1338 CumulativeString.push_back(C);
1341 uint64_t childNodeIndex = readULEB128(Top.Current);
1342 Top.NextChildIndex += 1;
1343 pushNode(childNodeIndex);
1345 if (!Stack.back().IsExportNode) {
1351 // We have a trie data structure and need a way to walk it that is compatible
1352 // with the C++ iterator model. The solution is a non-recursive depth first
1353 // traversal where the iterator contains a stack of parent nodes along with a
1354 // string that is the accumulation of all edge strings along the parent chain
1357 // There is one "export" node for each exported symbol. But because some
1358 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
1359 // node may have child nodes too.
1361 // The algorithm for moveNext() is to keep moving down the leftmost unvisited
1362 // child until hitting a node with no children (which is an export node or
1363 // else the trie is malformed). On the way down, each node is pushed on the
1364 // stack ivar. If there is no more ways down, it pops up one and tries to go
1365 // down a sibling path until a childless node is reached.
1366 void ExportEntry::moveNext() {
1367 if (Stack.empty() || !Stack.back().IsExportNode) {
1374 while (!Stack.empty()) {
1375 NodeState &Top = Stack.back();
1376 if (Top.NextChildIndex < Top.ChildCount) {
1377 pushDownUntilBottom();
1378 // Now at the next export node.
1381 if (Top.IsExportNode) {
1382 // This node has no children but is itself an export node.
1383 CumulativeString.resize(Top.ParentStringLength);
1392 iterator_range<export_iterator>
1393 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
1394 ExportEntry Start(Trie);
1395 if (Trie.size() == 0)
1398 Start.moveToFirst();
1400 ExportEntry Finish(Trie);
1403 return iterator_range<export_iterator>(export_iterator(Start),
1404 export_iterator(Finish));
1407 iterator_range<export_iterator> MachOObjectFile::exports() const {
1408 return exports(getDyldInfoExportsTrie());
1411 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
1412 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1413 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
1414 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
1416 void MachORebaseEntry::moveToFirst() {
1417 Ptr = Opcodes.begin();
1421 void MachORebaseEntry::moveToEnd() {
1422 Ptr = Opcodes.end();
1423 RemainingLoopCount = 0;
1427 void MachORebaseEntry::moveNext() {
1428 // If in the middle of some loop, move to next rebasing in loop.
1429 SegmentOffset += AdvanceAmount;
1430 if (RemainingLoopCount) {
1431 --RemainingLoopCount;
1434 if (Ptr == Opcodes.end()) {
1439 while (More && !Malformed) {
1440 // Parse next opcode and set up next loop.
1441 uint8_t Byte = *Ptr++;
1442 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
1443 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
1445 case MachO::REBASE_OPCODE_DONE:
1449 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
1451 case MachO::REBASE_OPCODE_SET_TYPE_IMM:
1452 RebaseType = ImmValue;
1455 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
1456 << "RebaseType=" << (int) RebaseType << "\n");
1458 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1459 SegmentIndex = ImmValue;
1460 SegmentOffset = readULEB128();
1463 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1464 << "SegmentIndex=" << SegmentIndex << ", "
1465 << format("SegmentOffset=0x%06X", SegmentOffset)
1468 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
1469 SegmentOffset += readULEB128();
1470 DEBUG_WITH_TYPE("mach-o-rebase",
1471 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
1472 << format("SegmentOffset=0x%06X",
1473 SegmentOffset) << "\n");
1475 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
1476 SegmentOffset += ImmValue * PointerSize;
1477 DEBUG_WITH_TYPE("mach-o-rebase",
1478 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
1479 << format("SegmentOffset=0x%06X",
1480 SegmentOffset) << "\n");
1482 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
1483 AdvanceAmount = PointerSize;
1484 RemainingLoopCount = ImmValue - 1;
1487 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
1488 << format("SegmentOffset=0x%06X", SegmentOffset)
1489 << ", AdvanceAmount=" << AdvanceAmount
1490 << ", RemainingLoopCount=" << RemainingLoopCount
1493 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
1494 AdvanceAmount = PointerSize;
1495 RemainingLoopCount = readULEB128() - 1;
1498 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
1499 << format("SegmentOffset=0x%06X", SegmentOffset)
1500 << ", AdvanceAmount=" << AdvanceAmount
1501 << ", RemainingLoopCount=" << RemainingLoopCount
1504 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
1505 AdvanceAmount = readULEB128() + PointerSize;
1506 RemainingLoopCount = 0;
1509 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
1510 << format("SegmentOffset=0x%06X", SegmentOffset)
1511 << ", AdvanceAmount=" << AdvanceAmount
1512 << ", RemainingLoopCount=" << RemainingLoopCount
1515 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
1516 RemainingLoopCount = readULEB128() - 1;
1517 AdvanceAmount = readULEB128() + PointerSize;
1520 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
1521 << format("SegmentOffset=0x%06X", SegmentOffset)
1522 << ", AdvanceAmount=" << AdvanceAmount
1523 << ", RemainingLoopCount=" << RemainingLoopCount
1532 uint64_t MachORebaseEntry::readULEB128() {
1534 uint64_t Result = decodeULEB128(Ptr, &Count);
1536 if (Ptr > Opcodes.end()) {
1537 Ptr = Opcodes.end();
1543 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
1545 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
1547 StringRef MachORebaseEntry::typeName() const {
1548 switch (RebaseType) {
1549 case MachO::REBASE_TYPE_POINTER:
1551 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
1552 return "text abs32";
1553 case MachO::REBASE_TYPE_TEXT_PCREL32:
1554 return "text rel32";
1559 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
1560 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1561 return (Ptr == Other.Ptr) &&
1562 (RemainingLoopCount == Other.RemainingLoopCount) &&
1563 (Done == Other.Done);
1566 iterator_range<rebase_iterator>
1567 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
1568 MachORebaseEntry Start(Opcodes, is64);
1569 Start.moveToFirst();
1571 MachORebaseEntry Finish(Opcodes, is64);
1574 return iterator_range<rebase_iterator>(rebase_iterator(Start),
1575 rebase_iterator(Finish));
1578 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
1579 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
1582 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
1583 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
1584 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
1585 BindType(0), PointerSize(is64Bit ? 8 : 4),
1586 TableKind(BK), Malformed(false), Done(false) {}
1588 void MachOBindEntry::moveToFirst() {
1589 Ptr = Opcodes.begin();
1593 void MachOBindEntry::moveToEnd() {
1594 Ptr = Opcodes.end();
1595 RemainingLoopCount = 0;
1599 void MachOBindEntry::moveNext() {
1600 // If in the middle of some loop, move to next binding in loop.
1601 SegmentOffset += AdvanceAmount;
1602 if (RemainingLoopCount) {
1603 --RemainingLoopCount;
1606 if (Ptr == Opcodes.end()) {
1611 while (More && !Malformed) {
1612 // Parse next opcode and set up next loop.
1613 uint8_t Byte = *Ptr++;
1614 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
1615 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
1616 int8_t SignExtended;
1617 const uint8_t *SymStart;
1619 case MachO::BIND_OPCODE_DONE:
1620 if (TableKind == Kind::Lazy) {
1621 // Lazying bindings have a DONE opcode between entries. Need to ignore
1622 // it to advance to next entry. But need not if this is last entry.
1623 bool NotLastEntry = false;
1624 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
1626 NotLastEntry = true;
1635 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
1637 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1641 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
1642 << "Ordinal=" << Ordinal << "\n");
1644 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1645 Ordinal = readULEB128();
1648 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
1649 << "Ordinal=" << Ordinal << "\n");
1651 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1653 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
1654 Ordinal = SignExtended;
1659 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
1660 << "Ordinal=" << Ordinal << "\n");
1662 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1668 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
1673 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
1674 << "SymbolName=" << SymbolName << "\n");
1675 if (TableKind == Kind::Weak) {
1676 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
1680 case MachO::BIND_OPCODE_SET_TYPE_IMM:
1681 BindType = ImmValue;
1684 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
1685 << "BindType=" << (int)BindType << "\n");
1687 case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
1688 Addend = readSLEB128();
1689 if (TableKind == Kind::Lazy)
1693 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
1694 << "Addend=" << Addend << "\n");
1696 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1697 SegmentIndex = ImmValue;
1698 SegmentOffset = readULEB128();
1701 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
1702 << "SegmentIndex=" << SegmentIndex << ", "
1703 << format("SegmentOffset=0x%06X", SegmentOffset)
1706 case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
1707 SegmentOffset += readULEB128();
1708 DEBUG_WITH_TYPE("mach-o-bind",
1709 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
1710 << format("SegmentOffset=0x%06X",
1711 SegmentOffset) << "\n");
1713 case MachO::BIND_OPCODE_DO_BIND:
1714 AdvanceAmount = PointerSize;
1715 RemainingLoopCount = 0;
1716 DEBUG_WITH_TYPE("mach-o-bind",
1717 llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
1718 << format("SegmentOffset=0x%06X",
1719 SegmentOffset) << "\n");
1721 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1722 AdvanceAmount = readULEB128() + PointerSize;
1723 RemainingLoopCount = 0;
1724 if (TableKind == Kind::Lazy)
1728 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
1729 << format("SegmentOffset=0x%06X", SegmentOffset)
1730 << ", AdvanceAmount=" << AdvanceAmount
1731 << ", RemainingLoopCount=" << RemainingLoopCount
1734 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1735 AdvanceAmount = ImmValue * PointerSize + PointerSize;
1736 RemainingLoopCount = 0;
1737 if (TableKind == Kind::Lazy)
1739 DEBUG_WITH_TYPE("mach-o-bind",
1741 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
1742 << format("SegmentOffset=0x%06X",
1743 SegmentOffset) << "\n");
1745 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1746 RemainingLoopCount = readULEB128() - 1;
1747 AdvanceAmount = readULEB128() + PointerSize;
1748 if (TableKind == Kind::Lazy)
1752 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
1753 << format("SegmentOffset=0x%06X", SegmentOffset)
1754 << ", AdvanceAmount=" << AdvanceAmount
1755 << ", RemainingLoopCount=" << RemainingLoopCount
1764 uint64_t MachOBindEntry::readULEB128() {
1766 uint64_t Result = decodeULEB128(Ptr, &Count);
1768 if (Ptr > Opcodes.end()) {
1769 Ptr = Opcodes.end();
1775 int64_t MachOBindEntry::readSLEB128() {
1777 int64_t Result = decodeSLEB128(Ptr, &Count);
1779 if (Ptr > Opcodes.end()) {
1780 Ptr = Opcodes.end();
1786 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
1788 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
1790 StringRef MachOBindEntry::typeName() const {
1792 case MachO::BIND_TYPE_POINTER:
1794 case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
1795 return "text abs32";
1796 case MachO::BIND_TYPE_TEXT_PCREL32:
1797 return "text rel32";
1802 StringRef MachOBindEntry::symbolName() const { return SymbolName; }
1804 int64_t MachOBindEntry::addend() const { return Addend; }
1806 uint32_t MachOBindEntry::flags() const { return Flags; }
1808 int MachOBindEntry::ordinal() const { return Ordinal; }
1810 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
1811 assert(Opcodes == Other.Opcodes && "compare iterators of different files");
1812 return (Ptr == Other.Ptr) &&
1813 (RemainingLoopCount == Other.RemainingLoopCount) &&
1814 (Done == Other.Done);
1817 iterator_range<bind_iterator>
1818 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
1819 MachOBindEntry::Kind BKind) {
1820 MachOBindEntry Start(Opcodes, is64, BKind);
1821 Start.moveToFirst();
1823 MachOBindEntry Finish(Opcodes, is64, BKind);
1826 return iterator_range<bind_iterator>(bind_iterator(Start),
1827 bind_iterator(Finish));
1830 iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
1831 return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
1832 MachOBindEntry::Kind::Regular);
1835 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
1836 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
1837 MachOBindEntry::Kind::Lazy);
1840 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
1841 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
1842 MachOBindEntry::Kind::Weak);
1845 MachOObjectFile::load_command_iterator
1846 MachOObjectFile::begin_load_commands() const {
1847 return LoadCommands.begin();
1850 MachOObjectFile::load_command_iterator
1851 MachOObjectFile::end_load_commands() const {
1852 return LoadCommands.end();
1855 iterator_range<MachOObjectFile::load_command_iterator>
1856 MachOObjectFile::load_commands() const {
1857 return iterator_range<load_command_iterator>(begin_load_commands(),
1858 end_load_commands());
1862 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1863 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1864 return parseSegmentOrSectionName(Raw.data());
1868 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1869 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1870 const section_base *Base =
1871 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1872 return makeArrayRef(Base->sectname);
1876 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1877 assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
1878 const section_base *Base =
1879 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1880 return makeArrayRef(Base->segname);
1884 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1886 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1888 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1891 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1892 const MachO::any_relocation_info &RE) const {
1893 if (isLittleEndian())
1894 return RE.r_word1 & 0xffffff;
1895 return RE.r_word1 >> 8;
1898 bool MachOObjectFile::getPlainRelocationExternal(
1899 const MachO::any_relocation_info &RE) const {
1900 if (isLittleEndian())
1901 return (RE.r_word1 >> 27) & 1;
1902 return (RE.r_word1 >> 4) & 1;
1905 bool MachOObjectFile::getScatteredRelocationScattered(
1906 const MachO::any_relocation_info &RE) const {
1907 return RE.r_word0 >> 31;
1910 uint32_t MachOObjectFile::getScatteredRelocationValue(
1911 const MachO::any_relocation_info &RE) const {
1915 uint32_t MachOObjectFile::getScatteredRelocationType(
1916 const MachO::any_relocation_info &RE) const {
1917 return (RE.r_word0 >> 24) & 0xf;
1920 unsigned MachOObjectFile::getAnyRelocationAddress(
1921 const MachO::any_relocation_info &RE) const {
1922 if (isRelocationScattered(RE))
1923 return getScatteredRelocationAddress(RE);
1924 return getPlainRelocationAddress(RE);
1927 unsigned MachOObjectFile::getAnyRelocationPCRel(
1928 const MachO::any_relocation_info &RE) const {
1929 if (isRelocationScattered(RE))
1930 return getScatteredRelocationPCRel(this, RE);
1931 return getPlainRelocationPCRel(this, RE);
1934 unsigned MachOObjectFile::getAnyRelocationLength(
1935 const MachO::any_relocation_info &RE) const {
1936 if (isRelocationScattered(RE))
1937 return getScatteredRelocationLength(RE);
1938 return getPlainRelocationLength(this, RE);
1942 MachOObjectFile::getAnyRelocationType(
1943 const MachO::any_relocation_info &RE) const {
1944 if (isRelocationScattered(RE))
1945 return getScatteredRelocationType(RE);
1946 return getPlainRelocationType(this, RE);
1950 MachOObjectFile::getAnyRelocationSection(
1951 const MachO::any_relocation_info &RE) const {
1952 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1953 return *section_end();
1954 unsigned SecNum = getPlainRelocationSymbolNum(RE);
1955 if (SecNum == MachO::R_ABS || SecNum > Sections.size())
1956 return *section_end();
1958 DRI.d.a = SecNum - 1;
1959 return SectionRef(DRI, this);
1962 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1963 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1964 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1967 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1968 assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
1969 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1972 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1973 unsigned Index) const {
1974 const char *Sec = getSectionPtr(this, L, Index);
1975 return getStruct<MachO::section>(this, Sec);
1978 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1979 unsigned Index) const {
1980 const char *Sec = getSectionPtr(this, L, Index);
1981 return getStruct<MachO::section_64>(this, Sec);
1985 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1986 const char *P = reinterpret_cast<const char *>(DRI.p);
1987 return getStruct<MachO::nlist>(this, P);
1991 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1992 const char *P = reinterpret_cast<const char *>(DRI.p);
1993 return getStruct<MachO::nlist_64>(this, P);
1996 MachO::linkedit_data_command
1997 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1998 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
2001 MachO::segment_command
2002 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
2003 return getStruct<MachO::segment_command>(this, L.Ptr);
2006 MachO::segment_command_64
2007 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
2008 return getStruct<MachO::segment_command_64>(this, L.Ptr);
2011 MachO::linker_option_command
2012 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
2013 return getStruct<MachO::linker_option_command>(this, L.Ptr);
2016 MachO::version_min_command
2017 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
2018 return getStruct<MachO::version_min_command>(this, L.Ptr);
2021 MachO::dylib_command
2022 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
2023 return getStruct<MachO::dylib_command>(this, L.Ptr);
2026 MachO::dyld_info_command
2027 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
2028 return getStruct<MachO::dyld_info_command>(this, L.Ptr);
2031 MachO::dylinker_command
2032 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
2033 return getStruct<MachO::dylinker_command>(this, L.Ptr);
2037 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
2038 return getStruct<MachO::uuid_command>(this, L.Ptr);
2041 MachO::rpath_command
2042 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
2043 return getStruct<MachO::rpath_command>(this, L.Ptr);
2046 MachO::source_version_command
2047 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
2048 return getStruct<MachO::source_version_command>(this, L.Ptr);
2051 MachO::entry_point_command
2052 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
2053 return getStruct<MachO::entry_point_command>(this, L.Ptr);
2056 MachO::encryption_info_command
2057 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
2058 return getStruct<MachO::encryption_info_command>(this, L.Ptr);
2061 MachO::encryption_info_command_64
2062 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
2063 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr);
2066 MachO::sub_framework_command
2067 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
2068 return getStruct<MachO::sub_framework_command>(this, L.Ptr);
2071 MachO::sub_umbrella_command
2072 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
2073 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr);
2076 MachO::sub_library_command
2077 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
2078 return getStruct<MachO::sub_library_command>(this, L.Ptr);
2081 MachO::sub_client_command
2082 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
2083 return getStruct<MachO::sub_client_command>(this, L.Ptr);
2086 MachO::routines_command
2087 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
2088 return getStruct<MachO::routines_command>(this, L.Ptr);
2091 MachO::routines_command_64
2092 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
2093 return getStruct<MachO::routines_command_64>(this, L.Ptr);
2096 MachO::thread_command
2097 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
2098 return getStruct<MachO::thread_command>(this, L.Ptr);
2101 MachO::any_relocation_info
2102 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
2107 MachO::section_64 Sect = getSection64(Sec);
2108 Offset = Sect.reloff;
2110 MachO::section Sect = getSection(Sec);
2111 Offset = Sect.reloff;
2114 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
2115 getPtr(this, Offset)) + Rel.d.b;
2116 return getStruct<MachO::any_relocation_info>(
2117 this, reinterpret_cast<const char *>(P));
2120 MachO::data_in_code_entry
2121 MachOObjectFile::getDice(DataRefImpl Rel) const {
2122 const char *P = reinterpret_cast<const char *>(Rel.p);
2123 return getStruct<MachO::data_in_code_entry>(this, P);
2126 const MachO::mach_header &MachOObjectFile::getHeader() const {
2130 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
2135 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
2136 const MachO::dysymtab_command &DLC,
2137 unsigned Index) const {
2138 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
2139 return getStruct<uint32_t>(this, getPtr(this, Offset));
2142 MachO::data_in_code_entry
2143 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
2144 unsigned Index) const {
2145 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
2146 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
2149 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
2151 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
2153 // If there is no SymtabLoadCmd return a load command with zero'ed fields.
2154 MachO::symtab_command Cmd;
2155 Cmd.cmd = MachO::LC_SYMTAB;
2156 Cmd.cmdsize = sizeof(MachO::symtab_command);
2164 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
2165 if (DysymtabLoadCmd)
2166 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
2168 // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
2169 MachO::dysymtab_command Cmd;
2170 Cmd.cmd = MachO::LC_DYSYMTAB;
2171 Cmd.cmdsize = sizeof(MachO::dysymtab_command);
2182 Cmd.extrefsymoff = 0;
2183 Cmd.nextrefsyms = 0;
2184 Cmd.indirectsymoff = 0;
2185 Cmd.nindirectsyms = 0;
2193 MachO::linkedit_data_command
2194 MachOObjectFile::getDataInCodeLoadCommand() const {
2195 if (DataInCodeLoadCmd)
2196 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
2198 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
2199 MachO::linkedit_data_command Cmd;
2200 Cmd.cmd = MachO::LC_DATA_IN_CODE;
2201 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2207 MachO::linkedit_data_command
2208 MachOObjectFile::getLinkOptHintsLoadCommand() const {
2209 if (LinkOptHintsLoadCmd)
2210 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd);
2212 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
2214 MachO::linkedit_data_command Cmd;
2215 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
2216 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
2222 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
2223 if (!DyldInfoLoadCmd)
2226 MachO::dyld_info_command DyldInfo =
2227 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2228 const uint8_t *Ptr =
2229 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off));
2230 return makeArrayRef(Ptr, DyldInfo.rebase_size);
2233 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
2234 if (!DyldInfoLoadCmd)
2237 MachO::dyld_info_command DyldInfo =
2238 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2239 const uint8_t *Ptr =
2240 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off));
2241 return makeArrayRef(Ptr, DyldInfo.bind_size);
2244 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
2245 if (!DyldInfoLoadCmd)
2248 MachO::dyld_info_command DyldInfo =
2249 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2250 const uint8_t *Ptr =
2251 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off));
2252 return makeArrayRef(Ptr, DyldInfo.weak_bind_size);
2255 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
2256 if (!DyldInfoLoadCmd)
2259 MachO::dyld_info_command DyldInfo =
2260 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2261 const uint8_t *Ptr =
2262 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off));
2263 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
2266 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
2267 if (!DyldInfoLoadCmd)
2270 MachO::dyld_info_command DyldInfo =
2271 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);
2272 const uint8_t *Ptr =
2273 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off));
2274 return makeArrayRef(Ptr, DyldInfo.export_size);
2277 ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
2280 // Returning a pointer is fine as uuid doesn't need endian swapping.
2281 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
2282 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
2285 StringRef MachOObjectFile::getStringTableData() const {
2286 MachO::symtab_command S = getSymtabLoadCommand();
2287 return getData().substr(S.stroff, S.strsize);
2290 bool MachOObjectFile::is64Bit() const {
2291 return getType() == getMachOType(false, true) ||
2292 getType() == getMachOType(true, true);
2295 void MachOObjectFile::ReadULEB128s(uint64_t Index,
2296 SmallVectorImpl<uint64_t> &Out) const {
2297 DataExtractor extractor(ObjectFile::getData(), true, 0);
2299 uint32_t offset = Index;
2301 while (uint64_t delta = extractor.getULEB128(&offset)) {
2303 Out.push_back(data);
2307 bool MachOObjectFile::isRelocatableObject() const {
2308 return getHeader().filetype == MachO::MH_OBJECT;
2311 ErrorOr<std::unique_ptr<MachOObjectFile>>
2312 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) {
2313 StringRef Magic = Buffer.getBuffer().slice(0, 4);
2315 std::unique_ptr<MachOObjectFile> Ret;
2316 if (Magic == "\xFE\xED\xFA\xCE")
2317 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
2318 else if (Magic == "\xCE\xFA\xED\xFE")
2319 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
2320 else if (Magic == "\xFE\xED\xFA\xCF")
2321 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
2322 else if (Magic == "\xCF\xFA\xED\xFE")
2323 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
2325 return object_error::parse_failed;
2329 return std::move(Ret);