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/MachOFormat.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Format.h"
26 #include "llvm/Support/MachO.h"
27 #include "llvm/Support/raw_ostream.h"
32 using support::endianness;
34 template<endianness E, bool B>
36 static const endianness TargetEndianness = E;
37 static const bool Is64Bits = B;
40 template<endianness TargetEndianness>
41 struct MachOInt24Impl;
44 struct MachOInt24Impl<support::little> {
46 operator uint32_t() const {
47 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
52 struct MachOInt24Impl<support::big> {
54 operator uint32_t() const {
55 return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2];
59 template<endianness TargetEndianness>
60 struct MachODataTypeTypedefHelperCommon {
61 typedef support::detail::packed_endian_specific_integral
62 <uint16_t, TargetEndianness, support::unaligned> MachOInt16;
63 typedef support::detail::packed_endian_specific_integral
64 <uint32_t, TargetEndianness, support::unaligned> MachOInt32;
65 typedef support::detail::packed_endian_specific_integral
66 <uint64_t, TargetEndianness, support::unaligned> MachOInt64;
67 typedef MachOInt24Impl<TargetEndianness> MachOInt24;
70 #define LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \
71 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
72 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
73 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \
74 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24;
76 #define LLVM_MACHOB_IMPORT_TYPES(E) \
77 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
78 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
79 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \
80 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24;
82 template<class MachOT>
83 struct MachODataTypeTypedefHelper;
85 template<endianness TargetEndianness>
86 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
87 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
88 typedef typename Base::MachOInt32 MachOIntPtr;
91 template<endianness TargetEndianness>
92 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
93 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
94 typedef typename Base::MachOInt64 MachOIntPtr;
97 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \
98 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \
100 MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
102 namespace MachOFormat {
105 char SegmentName[16];
108 template<class MachOT>
111 template<endianness TargetEndianness>
112 struct Section<MachOType<TargetEndianness, false> > {
113 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
115 char SegmentName[16];
120 MachOInt32 RelocationTableOffset;
121 MachOInt32 NumRelocationTableEntries;
123 MachOInt32 Reserved1;
124 MachOInt32 Reserved2;
127 template<endianness TargetEndianness>
128 struct Section<MachOType<TargetEndianness, true> > {
129 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
131 char SegmentName[16];
136 MachOInt32 RelocationTableOffset;
137 MachOInt32 NumRelocationTableEntries;
139 MachOInt32 Reserved1;
140 MachOInt32 Reserved2;
141 MachOInt32 Reserved3;
146 operator uint32_t() const {
147 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
151 template<endianness TargetEndianness>
152 struct RelocationEntry;
155 struct RelocationEntry<support::little> {
156 LLVM_MACHOB_IMPORT_TYPES(support::little)
158 MachOInt24 SymbolNum;
161 unsigned getPCRel() const {
164 unsigned getLength() const {
165 return (Bits >> 1) & 0x3;
167 unsigned getExternal() const {
168 return (Bits >> 3) & 0x1;
170 unsigned getType() const {
176 struct RelocationEntry<support::big> {
177 LLVM_MACHOB_IMPORT_TYPES(support::big)
179 MachOInt24 SymbolNum;
182 unsigned getType() const {
185 unsigned getExternal() const {
186 return (Bits >> 4) & 0x1;
188 unsigned getLength() const {
189 return (Bits >> 5) & 0x3;
191 unsigned getPCRel() const {
196 template<endianness TargetEndianness>
197 struct ScatteredRelocationEntry;
200 struct ScatteredRelocationEntry<support::little> {
201 LLVM_MACHOB_IMPORT_TYPES(support::little)
206 unsigned getType() const {
209 unsigned getLength() const {
210 return (Bits >> 4) & 0x3;
212 unsigned getPCRel() const {
213 return (Bits >> 6) & 0x1;
215 unsigned getScattered() const {
221 struct ScatteredRelocationEntry<support::big> {
222 LLVM_MACHOB_IMPORT_TYPES(support::big)
224 unsigned getType() const {
227 unsigned getLength() const {
228 return (Bits >> 4) & 0x3;
230 unsigned getPCRel() const {
231 return (Bits >> 6) & 0x1;
233 unsigned getScattered() const {
240 template<endianness TargetEndianness>
241 struct SymbolTableEntryBase {
242 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
243 MachOInt32 StringIndex;
245 uint8_t SectionIndex;
249 template<class MachOT>
250 struct SymbolTableEntry;
252 template<endianness TargetEndianness, bool Is64Bits>
253 struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
254 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
255 MachOInt32 StringIndex;
257 uint8_t SectionIndex;
262 template<endianness TargetEndianness>
264 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
269 template<endianness TargetEndianness>
270 struct SymtabLoadCommand {
271 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
274 MachOInt32 SymbolTableOffset;
275 MachOInt32 NumSymbolTableEntries;
276 MachOInt32 StringTableOffset;
277 MachOInt32 StringTableSize;
280 template<class MachOT>
281 struct SegmentLoadCommand;
283 template<endianness TargetEndianness, bool Is64Bits>
284 struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
285 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
289 MachOIntPtr VMAddress;
291 MachOIntPtr FileOffset;
292 MachOIntPtr FileSize;
293 MachOInt32 MaxVMProtection;
294 MachOInt32 InitialVMProtection;
295 MachOInt32 NumSections;
299 template<endianness TargetEndianness>
300 struct LinkeditDataLoadCommand {
301 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
304 MachOInt32 DataOffset;
308 template<endianness TargetEndianness>
310 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
313 MachOInt32 CPUSubtype;
315 MachOInt32 NumLoadCommands;
316 MachOInt32 SizeOfLoadCommands;
321 class MachOObjectFileBase : public ObjectFile {
323 typedef MachOFormat::SectionBase SectionBase;
325 MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
328 virtual symbol_iterator begin_dynamic_symbols() const;
329 virtual symbol_iterator end_dynamic_symbols() const;
330 virtual library_iterator begin_libraries_needed() const;
331 virtual library_iterator end_libraries_needed() const;
333 virtual uint8_t getBytesInAddress() const;
334 virtual StringRef getLoadName() const;
336 bool is64Bit() const;
337 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
338 unsigned getHeaderSize() const;
339 StringRef getData(size_t Offset, size_t Size) const;
341 static inline bool classof(const Binary *v) {
346 StringRef parseSegmentOrSectionName(const char *P) const;
348 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
349 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
350 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
351 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
353 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
354 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
355 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
357 virtual error_code getRelocationNext(DataRefImpl Rel,
358 RelocationRef &Res) const;
360 virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
361 virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
362 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
365 std::size_t getSectionIndex(DataRefImpl Sec) const;
367 typedef SmallVector<DataRefImpl, 1> SectionList;
368 SectionList Sections;
371 template<endianness TargetEndianness>
372 class MachOObjectFileMiddle : public MachOObjectFileBase {
375 typedef MachOFormat::SymbolTableEntryBase<TargetEndianness>
376 SymbolTableEntryBase;
377 typedef MachOFormat::LinkeditDataLoadCommand<TargetEndianness>
378 LinkeditDataLoadCommand;
379 typedef MachOFormat::Header<TargetEndianness> Header;
380 typedef MachOFormat::SymtabLoadCommand<TargetEndianness> SymtabLoadCommand;
381 typedef MachOFormat::RelocationEntry<TargetEndianness> RelocationEntry;
382 typedef MachOFormat::ScatteredRelocationEntry<TargetEndianness>
383 ScatteredRelocationEntry;
384 typedef MachOFormat::LoadCommand<TargetEndianness> LoadCommand;
386 MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
388 const Header *getHeader() const;
389 const LoadCommand *getLoadCommandInfo(unsigned Index) const;
390 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
391 bool isRelocationScattered(const RelocationEntry *RE) const;
392 bool isRelocationPCRel(const RelocationEntry *RE) const;
393 unsigned getRelocationLength(const RelocationEntry *RE) const;
394 unsigned getRelocationTypeImpl(const RelocationEntry *RE) const;
396 void moveToNextSymbol(DataRefImpl &DRI) const;
397 void printRelocationTargetName(const RelocationEntry *RE,
398 raw_string_ostream &fmt) const;
399 const SectionBase *getSectionBase(DataRefImpl DRI) const;
400 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
401 unsigned getCPUType() const;
403 // In a MachO file, sections have a segment name. This is used in the .o
404 // files. They have a single segment, but this field specifies which segment
405 // a section should be put in in the final object.
406 StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
408 // Names are stored as 16 bytes. These returns the raw 16 bytes without
409 // interpreting them as a C string.
410 ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
411 ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
413 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
414 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
415 virtual error_code getSymbolType(DataRefImpl Symb,
416 SymbolRef::Type &Res) const;
417 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
418 virtual error_code getSymbolSection(DataRefImpl Symb,
419 section_iterator &Res) const;
420 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
421 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
422 virtual symbol_iterator begin_symbols() const;
423 virtual unsigned getArch() const;
424 virtual StringRef getFileFormatName() const;
425 virtual symbol_iterator end_symbols() const;
426 virtual section_iterator end_sections() const;
428 static bool classof(const Binary *v);
431 // Helper to advance a section or symbol iterator multiple increments at a
434 static error_code advance(T &it, size_t Val);
437 static void advanceTo(T &it, size_t Val);
440 template<class MachOT>
441 struct MachOObjectFileHelperCommon;
443 template<endianness TargetEndianness, bool Is64Bits>
444 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
446 MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
448 typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
450 typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
453 template<class MachOT>
454 struct MachOObjectFileHelper;
456 template<endianness TargetEndianness>
457 struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > :
458 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > {
459 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
462 template<endianness TargetEndianness>
463 struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > :
464 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > {
465 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
468 template<class MachOT>
469 class MachOObjectFile : public MachOObjectFileMiddle<MachOT::TargetEndianness> {
471 static const endianness TargetEndianness = MachOT::TargetEndianness;
472 static const bool Is64Bits = MachOT::Is64Bits;
474 typedef MachOObjectFileMiddle<MachOT::TargetEndianness> Base;
475 typedef typename Base::RelocationEntry RelocationEntry;
476 typedef typename Base::SectionBase SectionBase;
477 typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase;
478 typedef typename Base::LoadCommand LoadCommand;
480 typedef MachOObjectFileHelper<MachOT> Helper;
481 static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
482 typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
483 typedef typename Helper::SymbolTableEntry SymbolTableEntry;
484 typedef typename Helper::Section Section;
486 MachOObjectFile(MemoryBuffer *Object, error_code &ec);
487 static bool classof(const Binary *v);
489 const Section *getSection(DataRefImpl DRI) const;
490 const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
491 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
493 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
494 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
495 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
496 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
497 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
498 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
499 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
500 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
501 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
502 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
503 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
504 virtual error_code getRelocationTypeName(DataRefImpl Rel,
505 SmallVectorImpl<char> &Result) const;
506 virtual error_code getRelocationValueString(DataRefImpl Rel,
507 SmallVectorImpl<char> &Result) const;
508 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
509 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
510 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
512 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
513 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
514 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
515 virtual section_iterator begin_sections() const;
516 void moveToNextSection(DataRefImpl &DRI) const;
519 typedef MachOObjectFileMiddle<support::little> MachOObjectFileLE;
520 typedef MachOObjectFileMiddle<support::big> MachOObjectFileBE;
522 typedef MachOObjectFile<MachOType<support::little, false> >
524 typedef MachOObjectFile<MachOType<support::big, false> >
526 typedef MachOObjectFile<MachOType<support::little, true> >
528 typedef MachOObjectFile<MachOType<support::big, true> >
531 template<endianness TargetEndianness>
532 MachOObjectFileMiddle<TargetEndianness>::MachOObjectFileMiddle(MemoryBuffer *O,
535 MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) {
538 template<endianness E>
539 const typename MachOObjectFileMiddle<E>::SymbolTableEntryBase *
540 MachOObjectFileMiddle<E>::getSymbolTableEntryBase(DataRefImpl DRI) const {
541 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
542 const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
544 unsigned Index = DRI.d.b;
546 unsigned SymbolTableEntrySize = is64Bit() ?
547 sizeof(MachOObjectFileLE64::SymbolTableEntry) :
548 sizeof(MachOObjectFileLE32::SymbolTableEntry);
550 uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize;
551 StringRef Data = getData(Offset, SymbolTableEntrySize);
552 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
555 template<endianness E>
556 const typename MachOObjectFileMiddle<E>::Header *
557 MachOObjectFileMiddle<E>::getHeader() const {
558 StringRef Data = getData(0, sizeof(Header));
559 return reinterpret_cast<const Header*>(Data.data());
562 template<endianness E>
563 const typename MachOObjectFileMiddle<E>::LoadCommand *
564 MachOObjectFileMiddle<E>::getLoadCommandInfo(unsigned Index) const {
565 assert(Index < getHeader()->NumLoadCommands);
567 uint64_t NewOffset = getHeaderSize();
568 const LoadCommand *Load;
572 StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand));
573 Load = reinterpret_cast<const LoadCommand*>(Data.data());
574 NewOffset = Offset + Load->Size;
576 } while (I != Index + 1);
578 return reinterpret_cast<const LoadCommand*>(Load);
581 template<endianness E>
582 const typename MachOObjectFileMiddle<E>::RelocationEntry *
583 MachOObjectFileMiddle<E>::getRelocation(DataRefImpl Rel) const {
584 if (const MachOObjectFile<MachOType<E, true> > *O =
585 dyn_cast<MachOObjectFile<MachOType<E, true> > >(this))
586 return O->getRelocation(Rel);
588 const MachOObjectFile<MachOType<E, false> > *O =
589 cast<MachOObjectFile<MachOType<E, false> > >(this);
590 return O->getRelocation(Rel);
593 template<endianness E>
595 MachOObjectFileMiddle<E>::isRelocationScattered(const RelocationEntry *RE)
597 if (this->getCPUType() == llvm::MachO::CPUTypeX86_64)
599 return RE->Address & macho::RF_Scattered;
602 template<endianness E>
604 MachOObjectFileMiddle<E>::isRelocationPCRel(const RelocationEntry *RE) const {
605 typedef MachOObjectFileMiddle<E> ObjType;
606 if (isRelocationScattered(RE)) {
607 const typename MachOObjectFileMiddle<E>::ScatteredRelocationEntry *SRE =
608 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
609 return SRE->getPCRel();
611 return RE->getPCRel();
614 template<endianness E>
616 MachOObjectFileMiddle<E>::getRelocationLength(const RelocationEntry *RE) const {
617 typedef MachOObjectFileMiddle<E> ObjType;
618 if (isRelocationScattered(RE)) {
619 const typename ObjType::ScatteredRelocationEntry *SRE =
620 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
621 return SRE->getLength();
623 return RE->getLength();
626 template<endianness E>
628 MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE)
630 typedef MachOObjectFileMiddle<E> ObjType;
631 if (isRelocationScattered(RE)) {
632 const typename ObjType::ScatteredRelocationEntry *SRE =
633 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
634 return SRE->getType();
636 return RE->getType();
639 // Helper to advance a section or symbol iterator multiple increments at a time.
640 template<endianness E>
642 error_code MachOObjectFileMiddle<E>::advance(T &it, size_t Val) {
650 template<endianness E>
652 void MachOObjectFileMiddle<E>::advanceTo(T &it, size_t Val) {
653 if (error_code ec = advance(it, Val))
654 report_fatal_error(ec.message());
657 template<endianness E>
659 MachOObjectFileMiddle<E>::printRelocationTargetName(const RelocationEntry *RE,
660 raw_string_ostream &fmt) const {
661 bool IsScattered = isRelocationScattered(RE);
663 // Target of a scattered relocation is an address. In the interest of
664 // generating pretty output, scan through the symbol table looking for a
665 // symbol that aligns with that address. If we find one, print it.
666 // Otherwise, we just print the hex address of the target.
668 uint32_t Val = RE->SymbolNum;
671 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
673 if (ec) report_fatal_error(ec.message());
678 if ((ec = SI->getAddress(Addr)))
679 report_fatal_error(ec.message());
680 if (Addr != Val) continue;
681 if ((ec = SI->getName(Name)))
682 report_fatal_error(ec.message());
687 // If we couldn't find a symbol that this relocation refers to, try
688 // to find a section beginning instead.
689 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
691 if (ec) report_fatal_error(ec.message());
696 if ((ec = SI->getAddress(Addr)))
697 report_fatal_error(ec.message());
698 if (Addr != Val) continue;
699 if ((ec = SI->getName(Name)))
700 report_fatal_error(ec.message());
705 fmt << format("0x%x", Val);
710 bool isExtern = RE->getExternal();
711 uint64_t Val = RE->Address;
714 symbol_iterator SI = begin_symbols();
718 section_iterator SI = begin_sections();
726 template<endianness E>
727 const typename MachOObjectFileMiddle<E>::SectionBase *
728 MachOObjectFileMiddle<E>::getSectionBase(DataRefImpl DRI) const {
729 uintptr_t CommandAddr =
730 reinterpret_cast<uintptr_t>(getLoadCommandInfo(DRI.d.a));
732 bool Is64 = is64Bit();
733 unsigned SegmentLoadSize =
734 Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) :
735 sizeof(MachOObjectFileLE32::SegmentLoadCommand);
736 unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) :
737 sizeof(MachOObjectFileLE32::Section);
739 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
740 return reinterpret_cast<const SectionBase*>(SectionAddr);
743 template<endianness E>
744 unsigned MachOObjectFileMiddle<E>::getCPUType() const {
745 return getHeader()->CPUType;
748 template<endianness E>
749 void MachOObjectFileMiddle<E>::moveToNextSymbol(DataRefImpl &DRI) const {
750 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
751 while (DRI.d.a < LoadCommandCount) {
752 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
753 if (L->Type == macho::LCT_Symtab) {
754 const SymtabLoadCommand *S =
755 reinterpret_cast<const SymtabLoadCommand *>(L);
756 if (DRI.d.b < S->NumSymbolTableEntries)
765 template<endianness E>
767 MachOObjectFileMiddle<E>::getSectionFinalSegmentName(DataRefImpl Sec) const {
768 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
769 return parseSegmentOrSectionName(Raw.data());
772 template<endianness E>
774 MachOObjectFileMiddle<E>::getSectionRawName(DataRefImpl Sec) const {
775 const SectionBase *Base = getSectionBase(Sec);
776 return ArrayRef<char>(Base->Name);
779 template<endianness E>
781 MachOObjectFileMiddle<E>::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
782 const SectionBase *Base = getSectionBase(Sec);
783 return ArrayRef<char>(Base->SegmentName);
786 template<endianness E>
787 error_code MachOObjectFileMiddle<E>::getSymbolFlags(DataRefImpl DRI,
788 uint32_t &Result) const {
789 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
791 uint8_t MachOType = Entry->Type;
792 uint16_t MachOFlags = Entry->Flags;
794 // TODO: Correctly set SF_ThreadLocal
795 Result = SymbolRef::SF_None;
797 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
798 Result |= SymbolRef::SF_Undefined;
800 if (MachOFlags & macho::STF_StabsEntryMask)
801 Result |= SymbolRef::SF_FormatSpecific;
803 if (MachOType & MachO::NlistMaskExternal) {
804 Result |= SymbolRef::SF_Global;
805 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
806 Result |= SymbolRef::SF_Common;
809 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
810 Result |= SymbolRef::SF_Weak;
812 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
813 Result |= SymbolRef::SF_Absolute;
815 return object_error::success;
818 template<endianness E>
819 error_code MachOObjectFileMiddle<E>::getSymbolType(DataRefImpl Symb,
820 SymbolRef::Type &Res) const {
821 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
822 uint8_t n_type = Entry->Type;
824 Res = SymbolRef::ST_Other;
826 // If this is a STAB debugging symbol, we can do nothing more.
827 if (n_type & MachO::NlistMaskStab) {
828 Res = SymbolRef::ST_Debug;
829 return object_error::success;
832 switch (n_type & MachO::NlistMaskType) {
833 case MachO::NListTypeUndefined :
834 Res = SymbolRef::ST_Unknown;
836 case MachO::NListTypeSection :
837 Res = SymbolRef::ST_Function;
840 return object_error::success;
843 template<endianness E>
844 error_code MachOObjectFileMiddle<E>::getSymbolName(DataRefImpl Symb,
845 StringRef &Res) const {
846 const LoadCommand *L = getLoadCommandInfo(Symb.d.a);
847 const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
848 StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize);
849 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
850 const char *Start = &StringTable.data()[Entry->StringIndex];
851 Res = StringRef(Start);
852 return object_error::success;
855 template<endianness E>
857 MachOObjectFileMiddle<E>::getSymbolSection(DataRefImpl Symb,
858 section_iterator &Res) const {
859 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
860 uint8_t index = Entry->SectionIndex;
863 Res = end_sections();
865 Res = section_iterator(SectionRef(Sections[index-1], this));
867 return object_error::success;
871 template<endianness E>
872 error_code MachOObjectFileMiddle<E>::getSymbolNMTypeChar(DataRefImpl Symb,
874 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
875 uint8_t Type = Entry->Type;
876 uint16_t Flags = Entry->Flags;
879 switch (Type & macho::STF_TypeMask) {
880 case macho::STT_Undefined:
883 case macho::STT_Absolute:
884 case macho::STT_Section:
892 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
893 Char = toupper(static_cast<unsigned char>(Char));
895 return object_error::success;
898 template<endianness E>
900 MachOObjectFileMiddle<E>::getSectionName(DataRefImpl Sec,
901 StringRef &Result) const {
902 ArrayRef<char> Raw = getSectionRawName(Sec);
903 Result = parseSegmentOrSectionName(Raw.data());
904 return object_error::success;
907 template<endianness E>
908 error_code MachOObjectFileMiddle<E>::getSymbolNext(DataRefImpl Symb,
909 SymbolRef &Res) const {
911 moveToNextSymbol(Symb);
912 Res = SymbolRef(Symb, this);
913 return object_error::success;
916 template<endianness E>
917 symbol_iterator MachOObjectFileMiddle<E>::begin_symbols() const {
918 // DRI.d.a = segment number; DRI.d.b = symbol index.
920 moveToNextSymbol(DRI);
921 return symbol_iterator(SymbolRef(DRI, this));
924 template<endianness E>
925 unsigned MachOObjectFileMiddle<E>::getArch() const {
926 switch (getCPUType()) {
927 case llvm::MachO::CPUTypeI386:
929 case llvm::MachO::CPUTypeX86_64:
930 return Triple::x86_64;
931 case llvm::MachO::CPUTypeARM:
933 case llvm::MachO::CPUTypePowerPC:
935 case llvm::MachO::CPUTypePowerPC64:
936 return Triple::ppc64;
938 return Triple::UnknownArch;
942 template<endianness E>
943 StringRef MachOObjectFileMiddle<E>::getFileFormatName() const {
944 unsigned CPUType = getCPUType();
947 case llvm::MachO::CPUTypeI386:
948 return "Mach-O 32-bit i386";
949 case llvm::MachO::CPUTypeARM:
951 case llvm::MachO::CPUTypePowerPC:
952 return "Mach-O 32-bit ppc";
954 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
955 "64-bit object file when we're not 64-bit?");
956 return "Mach-O 32-bit unknown";
960 // Make sure the cpu type has the correct mask.
961 assert((CPUType & llvm::MachO::CPUArchABI64)
962 == llvm::MachO::CPUArchABI64 &&
963 "32-bit object file when we're 64-bit?");
966 case llvm::MachO::CPUTypeX86_64:
967 return "Mach-O 64-bit x86-64";
968 case llvm::MachO::CPUTypePowerPC64:
969 return "Mach-O 64-bit ppc64";
971 return "Mach-O 64-bit unknown";
975 template<endianness E>
976 symbol_iterator MachOObjectFileMiddle<E>::end_symbols() const {
978 DRI.d.a = getHeader()->NumLoadCommands;
979 return symbol_iterator(SymbolRef(DRI, this));
982 template<endianness E>
983 section_iterator MachOObjectFileMiddle<E>::end_sections() const {
985 DRI.d.a = getHeader()->NumLoadCommands;
986 return section_iterator(SectionRef(DRI, this));
989 template<endianness E>
990 bool MachOObjectFileMiddle<E>::classof(const Binary *v) {
991 return isa<MachOObjectFile<MachOType<E, false> > >(v) ||
992 isa<MachOObjectFile<MachOType<E, true> > >(v);
995 template<class MachOT>
996 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
998 MachOObjectFileMiddle<TargetEndianness>(Object, Is64Bits, ec) {
1000 moveToNextSection(DRI);
1001 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1002 while (DRI.d.a < LoadCommandCount) {
1003 this->Sections.push_back(DRI);
1005 moveToNextSection(DRI);
1009 template<class MachOT>
1010 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
1011 return v->getType() ==
1012 Base::getMachOType(TargetEndianness == support::little, Is64Bits);
1015 template<class MachOT>
1016 const typename MachOObjectFile<MachOT>::Section *
1017 MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const {
1018 const SectionBase *Addr = this->getSectionBase(DRI);
1019 return reinterpret_cast<const Section*>(Addr);
1022 template<class MachOT>
1023 const typename MachOObjectFile<MachOT>::SymbolTableEntry *
1024 MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const {
1025 const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI);
1026 return reinterpret_cast<const SymbolTableEntry*>(Base);
1029 template<class MachOT>
1030 const typename MachOObjectFile<MachOT>::RelocationEntry *
1031 MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const {
1032 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1033 uint32_t RelOffset = Sect->RelocationTableOffset;
1034 uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
1035 StringRef Data = this->getData(Offset, sizeof(RelocationEntry));
1036 return reinterpret_cast<const RelocationEntry*>(Data.data());
1039 template<class MachOT>
1041 MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec,
1042 uint64_t &Res) const {
1043 const Section *Sect = getSection(Sec);
1044 Res = Sect->Address;
1045 return object_error::success;
1048 template<class MachOT>
1050 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
1051 uint64_t &Res) const {
1052 const Section *Sect = getSection(Sec);
1054 return object_error::success;
1057 template<class MachOT>
1059 MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec,
1060 StringRef &Res) const {
1061 const Section *Sect = getSection(Sec);
1062 Res = this->getData(Sect->Offset, Sect->Size);
1063 return object_error::success;
1066 template<class MachOT>
1068 MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec,
1069 uint64_t &Res) const {
1070 const Section *Sect = getSection(Sec);
1071 Res = uint64_t(1) << Sect->Align;
1072 return object_error::success;
1075 template<class MachOT>
1077 MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const {
1078 const Section *Sect = getSection(Sec);
1079 Res = Sect->Flags & macho::SF_PureInstructions;
1080 return object_error::success;
1083 template<class MachOT>
1085 MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
1086 const Section *Sect = getSection(Sec);
1087 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
1088 Res = SectionType == MachO::SectionTypeZeroFill ||
1089 SectionType == MachO::SectionTypeZeroFillLarge;
1090 return object_error::success;
1093 template<class MachOT>
1095 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
1096 const Section *Sect = getSection(Sec);
1097 uint32_t LastReloc = Sect->NumRelocationTableEntries;
1099 Ret.d.a = LastReloc;
1100 Ret.d.b = this->getSectionIndex(Sec);
1101 return relocation_iterator(RelocationRef(Ret, this));
1104 template<class MachOT>
1106 MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
1107 uint64_t &Res) const {
1108 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1109 uint64_t SectAddress = Sect->Address;
1110 const RelocationEntry *RE = getRelocation(Rel);
1113 if (this->isRelocationScattered(RE))
1114 RelAddr = RE->Address & 0xFFFFFF;
1116 RelAddr = RE->Address;
1118 Res = SectAddress + RelAddr;
1119 return object_error::success;
1122 template<class MachOT>
1124 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
1125 uint64_t &Res) const {
1126 const RelocationEntry *RE = getRelocation(Rel);
1127 if (this->isRelocationScattered(RE))
1128 Res = RE->Address & 0xFFFFFF;
1131 return object_error::success;
1134 template<class MachOT>
1136 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
1137 SymbolRef &Res) const {
1138 const RelocationEntry *RE = getRelocation(Rel);
1139 uint32_t SymbolIdx = RE->SymbolNum;
1140 bool isExtern = RE->getExternal();
1143 this->moveToNextSymbol(Sym);
1145 for (unsigned i = 0; i < SymbolIdx; i++) {
1147 this->moveToNextSymbol(Sym);
1148 assert(Sym.d.a < this->getHeader()->NumLoadCommands &&
1149 "Relocation symbol index out of range!");
1152 Res = SymbolRef(Sym, this);
1153 return object_error::success;
1156 template<class MachOT>
1157 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
1158 uint64_t &Res) const {
1159 const RelocationEntry *RE = getRelocation(Rel);
1160 Res = this->getRelocationTypeImpl(RE);
1161 return object_error::success;
1164 template<class MachOT>
1166 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
1167 SmallVectorImpl<char> &Result) const {
1168 // TODO: Support scattered relocations.
1170 const RelocationEntry *RE = getRelocation(Rel);
1172 unsigned Arch = this->getArch();
1174 unsigned r_type = this->getRelocationTypeImpl(RE);
1178 static const char *const Table[] = {
1179 "GENERIC_RELOC_VANILLA",
1180 "GENERIC_RELOC_PAIR",
1181 "GENERIC_RELOC_SECTDIFF",
1182 "GENERIC_RELOC_PB_LA_PTR",
1183 "GENERIC_RELOC_LOCAL_SECTDIFF",
1184 "GENERIC_RELOC_TLV" };
1189 res = Table[r_type];
1192 case Triple::x86_64: {
1193 static const char *const Table[] = {
1194 "X86_64_RELOC_UNSIGNED",
1195 "X86_64_RELOC_SIGNED",
1196 "X86_64_RELOC_BRANCH",
1197 "X86_64_RELOC_GOT_LOAD",
1199 "X86_64_RELOC_SUBTRACTOR",
1200 "X86_64_RELOC_SIGNED_1",
1201 "X86_64_RELOC_SIGNED_2",
1202 "X86_64_RELOC_SIGNED_4",
1203 "X86_64_RELOC_TLV" };
1208 res = Table[r_type];
1212 static const char *const Table[] = {
1213 "ARM_RELOC_VANILLA",
1215 "ARM_RELOC_SECTDIFF",
1216 "ARM_RELOC_LOCAL_SECTDIFF",
1217 "ARM_RELOC_PB_LA_PTR",
1219 "ARM_THUMB_RELOC_BR22",
1220 "ARM_THUMB_32BIT_BRANCH",
1222 "ARM_RELOC_HALF_SECTDIFF" };
1227 res = Table[r_type];
1231 static const char *const Table[] = {
1232 "PPC_RELOC_VANILLA",
1240 "PPC_RELOC_SECTDIFF",
1241 "PPC_RELOC_PB_LA_PTR",
1242 "PPC_RELOC_HI16_SECTDIFF",
1243 "PPC_RELOC_LO16_SECTDIFF",
1244 "PPC_RELOC_HA16_SECTDIFF",
1246 "PPC_RELOC_LO14_SECTDIFF",
1247 "PPC_RELOC_LOCAL_SECTDIFF" };
1249 res = Table[r_type];
1252 case Triple::UnknownArch:
1256 Result.append(res.begin(), res.end());
1257 return object_error::success;
1260 template<class MachOT>
1262 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
1263 SmallVectorImpl<char> &Result) const {
1264 const RelocationEntry *RE = getRelocation(Rel);
1266 unsigned Arch = this->getArch();
1267 bool IsScattered = this->isRelocationScattered(RE);
1270 raw_string_ostream fmt(fmtbuf);
1272 unsigned Type = this->getRelocationTypeImpl(RE);
1273 bool IsPCRel = this->isRelocationPCRel(RE);
1275 // Determine any addends that should be displayed with the relocation.
1276 // These require decoding the relocation type, which is triple-specific.
1278 // X86_64 has entirely custom relocation types.
1279 if (Arch == Triple::x86_64) {
1280 bool isPCRel = RE->getPCRel();
1283 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1284 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1285 this->printRelocationTargetName(RE, fmt);
1287 if (isPCRel) fmt << "PCREL";
1290 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1291 DataRefImpl RelNext = Rel;
1293 const RelocationEntry *RENext = getRelocation(RelNext);
1295 // X86_64_SUBTRACTOR must be followed by a relocation of type
1296 // X86_64_RELOC_UNSIGNED.
1297 // NOTE: Scattered relocations don't exist on x86_64.
1298 unsigned RType = RENext->getType();
1300 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1301 "X86_64_RELOC_SUBTRACTOR.");
1303 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1304 // X86_64_SUBTRACTOR contains to the subtrahend.
1305 this->printRelocationTargetName(RENext, fmt);
1307 this->printRelocationTargetName(RE, fmt);
1310 case macho::RIT_X86_64_TLV:
1311 this->printRelocationTargetName(RE, fmt);
1313 if (isPCRel) fmt << "P";
1315 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1316 this->printRelocationTargetName(RE, fmt);
1319 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1320 this->printRelocationTargetName(RE, fmt);
1323 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1324 this->printRelocationTargetName(RE, fmt);
1328 this->printRelocationTargetName(RE, fmt);
1331 // X86 and ARM share some relocation types in common.
1332 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1333 // Generic relocation types...
1335 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1336 return object_error::success;
1337 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1338 DataRefImpl RelNext = Rel;
1340 const RelocationEntry *RENext = getRelocation(RelNext);
1342 // X86 sect diff's must be followed by a relocation of type
1343 // GENERIC_RELOC_PAIR.
1344 bool isNextScattered = (Arch != Triple::x86_64) &&
1345 (RENext->Address & macho::RF_Scattered);
1347 if (isNextScattered)
1348 RType = (RENext->Address >> 24) & 0xF;
1350 RType = RENext->getType();
1352 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1353 "GENERIC_RELOC_SECTDIFF.");
1355 this->printRelocationTargetName(RE, fmt);
1357 this->printRelocationTargetName(RENext, fmt);
1362 if (Arch == Triple::x86) {
1363 // All X86 relocations that need special printing were already
1364 // handled in the generic code.
1366 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1367 DataRefImpl RelNext = Rel;
1369 const RelocationEntry *RENext = getRelocation(RelNext);
1371 // X86 sect diff's must be followed by a relocation of type
1372 // GENERIC_RELOC_PAIR.
1373 bool isNextScattered = (Arch != Triple::x86_64) &&
1374 (RENext->Address & macho::RF_Scattered);
1376 if (isNextScattered)
1377 RType = (RENext->Address >> 24) & 0xF;
1379 RType = RENext->getType();
1381 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1382 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1384 this->printRelocationTargetName(RE, fmt);
1386 this->printRelocationTargetName(RENext, fmt);
1389 case macho::RIT_Generic_TLV: {
1390 this->printRelocationTargetName(RE, fmt);
1392 if (IsPCRel) fmt << "P";
1396 this->printRelocationTargetName(RE, fmt);
1398 } else { // ARM-specific relocations
1400 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1401 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1402 // Half relocations steal a bit from the length field to encode
1403 // whether this is an upper16 or a lower16 relocation.
1406 isUpper = (RE->Address >> 28) & 1;
1408 isUpper = (RE->getLength() >> 1) & 1;
1411 fmt << ":upper16:(";
1413 fmt << ":lower16:(";
1414 this->printRelocationTargetName(RE, fmt);
1416 DataRefImpl RelNext = Rel;
1418 const RelocationEntry *RENext = getRelocation(RelNext);
1420 // ARM half relocs must be followed by a relocation of type
1422 bool isNextScattered = (Arch != Triple::x86_64) &&
1423 (RENext->Address & macho::RF_Scattered);
1425 if (isNextScattered)
1426 RType = (RENext->Address >> 24) & 0xF;
1428 RType = RENext->getType();
1431 report_fatal_error("Expected ARM_RELOC_PAIR after "
1432 "GENERIC_RELOC_HALF");
1434 // NOTE: The half of the target virtual address is stashed in the
1435 // address field of the secondary relocation, but we can't reverse
1436 // engineer the constant offset from it without decoding the movw/movt
1437 // instruction to find the other half in its immediate field.
1439 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1440 // symbol/section pointer of the follow-on relocation.
1441 if (Type == macho::RIT_ARM_HalfDifference) {
1443 this->printRelocationTargetName(RENext, fmt);
1450 this->printRelocationTargetName(RE, fmt);
1455 this->printRelocationTargetName(RE, fmt);
1458 Result.append(fmtbuf.begin(), fmtbuf.end());
1459 return object_error::success;
1462 template<class MachOT>
1464 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
1465 bool &Result) const {
1466 const RelocationEntry *RE = getRelocation(Rel);
1467 unsigned Arch = this->getArch();
1468 unsigned Type = this->getRelocationTypeImpl(RE);
1472 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1473 // is always hidden.
1474 if (Arch == Triple::x86 || Arch == Triple::arm) {
1475 if (Type == macho::RIT_Pair) Result = true;
1476 } else if (Arch == Triple::x86_64) {
1477 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1478 // an X864_64_RELOC_SUBTRACTOR.
1479 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1480 DataRefImpl RelPrev = Rel;
1482 const RelocationEntry *REPrev = this->getRelocation(RelPrev);
1484 unsigned PrevType = REPrev->getType();
1486 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1490 return object_error::success;
1493 template<class MachOT>
1495 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
1496 uint64_t &Res) const {
1497 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1499 if (Entry->SectionIndex) {
1500 const Section *Sec =
1501 this->getSection(this->Sections[Entry->SectionIndex-1]);
1502 Res += Sec->Offset - Sec->Address;
1505 return object_error::success;
1508 template<class MachOT>
1510 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
1512 bool &Result) const {
1514 this->getSymbolType(Symb, ST);
1515 if (ST == SymbolRef::ST_Unknown) {
1517 return object_error::success;
1520 uint64_t SectBegin, SectEnd;
1521 getSectionAddress(Sec, SectBegin);
1522 getSectionSize(Sec, SectEnd);
1523 SectEnd += SectBegin;
1525 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1526 uint64_t SymAddr= Entry->Value;
1527 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
1529 return object_error::success;
1532 template<class MachOT>
1533 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
1534 uint64_t &Res) const {
1535 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1537 return object_error::success;
1540 template<class MachOT>
1541 error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI,
1542 uint64_t &Result) const {
1543 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1544 uint64_t BeginOffset;
1545 uint64_t EndOffset = 0;
1546 uint8_t SectionIndex;
1548 const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
1549 BeginOffset = Entry->Value;
1550 SectionIndex = Entry->SectionIndex;
1551 if (!SectionIndex) {
1552 uint32_t flags = SymbolRef::SF_None;
1553 this->getSymbolFlags(DRI, flags);
1554 if (flags & SymbolRef::SF_Common)
1555 Result = Entry->Value;
1557 Result = UnknownAddressOrSize;
1558 return object_error::success;
1560 // Unfortunately symbols are unsorted so we need to touch all
1561 // symbols from load command
1563 uint32_t Command = DRI.d.a;
1564 while (Command == DRI.d.a) {
1565 this->moveToNextSymbol(DRI);
1566 if (DRI.d.a < LoadCommandCount) {
1567 Entry = getSymbolTableEntry(DRI);
1568 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
1569 if (!EndOffset || Entry->Value < EndOffset)
1570 EndOffset = Entry->Value;
1576 this->getSectionSize(this->Sections[SectionIndex-1], Size);
1577 this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset);
1580 Result = EndOffset - BeginOffset;
1581 return object_error::success;
1584 template<class MachOT>
1585 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
1586 SectionRef &Res) const {
1588 moveToNextSection(Sec);
1589 Res = SectionRef(Sec, this);
1590 return object_error::success;
1593 template<class MachOT>
1594 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
1596 moveToNextSection(DRI);
1597 return section_iterator(SectionRef(DRI, this));
1600 template<class MachOT>
1601 void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const {
1602 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1603 while (DRI.d.a < LoadCommandCount) {
1604 const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a);
1605 if (Command->Type == SegmentLoadType) {
1606 const SegmentLoadCommand *SegmentLoadCmd =
1607 reinterpret_cast<const SegmentLoadCommand*>(Command);
1608 if (DRI.d.b < SegmentLoadCmd->NumSections)