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 const char *getSymbolTableEntryPtr(const MachOObjectFile *O,
221 macho::SymtabLoadCommand S = O->getSymtabLoadCommand();
223 unsigned Index = DRI.d.b;
225 unsigned SymbolTableEntrySize = O->is64Bit() ?
226 sizeof(macho::Symbol64TableEntry) :
227 sizeof(macho::SymbolTableEntry);
229 uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize;
230 return getPtr(O, Offset);
233 static SymbolTableEntryBase
234 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
235 const char *P = getSymbolTableEntryPtr(O, DRI);
236 return getStruct<SymbolTableEntryBase>(O, P);
239 static StringRef parseSegmentOrSectionName(const char *P) {
243 // Not null terminated, so this is a 16 char string.
244 return StringRef(P, 16);
247 // Helper to advance a section or symbol iterator multiple increments at a time.
249 static error_code advance(T &it, size_t Val) {
258 static void advanceTo(T &it, size_t Val) {
259 if (error_code ec = advance(it, Val))
260 report_fatal_error(ec.message());
263 static unsigned getCPUType(const MachOObjectFile *O) {
264 return O->getHeader().CPUType;
267 static void printRelocationTargetName(const MachOObjectFile *O,
268 const macho::RelocationEntry &RE,
269 raw_string_ostream &fmt) {
270 bool IsScattered = O->isRelocationScattered(RE);
272 // Target of a scattered relocation is an address. In the interest of
273 // generating pretty output, scan through the symbol table looking for a
274 // symbol that aligns with that address. If we find one, print it.
275 // Otherwise, we just print the hex address of the target.
277 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
280 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
281 SI != SE; SI.increment(ec)) {
282 if (ec) report_fatal_error(ec.message());
287 if ((ec = SI->getAddress(Addr)))
288 report_fatal_error(ec.message());
289 if (Addr != Val) continue;
290 if ((ec = SI->getName(Name)))
291 report_fatal_error(ec.message());
296 // If we couldn't find a symbol that this relocation refers to, try
297 // to find a section beginning instead.
298 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
299 SI != SE; SI.increment(ec)) {
300 if (ec) report_fatal_error(ec.message());
305 if ((ec = SI->getAddress(Addr)))
306 report_fatal_error(ec.message());
307 if (Addr != Val) continue;
308 if ((ec = SI->getName(Name)))
309 report_fatal_error(ec.message());
314 fmt << format("0x%x", Val);
319 bool isExtern = O->getPlainRelocationExternal(RE);
320 uint64_t Val = O->getAnyRelocationAddress(RE);
323 symbol_iterator SI = O->begin_symbols();
327 section_iterator SI = O->begin_sections();
335 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
340 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
341 return RE.Word0 & 0xffffff;
344 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
345 const macho::RelocationEntry &RE) {
346 if (O->isLittleEndian())
347 return (RE.Word1 >> 24) & 1;
348 return (RE.Word1 >> 7) & 1;
352 getScatteredRelocationPCRel(const MachOObjectFile *O,
353 const macho::RelocationEntry &RE) {
354 return (RE.Word0 >> 30) & 1;
357 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
358 const macho::RelocationEntry &RE) {
359 if (O->isLittleEndian())
360 return (RE.Word1 >> 25) & 3;
361 return (RE.Word1 >> 5) & 3;
365 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
366 return (RE.Word0 >> 28) & 3;
369 static unsigned getPlainRelocationType(const MachOObjectFile *O,
370 const macho::RelocationEntry &RE) {
371 if (O->isLittleEndian())
372 return RE.Word1 >> 28;
373 return RE.Word1 & 0xf;
376 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
377 return (RE.Word0 >> 24) & 0xf;
380 static uint32_t getSectionFlags(const MachOObjectFile *O,
383 macho::Section64 Sect = O->getSection64(Sec);
386 macho::Section Sect = O->getSection(Sec);
390 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
391 bool IsLittleEndian, bool Is64bits,
393 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
394 SymtabLoadCmd(NULL) {
395 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
396 macho::LoadCommandType SegmentLoadType = is64Bit() ?
397 macho::LCT_Segment64 : macho::LCT_Segment;
399 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
400 for (unsigned I = 0; ; ++I) {
401 if (Load.C.Type == macho::LCT_Symtab) {
402 assert(!SymtabLoadCmd && "Multiple symbol tables");
403 SymtabLoadCmd = Load.Ptr;
406 if (Load.C.Type == SegmentLoadType) {
407 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
408 for (unsigned J = 0; J < NumSections; ++J) {
409 const SectionBase *Sec = getSectionBase(this, Load, J);
410 Sections.push_back(reinterpret_cast<const char*>(Sec));
414 if (I == LoadCommandCount - 1)
417 Load = getNextLoadCommandInfo(Load);
421 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
422 SymbolRef &Res) const {
424 Res = SymbolRef(Symb, this);
425 return object_error::success;
428 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
429 StringRef &Res) const {
430 macho::SymtabLoadCommand S = getSymtabLoadCommand();
431 const char *StringTable = getPtr(this, S.StringTableOffset);
432 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
433 const char *Start = &StringTable[Entry.StringIndex];
434 Res = StringRef(Start);
435 return object_error::success;
438 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
439 uint64_t &Res) const {
441 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
444 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
447 return object_error::success;
451 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
452 uint64_t &Res) const {
453 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
454 getSymbolAddress(Symb, Res);
455 if (Entry.SectionIndex) {
458 SecRel.d.a = Entry.SectionIndex-1;
460 macho::Section64 Sec = getSection64(SecRel);
461 Delta = Sec.Offset - Sec.Address;
463 macho::Section Sec = getSection(SecRel);
464 Delta = Sec.Offset - Sec.Address;
470 return object_error::success;
473 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
474 uint64_t &Result) const {
475 uint64_t BeginOffset;
476 uint64_t EndOffset = 0;
477 uint8_t SectionIndex;
479 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
481 getSymbolAddress(DRI, Value);
485 SectionIndex = Entry.SectionIndex;
487 uint32_t flags = SymbolRef::SF_None;
488 this->getSymbolFlags(DRI, flags);
489 if (flags & SymbolRef::SF_Common)
492 Result = UnknownAddressOrSize;
493 return object_error::success;
495 // Unfortunately symbols are unsorted so we need to touch all
496 // symbols from load command
497 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
499 while (DRI.d.b <= Symtab.NumSymbolTableEntries) {
500 Entry = getSymbolTableEntryBase(this, DRI);
501 getSymbolAddress(DRI, Value);
502 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
503 if (!EndOffset || Value < EndOffset)
510 Sec.d.a = SectionIndex-1;
511 getSectionSize(Sec, Size);
512 getSectionAddress(Sec, EndOffset);
515 Result = EndOffset - BeginOffset;
516 return object_error::success;
519 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
520 SymbolRef::Type &Res) const {
521 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
522 uint8_t n_type = Entry.Type;
524 Res = SymbolRef::ST_Other;
526 // If this is a STAB debugging symbol, we can do nothing more.
527 if (n_type & MachO::NlistMaskStab) {
528 Res = SymbolRef::ST_Debug;
529 return object_error::success;
532 switch (n_type & MachO::NlistMaskType) {
533 case MachO::NListTypeUndefined :
534 Res = SymbolRef::ST_Unknown;
536 case MachO::NListTypeSection :
537 Res = SymbolRef::ST_Function;
540 return object_error::success;
543 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
545 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
546 uint8_t Type = Entry.Type;
547 uint16_t Flags = Entry.Flags;
550 switch (Type & macho::STF_TypeMask) {
551 case macho::STT_Undefined:
554 case macho::STT_Absolute:
555 case macho::STT_Section:
563 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
564 Char = toupper(static_cast<unsigned char>(Char));
566 return object_error::success;
569 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
570 uint32_t &Result) const {
571 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
573 uint8_t MachOType = Entry.Type;
574 uint16_t MachOFlags = Entry.Flags;
576 // TODO: Correctly set SF_ThreadLocal
577 Result = SymbolRef::SF_None;
579 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
580 Result |= SymbolRef::SF_Undefined;
582 if (MachOFlags & macho::STF_StabsEntryMask)
583 Result |= SymbolRef::SF_FormatSpecific;
585 if (MachOType & MachO::NlistMaskExternal) {
586 Result |= SymbolRef::SF_Global;
587 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
588 Result |= SymbolRef::SF_Common;
591 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
592 Result |= SymbolRef::SF_Weak;
594 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
595 Result |= SymbolRef::SF_Absolute;
597 return object_error::success;
601 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
602 section_iterator &Res) const {
603 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
604 uint8_t index = Entry.SectionIndex;
607 Res = end_sections();
611 Res = section_iterator(SectionRef(DRI, this));
614 return object_error::success;
617 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
618 uint64_t &Val) const {
619 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
622 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
623 SectionRef &Res) const {
625 Res = SectionRef(Sec, this);
626 return object_error::success;
630 MachOObjectFile::getSectionName(DataRefImpl Sec,
631 StringRef &Result) const {
632 ArrayRef<char> Raw = getSectionRawName(Sec);
633 Result = parseSegmentOrSectionName(Raw.data());
634 return object_error::success;
638 MachOObjectFile::getSectionAddress(DataRefImpl Sec,
639 uint64_t &Res) const {
641 macho::Section64 Sect = getSection64(Sec);
644 macho::Section Sect = getSection(Sec);
647 return object_error::success;
651 MachOObjectFile::getSectionSize(DataRefImpl Sec,
652 uint64_t &Res) const {
654 macho::Section64 Sect = getSection64(Sec);
657 macho::Section Sect = getSection(Sec);
661 return object_error::success;
665 MachOObjectFile::getSectionContents(DataRefImpl Sec,
666 StringRef &Res) const {
671 macho::Section64 Sect = getSection64(Sec);
672 Offset = Sect.Offset;
675 macho::Section Sect =getSection(Sec);
676 Offset = Sect.Offset;
680 Res = this->getData().substr(Offset, Size);
681 return object_error::success;
685 MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
686 uint64_t &Res) const {
689 macho::Section64 Sect = getSection64(Sec);
692 macho::Section Sect = getSection(Sec);
696 Res = uint64_t(1) << Align;
697 return object_error::success;
701 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
702 uint32_t Flags = getSectionFlags(this, Sec);
703 Res = Flags & macho::SF_PureInstructions;
704 return object_error::success;
707 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
708 bool &Result) const {
709 // FIXME: Unimplemented.
711 return object_error::success;
714 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
715 bool &Result) const {
716 // FIXME: Unimplemented.
718 return object_error::success;
722 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
723 bool &Result) const {
724 // FIXME: Unimplemented.
726 return object_error::success;
729 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
730 bool &Result) const {
731 // FIXME: Unimplemented.
733 return object_error::success;
737 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
738 uint32_t Flags = getSectionFlags(this, Sec);
739 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
740 Res = SectionType == MachO::SectionTypeZeroFill ||
741 SectionType == MachO::SectionTypeZeroFillLarge;
742 return object_error::success;
745 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
746 bool &Result) const {
747 // Consider using the code from isSectionText to look for __const sections.
748 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
749 // to use section attributes to distinguish code from data.
751 // FIXME: Unimplemented.
753 return object_error::success;
757 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
759 bool &Result) const {
761 this->getSymbolType(Symb, ST);
762 if (ST == SymbolRef::ST_Unknown) {
764 return object_error::success;
767 uint64_t SectBegin, SectEnd;
768 getSectionAddress(Sec, SectBegin);
769 getSectionSize(Sec, SectEnd);
770 SectEnd += SectBegin;
773 getSymbolAddress(Symb, SymAddr);
774 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
776 return object_error::success;
779 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
782 macho::Section64 Sect = getSection64(Sec);
783 Offset = Sect.RelocationTableOffset;
785 macho::Section Sect = getSection(Sec);
786 Offset = Sect.RelocationTableOffset;
790 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
791 return relocation_iterator(RelocationRef(Ret, this));
795 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
799 macho::Section64 Sect = getSection64(Sec);
800 Offset = Sect.RelocationTableOffset;
801 Num = Sect.NumRelocationTableEntries;
803 macho::Section Sect = getSection(Sec);
804 Offset = Sect.RelocationTableOffset;
805 Num = Sect.NumRelocationTableEntries;
808 const macho::RelocationEntry *P =
809 reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset));
812 Ret.p = reinterpret_cast<uintptr_t>(P + Num);
813 return relocation_iterator(RelocationRef(Ret, this));
816 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
817 RelocationRef &Res) const {
818 const macho::RelocationEntry *P =
819 reinterpret_cast<const macho::RelocationEntry *>(Rel.p);
820 Rel.p = reinterpret_cast<uintptr_t>(P + 1);
821 Res = RelocationRef(Rel, this);
822 return object_error::success;
826 MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
827 uint64_t &Res) const {
828 uint64_t SectAddress;
832 macho::Section64 Sect = getSection64(Sec);
833 SectAddress = Sect.Address;
835 macho::Section Sect = getSection(Sec);
836 SectAddress = Sect.Address;
839 macho::RelocationEntry RE = getRelocation(Rel);
840 uint64_t RelAddr = getAnyRelocationAddress(RE);
841 Res = SectAddress + RelAddr;
842 return object_error::success;
845 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
846 uint64_t &Res) const {
847 macho::RelocationEntry RE = getRelocation(Rel);
848 Res = getAnyRelocationAddress(RE);
849 return object_error::success;
853 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
854 SymbolRef &Res) const {
855 macho::RelocationEntry RE = getRelocation(Rel);
856 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
857 bool isExtern = getPlainRelocationExternal(RE);
863 Res = SymbolRef(Sym, this);
864 return object_error::success;
867 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
868 uint64_t &Res) const {
869 macho::RelocationEntry RE = getRelocation(Rel);
870 Res = getAnyRelocationType(RE);
871 return object_error::success;
875 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
876 SmallVectorImpl<char> &Result) const {
879 getRelocationType(Rel, RType);
881 unsigned Arch = this->getArch();
885 static const char *const Table[] = {
886 "GENERIC_RELOC_VANILLA",
887 "GENERIC_RELOC_PAIR",
888 "GENERIC_RELOC_SECTDIFF",
889 "GENERIC_RELOC_PB_LA_PTR",
890 "GENERIC_RELOC_LOCAL_SECTDIFF",
891 "GENERIC_RELOC_TLV" };
899 case Triple::x86_64: {
900 static const char *const Table[] = {
901 "X86_64_RELOC_UNSIGNED",
902 "X86_64_RELOC_SIGNED",
903 "X86_64_RELOC_BRANCH",
904 "X86_64_RELOC_GOT_LOAD",
906 "X86_64_RELOC_SUBTRACTOR",
907 "X86_64_RELOC_SIGNED_1",
908 "X86_64_RELOC_SIGNED_2",
909 "X86_64_RELOC_SIGNED_4",
910 "X86_64_RELOC_TLV" };
919 static const char *const Table[] = {
922 "ARM_RELOC_SECTDIFF",
923 "ARM_RELOC_LOCAL_SECTDIFF",
924 "ARM_RELOC_PB_LA_PTR",
926 "ARM_THUMB_RELOC_BR22",
927 "ARM_THUMB_32BIT_BRANCH",
929 "ARM_RELOC_HALF_SECTDIFF" };
938 static const char *const Table[] = {
947 "PPC_RELOC_SECTDIFF",
948 "PPC_RELOC_PB_LA_PTR",
949 "PPC_RELOC_HI16_SECTDIFF",
950 "PPC_RELOC_LO16_SECTDIFF",
951 "PPC_RELOC_HA16_SECTDIFF",
953 "PPC_RELOC_LO14_SECTDIFF",
954 "PPC_RELOC_LOCAL_SECTDIFF" };
959 case Triple::UnknownArch:
963 Result.append(res.begin(), res.end());
964 return object_error::success;
967 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
968 int64_t &Res) const {
970 return object_error::success;
974 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
975 SmallVectorImpl<char> &Result) const {
976 macho::RelocationEntry RE = getRelocation(Rel);
978 unsigned Arch = this->getArch();
981 raw_string_ostream fmt(fmtbuf);
982 unsigned Type = this->getAnyRelocationType(RE);
983 bool IsPCRel = this->getAnyRelocationPCRel(RE);
985 // Determine any addends that should be displayed with the relocation.
986 // These require decoding the relocation type, which is triple-specific.
988 // X86_64 has entirely custom relocation types.
989 if (Arch == Triple::x86_64) {
990 bool isPCRel = getAnyRelocationPCRel(RE);
993 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
994 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
995 printRelocationTargetName(this, RE, fmt);
997 if (isPCRel) fmt << "PCREL";
1000 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1001 DataRefImpl RelNext = Rel;
1003 macho::RelocationEntry RENext = getRelocation(RelNext);
1005 // X86_64_SUBTRACTOR must be followed by a relocation of type
1006 // X86_64_RELOC_UNSIGNED.
1007 // NOTE: Scattered relocations don't exist on x86_64.
1008 unsigned RType = getAnyRelocationType(RENext);
1010 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1011 "X86_64_RELOC_SUBTRACTOR.");
1013 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1014 // X86_64_SUBTRACTOR contains to the subtrahend.
1015 printRelocationTargetName(this, RENext, fmt);
1017 printRelocationTargetName(this, RE, fmt);
1020 case macho::RIT_X86_64_TLV:
1021 printRelocationTargetName(this, RE, fmt);
1023 if (isPCRel) fmt << "P";
1025 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1026 printRelocationTargetName(this, RE, fmt);
1029 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1030 printRelocationTargetName(this, RE, fmt);
1033 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1034 printRelocationTargetName(this, RE, fmt);
1038 printRelocationTargetName(this, RE, fmt);
1041 // X86 and ARM share some relocation types in common.
1042 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1043 // Generic relocation types...
1045 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1046 return object_error::success;
1047 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1048 DataRefImpl RelNext = Rel;
1050 macho::RelocationEntry RENext = getRelocation(RelNext);
1052 // X86 sect diff's must be followed by a relocation of type
1053 // GENERIC_RELOC_PAIR.
1054 unsigned RType = getAnyRelocationType(RENext);
1057 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1058 "GENERIC_RELOC_SECTDIFF.");
1060 printRelocationTargetName(this, RE, fmt);
1062 printRelocationTargetName(this, RENext, fmt);
1067 if (Arch == Triple::x86) {
1068 // All X86 relocations that need special printing were already
1069 // handled in the generic code.
1071 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1072 DataRefImpl RelNext = Rel;
1074 macho::RelocationEntry RENext = getRelocation(RelNext);
1076 // X86 sect diff's must be followed by a relocation of type
1077 // GENERIC_RELOC_PAIR.
1078 unsigned RType = getAnyRelocationType(RENext);
1080 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1081 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1083 printRelocationTargetName(this, RE, fmt);
1085 printRelocationTargetName(this, RENext, fmt);
1088 case macho::RIT_Generic_TLV: {
1089 printRelocationTargetName(this, RE, fmt);
1091 if (IsPCRel) fmt << "P";
1095 printRelocationTargetName(this, RE, fmt);
1097 } else { // ARM-specific relocations
1099 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1100 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1101 // Half relocations steal a bit from the length field to encode
1102 // whether this is an upper16 or a lower16 relocation.
1103 bool isUpper = getAnyRelocationLength(RE) >> 1;
1106 fmt << ":upper16:(";
1108 fmt << ":lower16:(";
1109 printRelocationTargetName(this, RE, fmt);
1111 DataRefImpl RelNext = Rel;
1113 macho::RelocationEntry RENext = getRelocation(RelNext);
1115 // ARM half relocs must be followed by a relocation of type
1117 unsigned RType = getAnyRelocationType(RENext);
1119 report_fatal_error("Expected ARM_RELOC_PAIR after "
1120 "GENERIC_RELOC_HALF");
1122 // NOTE: The half of the target virtual address is stashed in the
1123 // address field of the secondary relocation, but we can't reverse
1124 // engineer the constant offset from it without decoding the movw/movt
1125 // instruction to find the other half in its immediate field.
1127 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1128 // symbol/section pointer of the follow-on relocation.
1129 if (Type == macho::RIT_ARM_HalfDifference) {
1131 printRelocationTargetName(this, RENext, fmt);
1138 printRelocationTargetName(this, RE, fmt);
1143 printRelocationTargetName(this, RE, fmt);
1146 Result.append(fmtbuf.begin(), fmtbuf.end());
1147 return object_error::success;
1151 MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1152 bool &Result) const {
1153 unsigned Arch = getArch();
1155 getRelocationType(Rel, Type);
1159 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1160 // is always hidden.
1161 if (Arch == Triple::x86 || Arch == Triple::arm) {
1162 if (Type == macho::RIT_Pair) Result = true;
1163 } else if (Arch == Triple::x86_64) {
1164 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1165 // an X864_64_RELOC_SUBTRACTOR.
1166 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1167 DataRefImpl RelPrev = Rel;
1170 getRelocationType(RelPrev, PrevType);
1171 if (PrevType == macho::RIT_X86_64_Subtractor)
1176 return object_error::success;
1179 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1180 LibraryRef &Res) const {
1181 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1184 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1185 StringRef &Res) const {
1186 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1189 symbol_iterator MachOObjectFile::begin_symbols() const {
1190 // DRI.d.a = segment number; DRI.d.b = symbol index.
1192 return symbol_iterator(SymbolRef(DRI, this));
1195 symbol_iterator MachOObjectFile::end_symbols() const {
1197 if (SymtabLoadCmd) {
1198 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1199 DRI.d.b = Symtab.NumSymbolTableEntries;
1201 return symbol_iterator(SymbolRef(DRI, this));
1204 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1206 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1209 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1211 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1214 section_iterator MachOObjectFile::begin_sections() const {
1216 return section_iterator(SectionRef(DRI, this));
1219 section_iterator MachOObjectFile::end_sections() const {
1221 DRI.d.a = Sections.size();
1222 return section_iterator(SectionRef(DRI, this));
1225 library_iterator MachOObjectFile::begin_libraries_needed() const {
1227 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1230 library_iterator MachOObjectFile::end_libraries_needed() const {
1232 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1235 uint8_t MachOObjectFile::getBytesInAddress() const {
1236 return is64Bit() ? 8 : 4;
1239 StringRef MachOObjectFile::getFileFormatName() const {
1240 unsigned CPUType = getCPUType(this);
1243 case llvm::MachO::CPUTypeI386:
1244 return "Mach-O 32-bit i386";
1245 case llvm::MachO::CPUTypeARM:
1246 return "Mach-O arm";
1247 case llvm::MachO::CPUTypePowerPC:
1248 return "Mach-O 32-bit ppc";
1250 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1251 "64-bit object file when we're not 64-bit?");
1252 return "Mach-O 32-bit unknown";
1256 // Make sure the cpu type has the correct mask.
1257 assert((CPUType & llvm::MachO::CPUArchABI64)
1258 == llvm::MachO::CPUArchABI64 &&
1259 "32-bit object file when we're 64-bit?");
1262 case llvm::MachO::CPUTypeX86_64:
1263 return "Mach-O 64-bit x86-64";
1264 case llvm::MachO::CPUTypePowerPC64:
1265 return "Mach-O 64-bit ppc64";
1267 return "Mach-O 64-bit unknown";
1271 unsigned MachOObjectFile::getArch() const {
1272 switch (getCPUType(this)) {
1273 case llvm::MachO::CPUTypeI386:
1275 case llvm::MachO::CPUTypeX86_64:
1276 return Triple::x86_64;
1277 case llvm::MachO::CPUTypeARM:
1279 case llvm::MachO::CPUTypePowerPC:
1281 case llvm::MachO::CPUTypePowerPC64:
1282 return Triple::ppc64;
1284 return Triple::UnknownArch;
1288 StringRef MachOObjectFile::getLoadName() const {
1290 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1294 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1295 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1296 return parseSegmentOrSectionName(Raw.data());
1300 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1301 const SectionBase *Base =
1302 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1303 return ArrayRef<char>(Base->Name);
1307 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1308 const SectionBase *Base =
1309 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1310 return ArrayRef<char>(Base->SegmentName);
1314 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1316 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1318 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1321 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1322 if (isLittleEndian())
1323 return RE.Word1 & 0xffffff;
1324 return RE.Word1 >> 8;
1327 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1328 if (isLittleEndian())
1329 return (RE.Word1 >> 27) & 1;
1330 return (RE.Word1 >> 4) & 1;
1334 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1335 return RE.Word0 >> 31;
1339 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1344 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1345 if (isRelocationScattered(RE))
1346 return getScatteredRelocationAddress(RE);
1347 return getPlainRelocationAddress(RE);
1351 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1352 if (isRelocationScattered(RE))
1353 return getScatteredRelocationPCRel(this, RE);
1354 return getPlainRelocationPCRel(this, RE);
1358 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1359 if (isRelocationScattered(RE))
1360 return getScatteredRelocationLength(RE);
1361 return getPlainRelocationLength(this, RE);
1365 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1366 if (isRelocationScattered(RE))
1367 return getScatteredRelocationType(RE);
1368 return getPlainRelocationType(this, RE);
1371 MachOObjectFile::LoadCommandInfo
1372 MachOObjectFile::getFirstLoadCommandInfo() const {
1373 MachOObjectFile::LoadCommandInfo Load;
1375 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1376 Load.Ptr = getPtr(this, HeaderSize);
1377 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
1381 MachOObjectFile::LoadCommandInfo
1382 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1383 MachOObjectFile::LoadCommandInfo Next;
1384 Next.Ptr = L.Ptr + L.C.Size;
1385 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
1389 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1390 return getStruct<macho::Section>(this, Sections[DRI.d.a]);
1393 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1394 return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
1397 macho::SymbolTableEntry
1398 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1399 const char *P = getSymbolTableEntryPtr(this, DRI);
1400 return getStruct<macho::SymbolTableEntry>(this, P);
1403 macho::Symbol64TableEntry
1404 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1405 const char *P = getSymbolTableEntryPtr(this, DRI);
1406 return getStruct<macho::Symbol64TableEntry>(this, P);
1409 macho::LinkeditDataLoadCommand
1410 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1411 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
1414 macho::RelocationEntry
1415 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1416 const char *P = reinterpret_cast<const char *>(Rel.p);
1417 return getStruct<macho::RelocationEntry>(this, P);
1420 macho::Header MachOObjectFile::getHeader() const {
1421 return getStruct<macho::Header>(this, getPtr(this, 0));
1424 macho::SymtabLoadCommand
1425 MachOObjectFile::getSymtabLoadCommand() const {
1426 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
1429 bool MachOObjectFile::is64Bit() const {
1430 return getType() == getMachOType(false, true) ||
1431 getType() == getMachOType(true, true);
1434 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1435 SmallVectorImpl<uint64_t> &Out) const {
1436 DataExtractor extractor(ObjectFile::getData(), true, 0);
1438 uint32_t offset = Index;
1440 while (uint64_t delta = extractor.getULEB128(&offset)) {
1442 Out.push_back(data);
1446 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1447 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1450 if (Magic == "\xFE\xED\xFA\xCE")
1451 Ret = new MachOObjectFile(Buffer, false, false, ec);
1452 else if (Magic == "\xCE\xFA\xED\xFE")
1453 Ret = new MachOObjectFile(Buffer, true, false, ec);
1454 else if (Magic == "\xFE\xED\xFA\xCF")
1455 Ret = new MachOObjectFile(Buffer, false, true, ec);
1456 else if (Magic == "\xCF\xFA\xED\xFE")
1457 Ret = new MachOObjectFile(Buffer, true, true, ec);
1466 } // end namespace object
1467 } // end namespace llvm