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;
1013 // guessLibraryShortName() is passed a name of a dynamic library and returns a
1014 // guess on what the short name is. Then name is returned as a substring of the
1015 // StringRef Name passed in. The name of the dynamic library is recognized as
1016 // a framework if it has one of the two following forms:
1017 // Foo.framework/Versions/A/Foo
1018 // Foo.framework/Foo
1019 // Where A and Foo can be any string. And may contain a trailing suffix
1020 // starting with an underbar. If the Name is recognized as a framework then
1021 // isFramework is set to true else it is set to false. If the Name has a
1022 // suffix then Suffix is set to the substring in Name that contains the suffix
1023 // else it is set to a NULL StringRef.
1025 // The Name of the dynamic library is recognized as a library name if it has
1026 // one of the two following forms:
1029 // The library may have a suffix trailing the name Foo of the form:
1030 // libFoo_profile.A.dylib
1031 // libFoo_profile.dylib
1033 // The Name of the dynamic library is also recognized as a library name if it
1034 // has the following form:
1037 // If the Name of the dynamic library is none of the forms above then a NULL
1038 // StringRef is returned.
1040 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
1042 StringRef &Suffix) {
1043 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
1044 size_t a, b, c, d, Idx;
1046 isFramework = false;
1047 Suffix = StringRef();
1049 // Pull off the last component and make Foo point to it
1050 a = Name.rfind('/');
1051 if (a == Name.npos || a == 0)
1053 Foo = Name.slice(a+1, Name.npos);
1055 // Look for a suffix starting with a '_'
1056 Idx = Foo.rfind('_');
1057 if (Idx != Foo.npos && Foo.size() >= 2) {
1058 Suffix = Foo.slice(Idx, Foo.npos);
1059 Foo = Foo.slice(0, Idx);
1062 // First look for the form Foo.framework/Foo
1063 b = Name.rfind('/', a);
1068 F = Name.slice(Idx, Idx + Foo.size());
1069 DotFramework = Name.slice(Idx + Foo.size(),
1070 Idx + Foo.size() + sizeof(".framework/")-1);
1071 if (F == Foo && DotFramework == ".framework/") {
1076 // Next look for the form Foo.framework/Versions/A/Foo
1079 c = Name.rfind('/', b);
1080 if (c == Name.npos || c == 0)
1082 V = Name.slice(c+1, Name.npos);
1083 if (!V.startswith("Versions/"))
1085 d = Name.rfind('/', c);
1090 F = Name.slice(Idx, Idx + Foo.size());
1091 DotFramework = Name.slice(Idx + Foo.size(),
1092 Idx + Foo.size() + sizeof(".framework/")-1);
1093 if (F == Foo && DotFramework == ".framework/") {
1099 // pull off the suffix after the "." and make a point to it
1100 a = Name.rfind('.');
1101 if (a == Name.npos || a == 0)
1103 Dylib = Name.slice(a, Name.npos);
1104 if (Dylib != ".dylib")
1107 // First pull off the version letter for the form Foo.A.dylib if any.
1109 Dot = Name.slice(a-2, a-1);
1114 b = Name.rfind('/', a);
1119 // ignore any suffix after an underbar like Foo_profile.A.dylib
1120 Idx = Name.find('_', b);
1121 if (Idx != Name.npos && Idx != b) {
1122 Lib = Name.slice(b, Idx);
1123 Suffix = Name.slice(Idx, a);
1126 Lib = Name.slice(b, a);
1127 // There are incorrect library names of the form:
1128 // libATS.A_profile.dylib so check for these.
1129 if (Lib.size() >= 3) {
1130 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1132 Lib = Lib.slice(0, Lib.size()-2);
1137 Qtx = Name.slice(a, Name.npos);
1140 b = Name.rfind('/', a);
1142 Lib = Name.slice(0, a);
1144 Lib = Name.slice(b+1, a);
1145 // There are library names of the form: QT.A.qtx so check for these.
1146 if (Lib.size() >= 3) {
1147 Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
1149 Lib = Lib.slice(0, Lib.size()-2);
1154 // getLibraryShortNameByIndex() is used to get the short name of the library
1155 // for an undefined symbol in a linked Mach-O binary that was linked with the
1156 // normal two-level namespace default (that is MH_TWOLEVEL in the header).
1157 // It is passed the index (0 - based) of the library as translated from
1158 // GET_LIBRARY_ORDINAL (1 - based).
1159 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
1161 if (Index >= Libraries.size())
1162 return object_error::parse_failed;
1164 MachO::dylib_command D =
1165 getStruct<MachO::dylib_command>(this, Libraries[Index]);
1166 if (D.dylib.name >= D.cmdsize)
1167 return object_error::parse_failed;
1169 // If the cache of LibrariesShortNames is not built up do that first for
1170 // all the Libraries.
1171 if (LibrariesShortNames.size() == 0) {
1172 for (unsigned i = 0; i < Libraries.size(); i++) {
1173 MachO::dylib_command D =
1174 getStruct<MachO::dylib_command>(this, Libraries[i]);
1175 if (D.dylib.name >= D.cmdsize) {
1176 LibrariesShortNames.push_back(StringRef());
1179 const char *P = (const char *)(Libraries[i]) + D.dylib.name;
1180 StringRef Name = StringRef(P);
1183 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
1184 if (shortName == StringRef())
1185 LibrariesShortNames.push_back(Name);
1187 LibrariesShortNames.push_back(shortName);
1191 Res = LibrariesShortNames[Index];
1192 return object_error::success;
1195 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
1196 return getSymbolByIndex(0);
1199 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
1202 return basic_symbol_iterator(SymbolRef(DRI, this));
1204 MachO::symtab_command Symtab = getSymtabLoadCommand();
1205 unsigned SymbolTableEntrySize = is64Bit() ?
1206 sizeof(MachO::nlist_64) :
1207 sizeof(MachO::nlist);
1208 unsigned Offset = Symtab.symoff +
1209 Symtab.nsyms * SymbolTableEntrySize;
1210 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1211 return basic_symbol_iterator(SymbolRef(DRI, this));
1214 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
1217 return basic_symbol_iterator(SymbolRef(DRI, this));
1219 MachO::symtab_command Symtab = getSymtabLoadCommand();
1220 assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
1221 unsigned SymbolTableEntrySize =
1222 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
1223 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
1224 DRI.p += Index * SymbolTableEntrySize;
1225 return basic_symbol_iterator(SymbolRef(DRI, this));
1228 section_iterator MachOObjectFile::section_begin() const {
1230 return section_iterator(SectionRef(DRI, this));
1233 section_iterator MachOObjectFile::section_end() const {
1235 DRI.d.a = Sections.size();
1236 return section_iterator(SectionRef(DRI, this));
1239 uint8_t MachOObjectFile::getBytesInAddress() const {
1240 return is64Bit() ? 8 : 4;
1243 StringRef MachOObjectFile::getFileFormatName() const {
1244 unsigned CPUType = getCPUType(this);
1247 case llvm::MachO::CPU_TYPE_I386:
1248 return "Mach-O 32-bit i386";
1249 case llvm::MachO::CPU_TYPE_ARM:
1250 return "Mach-O arm";
1251 case llvm::MachO::CPU_TYPE_POWERPC:
1252 return "Mach-O 32-bit ppc";
1254 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
1255 "64-bit object file when we're not 64-bit?");
1256 return "Mach-O 32-bit unknown";
1260 // Make sure the cpu type has the correct mask.
1261 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1262 == llvm::MachO::CPU_ARCH_ABI64 &&
1263 "32-bit object file when we're 64-bit?");
1266 case llvm::MachO::CPU_TYPE_X86_64:
1267 return "Mach-O 64-bit x86-64";
1268 case llvm::MachO::CPU_TYPE_ARM64:
1269 return "Mach-O arm64";
1270 case llvm::MachO::CPU_TYPE_POWERPC64:
1271 return "Mach-O 64-bit ppc64";
1273 return "Mach-O 64-bit unknown";
1277 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1279 case llvm::MachO::CPU_TYPE_I386:
1281 case llvm::MachO::CPU_TYPE_X86_64:
1282 return Triple::x86_64;
1283 case llvm::MachO::CPU_TYPE_ARM:
1285 case llvm::MachO::CPU_TYPE_ARM64:
1286 return Triple::aarch64;
1287 case llvm::MachO::CPU_TYPE_POWERPC:
1289 case llvm::MachO::CPU_TYPE_POWERPC64:
1290 return Triple::ppc64;
1292 return Triple::UnknownArch;
1296 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
1298 case MachO::CPU_TYPE_I386:
1299 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1300 case MachO::CPU_SUBTYPE_I386_ALL:
1301 return Triple("i386-apple-darwin");
1305 case MachO::CPU_TYPE_X86_64:
1306 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1307 case MachO::CPU_SUBTYPE_X86_64_ALL:
1308 return Triple("x86_64-apple-darwin");
1309 case MachO::CPU_SUBTYPE_X86_64_H:
1310 return Triple("x86_64h-apple-darwin");
1314 case MachO::CPU_TYPE_ARM:
1315 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1316 case MachO::CPU_SUBTYPE_ARM_V4T:
1317 return Triple("armv4t-apple-darwin");
1318 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1319 return Triple("armv5e-apple-darwin");
1320 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1321 return Triple("xscale-apple-darwin");
1322 case MachO::CPU_SUBTYPE_ARM_V6:
1323 return Triple("armv6-apple-darwin");
1324 case MachO::CPU_SUBTYPE_ARM_V6M:
1325 return Triple("armv6m-apple-darwin");
1326 case MachO::CPU_SUBTYPE_ARM_V7:
1327 return Triple("armv7-apple-darwin");
1328 case MachO::CPU_SUBTYPE_ARM_V7EM:
1329 return Triple("armv7em-apple-darwin");
1330 case MachO::CPU_SUBTYPE_ARM_V7K:
1331 return Triple("armv7k-apple-darwin");
1332 case MachO::CPU_SUBTYPE_ARM_V7M:
1333 return Triple("armv7m-apple-darwin");
1334 case MachO::CPU_SUBTYPE_ARM_V7S:
1335 return Triple("armv7s-apple-darwin");
1339 case MachO::CPU_TYPE_ARM64:
1340 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1341 case MachO::CPU_SUBTYPE_ARM64_ALL:
1342 return Triple("arm64-apple-darwin");
1346 case MachO::CPU_TYPE_POWERPC:
1347 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1348 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1349 return Triple("ppc-apple-darwin");
1353 case MachO::CPU_TYPE_POWERPC64:
1354 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
1355 case MachO::CPU_SUBTYPE_POWERPC_ALL:
1356 return Triple("ppc64-apple-darwin");
1365 Triple MachOObjectFile::getHostArch() {
1366 return Triple(sys::getDefaultTargetTriple());
1369 bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
1370 return StringSwitch<bool>(ArchFlag)
1372 .Case("x86_64", true)
1373 .Case("x86_64h", true)
1374 .Case("armv4t", true)
1376 .Case("armv5e", true)
1377 .Case("armv6", true)
1378 .Case("armv6m", true)
1379 .Case("armv7em", true)
1380 .Case("armv7k", true)
1381 .Case("armv7m", true)
1382 .Case("armv7s", true)
1383 .Case("arm64", true)
1385 .Case("ppc64", true)
1389 unsigned MachOObjectFile::getArch() const {
1390 return getArch(getCPUType(this));
1393 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
1396 return section_rel_begin(DRI);
1399 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
1402 return section_rel_end(DRI);
1405 dice_iterator MachOObjectFile::begin_dices() const {
1407 if (!DataInCodeLoadCmd)
1408 return dice_iterator(DiceRef(DRI, this));
1410 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1411 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
1412 return dice_iterator(DiceRef(DRI, this));
1415 dice_iterator MachOObjectFile::end_dices() const {
1417 if (!DataInCodeLoadCmd)
1418 return dice_iterator(DiceRef(DRI, this));
1420 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
1421 unsigned Offset = DicLC.dataoff + DicLC.datasize;
1422 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1423 return dice_iterator(DiceRef(DRI, this));
1427 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1428 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1429 return parseSegmentOrSectionName(Raw.data());
1433 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1434 const section_base *Base =
1435 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1436 return ArrayRef<char>(Base->sectname);
1440 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1441 const section_base *Base =
1442 reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
1443 return ArrayRef<char>(Base->segname);
1447 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
1449 if (getCPUType(this) == MachO::CPU_TYPE_X86_64)
1451 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
1454 unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1455 const MachO::any_relocation_info &RE) const {
1456 if (isLittleEndian())
1457 return RE.r_word1 & 0xffffff;
1458 return RE.r_word1 >> 8;
1461 bool MachOObjectFile::getPlainRelocationExternal(
1462 const MachO::any_relocation_info &RE) const {
1463 if (isLittleEndian())
1464 return (RE.r_word1 >> 27) & 1;
1465 return (RE.r_word1 >> 4) & 1;
1468 bool MachOObjectFile::getScatteredRelocationScattered(
1469 const MachO::any_relocation_info &RE) const {
1470 return RE.r_word0 >> 31;
1473 uint32_t MachOObjectFile::getScatteredRelocationValue(
1474 const MachO::any_relocation_info &RE) const {
1478 unsigned MachOObjectFile::getAnyRelocationAddress(
1479 const MachO::any_relocation_info &RE) const {
1480 if (isRelocationScattered(RE))
1481 return getScatteredRelocationAddress(RE);
1482 return getPlainRelocationAddress(RE);
1485 unsigned MachOObjectFile::getAnyRelocationPCRel(
1486 const MachO::any_relocation_info &RE) const {
1487 if (isRelocationScattered(RE))
1488 return getScatteredRelocationPCRel(this, RE);
1489 return getPlainRelocationPCRel(this, RE);
1492 unsigned MachOObjectFile::getAnyRelocationLength(
1493 const MachO::any_relocation_info &RE) const {
1494 if (isRelocationScattered(RE))
1495 return getScatteredRelocationLength(RE);
1496 return getPlainRelocationLength(this, RE);
1500 MachOObjectFile::getAnyRelocationType(
1501 const MachO::any_relocation_info &RE) const {
1502 if (isRelocationScattered(RE))
1503 return getScatteredRelocationType(RE);
1504 return getPlainRelocationType(this, RE);
1508 MachOObjectFile::getRelocationSection(
1509 const MachO::any_relocation_info &RE) const {
1510 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1511 return *section_end();
1512 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1515 return SectionRef(DRI, this);
1518 MachOObjectFile::LoadCommandInfo
1519 MachOObjectFile::getFirstLoadCommandInfo() const {
1520 MachOObjectFile::LoadCommandInfo Load;
1522 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) :
1523 sizeof(MachO::mach_header);
1524 Load.Ptr = getPtr(this, HeaderSize);
1525 Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
1529 MachOObjectFile::LoadCommandInfo
1530 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1531 MachOObjectFile::LoadCommandInfo Next;
1532 Next.Ptr = L.Ptr + L.C.cmdsize;
1533 Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
1537 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
1538 return getStruct<MachO::section>(this, Sections[DRI.d.a]);
1541 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1542 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
1545 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
1546 unsigned Index) const {
1547 const char *Sec = getSectionPtr(this, L, Index);
1548 return getStruct<MachO::section>(this, Sec);
1551 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1552 unsigned Index) const {
1553 const char *Sec = getSectionPtr(this, L, Index);
1554 return getStruct<MachO::section_64>(this, Sec);
1558 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1559 const char *P = reinterpret_cast<const char *>(DRI.p);
1560 return getStruct<MachO::nlist>(this, P);
1564 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1565 const char *P = reinterpret_cast<const char *>(DRI.p);
1566 return getStruct<MachO::nlist_64>(this, P);
1569 MachO::linkedit_data_command
1570 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
1571 return getStruct<MachO::linkedit_data_command>(this, L.Ptr);
1574 MachO::segment_command
1575 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1576 return getStruct<MachO::segment_command>(this, L.Ptr);
1579 MachO::segment_command_64
1580 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1581 return getStruct<MachO::segment_command_64>(this, L.Ptr);
1584 MachO::linker_options_command
1585 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1586 return getStruct<MachO::linker_options_command>(this, L.Ptr);
1589 MachO::version_min_command
1590 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
1591 return getStruct<MachO::version_min_command>(this, L.Ptr);
1594 MachO::dylib_command
1595 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
1596 return getStruct<MachO::dylib_command>(this, L.Ptr);
1600 MachO::any_relocation_info
1601 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1606 MachO::section_64 Sect = getSection64(Sec);
1607 Offset = Sect.reloff;
1609 MachO::section Sect = getSection(Sec);
1610 Offset = Sect.reloff;
1613 auto P = reinterpret_cast<const MachO::any_relocation_info *>(
1614 getPtr(this, Offset)) + Rel.d.b;
1615 return getStruct<MachO::any_relocation_info>(
1616 this, reinterpret_cast<const char *>(P));
1619 MachO::data_in_code_entry
1620 MachOObjectFile::getDice(DataRefImpl Rel) const {
1621 const char *P = reinterpret_cast<const char *>(Rel.p);
1622 return getStruct<MachO::data_in_code_entry>(this, P);
1625 MachO::mach_header MachOObjectFile::getHeader() const {
1626 return getStruct<MachO::mach_header>(this, getPtr(this, 0));
1629 MachO::mach_header_64 MachOObjectFile::getHeader64() const {
1630 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
1633 uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
1634 const MachO::dysymtab_command &DLC,
1635 unsigned Index) const {
1636 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
1637 return getStruct<uint32_t>(this, getPtr(this, Offset));
1640 MachO::data_in_code_entry
1641 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1642 unsigned Index) const {
1643 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
1644 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset));
1647 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
1648 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd);
1651 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
1652 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd);
1655 MachO::linkedit_data_command
1656 MachOObjectFile::getDataInCodeLoadCommand() const {
1657 if (DataInCodeLoadCmd)
1658 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd);
1660 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1661 MachO::linkedit_data_command Cmd;
1662 Cmd.cmd = MachO::LC_DATA_IN_CODE;
1663 Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
1669 StringRef MachOObjectFile::getStringTableData() const {
1670 MachO::symtab_command S = getSymtabLoadCommand();
1671 return getData().substr(S.stroff, S.strsize);
1674 bool MachOObjectFile::is64Bit() const {
1675 return getType() == getMachOType(false, true) ||
1676 getType() == getMachOType(true, true);
1679 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1680 SmallVectorImpl<uint64_t> &Out) const {
1681 DataExtractor extractor(ObjectFile::getData(), true, 0);
1683 uint32_t offset = Index;
1685 while (uint64_t delta = extractor.getULEB128(&offset)) {
1687 Out.push_back(data);
1691 bool MachOObjectFile::isRelocatableObject() const {
1692 return getHeader().filetype == MachO::MH_OBJECT;
1695 ErrorOr<std::unique_ptr<MachOObjectFile>>
1696 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
1697 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1699 std::unique_ptr<MachOObjectFile> Ret;
1700 if (Magic == "\xFE\xED\xFA\xCE")
1701 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));
1702 else if (Magic == "\xCE\xFA\xED\xFE")
1703 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));
1704 else if (Magic == "\xFE\xED\xFA\xCF")
1705 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));
1706 else if (Magic == "\xCF\xFA\xED\xFE")
1707 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC));
1709 return object_error::parse_failed;
1713 return std::move(Ret);