1 //===- MachO.h - MachO object file implementation ---------------*- 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 declares the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_OBJECT_MACHO_H
16 #define LLVM_OBJECT_MACHO_H
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Object/MachOObject.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/raw_ostream.h"
30 namespace MachOFormat {
36 template<bool is64Bits>
40 struct Section<false> {
43 support::ulittle32_t Address;
44 support::ulittle32_t Size;
45 support::ulittle32_t Offset;
46 support::ulittle32_t Align;
47 support::ulittle32_t RelocationTableOffset;
48 support::ulittle32_t NumRelocationTableEntries;
49 support::ulittle32_t Flags;
50 support::ulittle32_t Reserved1;
51 support::ulittle32_t Reserved2;
55 struct Section<true> {
58 support::ulittle64_t Address;
59 support::ulittle64_t Size;
60 support::ulittle32_t Offset;
61 support::ulittle32_t Align;
62 support::ulittle32_t RelocationTableOffset;
63 support::ulittle32_t NumRelocationTableEntries;
64 support::ulittle32_t Flags;
65 support::ulittle32_t Reserved1;
66 support::ulittle32_t Reserved2;
67 support::ulittle32_t Reserved3;
70 struct RelocationEntry {
71 support::ulittle32_t Word0;
72 support::ulittle32_t Word1;
75 struct SymbolTableEntryBase {
76 support::ulittle32_t StringIndex;
79 support::ulittle16_t Flags;
82 template<bool is64Bits>
83 struct SymbolTableEntry;
86 struct SymbolTableEntry<false> {
87 support::ulittle32_t StringIndex;
90 support::ulittle16_t Flags;
91 support::ulittle32_t Value;
95 struct SymbolTableEntry<true> {
96 support::ulittle32_t StringIndex;
99 support::ulittle16_t Flags;
100 support::ulittle64_t Value;
104 support::ulittle32_t Type;
105 support::ulittle32_t Size;
108 struct SymtabLoadCommand {
109 support::ulittle32_t Type;
110 support::ulittle32_t Size;
111 support::ulittle32_t SymbolTableOffset;
112 support::ulittle32_t NumSymbolTableEntries;
113 support::ulittle32_t StringTableOffset;
114 support::ulittle32_t StringTableSize;
117 template<bool is64Bits>
118 struct SegmentLoadCommand;
121 struct SegmentLoadCommand<false> {
122 support::ulittle32_t Type;
123 support::ulittle32_t Size;
125 support::ulittle32_t VMAddress;
126 support::ulittle32_t VMSize;
127 support::ulittle32_t FileOffset;
128 support::ulittle32_t FileSize;
129 support::ulittle32_t MaxVMProtection;
130 support::ulittle32_t InitialVMProtection;
131 support::ulittle32_t NumSections;
132 support::ulittle32_t Flags;
136 struct SegmentLoadCommand<true> {
137 support::ulittle32_t Type;
138 support::ulittle32_t Size;
140 support::ulittle64_t VMAddress;
141 support::ulittle64_t VMSize;
142 support::ulittle64_t FileOffset;
143 support::ulittle64_t FileSize;
144 support::ulittle32_t MaxVMProtection;
145 support::ulittle32_t InitialVMProtection;
146 support::ulittle32_t NumSections;
147 support::ulittle32_t Flags;
150 struct LinkeditDataLoadCommand {
151 support::ulittle32_t Type;
152 support::ulittle32_t Size;
153 support::ulittle32_t DataOffset;
154 support::ulittle32_t DataSize;
158 support::ulittle32_t Magic;
159 support::ulittle32_t CPUType;
160 support::ulittle32_t CPUSubtype;
161 support::ulittle32_t FileType;
162 support::ulittle32_t NumLoadCommands;
163 support::ulittle32_t SizeOfLoadCommands;
164 support::ulittle32_t Flags;
168 class MachOObjectFileBase : public ObjectFile {
170 typedef MachOFormat::SymbolTableEntryBase SymbolTableEntryBase;
171 typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand;
172 typedef MachOFormat::RelocationEntry RelocationEntry;
173 typedef MachOFormat::SectionBase SectionBase;
174 typedef MachOFormat::LoadCommand LoadCommand;
175 typedef MachOFormat::Header Header;
177 MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
179 virtual symbol_iterator begin_symbols() const;
180 virtual symbol_iterator end_symbols() const;
181 virtual symbol_iterator begin_dynamic_symbols() const;
182 virtual symbol_iterator end_dynamic_symbols() const;
183 virtual library_iterator begin_libraries_needed() const;
184 virtual library_iterator end_libraries_needed() const;
185 virtual section_iterator end_sections() const;
187 virtual uint8_t getBytesInAddress() const;
188 virtual StringRef getFileFormatName() const;
189 virtual unsigned getArch() const;
190 virtual StringRef getLoadName() const;
192 // In a MachO file, sections have a segment name. This is used in the .o
193 // files. They have a single segment, but this field specifies which segment
194 // a section should be put in in the final object.
195 StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
197 // Names are stored as 16 bytes. These returns the raw 16 bytes without
198 // interpreting them as a C string.
199 ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
200 ArrayRef<char>getSectionRawFinalSegmentName(DataRefImpl Sec) const;
202 bool is64Bit() const;
203 const LoadCommand *getLoadCommandInfo(unsigned Index) const;
204 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
205 const Header *getHeader() const;
206 unsigned getHeaderSize() const;
207 StringRef getData(size_t Offset, size_t Size) const;
209 static inline bool classof(const Binary *v) {
214 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
215 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
216 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
217 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
218 virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const;
219 virtual error_code getSymbolSection(DataRefImpl Symb,
220 section_iterator &Res) const;
221 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
222 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
223 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
224 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
225 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
227 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
228 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
229 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
231 virtual error_code getRelocationNext(DataRefImpl Rel,
232 RelocationRef &Res) const;
234 virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
235 virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
237 std::size_t getSectionIndex(DataRefImpl Sec) const;
239 typedef SmallVector<DataRefImpl, 1> SectionList;
240 SectionList Sections;
242 void moveToNextSymbol(DataRefImpl &DRI) const;
243 void printRelocationTargetName(const RelocationEntry *RE,
244 raw_string_ostream &fmt) const;
245 const SectionBase *getSectionBase(DataRefImpl DRI) const;
246 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
250 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI,
251 const SymtabLoadCommand *SymtabLoadCmd) const;
254 template<bool is64Bits>
255 struct MachOObjectFileHelperCommon {
256 typedef MachOFormat::SegmentLoadCommand<is64Bits> SegmentLoadCommand;
257 typedef MachOFormat::SymbolTableEntry<is64Bits> SymbolTableEntry;
258 typedef MachOFormat::Section<is64Bits> Section;
261 template<bool is64Bits>
262 struct MachOObjectFileHelper;
265 struct MachOObjectFileHelper<false> :
266 public MachOObjectFileHelperCommon<false> {
267 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
271 struct MachOObjectFileHelper<true> :
272 public MachOObjectFileHelperCommon<true> {
273 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
276 template<bool is64Bits>
277 class MachOObjectFile : public MachOObjectFileBase {
279 static const macho::LoadCommandType SegmentLoadType =
280 MachOObjectFileHelper<is64Bits>::SegmentLoadType;
281 typedef typename MachOObjectFileHelper<is64Bits>::SegmentLoadCommand
283 typedef typename MachOObjectFileHelper<is64Bits>::SymbolTableEntry
285 typedef typename MachOObjectFileHelper<is64Bits>::Section Section;
287 MachOObjectFile(MemoryBuffer *Object, error_code &ec) :
288 MachOObjectFileBase(Object, is64Bits, ec) {
290 moveToNextSection(DRI);
291 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
292 while (DRI.d.a < LoadCommandCount) {
293 Sections.push_back(DRI);
295 moveToNextSection(DRI);
299 static inline bool classof(const Binary *v) {
300 return v->getType() == getMachOType(true, is64Bits);
303 const Section *getSection(DataRefImpl DRI) const;
304 const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
305 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
307 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
308 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
309 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
310 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
311 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
312 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
313 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
314 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
315 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
316 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
317 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
319 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
320 virtual error_code getRelocationTypeName(DataRefImpl Rel,
321 SmallVectorImpl<char> &Result) const;
322 virtual error_code getRelocationValueString(DataRefImpl Rel,
323 SmallVectorImpl<char> &Result) const;
324 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
325 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
326 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
328 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
329 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
330 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
331 virtual section_iterator begin_sections() const;
332 void moveToNextSection(DataRefImpl &DRI) const;
335 template<bool is64Bits>
336 const typename MachOObjectFile<is64Bits>::Section *
337 MachOObjectFile<is64Bits>::getSection(DataRefImpl DRI) const {
338 const SectionBase *Addr = getSectionBase(DRI);
339 return reinterpret_cast<const Section*>(Addr);
342 template<bool is64Bits>
343 const typename MachOObjectFile<is64Bits>::SymbolTableEntry *
344 MachOObjectFile<is64Bits>::getSymbolTableEntry(DataRefImpl DRI) const {
345 const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
346 return reinterpret_cast<const SymbolTableEntry*>(Base);
349 template<bool is64Bits>
350 const typename MachOObjectFile<is64Bits>::RelocationEntry *
351 MachOObjectFile<is64Bits>::getRelocation(DataRefImpl Rel) const {
352 const Section *Sect = getSection(Sections[Rel.d.b]);
353 uint32_t RelOffset = Sect->RelocationTableOffset;
354 uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
355 StringRef Data = getData(Offset, sizeof(RelocationEntry));
356 return reinterpret_cast<const RelocationEntry*>(Data.data());
359 template<bool is64Bits>
361 MachOObjectFile<is64Bits>::getSectionAddress(DataRefImpl Sec,
362 uint64_t &Res) const {
363 const Section *Sect = getSection(Sec);
365 return object_error::success;
368 template<bool is64Bits>
370 MachOObjectFile<is64Bits>::getSectionSize(DataRefImpl Sec,
371 uint64_t &Res) const {
372 const Section *Sect = getSection(Sec);
374 return object_error::success;
377 template<bool is64Bits>
379 MachOObjectFile<is64Bits>::getSectionContents(DataRefImpl Sec,
380 StringRef &Res) const {
381 const Section *Sect = getSection(Sec);
382 Res = getData(Sect->Offset, Sect->Size);
383 return object_error::success;
386 template<bool is64Bits>
388 MachOObjectFile<is64Bits>::getSectionAlignment(DataRefImpl Sec,
389 uint64_t &Res) const {
390 const Section *Sect = getSection(Sec);
391 Res = uint64_t(1) << Sect->Align;
392 return object_error::success;
395 template<bool is64Bits>
397 MachOObjectFile<is64Bits>::isSectionText(DataRefImpl Sec, bool &Res) const {
398 const Section *Sect = getSection(Sec);
399 Res = Sect->Flags & macho::SF_PureInstructions;
400 return object_error::success;
403 template<bool is64Bits>
405 MachOObjectFile<is64Bits>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
406 const Section *Sect = getSection(Sec);
407 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
408 Res = SectionType == MachO::SectionTypeZeroFill ||
409 SectionType == MachO::SectionTypeZeroFillLarge;
410 return object_error::success;
413 template<bool is64Bits>
415 MachOObjectFile<is64Bits>::getSectionRelEnd(DataRefImpl Sec) const {
416 const Section *Sect = getSection(Sec);
417 uint32_t LastReloc = Sect->NumRelocationTableEntries;
420 Ret.d.b = getSectionIndex(Sec);
421 return relocation_iterator(RelocationRef(Ret, this));
424 template<bool is64Bits>
426 MachOObjectFile<is64Bits>::getRelocationAddress(DataRefImpl Rel,
427 uint64_t &Res) const {
428 const Section *Sect = getSection(Sections[Rel.d.b]);
429 uint64_t SectAddress = Sect->Address;
430 const RelocationEntry *RE = getRelocation(Rel);
431 unsigned Arch = getArch();
432 bool isScattered = (Arch != Triple::x86_64) &&
433 (RE->Word0 & macho::RF_Scattered);
437 RelAddr = RE->Word0 & 0xFFFFFF;
441 Res = SectAddress + RelAddr;
442 return object_error::success;
445 template<bool is64Bits>
447 MachOObjectFile<is64Bits>::getRelocationOffset(DataRefImpl Rel,
448 uint64_t &Res) const {
449 const RelocationEntry *RE = getRelocation(Rel);
451 unsigned Arch = getArch();
452 bool isScattered = (Arch != Triple::x86_64) &&
453 (RE->Word0 & macho::RF_Scattered);
455 Res = RE->Word0 & 0xFFFFFF;
458 return object_error::success;
461 template<bool is64Bits>
463 MachOObjectFile<is64Bits>::getRelocationSymbol(DataRefImpl Rel,
464 SymbolRef &Res) const {
465 const RelocationEntry *RE = getRelocation(Rel);
466 uint32_t SymbolIdx = RE->Word1 & 0xffffff;
467 bool isExtern = (RE->Word1 >> 27) & 1;
470 moveToNextSymbol(Sym);
472 for (unsigned i = 0; i < SymbolIdx; i++) {
474 moveToNextSymbol(Sym);
475 assert(Sym.d.a < getHeader()->NumLoadCommands &&
476 "Relocation symbol index out of range!");
479 Res = SymbolRef(Sym, this);
480 return object_error::success;
483 template<bool is64Bits>
485 MachOObjectFile<is64Bits>::getRelocationAdditionalInfo(DataRefImpl Rel,
486 int64_t &Res) const {
487 const RelocationEntry *RE = getRelocation(Rel);
488 bool isExtern = (RE->Word1 >> 27) & 1;
491 const uint8_t* sectAddress = base();
492 const Section *Sect = getSection(Sections[Rel.d.b]);
493 sectAddress += Sect->Offset;
494 Res = reinterpret_cast<uintptr_t>(sectAddress);
496 return object_error::success;
499 template<bool is64Bits>
500 error_code MachOObjectFile<is64Bits>::getRelocationType(DataRefImpl Rel,
501 uint64_t &Res) const {
502 const RelocationEntry *RE = getRelocation(Rel);
506 return object_error::success;
509 template<bool is64Bits>
511 MachOObjectFile<is64Bits>::getRelocationTypeName(DataRefImpl Rel,
512 SmallVectorImpl<char> &Result) const {
513 // TODO: Support scattered relocations.
515 const RelocationEntry *RE = getRelocation(Rel);
517 unsigned Arch = getArch();
518 bool isScattered = (Arch != Triple::x86_64) &&
519 (RE->Word0 & macho::RF_Scattered);
523 r_type = (RE->Word0 >> 24) & 0xF;
525 r_type = (RE->Word1 >> 28) & 0xF;
529 static const char *const Table[] = {
530 "GENERIC_RELOC_VANILLA",
531 "GENERIC_RELOC_PAIR",
532 "GENERIC_RELOC_SECTDIFF",
533 "GENERIC_RELOC_PB_LA_PTR",
534 "GENERIC_RELOC_LOCAL_SECTDIFF",
535 "GENERIC_RELOC_TLV" };
543 case Triple::x86_64: {
544 static const char *const Table[] = {
545 "X86_64_RELOC_UNSIGNED",
546 "X86_64_RELOC_SIGNED",
547 "X86_64_RELOC_BRANCH",
548 "X86_64_RELOC_GOT_LOAD",
550 "X86_64_RELOC_SUBTRACTOR",
551 "X86_64_RELOC_SIGNED_1",
552 "X86_64_RELOC_SIGNED_2",
553 "X86_64_RELOC_SIGNED_4",
554 "X86_64_RELOC_TLV" };
563 static const char *const Table[] = {
566 "ARM_RELOC_SECTDIFF",
567 "ARM_RELOC_LOCAL_SECTDIFF",
568 "ARM_RELOC_PB_LA_PTR",
570 "ARM_THUMB_RELOC_BR22",
571 "ARM_THUMB_32BIT_BRANCH",
573 "ARM_RELOC_HALF_SECTDIFF" };
582 static const char *const Table[] = {
591 "PPC_RELOC_SECTDIFF",
592 "PPC_RELOC_PB_LA_PTR",
593 "PPC_RELOC_HI16_SECTDIFF",
594 "PPC_RELOC_LO16_SECTDIFF",
595 "PPC_RELOC_HA16_SECTDIFF",
597 "PPC_RELOC_LO14_SECTDIFF",
598 "PPC_RELOC_LOCAL_SECTDIFF" };
603 case Triple::UnknownArch:
607 Result.append(res.begin(), res.end());
608 return object_error::success;
611 template<bool is64Bits>
613 MachOObjectFile<is64Bits>::getRelocationValueString(DataRefImpl Rel,
614 SmallVectorImpl<char> &Result) const {
615 const RelocationEntry *RE = getRelocation(Rel);
617 unsigned Arch = getArch();
618 bool isScattered = (Arch != Triple::x86_64) &&
619 (RE->Word0 & macho::RF_Scattered);
622 raw_string_ostream fmt(fmtbuf);
626 Type = (RE->Word0 >> 24) & 0xF;
628 Type = (RE->Word1 >> 28) & 0xF;
632 isPCRel = ((RE->Word0 >> 30) & 1);
634 isPCRel = ((RE->Word1 >> 24) & 1);
636 // Determine any addends that should be displayed with the relocation.
637 // These require decoding the relocation type, which is triple-specific.
639 // X86_64 has entirely custom relocation types.
640 if (Arch == Triple::x86_64) {
641 bool isPCRel = ((RE->Word1 >> 24) & 1);
644 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
645 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
646 printRelocationTargetName(RE, fmt);
648 if (isPCRel) fmt << "PCREL";
651 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
652 DataRefImpl RelNext = Rel;
654 const RelocationEntry *RENext = getRelocation(RelNext);
656 // X86_64_SUBTRACTOR must be followed by a relocation of type
657 // X86_64_RELOC_UNSIGNED.
658 // NOTE: Scattered relocations don't exist on x86_64.
659 unsigned RType = (RENext->Word1 >> 28) & 0xF;
661 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
662 "X86_64_RELOC_SUBTRACTOR.");
664 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
665 // X86_64_SUBTRACTOR contains to the subtrahend.
666 printRelocationTargetName(RENext, fmt);
668 printRelocationTargetName(RE, fmt);
671 case macho::RIT_X86_64_TLV:
672 printRelocationTargetName(RE, fmt);
674 if (isPCRel) fmt << "P";
676 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
677 printRelocationTargetName(RE, fmt);
680 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
681 printRelocationTargetName(RE, fmt);
684 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
685 printRelocationTargetName(RE, fmt);
689 printRelocationTargetName(RE, fmt);
692 // X86 and ARM share some relocation types in common.
693 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
694 // Generic relocation types...
696 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
697 return object_error::success;
698 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
699 DataRefImpl RelNext = Rel;
701 const RelocationEntry *RENext = getRelocation(RelNext);
703 // X86 sect diff's must be followed by a relocation of type
704 // GENERIC_RELOC_PAIR.
705 bool isNextScattered = (Arch != Triple::x86_64) &&
706 (RENext->Word0 & macho::RF_Scattered);
709 RType = (RENext->Word0 >> 24) & 0xF;
711 RType = (RENext->Word1 >> 28) & 0xF;
713 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
714 "GENERIC_RELOC_SECTDIFF.");
716 printRelocationTargetName(RE, fmt);
718 printRelocationTargetName(RENext, fmt);
723 if (Arch == Triple::x86) {
724 // All X86 relocations that need special printing were already
725 // handled in the generic code.
727 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
728 DataRefImpl RelNext = Rel;
730 const RelocationEntry *RENext = getRelocation(RelNext);
732 // X86 sect diff's must be followed by a relocation of type
733 // GENERIC_RELOC_PAIR.
734 bool isNextScattered = (Arch != Triple::x86_64) &&
735 (RENext->Word0 & macho::RF_Scattered);
738 RType = (RENext->Word0 >> 24) & 0xF;
740 RType = (RENext->Word1 >> 28) & 0xF;
742 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
743 "GENERIC_RELOC_LOCAL_SECTDIFF.");
745 printRelocationTargetName(RE, fmt);
747 printRelocationTargetName(RENext, fmt);
750 case macho::RIT_Generic_TLV: {
751 printRelocationTargetName(RE, fmt);
753 if (isPCRel) fmt << "P";
757 printRelocationTargetName(RE, fmt);
759 } else { // ARM-specific relocations
761 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
762 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
763 // Half relocations steal a bit from the length field to encode
764 // whether this is an upper16 or a lower16 relocation.
767 isUpper = (RE->Word0 >> 28) & 1;
769 isUpper = (RE->Word1 >> 25) & 1;
775 printRelocationTargetName(RE, fmt);
777 DataRefImpl RelNext = Rel;
779 const RelocationEntry *RENext = getRelocation(RelNext);
781 // ARM half relocs must be followed by a relocation of type
783 bool isNextScattered = (Arch != Triple::x86_64) &&
784 (RENext->Word0 & macho::RF_Scattered);
787 RType = (RENext->Word0 >> 24) & 0xF;
789 RType = (RENext->Word1 >> 28) & 0xF;
792 report_fatal_error("Expected ARM_RELOC_PAIR after "
793 "GENERIC_RELOC_HALF");
795 // NOTE: The half of the target virtual address is stashed in the
796 // address field of the secondary relocation, but we can't reverse
797 // engineer the constant offset from it without decoding the movw/movt
798 // instruction to find the other half in its immediate field.
800 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
801 // symbol/section pointer of the follow-on relocation.
802 if (Type == macho::RIT_ARM_HalfDifference) {
804 printRelocationTargetName(RENext, fmt);
811 printRelocationTargetName(RE, fmt);
816 printRelocationTargetName(RE, fmt);
819 Result.append(fmtbuf.begin(), fmtbuf.end());
820 return object_error::success;
823 template<bool is64Bits>
825 MachOObjectFile<is64Bits>::getRelocationHidden(DataRefImpl Rel,
826 bool &Result) const {
827 const RelocationEntry *RE = getRelocation(Rel);
829 unsigned Arch = getArch();
830 bool isScattered = (Arch != Triple::x86_64) &&
831 (RE->Word0 & macho::RF_Scattered);
834 Type = (RE->Word0 >> 24) & 0xF;
836 Type = (RE->Word1 >> 28) & 0xF;
840 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
842 if (Arch == Triple::x86 || Arch == Triple::arm) {
843 if (Type == macho::RIT_Pair) Result = true;
844 } else if (Arch == Triple::x86_64) {
845 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
846 // an X864_64_RELOC_SUBTRACTOR.
847 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
848 DataRefImpl RelPrev = Rel;
850 const RelocationEntry *REPrev = getRelocation(RelPrev);
852 unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
854 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
858 return object_error::success;
861 template<bool is64Bits>
863 MachOObjectFile<is64Bits>::getSymbolFileOffset(DataRefImpl Symb,
864 uint64_t &Res) const {
865 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
867 if (Entry->SectionIndex) {
868 const Section *Sec = getSection(Sections[Entry->SectionIndex-1]);
869 Res += Sec->Offset - Sec->Address;
872 return object_error::success;
875 template<bool is64Bits>
877 MachOObjectFile<is64Bits>::sectionContainsSymbol(DataRefImpl Sec,
879 bool &Result) const {
881 getSymbolType(Symb, ST);
882 if (ST == SymbolRef::ST_Unknown) {
884 return object_error::success;
887 uint64_t SectBegin, SectEnd;
888 getSectionAddress(Sec, SectBegin);
889 getSectionSize(Sec, SectEnd);
890 SectEnd += SectBegin;
892 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
893 uint64_t SymAddr= Entry->Value;
894 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
896 return object_error::success;
899 template<bool is64Bits>
900 error_code MachOObjectFile<is64Bits>::getSymbolAddress(DataRefImpl Symb,
901 uint64_t &Res) const {
902 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
904 return object_error::success;
907 template<bool is64Bits>
908 error_code MachOObjectFile<is64Bits>::getSymbolSize(DataRefImpl DRI,
909 uint64_t &Result) const {
910 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
911 uint64_t BeginOffset;
912 uint64_t EndOffset = 0;
913 uint8_t SectionIndex;
915 const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
916 BeginOffset = Entry->Value;
917 SectionIndex = Entry->SectionIndex;
919 uint32_t flags = SymbolRef::SF_None;
920 getSymbolFlags(DRI, flags);
921 if (flags & SymbolRef::SF_Common)
922 Result = Entry->Value;
924 Result = UnknownAddressOrSize;
925 return object_error::success;
927 // Unfortunately symbols are unsorted so we need to touch all
928 // symbols from load command
930 uint32_t Command = DRI.d.a;
931 while (Command == DRI.d.a) {
932 moveToNextSymbol(DRI);
933 if (DRI.d.a < LoadCommandCount) {
934 Entry = getSymbolTableEntry(DRI);
935 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
936 if (!EndOffset || Entry->Value < EndOffset)
937 EndOffset = Entry->Value;
943 getSectionSize(Sections[SectionIndex-1], Size);
944 getSectionAddress(Sections[SectionIndex-1], EndOffset);
947 Result = EndOffset - BeginOffset;
948 return object_error::success;
951 template<bool is64Bits>
952 error_code MachOObjectFile<is64Bits>::getSectionNext(DataRefImpl Sec,
953 SectionRef &Res) const {
955 moveToNextSection(Sec);
956 Res = SectionRef(Sec, this);
957 return object_error::success;
960 template<bool is64Bits>
961 section_iterator MachOObjectFile<is64Bits>::begin_sections() const {
963 moveToNextSection(DRI);
964 return section_iterator(SectionRef(DRI, this));
967 template<bool is64Bits>
968 void MachOObjectFile<is64Bits>::moveToNextSection(DataRefImpl &DRI) const {
969 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
970 while (DRI.d.a < LoadCommandCount) {
971 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
972 if (Command->Type == SegmentLoadType) {
973 const SegmentLoadCommand *SegmentLoadCmd =
974 reinterpret_cast<const SegmentLoadCommand*>(Command);
975 if (DRI.d.b < SegmentLoadCmd->NumSections)