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);
168 static bool isSwappedEndian(const MachOObjectFile *O) {
169 return O->isLittleEndian() != sys::IsLittleEndianHost;
172 static macho::SegmentLoadCommand
173 getSegmentLoadCommand(const MachOObjectFile *O,
174 const MachOObjectFile::LoadCommandInfo &L) {
175 macho::SegmentLoadCommand Cmd;
176 memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand));
177 if (isSwappedEndian(O))
182 static macho::Segment64LoadCommand
183 getSegment64LoadCommand(const MachOObjectFile *O,
184 const MachOObjectFile::LoadCommandInfo &L) {
185 macho::Segment64LoadCommand Cmd;
186 memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand));
187 if (isSwappedEndian(O))
193 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
194 const MachOObjectFile::LoadCommandInfo &L) {
196 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
197 return S.NumSections;
199 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
200 return S.NumSections;
203 static const SectionBase *
204 getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
206 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
208 bool Is64 = O->is64Bit();
209 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
210 sizeof(macho::SegmentLoadCommand);
211 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
212 sizeof(macho::Section);
214 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
215 return reinterpret_cast<const SectionBase*>(SectionAddr);
218 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
219 return O->getData().substr(Offset, 1).data();
222 static const char *getSymbolTableEntryPtr(const MachOObjectFile *O,
224 macho::SymtabLoadCommand S = O->getSymtabLoadCommand();
226 unsigned Index = DRI.d.b;
228 unsigned SymbolTableEntrySize = O->is64Bit() ?
229 sizeof(macho::Symbol64TableEntry) :
230 sizeof(macho::SymbolTableEntry);
232 uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize;
233 return getPtr(O, Offset);
236 static SymbolTableEntryBase
237 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
238 const char *P = getSymbolTableEntryPtr(O, DRI);
239 SymbolTableEntryBase Ret;
240 memcpy(&Ret, P, sizeof(SymbolTableEntryBase));
241 if (isSwappedEndian(O))
247 static StringRef parseSegmentOrSectionName(const char *P) {
251 // Not null terminated, so this is a 16 char string.
252 return StringRef(P, 16);
255 // Helper to advance a section or symbol iterator multiple increments at a time.
257 static error_code advance(T &it, size_t Val) {
266 static void advanceTo(T &it, size_t Val) {
267 if (error_code ec = advance(it, Val))
268 report_fatal_error(ec.message());
271 static unsigned getCPUType(const MachOObjectFile *O) {
272 return O->getHeader().CPUType;
275 static void printRelocationTargetName(const MachOObjectFile *O,
276 const macho::RelocationEntry &RE,
277 raw_string_ostream &fmt) {
278 bool IsScattered = O->isRelocationScattered(RE);
280 // Target of a scattered relocation is an address. In the interest of
281 // generating pretty output, scan through the symbol table looking for a
282 // symbol that aligns with that address. If we find one, print it.
283 // Otherwise, we just print the hex address of the target.
285 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
288 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
289 SI != SE; SI.increment(ec)) {
290 if (ec) report_fatal_error(ec.message());
295 if ((ec = SI->getAddress(Addr)))
296 report_fatal_error(ec.message());
297 if (Addr != Val) continue;
298 if ((ec = SI->getName(Name)))
299 report_fatal_error(ec.message());
304 // If we couldn't find a symbol that this relocation refers to, try
305 // to find a section beginning instead.
306 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
307 SI != SE; SI.increment(ec)) {
308 if (ec) report_fatal_error(ec.message());
313 if ((ec = SI->getAddress(Addr)))
314 report_fatal_error(ec.message());
315 if (Addr != Val) continue;
316 if ((ec = SI->getName(Name)))
317 report_fatal_error(ec.message());
322 fmt << format("0x%x", Val);
327 bool isExtern = O->getPlainRelocationExternal(RE);
328 uint64_t Val = O->getAnyRelocationAddress(RE);
331 symbol_iterator SI = O->begin_symbols();
335 section_iterator SI = O->begin_sections();
343 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
348 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
349 return RE.Word0 & 0xffffff;
352 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
353 const macho::RelocationEntry &RE) {
354 if (O->isLittleEndian())
355 return (RE.Word1 >> 24) & 1;
356 return (RE.Word1 >> 7) & 1;
360 getScatteredRelocationPCRel(const MachOObjectFile *O,
361 const macho::RelocationEntry &RE) {
362 return (RE.Word0 >> 30) & 1;
365 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
366 const macho::RelocationEntry &RE) {
367 if (O->isLittleEndian())
368 return (RE.Word1 >> 25) & 3;
369 return (RE.Word1 >> 5) & 3;
373 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
374 return (RE.Word0 >> 28) & 3;
377 static unsigned getPlainRelocationType(const MachOObjectFile *O,
378 const macho::RelocationEntry &RE) {
379 if (O->isLittleEndian())
380 return RE.Word1 >> 28;
381 return RE.Word1 & 0xf;
384 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
385 return (RE.Word0 >> 24) & 0xf;
388 static uint32_t getSectionFlags(const MachOObjectFile *O,
391 macho::Section64 Sect = O->getSection64(Sec);
394 macho::Section Sect = O->getSection(Sec);
398 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
399 bool IsLittleEndian, bool Is64bits,
401 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
402 SymtabLoadCmd(NULL) {
403 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
404 macho::LoadCommandType SegmentLoadType = is64Bit() ?
405 macho::LCT_Segment64 : macho::LCT_Segment;
407 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
408 for (unsigned I = 0; I < LoadCommandCount; ++I) {
409 if (Load.C.Type == macho::LCT_Symtab) {
410 assert(!SymtabLoadCmd && "Multiple symbol tables");
411 SymtabLoadCmd = Load.Ptr;
414 if (Load.C.Type == SegmentLoadType) {
415 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
416 for (unsigned J = 0; J < NumSections; ++J) {
417 const SectionBase *Sec = getSectionBase(this, Load, J);
418 Sections.push_back(reinterpret_cast<const char*>(Sec));
421 Load = getNextLoadCommandInfo(Load);
425 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
426 SymbolRef &Res) const {
428 Res = SymbolRef(Symb, this);
429 return object_error::success;
432 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
433 StringRef &Res) const {
434 macho::SymtabLoadCommand S = getSymtabLoadCommand();
435 const char *StringTable = getPtr(this, S.StringTableOffset);
436 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
437 const char *Start = &StringTable[Entry.StringIndex];
438 Res = StringRef(Start);
439 return object_error::success;
442 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
443 uint64_t &Res) const {
445 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
448 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
451 return object_error::success;
455 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
456 uint64_t &Res) const {
457 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
458 getSymbolAddress(Symb, Res);
459 if (Entry.SectionIndex) {
462 SecRel.d.a = Entry.SectionIndex-1;
464 macho::Section64 Sec = getSection64(SecRel);
465 Delta = Sec.Offset - Sec.Address;
467 macho::Section Sec = getSection(SecRel);
468 Delta = Sec.Offset - Sec.Address;
474 return object_error::success;
477 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
478 uint64_t &Result) const {
479 uint64_t BeginOffset;
480 uint64_t EndOffset = 0;
481 uint8_t SectionIndex;
483 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
485 getSymbolAddress(DRI, Value);
489 SectionIndex = Entry.SectionIndex;
491 uint32_t flags = SymbolRef::SF_None;
492 this->getSymbolFlags(DRI, flags);
493 if (flags & SymbolRef::SF_Common)
496 Result = UnknownAddressOrSize;
497 return object_error::success;
499 // Unfortunately symbols are unsorted so we need to touch all
500 // symbols from load command
501 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
503 while (DRI.d.b <= Symtab.NumSymbolTableEntries) {
504 Entry = getSymbolTableEntryBase(this, DRI);
505 getSymbolAddress(DRI, Value);
506 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
507 if (!EndOffset || Value < EndOffset)
514 Sec.d.a = SectionIndex-1;
515 getSectionSize(Sec, Size);
516 getSectionAddress(Sec, EndOffset);
519 Result = EndOffset - BeginOffset;
520 return object_error::success;
523 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
524 SymbolRef::Type &Res) const {
525 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
526 uint8_t n_type = Entry.Type;
528 Res = SymbolRef::ST_Other;
530 // If this is a STAB debugging symbol, we can do nothing more.
531 if (n_type & MachO::NlistMaskStab) {
532 Res = SymbolRef::ST_Debug;
533 return object_error::success;
536 switch (n_type & MachO::NlistMaskType) {
537 case MachO::NListTypeUndefined :
538 Res = SymbolRef::ST_Unknown;
540 case MachO::NListTypeSection :
541 Res = SymbolRef::ST_Function;
544 return object_error::success;
547 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
549 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
550 uint8_t Type = Entry.Type;
551 uint16_t Flags = Entry.Flags;
554 switch (Type & macho::STF_TypeMask) {
555 case macho::STT_Undefined:
558 case macho::STT_Absolute:
559 case macho::STT_Section:
567 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
568 Char = toupper(static_cast<unsigned char>(Char));
570 return object_error::success;
573 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
574 uint32_t &Result) const {
575 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
577 uint8_t MachOType = Entry.Type;
578 uint16_t MachOFlags = Entry.Flags;
580 // TODO: Correctly set SF_ThreadLocal
581 Result = SymbolRef::SF_None;
583 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
584 Result |= SymbolRef::SF_Undefined;
586 if (MachOFlags & macho::STF_StabsEntryMask)
587 Result |= SymbolRef::SF_FormatSpecific;
589 if (MachOType & MachO::NlistMaskExternal) {
590 Result |= SymbolRef::SF_Global;
591 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
592 Result |= SymbolRef::SF_Common;
595 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
596 Result |= SymbolRef::SF_Weak;
598 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
599 Result |= SymbolRef::SF_Absolute;
601 return object_error::success;
605 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
606 section_iterator &Res) const {
607 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
608 uint8_t index = Entry.SectionIndex;
611 Res = end_sections();
615 Res = section_iterator(SectionRef(DRI, this));
618 return object_error::success;
621 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
622 uint64_t &Val) const {
623 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
626 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
627 SectionRef &Res) const {
629 Res = SectionRef(Sec, this);
630 return object_error::success;
634 MachOObjectFile::getSectionName(DataRefImpl Sec,
635 StringRef &Result) const {
636 ArrayRef<char> Raw = getSectionRawName(Sec);
637 Result = parseSegmentOrSectionName(Raw.data());
638 return object_error::success;
642 MachOObjectFile::getSectionAddress(DataRefImpl Sec,
643 uint64_t &Res) const {
645 macho::Section64 Sect = getSection64(Sec);
648 macho::Section Sect = getSection(Sec);
651 return object_error::success;
655 MachOObjectFile::getSectionSize(DataRefImpl Sec,
656 uint64_t &Res) const {
658 macho::Section64 Sect = getSection64(Sec);
661 macho::Section Sect = getSection(Sec);
665 return object_error::success;
669 MachOObjectFile::getSectionContents(DataRefImpl Sec,
670 StringRef &Res) const {
675 macho::Section64 Sect = getSection64(Sec);
676 Offset = Sect.Offset;
679 macho::Section Sect =getSection(Sec);
680 Offset = Sect.Offset;
684 Res = this->getData().substr(Offset, Size);
685 return object_error::success;
689 MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
690 uint64_t &Res) const {
693 macho::Section64 Sect = getSection64(Sec);
696 macho::Section Sect = getSection(Sec);
700 Res = uint64_t(1) << Align;
701 return object_error::success;
705 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
706 uint32_t Flags = getSectionFlags(this, Sec);
707 Res = Flags & macho::SF_PureInstructions;
708 return object_error::success;
711 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
712 bool &Result) const {
713 // FIXME: Unimplemented.
715 return object_error::success;
718 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
719 bool &Result) const {
720 // FIXME: Unimplemented.
722 return object_error::success;
726 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
727 bool &Result) const {
728 // FIXME: Unimplemented.
730 return object_error::success;
733 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
734 bool &Result) const {
735 // FIXME: Unimplemented.
737 return object_error::success;
741 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
742 uint32_t Flags = getSectionFlags(this, Sec);
743 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
744 Res = SectionType == MachO::SectionTypeZeroFill ||
745 SectionType == MachO::SectionTypeZeroFillLarge;
746 return object_error::success;
749 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
750 bool &Result) const {
751 // Consider using the code from isSectionText to look for __const sections.
752 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
753 // to use section attributes to distinguish code from data.
755 // FIXME: Unimplemented.
757 return object_error::success;
761 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
763 bool &Result) const {
765 this->getSymbolType(Symb, ST);
766 if (ST == SymbolRef::ST_Unknown) {
768 return object_error::success;
771 uint64_t SectBegin, SectEnd;
772 getSectionAddress(Sec, SectBegin);
773 getSectionSize(Sec, SectEnd);
774 SectEnd += SectBegin;
777 getSymbolAddress(Symb, SymAddr);
778 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
780 return object_error::success;
783 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
786 return relocation_iterator(RelocationRef(ret, this));
790 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
793 macho::Section64 Sect = getSection64(Sec);
794 LastReloc = Sect.NumRelocationTableEntries;
796 macho::Section Sect = getSection(Sec);
797 LastReloc = Sect.NumRelocationTableEntries;
803 return relocation_iterator(RelocationRef(Ret, this));
806 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
807 RelocationRef &Res) const {
809 Res = RelocationRef(Rel, this);
810 return object_error::success;
814 MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
815 uint64_t &Res) const {
816 uint64_t SectAddress;
820 macho::Section64 Sect = getSection64(Sec);
821 SectAddress = Sect.Address;
823 macho::Section Sect = getSection(Sec);
824 SectAddress = Sect.Address;
827 macho::RelocationEntry RE = getRelocation(Rel);
828 uint64_t RelAddr = getAnyRelocationAddress(RE);
829 Res = SectAddress + RelAddr;
830 return object_error::success;
833 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
834 uint64_t &Res) const {
835 macho::RelocationEntry RE = getRelocation(Rel);
836 Res = getAnyRelocationAddress(RE);
837 return object_error::success;
841 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
842 SymbolRef &Res) const {
843 macho::RelocationEntry RE = getRelocation(Rel);
844 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
845 bool isExtern = getPlainRelocationExternal(RE);
851 Res = SymbolRef(Sym, this);
852 return object_error::success;
855 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
856 uint64_t &Res) const {
857 macho::RelocationEntry RE = getRelocation(Rel);
858 Res = getAnyRelocationType(RE);
859 return object_error::success;
863 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
864 SmallVectorImpl<char> &Result) const {
867 getRelocationType(Rel, RType);
869 unsigned Arch = this->getArch();
873 static const char *const Table[] = {
874 "GENERIC_RELOC_VANILLA",
875 "GENERIC_RELOC_PAIR",
876 "GENERIC_RELOC_SECTDIFF",
877 "GENERIC_RELOC_PB_LA_PTR",
878 "GENERIC_RELOC_LOCAL_SECTDIFF",
879 "GENERIC_RELOC_TLV" };
887 case Triple::x86_64: {
888 static const char *const Table[] = {
889 "X86_64_RELOC_UNSIGNED",
890 "X86_64_RELOC_SIGNED",
891 "X86_64_RELOC_BRANCH",
892 "X86_64_RELOC_GOT_LOAD",
894 "X86_64_RELOC_SUBTRACTOR",
895 "X86_64_RELOC_SIGNED_1",
896 "X86_64_RELOC_SIGNED_2",
897 "X86_64_RELOC_SIGNED_4",
898 "X86_64_RELOC_TLV" };
907 static const char *const Table[] = {
910 "ARM_RELOC_SECTDIFF",
911 "ARM_RELOC_LOCAL_SECTDIFF",
912 "ARM_RELOC_PB_LA_PTR",
914 "ARM_THUMB_RELOC_BR22",
915 "ARM_THUMB_32BIT_BRANCH",
917 "ARM_RELOC_HALF_SECTDIFF" };
926 static const char *const Table[] = {
935 "PPC_RELOC_SECTDIFF",
936 "PPC_RELOC_PB_LA_PTR",
937 "PPC_RELOC_HI16_SECTDIFF",
938 "PPC_RELOC_LO16_SECTDIFF",
939 "PPC_RELOC_HA16_SECTDIFF",
941 "PPC_RELOC_LO14_SECTDIFF",
942 "PPC_RELOC_LOCAL_SECTDIFF" };
947 case Triple::UnknownArch:
951 Result.append(res.begin(), res.end());
952 return object_error::success;
955 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
956 int64_t &Res) const {
958 return object_error::success;
962 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
963 SmallVectorImpl<char> &Result) const {
964 macho::RelocationEntry RE = getRelocation(Rel);
966 unsigned Arch = this->getArch();
969 raw_string_ostream fmt(fmtbuf);
970 unsigned Type = this->getAnyRelocationType(RE);
971 bool IsPCRel = this->getAnyRelocationPCRel(RE);
973 // Determine any addends that should be displayed with the relocation.
974 // These require decoding the relocation type, which is triple-specific.
976 // X86_64 has entirely custom relocation types.
977 if (Arch == Triple::x86_64) {
978 bool isPCRel = getAnyRelocationPCRel(RE);
981 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
982 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
983 printRelocationTargetName(this, RE, fmt);
985 if (isPCRel) fmt << "PCREL";
988 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
989 DataRefImpl RelNext = Rel;
991 macho::RelocationEntry RENext = getRelocation(RelNext);
993 // X86_64_SUBTRACTOR must be followed by a relocation of type
994 // X86_64_RELOC_UNSIGNED.
995 // NOTE: Scattered relocations don't exist on x86_64.
996 unsigned RType = getAnyRelocationType(RENext);
998 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
999 "X86_64_RELOC_SUBTRACTOR.");
1001 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1002 // X86_64_SUBTRACTOR contains to the subtrahend.
1003 printRelocationTargetName(this, RENext, fmt);
1005 printRelocationTargetName(this, RE, fmt);
1008 case macho::RIT_X86_64_TLV:
1009 printRelocationTargetName(this, RE, fmt);
1011 if (isPCRel) fmt << "P";
1013 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1014 printRelocationTargetName(this, RE, fmt);
1017 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1018 printRelocationTargetName(this, RE, fmt);
1021 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1022 printRelocationTargetName(this, RE, fmt);
1026 printRelocationTargetName(this, RE, fmt);
1029 // X86 and ARM share some relocation types in common.
1030 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1031 // Generic relocation types...
1033 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1034 return object_error::success;
1035 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1036 DataRefImpl RelNext = Rel;
1038 macho::RelocationEntry RENext = getRelocation(RelNext);
1040 // X86 sect diff's must be followed by a relocation of type
1041 // GENERIC_RELOC_PAIR.
1042 unsigned RType = getAnyRelocationType(RENext);
1045 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1046 "GENERIC_RELOC_SECTDIFF.");
1048 printRelocationTargetName(this, RE, fmt);
1050 printRelocationTargetName(this, RENext, fmt);
1055 if (Arch == Triple::x86) {
1056 // All X86 relocations that need special printing were already
1057 // handled in the generic code.
1059 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1060 DataRefImpl RelNext = Rel;
1062 macho::RelocationEntry RENext = getRelocation(RelNext);
1064 // X86 sect diff's must be followed by a relocation of type
1065 // GENERIC_RELOC_PAIR.
1066 unsigned RType = getAnyRelocationType(RENext);
1068 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1069 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1071 printRelocationTargetName(this, RE, fmt);
1073 printRelocationTargetName(this, RENext, fmt);
1076 case macho::RIT_Generic_TLV: {
1077 printRelocationTargetName(this, RE, fmt);
1079 if (IsPCRel) fmt << "P";
1083 printRelocationTargetName(this, RE, fmt);
1085 } else { // ARM-specific relocations
1087 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1088 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1089 // Half relocations steal a bit from the length field to encode
1090 // whether this is an upper16 or a lower16 relocation.
1091 bool isUpper = getAnyRelocationLength(RE) >> 1;
1094 fmt << ":upper16:(";
1096 fmt << ":lower16:(";
1097 printRelocationTargetName(this, RE, fmt);
1099 DataRefImpl RelNext = Rel;
1101 macho::RelocationEntry RENext = getRelocation(RelNext);
1103 // ARM half relocs must be followed by a relocation of type
1105 unsigned RType = getAnyRelocationType(RENext);
1107 report_fatal_error("Expected ARM_RELOC_PAIR after "
1108 "GENERIC_RELOC_HALF");
1110 // NOTE: The half of the target virtual address is stashed in the
1111 // address field of the secondary relocation, but we can't reverse
1112 // engineer the constant offset from it without decoding the movw/movt
1113 // instruction to find the other half in its immediate field.
1115 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1116 // symbol/section pointer of the follow-on relocation.
1117 if (Type == macho::RIT_ARM_HalfDifference) {
1119 printRelocationTargetName(this, RENext, fmt);
1126 printRelocationTargetName(this, RE, fmt);
1131 printRelocationTargetName(this, RE, fmt);
1134 Result.append(fmtbuf.begin(), fmtbuf.end());
1135 return object_error::success;
1139 MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1140 bool &Result) const {
1141 unsigned Arch = getArch();
1143 getRelocationType(Rel, Type);
1147 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1148 // is always hidden.
1149 if (Arch == Triple::x86 || Arch == Triple::arm) {
1150 if (Type == macho::RIT_Pair) Result = true;
1151 } else if (Arch == Triple::x86_64) {
1152 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1153 // an X864_64_RELOC_SUBTRACTOR.
1154 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1155 DataRefImpl RelPrev = Rel;
1158 getRelocationType(RelPrev, PrevType);
1159 if (PrevType == macho::RIT_X86_64_Subtractor)
1164 return object_error::success;
1167 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1168 LibraryRef &Res) const {
1169 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1172 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1173 StringRef &Res) const {
1174 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1177 symbol_iterator MachOObjectFile::begin_symbols() const {
1178 // DRI.d.a = segment number; DRI.d.b = symbol index.
1180 return symbol_iterator(SymbolRef(DRI, this));
1183 symbol_iterator MachOObjectFile::end_symbols() const {
1185 if (SymtabLoadCmd) {
1186 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1187 DRI.d.b = Symtab.NumSymbolTableEntries;
1189 return symbol_iterator(SymbolRef(DRI, this));
1192 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1194 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1197 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1199 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1202 section_iterator MachOObjectFile::begin_sections() const {
1204 return section_iterator(SectionRef(DRI, this));
1207 section_iterator MachOObjectFile::end_sections() const {
1209 DRI.d.a = Sections.size();
1210 return section_iterator(SectionRef(DRI, this));
1213 library_iterator MachOObjectFile::begin_libraries_needed() const {
1215 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1218 library_iterator MachOObjectFile::end_libraries_needed() const {
1220 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1223 uint8_t MachOObjectFile::getBytesInAddress() const {
1224 return is64Bit() ? 8 : 4;
1227 StringRef MachOObjectFile::getFileFormatName() const {
1228 unsigned CPUType = getCPUType(this);
1231 case llvm::MachO::CPUTypeI386:
1232 return "Mach-O 32-bit i386";
1233 case llvm::MachO::CPUTypeARM:
1234 return "Mach-O arm";
1235 case llvm::MachO::CPUTypePowerPC:
1236 return "Mach-O 32-bit ppc";
1238 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1239 "64-bit object file when we're not 64-bit?");
1240 return "Mach-O 32-bit unknown";
1244 // Make sure the cpu type has the correct mask.
1245 assert((CPUType & llvm::MachO::CPUArchABI64)
1246 == llvm::MachO::CPUArchABI64 &&
1247 "32-bit object file when we're 64-bit?");
1250 case llvm::MachO::CPUTypeX86_64:
1251 return "Mach-O 64-bit x86-64";
1252 case llvm::MachO::CPUTypePowerPC64:
1253 return "Mach-O 64-bit ppc64";
1255 return "Mach-O 64-bit unknown";
1259 unsigned MachOObjectFile::getArch() const {
1260 switch (getCPUType(this)) {
1261 case llvm::MachO::CPUTypeI386:
1263 case llvm::MachO::CPUTypeX86_64:
1264 return Triple::x86_64;
1265 case llvm::MachO::CPUTypeARM:
1267 case llvm::MachO::CPUTypePowerPC:
1269 case llvm::MachO::CPUTypePowerPC64:
1270 return Triple::ppc64;
1272 return Triple::UnknownArch;
1276 StringRef MachOObjectFile::getLoadName() const {
1278 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1282 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1283 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1284 return parseSegmentOrSectionName(Raw.data());
1288 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1289 const SectionBase *Base =
1290 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1291 return ArrayRef<char>(Base->Name);
1295 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1296 const SectionBase *Base =
1297 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1298 return ArrayRef<char>(Base->SegmentName);
1302 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1304 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1306 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1309 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1310 if (isLittleEndian())
1311 return RE.Word1 & 0xffffff;
1312 return RE.Word1 >> 8;
1315 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1316 if (isLittleEndian())
1317 return (RE.Word1 >> 27) & 1;
1318 return (RE.Word1 >> 4) & 1;
1322 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1323 return RE.Word0 >> 31;
1327 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1332 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1333 if (isRelocationScattered(RE))
1334 return getScatteredRelocationAddress(RE);
1335 return getPlainRelocationAddress(RE);
1339 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1340 if (isRelocationScattered(RE))
1341 return getScatteredRelocationPCRel(this, RE);
1342 return getPlainRelocationPCRel(this, RE);
1346 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1347 if (isRelocationScattered(RE))
1348 return getScatteredRelocationLength(RE);
1349 return getPlainRelocationLength(this, RE);
1353 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1354 if (isRelocationScattered(RE))
1355 return getScatteredRelocationType(RE);
1356 return getPlainRelocationType(this, RE);
1359 MachOObjectFile::LoadCommandInfo
1360 MachOObjectFile::getFirstLoadCommandInfo() const {
1361 MachOObjectFile::LoadCommandInfo Load;
1363 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1364 Load.Ptr = getPtr(this, HeaderSize);
1365 memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand));
1366 if (isSwappedEndian(this))
1371 MachOObjectFile::LoadCommandInfo
1372 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1373 MachOObjectFile::LoadCommandInfo Next;
1374 Next.Ptr = L.Ptr + L.C.Size;
1375 memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand));
1376 if (isSwappedEndian(this))
1381 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1382 const SectionBase *Addr =
1383 reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1385 memcpy(&Ret, Addr, sizeof(macho::Section));
1386 if (isSwappedEndian(this))
1391 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1392 const SectionBase *Addr =
1393 reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1394 macho::Section64 Ret;
1395 memcpy(&Ret, Addr, sizeof(macho::Section64));
1396 if (isSwappedEndian(this))
1401 macho::SymbolTableEntry
1402 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1403 const char *P = getSymbolTableEntryPtr(this, DRI);
1404 macho::SymbolTableEntry Ret;
1405 memcpy(&Ret, P, sizeof(macho::SymbolTableEntry));
1406 if (isSwappedEndian(this))
1411 macho::Symbol64TableEntry
1412 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1413 const char *P = getSymbolTableEntryPtr(this, DRI);
1414 macho::Symbol64TableEntry Ret;
1415 memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry));
1416 if (isSwappedEndian(this))
1421 macho::LinkeditDataLoadCommand
1422 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1423 macho::LinkeditDataLoadCommand Cmd;
1424 memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand));
1425 if (isSwappedEndian(this))
1430 macho::RelocationEntry
1431 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1436 macho::Section64 Sect = getSection64(Sec);
1437 RelOffset = Sect.RelocationTableOffset;
1439 macho::Section Sect = getSection(Sec);
1440 RelOffset = Sect.RelocationTableOffset;
1443 uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry);
1445 macho::RelocationEntry Ret;
1446 memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry));
1447 if (isSwappedEndian(this))
1453 macho::Header MachOObjectFile::getHeader() const {
1455 memcpy(&H, getPtr(this, 0), sizeof(macho::Header));
1456 if (isSwappedEndian(this))
1461 macho::SymtabLoadCommand
1462 MachOObjectFile::getSymtabLoadCommand() const {
1463 macho::SymtabLoadCommand Cmd;
1464 memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand));
1465 if (isSwappedEndian(this))
1470 bool MachOObjectFile::is64Bit() const {
1471 return getType() == getMachOType(false, true) ||
1472 getType() == getMachOType(true, true);
1475 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1476 SmallVectorImpl<uint64_t> &Out) const {
1477 DataExtractor extractor(ObjectFile::getData(), true, 0);
1479 uint32_t offset = Index;
1481 while (uint64_t delta = extractor.getULEB128(&offset)) {
1483 Out.push_back(data);
1487 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1488 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1491 if (Magic == "\xFE\xED\xFA\xCE")
1492 Ret = new MachOObjectFile(Buffer, false, false, ec);
1493 else if (Magic == "\xCE\xFA\xED\xFE")
1494 Ret = new MachOObjectFile(Buffer, true, false, ec);
1495 else if (Magic == "\xFE\xED\xFA\xCF")
1496 Ret = new MachOObjectFile(Buffer, false, true, ec);
1497 else if (Magic == "\xCF\xFA\xED\xFE")
1498 Ret = new MachOObjectFile(Buffer, true, true, ec);
1507 } // end namespace object
1508 } // end namespace llvm