Fix MachO's getRelocationAdditionalInfo.
[oota-llvm.git] / include / llvm / Object / MachO.h
1 //===- MachO.h - MachO object file implementation ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares the MachOObjectFile class, which binds the MachOObject
11 // class to the generic ObjectFile wrapper.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_OBJECT_MACHO_H
16 #define LLVM_OBJECT_MACHO_H
17
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/Endian.h"
24 #include "llvm/Support/MachO.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 namespace llvm {
28 namespace object {
29
30 using support::endianness;
31
32 template<endianness E, bool B>
33 struct MachOType {
34   static const endianness TargetEndianness = E;
35   static const bool Is64Bits = B;
36 };
37
38 template<endianness TargetEndianness>
39 struct MachODataTypeTypedefHelperCommon {
40   typedef support::detail::packed_endian_specific_integral
41     <uint16_t, TargetEndianness, support::unaligned> MachOInt16;
42   typedef support::detail::packed_endian_specific_integral
43     <uint32_t, TargetEndianness, support::unaligned> MachOInt32;
44   typedef support::detail::packed_endian_specific_integral
45     <uint64_t, TargetEndianness, support::unaligned> MachOInt64;
46 };
47
48 #define LLVM_MACHOB_IMPORT_TYPES(E)                                          \
49 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
50 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
51 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64;
52
53 template<class MachOT>
54 struct MachODataTypeTypedefHelper;
55
56 template<endianness TargetEndianness>
57 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
58   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
59   typedef typename Base::MachOInt32 MachOIntPtr;
60 };
61
62 template<endianness TargetEndianness>
63 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
64   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
65   typedef typename Base::MachOInt64 MachOIntPtr;
66 };
67
68 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B)                        \
69 LLVM_MACHOB_IMPORT_TYPES(E)                                          \
70 typedef typename                                                     \
71   MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
72
73 namespace MachOFormat {
74   struct SectionBase {
75     char Name[16];
76     char SegmentName[16];
77   };
78
79   template<class MachOT>
80   struct Section;
81
82   template<endianness TargetEndianness>
83   struct Section<MachOType<TargetEndianness, false> > {
84     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
85     char Name[16];
86     char SegmentName[16];
87     MachOInt32 Address;
88     MachOInt32 Size;
89     MachOInt32 Offset;
90     MachOInt32 Align;
91     MachOInt32 RelocationTableOffset;
92     MachOInt32 NumRelocationTableEntries;
93     MachOInt32 Flags;
94     MachOInt32 Reserved1;
95     MachOInt32 Reserved2;
96   };
97
98   template<endianness TargetEndianness>
99   struct Section<MachOType<TargetEndianness, true> > {
100     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
101     char Name[16];
102     char SegmentName[16];
103     MachOInt64 Address;
104     MachOInt64 Size;
105     MachOInt32 Offset;
106     MachOInt32 Align;
107     MachOInt32 RelocationTableOffset;
108     MachOInt32 NumRelocationTableEntries;
109     MachOInt32 Flags;
110     MachOInt32 Reserved1;
111     MachOInt32 Reserved2;
112     MachOInt32 Reserved3;
113   };
114
115   template<endianness TargetEndianness>
116   struct RelocationEntry {
117     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
118     MachOInt32 Word0;
119     MachOInt32 Word1;
120   };
121
122   template<endianness TargetEndianness>
123   struct SymbolTableEntryBase {
124     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
125     MachOInt32 StringIndex;
126     uint8_t Type;
127     uint8_t SectionIndex;
128     MachOInt16 Flags;
129   };
130
131   template<class MachOT>
132   struct SymbolTableEntry;
133
134   template<endianness TargetEndianness, bool Is64Bits>
135   struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
136     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
137     MachOInt32 StringIndex;
138     uint8_t Type;
139     uint8_t SectionIndex;
140     MachOInt16 Flags;
141     MachOIntPtr Value;
142   };
143
144   template<endianness TargetEndianness>
145   struct LoadCommand {
146     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
147     MachOInt32 Type;
148     MachOInt32 Size;
149   };
150
151   template<endianness TargetEndianness>
152   struct SymtabLoadCommand {
153     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
154     MachOInt32 Type;
155     MachOInt32 Size;
156     MachOInt32 SymbolTableOffset;
157     MachOInt32 NumSymbolTableEntries;
158     MachOInt32 StringTableOffset;
159     MachOInt32 StringTableSize;
160   };
161
162   template<class MachOT>
163   struct SegmentLoadCommand;
164
165   template<endianness TargetEndianness, bool Is64Bits>
166   struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
167     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
168     MachOInt32 Type;
169     MachOInt32 Size;
170     char Name[16];
171     MachOIntPtr VMAddress;
172     MachOIntPtr VMSize;
173     MachOIntPtr FileOffset;
174     MachOIntPtr FileSize;
175     MachOInt32 MaxVMProtection;
176     MachOInt32 InitialVMProtection;
177     MachOInt32 NumSections;
178     MachOInt32 Flags;
179   };
180
181   template<endianness TargetEndianness>
182   struct LinkeditDataLoadCommand {
183     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
184     MachOInt32 Type;
185     MachOInt32 Size;
186     MachOInt32 DataOffset;
187     MachOInt32 DataSize;
188   };
189
190   template<endianness TargetEndianness>
191   struct Header {
192     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
193     MachOInt32 Magic;
194     MachOInt32 CPUType;
195     MachOInt32 CPUSubtype;
196     MachOInt32 FileType;
197     MachOInt32 NumLoadCommands;
198     MachOInt32 SizeOfLoadCommands;
199     MachOInt32 Flags;
200   };
201 }
202
203 class MachOObjectFileBase : public ObjectFile {
204 public:
205   typedef MachOFormat::SymbolTableEntryBase<support::little>
206     SymbolTableEntryBase;
207   typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand;
208   typedef MachOFormat::RelocationEntry<support::little> RelocationEntry;
209   typedef MachOFormat::SectionBase SectionBase;
210   typedef MachOFormat::LoadCommand<support::little> LoadCommand;
211   typedef MachOFormat::Header<support::little> Header;
212   typedef MachOFormat::LinkeditDataLoadCommand<support::little>
213     LinkeditDataLoadCommand;
214
215   MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
216
217   virtual symbol_iterator begin_symbols() const;
218   virtual symbol_iterator end_symbols() const;
219   virtual symbol_iterator begin_dynamic_symbols() const;
220   virtual symbol_iterator end_dynamic_symbols() const;
221   virtual library_iterator begin_libraries_needed() const;
222   virtual library_iterator end_libraries_needed() const;
223   virtual section_iterator end_sections() const;
224
225   virtual uint8_t getBytesInAddress() const;
226   virtual StringRef getFileFormatName() const;
227   virtual unsigned getArch() const;
228   virtual StringRef getLoadName() const;
229
230   // In a MachO file, sections have a segment name. This is used in the .o
231   // files. They have a single segment, but this field specifies which segment
232   // a section should be put in in the final object.
233   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
234
235   // Names are stored as 16 bytes. These returns the raw 16 bytes without
236   // interpreting them as a C string.
237   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
238   ArrayRef<char>getSectionRawFinalSegmentName(DataRefImpl Sec) const;
239
240   bool is64Bit() const;
241   const LoadCommand *getLoadCommandInfo(unsigned Index) const;
242   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
243   const Header *getHeader() const;
244   unsigned getHeaderSize() const;
245   StringRef getData(size_t Offset, size_t Size) const;
246
247   static inline bool classof(const Binary *v) {
248     return v->isMachO();
249   }
250
251 protected:
252   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
253   virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
254   virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
255   virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
256   virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const;
257   virtual error_code getSymbolSection(DataRefImpl Symb,
258                                       section_iterator &Res) const;
259   virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
260   virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
261   virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
262   virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
263   virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
264                                                    bool &Res) const;
265   virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
266   virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
267   virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
268
269   virtual error_code getRelocationNext(DataRefImpl Rel,
270                                        RelocationRef &Res) const;
271
272   virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
273   virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
274   virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
275                                                  int64_t &Res) const;
276
277   std::size_t getSectionIndex(DataRefImpl Sec) const;
278
279   typedef SmallVector<DataRefImpl, 1> SectionList;
280   SectionList Sections;
281
282   void moveToNextSymbol(DataRefImpl &DRI) const;
283   void printRelocationTargetName(const RelocationEntry *RE,
284                                  raw_string_ostream &fmt) const;
285   const SectionBase *getSectionBase(DataRefImpl DRI) const;
286   const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
287
288 private:
289
290   const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI,
291                                   const SymtabLoadCommand *SymtabLoadCmd) const;
292 };
293
294 template<class MachOT>
295 struct MachOObjectFileHelperCommon;
296
297 template<endianness TargetEndianness, bool Is64Bits>
298 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
299   typedef
300     MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
301     SegmentLoadCommand;
302   typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
303     SymbolTableEntry;
304   typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
305 };
306
307 template<class MachOT>
308 struct MachOObjectFileHelper;
309
310 template<endianness TargetEndianness>
311 struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > :
312     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > {
313   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
314 };
315
316 template<endianness TargetEndianness>
317 struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > :
318     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > {
319   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
320 };
321
322 template<class MachOT>
323 class MachOObjectFile : public MachOObjectFileBase {
324 public:
325   static const endianness TargetEndianness = MachOT::TargetEndianness;
326   static const bool Is64Bits = MachOT::Is64Bits;
327
328   typedef MachOObjectFileHelper<MachOT> Helper;
329   static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
330   typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
331   typedef typename Helper::SymbolTableEntry SymbolTableEntry;
332   typedef typename Helper::Section Section;
333
334   MachOObjectFile(MemoryBuffer *Object, error_code &ec);
335   static bool classof(const Binary *v);
336
337   const Section *getSection(DataRefImpl DRI) const;
338   const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
339   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
340
341   virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
342   virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
343   virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
344   virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
345   virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
346   virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
347   virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
348   virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
349   virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
350   virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
351   virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
352   virtual error_code getRelocationTypeName(DataRefImpl Rel,
353                                            SmallVectorImpl<char> &Result) const;
354   virtual error_code getRelocationValueString(DataRefImpl Rel,
355                                            SmallVectorImpl<char> &Result) const;
356   virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
357   virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
358   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
359                                            bool &Result) const;
360   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
361   virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
362   virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
363   virtual section_iterator begin_sections() const;
364   void moveToNextSection(DataRefImpl &DRI) const;
365 };
366
367 template<class MachOT>
368 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
369                                          error_code &ec) :
370   MachOObjectFileBase(Object, Is64Bits, ec) {
371   DataRefImpl DRI;
372   moveToNextSection(DRI);
373   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
374   while (DRI.d.a < LoadCommandCount) {
375     Sections.push_back(DRI);
376     DRI.d.b++;
377     moveToNextSection(DRI);
378   }
379 }
380
381 template<class MachOT>
382 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
383   return v->getType() == getMachOType(true, Is64Bits);
384 }
385
386 template<class MachOT>
387 const typename MachOObjectFile<MachOT>::Section *
388 MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const {
389   const SectionBase *Addr = getSectionBase(DRI);
390   return reinterpret_cast<const Section*>(Addr);
391 }
392
393 template<class MachOT>
394 const typename MachOObjectFile<MachOT>::SymbolTableEntry *
395 MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const {
396   const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI);
397   return reinterpret_cast<const SymbolTableEntry*>(Base);
398 }
399
400 template<class MachOT>
401 const typename MachOObjectFile<MachOT>::RelocationEntry *
402 MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const {
403   const Section *Sect = getSection(Sections[Rel.d.b]);
404   uint32_t RelOffset = Sect->RelocationTableOffset;
405   uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
406   StringRef Data = getData(Offset, sizeof(RelocationEntry));
407   return reinterpret_cast<const RelocationEntry*>(Data.data());
408 }
409
410 template<class MachOT>
411 error_code
412 MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec,
413                                            uint64_t &Res) const {
414   const Section *Sect = getSection(Sec);
415   Res = Sect->Address;
416   return object_error::success;
417 }
418
419 template<class MachOT>
420 error_code
421 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
422                                         uint64_t &Res) const {
423   const Section *Sect = getSection(Sec);
424   Res = Sect->Size;
425   return object_error::success;
426 }
427
428 template<class MachOT>
429 error_code
430 MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec,
431                                             StringRef &Res) const {
432   const Section *Sect = getSection(Sec);
433   Res = getData(Sect->Offset, Sect->Size);
434   return object_error::success;
435 }
436
437 template<class MachOT>
438 error_code
439 MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec,
440                                              uint64_t &Res) const {
441   const Section *Sect = getSection(Sec);
442   Res = uint64_t(1) << Sect->Align;
443   return object_error::success;
444 }
445
446 template<class MachOT>
447 error_code
448 MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const {
449   const Section *Sect = getSection(Sec);
450   Res = Sect->Flags & macho::SF_PureInstructions;
451   return object_error::success;
452 }
453
454 template<class MachOT>
455 error_code
456 MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
457   const Section *Sect = getSection(Sec);
458   unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
459   Res = SectionType == MachO::SectionTypeZeroFill ||
460     SectionType == MachO::SectionTypeZeroFillLarge;
461   return object_error::success;
462 }
463
464 template<class MachOT>
465 relocation_iterator
466 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
467   const Section *Sect = getSection(Sec);
468   uint32_t LastReloc = Sect->NumRelocationTableEntries;
469   DataRefImpl Ret;
470   Ret.d.a = LastReloc;
471   Ret.d.b = getSectionIndex(Sec);
472   return relocation_iterator(RelocationRef(Ret, this));
473 }
474
475 template<class MachOT>
476 error_code
477 MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
478                                               uint64_t &Res) const {
479   const Section *Sect = getSection(Sections[Rel.d.b]);
480   uint64_t SectAddress = Sect->Address;
481   const RelocationEntry *RE = getRelocation(Rel);
482   unsigned Arch = getArch();
483   bool isScattered = (Arch != Triple::x86_64) &&
484                      (RE->Word0 & macho::RF_Scattered);
485
486   uint64_t RelAddr;
487   if (isScattered)
488     RelAddr = RE->Word0 & 0xFFFFFF;
489   else
490     RelAddr = RE->Word0;
491
492   Res = SectAddress + RelAddr;
493   return object_error::success;
494 }
495
496 template<class MachOT>
497 error_code
498 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
499                                              uint64_t &Res) const {
500   const RelocationEntry *RE = getRelocation(Rel);
501
502   unsigned Arch = getArch();
503   bool isScattered = (Arch != Triple::x86_64) &&
504                      (RE->Word0 & macho::RF_Scattered);
505   if (isScattered)
506     Res = RE->Word0 & 0xFFFFFF;
507   else
508     Res = RE->Word0;
509   return object_error::success;
510 }
511
512 template<class MachOT>
513 error_code
514 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
515                                              SymbolRef &Res) const {
516   const RelocationEntry *RE = getRelocation(Rel);
517   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
518   bool isExtern = (RE->Word1 >> 27) & 1;
519
520   DataRefImpl Sym;
521   moveToNextSymbol(Sym);
522   if (isExtern) {
523     for (unsigned i = 0; i < SymbolIdx; i++) {
524       Sym.d.b++;
525       moveToNextSymbol(Sym);
526       assert(Sym.d.a < getHeader()->NumLoadCommands &&
527              "Relocation symbol index out of range!");
528     }
529   }
530   Res = SymbolRef(Sym, this);
531   return object_error::success;
532 }
533
534 template<class MachOT>
535 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
536                                                       uint64_t &Res) const {
537   const RelocationEntry *RE = getRelocation(Rel);
538   Res = RE->Word0;
539   Res <<= 32;
540   Res |= RE->Word1;
541   return object_error::success;
542 }
543
544 template<class MachOT>
545 error_code
546 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
547                                           SmallVectorImpl<char> &Result) const {
548     // TODO: Support scattered relocations.
549   StringRef res;
550   const RelocationEntry *RE = getRelocation(Rel);
551
552   unsigned Arch = getArch();
553   bool isScattered = (Arch != Triple::x86_64) &&
554                      (RE->Word0 & macho::RF_Scattered);
555
556   unsigned r_type;
557   if (isScattered)
558     r_type = (RE->Word0 >> 24) & 0xF;
559   else
560     r_type = (RE->Word1 >> 28) & 0xF;
561
562   switch (Arch) {
563     case Triple::x86: {
564       static const char *const Table[] =  {
565         "GENERIC_RELOC_VANILLA",
566         "GENERIC_RELOC_PAIR",
567         "GENERIC_RELOC_SECTDIFF",
568         "GENERIC_RELOC_PB_LA_PTR",
569         "GENERIC_RELOC_LOCAL_SECTDIFF",
570         "GENERIC_RELOC_TLV" };
571
572       if (r_type > 6)
573         res = "Unknown";
574       else
575         res = Table[r_type];
576       break;
577     }
578     case Triple::x86_64: {
579       static const char *const Table[] =  {
580         "X86_64_RELOC_UNSIGNED",
581         "X86_64_RELOC_SIGNED",
582         "X86_64_RELOC_BRANCH",
583         "X86_64_RELOC_GOT_LOAD",
584         "X86_64_RELOC_GOT",
585         "X86_64_RELOC_SUBTRACTOR",
586         "X86_64_RELOC_SIGNED_1",
587         "X86_64_RELOC_SIGNED_2",
588         "X86_64_RELOC_SIGNED_4",
589         "X86_64_RELOC_TLV" };
590
591       if (r_type > 9)
592         res = "Unknown";
593       else
594         res = Table[r_type];
595       break;
596     }
597     case Triple::arm: {
598       static const char *const Table[] =  {
599         "ARM_RELOC_VANILLA",
600         "ARM_RELOC_PAIR",
601         "ARM_RELOC_SECTDIFF",
602         "ARM_RELOC_LOCAL_SECTDIFF",
603         "ARM_RELOC_PB_LA_PTR",
604         "ARM_RELOC_BR24",
605         "ARM_THUMB_RELOC_BR22",
606         "ARM_THUMB_32BIT_BRANCH",
607         "ARM_RELOC_HALF",
608         "ARM_RELOC_HALF_SECTDIFF" };
609
610       if (r_type > 9)
611         res = "Unknown";
612       else
613         res = Table[r_type];
614       break;
615     }
616     case Triple::ppc: {
617       static const char *const Table[] =  {
618         "PPC_RELOC_VANILLA",
619         "PPC_RELOC_PAIR",
620         "PPC_RELOC_BR14",
621         "PPC_RELOC_BR24",
622         "PPC_RELOC_HI16",
623         "PPC_RELOC_LO16",
624         "PPC_RELOC_HA16",
625         "PPC_RELOC_LO14",
626         "PPC_RELOC_SECTDIFF",
627         "PPC_RELOC_PB_LA_PTR",
628         "PPC_RELOC_HI16_SECTDIFF",
629         "PPC_RELOC_LO16_SECTDIFF",
630         "PPC_RELOC_HA16_SECTDIFF",
631         "PPC_RELOC_JBSR",
632         "PPC_RELOC_LO14_SECTDIFF",
633         "PPC_RELOC_LOCAL_SECTDIFF" };
634
635       res = Table[r_type];
636       break;
637     }
638     case Triple::UnknownArch:
639       res = "Unknown";
640       break;
641   }
642   Result.append(res.begin(), res.end());
643   return object_error::success;
644 }
645
646 template<class MachOT>
647 error_code
648 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
649                                           SmallVectorImpl<char> &Result) const {
650   const RelocationEntry *RE = getRelocation(Rel);
651
652   unsigned Arch = getArch();
653   bool isScattered = (Arch != Triple::x86_64) &&
654                      (RE->Word0 & macho::RF_Scattered);
655
656   std::string fmtbuf;
657   raw_string_ostream fmt(fmtbuf);
658
659   unsigned Type;
660   if (isScattered)
661     Type = (RE->Word0 >> 24) & 0xF;
662   else
663     Type = (RE->Word1 >> 28) & 0xF;
664
665   bool isPCRel;
666   if (isScattered)
667     isPCRel = ((RE->Word0 >> 30) & 1);
668   else
669     isPCRel = ((RE->Word1 >> 24) & 1);
670
671   // Determine any addends that should be displayed with the relocation.
672   // These require decoding the relocation type, which is triple-specific.
673
674   // X86_64 has entirely custom relocation types.
675   if (Arch == Triple::x86_64) {
676     bool isPCRel = ((RE->Word1 >> 24) & 1);
677
678     switch (Type) {
679       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
680       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
681         printRelocationTargetName(RE, fmt);
682         fmt << "@GOT";
683         if (isPCRel) fmt << "PCREL";
684         break;
685       }
686       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
687         DataRefImpl RelNext = Rel;
688         RelNext.d.a++;
689         const RelocationEntry *RENext = getRelocation(RelNext);
690
691         // X86_64_SUBTRACTOR must be followed by a relocation of type
692         // X86_64_RELOC_UNSIGNED.
693         // NOTE: Scattered relocations don't exist on x86_64.
694         unsigned RType = (RENext->Word1 >> 28) & 0xF;
695         if (RType != 0)
696           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
697                              "X86_64_RELOC_SUBTRACTOR.");
698
699         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
700         // X86_64_SUBTRACTOR contains to the subtrahend.
701         printRelocationTargetName(RENext, fmt);
702         fmt << "-";
703         printRelocationTargetName(RE, fmt);
704         break;
705       }
706       case macho::RIT_X86_64_TLV:
707         printRelocationTargetName(RE, fmt);
708         fmt << "@TLV";
709         if (isPCRel) fmt << "P";
710         break;
711       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
712         printRelocationTargetName(RE, fmt);
713         fmt << "-1";
714         break;
715       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
716         printRelocationTargetName(RE, fmt);
717         fmt << "-2";
718         break;
719       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
720         printRelocationTargetName(RE, fmt);
721         fmt << "-4";
722         break;
723       default:
724         printRelocationTargetName(RE, fmt);
725         break;
726     }
727   // X86 and ARM share some relocation types in common.
728   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
729     // Generic relocation types...
730     switch (Type) {
731       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
732         return object_error::success;
733       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
734         DataRefImpl RelNext = Rel;
735         RelNext.d.a++;
736         const RelocationEntry *RENext = getRelocation(RelNext);
737
738         // X86 sect diff's must be followed by a relocation of type
739         // GENERIC_RELOC_PAIR.
740         bool isNextScattered = (Arch != Triple::x86_64) &&
741                                (RENext->Word0 & macho::RF_Scattered);
742         unsigned RType;
743         if (isNextScattered)
744           RType = (RENext->Word0 >> 24) & 0xF;
745         else
746           RType = (RENext->Word1 >> 28) & 0xF;
747         if (RType != 1)
748           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
749                              "GENERIC_RELOC_SECTDIFF.");
750
751         printRelocationTargetName(RE, fmt);
752         fmt << "-";
753         printRelocationTargetName(RENext, fmt);
754         break;
755       }
756     }
757
758     if (Arch == Triple::x86) {
759       // All X86 relocations that need special printing were already
760       // handled in the generic code.
761       switch (Type) {
762         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
763           DataRefImpl RelNext = Rel;
764           RelNext.d.a++;
765           const RelocationEntry *RENext = getRelocation(RelNext);
766
767           // X86 sect diff's must be followed by a relocation of type
768           // GENERIC_RELOC_PAIR.
769           bool isNextScattered = (Arch != Triple::x86_64) &&
770                                (RENext->Word0 & macho::RF_Scattered);
771           unsigned RType;
772           if (isNextScattered)
773             RType = (RENext->Word0 >> 24) & 0xF;
774           else
775             RType = (RENext->Word1 >> 28) & 0xF;
776           if (RType != 1)
777             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
778                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
779
780           printRelocationTargetName(RE, fmt);
781           fmt << "-";
782           printRelocationTargetName(RENext, fmt);
783           break;
784         }
785         case macho::RIT_Generic_TLV: {
786           printRelocationTargetName(RE, fmt);
787           fmt << "@TLV";
788           if (isPCRel) fmt << "P";
789           break;
790         }
791         default:
792           printRelocationTargetName(RE, fmt);
793       }
794     } else { // ARM-specific relocations
795       switch (Type) {
796         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
797         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
798           // Half relocations steal a bit from the length field to encode
799           // whether this is an upper16 or a lower16 relocation.
800           bool isUpper;
801           if (isScattered)
802             isUpper = (RE->Word0 >> 28) & 1;
803           else
804             isUpper = (RE->Word1 >> 25) & 1;
805
806           if (isUpper)
807             fmt << ":upper16:(";
808           else
809             fmt << ":lower16:(";
810           printRelocationTargetName(RE, fmt);
811
812           DataRefImpl RelNext = Rel;
813           RelNext.d.a++;
814           const RelocationEntry *RENext = getRelocation(RelNext);
815
816           // ARM half relocs must be followed by a relocation of type
817           // ARM_RELOC_PAIR.
818           bool isNextScattered = (Arch != Triple::x86_64) &&
819                                  (RENext->Word0 & macho::RF_Scattered);
820           unsigned RType;
821           if (isNextScattered)
822             RType = (RENext->Word0 >> 24) & 0xF;
823           else
824             RType = (RENext->Word1 >> 28) & 0xF;
825
826           if (RType != 1)
827             report_fatal_error("Expected ARM_RELOC_PAIR after "
828                                "GENERIC_RELOC_HALF");
829
830           // NOTE: The half of the target virtual address is stashed in the
831           // address field of the secondary relocation, but we can't reverse
832           // engineer the constant offset from it without decoding the movw/movt
833           // instruction to find the other half in its immediate field.
834
835           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
836           // symbol/section pointer of the follow-on relocation.
837           if (Type == macho::RIT_ARM_HalfDifference) {
838             fmt << "-";
839             printRelocationTargetName(RENext, fmt);
840           }
841
842           fmt << ")";
843           break;
844         }
845         default: {
846           printRelocationTargetName(RE, fmt);
847         }
848       }
849     }
850   } else
851     printRelocationTargetName(RE, fmt);
852
853   fmt.flush();
854   Result.append(fmtbuf.begin(), fmtbuf.end());
855   return object_error::success;
856 }
857
858 template<class MachOT>
859 error_code
860 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
861                                              bool &Result) const {
862   const RelocationEntry *RE = getRelocation(Rel);
863
864   unsigned Arch = getArch();
865   bool isScattered = (Arch != Triple::x86_64) &&
866                      (RE->Word0 & macho::RF_Scattered);
867   unsigned Type;
868   if (isScattered)
869     Type = (RE->Word0 >> 24) & 0xF;
870   else
871     Type = (RE->Word1 >> 28) & 0xF;
872
873   Result = false;
874
875   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
876   // is always hidden.
877   if (Arch == Triple::x86 || Arch == Triple::arm) {
878     if (Type == macho::RIT_Pair) Result = true;
879   } else if (Arch == Triple::x86_64) {
880     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
881     // an X864_64_RELOC_SUBTRACTOR.
882     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
883       DataRefImpl RelPrev = Rel;
884       RelPrev.d.a--;
885       const RelocationEntry *REPrev = getRelocation(RelPrev);
886
887       unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
888
889       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
890     }
891   }
892
893   return object_error::success;
894 }
895
896 template<class MachOT>
897 error_code
898 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
899                                              uint64_t &Res) const {
900   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
901   Res = Entry->Value;
902   if (Entry->SectionIndex) {
903     const Section *Sec = getSection(Sections[Entry->SectionIndex-1]);
904     Res += Sec->Offset - Sec->Address;
905   }
906
907   return object_error::success;
908 }
909
910 template<class MachOT>
911 error_code
912 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
913                                                DataRefImpl Symb,
914                                                bool &Result) const {
915   SymbolRef::Type ST;
916   getSymbolType(Symb, ST);
917   if (ST == SymbolRef::ST_Unknown) {
918     Result = false;
919     return object_error::success;
920   }
921
922   uint64_t SectBegin, SectEnd;
923   getSectionAddress(Sec, SectBegin);
924   getSectionSize(Sec, SectEnd);
925   SectEnd += SectBegin;
926
927   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
928   uint64_t SymAddr= Entry->Value;
929   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
930
931   return object_error::success;
932 }
933
934 template<class MachOT>
935 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
936                                                      uint64_t &Res) const {
937   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
938   Res = Entry->Value;
939   return object_error::success;
940 }
941
942 template<class MachOT>
943 error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI,
944                                                     uint64_t &Result) const {
945   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
946   uint64_t BeginOffset;
947   uint64_t EndOffset = 0;
948   uint8_t SectionIndex;
949
950   const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
951   BeginOffset = Entry->Value;
952   SectionIndex = Entry->SectionIndex;
953   if (!SectionIndex) {
954     uint32_t flags = SymbolRef::SF_None;
955     getSymbolFlags(DRI, flags);
956     if (flags & SymbolRef::SF_Common)
957       Result = Entry->Value;
958     else
959       Result = UnknownAddressOrSize;
960     return object_error::success;
961   }
962   // Unfortunately symbols are unsorted so we need to touch all
963   // symbols from load command
964   DRI.d.b = 0;
965   uint32_t Command = DRI.d.a;
966   while (Command == DRI.d.a) {
967     moveToNextSymbol(DRI);
968     if (DRI.d.a < LoadCommandCount) {
969       Entry = getSymbolTableEntry(DRI);
970       if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
971         if (!EndOffset || Entry->Value < EndOffset)
972           EndOffset = Entry->Value;
973     }
974     DRI.d.b++;
975   }
976   if (!EndOffset) {
977     uint64_t Size;
978     getSectionSize(Sections[SectionIndex-1], Size);
979     getSectionAddress(Sections[SectionIndex-1], EndOffset);
980     EndOffset += Size;
981   }
982   Result = EndOffset - BeginOffset;
983   return object_error::success;
984 }
985
986 template<class MachOT>
987 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
988                                                    SectionRef &Res) const {
989   Sec.d.b++;
990   moveToNextSection(Sec);
991   Res = SectionRef(Sec, this);
992   return object_error::success;
993 }
994
995 template<class MachOT>
996 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
997   DataRefImpl DRI;
998   moveToNextSection(DRI);
999   return section_iterator(SectionRef(DRI, this));
1000 }
1001
1002 template<class MachOT>
1003 void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const {
1004   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
1005   while (DRI.d.a < LoadCommandCount) {
1006     const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
1007     if (Command->Type == SegmentLoadType) {
1008       const SegmentLoadCommand *SegmentLoadCmd =
1009         reinterpret_cast<const SegmentLoadCommand*>(Command);
1010       if (DRI.d.b < SegmentLoadCmd->NumSections)
1011         return;
1012     }
1013
1014     DRI.d.a++;
1015     DRI.d.b = 0;
1016   }
1017 }
1018
1019   typedef MachOObjectFile<MachOType<support::little, false> >
1020     MachOObjectFile32Le;
1021   typedef MachOObjectFile<MachOType<support::little, true> >
1022     MachOObjectFile64Le;
1023 }
1024 }
1025
1026 #endif
1027