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