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/Triple.h"
17 #include "llvm/Object/MachOFormat.h"
18 #include "llvm/Support/DataExtractor.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/Host.h"
21 #include "llvm/Support/MemoryBuffer.h"
27 using namespace object;
32 struct SymbolTableEntryBase {
45 static void SwapValue(T &Value) {
46 Value = sys::SwapByteOrder(Value);
50 static void SwapStruct(T &Value);
53 void SwapStruct(macho::RelocationEntry &H) {
59 void SwapStruct(macho::LoadCommand &L) {
65 void SwapStruct(SymbolTableEntryBase &S) {
66 SwapValue(S.StringIndex);
71 void SwapStruct(macho::Section &S) {
76 SwapValue(S.RelocationTableOffset);
77 SwapValue(S.NumRelocationTableEntries);
79 SwapValue(S.Reserved1);
80 SwapValue(S.Reserved2);
84 void SwapStruct(macho::Section64 &S) {
89 SwapValue(S.RelocationTableOffset);
90 SwapValue(S.NumRelocationTableEntries);
92 SwapValue(S.Reserved1);
93 SwapValue(S.Reserved2);
94 SwapValue(S.Reserved3);
98 void SwapStruct(macho::SymbolTableEntry &S) {
99 SwapValue(S.StringIndex);
105 void SwapStruct(macho::Symbol64TableEntry &S) {
106 SwapValue(S.StringIndex);
112 void SwapStruct(macho::Header &H) {
114 SwapValue(H.CPUType);
115 SwapValue(H.CPUSubtype);
116 SwapValue(H.FileType);
117 SwapValue(H.NumLoadCommands);
118 SwapValue(H.SizeOfLoadCommands);
123 void SwapStruct(macho::SymtabLoadCommand &C) {
126 SwapValue(C.SymbolTableOffset);
127 SwapValue(C.NumSymbolTableEntries);
128 SwapValue(C.StringTableOffset);
129 SwapValue(C.StringTableSize);
133 void SwapStruct(macho::LinkeditDataLoadCommand &C) {
136 SwapValue(C.DataOffset);
137 SwapValue(C.DataSize);
141 void SwapStruct(macho::SegmentLoadCommand &C) {
144 SwapValue(C.VMAddress);
146 SwapValue(C.FileOffset);
147 SwapValue(C.FileSize);
148 SwapValue(C.MaxVMProtection);
149 SwapValue(C.InitialVMProtection);
150 SwapValue(C.NumSections);
155 void SwapStruct(macho::Segment64LoadCommand &C) {
158 SwapValue(C.VMAddress);
160 SwapValue(C.FileOffset);
161 SwapValue(C.FileSize);
162 SwapValue(C.MaxVMProtection);
163 SwapValue(C.InitialVMProtection);
164 SwapValue(C.NumSections);
169 T getStruct(const MachOObjectFile *O, const char *P) {
171 memcpy(&Cmd, P, sizeof(T));
172 if (O->isLittleEndian() != sys::IsLittleEndianHost)
177 static macho::SegmentLoadCommand
178 getSegmentLoadCommand(const MachOObjectFile *O,
179 const MachOObjectFile::LoadCommandInfo &L) {
180 return getStruct<macho::SegmentLoadCommand>(O, L.Ptr);
183 static macho::Segment64LoadCommand
184 getSegment64LoadCommand(const MachOObjectFile *O,
185 const MachOObjectFile::LoadCommandInfo &L) {
186 return getStruct<macho::Segment64LoadCommand>(O, L.Ptr);
190 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
191 const MachOObjectFile::LoadCommandInfo &L) {
193 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
194 return S.NumSections;
196 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
197 return S.NumSections;
200 static const SectionBase *
201 getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
203 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
205 bool Is64 = O->is64Bit();
206 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
207 sizeof(macho::SegmentLoadCommand);
208 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
209 sizeof(macho::Section);
211 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
212 return reinterpret_cast<const SectionBase*>(SectionAddr);
215 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
216 return O->getData().substr(Offset, 1).data();
219 static SymbolTableEntryBase
220 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
221 const char *P = reinterpret_cast<const char *>(DRI.p);
222 return getStruct<SymbolTableEntryBase>(O, P);
225 static StringRef parseSegmentOrSectionName(const char *P) {
229 // Not null terminated, so this is a 16 char string.
230 return StringRef(P, 16);
233 // Helper to advance a section or symbol iterator multiple increments at a time.
235 static error_code advance(T &it, size_t Val) {
244 static void advanceTo(T &it, size_t Val) {
245 if (error_code ec = advance(it, Val))
246 report_fatal_error(ec.message());
249 static unsigned getCPUType(const MachOObjectFile *O) {
250 return O->getHeader().CPUType;
253 static void printRelocationTargetName(const MachOObjectFile *O,
254 const macho::RelocationEntry &RE,
255 raw_string_ostream &fmt) {
256 bool IsScattered = O->isRelocationScattered(RE);
258 // Target of a scattered relocation is an address. In the interest of
259 // generating pretty output, scan through the symbol table looking for a
260 // symbol that aligns with that address. If we find one, print it.
261 // Otherwise, we just print the hex address of the target.
263 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
266 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
267 SI != SE; SI.increment(ec)) {
268 if (ec) report_fatal_error(ec.message());
273 if ((ec = SI->getAddress(Addr)))
274 report_fatal_error(ec.message());
275 if (Addr != Val) continue;
276 if ((ec = SI->getName(Name)))
277 report_fatal_error(ec.message());
282 // If we couldn't find a symbol that this relocation refers to, try
283 // to find a section beginning instead.
284 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
285 SI != SE; SI.increment(ec)) {
286 if (ec) report_fatal_error(ec.message());
291 if ((ec = SI->getAddress(Addr)))
292 report_fatal_error(ec.message());
293 if (Addr != Val) continue;
294 if ((ec = SI->getName(Name)))
295 report_fatal_error(ec.message());
300 fmt << format("0x%x", Val);
305 bool isExtern = O->getPlainRelocationExternal(RE);
306 uint64_t Val = O->getAnyRelocationAddress(RE);
309 symbol_iterator SI = O->begin_symbols();
313 section_iterator SI = O->begin_sections();
321 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
326 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
327 return RE.Word0 & 0xffffff;
330 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
331 const macho::RelocationEntry &RE) {
332 if (O->isLittleEndian())
333 return (RE.Word1 >> 24) & 1;
334 return (RE.Word1 >> 7) & 1;
338 getScatteredRelocationPCRel(const MachOObjectFile *O,
339 const macho::RelocationEntry &RE) {
340 return (RE.Word0 >> 30) & 1;
343 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
344 const macho::RelocationEntry &RE) {
345 if (O->isLittleEndian())
346 return (RE.Word1 >> 25) & 3;
347 return (RE.Word1 >> 5) & 3;
351 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
352 return (RE.Word0 >> 28) & 3;
355 static unsigned getPlainRelocationType(const MachOObjectFile *O,
356 const macho::RelocationEntry &RE) {
357 if (O->isLittleEndian())
358 return RE.Word1 >> 28;
359 return RE.Word1 & 0xf;
362 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
363 return (RE.Word0 >> 24) & 0xf;
366 static uint32_t getSectionFlags(const MachOObjectFile *O,
369 macho::Section64 Sect = O->getSection64(Sec);
372 macho::Section Sect = O->getSection(Sec);
376 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
377 bool IsLittleEndian, bool Is64bits,
379 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
380 SymtabLoadCmd(NULL) {
381 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
382 macho::LoadCommandType SegmentLoadType = is64Bit() ?
383 macho::LCT_Segment64 : macho::LCT_Segment;
385 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
386 for (unsigned I = 0; ; ++I) {
387 if (Load.C.Type == macho::LCT_Symtab) {
388 assert(!SymtabLoadCmd && "Multiple symbol tables");
389 SymtabLoadCmd = Load.Ptr;
392 if (Load.C.Type == SegmentLoadType) {
393 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
394 for (unsigned J = 0; J < NumSections; ++J) {
395 const SectionBase *Sec = getSectionBase(this, Load, J);
396 Sections.push_back(reinterpret_cast<const char*>(Sec));
400 if (I == LoadCommandCount - 1)
403 Load = getNextLoadCommandInfo(Load);
407 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
408 SymbolRef &Res) const {
409 unsigned SymbolTableEntrySize = is64Bit() ?
410 sizeof(macho::Symbol64TableEntry) :
411 sizeof(macho::SymbolTableEntry);
412 Symb.p += SymbolTableEntrySize;
413 Res = SymbolRef(Symb, this);
414 return object_error::success;
417 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
418 StringRef &Res) const {
419 macho::SymtabLoadCommand S = getSymtabLoadCommand();
420 const char *StringTable = getPtr(this, S.StringTableOffset);
421 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
422 const char *Start = &StringTable[Entry.StringIndex];
423 Res = StringRef(Start);
424 return object_error::success;
427 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
428 uint64_t &Res) const {
430 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
433 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
436 return object_error::success;
440 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
441 uint64_t &Res) const {
442 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
443 getSymbolAddress(Symb, Res);
444 if (Entry.SectionIndex) {
447 SecRel.d.a = Entry.SectionIndex-1;
449 macho::Section64 Sec = getSection64(SecRel);
450 Delta = Sec.Offset - Sec.Address;
452 macho::Section Sec = getSection(SecRel);
453 Delta = Sec.Offset - Sec.Address;
459 return object_error::success;
462 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
463 uint64_t &Result) const {
464 uint64_t BeginOffset;
465 uint64_t EndOffset = 0;
466 uint8_t SectionIndex;
468 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
470 getSymbolAddress(DRI, Value);
474 SectionIndex = Entry.SectionIndex;
476 uint32_t flags = SymbolRef::SF_None;
477 this->getSymbolFlags(DRI, flags);
478 if (flags & SymbolRef::SF_Common)
481 Result = UnknownAddressOrSize;
482 return object_error::success;
484 // Unfortunately symbols are unsorted so we need to touch all
485 // symbols from load command
487 for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
489 DataRefImpl DRI = I->getRawDataRefImpl();
490 Entry = getSymbolTableEntryBase(this, DRI);
491 getSymbolAddress(DRI, Value);
492 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
493 if (!EndOffset || Value < EndOffset)
499 Sec.d.a = SectionIndex-1;
500 getSectionSize(Sec, Size);
501 getSectionAddress(Sec, EndOffset);
504 Result = EndOffset - BeginOffset;
505 return object_error::success;
508 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
509 SymbolRef::Type &Res) const {
510 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
511 uint8_t n_type = Entry.Type;
513 Res = SymbolRef::ST_Other;
515 // If this is a STAB debugging symbol, we can do nothing more.
516 if (n_type & MachO::NlistMaskStab) {
517 Res = SymbolRef::ST_Debug;
518 return object_error::success;
521 switch (n_type & MachO::NlistMaskType) {
522 case MachO::NListTypeUndefined :
523 Res = SymbolRef::ST_Unknown;
525 case MachO::NListTypeSection :
526 Res = SymbolRef::ST_Function;
529 return object_error::success;
532 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
534 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
535 uint8_t Type = Entry.Type;
536 uint16_t Flags = Entry.Flags;
539 switch (Type & macho::STF_TypeMask) {
540 case macho::STT_Undefined:
543 case macho::STT_Absolute:
544 case macho::STT_Section:
552 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
553 Char = toupper(static_cast<unsigned char>(Char));
555 return object_error::success;
558 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
559 uint32_t &Result) const {
560 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
562 uint8_t MachOType = Entry.Type;
563 uint16_t MachOFlags = Entry.Flags;
565 // TODO: Correctly set SF_ThreadLocal
566 Result = SymbolRef::SF_None;
568 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
569 Result |= SymbolRef::SF_Undefined;
571 if (MachOFlags & macho::STF_StabsEntryMask)
572 Result |= SymbolRef::SF_FormatSpecific;
574 if (MachOType & MachO::NlistMaskExternal) {
575 Result |= SymbolRef::SF_Global;
576 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
577 Result |= SymbolRef::SF_Common;
580 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
581 Result |= SymbolRef::SF_Weak;
583 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
584 Result |= SymbolRef::SF_Absolute;
586 return object_error::success;
590 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
591 section_iterator &Res) const {
592 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
593 uint8_t index = Entry.SectionIndex;
596 Res = end_sections();
600 Res = section_iterator(SectionRef(DRI, this));
603 return object_error::success;
606 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
607 uint64_t &Val) const {
608 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
611 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
612 SectionRef &Res) const {
614 Res = SectionRef(Sec, this);
615 return object_error::success;
619 MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
620 ArrayRef<char> Raw = getSectionRawName(Sec);
621 Result = parseSegmentOrSectionName(Raw.data());
622 return object_error::success;
626 MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
628 macho::Section64 Sect = getSection64(Sec);
631 macho::Section Sect = getSection(Sec);
634 return object_error::success;
638 MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
640 macho::Section64 Sect = getSection64(Sec);
643 macho::Section Sect = getSection(Sec);
647 return object_error::success;
651 MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
656 macho::Section64 Sect = getSection64(Sec);
657 Offset = Sect.Offset;
660 macho::Section Sect =getSection(Sec);
661 Offset = Sect.Offset;
665 Res = this->getData().substr(Offset, Size);
666 return object_error::success;
670 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
673 macho::Section64 Sect = getSection64(Sec);
676 macho::Section Sect = getSection(Sec);
680 Res = uint64_t(1) << Align;
681 return object_error::success;
685 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
686 uint32_t Flags = getSectionFlags(this, Sec);
687 Res = Flags & macho::SF_PureInstructions;
688 return object_error::success;
691 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
692 // FIXME: Unimplemented.
694 return object_error::success;
697 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
698 // FIXME: Unimplemented.
700 return object_error::success;
704 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
705 bool &Result) const {
706 // FIXME: Unimplemented.
708 return object_error::success;
711 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
712 bool &Result) const {
713 // FIXME: Unimplemented.
715 return object_error::success;
719 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
720 uint32_t Flags = getSectionFlags(this, Sec);
721 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
722 Res = SectionType == MachO::SectionTypeZeroFill ||
723 SectionType == MachO::SectionTypeZeroFillLarge;
724 return object_error::success;
727 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
728 bool &Result) const {
729 // Consider using the code from isSectionText to look for __const sections.
730 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
731 // to use section attributes to distinguish code from data.
733 // FIXME: Unimplemented.
735 return object_error::success;
739 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
740 bool &Result) const {
742 this->getSymbolType(Symb, ST);
743 if (ST == SymbolRef::ST_Unknown) {
745 return object_error::success;
748 uint64_t SectBegin, SectEnd;
749 getSectionAddress(Sec, SectBegin);
750 getSectionSize(Sec, SectEnd);
751 SectEnd += SectBegin;
754 getSymbolAddress(Symb, SymAddr);
755 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
757 return object_error::success;
760 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
763 macho::Section64 Sect = getSection64(Sec);
764 Offset = Sect.RelocationTableOffset;
766 macho::Section Sect = getSection(Sec);
767 Offset = Sect.RelocationTableOffset;
771 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
772 return relocation_iterator(RelocationRef(Ret, this));
776 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
780 macho::Section64 Sect = getSection64(Sec);
781 Offset = Sect.RelocationTableOffset;
782 Num = Sect.NumRelocationTableEntries;
784 macho::Section Sect = getSection(Sec);
785 Offset = Sect.RelocationTableOffset;
786 Num = Sect.NumRelocationTableEntries;
789 const macho::RelocationEntry *P =
790 reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset));
793 Ret.p = reinterpret_cast<uintptr_t>(P + Num);
794 return relocation_iterator(RelocationRef(Ret, this));
797 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
798 RelocationRef &Res) const {
799 const macho::RelocationEntry *P =
800 reinterpret_cast<const macho::RelocationEntry *>(Rel.p);
801 Rel.p = reinterpret_cast<uintptr_t>(P + 1);
802 Res = RelocationRef(Rel, this);
803 return object_error::success;
807 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
808 report_fatal_error("getRelocationAddress not implemented in MachOObjectFile");
811 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
812 uint64_t &Res) const {
813 macho::RelocationEntry RE = getRelocation(Rel);
814 Res = getAnyRelocationAddress(RE);
815 return object_error::success;
819 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const {
820 macho::RelocationEntry RE = getRelocation(Rel);
821 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
822 bool isExtern = getPlainRelocationExternal(RE);
824 Res = *end_symbols();
825 return object_error::success;
828 macho::SymtabLoadCommand S = getSymtabLoadCommand();
829 unsigned SymbolTableEntrySize = is64Bit() ?
830 sizeof(macho::Symbol64TableEntry) :
831 sizeof(macho::SymbolTableEntry);
832 uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize;
834 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
835 Res = SymbolRef(Sym, this);
836 return object_error::success;
839 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
840 uint64_t &Res) const {
841 macho::RelocationEntry RE = getRelocation(Rel);
842 Res = getAnyRelocationType(RE);
843 return object_error::success;
847 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
848 SmallVectorImpl<char> &Result) const {
851 getRelocationType(Rel, RType);
853 unsigned Arch = this->getArch();
857 static const char *const Table[] = {
858 "GENERIC_RELOC_VANILLA",
859 "GENERIC_RELOC_PAIR",
860 "GENERIC_RELOC_SECTDIFF",
861 "GENERIC_RELOC_PB_LA_PTR",
862 "GENERIC_RELOC_LOCAL_SECTDIFF",
863 "GENERIC_RELOC_TLV" };
871 case Triple::x86_64: {
872 static const char *const Table[] = {
873 "X86_64_RELOC_UNSIGNED",
874 "X86_64_RELOC_SIGNED",
875 "X86_64_RELOC_BRANCH",
876 "X86_64_RELOC_GOT_LOAD",
878 "X86_64_RELOC_SUBTRACTOR",
879 "X86_64_RELOC_SIGNED_1",
880 "X86_64_RELOC_SIGNED_2",
881 "X86_64_RELOC_SIGNED_4",
882 "X86_64_RELOC_TLV" };
891 static const char *const Table[] = {
894 "ARM_RELOC_SECTDIFF",
895 "ARM_RELOC_LOCAL_SECTDIFF",
896 "ARM_RELOC_PB_LA_PTR",
898 "ARM_THUMB_RELOC_BR22",
899 "ARM_THUMB_32BIT_BRANCH",
901 "ARM_RELOC_HALF_SECTDIFF" };
910 static const char *const Table[] = {
919 "PPC_RELOC_SECTDIFF",
920 "PPC_RELOC_PB_LA_PTR",
921 "PPC_RELOC_HI16_SECTDIFF",
922 "PPC_RELOC_LO16_SECTDIFF",
923 "PPC_RELOC_HA16_SECTDIFF",
925 "PPC_RELOC_LO14_SECTDIFF",
926 "PPC_RELOC_LOCAL_SECTDIFF" };
931 case Triple::UnknownArch:
935 Result.append(res.begin(), res.end());
936 return object_error::success;
939 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
940 int64_t &Res) const {
942 return object_error::success;
946 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
947 SmallVectorImpl<char> &Result) const {
948 macho::RelocationEntry RE = getRelocation(Rel);
950 unsigned Arch = this->getArch();
953 raw_string_ostream fmt(fmtbuf);
954 unsigned Type = this->getAnyRelocationType(RE);
955 bool IsPCRel = this->getAnyRelocationPCRel(RE);
957 // Determine any addends that should be displayed with the relocation.
958 // These require decoding the relocation type, which is triple-specific.
960 // X86_64 has entirely custom relocation types.
961 if (Arch == Triple::x86_64) {
962 bool isPCRel = getAnyRelocationPCRel(RE);
965 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
966 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
967 printRelocationTargetName(this, RE, fmt);
969 if (isPCRel) fmt << "PCREL";
972 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
973 DataRefImpl RelNext = Rel;
975 macho::RelocationEntry RENext = getRelocation(RelNext);
977 // X86_64_SUBTRACTOR must be followed by a relocation of type
978 // X86_64_RELOC_UNSIGNED.
979 // NOTE: Scattered relocations don't exist on x86_64.
980 unsigned RType = getAnyRelocationType(RENext);
982 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
983 "X86_64_RELOC_SUBTRACTOR.");
985 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
986 // X86_64_SUBTRACTOR contains to the subtrahend.
987 printRelocationTargetName(this, RENext, fmt);
989 printRelocationTargetName(this, RE, fmt);
992 case macho::RIT_X86_64_TLV:
993 printRelocationTargetName(this, RE, fmt);
995 if (isPCRel) fmt << "P";
997 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
998 printRelocationTargetName(this, RE, fmt);
1001 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1002 printRelocationTargetName(this, RE, fmt);
1005 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1006 printRelocationTargetName(this, RE, fmt);
1010 printRelocationTargetName(this, RE, fmt);
1013 // X86 and ARM share some relocation types in common.
1014 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1015 // Generic relocation types...
1017 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1018 return object_error::success;
1019 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1020 DataRefImpl RelNext = Rel;
1022 macho::RelocationEntry RENext = getRelocation(RelNext);
1024 // X86 sect diff's must be followed by a relocation of type
1025 // GENERIC_RELOC_PAIR.
1026 unsigned RType = getAnyRelocationType(RENext);
1029 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1030 "GENERIC_RELOC_SECTDIFF.");
1032 printRelocationTargetName(this, RE, fmt);
1034 printRelocationTargetName(this, RENext, fmt);
1039 if (Arch == Triple::x86) {
1040 // All X86 relocations that need special printing were already
1041 // handled in the generic code.
1043 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1044 DataRefImpl RelNext = Rel;
1046 macho::RelocationEntry RENext = getRelocation(RelNext);
1048 // X86 sect diff's must be followed by a relocation of type
1049 // GENERIC_RELOC_PAIR.
1050 unsigned RType = getAnyRelocationType(RENext);
1052 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1053 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1055 printRelocationTargetName(this, RE, fmt);
1057 printRelocationTargetName(this, RENext, fmt);
1060 case macho::RIT_Generic_TLV: {
1061 printRelocationTargetName(this, RE, fmt);
1063 if (IsPCRel) fmt << "P";
1067 printRelocationTargetName(this, RE, fmt);
1069 } else { // ARM-specific relocations
1071 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1072 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1073 // Half relocations steal a bit from the length field to encode
1074 // whether this is an upper16 or a lower16 relocation.
1075 bool isUpper = getAnyRelocationLength(RE) >> 1;
1078 fmt << ":upper16:(";
1080 fmt << ":lower16:(";
1081 printRelocationTargetName(this, RE, fmt);
1083 DataRefImpl RelNext = Rel;
1085 macho::RelocationEntry RENext = getRelocation(RelNext);
1087 // ARM half relocs must be followed by a relocation of type
1089 unsigned RType = getAnyRelocationType(RENext);
1091 report_fatal_error("Expected ARM_RELOC_PAIR after "
1092 "GENERIC_RELOC_HALF");
1094 // NOTE: The half of the target virtual address is stashed in the
1095 // address field of the secondary relocation, but we can't reverse
1096 // engineer the constant offset from it without decoding the movw/movt
1097 // instruction to find the other half in its immediate field.
1099 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1100 // symbol/section pointer of the follow-on relocation.
1101 if (Type == macho::RIT_ARM_HalfDifference) {
1103 printRelocationTargetName(this, RENext, fmt);
1110 printRelocationTargetName(this, RE, fmt);
1115 printRelocationTargetName(this, RE, fmt);
1118 Result.append(fmtbuf.begin(), fmtbuf.end());
1119 return object_error::success;
1123 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
1124 unsigned Arch = getArch();
1126 getRelocationType(Rel, Type);
1130 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1131 // is always hidden.
1132 if (Arch == Triple::x86 || Arch == Triple::arm) {
1133 if (Type == macho::RIT_Pair) Result = true;
1134 } else if (Arch == Triple::x86_64) {
1135 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1136 // an X864_64_RELOC_SUBTRACTOR.
1137 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1138 DataRefImpl RelPrev = Rel;
1141 getRelocationType(RelPrev, PrevType);
1142 if (PrevType == macho::RIT_X86_64_Subtractor)
1147 return object_error::success;
1150 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1151 LibraryRef &Res) const {
1152 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1155 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1156 StringRef &Res) const {
1157 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1160 symbol_iterator MachOObjectFile::begin_symbols() const {
1163 return symbol_iterator(SymbolRef(DRI, this));
1165 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1166 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset));
1167 return symbol_iterator(SymbolRef(DRI, this));
1170 symbol_iterator MachOObjectFile::end_symbols() const {
1173 return symbol_iterator(SymbolRef(DRI, this));
1175 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1176 unsigned SymbolTableEntrySize = is64Bit() ?
1177 sizeof(macho::Symbol64TableEntry) :
1178 sizeof(macho::SymbolTableEntry);
1179 unsigned Offset = Symtab.SymbolTableOffset +
1180 Symtab.NumSymbolTableEntries * SymbolTableEntrySize;
1181 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1182 return symbol_iterator(SymbolRef(DRI, this));
1185 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1187 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1190 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1192 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1195 section_iterator MachOObjectFile::begin_sections() const {
1197 return section_iterator(SectionRef(DRI, this));
1200 section_iterator MachOObjectFile::end_sections() const {
1202 DRI.d.a = Sections.size();
1203 return section_iterator(SectionRef(DRI, this));
1206 library_iterator MachOObjectFile::begin_libraries_needed() const {
1208 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1211 library_iterator MachOObjectFile::end_libraries_needed() const {
1213 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1216 uint8_t MachOObjectFile::getBytesInAddress() const {
1217 return is64Bit() ? 8 : 4;
1220 StringRef MachOObjectFile::getFileFormatName() const {
1221 unsigned CPUType = getCPUType(this);
1224 case llvm::MachO::CPUTypeI386:
1225 return "Mach-O 32-bit i386";
1226 case llvm::MachO::CPUTypeARM:
1227 return "Mach-O arm";
1228 case llvm::MachO::CPUTypePowerPC:
1229 return "Mach-O 32-bit ppc";
1231 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1232 "64-bit object file when we're not 64-bit?");
1233 return "Mach-O 32-bit unknown";
1237 // Make sure the cpu type has the correct mask.
1238 assert((CPUType & llvm::MachO::CPUArchABI64)
1239 == llvm::MachO::CPUArchABI64 &&
1240 "32-bit object file when we're 64-bit?");
1243 case llvm::MachO::CPUTypeX86_64:
1244 return "Mach-O 64-bit x86-64";
1245 case llvm::MachO::CPUTypePowerPC64:
1246 return "Mach-O 64-bit ppc64";
1248 return "Mach-O 64-bit unknown";
1252 unsigned MachOObjectFile::getArch() const {
1253 switch (getCPUType(this)) {
1254 case llvm::MachO::CPUTypeI386:
1256 case llvm::MachO::CPUTypeX86_64:
1257 return Triple::x86_64;
1258 case llvm::MachO::CPUTypeARM:
1260 case llvm::MachO::CPUTypePowerPC:
1262 case llvm::MachO::CPUTypePowerPC64:
1263 return Triple::ppc64;
1265 return Triple::UnknownArch;
1269 StringRef MachOObjectFile::getLoadName() const {
1271 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1275 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1276 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1277 return parseSegmentOrSectionName(Raw.data());
1281 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1282 const SectionBase *Base =
1283 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1284 return ArrayRef<char>(Base->Name);
1288 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1289 const SectionBase *Base =
1290 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1291 return ArrayRef<char>(Base->SegmentName);
1295 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1297 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1299 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1302 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1303 if (isLittleEndian())
1304 return RE.Word1 & 0xffffff;
1305 return RE.Word1 >> 8;
1308 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1309 if (isLittleEndian())
1310 return (RE.Word1 >> 27) & 1;
1311 return (RE.Word1 >> 4) & 1;
1315 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1316 return RE.Word0 >> 31;
1320 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1325 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1326 if (isRelocationScattered(RE))
1327 return getScatteredRelocationAddress(RE);
1328 return getPlainRelocationAddress(RE);
1332 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1333 if (isRelocationScattered(RE))
1334 return getScatteredRelocationPCRel(this, RE);
1335 return getPlainRelocationPCRel(this, RE);
1339 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1340 if (isRelocationScattered(RE))
1341 return getScatteredRelocationLength(RE);
1342 return getPlainRelocationLength(this, RE);
1346 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1347 if (isRelocationScattered(RE))
1348 return getScatteredRelocationType(RE);
1349 return getPlainRelocationType(this, RE);
1352 MachOObjectFile::LoadCommandInfo
1353 MachOObjectFile::getFirstLoadCommandInfo() const {
1354 MachOObjectFile::LoadCommandInfo Load;
1356 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1357 Load.Ptr = getPtr(this, HeaderSize);
1358 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
1362 MachOObjectFile::LoadCommandInfo
1363 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1364 MachOObjectFile::LoadCommandInfo Next;
1365 Next.Ptr = L.Ptr + L.C.Size;
1366 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
1370 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1371 return getStruct<macho::Section>(this, Sections[DRI.d.a]);
1374 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1375 return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
1378 macho::SymbolTableEntry
1379 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1380 const char *P = reinterpret_cast<const char *>(DRI.p);
1381 return getStruct<macho::SymbolTableEntry>(this, P);
1384 macho::Symbol64TableEntry
1385 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1386 const char *P = reinterpret_cast<const char *>(DRI.p);
1387 return getStruct<macho::Symbol64TableEntry>(this, P);
1390 macho::LinkeditDataLoadCommand
1391 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1392 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
1395 macho::RelocationEntry
1396 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1397 const char *P = reinterpret_cast<const char *>(Rel.p);
1398 return getStruct<macho::RelocationEntry>(this, P);
1401 macho::Header MachOObjectFile::getHeader() const {
1402 return getStruct<macho::Header>(this, getPtr(this, 0));
1405 macho::SymtabLoadCommand
1406 MachOObjectFile::getSymtabLoadCommand() const {
1407 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
1410 bool MachOObjectFile::is64Bit() const {
1411 return getType() == getMachOType(false, true) ||
1412 getType() == getMachOType(true, true);
1415 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1416 SmallVectorImpl<uint64_t> &Out) const {
1417 DataExtractor extractor(ObjectFile::getData(), true, 0);
1419 uint32_t offset = Index;
1421 while (uint64_t delta = extractor.getULEB128(&offset)) {
1423 Out.push_back(data);
1427 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1428 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1431 if (Magic == "\xFE\xED\xFA\xCE")
1432 Ret = new MachOObjectFile(Buffer, false, false, ec);
1433 else if (Magic == "\xCE\xFA\xED\xFE")
1434 Ret = new MachOObjectFile(Buffer, true, false, ec);
1435 else if (Magic == "\xFE\xED\xFA\xCF")
1436 Ret = new MachOObjectFile(Buffer, false, true, ec);
1437 else if (Magic == "\xCF\xFA\xED\xFE")
1438 Ret = new MachOObjectFile(Buffer, true, true, ec);
1447 } // end namespace object
1448 } // end namespace llvm