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(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 template<class MachOT>
77 struct MachODataTypeTypedefHelper;
79 template<endianness TargetEndianness>
80 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
81 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
82 typedef typename Base::MachOInt32 MachOIntPtr;
85 template<endianness TargetEndianness>
86 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
87 typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
88 typedef typename Base::MachOInt64 MachOIntPtr;
91 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \
92 LLVM_MACHOB_IMPORT_TYPES(E) \
94 MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
96 namespace MachOFormat {
102 template<class MachOT>
105 template<endianness TargetEndianness>
106 struct Section<MachOType<TargetEndianness, false> > {
107 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
109 char SegmentName[16];
114 MachOInt32 RelocationTableOffset;
115 MachOInt32 NumRelocationTableEntries;
117 MachOInt32 Reserved1;
118 MachOInt32 Reserved2;
121 template<endianness TargetEndianness>
122 struct Section<MachOType<TargetEndianness, true> > {
123 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
125 char SegmentName[16];
130 MachOInt32 RelocationTableOffset;
131 MachOInt32 NumRelocationTableEntries;
133 MachOInt32 Reserved1;
134 MachOInt32 Reserved2;
135 MachOInt32 Reserved3;
140 operator uint32_t() const {
141 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
145 template<endianness TargetEndianness>
146 struct RelocationEntry;
149 struct RelocationEntry<support::little> {
150 LLVM_MACHOB_IMPORT_TYPES(support::little)
152 MachOInt24 SymbolNum;
155 unsigned getPCRel() const {
158 unsigned getLength() const {
159 return (Bits >> 1) & 0x3;
161 unsigned getExternal() const {
162 return (Bits >> 3) & 0x1;
164 unsigned getType() const {
170 struct RelocationEntry<support::big> {
171 LLVM_MACHOB_IMPORT_TYPES(support::big)
173 MachOInt24 SymbolNum;
176 unsigned getType() const {
179 unsigned getExternal() const {
180 return (Bits >> 4) & 0x1;
182 unsigned getLength() const {
183 return (Bits >> 5) & 0x3;
185 unsigned getPCRel() const {
190 template<endianness TargetEndianness>
191 struct ScatteredRelocationEntry;
194 struct ScatteredRelocationEntry<support::little> {
195 LLVM_MACHOB_IMPORT_TYPES(support::little)
200 unsigned getType() const {
203 unsigned getLength() const {
204 return (Bits >> 4) & 0x3;
206 unsigned getPCRel() const {
207 return (Bits >> 6) & 0x1;
209 unsigned getScattered() const {
215 struct ScatteredRelocationEntry<support::big> {
216 LLVM_MACHOB_IMPORT_TYPES(support::big)
218 unsigned getType() const {
221 unsigned getLength() const {
222 return (Bits >> 4) & 0x3;
224 unsigned getPCRel() const {
225 return (Bits >> 6) & 0x1;
227 unsigned getScattered() const {
234 template<endianness TargetEndianness>
235 struct SymbolTableEntryBase {
236 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
237 MachOInt32 StringIndex;
239 uint8_t SectionIndex;
243 template<class MachOT>
244 struct SymbolTableEntry;
246 template<endianness TargetEndianness, bool Is64Bits>
247 struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
248 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
249 MachOInt32 StringIndex;
251 uint8_t SectionIndex;
256 template<endianness TargetEndianness>
258 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
263 template<endianness TargetEndianness>
264 struct SymtabLoadCommand {
265 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
268 MachOInt32 SymbolTableOffset;
269 MachOInt32 NumSymbolTableEntries;
270 MachOInt32 StringTableOffset;
271 MachOInt32 StringTableSize;
274 template<class MachOT>
275 struct SegmentLoadCommand;
277 template<endianness TargetEndianness, bool Is64Bits>
278 struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
279 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
283 MachOIntPtr VMAddress;
285 MachOIntPtr FileOffset;
286 MachOIntPtr FileSize;
287 MachOInt32 MaxVMProtection;
288 MachOInt32 InitialVMProtection;
289 MachOInt32 NumSections;
293 template<endianness TargetEndianness>
294 struct LinkeditDataLoadCommand {
295 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
298 MachOInt32 DataOffset;
302 template<endianness TargetEndianness>
304 LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
307 MachOInt32 CPUSubtype;
309 MachOInt32 NumLoadCommands;
310 MachOInt32 SizeOfLoadCommands;
315 class MachOObjectFileBase : public ObjectFile {
317 typedef MachOFormat::SectionBase SectionBase;
319 MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
322 virtual symbol_iterator begin_dynamic_symbols() const;
323 virtual symbol_iterator end_dynamic_symbols() const;
324 virtual library_iterator begin_libraries_needed() const;
325 virtual library_iterator end_libraries_needed() const;
327 virtual uint8_t getBytesInAddress() const;
328 virtual StringRef getLoadName() const;
330 bool is64Bit() const;
331 void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
332 unsigned getHeaderSize() const;
333 StringRef getData(size_t Offset, size_t Size) const;
335 static inline bool classof(const Binary *v) {
340 StringRef parseSegmentOrSectionName(const char *P) const;
342 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
343 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
344 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
345 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
347 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
348 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
349 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
351 virtual error_code getRelocationNext(DataRefImpl Rel,
352 RelocationRef &Res) const;
354 virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
355 virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
356 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
359 std::size_t getSectionIndex(DataRefImpl Sec) const;
361 typedef SmallVector<DataRefImpl, 1> SectionList;
362 SectionList Sections;
365 template<endianness TargetEndianness>
366 class MachOObjectFileMiddle : public MachOObjectFileBase {
369 typedef MachOFormat::SymbolTableEntryBase<TargetEndianness>
370 SymbolTableEntryBase;
371 typedef MachOFormat::LinkeditDataLoadCommand<TargetEndianness>
372 LinkeditDataLoadCommand;
373 typedef MachOFormat::Header<TargetEndianness> Header;
374 typedef MachOFormat::SymtabLoadCommand<TargetEndianness> SymtabLoadCommand;
375 typedef MachOFormat::RelocationEntry<TargetEndianness> RelocationEntry;
376 typedef MachOFormat::ScatteredRelocationEntry<TargetEndianness>
377 ScatteredRelocationEntry;
378 typedef MachOFormat::LoadCommand<TargetEndianness> LoadCommand;
380 MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
382 const Header *getHeader() const;
383 const LoadCommand *getLoadCommandInfo(unsigned Index) const;
384 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
385 bool isRelocationScattered(const RelocationEntry *RE) const;
386 bool isRelocationPCRel(const RelocationEntry *RE) const;
387 unsigned getRelocationLength(const RelocationEntry *RE) const;
388 unsigned getRelocationTypeImpl(const RelocationEntry *RE) const;
390 void moveToNextSymbol(DataRefImpl &DRI) const;
391 void printRelocationTargetName(const RelocationEntry *RE,
392 raw_string_ostream &fmt) const;
393 const SectionBase *getSectionBase(DataRefImpl DRI) const;
394 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
395 unsigned getCPUType() const;
397 // In a MachO file, sections have a segment name. This is used in the .o
398 // files. They have a single segment, but this field specifies which segment
399 // a section should be put in in the final object.
400 StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
402 // Names are stored as 16 bytes. These returns the raw 16 bytes without
403 // interpreting them as a C string.
404 ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
405 ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
407 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
408 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
409 virtual error_code getSymbolType(DataRefImpl Symb,
410 SymbolRef::Type &Res) const;
411 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
412 virtual error_code getSymbolSection(DataRefImpl Symb,
413 section_iterator &Res) const;
414 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
415 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
416 virtual symbol_iterator begin_symbols() const;
417 virtual unsigned getArch() const;
418 virtual StringRef getFileFormatName() const;
419 virtual symbol_iterator end_symbols() const;
420 virtual section_iterator end_sections() const;
422 static bool classof(const Binary *v);
425 // Helper to advance a section or symbol iterator multiple increments at a
428 static error_code advance(T &it, size_t Val);
431 static void advanceTo(T &it, size_t Val);
434 template<class MachOT>
435 struct MachOObjectFileHelperCommon;
437 template<endianness TargetEndianness, bool Is64Bits>
438 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
440 MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
442 typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
444 typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
447 template<class MachOT>
448 struct MachOObjectFileHelper;
450 template<endianness TargetEndianness>
451 struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > :
452 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > {
453 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
456 template<endianness TargetEndianness>
457 struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > :
458 public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > {
459 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
462 template<class MachOT>
463 class MachOObjectFile : public MachOObjectFileMiddle<MachOT::TargetEndianness> {
465 static const endianness TargetEndianness = MachOT::TargetEndianness;
466 static const bool Is64Bits = MachOT::Is64Bits;
468 typedef MachOObjectFileMiddle<MachOT::TargetEndianness> Base;
469 typedef typename Base::RelocationEntry RelocationEntry;
470 typedef typename Base::SectionBase SectionBase;
471 typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase;
472 typedef typename Base::LoadCommand LoadCommand;
474 typedef MachOObjectFileHelper<MachOT> Helper;
475 static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
476 typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
477 typedef typename Helper::SymbolTableEntry SymbolTableEntry;
478 typedef typename Helper::Section Section;
480 MachOObjectFile(MemoryBuffer *Object, error_code &ec);
481 static bool classof(const Binary *v);
483 const Section *getSection(DataRefImpl DRI) const;
484 const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
485 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
487 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
488 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
489 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
490 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
491 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
492 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
493 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
494 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
495 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
496 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
497 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
498 virtual error_code getRelocationTypeName(DataRefImpl Rel,
499 SmallVectorImpl<char> &Result) const;
500 virtual error_code getRelocationValueString(DataRefImpl Rel,
501 SmallVectorImpl<char> &Result) const;
502 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
503 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
504 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
506 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
507 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
508 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
509 virtual section_iterator begin_sections() const;
510 void moveToNextSection(DataRefImpl &DRI) const;
513 typedef MachOObjectFileMiddle<support::little> MachOObjectFileLE;
514 typedef MachOObjectFileMiddle<support::big> MachOObjectFileBE;
516 typedef MachOObjectFile<MachOType<support::little, false> >
518 typedef MachOObjectFile<MachOType<support::big, false> >
520 typedef MachOObjectFile<MachOType<support::little, true> >
522 typedef MachOObjectFile<MachOType<support::big, true> >
525 template<endianness TargetEndianness>
526 MachOObjectFileMiddle<TargetEndianness>::MachOObjectFileMiddle(MemoryBuffer *O,
529 MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) {
532 template<endianness E>
533 const typename MachOObjectFileMiddle<E>::SymbolTableEntryBase *
534 MachOObjectFileMiddle<E>::getSymbolTableEntryBase(DataRefImpl DRI) const {
535 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
536 const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
538 unsigned Index = DRI.d.b;
540 unsigned SymbolTableEntrySize = is64Bit() ?
541 sizeof(MachOObjectFileLE64::SymbolTableEntry) :
542 sizeof(MachOObjectFileLE32::SymbolTableEntry);
544 uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize;
545 StringRef Data = getData(Offset, SymbolTableEntrySize);
546 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
549 template<endianness E>
550 const typename MachOObjectFileMiddle<E>::Header *
551 MachOObjectFileMiddle<E>::getHeader() const {
552 StringRef Data = getData(0, sizeof(Header));
553 return reinterpret_cast<const Header*>(Data.data());
556 template<endianness E>
557 const typename MachOObjectFileMiddle<E>::LoadCommand *
558 MachOObjectFileMiddle<E>::getLoadCommandInfo(unsigned Index) const {
559 assert(Index < getHeader()->NumLoadCommands);
561 uint64_t NewOffset = getHeaderSize();
562 const LoadCommand *Load;
566 StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand));
567 Load = reinterpret_cast<const LoadCommand*>(Data.data());
568 NewOffset = Offset + Load->Size;
570 } while (I != Index + 1);
572 return reinterpret_cast<const LoadCommand*>(Load);
575 template<endianness E>
576 const typename MachOObjectFileMiddle<E>::RelocationEntry *
577 MachOObjectFileMiddle<E>::getRelocation(DataRefImpl Rel) const {
578 if (const MachOObjectFile<MachOType<E, true> > *O =
579 dyn_cast<MachOObjectFile<MachOType<E, true> > >(this))
580 return O->getRelocation(Rel);
582 const MachOObjectFile<MachOType<E, false> > *O =
583 cast<MachOObjectFile<MachOType<E, false> > >(this);
584 return O->getRelocation(Rel);
587 template<endianness E>
589 MachOObjectFileMiddle<E>::isRelocationScattered(const RelocationEntry *RE)
591 if (this->getCPUType() == llvm::MachO::CPUTypeX86_64)
593 return RE->Address & macho::RF_Scattered;
596 template<endianness E>
598 MachOObjectFileMiddle<E>::isRelocationPCRel(const RelocationEntry *RE) const {
599 typedef MachOObjectFileMiddle<E> ObjType;
600 if (isRelocationScattered(RE)) {
601 const ObjType::ScatteredRelocationEntry *SRE =
602 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
603 return SRE->getPCRel();
605 return RE->getPCRel();
608 template<endianness E>
610 MachOObjectFileMiddle<E>::getRelocationLength(const RelocationEntry *RE) const {
611 typedef MachOObjectFileMiddle<E> ObjType;
612 if (isRelocationScattered(RE)) {
613 const ObjType::ScatteredRelocationEntry *SRE =
614 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
615 return SRE->getLength();
617 return RE->getLength();
620 template<endianness E>
622 MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE)
624 typedef MachOObjectFileMiddle<E> ObjType;
625 if (isRelocationScattered(RE)) {
626 const ObjType::ScatteredRelocationEntry *SRE =
627 reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
628 return SRE->getType();
630 return RE->getType();
633 // Helper to advance a section or symbol iterator multiple increments at a time.
634 template<endianness E>
636 error_code MachOObjectFileMiddle<E>::advance(T &it, size_t Val) {
644 template<endianness E>
646 void MachOObjectFileMiddle<E>::advanceTo(T &it, size_t Val) {
647 if (error_code ec = advance(it, Val))
648 report_fatal_error(ec.message());
651 template<endianness E>
653 MachOObjectFileMiddle<E>::printRelocationTargetName(const RelocationEntry *RE,
654 raw_string_ostream &fmt) const {
655 bool IsScattered = isRelocationScattered(RE);
657 // Target of a scattered relocation is an address. In the interest of
658 // generating pretty output, scan through the symbol table looking for a
659 // symbol that aligns with that address. If we find one, print it.
660 // Otherwise, we just print the hex address of the target.
662 uint32_t Val = RE->SymbolNum;
665 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
667 if (ec) report_fatal_error(ec.message());
672 if ((ec = SI->getAddress(Addr)))
673 report_fatal_error(ec.message());
674 if (Addr != Val) continue;
675 if ((ec = SI->getName(Name)))
676 report_fatal_error(ec.message());
681 // If we couldn't find a symbol that this relocation refers to, try
682 // to find a section beginning instead.
683 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
685 if (ec) report_fatal_error(ec.message());
690 if ((ec = SI->getAddress(Addr)))
691 report_fatal_error(ec.message());
692 if (Addr != Val) continue;
693 if ((ec = SI->getName(Name)))
694 report_fatal_error(ec.message());
699 fmt << format("0x%x", Val);
704 bool isExtern = RE->getExternal();
705 uint64_t Val = RE->Address;
708 symbol_iterator SI = begin_symbols();
712 section_iterator SI = begin_sections();
720 template<endianness E>
721 const typename MachOObjectFileMiddle<E>::SectionBase *
722 MachOObjectFileMiddle<E>::getSectionBase(DataRefImpl DRI) const {
723 uintptr_t CommandAddr =
724 reinterpret_cast<uintptr_t>(getLoadCommandInfo(DRI.d.a));
726 bool Is64 = is64Bit();
727 unsigned SegmentLoadSize =
728 Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) :
729 sizeof(MachOObjectFileLE32::SegmentLoadCommand);
730 unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) :
731 sizeof(MachOObjectFileLE32::Section);
733 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
734 return reinterpret_cast<const SectionBase*>(SectionAddr);
737 template<endianness E>
738 unsigned MachOObjectFileMiddle<E>::getCPUType() const {
739 return getHeader()->CPUType;
742 template<endianness E>
743 void MachOObjectFileMiddle<E>::moveToNextSymbol(DataRefImpl &DRI) const {
744 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
745 while (DRI.d.a < LoadCommandCount) {
746 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
747 if (L->Type == macho::LCT_Symtab) {
748 const SymtabLoadCommand *S =
749 reinterpret_cast<const SymtabLoadCommand *>(L);
750 if (DRI.d.b < S->NumSymbolTableEntries)
759 template<endianness E>
761 MachOObjectFileMiddle<E>::getSectionFinalSegmentName(DataRefImpl Sec) const {
762 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
763 return parseSegmentOrSectionName(Raw.data());
766 template<endianness E>
768 MachOObjectFileMiddle<E>::getSectionRawName(DataRefImpl Sec) const {
769 const SectionBase *Base = getSectionBase(Sec);
770 return ArrayRef<char>(Base->Name);
773 template<endianness E>
775 MachOObjectFileMiddle<E>::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
776 const SectionBase *Base = getSectionBase(Sec);
777 return ArrayRef<char>(Base->SegmentName);
780 template<endianness E>
781 error_code MachOObjectFileMiddle<E>::getSymbolFlags(DataRefImpl DRI,
782 uint32_t &Result) const {
783 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
785 uint8_t MachOType = Entry->Type;
786 uint16_t MachOFlags = Entry->Flags;
788 // TODO: Correctly set SF_ThreadLocal
789 Result = SymbolRef::SF_None;
791 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
792 Result |= SymbolRef::SF_Undefined;
794 if (MachOFlags & macho::STF_StabsEntryMask)
795 Result |= SymbolRef::SF_FormatSpecific;
797 if (MachOType & MachO::NlistMaskExternal) {
798 Result |= SymbolRef::SF_Global;
799 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
800 Result |= SymbolRef::SF_Common;
803 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
804 Result |= SymbolRef::SF_Weak;
806 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
807 Result |= SymbolRef::SF_Absolute;
809 return object_error::success;
812 template<endianness E>
813 error_code MachOObjectFileMiddle<E>::getSymbolType(DataRefImpl Symb,
814 SymbolRef::Type &Res) const {
815 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
816 uint8_t n_type = Entry->Type;
818 Res = SymbolRef::ST_Other;
820 // If this is a STAB debugging symbol, we can do nothing more.
821 if (n_type & MachO::NlistMaskStab) {
822 Res = SymbolRef::ST_Debug;
823 return object_error::success;
826 switch (n_type & MachO::NlistMaskType) {
827 case MachO::NListTypeUndefined :
828 Res = SymbolRef::ST_Unknown;
830 case MachO::NListTypeSection :
831 Res = SymbolRef::ST_Function;
834 return object_error::success;
837 template<endianness E>
838 error_code MachOObjectFileMiddle<E>::getSymbolName(DataRefImpl Symb,
839 StringRef &Res) const {
840 const LoadCommand *L = getLoadCommandInfo(Symb.d.a);
841 const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
842 StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize);
843 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
844 const char *Start = &StringTable.data()[Entry->StringIndex];
845 Res = StringRef(Start);
846 return object_error::success;
849 template<endianness E>
851 MachOObjectFileMiddle<E>::getSymbolSection(DataRefImpl Symb,
852 section_iterator &Res) const {
853 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
854 uint8_t index = Entry->SectionIndex;
857 Res = end_sections();
859 Res = section_iterator(SectionRef(Sections[index-1], this));
861 return object_error::success;
865 template<endianness E>
866 error_code MachOObjectFileMiddle<E>::getSymbolNMTypeChar(DataRefImpl Symb,
868 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
869 uint8_t Type = Entry->Type;
870 uint16_t Flags = Entry->Flags;
873 switch (Type & macho::STF_TypeMask) {
874 case macho::STT_Undefined:
877 case macho::STT_Absolute:
878 case macho::STT_Section:
886 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
887 Char = toupper(static_cast<unsigned char>(Char));
889 return object_error::success;
892 template<endianness E>
894 MachOObjectFileMiddle<E>::getSectionName(DataRefImpl Sec,
895 StringRef &Result) const {
896 ArrayRef<char> Raw = getSectionRawName(Sec);
897 Result = parseSegmentOrSectionName(Raw.data());
898 return object_error::success;
901 template<endianness E>
902 error_code MachOObjectFileMiddle<E>::getSymbolNext(DataRefImpl Symb,
903 SymbolRef &Res) const {
905 moveToNextSymbol(Symb);
906 Res = SymbolRef(Symb, this);
907 return object_error::success;
910 template<endianness E>
911 symbol_iterator MachOObjectFileMiddle<E>::begin_symbols() const {
912 // DRI.d.a = segment number; DRI.d.b = symbol index.
914 moveToNextSymbol(DRI);
915 return symbol_iterator(SymbolRef(DRI, this));
918 template<endianness E>
919 unsigned MachOObjectFileMiddle<E>::getArch() const {
920 switch (getCPUType()) {
921 case llvm::MachO::CPUTypeI386:
923 case llvm::MachO::CPUTypeX86_64:
924 return Triple::x86_64;
925 case llvm::MachO::CPUTypeARM:
927 case llvm::MachO::CPUTypePowerPC:
929 case llvm::MachO::CPUTypePowerPC64:
930 return Triple::ppc64;
932 return Triple::UnknownArch;
936 template<endianness E>
937 StringRef MachOObjectFileMiddle<E>::getFileFormatName() const {
938 unsigned CPUType = getCPUType();
941 case llvm::MachO::CPUTypeI386:
942 return "Mach-O 32-bit i386";
943 case llvm::MachO::CPUTypeARM:
945 case llvm::MachO::CPUTypePowerPC:
946 return "Mach-O 32-bit ppc";
948 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
949 "64-bit object file when we're not 64-bit?");
950 return "Mach-O 32-bit unknown";
954 // Make sure the cpu type has the correct mask.
955 assert((CPUType & llvm::MachO::CPUArchABI64)
956 == llvm::MachO::CPUArchABI64 &&
957 "32-bit object file when we're 64-bit?");
960 case llvm::MachO::CPUTypeX86_64:
961 return "Mach-O 64-bit x86-64";
962 case llvm::MachO::CPUTypePowerPC64:
963 return "Mach-O 64-bit ppc64";
965 return "Mach-O 64-bit unknown";
969 template<endianness E>
970 symbol_iterator MachOObjectFileMiddle<E>::end_symbols() const {
972 DRI.d.a = getHeader()->NumLoadCommands;
973 return symbol_iterator(SymbolRef(DRI, this));
976 template<endianness E>
977 section_iterator MachOObjectFileMiddle<E>::end_sections() const {
979 DRI.d.a = getHeader()->NumLoadCommands;
980 return section_iterator(SectionRef(DRI, this));
983 template<endianness E>
984 bool MachOObjectFileMiddle<E>::classof(const Binary *v) {
985 return isa<MachOObjectFile<MachOType<E, false> > >(v) ||
986 isa<MachOObjectFile<MachOType<E, true> > >(v);
989 template<class MachOT>
990 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
992 MachOObjectFileMiddle<TargetEndianness>(Object, Is64Bits, ec) {
994 moveToNextSection(DRI);
995 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
996 while (DRI.d.a < LoadCommandCount) {
997 this->Sections.push_back(DRI);
999 moveToNextSection(DRI);
1003 template<class MachOT>
1004 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
1005 return v->getType() ==
1006 Base::getMachOType(TargetEndianness == support::little, Is64Bits);
1009 template<class MachOT>
1010 const typename MachOObjectFile<MachOT>::Section *
1011 MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const {
1012 const SectionBase *Addr = this->getSectionBase(DRI);
1013 return reinterpret_cast<const Section*>(Addr);
1016 template<class MachOT>
1017 const typename MachOObjectFile<MachOT>::SymbolTableEntry *
1018 MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const {
1019 const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI);
1020 return reinterpret_cast<const SymbolTableEntry*>(Base);
1023 template<class MachOT>
1024 const typename MachOObjectFile<MachOT>::RelocationEntry *
1025 MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const {
1026 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1027 uint32_t RelOffset = Sect->RelocationTableOffset;
1028 uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
1029 StringRef Data = this->getData(Offset, sizeof(RelocationEntry));
1030 return reinterpret_cast<const RelocationEntry*>(Data.data());
1033 template<class MachOT>
1035 MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec,
1036 uint64_t &Res) const {
1037 const Section *Sect = getSection(Sec);
1038 Res = Sect->Address;
1039 return object_error::success;
1042 template<class MachOT>
1044 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
1045 uint64_t &Res) const {
1046 const Section *Sect = getSection(Sec);
1048 return object_error::success;
1051 template<class MachOT>
1053 MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec,
1054 StringRef &Res) const {
1055 const Section *Sect = getSection(Sec);
1056 Res = this->getData(Sect->Offset, Sect->Size);
1057 return object_error::success;
1060 template<class MachOT>
1062 MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec,
1063 uint64_t &Res) const {
1064 const Section *Sect = getSection(Sec);
1065 Res = uint64_t(1) << Sect->Align;
1066 return object_error::success;
1069 template<class MachOT>
1071 MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const {
1072 const Section *Sect = getSection(Sec);
1073 Res = Sect->Flags & macho::SF_PureInstructions;
1074 return object_error::success;
1077 template<class MachOT>
1079 MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
1080 const Section *Sect = getSection(Sec);
1081 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
1082 Res = SectionType == MachO::SectionTypeZeroFill ||
1083 SectionType == MachO::SectionTypeZeroFillLarge;
1084 return object_error::success;
1087 template<class MachOT>
1089 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
1090 const Section *Sect = getSection(Sec);
1091 uint32_t LastReloc = Sect->NumRelocationTableEntries;
1093 Ret.d.a = LastReloc;
1094 Ret.d.b = this->getSectionIndex(Sec);
1095 return relocation_iterator(RelocationRef(Ret, this));
1098 template<class MachOT>
1100 MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
1101 uint64_t &Res) const {
1102 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1103 uint64_t SectAddress = Sect->Address;
1104 const RelocationEntry *RE = getRelocation(Rel);
1107 if (this->isRelocationScattered(RE))
1108 RelAddr = RE->Address & 0xFFFFFF;
1110 RelAddr = RE->Address;
1112 Res = SectAddress + RelAddr;
1113 return object_error::success;
1116 template<class MachOT>
1118 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
1119 uint64_t &Res) const {
1120 const RelocationEntry *RE = getRelocation(Rel);
1121 if (this->isRelocationScattered(RE))
1122 Res = RE->Address & 0xFFFFFF;
1125 return object_error::success;
1128 template<class MachOT>
1130 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
1131 SymbolRef &Res) const {
1132 const RelocationEntry *RE = getRelocation(Rel);
1133 uint32_t SymbolIdx = RE->SymbolNum;
1134 bool isExtern = RE->getExternal();
1137 this->moveToNextSymbol(Sym);
1139 for (unsigned i = 0; i < SymbolIdx; i++) {
1141 this->moveToNextSymbol(Sym);
1142 assert(Sym.d.a < this->getHeader()->NumLoadCommands &&
1143 "Relocation symbol index out of range!");
1146 Res = SymbolRef(Sym, this);
1147 return object_error::success;
1150 template<class MachOT>
1151 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
1152 uint64_t &Res) const {
1153 const RelocationEntry *RE = getRelocation(Rel);
1154 Res = this->getRelocationTypeImpl(RE);
1155 return object_error::success;
1158 template<class MachOT>
1160 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
1161 SmallVectorImpl<char> &Result) const {
1162 // TODO: Support scattered relocations.
1164 const RelocationEntry *RE = getRelocation(Rel);
1166 unsigned Arch = this->getArch();
1168 unsigned r_type = this->getRelocationTypeImpl(RE);
1172 static const char *const Table[] = {
1173 "GENERIC_RELOC_VANILLA",
1174 "GENERIC_RELOC_PAIR",
1175 "GENERIC_RELOC_SECTDIFF",
1176 "GENERIC_RELOC_PB_LA_PTR",
1177 "GENERIC_RELOC_LOCAL_SECTDIFF",
1178 "GENERIC_RELOC_TLV" };
1183 res = Table[r_type];
1186 case Triple::x86_64: {
1187 static const char *const Table[] = {
1188 "X86_64_RELOC_UNSIGNED",
1189 "X86_64_RELOC_SIGNED",
1190 "X86_64_RELOC_BRANCH",
1191 "X86_64_RELOC_GOT_LOAD",
1193 "X86_64_RELOC_SUBTRACTOR",
1194 "X86_64_RELOC_SIGNED_1",
1195 "X86_64_RELOC_SIGNED_2",
1196 "X86_64_RELOC_SIGNED_4",
1197 "X86_64_RELOC_TLV" };
1202 res = Table[r_type];
1206 static const char *const Table[] = {
1207 "ARM_RELOC_VANILLA",
1209 "ARM_RELOC_SECTDIFF",
1210 "ARM_RELOC_LOCAL_SECTDIFF",
1211 "ARM_RELOC_PB_LA_PTR",
1213 "ARM_THUMB_RELOC_BR22",
1214 "ARM_THUMB_32BIT_BRANCH",
1216 "ARM_RELOC_HALF_SECTDIFF" };
1221 res = Table[r_type];
1225 static const char *const Table[] = {
1226 "PPC_RELOC_VANILLA",
1234 "PPC_RELOC_SECTDIFF",
1235 "PPC_RELOC_PB_LA_PTR",
1236 "PPC_RELOC_HI16_SECTDIFF",
1237 "PPC_RELOC_LO16_SECTDIFF",
1238 "PPC_RELOC_HA16_SECTDIFF",
1240 "PPC_RELOC_LO14_SECTDIFF",
1241 "PPC_RELOC_LOCAL_SECTDIFF" };
1243 res = Table[r_type];
1246 case Triple::UnknownArch:
1250 Result.append(res.begin(), res.end());
1251 return object_error::success;
1254 template<class MachOT>
1256 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
1257 SmallVectorImpl<char> &Result) const {
1258 const RelocationEntry *RE = getRelocation(Rel);
1260 unsigned Arch = this->getArch();
1261 bool IsScattered = this->isRelocationScattered(RE);
1264 raw_string_ostream fmt(fmtbuf);
1266 unsigned Type = this->getRelocationTypeImpl(RE);
1267 bool IsPCRel = this->isRelocationPCRel(RE);
1269 // Determine any addends that should be displayed with the relocation.
1270 // These require decoding the relocation type, which is triple-specific.
1272 // X86_64 has entirely custom relocation types.
1273 if (Arch == Triple::x86_64) {
1274 bool isPCRel = RE->getPCRel();
1277 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1278 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1279 this->printRelocationTargetName(RE, fmt);
1281 if (isPCRel) fmt << "PCREL";
1284 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1285 DataRefImpl RelNext = Rel;
1287 const RelocationEntry *RENext = getRelocation(RelNext);
1289 // X86_64_SUBTRACTOR must be followed by a relocation of type
1290 // X86_64_RELOC_UNSIGNED.
1291 // NOTE: Scattered relocations don't exist on x86_64.
1292 unsigned RType = RENext->getType();
1294 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1295 "X86_64_RELOC_SUBTRACTOR.");
1297 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1298 // X86_64_SUBTRACTOR contains to the subtrahend.
1299 this->printRelocationTargetName(RENext, fmt);
1301 this->printRelocationTargetName(RE, fmt);
1304 case macho::RIT_X86_64_TLV:
1305 this->printRelocationTargetName(RE, fmt);
1307 if (isPCRel) fmt << "P";
1309 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1310 this->printRelocationTargetName(RE, fmt);
1313 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1314 this->printRelocationTargetName(RE, fmt);
1317 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1318 this->printRelocationTargetName(RE, fmt);
1322 this->printRelocationTargetName(RE, fmt);
1325 // X86 and ARM share some relocation types in common.
1326 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1327 // Generic relocation types...
1329 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1330 return object_error::success;
1331 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1332 DataRefImpl RelNext = Rel;
1334 const RelocationEntry *RENext = getRelocation(RelNext);
1336 // X86 sect diff's must be followed by a relocation of type
1337 // GENERIC_RELOC_PAIR.
1338 bool isNextScattered = (Arch != Triple::x86_64) &&
1339 (RENext->Address & macho::RF_Scattered);
1341 if (isNextScattered)
1342 RType = (RENext->Address >> 24) & 0xF;
1344 RType = RENext->getType();
1346 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1347 "GENERIC_RELOC_SECTDIFF.");
1349 this->printRelocationTargetName(RE, fmt);
1351 this->printRelocationTargetName(RENext, fmt);
1356 if (Arch == Triple::x86) {
1357 // All X86 relocations that need special printing were already
1358 // handled in the generic code.
1360 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1361 DataRefImpl RelNext = Rel;
1363 const RelocationEntry *RENext = getRelocation(RelNext);
1365 // X86 sect diff's must be followed by a relocation of type
1366 // GENERIC_RELOC_PAIR.
1367 bool isNextScattered = (Arch != Triple::x86_64) &&
1368 (RENext->Address & macho::RF_Scattered);
1370 if (isNextScattered)
1371 RType = (RENext->Address >> 24) & 0xF;
1373 RType = RENext->getType();
1375 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1376 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1378 this->printRelocationTargetName(RE, fmt);
1380 this->printRelocationTargetName(RENext, fmt);
1383 case macho::RIT_Generic_TLV: {
1384 this->printRelocationTargetName(RE, fmt);
1386 if (IsPCRel) fmt << "P";
1390 this->printRelocationTargetName(RE, fmt);
1392 } else { // ARM-specific relocations
1394 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1395 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1396 // Half relocations steal a bit from the length field to encode
1397 // whether this is an upper16 or a lower16 relocation.
1400 isUpper = (RE->Address >> 28) & 1;
1402 isUpper = (RE->getLength() >> 1) & 1;
1405 fmt << ":upper16:(";
1407 fmt << ":lower16:(";
1408 this->printRelocationTargetName(RE, fmt);
1410 DataRefImpl RelNext = Rel;
1412 const RelocationEntry *RENext = getRelocation(RelNext);
1414 // ARM half relocs must be followed by a relocation of type
1416 bool isNextScattered = (Arch != Triple::x86_64) &&
1417 (RENext->Address & macho::RF_Scattered);
1419 if (isNextScattered)
1420 RType = (RENext->Address >> 24) & 0xF;
1422 RType = RENext->getType();
1425 report_fatal_error("Expected ARM_RELOC_PAIR after "
1426 "GENERIC_RELOC_HALF");
1428 // NOTE: The half of the target virtual address is stashed in the
1429 // address field of the secondary relocation, but we can't reverse
1430 // engineer the constant offset from it without decoding the movw/movt
1431 // instruction to find the other half in its immediate field.
1433 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1434 // symbol/section pointer of the follow-on relocation.
1435 if (Type == macho::RIT_ARM_HalfDifference) {
1437 this->printRelocationTargetName(RENext, fmt);
1444 this->printRelocationTargetName(RE, fmt);
1449 this->printRelocationTargetName(RE, fmt);
1452 Result.append(fmtbuf.begin(), fmtbuf.end());
1453 return object_error::success;
1456 template<class MachOT>
1458 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
1459 bool &Result) const {
1460 const RelocationEntry *RE = getRelocation(Rel);
1461 unsigned Arch = this->getArch();
1462 unsigned Type = this->getRelocationTypeImpl(RE);
1466 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1467 // is always hidden.
1468 if (Arch == Triple::x86 || Arch == Triple::arm) {
1469 if (Type == macho::RIT_Pair) Result = true;
1470 } else if (Arch == Triple::x86_64) {
1471 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1472 // an X864_64_RELOC_SUBTRACTOR.
1473 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1474 DataRefImpl RelPrev = Rel;
1476 const RelocationEntry *REPrev = this->getRelocation(RelPrev);
1478 unsigned PrevType = REPrev->getType();
1480 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1484 return object_error::success;
1487 template<class MachOT>
1489 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
1490 uint64_t &Res) const {
1491 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1493 if (Entry->SectionIndex) {
1494 const Section *Sec =
1495 this->getSection(this->Sections[Entry->SectionIndex-1]);
1496 Res += Sec->Offset - Sec->Address;
1499 return object_error::success;
1502 template<class MachOT>
1504 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
1506 bool &Result) const {
1508 this->getSymbolType(Symb, ST);
1509 if (ST == SymbolRef::ST_Unknown) {
1511 return object_error::success;
1514 uint64_t SectBegin, SectEnd;
1515 getSectionAddress(Sec, SectBegin);
1516 getSectionSize(Sec, SectEnd);
1517 SectEnd += SectBegin;
1519 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1520 uint64_t SymAddr= Entry->Value;
1521 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
1523 return object_error::success;
1526 template<class MachOT>
1527 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
1528 uint64_t &Res) const {
1529 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1531 return object_error::success;
1534 template<class MachOT>
1535 error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI,
1536 uint64_t &Result) const {
1537 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1538 uint64_t BeginOffset;
1539 uint64_t EndOffset = 0;
1540 uint8_t SectionIndex;
1542 const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
1543 BeginOffset = Entry->Value;
1544 SectionIndex = Entry->SectionIndex;
1545 if (!SectionIndex) {
1546 uint32_t flags = SymbolRef::SF_None;
1547 this->getSymbolFlags(DRI, flags);
1548 if (flags & SymbolRef::SF_Common)
1549 Result = Entry->Value;
1551 Result = UnknownAddressOrSize;
1552 return object_error::success;
1554 // Unfortunately symbols are unsorted so we need to touch all
1555 // symbols from load command
1557 uint32_t Command = DRI.d.a;
1558 while (Command == DRI.d.a) {
1559 this->moveToNextSymbol(DRI);
1560 if (DRI.d.a < LoadCommandCount) {
1561 Entry = getSymbolTableEntry(DRI);
1562 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
1563 if (!EndOffset || Entry->Value < EndOffset)
1564 EndOffset = Entry->Value;
1570 this->getSectionSize(this->Sections[SectionIndex-1], Size);
1571 this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset);
1574 Result = EndOffset - BeginOffset;
1575 return object_error::success;
1578 template<class MachOT>
1579 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
1580 SectionRef &Res) const {
1582 moveToNextSection(Sec);
1583 Res = SectionRef(Sec, this);
1584 return object_error::success;
1587 template<class MachOT>
1588 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
1590 moveToNextSection(DRI);
1591 return section_iterator(SectionRef(DRI, this));
1594 template<class MachOT>
1595 void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const {
1596 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1597 while (DRI.d.a < LoadCommandCount) {
1598 const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a);
1599 if (Command->Type == SegmentLoadType) {
1600 const SegmentLoadCommand *SegmentLoadCmd =
1601 reinterpret_cast<const SegmentLoadCommand*>(Command);
1602 if (DRI.d.b < SegmentLoadCmd->NumSections)