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/Format.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/raw_ostream.h"
29 using namespace object;
39 static T getStruct(const MachOObjectFile *O, const char *P) {
41 memcpy(&Cmd, P, sizeof(T));
42 if (O->isLittleEndian() != sys::IsLittleEndianHost)
43 MachO::swapStruct(Cmd);
48 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
49 const MachOObjectFile::LoadCommandInfo &L) {
51 MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
54 MachO::segment_command S = O->getSegmentLoadCommand(L);
59 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
61 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
63 bool Is64 = O->is64Bit();
64 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
65 sizeof(MachO::segment_command);
66 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
67 sizeof(MachO::section);
69 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
70 return reinterpret_cast<const char*>(SectionAddr);
73 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
74 return O->getData().substr(Offset, 1).data();
77 static MachO::nlist_base
78 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
79 const char *P = reinterpret_cast<const char *>(DRI.p);
80 return getStruct<MachO::nlist_base>(O, P);
83 static StringRef parseSegmentOrSectionName(const char *P) {
87 // Not null terminated, so this is a 16 char string.
88 return StringRef(P, 16);
91 // Helper to advance a section or symbol iterator multiple increments at a time.
93 static void advance(T &it, size_t Val) {
98 static unsigned getCPUType(const MachOObjectFile *O) {
99 return O->getHeader().cputype;
102 static void printRelocationTargetName(const MachOObjectFile *O,
103 const MachO::any_relocation_info &RE,
104 raw_string_ostream &fmt) {
105 bool IsScattered = O->isRelocationScattered(RE);
107 // Target of a scattered relocation is an address. In the interest of
108 // generating pretty output, scan through the symbol table looking for a
109 // symbol that aligns with that address. If we find one, print it.
110 // Otherwise, we just print the hex address of the target.
112 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
114 for (const SymbolRef &Symbol : O->symbols()) {
119 if ((ec = Symbol.getAddress(Addr)))
120 report_fatal_error(ec.message());
123 if ((ec = Symbol.getName(Name)))
124 report_fatal_error(ec.message());
129 // If we couldn't find a symbol that this relocation refers to, try
130 // to find a section beginning instead.
131 for (const SectionRef &Section : O->sections()) {
136 if ((ec = Section.getAddress(Addr)))
137 report_fatal_error(ec.message());
140 if ((ec = Section.getName(Name)))
141 report_fatal_error(ec.message());
146 fmt << format("0x%x", Val);
151 bool isExtern = O->getPlainRelocationExternal(RE);
152 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
155 symbol_iterator SI = O->symbol_begin();
159 section_iterator SI = O->section_begin();
160 // Adjust for the fact that sections are 1-indexed.
161 advance(SI, Val - 1);
169 getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
174 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
175 return RE.r_word0 & 0xffffff;
178 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
179 const MachO::any_relocation_info &RE) {
180 if (O->isLittleEndian())
181 return (RE.r_word1 >> 24) & 1;
182 return (RE.r_word1 >> 7) & 1;
186 getScatteredRelocationPCRel(const MachOObjectFile *O,
187 const MachO::any_relocation_info &RE) {
188 return (RE.r_word0 >> 30) & 1;
191 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
192 const MachO::any_relocation_info &RE) {
193 if (O->isLittleEndian())
194 return (RE.r_word1 >> 25) & 3;
195 return (RE.r_word1 >> 5) & 3;
199 getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
200 return (RE.r_word0 >> 28) & 3;
203 static unsigned getPlainRelocationType(const MachOObjectFile *O,
204 const MachO::any_relocation_info &RE) {
205 if (O->isLittleEndian())
206 return RE.r_word1 >> 28;
207 return RE.r_word1 & 0xf;
211 getScatteredRelocationType(const MachO::any_relocation_info &RE) {
212 return (RE.r_word0 >> 24) & 0xf;
215 static uint32_t getSectionFlags(const MachOObjectFile *O,
218 MachO::section_64 Sect = O->getSection64(Sec);
221 MachO::section Sect = O->getSection(Sec);
225 MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,
226 bool IsLittleEndian, bool Is64bits,
228 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)),
229 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
230 DataInCodeLoadCmd(nullptr) {
231 uint32_t LoadCommandCount = this->getHeader().ncmds;
232 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
233 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
235 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
236 for (unsigned I = 0; ; ++I) {
237 if (Load.C.cmd == MachO::LC_SYMTAB) {
238 assert(!SymtabLoadCmd && "Multiple symbol tables");
239 SymtabLoadCmd = Load.Ptr;
240 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
241 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
242 DysymtabLoadCmd = Load.Ptr;
243 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
244 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
245 DataInCodeLoadCmd = Load.Ptr;
246 } else if (Load.C.cmd == SegmentLoadType) {
247 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
248 for (unsigned J = 0; J < NumSections; ++J) {
249 const char *Sec = getSectionPtr(this, Load, J);
250 Sections.push_back(Sec);
252 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
253 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
254 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
255 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
256 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
257 Libraries.push_back(Load.Ptr);
260 if (I == LoadCommandCount - 1)
263 Load = getNextLoadCommandInfo(Load);
267 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
268 unsigned SymbolTableEntrySize = is64Bit() ?
269 sizeof(MachO::nlist_64) :
270 sizeof(MachO::nlist);
271 Symb.p += SymbolTableEntrySize;
274 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
275 StringRef &Res) const {
276 StringRef StringTable = getStringTableData();
277 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
278 const char *Start = &StringTable.data()[Entry.n_strx];
279 Res = StringRef(Start);
280 return object_error::success;
283 // getIndirectName() returns the name of the alias'ed symbol who's string table
284 // index is in the n_value field.
285 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
286 StringRef &Res) const {
287 StringRef StringTable = getStringTableData();
290 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
291 NValue = Entry.n_value;
292 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
293 return object_error::parse_failed;
295 MachO::nlist Entry = getSymbolTableEntry(Symb);
296 NValue = Entry.n_value;
297 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
298 return object_error::parse_failed;
300 if (NValue >= StringTable.size())
301 return object_error::parse_failed;
302 const char *Start = &StringTable.data()[NValue];
303 Res = StringRef(Start);
304 return object_error::success;
307 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
308 uint64_t &Res) const {
310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb);
311 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
313 Res = UnknownAddressOrSize;
317 MachO::nlist Entry = getSymbolTableEntry(Symb);
318 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF &&
320 Res = UnknownAddressOrSize;
324 return object_error::success;
327 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
328 uint32_t &Result) const {
329 uint32_t flags = getSymbolFlags(DRI);
330 if (flags & SymbolRef::SF_Common) {
331 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
332 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
336 return object_error::success;
339 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
340 uint64_t &Result) const {
341 uint64_t BeginOffset;
342 uint64_t EndOffset = 0;
343 uint8_t SectionIndex;
345 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
347 getSymbolAddress(DRI, Value);
348 if (Value == UnknownAddressOrSize) {
349 Result = UnknownAddressOrSize;
350 return object_error::success;
355 SectionIndex = Entry.n_sect;
357 uint32_t flags = getSymbolFlags(DRI);
358 if (flags & SymbolRef::SF_Common)
361 Result = UnknownAddressOrSize;
362 return object_error::success;
364 // Unfortunately symbols are unsorted so we need to touch all
365 // symbols from load command
366 for (const SymbolRef &Symbol : symbols()) {
367 DataRefImpl DRI = Symbol.getRawDataRefImpl();
368 Entry = getSymbolTableEntryBase(this, DRI);
369 getSymbolAddress(DRI, Value);
370 if (Value == UnknownAddressOrSize)
372 if (Entry.n_sect == SectionIndex && Value > BeginOffset)
373 if (!EndOffset || Value < EndOffset)
379 Sec.d.a = SectionIndex-1;
380 getSectionSize(Sec, Size);
381 getSectionAddress(Sec, EndOffset);
384 Result = EndOffset - BeginOffset;
385 return object_error::success;
388 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
389 SymbolRef::Type &Res) const {
390 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
391 uint8_t n_type = Entry.n_type;
393 Res = SymbolRef::ST_Other;
395 // If this is a STAB debugging symbol, we can do nothing more.
396 if (n_type & MachO::N_STAB) {
397 Res = SymbolRef::ST_Debug;
398 return object_error::success;
401 switch (n_type & MachO::N_TYPE) {
403 Res = SymbolRef::ST_Unknown;
406 Res = SymbolRef::ST_Function;
409 return object_error::success;
412 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
413 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);
415 uint8_t MachOType = Entry.n_type;
416 uint16_t MachOFlags = Entry.n_desc;
418 uint32_t Result = SymbolRef::SF_None;
420 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
421 Result |= SymbolRef::SF_Undefined;
423 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
424 Result |= SymbolRef::SF_Indirect;
426 if (MachOType & MachO::N_STAB)
427 Result |= SymbolRef::SF_FormatSpecific;
429 if (MachOType & MachO::N_EXT) {
430 Result |= SymbolRef::SF_Global;
431 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
433 getSymbolAddress(DRI, Value);
434 if (Value && Value != UnknownAddressOrSize)
435 Result |= SymbolRef::SF_Common;
439 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
440 Result |= SymbolRef::SF_Weak;
442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
443 Result |= SymbolRef::SF_Absolute;
448 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
449 section_iterator &Res) const {
450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
451 uint8_t index = Entry.n_sect;
458 Res = section_iterator(SectionRef(DRI, this));
461 return object_error::success;
464 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
468 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec,
469 StringRef &Result) const {
470 ArrayRef<char> Raw = getSectionRawName(Sec);
471 Result = parseSegmentOrSectionName(Raw.data());
472 return object_error::success;
475 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
476 uint64_t &Res) const {
478 MachO::section_64 Sect = getSection64(Sec);
481 MachO::section Sect = getSection(Sec);
484 return object_error::success;
487 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
488 uint64_t &Res) const {
490 MachO::section_64 Sect = getSection64(Sec);
493 MachO::section Sect = getSection(Sec);
497 return object_error::success;
500 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
501 StringRef &Res) const {
506 MachO::section_64 Sect = getSection64(Sec);
507 Offset = Sect.offset;
510 MachO::section Sect = getSection(Sec);
511 Offset = Sect.offset;
515 Res = this->getData().substr(Offset, Size);
516 return object_error::success;
519 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
520 uint64_t &Res) const {
523 MachO::section_64 Sect = getSection64(Sec);
526 MachO::section Sect = getSection(Sec);
530 Res = uint64_t(1) << Align;
531 return object_error::success;
534 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
536 uint32_t Flags = getSectionFlags(this, Sec);
537 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
538 return object_error::success;
541 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
542 bool &Result) const {
543 uint32_t Flags = getSectionFlags(this, Sec);
544 unsigned SectionType = Flags & MachO::SECTION_TYPE;
545 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
546 !(SectionType == MachO::S_ZEROFILL ||
547 SectionType == MachO::S_GB_ZEROFILL);
548 return object_error::success;
551 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
552 bool &Result) const {
553 uint32_t Flags = getSectionFlags(this, Sec);
554 unsigned SectionType = Flags & MachO::SECTION_TYPE;
555 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
556 (SectionType == MachO::S_ZEROFILL ||
557 SectionType == MachO::S_GB_ZEROFILL);
558 return object_error::success;
562 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
563 bool &Result) const {
564 // FIXME: Unimplemented.
566 return object_error::success;
569 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
570 bool &Result) const {
571 // FIXME: Unimplemented.
573 return object_error::success;
576 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
578 uint32_t Flags = getSectionFlags(this, Sec);
579 unsigned SectionType = Flags & MachO::SECTION_TYPE;
580 Res = SectionType == MachO::S_ZEROFILL ||
581 SectionType == MachO::S_GB_ZEROFILL;
582 return object_error::success;
585 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
586 bool &Result) const {
587 // Consider using the code from isSectionText to look for __const sections.
588 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
589 // to use section attributes to distinguish code from data.
591 // FIXME: Unimplemented.
593 return object_error::success;
596 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
598 bool &Result) const {
600 this->getSymbolType(Symb, ST);
601 if (ST == SymbolRef::ST_Unknown) {
603 return object_error::success;
606 uint64_t SectBegin, SectEnd;
607 getSectionAddress(Sec, SectBegin);
608 getSectionSize(Sec, SectEnd);
609 SectEnd += SectBegin;
612 getSymbolAddress(Symb, SymAddr);
613 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
615 return object_error::success;
618 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
622 return relocation_iterator(RelocationRef(Ret, this));
626 MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
629 MachO::section_64 Sect = getSection64(Sec);
632 MachO::section Sect = getSection(Sec);
639 return relocation_iterator(RelocationRef(Ret, this));
642 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
646 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
647 uint64_t &Res) const {
649 getRelocationOffset(Rel, Offset);
654 getSectionAddress(Sec, SecAddress);
655 Res = SecAddress + Offset;
656 return object_error::success;
659 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
660 uint64_t &Res) const {
661 assert(getHeader().filetype == MachO::MH_OBJECT &&
662 "Only implemented for MH_OBJECT");
663 MachO::any_relocation_info RE = getRelocation(Rel);
664 Res = getAnyRelocationAddress(RE);
665 return object_error::success;
669 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
670 MachO::any_relocation_info RE = getRelocation(Rel);
671 if (isRelocationScattered(RE))
674 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
675 bool isExtern = getPlainRelocationExternal(RE);
679 MachO::symtab_command S = getSymtabLoadCommand();
680 unsigned SymbolTableEntrySize = is64Bit() ?
681 sizeof(MachO::nlist_64) :
682 sizeof(MachO::nlist);
683 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
685 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
686 return symbol_iterator(SymbolRef(Sym, this));
689 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
690 uint64_t &Res) const {
691 MachO::any_relocation_info RE = getRelocation(Rel);
692 Res = getAnyRelocationType(RE);
693 return object_error::success;
697 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
698 SmallVectorImpl<char> &Result) const {
701 getRelocationType(Rel, RType);
703 unsigned Arch = this->getArch();
707 static const char *const Table[] = {
708 "GENERIC_RELOC_VANILLA",
709 "GENERIC_RELOC_PAIR",
710 "GENERIC_RELOC_SECTDIFF",
711 "GENERIC_RELOC_PB_LA_PTR",
712 "GENERIC_RELOC_LOCAL_SECTDIFF",
713 "GENERIC_RELOC_TLV" };
721 case Triple::x86_64: {
722 static const char *const Table[] = {
723 "X86_64_RELOC_UNSIGNED",
724 "X86_64_RELOC_SIGNED",
725 "X86_64_RELOC_BRANCH",
726 "X86_64_RELOC_GOT_LOAD",
728 "X86_64_RELOC_SUBTRACTOR",
729 "X86_64_RELOC_SIGNED_1",
730 "X86_64_RELOC_SIGNED_2",
731 "X86_64_RELOC_SIGNED_4",
732 "X86_64_RELOC_TLV" };
741 static const char *const Table[] = {
744 "ARM_RELOC_SECTDIFF",
745 "ARM_RELOC_LOCAL_SECTDIFF",
746 "ARM_RELOC_PB_LA_PTR",
748 "ARM_THUMB_RELOC_BR22",
749 "ARM_THUMB_32BIT_BRANCH",
751 "ARM_RELOC_HALF_SECTDIFF" };
759 case Triple::aarch64: {
760 static const char *const Table[] = {
761 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
762 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
763 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
764 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
765 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
769 if (RType >= array_lengthof(Table))
776 static const char *const Table[] = {
785 "PPC_RELOC_SECTDIFF",
786 "PPC_RELOC_PB_LA_PTR",
787 "PPC_RELOC_HI16_SECTDIFF",
788 "PPC_RELOC_LO16_SECTDIFF",
789 "PPC_RELOC_HA16_SECTDIFF",
791 "PPC_RELOC_LO14_SECTDIFF",
792 "PPC_RELOC_LOCAL_SECTDIFF" };
800 case Triple::UnknownArch:
804 Result.append(res.begin(), res.end());
805 return object_error::success;
809 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
810 SmallVectorImpl<char> &Result) const {
811 MachO::any_relocation_info RE = getRelocation(Rel);
813 unsigned Arch = this->getArch();
816 raw_string_ostream fmt(fmtbuf);
817 unsigned Type = this->getAnyRelocationType(RE);
818 bool IsPCRel = this->getAnyRelocationPCRel(RE);
820 // Determine any addends that should be displayed with the relocation.
821 // These require decoding the relocation type, which is triple-specific.
823 // X86_64 has entirely custom relocation types.
824 if (Arch == Triple::x86_64) {
825 bool isPCRel = getAnyRelocationPCRel(RE);
828 case MachO::X86_64_RELOC_GOT_LOAD:
829 case MachO::X86_64_RELOC_GOT: {
830 printRelocationTargetName(this, RE, fmt);
832 if (isPCRel) fmt << "PCREL";
835 case MachO::X86_64_RELOC_SUBTRACTOR: {
836 DataRefImpl RelNext = Rel;
837 moveRelocationNext(RelNext);
838 MachO::any_relocation_info RENext = getRelocation(RelNext);
840 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
841 // X86_64_RELOC_UNSIGNED.
842 // NOTE: Scattered relocations don't exist on x86_64.
843 unsigned RType = getAnyRelocationType(RENext);
844 if (RType != MachO::X86_64_RELOC_UNSIGNED)
845 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
846 "X86_64_RELOC_SUBTRACTOR.");
848 // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
849 // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
850 printRelocationTargetName(this, RENext, fmt);
852 printRelocationTargetName(this, RE, fmt);
855 case MachO::X86_64_RELOC_TLV:
856 printRelocationTargetName(this, RE, fmt);
858 if (isPCRel) fmt << "P";
860 case MachO::X86_64_RELOC_SIGNED_1:
861 printRelocationTargetName(this, RE, fmt);
864 case MachO::X86_64_RELOC_SIGNED_2:
865 printRelocationTargetName(this, RE, fmt);
868 case MachO::X86_64_RELOC_SIGNED_4:
869 printRelocationTargetName(this, RE, fmt);
873 printRelocationTargetName(this, RE, fmt);
876 // X86 and ARM share some relocation types in common.
877 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
878 Arch == Triple::ppc) {
879 // Generic relocation types...
881 case MachO::GENERIC_RELOC_PAIR: // prints no info
882 return object_error::success;
883 case MachO::GENERIC_RELOC_SECTDIFF: {
884 DataRefImpl RelNext = Rel;
885 moveRelocationNext(RelNext);
886 MachO::any_relocation_info RENext = getRelocation(RelNext);
888 // X86 sect diff's must be followed by a relocation of type
889 // GENERIC_RELOC_PAIR.
890 unsigned RType = getAnyRelocationType(RENext);
892 if (RType != MachO::GENERIC_RELOC_PAIR)
893 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
894 "GENERIC_RELOC_SECTDIFF.");
896 printRelocationTargetName(this, RE, fmt);
898 printRelocationTargetName(this, RENext, fmt);
903 if (Arch == Triple::x86 || Arch == Triple::ppc) {
905 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
906 DataRefImpl RelNext = Rel;
907 moveRelocationNext(RelNext);
908 MachO::any_relocation_info RENext = getRelocation(RelNext);
910 // X86 sect diff's must be followed by a relocation of type
911 // GENERIC_RELOC_PAIR.
912 unsigned RType = getAnyRelocationType(RENext);
913 if (RType != MachO::GENERIC_RELOC_PAIR)
914 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
915 "GENERIC_RELOC_LOCAL_SECTDIFF.");
917 printRelocationTargetName(this, RE, fmt);
919 printRelocationTargetName(this, RENext, fmt);
922 case MachO::GENERIC_RELOC_TLV: {
923 printRelocationTargetName(this, RE, fmt);
925 if (IsPCRel) fmt << "P";
929 printRelocationTargetName(this, RE, fmt);
931 } else { // ARM-specific relocations
933 case MachO::ARM_RELOC_HALF:
934 case MachO::ARM_RELOC_HALF_SECTDIFF: {
935 // Half relocations steal a bit from the length field to encode
936 // whether this is an upper16 or a lower16 relocation.
937 bool isUpper = getAnyRelocationLength(RE) >> 1;
943 printRelocationTargetName(this, RE, fmt);
945 DataRefImpl RelNext = Rel;
946 moveRelocationNext(RelNext);
947 MachO::any_relocation_info RENext = getRelocation(RelNext);
949 // ARM half relocs must be followed by a relocation of type
951 unsigned RType = getAnyRelocationType(RENext);
952 if (RType != MachO::ARM_RELOC_PAIR)
953 report_fatal_error("Expected ARM_RELOC_PAIR after "
956 // NOTE: The half of the target virtual address is stashed in the
957 // address field of the secondary relocation, but we can't reverse
958 // engineer the constant offset from it without decoding the movw/movt
959 // instruction to find the other half in its immediate field.
961 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
962 // symbol/section pointer of the follow-on relocation.
963 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
965 printRelocationTargetName(this, RENext, fmt);
972 printRelocationTargetName(this, RE, fmt);
977 printRelocationTargetName(this, RE, fmt);
980 Result.append(fmtbuf.begin(), fmtbuf.end());
981 return object_error::success;
984 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
985 bool &Result) const {
986 unsigned Arch = getArch();
988 getRelocationType(Rel, Type);
992 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
994 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
995 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true;
996 } else if (Arch == Triple::x86_64) {
997 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
998 // an X86_64_RELOC_SUBTRACTOR.
999 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) {
1000 DataRefImpl RelPrev = Rel;
1003 getRelocationType(RelPrev, PrevType);
1004 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR)
1009 return object_error::success;
1012 std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1013 LibraryRef &Res) const {
1014 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1017 std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1018 StringRef &Res) const {
1019 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1023 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1024 // guess on what the short name is. Then name is returned as a substring of the
1025 // StringRef Name passed in. The name of the dynamic library is recognized as
1026 // a framework if it has one of the two following forms:
1027 // Foo.framework/Versions/A/Foo
1028 // Foo.framework/Foo
1029 // Where A and Foo can be any string. And may contain a trailing suffix
1030 // starting with an underbar. If the Name is recognized as a framework then
1031 // isFramework is set to true else it is set to false. If the Name has a
1032 // suffix then Suffix is set to the substring in Name that contains the suffix
1033 // else it is set to a NULL StringRef.
1035 // The Name of the dynamic library is recognized as a library name if it has
1036 // one of the two following forms:
1039 // The library may have a suffix trailing the name Foo of the form:
1040 // libFoo_profile.A.dylib
1041 // libFoo_profile.dylib
1043 // The Name of the dynamic library is also recognized as a library name if it
1044 // has the following form:
1047 // If the Name of the dynamic library is none of the forms above then a NULL
1048 // StringRef is returned.
1050 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1052 StringRef &Suffix) {
1053 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1054 size_t a, b, c, d, Idx;
1056 isFramework = false;
1057 Suffix = StringRef();
1059 // Pull off the last component and make Foo point to it
1060 a = Name.rfind('/');
1061 if (a == Name.npos || a == 0)
1063 Foo = Name.slice(a+1, Name.npos);
1065 // Look for a suffix starting with a '_'
1066 Idx = Foo.rfind('_');
1067 if (Idx != Foo.npos && Foo.size() >= 2) {
1068 Suffix = Foo.slice(Idx, Foo.npos);
1069 Foo = Foo.slice(0, Idx);
1072 // First look for the form Foo.framework/Foo
1073 b = Name.rfind('/', a);
1078 F = Name.slice(Idx, Idx + Foo.size());
1079 DotFramework = Name.slice(Idx + Foo.size(),
1080 Idx + Foo.size() + sizeof(".framework/")-1);
1081 if (F == Foo && DotFramework == ".framework/") {
1086 // Next look for the form Foo.framework/Versions/A/Foo
1089 c = Name.rfind('/', b);
1090 if (c == Name.npos || c == 0)
1092 V = Name.slice(c+1, Name.npos);
1093 if (!V.startswith("Versions/"))
1095 d = Name.rfind('/', c);
1100 F = Name.slice(Idx, Idx + Foo.size());
1101 DotFramework = Name.slice(Idx + Foo.size(),
1102 Idx + Foo.size() + sizeof(".framework/")-1);
1103 if (F == Foo && DotFramework == ".framework/") {
1109 // pull off the suffix after the "." and make a point to it
1110 a = Name.rfind('.');
1111 if (a == Name.npos || a == 0)
1113 Dylib = Name.slice(a, Name.npos);
1114 if (Dylib != ".dylib")
1117 // First pull off the version letter for the form Foo.A.dylib if any.
1119 Dot = Name.slice(a-2, a-1);
1124 b = Name.rfind('/', a);
1129 // ignore any suffix after an underbar like Foo_profile.A.dylib
1130 Idx = Name.find('_', b);
1131 if (Idx != Name.npos && Idx != b) {
1132 Lib = Name.slice(b, Idx);
1133 Suffix = Name.slice(Idx, a);
1136 Lib = Name.slice(b, a);
1137 // There are incorrect library names of the form:
1138 // libATS.A_profile.dylib so check for these.
1139 if (Lib.size() >= 3) {
1140 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1142 Lib = Lib.slice(0, Lib.size()-2);
1147 Qtx = Name.slice(a, Name.npos);
1150 b = Name.rfind('/', a);
1152 Lib = Name.slice(0, a);
1154 Lib = Name.slice(b+1, a);
1155 // There are library names of the form: QT.A.qtx so check for these.
1156 if (Lib.size() >= 3) {
1157 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1159 Lib = Lib.slice(0, Lib.size()-2);
1164 // getLibraryShortNameByIndex() is used to get the short name of the library
1165 // for an undefined symbol in a linked Mach-O binary that was linked with the
1166 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1167 // It is passed the index (0 - based) of the library as translated from
1168 // GET_LIBRARY_ORDINAL (1 - based).
1169 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1171 if (Index >= Libraries.size())
1172 return object_error::parse_failed;
1174 MachO::dylib_command D =
1175 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1176 if (D.dylib.name >= D.cmdsize)
1177 return object_error::parse_failed;
1179 // If the cache of LibrariesShortNames is not built up do that first for
1180 // all the Libraries.
1181 if (LibrariesShortNames.size() == 0) {
1182 for (unsigned i = 0; i < Libraries.size(); i++) {
1183 MachO::dylib_command D =
1184 getStruct<MachO::dylib_command>(this, Libraries[i]);
1185 if (D.dylib.name >= D.cmdsize) {
1186 LibrariesShortNames.push_back(StringRef());
1189 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1190 StringRef Name = StringRef(P);
1193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1194 if (shortName == StringRef())
1195 LibrariesShortNames.push_back(Name);
1197 LibrariesShortNames.push_back(shortName);
1201 Res = LibrariesShortNames[Index];
1202 return object_error::success;
1205 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1206 return getSymbolByIndex(0);
1209 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1212 return basic_symbol_iterator(SymbolRef(DRI, this));
1214 MachO::symtab_command Symtab = getSymtabLoadCommand();
1215 unsigned SymbolTableEntrySize = is64Bit() ?
1216 sizeof(MachO::nlist_64) :
1217 sizeof(MachO::nlist);
1218 unsigned Offset = Symtab.symoff +
1219 Symtab.nsyms * SymbolTableEntrySize;
1220 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1221 return basic_symbol_iterator(SymbolRef(DRI, this));
1224 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1227 return basic_symbol_iterator(SymbolRef(DRI, this));
1229 MachO::symtab_command Symtab = getSymtabLoadCommand();
1230 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1231 unsigned SymbolTableEntrySize =
1232 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1233 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1234 DRI.p += Index * SymbolTableEntrySize;
1235 return basic_symbol_iterator(SymbolRef(DRI, this));
1238 section_iterator MachOObjectFile::section_begin() const {
1240 return section_iterator(SectionRef(DRI, this));
1243 section_iterator MachOObjectFile::section_end() const {
1245 DRI.d.a = Sections.size();
1246 return section_iterator(SectionRef(DRI, this));
1249 library_iterator MachOObjectFile::needed_library_begin() const {
1251 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1254 library_iterator MachOObjectFile::needed_library_end() const {
1256 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1259 uint8_t MachOObjectFile::getBytesInAddress() const {
1260 return is64Bit() ? 8 : 4;
1263 StringRef MachOObjectFile::getFileFormatName() const {
1264 unsigned CPUType = getCPUType(this);
1267 case llvm::MachO::CPU_TYPE_I386:
1268 return "Mach-O 32-bit i386";
1269 case llvm::MachO::CPU_TYPE_ARM:
1270 return "Mach-O arm";
1271 case llvm::MachO::CPU_TYPE_POWERPC:
1272 return "Mach-O 32-bit ppc";
1274 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1275 "64-bit object file when we're not 64-bit?");
1276 return "Mach-O 32-bit unknown";
1280 // Make sure the cpu type has the correct mask.
1281 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1282 == llvm::MachO::CPU_ARCH_ABI64 &&
1283 "32-bit object file when we're 64-bit?");
1286 case llvm::MachO::CPU_TYPE_X86_64:
1287 return "Mach-O 64-bit x86-64";
1288 case llvm::MachO::CPU_TYPE_ARM64:
1289 return "Mach-O arm64";
1290 case llvm::MachO::CPU_TYPE_POWERPC64:
1291 return "Mach-O 64-bit ppc64";
1293 return "Mach-O 64-bit unknown";
1297 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1299 case llvm::MachO::CPU_TYPE_I386:
1301 case llvm::MachO::CPU_TYPE_X86_64:
1302 return Triple::x86_64;
1303 case llvm::MachO::CPU_TYPE_ARM:
1305 case llvm::MachO::CPU_TYPE_ARM64:
1306 return Triple::aarch64;
1307 case llvm::MachO::CPU_TYPE_POWERPC:
1309 case llvm::MachO::CPU_TYPE_POWERPC64:
1310 return Triple::ppc64;
1312 return Triple::UnknownArch;
1316 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
1318 case MachO::CPU_TYPE_I386:
1319 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1320 case MachO::CPU_SUBTYPE_I386_ALL:
1321 return Triple("i386-apple-darwin");
1325 case MachO::CPU_TYPE_X86_64:
1326 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1327 case MachO::CPU_SUBTYPE_X86_64_ALL:
1328 return Triple("x86_64-apple-darwin");
1329 case MachO::CPU_SUBTYPE_X86_64_H:
1330 return Triple("x86_64h-apple-darwin");
1334 case MachO::CPU_TYPE_ARM:
1335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1336 case MachO::CPU_SUBTYPE_ARM_V4T:
1337 return Triple("armv4t-apple-darwin");
1338 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1339 return Triple("armv5e-apple-darwin");
1340 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1341 return Triple("xscale-apple-darwin");
1342 case MachO::CPU_SUBTYPE_ARM_V6:
1343 return Triple("armv6-apple-darwin");
1344 case MachO::CPU_SUBTYPE_ARM_V6M:
1345 return Triple("armv6m-apple-darwin");
1346 case MachO::CPU_SUBTYPE_ARM_V7:
1347 return Triple("armv7-apple-darwin");
1348 case MachO::CPU_SUBTYPE_ARM_V7EM:
1349 return Triple("armv7em-apple-darwin");
1350 case MachO::CPU_SUBTYPE_ARM_V7K:
1351 return Triple("armv7k-apple-darwin");
1352 case MachO::CPU_SUBTYPE_ARM_V7M:
1353 return Triple("armv7m-apple-darwin");
1354 case MachO::CPU_SUBTYPE_ARM_V7S:
1355 return Triple("armv7s-apple-darwin");
1359 case MachO::CPU_TYPE_ARM64:
1360 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1361 case MachO::CPU_SUBTYPE_ARM64_ALL:
1362 return Triple("arm64-apple-darwin");
1366 case MachO::CPU_TYPE_POWERPC:
1367 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1368 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1369 return Triple("ppc-apple-darwin");
1373 case MachO::CPU_TYPE_POWERPC64:
1374 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1375 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1376 return Triple("ppc64-apple-darwin");
1385 Triple MachOObjectFile::getHostArch() {
1386 return Triple(sys::getDefaultTargetTriple());
1389 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1390 return StringSwitch<bool>(ArchFlag)
1392 .Case("x86_64", true)
1393 .Case("x86_64h", true)
1394 .Case("armv4t", true)
1396 .Case("armv5e", true)
1397 .Case("armv6", true)
1398 .Case("armv6m", true)
1399 .Case("armv7em", true)
1400 .Case("armv7k", true)
1401 .Case("armv7m", true)
1402 .Case("armv7s", true)
1403 .Case("arm64", true)
1405 .Case("ppc64", true)
1409 unsigned MachOObjectFile::getArch() const {
1410 return getArch(getCPUType(this));
1413 StringRef MachOObjectFile::getLoadName() const {
1415 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1418 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1421 return section_rel_begin(DRI);
1424 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1427 return section_rel_end(DRI);
1430 dice_iterator MachOObjectFile::begin_dices() const {
1432 if (!DataInCodeLoadCmd)
1433 return dice_iterator(DiceRef(DRI, this));
1435 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1436 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1437 return dice_iterator(DiceRef(DRI, this));
1440 dice_iterator MachOObjectFile::end_dices() const {
1442 if (!DataInCodeLoadCmd)
1443 return dice_iterator(DiceRef(DRI, this));
1445 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1446 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1447 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1448 return dice_iterator(DiceRef(DRI, this));
1452 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1453 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1454 return parseSegmentOrSectionName(Raw.data());
1458 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1459 const section_base *Base =
1460 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1461 return ArrayRef<char>(Base->sectname);
1465 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1466 const section_base *Base =
1467 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1468 return ArrayRef<char>(Base->segname);
1472 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1474 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1476 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1479 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1480 const MachO::any_relocation_info &RE) const {
1481 if (isLittleEndian())
1482 return RE.r_word1 & 0xffffff;
1483 return RE.r_word1 >> 8;
1486 bool MachOObjectFile::getPlainRelocationExternal(
1487 const MachO::any_relocation_info &RE) const {
1488 if (isLittleEndian())
1489 return (RE.r_word1 >> 27) & 1;
1490 return (RE.r_word1 >> 4) & 1;
1493 bool MachOObjectFile::getScatteredRelocationScattered(
1494 const MachO::any_relocation_info &RE) const {
1495 return RE.r_word0 >> 31;
1498 uint32_t MachOObjectFile::getScatteredRelocationValue(
1499 const MachO::any_relocation_info &RE) const {
1503 unsigned MachOObjectFile::getAnyRelocationAddress(
1504 const MachO::any_relocation_info &RE) const {
1505 if (isRelocationScattered(RE))
1506 return getScatteredRelocationAddress(RE);
1507 return getPlainRelocationAddress(RE);
1510 unsigned MachOObjectFile::getAnyRelocationPCRel(
1511 const MachO::any_relocation_info &RE) const {
1512 if (isRelocationScattered(RE))
1513 return getScatteredRelocationPCRel(this, RE);
1514 return getPlainRelocationPCRel(this, RE);
1517 unsigned MachOObjectFile::getAnyRelocationLength(
1518 const MachO::any_relocation_info &RE) const {
1519 if (isRelocationScattered(RE))
1520 return getScatteredRelocationLength(RE);
1521 return getPlainRelocationLength(this, RE);
1525 MachOObjectFile::getAnyRelocationType(
1526 const MachO::any_relocation_info &RE) const {
1527 if (isRelocationScattered(RE))
1528 return getScatteredRelocationType(RE);
1529 return getPlainRelocationType(this, RE);
1533 MachOObjectFile::getRelocationSection(
1534 const MachO::any_relocation_info &RE) const {
1535 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1536 return *section_end();
1537 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1540 return SectionRef(DRI, this);
1543 MachOObjectFile::LoadCommandInfo
1544 MachOObjectFile::getFirstLoadCommandInfo() const {
1545 MachOObjectFile::LoadCommandInfo Load;
1547 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1548 sizeof(MachO::mach_header);
1549 Load.Ptr = getPtr(this, HeaderSize);
1550 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1554 MachOObjectFile::LoadCommandInfo
1555 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1556 MachOObjectFile::LoadCommandInfo Next;
1557 Next.Ptr = L.Ptr + L.C.cmdsize;
1558 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1562 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1563 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1566 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1567 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1570 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1571 unsigned Index) const {
1572 const char *Sec = getSectionPtr(this, L, Index);
1573 return getStruct<MachO::section>(this, Sec);
1576 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1577 unsigned Index) const {
1578 const char *Sec = getSectionPtr(this, L, Index);
1579 return getStruct<MachO::section_64>(this, Sec);
1583 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1584 const char *P = reinterpret_cast<const char *>(DRI.p);
1585 return getStruct<MachO::nlist>(this, P);
1589 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1590 const char *P = reinterpret_cast<const char *>(DRI.p);
1591 return getStruct<MachO::nlist_64>(this, P);
1594 MachO::linkedit_data_command
1595 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1596 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1599 MachO::segment_command
1600 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1601 return getStruct<MachO::segment_command>(this, L.Ptr);
1604 MachO::segment_command_64
1605 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1606 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1609 MachO::linker_options_command
1610 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1611 return getStruct<MachO::linker_options_command>(this, L.Ptr);
1614 MachO::version_min_command
1615 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1616 return getStruct<MachO::version_min_command>(this, L.Ptr);
1619 MachO::dylib_command
1620 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1621 return getStruct<MachO::dylib_command>(this, L.Ptr);
1625 MachO::any_relocation_info
1626 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1631 MachO::section_64 Sect = getSection64(Sec);
1632 Offset = Sect.reloff;
1634 MachO::section Sect = getSection(Sec);
1635 Offset = Sect.reloff;
1638 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1639 getPtr(this, Offset)) + Rel.d.b;
1640 return getStruct<MachO::any_relocation_info>(
1641 this, reinterpret_cast<const char *>(P));
1644 MachO::data_in_code_entry
1645 MachOObjectFile::getDice(DataRefImpl Rel) const {
1646 const char *P = reinterpret_cast<const char *>(Rel.p);
1647 return getStruct<MachO::data_in_code_entry>(this, P);
1650 MachO::mach_header MachOObjectFile::getHeader() const {
1651 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1654 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1655 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1658 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1659 const MachO::dysymtab_command &DLC,
1660 unsigned Index) const {
1661 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1662 return getStruct<uint32_t>(this, getPtr(this, Offset));
1665 MachO::data_in_code_entry
1666 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1667 unsigned Index) const {
1668 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1669 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1672 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1673 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1676 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1677 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1680 MachO::linkedit_data_command
1681 MachOObjectFile::getDataInCodeLoadCommand() const {
1682 if (DataInCodeLoadCmd)
1683 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1685 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1686 MachO::linkedit_data_command Cmd;
1687 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1688 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1694 StringRef MachOObjectFile::getStringTableData() const {
1695 MachO::symtab_command S = getSymtabLoadCommand();
1696 return getData().substr(S.stroff, S.strsize);
1699 bool MachOObjectFile::is64Bit() const {
1700 return getType() == getMachOType(false, true) ||
1701 getType() == getMachOType(true, true);
1704 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1705 SmallVectorImpl<uint64_t> &Out) const {
1706 DataExtractor extractor(ObjectFile::getData(), true, 0);
1708 uint32_t offset = Index;
1710 while (uint64_t delta = extractor.getULEB128(&offset)) {
1712 Out.push_back(data);
1716 ErrorOr<std::unique_ptr<MachOObjectFile>>
1717 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
1718 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1720 std::unique_ptr<MachOObjectFile> Ret;
1721 if (Magic == "\xFE\xED\xFA\xCE")
1722 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
1723 else if (Magic == "\xCE\xFA\xED\xFE")
1724 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
1725 else if (Magic == "\xFE\xED\xFA\xCF")
1726 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
1727 else if (Magic == "\xCF\xFA\xED\xFE")
1728 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
1730 return object_error::parse_failed;
1734 return std::move(Ret);